Index: library/bdm/base/itpp/config_msvc.h
===================================================================
--- library/bdm/base/itpp/config_msvc.h (revision 812)
+++ library/bdm/base/itpp/config_msvc.h (revision 812)
@@ -0,0 +1,271 @@
+/* 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 you use zdotusub_ Fortran wrapper. */
+/* #undef HAVE_ZDOTUSUB */
+
+/* Define if "void zdotu_()" should be used. */
+#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) */
+
+/* Represent GCC version in a concise form */
+#define GCC_VERSION (__GNUC__ * 10000           \
+                     + __GNUC_MINOR__ * 100     \
+                     + __GNUC_PATCHLEVEL__)
+
+#endif /* #ifndef CONFIG_H */
+
Index: library/bdm/base/itpp/base/itassert.cpp
===================================================================
--- library/bdm/base/itpp/base/itassert.cpp (revision 812)
+++ library/bdm/base/itpp/base/itassert.cpp (revision 812)
@@ -0,0 +1,134 @@
+/*!
+ * \file
+ * \brief Error handling functions - source file
+ * \author Tobias Ringstrom and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <itpp/base/itassert.h>
+#include <iostream>
+#include <stdexcept>
+#include <cstdlib>
+
+
+namespace itpp
+{
+
+//! \cond
+static bool warnings_enabled = true;
+static bool file_line_info_enabled = true;
+static std::ostream *warn = &std::cerr;
+//! \endcond
+
+void it_assert_f(std::string ass, std::string msg, std::string file, int line)
+{
+  std::ostringstream error;
+  if (file_line_info_enabled) {
+    error << "*** Assertion failed in " << file << " on line " << line
+    << ":\n" << msg << " (" << ass << ")\n";
+  }
+  else {
+    error << msg << " (" << ass << ")\n";
+  }
+  std::cerr << error.str() << std::flush;
+#ifdef ITPP_EXCEPTIONS
+  throw std::runtime_error(error.str());
+#else
+  abort();
+#endif
+}
+
+void it_error_f(std::string msg, std::string file, int line)
+{
+  std::ostringstream error;
+  if (file_line_info_enabled) {
+    error << "*** Error in " << file << " on line " << line << ":\n"
+    << msg << "\n";
+  }
+  else {
+    error << msg << "\n";
+  }
+  std::cerr << error.str() << std::flush;
+#ifdef ITPP_EXCEPTIONS
+  throw std::runtime_error(error.str());
+#else
+  abort();
+#endif
+}
+
+void it_info_f(std::string msg)
+{
+  std::cerr << msg << std::flush;
+}
+
+void it_warning_f(std::string msg, std::string file, int line)
+{
+  if (warnings_enabled) {
+    if (file_line_info_enabled) {
+      (*warn) << "*** Warning in " << file << " on line " << line << ":\n"
+      << msg << std::endl << std::flush;
+    }
+    else {
+      (*warn) << msg << std::endl << std::flush;
+    }
+  }
+}
+
+void it_enable_warnings()
+{
+  warnings_enabled = true;
+}
+
+void it_disable_warnings()
+{
+  warnings_enabled = false;
+}
+
+void it_redirect_warnings(std::ostream *warn_stream)
+{
+  warn = warn_stream;
+}
+
+void it_error_msg_style(error_msg_style style)
+{
+  switch (style) {
+  case Full:
+    file_line_info_enabled = true;
+    break;
+  case Minimum:
+    file_line_info_enabled = false;
+    break;
+  default:
+    file_line_info_enabled = true;
+  }
+}
+
+} //namespace itpp
Index: library/bdm/base/itpp/base/copy_vector.h
===================================================================
--- library/bdm/base/itpp/base/copy_vector.h (revision 812)
+++ library/bdm/base/itpp/base/copy_vector.h (revision 812)
@@ -0,0 +1,321 @@
+/*!
+ * \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-2010  (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 and 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 and 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 increment incx
+ * and elements of y are stored linearly with increment 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: library/bdm/base/itpp/base/parser.h
===================================================================
--- library/bdm/base/itpp/base/parser.h (revision 812)
+++ library/bdm/base/itpp/base/parser.h (revision 812)
@@ -0,0 +1,235 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/specmat.h
===================================================================
--- library/bdm/base/itpp/base/specmat.h (revision 812)
+++ library/bdm/base/itpp/base/specmat.h (revision 812)
@@ -0,0 +1,474 @@
+/*!
+ * \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-2010  (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 Generate Toeplitz matrix from two vectors \c c and \c r.
+ *
+ * Returns 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 and a symmetric (Hermitian) Toeplitz matrix is created.
+ *
+ * An example 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
+ *
+ * \author Adam Piatyszek
+ */
+template <typename Num_T>
+const Mat<Num_T> toeplitz(const Vec<Num_T> &c, const Vec<Num_T> &r)
+{
+  int n_rows = c.size();
+  int n_cols = r.size();
+  Mat<Num_T> output(n_rows, n_cols);
+  for (int i = 0; i < n_rows; ++i) {
+    int j_limit = std::min(n_cols, n_rows - i);
+    for (int j = 0; j < j_limit; ++j) {
+      output(i + j, j) = c(i);
+    }
+  }
+  for (int j = 1; j < n_cols; ++j) {
+    int i_limit = std::min(n_rows, n_cols - j);
+    for (int i = 0; i < i_limit; ++i) {
+      output(i, i + j) = r(j);
+    }
+  }
+  return output;
+}
+
+//! Generate symmetric Toeplitz matrix from vector \c c.
+template <typename Num_T>
+const Mat<Num_T> toeplitz(const Vec<Num_T> &c)
+{
+  int s = c.size();
+  Mat<Num_T> output(s, s);
+  for (int i = 0; i < s; ++i) {
+    for (int j = 0; j < s - i; ++j) {
+      output(i + j, j) = c(i);
+    }
+  }
+  for (int j = 1; j < s; ++j) {
+    for (int i = 0; i < s - j; ++i) {
+      output(i, i + j) = c(j);
+    }
+  }
+  return output;
+}
+
+//! Generate symmetric Toeplitz matrix from vector \c c (complex valued)
+template <>
+const cmat toeplitz(const cvec &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: library/bdm/base/itpp/base/svec.h
===================================================================
--- library/bdm/base/itpp/base/svec.h (revision 812)
+++ library/bdm/base/itpp/base/svec.h (revision 812)
@@ -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-2010  (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];
+  }
+
+  //! Return 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: library/bdm/base/itpp/base/fastmath.cpp
===================================================================
--- library/bdm/base/itpp/base/fastmath.cpp (revision 812)
+++ library/bdm/base/itpp/base/fastmath.cpp (revision 812)
@@ -0,0 +1,93 @@
+/*!
+ * \file
+ * \brief Implementation 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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/fastmath.h>
+
+
+namespace itpp
+{
+
+// m=m-v*v'*m
+void sub_v_vT_m(mat &m, const vec &v)
+{
+  vec v2(m.cols());
+  double tmp, *v2p;
+  const double *vp;
+  int i, j;
+
+  it_assert(v.size() == m.rows(), "sub_v_vT_m()");
+
+  v2p = v2._data();
+  for (j = 0; j < m.cols(); j++) {
+    tmp = 0.0;
+    vp = v._data();
+    for (i = 0; i < m.rows(); i++)
+      tmp += *(vp++) * m._elem(i, j);
+    *(v2p++) = tmp;
+  }
+
+  vp = v._data();
+  for (i = 0; i < m.rows(); i++) {
+    v2p = v2._data();
+    for (j = 0; j < m.cols(); j++)
+      m._elem(i, j) -= *vp * *(v2p++);
+    vp++;
+  }
+}
+
+// m=m-m*v*v'
+void sub_m_v_vT(mat &m, const vec &v)
+{
+  vec v2(m.rows());
+  double tmp, *v2p;
+  const double *vp;
+  int i, j;
+
+  it_assert(v.size() == m.cols(), "sub_m_v_vT()");
+
+  v2p = v2._data();
+  for (i = 0; i < m.rows(); i++) {
+    tmp = 0.0;
+    vp = v._data();
+    for (j = 0; j < m.cols(); j++)
+      tmp += *(vp++) * m._elem(i, j);
+    *(v2p++) = tmp;
+  }
+
+  v2p = v2._data();
+  for (i = 0; i < m.rows(); i++) {
+    vp = v._data();
+    for (j = 0; j < m.cols(); j++)
+      m._elem(i, j) -= *v2p * *(vp++);
+    v2p++;
+  }
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/math/error.h
===================================================================
--- library/bdm/base/itpp/base/math/error.h (revision 812)
+++ library/bdm/base/itpp/base/math/error.h (revision 812)
@@ -0,0 +1,158 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/math/elem_math.h
===================================================================
--- library/bdm/base/itpp/base/math/elem_math.h (revision 812)
+++ library/bdm/base/itpp/base/math/elem_math.h (revision 812)
@@ -0,0 +1,287 @@
+/*!
+ * \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-2010  (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>
+
+// IT++ accepts only std::min() and std::max() functions, not macros
+#ifdef min
+#  undef min
+#endif
+#ifdef max
+#  undef max
+#endif
+
+//!\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); }
+//! Absolute 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); }
+//! Absolute square of elements
+vec sqr(const cvec &x);
+//! Absolute 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: library/bdm/base/itpp/base/math/misc.h
===================================================================
--- library/bdm/base/itpp/base/math/misc.h (revision 812)
+++ library/bdm/base/itpp/base/math/misc.h (revision 812)
@@ -0,0 +1,191 @@
+/*!
+ * \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-2010  (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 = static_cast<char>(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
+
+
+//! itpp namespace
+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: library/bdm/base/itpp/base/math/log_exp.h
===================================================================
--- library/bdm/base/itpp/base/math/log_exp.h (revision 812)
+++ library/bdm/base/itpp/base/math/log_exp.h (revision 812)
@@ -0,0 +1,366 @@
+/*!
+ * \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-2010  (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 <itpp/base/math/misc.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
+
+// IT++ accepts only log2() function, not a macro
+#ifdef log2
+#  undef log2
+#endif
+
+#ifndef HAVE_LOG2
+//! 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) || std::isnan(negdelta))
+    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: library/bdm/base/itpp/base/math/integration.cpp
===================================================================
--- library/bdm/base/itpp/base/math/integration.cpp (revision 812)
+++ library/bdm/base/itpp/base/math/integration.cpp (revision 812)
@@ -0,0 +1,208 @@
+/*!
+ * \file
+ * \brief Implementation of numerical integration
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/math/integration.h>
+#include <itpp/base/math/elem_math.h>
+#include <itpp/base/help_functions.h>
+#include <itpp/base/matfunc.h>
+#include <itpp/base/specmat.h>
+
+
+namespace itpp
+{
+
+//! quadstep function
+double quadstep(double(*f)(double), double a, double b,
+                double fa, double fm, double fb, double is)
+{
+  double Q, m, h, fml, fmr, i1, i2;
+  vec x(2), y(2);
+
+  m = (a + b) / 2;
+  h = (b - a) / 4;
+  x = vec_2(a + h, b - h);
+  y = apply_function<double>(f, x);
+  fml = y(0);
+  fmr = y(1);
+
+  i1 = h / 1.5 * (fa + 4 * fm + fb);
+  i2 = h / 3 * (fa + 4 * (fml + fmr) + 2 * fm + fb);
+  i1 = (16 * i2 - i1) / 15;
+
+  if ((is + (i1 - i2) == is) || (m <= a) || (b <= m)) {
+    if ((m <= a) || (b <= m)) {
+      it_warning("Interval contains no more machine number. Required tolerance may not be met");
+    }
+    Q = i1;
+    return Q;
+  }
+  else {
+    Q = quadstep(f, a, m, fa, fml, fm, is) + quadstep(f, m, b, fm, fmr, fb, is);
+  }
+  return Q;
+}
+
+
+double quad(double(*f)(double), double a, double b, double tol)
+{
+  vec x(3), y(3), yy(5);
+  double Q, fa, fm, fb, is;
+
+  x = vec_3(a, (a + b) / 2, b);
+  y = apply_function<double>(f, x);
+  fa = y(0);
+  fm = y(1);
+  fb = y(2);
+  yy = apply_function<double>(f, a + vec(".9501 .2311 .6068 .4860 .8913")
+                              * (b - a));
+  is = (b - a) / 8 * (sum(y) + sum(yy));
+
+  if (is == 0.0)
+    is = b - a;
+
+  is = is * tol / std::numeric_limits<double>::epsilon();
+  Q = quadstep(f, a, b, fa, fm, fb, is);
+
+  return Q;
+}
+
+
+//--------------------- quadl() ----------------------------------------
+
+//! quadlstep function
+double quadlstep(double(*f)(double), double a, double b,
+                 double fa, double fb, double is)
+{
+  double Q, h, m, alpha, beta, mll, ml, mr, mrr, fmll, fml, fm, fmr, fmrr,
+  i1, i2;
+  vec x(5), y(5);
+
+  h = (b - a) / 2;
+  m = (a + b) / 2;
+  alpha = std::sqrt(2.0 / 3);
+  beta = 1.0 / std::sqrt(5.0);
+  mll = m - alpha * h;
+  ml = m - beta * h;
+  mr = m + beta * h;
+  mrr = m + alpha * h;
+  x(0) = mll;
+  x(1) = ml;
+  x(2) = m;
+  x(3) = mr;
+  x(4) = mrr;
+
+  y = apply_function<double>(f, x);
+
+  fmll = y(0);
+  fml = y(1);
+  fm = y(2);
+  fmr = y(3);
+  fmrr = y(4);
+
+  i2 = (h / 6) * (fa + fb + 5 * (fml + fmr));
+  i1 = (h / 1470) * (77 * (fa + fb) + 432 * (fmll + fmrr) + 625 * (fml + fmr) + 672 * fm);
+
+  if ((is + (i1 - i2) == is) || (mll <= a) || (b <= mrr)) {
+    if ((m <= a) || (b <= m)) {
+      it_warning("Interval contains no more machine number. Required tolerance may not be met");
+    }
+    Q = i1;
+    return Q;
+  }
+  else {
+    Q = quadlstep(f, a, mll, fa, fmll, is) + quadlstep(f, mll, ml, fmll, fml, is) + quadlstep(f, ml, m, fml, fm, is) +
+        quadlstep(f, m, mr, fm, fmr, is) + quadlstep(f, mr, mrr, fmr, fmrr, is) + quadlstep(f, mrr, b, fmrr, fb, is);
+  }
+  return Q;
+}
+
+double quadl(double(*f)(double), double a, double b, double tol)
+{
+  double Q, m, h, alpha, beta, x1, x2, x3, fa, fb, i1, i2, is, s, erri1, erri2, R;
+  vec x(13), y(13);
+  double tol2 = tol;
+
+  m = (a + b) / 2;
+  h = (b - a) / 2;
+
+  alpha = std::sqrt(2.0 / 3);
+  beta = 1.0 / std::sqrt(5.0);
+
+  x1 = .942882415695480;
+  x2 = .641853342345781;
+  x3 = .236383199662150;
+  x(0) = a;
+  x(1) = m - x1 * h;
+  x(2) = m - alpha * h;
+  x(3) = m - x2 * h;
+  x(4) = m - beta * h;
+  x(5) = m - x3 * h;
+  x(6) = m;
+  x(7) = m + x3 * h;
+  x(8) = m + beta * h;
+  x(9) = m + x2 * h;
+  x(10) = m + alpha * h;
+  x(11) = m + x1 * h;
+  x(12) = b;
+
+  y = apply_function<double>(f, x);
+
+  fa = y(0);
+  fb = y(12);
+  i2 = (h / 6) * (y(0) + y(12) + 5 * (y(4) + y(8)));
+  i1 = (h / 1470) * (77 * (y(0) + y(12)) + 432 * (y(2) + y(10)) + 625 * (y(4) + y(8)) + 672 * y(6));
+
+  is = h * (.0158271919734802 * (y(0) + y(12)) + .0942738402188500 * (y(1) + y(11)) + .155071987336585 * (y(2) + y(10)) +
+            .188821573960182 * (y(3) + y(9)) + .199773405226859 * (y(4) + y(8)) + .224926465333340 * (y(5) + y(7)) + .242611071901408 * y(6));
+
+  s = sign(is);
+  if (s == 0.0)
+    s = 1;
+
+  erri1 = std::abs(i1 - is);
+  erri2 = std::abs(i2 - is);
+
+  R = 1;
+  if (erri2 != 0.0)
+    R = erri1 / erri2;
+
+  if (R > 0 && R < 1)
+    tol2 = tol2 / R;
+
+  is = s * std::abs(is) * tol2 / std::numeric_limits<double>::epsilon();
+  if (is == 0.0)
+    is = b - a;
+
+  Q = quadlstep(f, a, b, fa, fb, is);
+
+  return Q;
+}
+
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/math/integration.h
===================================================================
--- library/bdm/base/itpp/base/math/integration.h (revision 812)
+++ library/bdm/base/itpp/base/math/integration.h (revision 812)
@@ -0,0 +1,128 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/math/error.cpp
===================================================================
--- library/bdm/base/itpp/base/math/error.cpp (revision 812)
+++ library/bdm/base/itpp/base/math/error.cpp (revision 812)
@@ -0,0 +1,313 @@
+/*!
+ * \file
+ * \brief Error functions - source file
+ * \author Tony Ottosson, Pal Frenger and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/math/error.h>
+#include <itpp/base/math/elem_math.h>
+
+
+#ifndef HAVE_ERFC
+double erfc(double Y)
+{
+  int  ISW, I;
+  double P[4], Q[3], P1[6], Q1[5], P2[4], Q2[3];
+  double XMIN, XLARGE, SQRPI;
+  double X, RES, XSQ, XNUM, XDEN, XI, XBIG, ERFCret;
+  P[1] = 0.3166529;
+  P[2] = 1.722276;
+  P[3] = 21.38533;
+  Q[1] = 7.843746;
+  Q[2] = 18.95226;
+  P1[1] = 0.5631696;
+  P1[2] = 3.031799;
+  P1[3] = 6.865018;
+  P1[4] = 7.373888;
+  P1[5] = 4.318779e-5;
+  Q1[1] = 5.354217;
+  Q1[2] = 12.79553;
+  Q1[3] = 15.18491;
+  Q1[4] = 7.373961;
+  P2[1] = 5.168823e-2;
+  P2[2] = 0.1960690;
+  P2[3] = 4.257996e-2;
+  Q2[1] = 0.9214524;
+  Q2[2] = 0.1509421;
+  XMIN = 1.0E-5;
+  XLARGE = 4.1875E0;
+  XBIG = 9.0;
+  SQRPI = 0.5641896;
+  X = Y;
+  ISW = 1;
+  if (X < 0) {
+    ISW = -1;
+    X = -X;
+  }
+  if (X < 0.477) {
+    if (X >= XMIN) {
+      XSQ = X * X;
+      XNUM = (P[1] * XSQ + P[2]) * XSQ + P[3];
+      XDEN = (XSQ + Q[1]) * XSQ + Q[2];
+      RES = X * XNUM / XDEN;
+    }
+    else RES = X * P[3] / Q[2];
+    if (ISW == -1) RES = -RES;
+    RES = 1.0 - RES;
+    goto slut;
+  }
+  if (X > 4.0) {
+    if (ISW > 0) goto ulf;
+    if (X < XLARGE) goto eva;
+    RES = 2.0;
+    goto slut;
+  }
+  XSQ = X * X;
+  XNUM = P1[5] * X + P1[1];
+  XDEN = X + Q1[1];
+  for (I = 2;I <= 4;I++) {
+    XNUM = XNUM * X + P1[I];
+    XDEN = XDEN * X + Q1[I];
+  }
+  RES = XNUM / XDEN;
+  goto elin;
+ulf:
+  if (X > XBIG) goto fred;
+eva:
+  XSQ = X * X;
+  XI = 1.0 / XSQ;
+  XNUM = (P2[1] * XI + P2[2]) * XI + P2[3];
+  XDEN = XI + Q2[1] * XI + Q2[2];
+  RES = (SQRPI + XI * XNUM / XDEN) / X;
+elin:
+  RES = RES * exp(-XSQ);
+  if (ISW == -1) RES = 2.0 - RES;
+  goto slut;
+fred:
+  RES = 0.0;
+slut:
+  ERFCret = RES;
+  return  ERFCret;
+}
+#endif
+
+#ifndef HAVE_ERF
+double erf(double x)
+{
+  return (1.0 - ::erfc(x));
+}
+#endif
+
+
+namespace itpp
+{
+
+/*!
+ * Abramowitz and Stegun: Eq. (7.1.14) gives this continued fraction
+ * for erfc(z)
+ *
+ * erfc(z) = sqrt(pi).exp(-z^2).  1   1/2   1   3/2   2   5/2
+ *                               ---  ---  ---  ---  ---  --- ...
+ *                               z +  z +  z +  z +  z +  z +
+ *
+ * This is evaluated using Lentz's method, as described in the
+ * narative of Numerical Recipes in C.
+ *
+ * The continued fraction is true providing real(z) > 0. In practice
+ * we like real(z) to be significantly greater than 0, say greater
+ * than 0.5.
+ */
+std::complex<double> cerfc_continued_fraction(const std::complex<double>& z)
+{
+  const double tiny = std::numeric_limits<double>::min();
+
+  // first calculate z+ 1/2   1
+  //                    ---  --- ...
+  //                    z +  z +
+  std::complex<double> f(z);
+  std::complex<double> C(f);
+  std::complex<double> D(0.0);
+  std::complex<double> delta;
+  double a;
+
+  a = 0.0;
+  do {
+    a += 0.5;
+    D = z + a * D;
+    C = z + a / C;
+    if ((D.real() == 0.0) && (D.imag() == 0.0))
+      D = tiny;
+    D = 1.0 / D;
+    delta = C * D;
+    f = f * delta;
+  }
+  while (abs(1.0 - delta) > eps);
+
+  // Do the first term of the continued fraction
+  f = 1.0 / f;
+
+  // and do the final scaling
+  f = f * exp(-z * z) / std::sqrt(pi);
+
+  return f;
+}
+
+//! Complementary function to \c cerfc_continued_fraction
+std::complex<double> cerf_continued_fraction(const std::complex<double>& z)
+{
+  if (z.real() > 0)
+    return 1.0 - cerfc_continued_fraction(z);
+  else
+    return -1.0 + cerfc_continued_fraction(-z);
+}
+
+/*!
+ * Abramawitz and Stegun: Eq. (7.1.5) gives a series for erf(z) good
+ * for all z, but converges faster for smallish abs(z), say abs(z) < 2.
+ */
+std::complex<double> cerf_series(const std::complex<double>& z)
+{
+  const double tiny = std::numeric_limits<double>::min();
+  std::complex<double> sum(0.0);
+  std::complex<double> term(z);
+  std::complex<double> z2(z*z);
+
+  for (int n = 0; (n < 3) || (abs(term) > abs(sum) * tiny); n++) {
+    sum += term / static_cast<double>(2 * n + 1);
+    term *= -z2 / static_cast<double>(n + 1);
+  }
+
+  return sum * 2.0 / std::sqrt(pi);
+}
+
+/*!
+ * Numerical Recipes quotes a formula due to Rybicki for evaluating
+ * Dawson's Integral:
+ *
+ * exp(-x^2) integral exp(t^2).dt = 1/sqrt(pi) lim  sum  exp(-(z-n.h)^2) / n
+ *            0 to x                           h->0 n odd
+ *
+ * This can be adapted to erf(z).
+ */
+std::complex<double> cerf_rybicki(const std::complex<double>& z)
+{
+  double h = 0.2; // numerical experiment suggests this is small enough
+
+  // choose an even n0, and then shift z->z-n0.h and n->n-h.
+  // n0 is chosen so that real((z-n0.h)^2) is as small as possible.
+  int n0 = 2 * static_cast<int>(z.imag() / (2 * h) + 0.5);
+
+  std::complex<double> z0(0.0, n0 * h);
+  std::complex<double> zp(z - z0);
+  std::complex<double> sum(0.0, 0.0);
+
+  // limits of sum chosen so that the end sums of the sum are
+  // fairly small. In this case exp(-(35.h)^2)=5e-22
+  for (int np = -35; np <= 35; np += 2) {
+    std::complex<double> t(zp.real(), zp.imag() - np * h);
+    std::complex<double> b(exp(t * t) / static_cast<double>(np + n0));
+    sum += b;
+  }
+
+  sum *= 2.0 * exp(-z * z) / pi;
+
+  return std::complex<double>(-sum.imag(), sum.real());
+}
+
+/*
+ * This function calculates a well known error function erf(z) for
+ * complex z. Three methods are implemented. Which one is used
+ * depends on z.
+ */
+std::complex<double> erf(const std::complex<double>& z)
+{
+  // Use the method appropriate to size of z -
+  // there probably ought to be an extra option for NaN z, or infinite z
+  if (abs(z) < 2.0)
+    return cerf_series(z);
+  else {
+    if (std::abs(z.real()) < 0.5)
+      return cerf_rybicki(z);
+    else
+      return cerf_continued_fraction(z);
+  }
+}
+
+
+double erfinv(double P)
+{
+  double Y, A, B, X, Z, W, WI, SN, SD, F, Z2, SIGMA;
+  double A1 = -.5751703, A2 = -1.896513, A3 = -.5496261E-1;
+  double B0 = -.1137730, B1 = -3.293474, B2 = -2.374996, B3 = -1.187515;
+  double C0 = -.1146666, C1 = -.1314774, C2 = -.2368201, C3 = .5073975e-1;
+  double D0 = -44.27977, D1 = 21.98546, D2 = -7.586103;
+  double E0 = -.5668422E-1, E1 = .3937021, E2 = -.3166501, E3 = .6208963E-1;
+  double F0 = -6.266786, F1 = 4.666263, F2 = -2.962883;
+  double G0 = .1851159E-3, G1 = -.2028152E-2, G2 = -.1498384, G3 = .1078639E-1;
+  double H0 = .9952975E-1, H1 = .5211733, H2 = -.6888301E-1;
+  // double RINFM=1.7014E+38;
+
+  X = P;
+  SIGMA = sign(X);
+  it_error_if(X < -1 || X > 1, "erfinv : argument out of bounds");
+  Z = fabs(X);
+  if (Z > .85) {
+    A = 1 - Z;
+    B = Z;
+    W = std::sqrt(-log(A + A * B));
+    if (W >= 2.5) {
+      if (W >= 4.) {
+        WI = 1. / W;
+        SN = ((G3 * WI + G2) * WI + G1) * WI;
+        SD = ((WI + H2) * WI + H1) * WI + H0;
+        F = W + W * (G0 + SN / SD);
+      }
+      else {
+        SN = ((E3 * W + E2) * W + E1) * W;
+        SD = ((W + F2) * W + F1) * W + F0;
+        F = W + W * (E0 + SN / SD);
+      }
+    }
+    else {
+      SN = ((C3 * W + C2) * W + C1) * W;
+      SD = ((W + D2) * W + D1) * W + D0;
+      F = W + W * (C0 + SN / SD);
+    }
+  }
+  else {
+    Z2 = Z * Z;
+    F = Z + Z * (B0 + A1 * Z2 / (B1 + Z2 + A2 / (B2 + Z2 + A3 / (B3 + Z2))));
+  }
+  Y = SIGMA * F;
+  return Y;
+}
+
+double Qfunc(double x)
+{
+  return (0.5 * ::erfc(x / 1.41421356237310));
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/math/trig_hyp.h
===================================================================
--- library/bdm/base/itpp/base/math/trig_hyp.h (revision 812)
+++ library/bdm/base/itpp/base/math/trig_hyp.h (revision 812)
@@ -0,0 +1,156 @@
+/*!
+ * \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-2010  (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)
+{
+  if (x == 0) {
+    return 1.0;
+  }
+  else {
+    double pix = itpp::pi * x;
+    return sin(pix) / pix;
+  }
+}
+
+//! 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: library/bdm/base/itpp/base/math/elem_math.cpp
===================================================================
--- library/bdm/base/itpp/base/math/elem_math.cpp (revision 812)
+++ library/bdm/base/itpp/base/math/elem_math.cpp (revision 812)
@@ -0,0 +1,282 @@
+/*!
+ * \file
+ * \brief Elementary mathematical functions - source file
+ * \author Tony Ottosson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/math/elem_math.h>
+
+
+#ifndef HAVE_TGAMMA
+// "True" gamma function
+double tgamma(double x)
+{
+  double s = (2.50662827510730 + 190.9551718930764 / (x + 1)
+              - 216.8366818437280 / (x + 2) + 60.19441764023333
+              / (x + 3) - 3.08751323928546 / (x + 4) + 0.00302963870525
+              / (x + 5) - 0.00001352385959072596 / (x + 6)) / x;
+  if (s < 0)
+    return -exp((x + 0.5) * log(x + 5.5) - x - 5.5 + log(-s));
+  else
+    return exp((x + 0.5) * log(x + 5.5) - x - 5.5 + log(s));
+}
+#endif
+
+#if !defined(HAVE_LGAMMA) || (HAVE_DECL_SIGNGAM != 1)
+// The sign of the Gamma function is returned in the external integer
+// signgam declared in <math.h>. It is 1 when the Gamma function is positive
+// or zero, -1 when it is negative. However, MinGW definition of lgamma()
+// function does not use the global signgam variable.
+int signgam;
+// Logarithm of an absolute value of gamma function
+double lgamma(double x)
+{
+  double gam = tgamma(x);
+  signgam = (gam < 0) ? -1 : 1;
+  return log(fabs(gam));
+}
+#endif
+
+#ifndef HAVE_CBRT
+// Cubic root
+double cbrt(double x) { return std::pow(x, 1.0 / 3.0); }
+#endif
+
+
+namespace itpp
+{
+
+vec sqr(const cvec &data)
+{
+  vec temp(data.length());
+  for (int i = 0; i < data.length(); i++)
+    temp(i) = sqr(data(i));
+  return temp;
+}
+
+mat sqr(const cmat &data)
+{
+  mat temp(data.rows(), data.cols());
+  for (int i = 0; i < temp.rows(); i++) {
+    for (int j = 0; j < temp.cols(); j++) {
+      temp(i, j) = sqr(data(i, j));
+    }
+  }
+  return temp;
+}
+
+vec abs(const cvec &data)
+{
+  vec temp(data.length());
+
+  for (int i = 0;i < data.length();i++)
+    temp[i] = std::abs(data[i]);
+
+  return temp;
+}
+
+mat abs(const cmat &data)
+{
+  mat temp(data.rows(), data.cols());
+
+  for (int i = 0;i < temp.rows();i++) {
+    for (int j = 0;j < temp.cols();j++) {
+      temp(i, j) = std::abs(data(i, j));
+    }
+  }
+
+  return temp;
+}
+
+// Calculates factorial coefficient for index <= 170.
+double fact(int index)
+{
+  it_error_if(index > 170, "fact(int index): Function overflows if index > 170.");
+  it_error_if(index < 0, "fact(int index): index must be non-negative integer");
+  double prod = 1;
+  for (int i = 1; i <= index; i++)
+    prod *= static_cast<double>(i);
+  return prod;
+}
+
+// Calculates binomial coefficient "n over k".
+double binom(int n, int k)
+{
+  it_assert(k <= n, "binom(n, k): k can not be larger than n");
+  it_assert((n >= 0) && (k >= 0), "binom(n, k): n and k must be non-negative integers");
+  k = ((n - k) < k) ? n - k : k;
+
+  double out = 1.0;
+  for (int i = 1; i <= k; ++i) {
+    out *= (i + n - k);
+    out /= i;
+  }
+  return out;
+}
+
+// Calculates binomial coefficient "n over k".
+int binom_i(int n, int k)
+{
+  it_assert(k <= n, "binom_i(n, k): k can not be larger than n");
+  it_assert((n >= 0) && (k >= 0), "binom_i(n, k): n and k must be non-negative integers");
+  k = ((n - k) < k) ? n - k : k;
+
+  int out = 1;
+  for (int i = 1; i <= k; ++i) {
+    out *= (i + n - k);
+    out /= i;
+  }
+  return out;
+}
+
+// Calculates the base 10-logarithm of the binomial coefficient "n over k".
+double log_binom(int n, int k)
+{
+  it_assert(k <= n, "log_binom(n, k): k can not be larger than n");
+  it_assert((n >= 0) && (k >= 0), "log_binom(n, k): n and k must be non-negative integers");
+  k = ((n - k) < k) ? n - k : k;
+
+  double out = 0.0;
+  for (int i = 1; i <= k; i++)
+    out += log10(static_cast<double>(i + n - k))
+           - log10(static_cast<double>(i));
+
+  return out;
+}
+
+// Calculates the greatest common divisor
+int gcd(int a, int b)
+{
+  it_assert((a >= 0) && (b >= 0), "gcd(a, b): a and b must be non-negative integers");
+  int v, u, t, q;
+
+  u = a;
+  v = b;
+  while (v > 0) {
+    q = u / v;
+    t = u - v * q;
+    u = v;
+    v = t;
+  }
+  return u;
+}
+
+
+vec real(const cvec &data)
+{
+  vec temp(data.length());
+
+  for (int i = 0;i < data.length();i++)
+    temp[i] = data[i].real();
+
+  return temp;
+}
+
+mat real(const cmat &data)
+{
+  mat temp(data.rows(), data.cols());
+
+  for (int i = 0;i < temp.rows();i++) {
+    for (int j = 0;j < temp.cols();j++) {
+      temp(i, j) = data(i, j).real();
+    }
+  }
+
+  return temp;
+}
+
+vec imag(const cvec &data)
+{
+  vec temp(data.length());
+
+  for (int i = 0;i < data.length();i++)
+    temp[i] = data[i].imag();
+  return temp;
+}
+
+mat imag(const cmat &data)
+{
+  mat temp(data.rows(), data.cols());
+
+  for (int i = 0;i < temp.rows();i++) {
+    for (int j = 0;j < temp.cols();j++) {
+      temp(i, j) = data(i, j).imag();
+    }
+  }
+
+  return temp;
+}
+
+vec arg(const cvec &data)
+{
+  vec temp(data.length());
+
+  for (int i = 0;i < data.length();i++)
+    temp[i] = std::arg(data[i]);
+
+  return temp;
+}
+
+mat arg(const cmat &data)
+{
+  mat temp(data.rows(), data.cols());
+
+  for (int i = 0;i < temp.rows();i++) {
+    for (int j = 0;j < temp.cols();j++) {
+      temp(i, j) = std::arg(data(i, j));
+    }
+  }
+
+  return temp;
+}
+
+#ifdef _MSC_VER
+cvec conj(const cvec &x)
+{
+  cvec temp(x.size());
+
+  for (int i = 0; i < x.size(); i++) {
+    temp(i) = std::conj(x(i));
+  }
+
+  return temp;
+}
+
+cmat conj(const cmat &x)
+{
+  cmat temp(x.rows(), x.cols());
+
+  for (int i = 0; i < x.rows(); i++) {
+    for (int j = 0; j < x.cols(); j++) {
+      temp(i, j) = std::conj(x(i, j));
+    }
+  }
+
+  return temp;
+}
+#endif
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/math/misc.cpp
===================================================================
--- library/bdm/base/itpp/base/math/misc.cpp (revision 812)
+++ library/bdm/base/itpp/base/math/misc.cpp (revision 812)
@@ -0,0 +1,55 @@
+/*!
+ * \file
+ * \brief Miscellaneous functions - source file
+ * \author Tony Ottosson and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/math/misc.h>
+
+
+namespace itpp
+{
+
+std::string itpp_version(void)
+{
+#ifdef PACKAGE_VERSION
+  return std::string(PACKAGE_VERSION);
+#else
+  return std::string("Warning: Version unknown!");
+#endif
+}
+
+bool check_big_endianness()
+{
+  int i = 1;
+  char *p = (char *) & i;
+  if (p[0] == 1) // Lowest address contains the least significant byte
+    return false; // LITTLE_ENDIAN
+  else
+    return true; // BIG_ENDIAN
+}
+
+} //namespace itpp
Index: library/bdm/base/itpp/base/math/min_max.h
===================================================================
--- library/bdm/base/itpp/base/math/min_max.h (revision 812)
+++ library/bdm/base/itpp/base/math/min_max.h (revision 812)
@@ -0,0 +1,266 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/smat.h
===================================================================
--- library/bdm/base/itpp/base/smat.h (revision 812)
+++ library/bdm/base/itpp/base/smat.h (revision 812)
@@ -0,0 +1,1076 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/stack.h
===================================================================
--- library/bdm/base/itpp/base/stack.h (revision 812)
+++ library/bdm/base/itpp/base/stack.h (revision 812)
@@ -0,0 +1,230 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/itfile.cpp
===================================================================
--- library/bdm/base/itpp/base/itfile.cpp (revision 812)
+++ library/bdm/base/itpp/base/itfile.cpp (revision 812)
@@ -0,0 +1,3582 @@
+/*!
+ * \file
+ * \brief Implementation 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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+
+#include <itpp/base/itfile.h>
+
+
+namespace itpp
+{
+
+char it_file_base::file_magic[4] = { 'I', 'T', '+', '+' };
+char it_file_base::file_version = 3;
+
+// ----------------------------------------------------------------------
+// it_ifile class
+// ----------------------------------------------------------------------
+
+it_ifile::it_ifile() {}
+
+it_ifile::it_ifile(const std::string &name)
+{
+  open(name);
+}
+
+void it_ifile::open(const std::string &name)
+{
+  it_assert(exist(name), "it_ifile::open(): File does not exist");
+  s.open_readonly(name, bfstream_base::l_endian);
+  if (!read_check_file_header()) {
+    s.close();
+    it_error("it_ifile::open(): Corrupt file (not an it_file)");
+  }
+}
+
+void it_ifile::close()
+{
+  s.close();
+}
+
+bool it_ifile::seek(const std::string &name)
+{
+  data_header h;
+  std::streampos p;
+
+  s.clear();
+  s.seekg(sizeof(file_header));
+
+  while (true) {
+    p = s.tellg();
+    read_data_header(h);
+    if (s.eof()) {
+      s.clear();
+      return false;
+    }
+    if (h.type != "" && h.name == name) {
+      s.seekg(p);
+      break;
+    }
+    s.seekg(p + static_cast<std::streamoff>(h.block_bytes));
+  }
+
+  return true;
+}
+
+bool it_ifile::seek(int n)
+{
+  data_header h;
+  std::streampos p;
+
+  s.clear();
+  s.seekg(sizeof(file_header));
+  for (int i = 0; i <= n; i++) {
+    p = s.tellg();
+    read_data_header(h);
+    if (s.eof()) {
+      s.clear();
+      return false;
+    }
+    if (h.type == "")
+      i--;
+    s.seekg((i == n) ? p : p + static_cast<std::streamoff>(h.block_bytes));
+  }
+  return true;
+}
+
+void it_ifile::info(std::string &name, std::string &type,
+                    std::string &desc, uint64_t &bytes)
+{
+  data_header h;
+  std::streampos p;
+
+  p = s.tellg();
+  read_data_header(h);
+  s.seekg(p);
+  name = h.name;
+  type = h.type;
+  desc = h.desc;
+  bytes = h.data_bytes;
+}
+
+bool it_ifile::read_check_file_header()
+{
+  file_header h;
+  s.read(reinterpret_cast<char *>(&h), sizeof(h));
+  return (memcmp(h.magic, file_magic, 4) == 0
+          && (h.version == file_version));
+}
+
+void it_ifile::read_data_header(data_header &h)
+{
+  std::streampos p = s.tellg();
+  s.clear();
+  s >> h.hdr_bytes;
+  s >> h.data_bytes;
+  s >> h.block_bytes;
+  s >> h.name;
+  s >> h.type;
+  s >> h.desc;
+}
+
+void it_ifile::low_level_read(char &x)
+{
+  s >> x;
+}
+
+void it_ifile::low_level_read(uint64_t &x)
+{
+  s >> x;
+}
+
+void it_ifile::low_level_read(bool &x)
+{
+  char tmp;
+  s >> tmp;
+  x = (tmp == 0) ? false : true;
+}
+
+
+void it_ifile::low_level_read(bin &x)
+{
+  char tmp;
+  s >> tmp;
+  x = tmp;
+}
+
+void it_ifile::low_level_read(short &x)
+{
+  int16_t tmp;
+  s >> tmp;
+  x = tmp;
+}
+
+void it_ifile::low_level_read(int &x)
+{
+  int32_t tmp;
+  s >> tmp;
+  x = tmp;
+}
+
+void it_ifile::low_level_read(float &x)
+{
+  s >> x;
+}
+
+void it_ifile::low_level_read(double &x)
+{
+  s >> x;
+}
+
+void it_ifile::low_level_read(std::complex<float> &x)
+{
+  float x_real, x_imag;
+  s >> x_real;
+  s >> x_imag;
+  x = std::complex<float>(x_real, x_imag);
+}
+
+void it_ifile::low_level_read(std::complex<double> &x)
+{
+  double x_real, x_imag;
+  s >> x_real;
+  s >> x_imag;
+  x = std::complex<double>(x_real, x_imag);
+}
+
+void it_ifile::low_level_read(bvec &v)
+{
+  uint64_t size;
+  char tmp;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> tmp;
+    v(i) = tmp;
+  }
+}
+
+void it_ifile::low_level_read(svec &v)
+{
+  uint64_t size;
+  int16_t val;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val;
+    v(i) = val;
+  }
+}
+
+void it_ifile::low_level_read(ivec &v)
+{
+  uint64_t size;
+  int32_t val;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val;
+    v(i) = val;
+  }
+}
+
+void it_ifile::low_level_read_lo(vec &v)
+{
+  uint64_t size;
+  float val;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val;
+    v(i) = static_cast<double>(val);
+  }
+}
+
+void it_ifile::low_level_read_hi(vec &v)
+{
+  uint64_t size;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i)
+    s >> v(i);
+}
+
+void it_ifile::low_level_read_lo(cvec &v)
+{
+  uint64_t size;
+  float val_real, val_imag;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<double>(val_real, val_imag);
+  }
+}
+
+void it_ifile::low_level_read_hi(cvec &v)
+{
+  uint64_t size;
+  double val_real, val_imag;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<double>(val_real, val_imag);
+  }
+}
+
+void it_ifile::low_level_read(std::string &str)
+{
+  uint64_t size;
+  s >> size;
+  std::string::size_type size2 = static_cast<std::string::size_type>(size);
+  str.resize(size2);
+  for (std::string::size_type i = 0; i < size2; ++i)
+    s >> str[i];
+}
+
+void it_ifile::low_level_read(bmat &m)
+{
+  uint64_t i, j;
+  char tmp;
+  s >> i >> j;
+  m.set_size(static_cast<int>(i), static_cast<int>(j), false);
+  for (int j = 0; j < m.cols(); ++j) {
+    for (int i = 0; i < m.rows(); ++i) {
+      s >> tmp;
+      m(i, j) = tmp;
+    }
+  }
+}
+
+void it_ifile::low_level_read(smat &m)
+{
+  uint64_t i, j;
+  int16_t val;
+  s >> i >> j;
+  m.set_size(static_cast<int>(i), static_cast<int>(j), false);
+  for (int j = 0; j < m.cols(); ++j)
+    for (int i = 0; i < m.rows(); ++i) {
+      s >> val;
+      m(i, j) = val;
+    }
+}
+
+void it_ifile::low_level_read(imat &m)
+{
+  uint64_t i, j;
+  int32_t val;
+  s >> i >> j;
+  m.set_size(static_cast<int>(i), static_cast<int>(j), false);
+  for (int j = 0; j < m.cols(); ++j)
+    for (int i = 0; i < m.rows(); ++i) {
+      s >> val;
+      m(i, j) = val;
+    }
+}
+
+void it_ifile::low_level_read_lo(mat &m)
+{
+  uint64_t i, j;
+  float val;
+  s >> i >> j;
+  m.set_size(static_cast<int>(i), static_cast<int>(j), false);
+  for (int j = 0; j < m.cols(); ++j)
+    for (int i = 0; i < m.rows(); ++i) {
+      s >> val;
+      m(i, j) = static_cast<double>(val);
+    }
+}
+
+void it_ifile::low_level_read_hi(mat &m)
+{
+  uint64_t i, j;
+  s >> i >> j;
+  m.set_size(static_cast<int>(i), static_cast<int>(j), false);
+  for (int j = 0; j < m.cols(); ++j)
+    for (int i = 0; i < m.rows(); ++i)
+      s >> m(i, j);
+}
+
+void it_ifile::low_level_read_lo(cmat &m)
+{
+  uint64_t i, j;
+  float val_real, val_imag;
+  s >> i >> j;
+  m.set_size(static_cast<int>(i), static_cast<int>(j), false);
+  for (int j = 0; j < m.cols(); ++j)
+    for (int i = 0; i < m.rows(); ++i) {
+      s >> val_real;
+      s >> val_imag;
+      m(i, j) = std::complex<double>(val_real, val_imag);
+    }
+}
+
+void it_ifile::low_level_read_hi(cmat &m)
+{
+  uint64_t i, j;
+  double val_real, val_imag;
+  s >> i >> j;
+  m.set_size(static_cast<int>(i), static_cast<int>(j), false);
+  for (int j = 0; j < m.cols(); ++j)
+    for (int i = 0; i < m.rows(); ++i) {
+      s >> val_real;
+      s >> val_imag;
+      m(i, j) = std::complex<double>(val_real, val_imag);
+    }
+}
+
+void it_ifile::low_level_read(Array<bin> &v)
+{
+  uint64_t size;
+  char tmp;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> tmp;
+    v(i) = tmp;
+  }
+}
+
+void it_ifile::low_level_read(Array<short> &v)
+{
+  uint64_t size;
+  int16_t val;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val;
+    v(i) = val;
+  }
+}
+
+void it_ifile::low_level_read(Array<int> &v)
+{
+  uint64_t size;
+  int32_t val;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val;
+    v(i) = val;
+  }
+}
+
+void it_ifile::low_level_read(Array<float> &v)
+{
+  uint64_t size;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i)
+    s >> v(i);
+}
+
+void it_ifile::low_level_read_lo(Array<double> &v)
+{
+  uint64_t size;
+  float val;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val;
+    v(i) = static_cast<double>(val);
+  }
+}
+
+void it_ifile::low_level_read_hi(Array<double> &v)
+{
+  uint64_t size;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i)
+    s >> v(i);
+}
+
+void it_ifile::low_level_read(Array<std::complex<float> > &v)
+{
+  uint64_t size;
+  float val_real, val_imag;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<float>(val_real, val_imag);
+  }
+}
+
+void it_ifile::low_level_read_lo(Array<std::complex<double> > &v)
+{
+  uint64_t size;
+  float val_real, val_imag;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<double>(val_real, val_imag);
+  }
+}
+
+void it_ifile::low_level_read_hi(Array<std::complex<double> > &v)
+{
+  uint64_t size;
+  double val_real, val_imag;
+  s >> size;
+  v.set_size(static_cast<int>(size), false);
+  for (int i = 0; i < v.size(); ++i) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<double>(val_real, val_imag);
+  }
+}
+
+
+// ----------------------------------------------------------------------
+// it_file class
+// ----------------------------------------------------------------------
+
+it_file::it_file(): low_prec(false), next_name(""), next_desc(""),
+    fname("") {}
+
+it_file::it_file(const std::string &name, bool trunc):
+    low_prec(false), next_name(""), next_desc(""), fname("")
+{
+  open(name, trunc);
+}
+
+void it_file::open(const std::string &name, bool trunc)
+{
+  if (!exist(name))
+    trunc = true;
+
+  s.open(name, trunc, bfstream_base::l_endian);
+  it_assert(s.is_open(), "it_file::open(): Could not open file for writing");
+
+  if (trunc)
+    write_file_header();
+  else if (!read_check_file_header()) {
+    s.close();
+    it_error("it_file::open(): Corrupt file (not an it_file)");
+  }
+
+  fname = name;
+}
+
+void it_file::close()
+{
+  s.close();
+}
+
+void it_file::flush()
+{
+  s.flush();
+}
+
+void it_file::write_file_header()
+{
+  s.write(file_magic, 4);
+  s.put(file_version);
+}
+
+void it_file::write_data_header(const std::string &type, uint64_t size)
+{
+  it_error_if(next_name == "", "it_file::write_data_header(): Can not "
+              "write without a name");
+  write_data_header(type, next_name, size, next_desc);
+  next_name = "";
+  next_desc = "";
+}
+
+void it_file::write_data_header(const std::string &type,
+                                const std::string &name, uint64_t size,
+                                const std::string &desc)
+{
+  data_header h1, h2;
+
+  // Prepare a new data header
+  h1.hdr_bytes = 3 * sizeof(uint64_t) + type.size() + 1 + name.size() + 1
+                 + desc.size() + 1;
+  h1.data_bytes = size;
+  h1.block_bytes = h1.hdr_bytes + h1.data_bytes;
+  h1.name = name;
+  h1.type = type;
+  h1.desc = desc;
+
+  // If variable exists, remove it first
+  if (exists(name))
+    remove();
+
+  // Try to find an empty space
+  s.clear();
+  s.seekg(sizeof(file_header)); // skip file header
+  while (true) {
+    // save the current position
+    std::streampos p = s.tellp();
+    // read block at the current position
+    read_data_header(h2);
+    // if empty file, stop the search and set write pointer to the end of
+    // file
+    if (s.eof()) {
+      s.clear();
+      s.seekp(0, std::ios::end);
+      break;
+    }
+    // save the size of the current read block
+    std::streamoff skip = static_cast<std::streamoff>(h2.block_bytes);
+    // check if we have enough empty space from previously deleted data
+    if ((h2.type == "") && (h2.block_bytes >= h1.block_bytes)) {
+      h1.block_bytes = h2.block_bytes;
+      s.seekp(p);
+      break;
+    }
+    // if not, maybe we can squeeze the current block to find space
+    else if ((h2.block_bytes - h2.hdr_bytes - h2.data_bytes)
+             >= h1.block_bytes) {
+      h1.block_bytes = h2.block_bytes - h2.hdr_bytes - h2.data_bytes;
+      h2.block_bytes = h2.hdr_bytes + h2.data_bytes;
+      s.seekp(p);
+      // rewrite squeezed data block
+      write_data_header_here(h2);
+      s.seekp(p + static_cast<std::streamoff>(h2.block_bytes));
+      break;
+    }
+    // otherwise, skip the current block and try again
+    s.seekg(p + skip);
+  } // while(true)
+
+  write_data_header_here(h1);
+}
+
+void it_file::write_data_header_here(const data_header &h)
+{
+  s << h.hdr_bytes << h.data_bytes << h.block_bytes
+  << h.name << h.type << h.desc;
+}
+
+void it_file::remove(const std::string &name)
+{
+  seek(name);
+  remove();
+}
+
+void it_file::remove()
+{
+  data_header h;
+  std::streampos p;
+
+  p = s.tellp();
+  read_data_header(h);
+  h.type = "";
+  h.name = "";
+  h.desc = "";
+  h.hdr_bytes = 3 * sizeof(uint64_t) + 1 + 1 + 1;
+  h.data_bytes = 0;
+  s.seekp(p);
+  write_data_header_here(h);
+  s.seekp(p + static_cast<std::streamoff>(h.block_bytes));
+}
+
+bool it_file::exists(const std::string &name)
+{
+  return seek(name);
+}
+
+void it_file::pack()
+{
+  it_assert(s.is_open(), "it_file::pack(): File has to be open");
+
+  // check total file size
+  s.seekg(0, std::ios::end);
+  std::streampos p = s.tellg();
+  s.seekg(0, std::ios::beg);
+  s.clear();
+
+  // allocate buffer of size equal to file size
+  char* buffer = new char[p];
+  char* b_ptr = buffer;
+
+  // copy file header and start counting the size of compacted file
+  uint64_t size;
+  for (size = 0; size < sizeof(file_header); ++size)
+    s.get(*b_ptr++);
+
+  // remove empty space between data blocks
+  data_header h;
+  while (true) {
+    p = s.tellg();
+    read_data_header(h);
+    if (s.eof()) {
+      s.clear();
+      break;
+    }
+    if (h.type != "") {
+      s.seekg(p);
+      for (uint64_t i = 0; i < h.hdr_bytes + h.data_bytes; ++i)
+        s.get(*b_ptr++);
+      size += h.hdr_bytes + h.data_bytes;
+    }
+    s.seekg(p + static_cast<std::streamoff>(h.block_bytes));
+  }
+
+  // close and reopen file truncating it
+  s.close();
+  s.open(fname, true, bfstream_base::l_endian);
+  // write compacted data to the reopend empty file
+  for (uint64_t i = 0; i < size; ++i)
+    s.put(buffer[i]);
+
+  // free buffer memory
+  delete buffer;
+
+  // go back to the first data block (skiping file header)
+  s.seekg(sizeof(file_header));
+
+  // update block_bytes in headers of compacted data blocks
+  while (true) {
+    p = s.tellg();
+    read_data_header(h);
+    if (s.eof()) {
+      s.clear();
+      break;
+    }
+    if (h.hdr_bytes + h.data_bytes < h.block_bytes) {
+      h.block_bytes = h.hdr_bytes + h.data_bytes;
+      s.seekp(p);
+      write_data_header_here(h);
+    }
+    s.seekg(p + static_cast<std::streamoff>(h.block_bytes));
+  }
+}
+
+void it_file::low_level_write(char x)
+{
+  s << x;
+}
+
+void it_file::low_level_write(uint64_t x)
+{
+  s << x;
+}
+
+void it_file::low_level_write(bool x)
+{
+  s << static_cast<char>(x);
+}
+
+void it_file::low_level_write(bin x)
+{
+  s << x.value();
+}
+
+void it_file::low_level_write(short x)
+{
+  s << static_cast<int16_t>(x);
+}
+
+void it_file::low_level_write(int x)
+{
+  s << static_cast<int32_t>(x);
+}
+
+void it_file::low_level_write(float x)
+{
+  s << x;
+}
+
+void it_file::low_level_write(double x)
+{
+  s << x;
+}
+
+void it_file::low_level_write(const std::complex<float> &x)
+{
+  s << x.real();
+  s << x.imag();
+}
+
+void it_file::low_level_write(const std::complex<double> &x)
+{
+  s << x.real();
+  s << x.imag();
+}
+
+void it_file::low_level_write(const bvec &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  for (int i = 0; i < v.size(); ++i)
+    s << v(i).value();
+}
+
+void it_file::low_level_write(const svec &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  for (int i = 0; i < v.size(); ++i)
+    s << static_cast<int16_t>(v(i));
+}
+
+void it_file::low_level_write(const ivec &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  for (int i = 0; i < v.size(); ++i)
+    s << static_cast<int32_t>(v(i));
+}
+
+void it_file::low_level_write(const vec &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  if (get_low_precision()) {
+    for (int i = 0; i < v.size(); ++i)
+      s << static_cast<float>(v(i));
+  }
+  else {
+    for (int i = 0; i < v.size(); ++i)
+      s << v(i);
+  }
+}
+
+void it_file::low_level_write(const cvec &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  if (get_low_precision()) {
+    for (int i = 0; i < v.size(); ++i) {
+      s << static_cast<float>(v(i).real());
+      s << static_cast<float>(v(i).imag());
+    }
+  }
+  else {
+    for (int i = 0; i < v.size(); ++i) {
+      s << v(i).real();
+      s << v(i).imag();
+    }
+  }
+}
+
+void it_file::low_level_write(const std::string &str)
+{
+  s << static_cast<uint64_t>(str.size());
+  for (std::string::size_type i = 0; i < str.size(); ++i)
+    s << str[i];
+}
+
+void it_file::low_level_write(const bmat &m)
+{
+  s << static_cast<uint64_t>(m.rows())
+  << static_cast<uint64_t>(m.cols());
+  for (int j = 0; j < m.cols(); ++j)
+    for (int i = 0; i < m.rows(); ++i)
+      s << m(i, j).value();
+}
+
+void it_file::low_level_write(const smat &m)
+{
+  s << static_cast<uint64_t>(m.rows())
+  << static_cast<uint64_t>(m.cols());
+  for (int j = 0; j < m.cols(); ++j)
+    for (int i = 0; i < m.rows(); ++i)
+      s << static_cast<int16_t>(m(i, j));
+}
+
+void it_file::low_level_write(const imat &m)
+{
+  s << static_cast<uint64_t>(m.rows())
+  << static_cast<uint64_t>(m.cols());
+  for (int j = 0; j < m.cols(); ++j)
+    for (int i = 0; i < m.rows(); ++i)
+      s << static_cast<int32_t>(m(i, j));
+}
+
+void it_file::low_level_write(const mat &m)
+{
+  s << static_cast<uint64_t>(m.rows())
+  << static_cast<uint64_t>(m.cols());
+  if (get_low_precision()) {
+    for (int j = 0; j < m.cols(); ++j)
+      for (int i = 0; i < m.rows(); ++i)
+        s << static_cast<float>(m(i, j));
+  }
+  else {
+    for (int j = 0; j < m.cols(); ++j)
+      for (int i = 0; i < m.rows(); ++i)
+        s << m(i, j);
+  }
+}
+
+void it_file::low_level_write(const cmat &m)
+{
+  s << static_cast<uint64_t>(m.rows())
+  << static_cast<uint64_t>(m.cols());
+  if (get_low_precision()) {
+    for (int j = 0; j < m.cols(); ++j)
+      for (int i = 0; i < m.rows(); ++i) {
+        s << static_cast<float>(m(i, j).real());
+        s << static_cast<float>(m(i, j).imag());
+      }
+  }
+  else {
+    for (int j = 0; j < m.cols(); ++j)
+      for (int i = 0; i < m.rows(); ++i) {
+        s << m(i, j).real();
+        s << m(i, j).imag();
+      }
+  }
+}
+
+void it_file::low_level_write(const Array<bin> &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  for (int i = 0; i < v.size(); ++i)
+    s << v(i).value();
+}
+
+void it_file::low_level_write(const Array<short> &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  for (int i = 0; i < v.size(); ++i)
+    s << static_cast<int16_t>(v(i));
+}
+
+void it_file::low_level_write(const Array<int> &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  for (int i = 0; i < v.size(); ++i)
+    s << static_cast<int32_t>(v(i));
+}
+
+void it_file::low_level_write(const Array<float> &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  for (int i = 0; i < v.size(); ++i)
+    s << v(i);
+}
+
+void it_file::low_level_write(const Array<double> &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  if (get_low_precision()) {
+    for (int i = 0; i < v.size(); ++i)
+      s << static_cast<float>(v(i));
+  }
+  else {
+    for (int i = 0; i < v.size(); ++i)
+      s << static_cast<double>(v(i));
+  }
+}
+
+void it_file::low_level_write(const Array<std::complex<float> > &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  for (int i = 0; i < v.size(); ++i) {
+    s << v(i).real();
+    s << v(i).imag();
+  }
+}
+
+void it_file::low_level_write(const Array<std::complex<double> > &v)
+{
+  s << static_cast<uint64_t>(v.size());
+  if (get_low_precision()) {
+    for (int i = 0; i < v.size(); ++i) {
+      s << static_cast<float>(v(i).real());
+      s << static_cast<float>(v(i).imag());
+    }
+  }
+  else {
+    for (int i = 0; i < v.size(); ++i) {
+      s << v(i).real();
+      s << v(i).imag();
+    }
+  }
+}
+
+
+it_ifile &operator>>(it_ifile &f, char &x)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "int8", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(x);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, bool &x)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "bool", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(x);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, bin &x)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "bin", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(x);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, short &x)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "int16", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(x);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, int &x)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  if (h.type == "int32")
+    f.low_level_read(x);
+  else if (h.type == "int16") {
+    short x16;
+    f.low_level_read(x16);
+    x = static_cast<int>(x16);
+  }
+  else
+    it_error("it_ifile::operator>>(): Wrong type");
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, float &x)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "float32", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(x);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, double &x)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  if (h.type == "float64")
+    f.low_level_read(x);
+  else if (h.type == "float32") {
+    float f32;
+    f.low_level_read(f32);
+    x = static_cast<double>(f32);
+  }
+  else
+    it_error("it_ifile::operator>>(): Wrong type");
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, std::complex<float> &x)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "cfloat32",
+            "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(x);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, std::complex<double> &x)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  if (h.type == "cfloat64")
+    f.low_level_read(x);
+  else if (h.type == "cfloat32") {
+    std::complex<float> f32_c;
+    f.low_level_read(f32_c);
+    x = static_cast<std::complex<double> >(f32_c);
+  }
+  else
+    it_error("it_ifile::operator>>(): Wrong type");
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, bvec &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "bvec", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(v);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, svec &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "svec", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(v);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, ivec &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "ivec", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(v);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, vec &v)
+{
+  it_ifile::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fvec")
+    f.low_level_read_lo(v);
+  else if (h.type == "dvec")
+    f.low_level_read_hi(v);
+  else
+    it_error("it_ifile::operator>>(): Wrong type");
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, cvec &v)
+{
+  it_file::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fcvec")
+    f.low_level_read_lo(v);
+  else if (h.type == "dcvec")
+    f.low_level_read_hi(v);
+  else
+    it_error("it_ifile::operator>>(): Wrong type");
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, std::string &str)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "string", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(str);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, bmat &m)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "bmat", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(m);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, smat &m)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "smat", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(m);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, imat &m)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "imat", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(m);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, mat &m)
+{
+  it_file::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fmat")
+    f.low_level_read_lo(m);
+  else if (h.type == "dmat")
+    f.low_level_read_hi(m);
+  else
+    it_error("it_ifile::operator>>(): Wrong type");
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, cmat &m)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  if (h.type == "fcmat")
+    f.low_level_read_lo(m);
+  else if (h.type == "dcmat")
+    f.low_level_read_hi(m);
+  else
+    it_error("it_ifile::operator>>(): Wrong type");
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<bin> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "bArray", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(v);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<short> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "sArray", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(v);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<int> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "iArray", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(v);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<float> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "fArray", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(v);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<double> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  if (h.type == "fArray")
+    f.low_level_read_lo(v);
+  else if (h.type == "dArray")
+    f.low_level_read_hi(v);
+  else
+    it_error("it_ifile::operator>>(): Wrong type");
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<std::complex<float> > &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "fcArray", "it_ifile::operator>>(): Wrong type");
+  f.low_level_read(v);
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<std::complex<double> > &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  if (h.type == "fcArray")
+    f.low_level_read_lo(v);
+  else if (h.type == "dcArray")
+    f.low_level_read_hi(v);
+  else
+    it_error("it_ifile::operator>>(): Wrong type");
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<bvec> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "bvecArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<svec> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "svecArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<ivec> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "ivecArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<vec> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "vecArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read_hi(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<cvec> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "cvecArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read_hi(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<std::string> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "stringArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<bmat> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "bmatArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<smat> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "smatArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<imat> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "imatArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<mat> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "matArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read_hi(v(i));
+
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, Array<cmat> &v)
+{
+  it_file::data_header h;
+  f.read_data_header(h);
+  it_assert(h.type == "cmatArray", "it_ifile::operator>>(): Wrong type");
+  uint64_t n;
+  f.low_level_read(n);
+  int size = static_cast<int>(n);
+  v.set_size(size, false);
+  for (int i = 0; i < size; ++i)
+    f.low_level_read_hi(v(i));
+
+  return f;
+}
+
+
+it_file &operator<<(it_file &f, char x)
+{
+  f.write_data_header("int8", sizeof(char));
+  f.low_level_write(x);
+  return f;
+}
+
+it_file &operator<<(it_file &f, bool x)
+{
+  f.write_data_header("bool", sizeof(char));
+  f.low_level_write(x);
+  return f;
+}
+
+it_file &operator<<(it_file &f, bin x)
+{
+  f.write_data_header("bin", sizeof(char));
+  f.low_level_write(x);
+  return f;
+}
+
+it_file &operator<<(it_file &f, short x)
+{
+  f.write_data_header("int16", sizeof(int16_t));
+  f.low_level_write(x);
+  return f;
+}
+
+it_file &operator<<(it_file &f, int x)
+{
+  f.write_data_header("int32", sizeof(int32_t));
+  f.low_level_write(x);
+  return f;
+}
+
+it_file &operator<<(it_file &f, float x)
+{
+  f.write_data_header("float32", sizeof(float));
+  f.low_level_write(x);
+  return f;
+}
+
+it_file &operator<<(it_file &f, double x)
+{
+  f.write_data_header("float64", sizeof(double));
+  f.low_level_write(x);
+  return f;
+}
+
+it_file &operator<<(it_file &f, std::complex<float> x)
+{
+  f.write_data_header("cfloat32", 2 * sizeof(float));
+  f.low_level_write(x);
+  return f;
+}
+
+it_file &operator<<(it_file &f, std::complex<double> x)
+{
+  f.write_data_header("cfloat64", 2 * sizeof(double));
+  f.low_level_write(x);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const bvec &v)
+{
+  f.write_data_header("bvec", sizeof(uint64_t) + v.size() * sizeof(char));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const svec &v)
+{
+  f.write_data_header("svec", sizeof(uint64_t) + v.size() * sizeof(int16_t));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const ivec &v)
+{
+  f.write_data_header("ivec", sizeof(uint64_t) + v.size() * sizeof(int32_t));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const vec &v)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fvec", sizeof(uint64_t)
+                        + v.size() * sizeof(float));
+  else
+    f.write_data_header("dvec", sizeof(uint64_t)
+                        + v.size() * sizeof(double));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const cvec &v)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fcvec", sizeof(uint64_t)
+                        + v.size() * 2 * sizeof(float));
+  else
+    f.write_data_header("dcvec", sizeof(uint64_t)
+                        + v.size() * 2 * sizeof(double));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const std::string &str)
+{
+  f.write_data_header("string", sizeof(uint64_t) + str.size() * sizeof(char));
+  f.low_level_write(str);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const bmat &m)
+{
+  f.write_data_header("bmat", 2 * sizeof(uint64_t)
+                      + m.rows() * m.cols() * sizeof(char));
+  f.low_level_write(m);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const smat &m)
+{
+  f.write_data_header("smat", 2 * sizeof(uint64_t)
+                      + m.rows() * m.cols() * sizeof(int16_t));
+  f.low_level_write(m);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const imat &m)
+{
+  f.write_data_header("imat", 2 * sizeof(uint64_t)
+                      + m.rows() * m.cols() * sizeof(int32_t));
+  f.low_level_write(m);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const mat &m)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fmat", 2 * sizeof(uint64_t)
+                        + m.rows() * m.cols() * sizeof(float));
+  else
+    f.write_data_header("dmat", 2 * sizeof(uint64_t)
+                        + m.rows() * m.cols() * sizeof(double));
+  f.low_level_write(m);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const cmat &m)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fcmat", 2 * sizeof(uint64_t)
+                        + m.rows() * m.cols() * 2 * sizeof(float));
+  else
+    f.write_data_header("dcmat", 2 * sizeof(uint64_t)
+                        + m.rows() * m.cols() * 2 * sizeof(double));
+  f.low_level_write(m);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<bin> &v)
+{
+  f.write_data_header("bArray", sizeof(uint64_t) + v.size() * sizeof(char));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<short> &v)
+{
+  f.write_data_header("sArray", sizeof(uint64_t)
+                      + v.size() * sizeof(int16_t));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<int> &v)
+{
+  f.write_data_header("iArray", sizeof(uint64_t)
+                      + v.size() * sizeof(int32_t));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<float> &v)
+{
+  f.write_data_header("fArray", sizeof(uint64_t) + v.size() * sizeof(float));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<double> &v)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fArray", sizeof(uint64_t)
+                        + v.size() * sizeof(float));
+  else
+    f.write_data_header("dArray", sizeof(uint64_t)
+                        + v.size() * sizeof(double));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<std::complex<float> > &v)
+{
+  f.write_data_header("fcArray", sizeof(uint64_t)
+                      + v.size() * 2 * sizeof(float));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<std::complex<double> > &v)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fcArray", sizeof(uint64_t)
+                        + v.size() * 2 * sizeof(float));
+  else
+    f.write_data_header("dcArray", sizeof(uint64_t)
+                        + v.size() * 2 * sizeof(double));
+  f.low_level_write(v);
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<bvec> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i).size();
+
+  // write header
+  f.write_data_header("bvecArray", sizeof(uint64_t) * (1 + v.size())
+                      + sum_l * sizeof(char));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<svec> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i).size();
+
+  // write header
+  f.write_data_header("svecArray", sizeof(uint64_t) * (1 + v.size())
+                      + sum_l * sizeof(int16_t));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<ivec> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i).size();
+
+  // write header
+  f.write_data_header("ivecArray", sizeof(uint64_t) * (1 + v.size())
+                      + sum_l * sizeof(int32_t));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<vec> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i).size();
+
+  // write header
+  f.write_data_header("vecArray", sizeof(uint64_t) * (1 + v.size())
+                      + sum_l * sizeof(double));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<cvec> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i).size();
+
+  // write header
+  f.write_data_header("cvecArray", sizeof(uint64_t) * (1 + v.size())
+                      + sum_l * 2 * sizeof(double));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<std::string> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i).size();
+
+  // write header
+  f.write_data_header("stringArray", sizeof(uint64_t) * (1 + v.size())
+                      + sum_l * sizeof(char));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<bmat> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i)._datasize();
+
+  // write header
+  f.write_data_header("bmatArray", sizeof(uint64_t) * (1 + 2 * v.size())
+                      + sum_l * sizeof(char));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<smat> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i)._datasize();
+
+  // write header
+  f.write_data_header("smatArray", sizeof(uint64_t) * (1 + 2 * v.size())
+                      + sum_l * sizeof(int16_t));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<imat> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i)._datasize();
+
+  // write header
+  f.write_data_header("imatArray", sizeof(uint64_t) * (1 + 2 * v.size())
+                      + sum_l * sizeof(int32_t));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<mat> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i)._datasize();
+
+  // write header
+  f.write_data_header("matArray", sizeof(uint64_t) * (1 + 2 * v.size())
+                      + sum_l * sizeof(double));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file &operator<<(it_file &f, const Array<cmat> &v)
+{
+  // calculate total length of Array
+  int sum_l = 0;
+  for (int i = 0; i < v.size(); ++i)
+    sum_l += v(i)._datasize();
+
+  // write header
+  f.write_data_header("cmatArray", sizeof(uint64_t) * (1 + 2 * v.size())
+                      + sum_l * 2 * sizeof(double));
+  // write the length of the array
+  f.low_level_write(static_cast<uint64_t>(v.size()));
+
+  // write one vector at a time (i.e. size and elements)
+  for (int i = 0; i < v.size(); ++i)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+
+
+// ----------------------------------------------------------------------
+// Deprecated implementation of IT++ file format version 2
+// Will be removed in future versions
+// ----------------------------------------------------------------------
+
+char it_file_base_old::file_magic[4] = { 'I', 'T', '+', '+' };
+char it_file_base_old::file_version = 2;
+
+it_ifile_old::it_ifile_old()
+{
+}
+
+it_ifile_old::it_ifile_old(const std::string &name)
+{
+  open(name);
+}
+
+void it_ifile_old::open(const std::string &name)
+{
+  it_assert(exist(name), "File does not exist");
+
+  s.open_readonly(name);
+
+  if (!read_check_file_header()) {
+    s.close();
+    it_error("Corrupt file (Not an it-file)");
+  }
+
+}
+
+void it_ifile_old::close()
+{
+  s.close();
+}
+
+bool it_ifile_old::seek(const std::string &name)
+{
+  data_header h;
+  std::streampos p;
+
+  s.clear();
+  s.seekg(sizeof(file_header));
+
+  while (true) {
+    p = s.tellg();
+    read_data_header(h);
+    if (s.eof()) {
+      s.clear();
+      return false;
+    }
+    if (h.type != "" && h.name == name) {
+      s.seekg(p);
+      break;
+    }
+    s.seekg(p + static_cast<std::streamoff>(h.block_bytes));
+  }
+
+  return true;
+}
+
+bool it_ifile_old::seek(int n)
+{
+  data_header h;
+  std::streampos p;
+
+  s.clear();
+  s.seekg(sizeof(file_header));
+  for (int i = 0; i <= n; i++) {
+    p = s.tellg(); // changed from tellp() since probably an error
+    read_data_header(h);
+    if (s.eof()) {
+      s.clear();
+      return false;
+    }
+    if (h.type == "")
+      i--;
+    s.seekg(i == n ? p : p + static_cast<std::streamoff>(h.block_bytes));
+  }
+  return true;
+}
+
+void it_ifile_old::info(std::string &name, std::string &type, int &bytes)
+{
+  data_header h;
+  std::streampos p;
+
+  p = s.tellg(); // changed from tellp()
+  read_data_header(h);
+  s.seekg(p);
+  name = h.name;
+  type = h.type;
+  bytes = h.data_bytes;
+}
+
+bool it_ifile_old::read_check_file_header()
+{
+  file_header h;
+
+  memset(&h, 0, sizeof(h)); // Clear the struct
+  s.read(reinterpret_cast<char *>(&h), sizeof(h));
+
+  return (memcmp(h.magic, file_magic, 4) == 0 && (h.version <= file_version));
+}
+
+void it_ifile_old::read_data_header(data_header &h)
+{
+  std::streampos p = s.tellg();
+  s.clear();
+  s >> h.endianity;
+  if (s.eof())
+    return;
+  s.set_endianity(static_cast<bfstream_base::endian>(h.endianity));
+  uint32_t tmp;
+  s >> tmp;
+  h.hdr_bytes = tmp;
+  s >> tmp;
+  h.data_bytes = tmp;
+  s >> tmp;
+  h.block_bytes = tmp;
+  s >> h.name;
+  s >> h.type;
+  s.seekg(p + static_cast<std::streamoff>(h.hdr_bytes));
+}
+
+void it_ifile_old::low_level_read(char &x)
+{
+  s >> x;
+}
+
+void it_ifile_old::low_level_read(bin &x)
+{
+  s >> x;
+}
+
+void it_ifile_old::low_level_read(short &x)
+{
+  s >> x;
+}
+
+void it_ifile_old::low_level_read(int &x)
+{
+  int32_t tmp;
+  s >> tmp;
+  x = tmp;
+}
+
+void it_ifile_old::low_level_read(float &x)
+{
+  s >> x;
+}
+
+void it_ifile_old::low_level_read(double &x)
+{
+  s >> x;
+}
+
+void it_ifile_old::low_level_read(std::complex<float> &x)
+{
+  float x_real, x_imag;
+  s >> x_real;
+  s >> x_imag;
+  x = std::complex<float>(x_real, x_imag);
+}
+
+void it_ifile_old::low_level_read(std::complex<double> &x)
+{
+  double x_real, x_imag;
+  s >> x_real;
+  s >> x_imag;
+  x = std::complex<double>(x_real, x_imag);
+}
+
+void it_ifile_old::low_level_read_lo(vec &v)
+{
+  int32_t i;
+  float val;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val;
+    v(i) = static_cast<double>(val);
+  }
+}
+
+void it_ifile_old::low_level_read_hi(vec &v)
+{
+  int32_t i;
+  double val;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val;
+    v(i) = static_cast<double>(val);
+  }
+}
+
+void it_ifile_old::low_level_read(ivec &v)
+{
+  int32_t i, val;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val;
+    v(i) = val;
+  }
+}
+
+void it_ifile_old::low_level_read(bvec &v)
+{
+  int32_t i;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++)
+    s >> v(i);
+}
+
+void it_ifile_old::low_level_read_lo(cvec &v)
+{
+  int32_t i;
+  float val_real, val_imag;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<double>(val_real, val_imag);
+  }
+}
+
+void it_ifile_old::low_level_read_hi(cvec &v)
+{
+  int32_t i;
+  double val_real, val_imag;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<double>(val_real, val_imag);
+  }
+}
+
+void it_ifile_old::low_level_read(std::string &str)
+{
+  int32_t i, j;
+  char val;
+  str = "";
+
+  s >> i;
+
+  for (j = 0; j < i; j++) {
+    s >> val;
+    str += val;
+  }
+}
+
+void it_ifile_old::low_level_read_lo(mat &m)
+{
+  int32_t i, j;
+  float val;
+
+  s >> i >> j;
+  m.set_size(i, j, false);
+  for (j = 0; j < m.cols(); j++)
+    for (i = 0; i < m.rows(); i++) {
+      s >> val;
+      m(i, j) = static_cast<double>(val);
+    }
+}
+
+void it_ifile_old::low_level_read_hi(mat &m)
+{
+  int32_t i, j;
+  double val;
+
+  s >> i >> j;
+  m.set_size(i, j, false);
+  for (j = 0; j < m.cols(); j++)
+    for (i = 0; i < m.rows(); i++) {
+      s >> val;
+      m(i, j) = static_cast<double>(val);
+    }
+}
+
+void it_ifile_old::low_level_read(imat &m)
+{
+  int32_t i, j, val;
+
+  s >> i >> j;
+  m.set_size(i, j, false);
+  for (j = 0; j < m.cols(); j++)
+    for (i = 0; i < m.rows(); i++) {
+      s >> val;
+      m(i, j) = val;
+    }
+}
+
+void it_ifile_old::low_level_read(bmat &m)
+{
+  int32_t i, j;
+
+  s >> i >> j;
+  m.set_size(i, j, false);
+  for (j = 0; j < m.cols(); j++)
+    for (i = 0; i < m.rows(); i++)
+      s >> m(i, j);
+}
+
+void it_ifile_old::low_level_read_lo(cmat &m)
+{
+  int32_t i, j;
+  float val_real, val_imag;
+
+  s >> i >> j;
+  m.set_size(i, j, false);
+  for (j = 0; j < m.cols(); j++)
+    for (i = 0; i < m.rows(); i++) {
+      s >> val_real;
+      s >> val_imag;
+      m(i, j) = std::complex<double>(val_real, val_imag);
+    }
+}
+
+void it_ifile_old::low_level_read_hi(cmat &m)
+{
+  int32_t i, j;
+  double val_real, val_imag;
+
+  s >> i >> j;
+  m.set_size(i, j, false);
+  for (j = 0; j < m.cols(); j++)
+    for (i = 0; i < m.rows(); i++) {
+      s >> val_real;
+      s >> val_imag;
+      m(i, j) = std::complex<double>(val_real, val_imag);
+    }
+}
+
+
+void it_ifile_old::low_level_read_lo(Array<float> &v)
+{
+  int32_t i;
+  float val;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val;
+    v(i) = val;
+  }
+}
+
+void it_ifile_old::low_level_read_lo(Array<double> &v)
+{
+  int32_t i;
+  float val;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val;
+    v(i) = static_cast<double>(val);
+  }
+}
+
+void it_ifile_old::low_level_read_hi(Array<double> &v)
+{
+  int32_t i;
+  double val;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val;
+    v(i) = static_cast<double>(val);
+  }
+}
+
+void it_ifile_old::low_level_read(Array<int> &v)
+{
+  int32_t i, val;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val;
+    v(i) = val;
+  }
+}
+
+void it_ifile_old::low_level_read(Array<bin> &v)
+{
+  int32_t i;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++)
+    s >> v(i);
+}
+
+void it_ifile_old::low_level_read_lo(Array<std::complex<float> > &v)
+{
+  int32_t i;
+  float val_real, val_imag;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<float>(val_real, val_imag);
+  }
+}
+
+void it_ifile_old::low_level_read_lo(Array<std::complex<double> > &v)
+{
+  int32_t i;
+  float val_real, val_imag;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<double>(val_real, val_imag);
+  }
+}
+
+void it_ifile_old::low_level_read_hi(Array<std::complex<double> > &v)
+{
+  int32_t i;
+  double val_real, val_imag;
+
+  s >> i;
+  v.set_size(i, false);
+  for (i = 0; i < v.size(); i++) {
+    s >> val_real;
+    s >> val_imag;
+    v(i) = std::complex<double>(val_real, val_imag);
+  }
+}
+
+it_file_old::it_file_old()
+{
+  low_prec = false;
+  next_name = "";
+}
+
+it_file_old::it_file_old(const std::string &name, bool trunc)
+{
+  low_prec = false;
+  next_name = "";
+  open(name, trunc);
+}
+
+void it_file_old::open(const std::string &name, bool trunc)
+{
+  if (!exist(name))
+    trunc = true;
+
+  s.open(name, trunc);
+  it_error_if(!s.is_open(), "Could not open file for writing");
+
+  if (trunc)
+    write_file_header();
+  else if (!read_check_file_header()) {
+    s.close();
+    it_error("Corrupt file (Not an it-file)");
+  }
+}
+
+void it_file_old::close()
+{
+  s.close();
+}
+
+void it_file_old::flush()
+{
+  s.flush();
+}
+
+void it_file_old::write_file_header()
+{
+  s.write(file_magic, 4);
+  s << file_version;
+}
+
+void it_file_old::write_data_header(const std::string &type, uint32_t size)
+{
+  it_error_if(next_name == "", "Try to write without a name");
+  write_data_header(type, next_name, size);
+  next_name = "";
+}
+
+void it_file_old::write_data_header(const std::string &type,
+                                    const std::string &name, uint32_t size)
+{
+  data_header h1, h2;
+  std::streampos p;
+  int availpos = 0;
+  bool removed = false;
+  int skip;
+
+  h1.endianity = static_cast<char>(s.get_native_endianity());
+  h1.hdr_bytes = 1 + 3 * 4 + type.size() + 1 + name.size() + 1;
+  h1.data_bytes = size;
+  h1.block_bytes = h1.hdr_bytes + h1.data_bytes;
+  h1.name = name;
+  h1.type = type;
+
+  if (exists(name))
+    remove();
+
+  // Try to find an empty space
+  s.clear();
+  s.seekg(sizeof(file_header));
+  while (true) {
+    p = s.tellp();
+    read_data_header(h2);
+    if (s.eof()) {
+      s.clear();
+      break;
+    }
+    skip = h2.block_bytes;
+    if (h2.type != "" && h2.name == name) {
+      s.seekg(p);
+      remove();
+      s.seekg(p);
+      read_data_header(h2);
+      removed = true;
+      if (availpos != 0)
+        break;
+    }
+    if (availpos == 0) {
+      if (h2.type == "" && h2.block_bytes >= h1.block_bytes) {
+        h1.block_bytes = h2.block_bytes;
+        availpos = p;
+      }
+      else if (h2.block_bytes - h2.hdr_bytes - h2.data_bytes >= h1.block_bytes) {
+        h1.block_bytes = h2.block_bytes - h2.hdr_bytes - h2.data_bytes;
+        h2.block_bytes = h2.hdr_bytes + h2.data_bytes;
+        s.seekp(p);
+        write_data_header_here(h2);
+        availpos = static_cast<int>(p) + h2.block_bytes;
+        if (removed)
+          break;
+      }
+    }
+    s.seekg(p + static_cast<std::streamoff>(skip));
+  }
+  if (availpos != 0)
+    s.seekp(availpos);
+  else
+    s.seekp(0, std::ios::end);
+
+  write_data_header_here(h1);
+}
+
+void it_file_old::write_data_header_here(const data_header &h)
+{
+  s.set_endianity(static_cast<bfstream_base::endian>(h.endianity));
+  s << h.endianity << h.hdr_bytes << h.data_bytes << h.block_bytes << h.name << h.type;
+}
+
+void it_file_old::remove(const std::string &name)
+{
+  seek(name);
+  remove();
+}
+
+void it_file_old::remove()
+{
+  data_header h;
+  std::streampos p;
+
+  p = s.tellp();
+  read_data_header(h);
+  h.type = "";
+  h.name = "";
+  h.hdr_bytes = 1 + 3 * 4 + 1 + 1;
+  h.data_bytes = 0;
+  s.seekp(p);
+  write_data_header_here(h);
+  s.seekp(p + static_cast<std::streamoff>(h.block_bytes));
+}
+
+bool it_file_old::exists(const std::string &name)
+{
+  if (seek(name))
+    return true;
+  else
+    return false;
+}
+
+void it_file_old::pack()
+{
+  it_warning("pack() is not implemented!");
+}
+
+void it_file_old::low_level_write(char x)
+{
+  s << x;
+}
+
+void it_file_old::low_level_write(bin x)
+{
+  s << x.value();
+}
+
+void it_file_old::low_level_write(short x)
+{
+  s << x;
+}
+
+void it_file_old::low_level_write(int x)
+{
+  s << static_cast<int32_t>(x);
+}
+
+void it_file_old::low_level_write(float x)
+{
+  s << x;
+}
+
+void it_file_old::low_level_write(double x)
+{
+  s << x;
+}
+
+void it_file_old::low_level_write(const std::complex<float> &x)
+{
+  s << x.real();
+  s << x.imag();
+}
+
+void it_file_old::low_level_write(const std::complex<double> &x)
+{
+  s << x.real();
+  s << x.imag();
+}
+
+void it_file_old::low_level_write(const vec &v)
+{
+  if (get_low_precision()) {
+    s << static_cast<int32_t>(v.size());
+    for (int i = 0; i < v.size(); i++)
+      s << static_cast<float>(v(i));
+  }
+  else {
+    s << static_cast<int32_t>(v.size());
+    for (int i = 0; i < v.size(); i++)
+      s << static_cast<double>(v(i));
+  }
+}
+
+void it_file_old::low_level_write(const ivec &v)
+{
+  s << static_cast<int32_t>(v.size());
+  for (int i = 0; i < v.size(); i++)
+    s << static_cast<int32_t>(v(i));
+}
+
+void it_file_old::low_level_write(const bvec &v)
+{
+  s << static_cast<int32_t>(v.size());
+  for (int i = 0; i < v.size(); i++)
+    s << v(i).value();
+}
+
+void it_file_old::low_level_write(const cvec &v)
+{
+  if (get_low_precision()) {
+    s << static_cast<int32_t>(v.size());
+    for (int i = 0; i < v.size(); i++) {
+      s << static_cast<float>(v(i).real());
+      s << static_cast<float>(v(i).imag());
+    }
+  }
+  else {
+    s << static_cast<int32_t>(v.size());
+    for (int i = 0; i < v.size(); i++) {
+      s << static_cast<double>(v(i).real());
+      s << static_cast<double>(v(i).imag());
+    }
+  }
+}
+
+void it_file_old::low_level_write(const std::string &str)
+{
+  int size = str.size();
+  s << static_cast<int32_t>(size);
+
+  for (int i = 0; i < size; i++)
+    s << str[i];
+}
+
+void it_file_old::low_level_write(const mat &m)
+{
+  int i, j;
+
+  if (get_low_precision()) {
+    s << static_cast<int32_t>(m.rows()) << static_cast<int32_t>(m.cols());
+    for (j = 0; j < m.cols(); j++)
+      for (i = 0; i < m.rows(); i++)
+        s << static_cast<float>(m(i, j));
+  }
+  else {
+    s << static_cast<int32_t>(m.rows()) << static_cast<int32_t>(m.cols());
+    for (j = 0; j < m.cols(); j++)
+      for (i = 0; i < m.rows(); i++)
+        s << static_cast<double>(m(i, j));
+  }
+}
+
+void it_file_old::low_level_write(const imat &m)
+{
+  int i, j;
+
+  s << static_cast<int32_t>(m.rows()) << static_cast<int32_t>(m.cols());
+  for (j = 0; j < m.cols(); j++)
+    for (i = 0; i < m.rows(); i++)
+      s << static_cast<int32_t>(m(i, j));
+}
+
+void it_file_old::low_level_write(const bmat &m)
+{
+  int i, j;
+
+  s << static_cast<int32_t>(m.rows()) << static_cast<int32_t>(m.cols());
+  for (j = 0; j < m.cols(); j++)
+    for (i = 0; i < m.rows(); i++)
+      s << m(i, j).value();
+}
+
+void it_file_old::low_level_write(const cmat &m)
+{
+  int i, j;
+
+  if (get_low_precision()) {
+    s << static_cast<int32_t>(m.rows()) << static_cast<int32_t>(m.cols());
+    for (j = 0; j < m.cols(); j++)
+      for (i = 0; i < m.rows(); i++) {
+        s << static_cast<float>(m(i, j).real());
+        s << static_cast<float>(m(i, j).imag());
+      }
+
+  }
+  else {
+    s << static_cast<int32_t>(m.rows()) << static_cast<int32_t>(m.cols());
+    for (j = 0; j < m.cols(); j++)
+      for (i = 0; i < m.rows(); i++) {
+        s << static_cast<double>(m(i, j).real());
+        s << static_cast<double>(m(i, j).imag());
+      }
+  }
+}
+
+void it_file_old::low_level_write(const Array<float> &v)
+{
+  s << static_cast<int32_t>(v.size());
+  for (int i = 0; i < v.size(); i++)
+    s << v(i);
+}
+
+void it_file_old::low_level_write(const Array<double> &v)
+{
+  if (get_low_precision()) {
+    s << static_cast<int32_t>(v.size());
+    for (int i = 0; i < v.size(); i++)
+      s << static_cast<float>(v(i));
+  }
+  else {
+    s << static_cast<int32_t>(v.size());
+    for (int i = 0; i < v.size(); i++)
+      s << static_cast<double>(v(i));
+  }
+}
+
+void it_file_old::low_level_write(const Array<int> &v)
+{
+  s << static_cast<int32_t>(v.size());
+  for (int i = 0; i < v.size(); i++)
+    s << static_cast<int32_t>(v(i));
+}
+
+void it_file_old::low_level_write(const Array<bin> &v)
+{
+  s << static_cast<int32_t>(v.size());
+  for (int i = 0; i < v.size(); i++)
+    s << v(i).value();
+}
+
+void it_file_old::low_level_write(const Array<std::complex<float> > &v)
+{
+  s << static_cast<int32_t>(v.size());
+  for (int i = 0; i < v.size(); i++) {
+    s << v(i).real();
+    s << v(i).imag();
+  }
+}
+
+void it_file_old::low_level_write(const Array<std::complex<double> > &v)
+{
+  if (get_low_precision()) {
+    s << static_cast<int32_t>(v.size());
+    for (int i = 0; i < v.size(); i++) {
+      s << static_cast<float>(v(i).real());
+      s << static_cast<float>(v(i).imag());
+    }
+  }
+  else {
+    s << static_cast<int32_t>(v.size());
+    for (int i = 0; i < v.size(); i++) {
+      s << static_cast<double>(v(i).real());
+      s << static_cast<double>(v(i).imag());
+    }
+  }
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, char &x)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "int8")
+    f.low_level_read(x);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, bin &x)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "bin")
+    f.low_level_read(x);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, short &x)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "int16")
+    f.low_level_read(x);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, int &x)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "int32")
+    f.low_level_read(x);
+  else if (h.type == "int16") {
+    short x16;
+    f.low_level_read(x16);
+    x = x16;
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, double &x)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "float64")
+    f.low_level_read(x);
+  else if (h.type == "float32") {
+    float f32;
+    f.low_level_read(f32);
+    x = f32;
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, float &x)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "float32")
+    f.low_level_read(x);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, std::complex<float> &x)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+
+  if (h.type == "float32_complex") {
+    std::complex<float> f32_c;
+    f.low_level_read(f32_c);
+    x = f32_c;
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, std::complex<double> &x)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "float64_complex")
+    f.low_level_read(x);
+  else if (h.type == "float32_complex") {
+    std::complex<float> f32_c;
+    f.low_level_read(f32_c);
+    x = f32_c;
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, vec &v)
+{
+  it_ifile_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fvec")
+    f.low_level_read_lo(v);
+  else if (h.type == "dvec")
+    f.low_level_read_hi(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, ivec &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "ivec")
+    f.low_level_read(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, bvec &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "bvec")
+    f.low_level_read(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, cvec &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fcvec")
+    f.low_level_read_lo(v);
+  else if (h.type == "dcvec")
+    f.low_level_read_hi(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, std::string &str)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "string")
+    f.low_level_read(str);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, mat &m)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fmat")
+    f.low_level_read_lo(m);
+  else if (h.type == "dmat")
+    f.low_level_read_hi(m);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, imat &m)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "imat")
+    f.low_level_read(m);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, bmat &m)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "bmat")
+    f.low_level_read(m);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, cmat &m)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fcmat")
+    f.low_level_read_lo(m);
+  else if (h.type == "dcmat")
+    f.low_level_read_hi(m);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<float> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fArray")
+    f.low_level_read_lo(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<double> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fArray")
+    f.low_level_read_lo(v);
+  else if (h.type == "dArray")
+    f.low_level_read_hi(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<int> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "iArray")
+    f.low_level_read(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<bin> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "bArray")
+    f.low_level_read(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<std::complex<float> > &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fcArray")
+    f.low_level_read_lo(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<std::complex<double> > &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "fcArray")
+    f.low_level_read_lo(v);
+  else if (h.type == "dcArray")
+    f.low_level_read_hi(v);
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<vec> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "vecArray") {
+    int n;
+    f.low_level_read(n);
+    v.set_size(n, false);
+    for (int i = 0; i < n; i++)
+      f.low_level_read_hi(v(i));
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<ivec> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "ivecArray") {
+    int n;
+    f.low_level_read(n);
+    v.set_size(n, false);
+    for (int i = 0; i < n; i++)
+      f.low_level_read(v(i));
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<bvec> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "bvecArray") {
+    int n;
+    f.low_level_read(n);
+    v.set_size(n, false);
+    for (int i = 0; i < n; i++)
+      f.low_level_read(v(i));
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<cvec> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "cvecArray") {
+    int n;
+    f.low_level_read(n);
+    v.set_size(n, false);
+    for (int i = 0; i < n; i++)
+      f.low_level_read_hi(v(i));
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<std::string> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "stringArray") {
+    int n;
+    f.low_level_read(n);
+    v.set_size(n, false);
+    for (int i = 0; i < n; i++)
+      f.low_level_read(v(i));
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<mat> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "matArray") {
+    int n;
+    f.low_level_read(n);
+    v.set_size(n, false);
+    for (int i = 0; i < n; i++)
+      f.low_level_read_hi(v(i));
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<imat> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "imatArray") {
+    int n;
+    f.low_level_read(n);
+    v.set_size(n, false);
+    for (int i = 0; i < n; i++)
+      f.low_level_read(v(i));
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<bmat> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "bmatArray") {
+    int n;
+    f.low_level_read(n);
+    v.set_size(n, false);
+    for (int i = 0; i < n; i++)
+      f.low_level_read(v(i));
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_ifile_old &operator>>(it_ifile_old &f, Array<cmat> &v)
+{
+  it_file_old::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "cmatArray") {
+    int n;
+    f.low_level_read(n);
+    v.set_size(n, false);
+    for (int i = 0; i < n; i++)
+      f.low_level_read_hi(v(i));
+  }
+  else
+    it_error("Wrong type");
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, char x)
+{
+  f.write_data_header("int8", sizeof(char));
+  f.low_level_write(x);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, bin x)
+{
+  f.write_data_header("bin", sizeof(bin));
+  f.low_level_write(x);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, short x)
+{
+  f.write_data_header("int16", sizeof(short));
+  f.low_level_write(x);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, int x)
+{
+  f.write_data_header("int32", sizeof(int));
+  f.low_level_write(x);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, float x)
+{
+  f.write_data_header("float32", sizeof(float));
+  f.low_level_write(x);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, double x)
+{
+  f.write_data_header("float64", sizeof(double));
+  f.low_level_write(x);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, std::complex<float> x)
+{
+  f.write_data_header("float32_complex", 2*sizeof(float));
+  f.low_level_write(x);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, std::complex<double> x)
+{
+  f.write_data_header("float64_complex", 2*sizeof(double));
+  f.low_level_write(x);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const vec &v)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fvec", sizeof(int) + v.size() * sizeof(float));
+  else
+    f.write_data_header("dvec", sizeof(int) + v.size() * sizeof(double));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const ivec &v)
+{
+  f.write_data_header("ivec", (1 + v.size()) * sizeof(int));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const bvec &v)
+{
+  f.write_data_header("bvec", sizeof(int) + v.size() * sizeof(bin));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const cvec &v)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fcvec", sizeof(int) + v.size() * 2 * sizeof(float));
+  else
+    f.write_data_header("dcvec", sizeof(int) + v.size() * 2 * sizeof(double));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const std::string &str)
+{
+  f.write_data_header("string", sizeof(int) + str.size() * sizeof(char));
+  f.low_level_write(str);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const mat &m)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fmat", 2*sizeof(int) + m.rows()*m.cols()*sizeof(float));
+  else
+    f.write_data_header("dmat", 2*sizeof(int) + m.rows()*m.cols()*sizeof(double));
+  f.low_level_write(m);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const imat &m)
+{
+  f.write_data_header("imat", (2 + m.rows()*m.cols()) * sizeof(int));
+  f.low_level_write(m);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const bmat &m)
+{
+  f.write_data_header("bmat", 2*sizeof(int) + m.rows()*m.cols()*sizeof(bin));
+  f.low_level_write(m);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const cmat &m)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fcmat", 2*sizeof(int) + 2*m.rows()*m.cols()*sizeof(float));
+  else
+    f.write_data_header("dcmat", 2*sizeof(int) + 2*m.rows()*m.cols()*sizeof(double));
+  f.low_level_write(m);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<float> &v)
+{
+  f.write_data_header("fArray", sizeof(int) + v.size() * sizeof(float));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<double> &v)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fArray", sizeof(int) + v.size() * sizeof(float));
+  else
+    f.write_data_header("dArray", sizeof(int) + v.size() * sizeof(double));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<int> &v)
+{
+  f.write_data_header("iArray", (1 + v.size()) * sizeof(int));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<bin> &v)
+{
+  f.write_data_header("bArray", sizeof(int) + v.size() * sizeof(bin));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<std::complex<float> > &v)
+{
+  f.write_data_header("fcArray", sizeof(int) + v.size() * 2 * sizeof(float));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<std::complex<double> > &v)
+{
+  if (f.get_low_precision())
+    f.write_data_header("fcArray", sizeof(int) + v.size() * 2 * sizeof(float));
+  else
+    f.write_data_header("dcArray", sizeof(int) + v.size() * 2 * sizeof(double));
+  f.low_level_write(v);
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<vec> &v)
+{
+  int i, sum_l = 0;
+
+  // calculate total length of Array
+  for (i = 0; i < v.size(); i++) {
+    sum_l += v(i).size();
+  }
+
+  // write header
+  f.write_data_header("vecArray", sizeof(int)*(1 + v.size()) + sum_l * sizeof(double));
+
+  f.low_level_write(v.size());  // the length of the array
+
+  // write one vector at a time (i.e. size and elements)
+  for (i = 0; i < v.size(); i++)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<ivec> &v)
+{
+  int i, sum_l = 0;
+
+  // calculate total length of Array
+  for (i = 0; i < v.size(); i++) {
+    sum_l += v(i).size();
+  }
+
+  // write header
+  f.write_data_header("ivecArray", sizeof(int)*(1 + v.size()) + sum_l * sizeof(int));
+
+  f.low_level_write(v.size());  // the length of the array
+
+  // write one vector at a time (i.e. size and elements)
+  for (i = 0; i < v.size(); i++)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<bvec> &v)
+{
+  int i, sum_l = 0;
+
+  // calculate total length of Array
+  for (i = 0; i < v.size(); i++) {
+    sum_l += v(i).size();
+  }
+
+  // write header
+  f.write_data_header("bvecArray", sizeof(int)*(1 + v.size()) + sum_l * sizeof(bin));
+
+  f.low_level_write(v.size());  // the length of the array
+
+  // write one vector at a time (i.e. size and elements)
+  for (i = 0; i < v.size(); i++)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<cvec> &v)
+{
+  int i, sum_l = 0;
+
+  // calculate total length of Array
+  for (i = 0; i < v.size(); i++) {
+    sum_l += v(i).size();
+  }
+
+  // write header
+  f.write_data_header("cvecArray", sizeof(int)*(1 + v.size()) + sum_l * sizeof(std::complex<double>));
+
+  f.low_level_write(v.size());  // the length of the array
+
+  // write one vector at a time (i.e. size and elements)
+  for (i = 0; i < v.size(); i++)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<std::string> &v)
+{
+  int i, sum_l = 0;
+
+  // calculate total length of Array
+  for (i = 0; i < v.size(); i++) {
+    sum_l += v(i).size();
+  }
+
+  // write header
+  f.write_data_header("stringArray", sizeof(int)*(1 + v.size()) + sum_l * sizeof(char));
+
+  f.low_level_write(v.size());  // the length of the array
+
+  // write one vector at a time (i.e. size and elements)
+  for (i = 0; i < v.size(); i++)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<mat> &v)
+{
+  int i, sum_l = 0;
+
+  // calculate total length of Array
+  for (i = 0; i < v.size(); i++) {
+    sum_l += v(i)._datasize();
+  }
+
+  // write header
+  f.write_data_header("matArray", sizeof(int)*(1 + 2*v.size()) + sum_l * sizeof(double));
+
+  f.low_level_write(v.size());  // the length of the array
+
+  // write one matrix at a time (i.e. size and elements)
+  for (i = 0; i < v.size(); i++)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<imat> &v)
+{
+  int i, sum_l = 0;
+
+  // calculate total length of Array
+  for (i = 0; i < v.size(); i++) {
+    sum_l += v(i)._datasize();
+  }
+
+  // write header
+  f.write_data_header("imatArray", sizeof(int)*(1 + 2*v.size()) + sum_l * sizeof(int));
+
+  f.low_level_write(v.size());  // the length of the array
+
+  // write one matrix at a time (i.e. size and elements)
+  for (i = 0; i < v.size(); i++)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<bmat> &v)
+{
+  int i, sum_l = 0;
+
+  // calculate total length of Array
+  for (i = 0; i < v.size(); i++) {
+    sum_l += v(i)._datasize();
+  }
+
+  // write header
+  f.write_data_header("bmatArray", sizeof(int)*(1 + 2*v.size()) + sum_l * sizeof(bin));
+
+  f.low_level_write(v.size());  // the length of the array
+
+  // write one matrix at a time (i.e. size and elements)
+  for (i = 0; i < v.size(); i++)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+it_file_old &operator<<(it_file_old &f, const Array<cmat> &v)
+{
+  int i, sum_l = 0;
+
+  // calculate total length of Array
+  for (i = 0; i < v.size(); i++) {
+    sum_l += v(i)._datasize();
+  }
+
+  // write header
+  f.write_data_header("cmatArray", sizeof(int)*(1 + 2*v.size()) + sum_l * sizeof(std::complex<double>));
+
+  f.low_level_write(v.size());  // the length of the array
+
+  // write one matrix at a time (i.e. size and elements)
+  for (i = 0; i < v.size(); i++)
+    f.low_level_write(v(i));
+
+  return f;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/binfile.h
===================================================================
--- library/bdm/base/itpp/base/binfile.h (revision 812)
+++ library/bdm/base/itpp/base/binfile.h (revision 812)
@@ -0,0 +1,342 @@
+/*!
+ * \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-2010  (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 file named \c name 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 address (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: library/bdm/base/itpp/base/vec.cpp
===================================================================
--- library/bdm/base/itpp/base/vec.cpp (revision 812)
+++ library/bdm/base/itpp/base/vec.cpp (revision 812)
@@ -0,0 +1,1065 @@
+/*!
+ * \file
+ * \brief Templated Vector Class Implementation
+ * \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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/vec.h>
+#include <itpp/base/converters.h>
+#include <cstdio>
+#include <limits>
+
+//! \cond
+
+namespace itpp
+{
+
+
+template<class Num_T>
+std::string Vec<Num_T>::replace_commas(const std::string &str_in)
+{
+  // copy an input sting into a local variable str
+  std::string str(str_in);
+  // find first occurence of comma in string str
+  std::string::size_type index = str.find(',', 0);
+  while (index != std::string::npos) {
+    // replace character at position index with space
+    str.replace(index, 1, 1, ' ');
+    // find next occurence of comma in string str
+    index = str.find(',', index);
+  }
+  return str;
+}
+
+
+template<>
+void Vec<double>::set(const std::string &str)
+{
+  std::istringstream buffer(replace_commas(str));
+  double b = 0.0;
+  double c = 0.0;
+  double eps_margin;
+  bool b_parsed = false;
+  bool c_parsed = false;
+  bool negative = false;
+  bool nan_inf = false;
+  int pos = 0, maxpos = 10;
+
+  free();
+  alloc(maxpos);
+
+  while (buffer.peek() != EOF) {
+    switch (buffer.peek()) {
+      // skip spaces
+    case ' ':
+    case '\t':
+      buffer.seekg(1, std::ios_base::cur);
+      break;
+
+      // skip '+' sign
+    case '+':
+      // check for not handled '-' sign
+      it_assert(!negative, "Vec<double>::set(): Improper data string (-)");
+      buffer.seekg(1, std::ios_base::cur);
+      break;
+
+      // check for '-' sign
+    case '-':
+      buffer.seekg(1, std::ios_base::cur);
+      negative = true;
+      break;
+
+      // check for NaN
+    case 'N':
+    case 'n':
+      buffer.seekg(1, std::ios_base::cur);
+      it_assert((buffer.peek() == 'A') || (buffer.peek() == 'a'),
+                "Vec<double>::set(): Improper data string (NaN)");
+      buffer.seekg(1, std::ios_base::cur);
+      it_assert((buffer.peek() == 'N') || (buffer.peek() == 'n'),
+                "Vec<double>::set(): Improper data string (NaN)");
+      buffer.seekg(1, std::ios_base::cur);
+      it_assert(!negative, "Vec<double>::set(): Improper data string "
+                "(-NaN not exist)");
+      if (++pos > maxpos) {
+        maxpos <<= 1;
+        set_size(maxpos, true);
+      }
+      if (std::numeric_limits<double>::has_quiet_NaN) {
+        data[pos-1] = std::numeric_limits<double>::quiet_NaN();
+      }
+      else if (std::numeric_limits<double>::has_signaling_NaN) {
+        data[pos-1] = std::numeric_limits<double>::signaling_NaN();
+      }
+      else {
+        it_error("Vec<double::set(): NaN not supported");
+      }
+      nan_inf = true;
+      break; // case 'N'...
+
+      // check for Inf
+    case 'I':
+    case 'i':
+      buffer.seekg(1, std::ios_base::cur);
+      it_assert((buffer.peek() == 'N') || (buffer.peek() == 'n'),
+                "Vec<double>::set(): Improper data string (Inf)");
+      buffer.seekg(1, std::ios_base::cur);
+      it_assert((buffer.peek() == 'F') || (buffer.peek() == 'f'),
+                "Vec<double>::set(): Improper data string (Inf)");
+      buffer.seekg(1, std::ios_base::cur);
+      it_assert(std::numeric_limits<double>::has_infinity,
+                "Vec<double::set(): Inf not supported");
+      if (++pos > maxpos) {
+        maxpos <<= 1;
+        set_size(maxpos, true);
+      }
+      if (negative) {
+        data[pos-1] = -std::numeric_limits<double>::infinity();
+        negative = false;
+      }
+      else {
+        data[pos-1] = std::numeric_limits<double>::infinity();
+      }
+      nan_inf = true;
+      break; // case 'I'...
+
+    case ':': // reads format a:b:c or a:b
+      it_assert(!negative, "Vec<double>::set(): Improper data string (-)");
+      it_assert(!nan_inf, "Vec<double>::set(): Improper data string (Nan/Inf "
+                " can not be used with a:b or a:b:c)");
+      it_assert(pos == 1, "Vec<double>::set(): Improper data string (a:b)");
+      buffer.seekg(1, std::ios_base::cur);
+      // parse b
+      while (buffer.peek() != EOF) {
+        switch (buffer.peek()) {
+        case ' ':
+        case '\t':
+          buffer.seekg(1, std::ios_base::cur);
+          break;
+
+        case ':':
+          it_assert(b_parsed, "Vec<double>::set(): Improper data string "
+                    "(a:b)");
+          buffer.seekg(1, std::ios_base::cur);
+          // parse c
+          while (buffer.peek() != EOF) {
+            switch (buffer.peek()) {
+            case ' ':
+            case '\t':
+              buffer.seekg(1, std::ios_base::cur);
+              break;
+
+            default:
+              it_assert(!c_parsed, "Vec<double>::set(): Improper data "
+                        "string (a:b:c)");
+              buffer.clear();
+              buffer >> c;
+              it_assert(!buffer.fail(), "Vec<double>::set(): Stream "
+                        "operation failed (buffer >> c)");
+              c_parsed = true;
+            }
+          }
+          it_assert(c_parsed, "Vec<double>::set(): Improper data string "
+                    "(a:b:c)");
+          break;
+
+        default:
+          it_assert(!b_parsed, "Vec<double>::set(): Improper data string "
+                    "(a:b)");
+          buffer.clear();
+          buffer >> b;
+          it_assert(!buffer.fail(), "Vec<double>::set(): Stream operation "
+                    "failed (buffer >> b)");
+          b_parsed = true;
+        }
+      }
+      it_assert(b_parsed, "Vec<double>::set(): Improper data string (a:b)");
+
+      if (c_parsed) {
+        // Adding this margin fixes precision problems in e.g. "0:0.2:3",
+        // where the last value was 2.8 instead of 3.
+        eps_margin = std::fabs((c - data[pos-1]) / b) * eps;
+        if (b > 0 && c >= data[pos-1]) {
+          while (data[pos-1] + b <= c + eps_margin) {
+            if (++pos > maxpos) {
+              maxpos <<= 1;
+              set_size(maxpos, true);
+            }
+            data[pos-1] = data[pos-2] + b;
+          }
+        }
+        else if (b < 0 && c <= data[pos-1]) {
+          while (data[pos-1] + b >= c - eps_margin) {
+            if (++pos > maxpos) {
+              maxpos <<= 1;
+              set_size(maxpos, true);
+            }
+            data[pos-1] = data[pos-2] + b;
+          }
+        }
+        else if (b == 0 && c == data[pos-1]) {
+          break;
+        }
+        else {
+          it_error("Vec<double>::set(): Improper data string (a:b:c)");
+        }
+      } // if (c_parsed)
+      else if (b_parsed) {
+        eps_margin = std::fabs(b - data[pos-1]) * eps;
+        if (b < data[pos-1]) {
+          while (data[pos-1] - 1.0 >= b - eps_margin) {
+            if (++pos > maxpos) {
+              maxpos <<= 1;
+              set_size(maxpos, true);
+            }
+            data[pos-1] = data[pos-2] - 1.0;
+          }
+        }
+        else {
+          while (data[pos-1] + 1.0 <= b + eps_margin) {
+            if (++pos > maxpos) {
+              maxpos <<= 1;
+              set_size(maxpos, true);
+            }
+            data[pos-1] = data[pos-2] + 1.0;
+          }
+        }
+      } // else if (b_parsed)
+      else {
+        it_error("Vec<double>::set(): Improper data string (a:b)");
+      }
+      break; // case ':'
+
+    default:
+      if (++pos > maxpos) {
+        maxpos <<= 1;
+        set_size(maxpos, true);
+      }
+      buffer >> data[pos-1];
+      it_assert(!buffer.fail(), "Vec<double>::set(): Stream operation "
+                "failed (buffer >> data)");
+      if (negative) {
+        data[pos-1] = -data[pos-1];
+        negative = false;
+      }
+      break; // default
+    }
+  }
+  set_size(pos, true);
+}
+
+
+template<>
+void Vec<std::complex<double> >::set(const std::string &str)
+{
+  std::istringstream buffer(str);
+  int pos = 0, maxpos = 10;
+
+  free();
+  alloc(maxpos);
+
+  while (buffer.peek() != EOF) {
+    switch (buffer.peek()) {
+    case ':':
+      it_error("Vec<complex>::set(): a:b:c and a:b expressions not valid "
+               "for cvec");
+      break;
+    case ' ':
+    case '\t':
+    case ',':
+      buffer.seekg(1, std::ios_base::cur);
+      break;
+    default:
+      if (++pos > maxpos) {
+        maxpos <<= 1;
+        set_size(maxpos, true);
+      }
+      buffer >> data[pos-1];
+      it_assert(!buffer.fail(), "Vec<complex>::set(): Stream operation "
+                "failed (buffer >> data)");
+    }
+  }
+  set_size(pos, true);
+}
+
+
+template<>
+void Vec<bin>::set(const std::string &str)
+{
+  std::istringstream buffer(replace_commas(str));
+  int pos = 0, maxpos = 10;
+
+  free();
+  alloc(maxpos);
+
+  while (buffer.peek() != EOF) {
+    switch (buffer.peek()) {
+    case ':':
+      it_error("Vec<bin>::set(): a:b:c and a:b expressions not valid "
+               "for bvec");
+      break;
+    case ' ':
+    case '\t':
+      buffer.seekg(1, std::ios_base::cur);
+      break;
+    default:
+      if (++pos > maxpos) {
+        maxpos <<= 1;
+        set_size(maxpos, true);
+      }
+      buffer >> data[pos-1];
+      it_assert(!buffer.fail(), "Vec<bin>::set(): Stream operation failed "
+                "(buffer >> data)");
+    }
+  }
+  set_size(pos, true);
+}
+
+
+template<>
+void Vec<int>::set(const std::string &str)
+{
+  std::istringstream buffer(replace_commas(str));
+  int b = 0;
+  int c = 0;
+  bool b_parsed = false;
+  bool c_parsed = false;
+  bool negative = false;
+  int pos = 0;
+  int maxpos = 10;
+
+  free();
+  alloc(maxpos);
+
+  while (buffer.peek() != EOF) {
+    switch (buffer.peek()) {
+      // skip spaces and tabs
+    case ' ':
+    case '\t':
+      buffer.seekg(1, std::ios_base::cur);
+      break;
+
+      // skip '+' sign
+    case '+':
+      // check for not handled '-' sign
+      it_assert(!negative, "Vec<double>::set(): Improper data string (-)");
+      buffer.seekg(1, std::ios_base::cur);
+      break;
+
+      // check for '-' sign
+    case '-':
+      buffer.seekg(1, std::ios_base::cur);
+      negative = true;
+      break;
+
+      // hexadecimal number or octal number or zero
+    case '0':
+      buffer.seekg(1, std::ios_base::cur);
+      switch (buffer.peek()) {
+        // hexadecimal number
+      case 'x':
+      case 'X':
+        buffer.clear();
+        buffer.seekg(-1, std::ios_base::cur);
+        if (++pos > maxpos) {
+          maxpos <<= 1;
+          set_size(maxpos, true);
+        }
+        buffer >> std::hex >> data[pos-1];
+        it_assert(!buffer.fail(), "Vec<int>::set(): Stream operation "
+                  "failed (buffer >> hex >> data)");
+        break; // case 'x'...
+
+        // octal number
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+        buffer.clear();
+        buffer.seekg(-1, std::ios_base::cur);
+        if (++pos > maxpos) {
+          maxpos <<= 1;
+          set_size(maxpos, true);
+        }
+        buffer >> std::oct >> data[pos-1];
+        it_assert(!buffer.fail(), "Vec<int>::set(): Stream operation "
+                  "failed (buffer >> oct >> data)");
+        break; // case '1'...
+
+        // zero
+      case EOF:
+      case ' ':
+      case '\t':
+      case ':':
+      case '0':
+        buffer.clear();
+        buffer.seekg(-1, std::ios_base::cur);
+        if (++pos > maxpos) {
+          maxpos <<= 1;
+          set_size(maxpos, true);
+        }
+        buffer >> std::dec >> data[pos-1];
+        it_assert(!buffer.fail(), "Vec<int>::set(): Stream operation "
+                  "failed (buffer >> dec >> data)");
+        break; // case EOF...
+
+      default:
+        it_error("Vec<int>::set(): Improper data string");
+      }
+      // check if just parsed data was negative
+      if (negative) {
+        data[pos-1] = -data[pos-1];
+        negative = false;
+      }
+      break; // case '0'
+
+      // decimal number
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      buffer.clear();
+      if (++pos > maxpos) {
+        maxpos <<= 1;
+        set_size(maxpos, true);
+      }
+      buffer >> std::dec >> data[pos-1];
+      it_assert(!buffer.fail(), "Vec<int>::set(): Stream operation "
+                "failed (buffer >> dec >> data)");
+      // check if just parsed data was negative
+      if (negative) {
+        data[pos-1] = -data[pos-1];
+        negative = false;
+      }
+      break; // case '1'...
+
+      // parse format a:b:c or a:b
+    case ':':
+      it_assert(pos == 1, "Vec<int>::set(): Improper data string (a:b)");
+      buffer.seekg(1, std::ios_base::cur);
+      // parse b
+      while (buffer.peek() != EOF) {
+        switch (buffer.peek()) {
+        case ' ':
+        case '\t':
+          buffer.seekg(1, std::ios_base::cur);
+          break;
+
+          // skip '+' sign
+        case '+':
+          // check for not handled '-' sign
+          it_assert(!negative, "Vec<double>::set(): Improper data string "
+                    "(-)");
+          buffer.seekg(1, std::ios_base::cur);
+          break;
+
+          // check for '-' sign
+        case '-':
+          buffer.seekg(1, std::ios_base::cur);
+          negative = true;
+          break;
+
+          // hexadecimal number or octal number or zero
+        case '0':
+          it_assert(!b_parsed, "Vec<int>::set(): Improper data string "
+                    "(a:b)");
+          buffer.seekg(1, std::ios_base::cur);
+          switch (buffer.peek()) {
+            // hexadecimal number
+          case 'x':
+          case 'X':
+            buffer.clear();
+            buffer.seekg(-1, std::ios_base::cur);
+            buffer >> std::hex >> b;
+            it_assert(!buffer.fail(), "Vec<int>::set(): Stream operation "
+                      "failed (buffer >> hex >> data)");
+            break; // case 'x'...
+
+            // octal number
+          case '1':
+          case '2':
+          case '3':
+          case '4':
+          case '5':
+          case '6':
+          case '7':
+            buffer.clear();
+            buffer.seekg(-1, std::ios_base::cur);
+            buffer >> std::oct >> b;
+            it_assert(!buffer.fail(), "Vec<int>::set(): Stream operation "
+                      "failed (buffer >> oct >> data)");
+            break; // case '1'...
+
+            // zero
+          case EOF:
+          case ' ':
+          case '\t':
+          case ':':
+          case '0':
+            buffer.clear();
+            buffer.seekg(-1, std::ios_base::cur);
+            buffer >> std::dec >> b;
+            it_assert(!buffer.fail(), "Vec<int>::set(): Stream operation "
+                      "failed (buffer >> dec >> data)");
+            break; // case EOF...
+
+          default:
+            it_error("Vec<int>::set(): Improper data string (a:b)");
+          } // switch (buffer.peek())
+          // check if just parsed data was negative
+          if (negative) {
+            b = -b;
+            negative = false;
+          }
+          b_parsed = true;
+          break; // case '0'
+
+          // decimal number
+        case '1':
+        case '2':
+        case '3':
+        case '4':
+        case '5':
+        case '6':
+        case '7':
+        case '8':
+        case '9':
+          it_assert(!b_parsed, "Vec<int>::set(): Improper data string "
+                    "(a:b)");
+          buffer.clear();
+          buffer >> std::dec >> b;
+          it_assert(!buffer.fail(), "Vec<int>::set(): Stream operation "
+                    "failed (buffer >> dec >> data)");
+          // check if just parsed data was negative
+          if (negative) {
+            b = -b;
+            negative = false;
+          }
+          b_parsed = true;
+          break; // case '1'...
+
+        case ':':
+          it_assert(b_parsed, "Vec<int>::set(): Improper data string (a:b)");
+          buffer.seekg(1, std::ios_base::cur);
+          // parse c
+          while (buffer.peek() != EOF) {
+            switch (buffer.peek()) {
+            case ' ':
+            case '\t':
+              buffer.seekg(1, std::ios_base::cur);
+              break;
+
+              // skip '+' sign
+            case '+':
+              // check for not handled '-' sign
+              it_assert(!negative, "Vec<double>::set(): Improper data "
+                        "string (-)");
+              buffer.seekg(1, std::ios_base::cur);
+              break;
+
+              // check for '-' sign
+            case '-':
+              buffer.seekg(1, std::ios_base::cur);
+              negative = true;
+              break;
+
+              // hexadecimal number or octal number or zero
+            case '0':
+              it_assert(!c_parsed, "Vec<int>::set(): Improper data string "
+                        "(a:b:c)");
+              buffer.seekg(1, std::ios_base::cur);
+              switch (buffer.peek()) {
+                // hexadecimal number
+              case 'x':
+              case 'X':
+                buffer.clear();
+                buffer.seekg(-1, std::ios_base::cur);
+                buffer >> std::hex >> c;
+                it_assert(!buffer.fail(), "Vec<int>::set(): Stream "
+                          "operation failed (buffer >> hex >> data)");
+                break; // case 'x'...
+
+                // octal number
+              case '1':
+              case '2':
+              case '3':
+              case '4':
+              case '5':
+              case '6':
+              case '7':
+                buffer.clear();
+                buffer.seekg(-1, std::ios_base::cur);
+                buffer >> std::oct >> c;
+                it_assert(!buffer.fail(), "Vec<int>::set(): Stream "
+                          "operation failed (buffer >> oct >> data)");
+                break; // case '1'...
+
+                // zero
+              case EOF:
+              case ' ':
+              case '\t':
+              case '0':
+                buffer.clear();
+                buffer.seekg(-1, std::ios_base::cur);
+                buffer >> std::dec >> c;
+                it_assert(!buffer.fail(), "Vec<int>::set(): Stream "
+                          "operation failed (buffer >> dec >> data)");
+                break; // case EOF...
+
+              default:
+                it_error("Vec<int>::set(): Improper data string (a:b:c)");
+              }
+              c_parsed = true;
+              break; // case '0'
+
+              // decimal number
+            case '1':
+            case '2':
+            case '3':
+            case '4':
+            case '5':
+            case '6':
+            case '7':
+            case '8':
+            case '9':
+              it_assert(!c_parsed, "Vec<int>::set(): Improper data string "
+                        "(a:b:c)");
+              buffer.clear();
+              buffer >> std::dec >> c;
+              it_assert(!buffer.fail(), "Vec<int>::set(): Stream operation "
+                        "failed (buffer >> dec >> data)");
+              c_parsed = true;
+              break;
+
+            default:
+              it_error("Vec<int>::set(): Improper data string (a:b:c)");
+            } // switch (buffer.peek())
+          } // while (buffer.peek() != EOF)
+          // check if just parsed data was negative
+          if (negative) {
+            c = -c;
+            negative = false;
+          }
+          it_assert(c_parsed, "Vec<int>::set(): Improper data string "
+                    "(a:b:c)");
+          break; // case ':'
+
+        default:
+          it_error("Vec<int>::set(): Improper data string (a:b)");
+        } // switch (buffer.peek())
+      } // while (buffer.peek() != EOF)
+
+      if (c_parsed) {
+        if (b > 0 && c >= data[pos-1]) {
+          while (data[pos-1] + b <= c) {
+            if (++pos > maxpos) {
+              maxpos <<= 1;
+              set_size(maxpos, true);
+            }
+            data[pos-1] = data[pos-2] + b;
+          }
+        }
+        else if (b < 0 && c <= data[pos-1]) {
+          while (data[pos-1] + b >= c) {
+            if (++pos > maxpos) {
+              maxpos <<= 1;
+              set_size(maxpos, true);
+            }
+            data[pos-1] = data[pos-2] + b;
+          }
+        }
+        else if (b == 0 && c == data[pos-1]) {
+          break;
+        }
+        else {
+          it_error("Vec<int>::set(): Improper data string (a:b:c)");
+        }
+      } // if (c_parsed)
+      else if (b_parsed) {
+        if (b < data[pos-1]) {
+          while (data[pos-1] > b) {
+            if (++pos > maxpos) {
+              maxpos <<= 1;
+              set_size(maxpos, true);
+            }
+            data[pos-1] = data[pos-2] - 1;
+          }
+        }
+        else {
+          while (data[pos-1] < b) {
+            if (++pos > maxpos) {
+              maxpos <<= 1;
+              set_size(maxpos, true);
+            }
+            data[pos-1] = data[pos-2] + 1;
+          }
+        }
+      } // else if (b_parsed)
+      else {
+        it_error("Vec<int>::set(): Improper data string (a:b)");
+      }
+      break; // case ':'
+
+    default:
+      it_error("Vec<int>::set(): Improper data string");
+    }
+  }
+  // resize the parsed vector to its final length
+  set_size(pos, true);
+}
+
+template<>
+void Vec<short int>::set(const std::string &str)
+{
+  // parser for "short int" is the same as for "int", so reuse it here
+  ivec iv(str);
+  this->operator=(to_svec(iv));
+}
+
+
+template<>
+bvec Vec<std::complex<double> >::operator<=(std::complex<double>) const
+{
+  it_error("operator<=: not implemented for complex");
+  bvec temp;
+  return temp;
+}
+
+template<>
+bvec Vec<std::complex<double> >::operator>(std::complex<double>) const
+{
+  it_error("operator>: not implemented for complex");
+  bvec temp;
+  return temp;
+}
+
+template<>
+bvec Vec<std::complex<double> >::operator<(std::complex<double>) const
+{
+  it_error("operator<: not implemented for complex");
+  bvec temp;
+  return temp;
+}
+
+template<>
+bvec Vec<std::complex<double> >::operator>=(std::complex<double>) const
+{
+  it_error("operator>=: not implemented for complex");
+  bvec temp;
+  return temp;
+}
+
+template<>
+Mat<std::complex<double> > Vec<std::complex<double> >::hermitian_transpose() const
+{
+  Mat<std::complex<double> > temp(1, datasize);
+  for (int i = 0; i < datasize; i++)
+    temp(i) = std::conj(data[i]);
+
+  return temp;
+}
+
+
+//---------------------------------------------------------------------
+// Instantiations
+//---------------------------------------------------------------------
+
+template class Vec<double>;
+template class Vec<int>;
+template class Vec<short int>;
+template class Vec<std::complex<double> >;
+template class Vec<bin>;
+
+// addition operator
+
+template vec operator+(const vec &v1, const vec &v2);
+template cvec operator+(const cvec &v1, const cvec &v2);
+template ivec operator+(const ivec &v1, const ivec &v2);
+template svec operator+(const svec &v1, const svec &v2);
+template bvec operator+(const bvec &v1, const bvec &v2);
+
+template vec operator+(const vec &v1, double t);
+template cvec operator+(const cvec &v1, std::complex<double> t);
+template ivec operator+(const ivec &v1, int t);
+template svec operator+(const svec &v1, short t);
+template bvec operator+(const bvec &v1, bin t);
+
+template vec operator+(double t, const vec &v1);
+template cvec operator+(std::complex<double> t, const cvec &v1);
+template ivec operator+(int t, const ivec &v1);
+template svec operator+(short t, const svec &v1);
+template bvec operator+(bin t, const bvec &v1);
+
+// subraction operator
+
+template vec operator-(const vec &v1, const vec &v2);
+template cvec operator-(const cvec &v1, const cvec &v2);
+template ivec operator-(const ivec &v1, const ivec &v2);
+template svec operator-(const svec &v1, const svec &v2);
+template bvec operator-(const bvec &v1, const bvec &v2);
+
+template vec operator-(const vec &v, double t);
+template cvec operator-(const cvec &v, std::complex<double> t);
+template ivec operator-(const ivec &v, int t);
+template svec operator-(const svec &v, short t);
+template bvec operator-(const bvec &v, bin t);
+
+template vec operator-(double t, const vec &v);
+template cvec operator-(std::complex<double> t, const cvec &v);
+template ivec operator-(int t, const ivec &v);
+template svec operator-(short t, const svec &v);
+template bvec operator-(bin t, const bvec &v);
+
+// unary minus
+
+template vec operator-(const vec &v);
+template cvec operator-(const cvec &v);
+template ivec operator-(const ivec &v);
+template svec operator-(const svec &v);
+template bvec operator-(const bvec &v);
+
+// multiplication operator
+
+#if !defined(HAVE_BLAS)
+template double dot(const vec &v1, const vec &v2);
+#if !(defined(HAVE_ZDOTUSUB) || defined(HAVE_ZDOTU_VOID))
+template std::complex<double> dot(const cvec &v1, const cvec &v2);
+#endif // !(HAVE_ZDOTUSUB || HAVE_ZDOTU_VOID)
+#endif // HAVE_BLAS
+template int dot(const ivec &v1, const ivec &v2);
+template short dot(const svec &v1, const svec &v2);
+template bin dot(const bvec &v1, const bvec &v2);
+
+#if !defined(HAVE_BLAS)
+template double operator*(const vec &v1, const vec &v2);
+template std::complex<double> operator*(const cvec &v1, const cvec &v2);
+#endif
+template int operator*(const ivec &v1, const ivec &v2);
+template short operator*(const svec &v1, const svec &v2);
+template bin operator*(const bvec &v1, const bvec &v2);
+
+#if !defined(HAVE_BLAS)
+template mat outer_product(const vec &v1, const vec &v2, bool hermitian);
+#endif
+template imat outer_product(const ivec &v1, const ivec &v2, bool hermitian);
+template smat outer_product(const svec &v1, const svec &v2, bool hermitian);
+template bmat outer_product(const bvec &v1, const bvec &v2, bool hermitian);
+
+template vec operator*(const vec &v, double t);
+template cvec operator*(const cvec &v, std::complex<double> t);
+template ivec operator*(const ivec &v, int t);
+template svec operator*(const svec &v, short t);
+template bvec operator*(const bvec &v, bin t);
+
+template vec operator*(double t, const vec &v);
+template cvec operator*(std::complex<double> t, const cvec &v);
+template ivec operator*(int t, const ivec &v);
+template svec operator*(short t, const svec &v);
+template bvec operator*(bin t, const bvec &v);
+
+// elementwise multiplication
+
+template vec elem_mult(const vec &a, const vec &b);
+template cvec elem_mult(const cvec &a, const cvec &b);
+template ivec elem_mult(const ivec &a, const ivec &b);
+template svec elem_mult(const svec &a, const svec &b);
+template bvec elem_mult(const bvec &a, const bvec &b);
+
+template void elem_mult_out(const vec &a, const vec &b, vec &out);
+template void elem_mult_out(const cvec &a, const cvec &b, cvec &out);
+template void elem_mult_out(const ivec &a, const ivec &b, ivec &out);
+template void elem_mult_out(const svec &a, const svec &b, svec &out);
+template void elem_mult_out(const bvec &a, const bvec &b, bvec &out);
+
+template vec elem_mult(const vec &a, const vec &b, const vec &c);
+template cvec elem_mult(const cvec &a, const cvec &b, const cvec &c);
+template ivec elem_mult(const ivec &a, const ivec &b, const ivec &c);
+template svec elem_mult(const svec &a, const svec &b, const svec &c);
+template bvec elem_mult(const bvec &a, const bvec &b, const bvec &c);
+
+template void elem_mult_out(const vec &a, const vec &b, const vec &c,
+                            vec &out);
+template void elem_mult_out(const cvec &a, const cvec &b, const cvec &c,
+                            cvec &out);
+template void elem_mult_out(const ivec &a, const ivec &b, const ivec &c,
+                            ivec &out);
+template void elem_mult_out(const svec &a, const svec &b, const svec &c,
+                            svec &out);
+template void elem_mult_out(const bvec &a, const bvec &b, const bvec &c,
+                            bvec &out);
+
+template vec elem_mult(const vec &a, const vec &b, const vec &c,
+                       const vec &d);
+template cvec elem_mult(const cvec &a, const cvec &b, const cvec &c,
+                        const cvec &d);
+template ivec elem_mult(const ivec &a, const ivec &b, const ivec &c,
+                        const ivec &d);
+template svec elem_mult(const svec &a, const svec &b, const svec &c,
+                        const svec &d);
+template bvec elem_mult(const bvec &a, const bvec &b, const bvec &c,
+                        const bvec &d);
+
+template void elem_mult_out(const vec &a, const vec &b, const vec &c,
+                            const vec &d, vec &out);
+template void elem_mult_out(const cvec &a, const cvec &b, const cvec &c,
+                            const cvec &d, cvec &out);
+template void elem_mult_out(const ivec &a, const ivec &b, const ivec &c,
+                            const ivec &d, ivec &out);
+template void elem_mult_out(const svec &a, const svec &b, const svec &c,
+                            const svec &d, svec &out);
+template void elem_mult_out(const bvec &a, const bvec &b, const bvec &c,
+                            const bvec &d, bvec &out);
+
+// in-place elementwise multiplication
+
+template void elem_mult_inplace(const vec &a, vec &b);
+template void elem_mult_inplace(const cvec &a, cvec &b);
+template void elem_mult_inplace(const ivec &a, ivec &b);
+template void elem_mult_inplace(const svec &a, svec &b);
+template void elem_mult_inplace(const bvec &a, bvec &b);
+
+// elementwise multiplication followed by summation
+
+template double elem_mult_sum(const vec &a, const vec &b);
+template std::complex<double> elem_mult_sum(const cvec &a, const cvec &b);
+template int elem_mult_sum(const ivec &a, const ivec &b);
+template short elem_mult_sum(const svec &a, const svec &b);
+template bin elem_mult_sum(const bvec &a, const bvec &b);
+
+// division operator
+
+template vec operator/(const vec &v, double t);
+template cvec operator/(const cvec &v, std::complex<double> t);
+template ivec operator/(const ivec &v, int t);
+template svec operator/(const svec &v, short t);
+template bvec operator/(const bvec &v, bin t);
+
+template vec operator/(double t, const vec &v);
+template cvec operator/(std::complex<double> t, const cvec &v);
+template ivec operator/(int t, const ivec &v);
+template svec operator/(short t, const svec &v);
+template bvec operator/(bin t, const bvec &v);
+
+// elementwise division operator
+
+template vec elem_div(const vec &a, const vec &b);
+template cvec elem_div(const cvec &a, const cvec &b);
+template ivec elem_div(const ivec &a, const ivec &b);
+template svec elem_div(const svec &a, const svec &b);
+template bvec elem_div(const bvec &a, const bvec &b);
+
+template vec elem_div(double t, const vec &v);
+template cvec elem_div(std::complex<double> t, const cvec &v);
+template ivec elem_div(int t, const ivec &v);
+template svec elem_div(short t, const svec &v);
+template bvec elem_div(bin t, const bvec &v);
+
+template void elem_div_out(const vec &a, const vec &b, vec &out);
+template void elem_div_out(const cvec &a, const cvec &b, cvec &out);
+template void elem_div_out(const ivec &a, const ivec &b, ivec &out);
+template void elem_div_out(const svec &a, const svec &b, svec &out);
+template void elem_div_out(const bvec &a, const bvec &b, bvec &out);
+
+// elementwise division followed by summation
+
+template double elem_div_sum(const vec &a, const vec &b);
+template std::complex<double> elem_div_sum(const cvec &a, const cvec &b);
+template int elem_div_sum(const ivec &a, const ivec &b);
+template short elem_div_sum(const svec &a, const svec &b);
+template bin elem_div_sum(const bvec &a, const bvec &b);
+
+// concat operator
+
+template vec concat(const vec &v, double a);
+template cvec concat(const cvec &v, std::complex<double> a);
+template ivec concat(const ivec &v, int a);
+template svec concat(const svec &v, short a);
+template bvec concat(const bvec &v, bin a);
+
+template vec concat(double a, const vec &v);
+template cvec concat(std::complex<double> a, const cvec &v);
+template ivec concat(int a, const ivec &v);
+template svec concat(short a, const svec &v);
+template bvec concat(bin a, const bvec &v);
+
+template vec concat(const vec &v1, const vec &v2);
+template cvec concat(const cvec &v1, const cvec &v2);
+template ivec concat(const ivec &v1, const ivec &v2);
+template svec concat(const svec &v1, const svec &v2);
+template bvec concat(const bvec &v1, const bvec &v2);
+
+template vec concat(const vec &v1, const vec &v2, const vec &v3);
+template cvec concat(const cvec &v1, const cvec &v2, const cvec &v3);
+template ivec concat(const ivec &v1, const ivec &v2, const ivec &v3);
+template svec concat(const svec &v1, const svec &v2, const svec &v3);
+template bvec concat(const bvec &v1, const bvec &v2, const bvec &v3);
+
+template vec concat(const vec &v1, const vec &v2,
+                    const vec &v3, const vec &v4);
+template cvec concat(const cvec &v1, const cvec &v2,
+                     const cvec &v3, const cvec &v4);
+template ivec concat(const ivec &v1, const ivec &v2,
+                     const ivec &v3, const ivec &v4);
+template svec concat(const svec &v1, const svec &v2,
+                     const svec &v3, const svec &v4);
+template bvec concat(const bvec &v1, const bvec &v2,
+                     const bvec &v3, const bvec &v4);
+
+template vec concat(const vec &v1, const vec &v2, const vec &v3,
+                    const vec &v4, const vec &v5);
+template cvec concat(const cvec &v1, const cvec &v2, const cvec &v3,
+                     const cvec &v4, const cvec &v5);
+template ivec concat(const ivec &v1, const ivec &v2, const ivec &v3,
+                     const ivec &v4, const ivec &v5);
+template svec concat(const svec &v1, const svec &v2, const svec &v3,
+                     const svec &v4, const svec &v5);
+template bvec concat(const bvec &v1, const bvec &v2, const bvec &v3,
+                     const bvec &v4, const bvec &v5);
+
+// I/O streams
+
+template std::ostream &operator<<(std::ostream& os, const vec &vect);
+template std::ostream &operator<<(std::ostream& os, const cvec &vect);
+template std::ostream &operator<<(std::ostream& os, const svec &vect);
+template std::ostream &operator<<(std::ostream& os, const ivec &vect);
+template std::ostream &operator<<(std::ostream& os, const bvec &vect);
+template std::istream &operator>>(std::istream& is, vec &vect);
+template std::istream &operator>>(std::istream& is, cvec &vect);
+template std::istream &operator>>(std::istream& is, svec &vect);
+template std::istream &operator>>(std::istream& is, ivec &vect);
+template std::istream &operator>>(std::istream& is, bvec &vect);
+
+} // namespace itpp
+
+//! \endcond
Index: library/bdm/base/itpp/base/operators.cpp
===================================================================
--- library/bdm/base/itpp/base/operators.cpp (revision 812)
+++ library/bdm/base/itpp/base/operators.cpp (revision 812)
@@ -0,0 +1,484 @@
+/*!
+ * \file
+ * \brief Implementation 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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/operators.h>
+
+
+namespace itpp
+{
+
+//-----------  Scalar and a ivec -----------------
+
+vec operator+(const double &s, const ivec &v)
+{
+  it_assert_debug(v.size() > 0, "operator+(): Vector of zero length");
+
+  vec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s + double(v(i));
+  }
+  return temp;
+}
+
+vec operator-(const double &s, const ivec &v)
+{
+  it_assert_debug(v.size() > 0, "operator-(): Vector of zero length");
+
+  vec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s - double(v(i));
+  }
+  return temp;
+}
+
+vec operator*(const double &s, const ivec &v)
+{
+  it_assert_debug(v.size() > 0, "operator*(): Vector of zero length");
+
+  vec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s * double(v(i));
+  }
+  return temp;
+}
+
+vec operator/(const double &s, const ivec &v)
+{
+  it_assert_debug(v.size() > 0, "operator/(): Vector of zero length");
+
+  vec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s / double(v(i));
+  }
+  return temp;
+}
+
+vec operator/(const ivec &v, const double &s)
+{
+  it_assert_debug(v.size() > 0, "operator/(): Vector of zero length");
+
+  vec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = double(v(i)) / s;
+  }
+  return temp;
+}
+
+cvec operator+(const std::complex<double> &s, const ivec &v)
+{
+  it_assert_debug(v.size() > 0, "operator+(): Vector of zero length");
+
+  cvec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s + std::complex<double>(v(i));
+  }
+  return temp;
+}
+
+cvec operator-(const std::complex<double> &s, const ivec &v)
+{
+  it_assert_debug(v.size() > 0, "operator-(): Vector of zero length");
+
+  cvec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s - std::complex<double>(v(i));
+  }
+  return temp;
+}
+
+cvec operator*(const std::complex<double> &s, const ivec &v)
+{
+  it_assert_debug(v.size() > 0, "operator*(): Vector of zero length");
+
+  cvec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s * std::complex<double>(v(i));
+  }
+  return temp;
+}
+
+cvec operator/(const std::complex<double> &s, const ivec &v)
+{
+  it_assert_debug(v.size() > 0, "operator/(): Vector of zero length");
+
+  cvec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s / std::complex<double>(v(i));
+  }
+  return temp;
+}
+
+cvec operator/(const ivec &v, const std::complex<double> &s)
+{
+  it_assert_debug(v.size() > 0, "operator/(): Vector of zero length");
+
+  cvec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = std::complex<double>(v(i)) / s;
+  }
+  return temp;
+}
+
+//-----------  Scalar and a cvec -----------------
+
+cvec operator+(const double &s, const cvec &v)
+{
+  it_assert_debug(v.size() > 0, "operator+(): Vector of zero length");
+
+  cvec temp = v;
+  for (int i = 0;i < v.size();i++) {
+    temp(i) += s;
+  }
+  return temp;
+}
+
+cvec operator-(const double &s, const cvec &v)
+{
+  it_assert_debug(v.size() > 0, "operator-(): Vector of zero length");
+
+  cvec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = std::complex<double>((double)s - v(i).real(), -v(i).imag());
+  }
+  return temp;
+}
+
+cvec operator*(const double &s, const cvec &v)
+{
+  it_assert_debug(v.size() > 0, "operator*(): Vector of zero length");
+
+  cvec temp = v;
+  for (int i = 0;i < v.size();i++) {
+    temp(i) *= (double)s;
+  }
+  return temp;
+}
+
+cvec operator/(const cvec &v, const double &s)
+{
+  it_assert_debug(v.size() > 0, "operator/(): Vector of zero length");
+
+  cvec temp = v;
+  for (int i = 0;i < v.size();i++) {
+    temp(i) /= (double)s;
+  }
+  return temp;
+}
+
+cvec operator/(const double &s, const cvec &v)
+{
+  it_assert_debug(v.size() > 0, "operator/(): Vector of zero length");
+
+  cvec temp(v.length());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s / v(i);
+  }
+  return temp;
+}
+
+//-----------  Scalar and a cmat -----------------
+
+cmat operator+(const double &s, const cmat &m)
+{
+  it_assert_debug(m.rows() > 0 && m.cols() > 0, "operator+(): Matrix of zero length");
+
+  cmat temp = m;
+  for (int i = 0;i < m._datasize();i++) {
+    temp._data()[i] += s;
+  }
+  return temp;
+}
+
+cmat operator-(const double &s, const cmat &m)
+{
+  it_assert_debug(m.rows() > 0 && m.cols() > 0, "operator-(): Matrix of zero length");
+
+  cmat temp(m.rows(), m.cols());
+  for (int i = 0;i < m._datasize();i++) {
+    temp._data()[i] = std::complex<double>((double)s - m(i).real(), -m(i).imag());
+  }
+  return temp;
+}
+
+cmat operator*(const double &s, const cmat &m)
+{
+  it_assert_debug(m.rows() > 0 && m.cols() > 0, "operator*(): Matrix of zero length");
+
+  cmat temp = m;
+  for (int i = 0;i < m._datasize();i++) {
+    temp._data()[i] *= (double)s;
+  }
+  return temp;
+}
+
+cmat operator*(const std::complex<double> &s, const mat &m)
+{
+  it_assert_debug(m.rows() > 0 && m.cols() > 0, "operator*(): Matrix of zero length");
+
+  cmat temp(m.rows(), m.cols());
+
+  for (int i = 0;i < m._datasize();i++) {
+    temp._data()[i] = s * m._data()[i];
+  }
+  return temp;
+}
+
+cmat operator/(const cmat &m, const double &s)
+{
+  it_assert_debug(m.rows() > 0 && m.cols() > 0, "operator/(): Matrix of zero length");
+
+  cmat temp = m;
+  for (int i = 0;i < m._datasize();i++) {
+    temp._data()[i] /= (double)s;
+  }
+  return temp;
+}
+
+//---------------------- between matrix and scalar --------------------
+
+//----------- Multiplication of a scalar and a vec -----------------
+
+cvec operator*(const std::complex<double> &s, const vec &v)
+{
+  cvec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s * std::complex<double>(v(i), 0.0);
+  }
+  return temp;
+}
+
+cvec operator*(const vec &v, const std::complex<double> &s)
+{
+  cvec temp(v.size());
+  for (int i = 0;i < v.size();i++) {
+    temp(i) = s * std::complex<double>(v(i), 0.0);
+  }
+  return temp;
+}
+
+// ===============================================================================================
+
+// ---------------- Addition of vectors ---------------
+
+
+vec operator+(const bvec &a, const vec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator+(): sizes does not match");
+  vec temp(a.size());
+  for (int i = 0;i < a.size();i++) {temp(i) = (double)a(i) + b(i);}
+  return temp;
+}
+
+vec operator+(const svec &a, const vec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator+(): sizes does not match");
+  vec temp(a.size());
+  for (int i = 0;i < a.size();i++) {temp(i) = (double)a(i) + b(i);}
+  return temp;
+}
+
+vec operator+(const ivec &a, const vec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator+(): sizes does not match");
+  vec temp(a.size());
+  for (int i = 0;i < a.size();i++) {temp(i) = (double)a(i) + b(i);}
+  return temp;
+}
+
+cvec operator+(const bvec &a, const cvec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator+(): sizes does not match");
+  cvec temp = b;
+  for (int i = 0;i < a.size();i++) {temp(i) += (double)a(i);}
+  return temp;
+}
+
+cvec operator+(const svec &a, const cvec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator+(): sizes does not match");
+  cvec temp = b;
+  for (int i = 0;i < a.size();i++) {temp(i) += (double)a(i);}
+  return temp;
+}
+
+cvec operator+(const ivec &a, const cvec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator+(): sizes does not match");
+  cvec temp = b;
+  for (int i = 0;i < a.size();i++) {temp(i) += (double)a(i);}
+  return temp;
+}
+
+// ---------------- Multiplication of vectors ---------------
+
+double operator*(const bvec &a, const vec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator*(): sizes does not match");
+  double temp = 0;
+  for (int i = 0;i < a.size();i++) {temp += (double)a(i) * b(i);}
+  return temp;
+}
+
+double operator*(const svec &a, const vec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator*(): sizes does not match");
+  double temp = 0;
+  for (int i = 0;i < a.size();i++) {temp += (double)a(i) * b(i);}
+  return temp;
+}
+
+double operator*(const ivec &a, const vec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator*(): sizes does not match");
+  double temp = 0;
+  for (int i = 0;i < a.size();i++) {temp += (double)a(i) * b(i);}
+  return temp;
+}
+
+std::complex<double> operator*(const bvec &a, const cvec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator*(): sizes does not match");
+  std::complex<double> temp = 0;
+  for (int i = 0;i < a.size();i++) {temp += (double)a(i) * b(i);}
+  return temp;
+}
+
+std::complex<double> operator*(const svec &a, const cvec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator*(): sizes does not match");
+  std::complex<double> temp = 0;
+  for (int i = 0;i < a.size();i++) {temp += (double)a(i) * b(i);}
+  return temp;
+}
+
+std::complex<double> operator*(const ivec &a, const cvec &b)
+{
+  it_assert_debug(a.size() == b.size(), "operator*(): sizes does not match");
+  std::complex<double> temp = 0;
+  for (int i = 0;i < a.size();i++) {temp += (double)a(i) * b(i);}
+  return temp;
+}
+
+// ---------------- Addition of matricies ---------------
+
+mat operator+(const bmat &a, const mat &b)
+{
+  it_assert_debug(a.cols() == b.cols() && a.rows() == b.rows(), "operator+(): sizes does not match");
+  mat temp(b);
+
+  for (int i = 0;i < a.rows();i++) {
+    for (int j = 0;j < a.cols();j++) {
+      temp(i, j) += (double)a(i, j);
+    }
+  }
+  return temp;
+}
+
+mat operator+(const smat &a, const mat &b)
+{
+  it_assert_debug(a.cols() == b.cols() && a.rows() == b.rows(), "operator+(): sizes does not match");
+  mat temp(b);
+
+  for (int i = 0;i < a.rows();i++) {
+    for (int j = 0;j < a.cols();j++) {
+      temp(i, j) += (double)a(i, j);
+    }
+  }
+  return temp;
+}
+
+mat operator+(const imat &a, const mat &b)
+{
+  it_assert_debug(a.cols() == b.cols() && a.rows() == b.rows(), "operator+(): sizes does not match");
+  mat temp(b);
+
+  for (int i = 0;i < a.rows();i++) {
+    for (int j = 0;j < a.cols();j++) {
+      temp(i, j) += (double)a(i, j);
+    }
+  }
+  return temp;
+}
+
+// ---------------- Addition of cmat and matrices ---------------
+
+cmat operator+(const bmat &a, const cmat &b)
+{
+  it_assert_debug(a.cols() == b.cols() && a.rows() == b.rows(), "operator+(): sizes does not match");
+  cmat temp(b);
+
+  for (int i = 0;i < a.rows();i++) {
+    for (int j = 0;j < a.cols();j++) {
+      temp(i, j) += std::complex<double>(static_cast<double>(a(i, j)), 0.0);
+    }
+  }
+  return temp;
+}
+
+cmat operator+(const smat &a, const cmat &b)
+{
+  it_assert_debug(a.cols() == b.cols() && a.rows() == b.rows(), "operator+(): sizes does not match");
+  cmat temp(b);
+
+  for (int i = 0;i < a.rows();i++) {
+    for (int j = 0;j < a.cols();j++) {
+      temp(i, j) += (double)a(i, j);
+    }
+  }
+  return temp;
+}
+
+cmat operator+(const imat &a, const cmat &b)
+{
+  it_assert_debug(a.cols() == b.cols() && a.rows() == b.rows(), "operator+(): sizes does not match");
+  cmat temp(b);
+
+  for (int i = 0;i < a.rows();i++) {
+    for (int j = 0;j < a.cols();j++) {
+      temp(i, j) += std::complex<double>(static_cast<double>(a(i, j)), 0.0);
+    }
+  }
+  return temp;
+}
+
+cmat operator+(const mat &a, const cmat &b)
+{
+  it_assert_debug(a.cols() == b.cols() && a.rows() == b.rows(), "operator+(): sizes does not match");
+  cmat temp(b);
+
+  for (int i = 0;i < a.rows();i++) {
+    for (int j = 0;j < a.cols();j++) {
+      temp(i, j) += std::complex<double>(static_cast<double>(a(i, j)), 0.0);
+    }
+  }
+  return temp;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/help_functions.cpp
===================================================================
--- library/bdm/base/itpp/base/help_functions.cpp (revision 812)
+++ library/bdm/base/itpp/base/help_functions.cpp (revision 812)
@@ -0,0 +1,85 @@
+/*!
+ * \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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/help_functions.h>
+
+//! \cond
+
+namespace itpp
+{
+
+template vec apply_function(double(*f)(double), const vec &v);
+template cvec apply_function(std::complex<double> (*f)(const std::complex<double> &),
+                             const cvec &v);
+template svec apply_function(short(*f)(short), const svec &v);
+template ivec apply_function(int (*f)(int), const ivec &v);
+template bvec apply_function(bin(*f)(bin), const bvec &v);
+
+template mat apply_function(double(*f)(double), const mat &m);
+template cmat apply_function(std::complex<double> (*f)(const std::complex<double> &),
+                             const cmat &m);
+template smat apply_function(short(*f)(short), const smat &m);
+template imat apply_function(int (*f)(int), const imat &m);
+template bmat apply_function(bin(*f)(bin), const bmat &m);
+
+template vec apply_function(double(*f)(double, double), const double& x, const vec &v);
+template cvec apply_function(std::complex<double> (*f)(const std::complex<double> &,
+                             const std::complex<double> &),
+                             const std::complex<double>& x, const cvec &v);
+template svec apply_function(short(*f)(short, short), const short& x, const svec &v);
+template ivec apply_function(int (*f)(int, int), const int& x, const ivec &v);
+template bvec apply_function(bin(*f)(bin, bin), const bin& x, const bvec &v);
+
+template mat apply_function(double(*f)(double, double), const double& x, const mat &m);
+template cmat apply_function(std::complex<double> (*f)(const std::complex<double> &,
+                             const std::complex<double> &),
+                             const std::complex<double>& x, const cmat &m);
+template smat apply_function(short(*f)(short, short), const short& x, const smat &m);
+template imat apply_function(int (*f)(int, int), const int& x, const imat &m);
+template bmat apply_function(bin(*f)(bin, bin), const bin& x, const bmat &m);
+
+template vec apply_function(double(*f)(double, double), const vec &v, const double& x);
+template cvec apply_function(std::complex<double> (*f)(const std::complex<double> &,
+                             const std::complex<double> &),
+                             const cvec &v, const std::complex<double>& x);
+template svec apply_function(short(*f)(short, short), const svec &v, const short& x);
+template ivec apply_function(int (*f)(int, int), const ivec &v, const int& x);
+template bvec apply_function(bin(*f)(bin, bin), const bvec &v, const bin& x);
+
+template mat apply_function(double(*f)(double, double), const mat &m, const double& x);
+template cmat apply_function(std::complex<double> (*f)(const std::complex<double> &,
+                             const std::complex<double> &),
+                             const cmat &m, const std::complex<double>& x);
+template smat apply_function(short(*f)(short, short), const smat &m, const short& x);
+template imat apply_function(int (*f)(int, int), const imat &m, const int& x);
+template bmat apply_function(bin(*f)(bin, bin), const bmat &m, const bin& x);
+
+} // namespace itpp
+
+//! \endcond
Index: library/bdm/base/itpp/base/random.cpp
===================================================================
--- library/bdm/base/itpp/base/random.cpp (revision 812)
+++ library/bdm/base/itpp/base/random.cpp (revision 812)
@@ -0,0 +1,590 @@
+/*!
+ * \file
+ * \brief Implementation 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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/random.h>
+#include <itpp/base/math/elem_math.h>
+#include <limits>
+
+
+namespace itpp
+{
+
+///////////////////////////////////////////////
+// Random_Generator
+///////////////////////////////////////////////
+
+bool Random_Generator::initialized = false;
+int Random_Generator::left = 0;
+unsigned int Random_Generator::state[624];
+unsigned int *Random_Generator::pNext;
+
+unsigned int Random_Generator::hash(time_t t, clock_t c)
+{
+  // Get a unsigned int from t and c
+  // Better than uint(x) in case x is floating point in [0,1]
+  // Based on code by Lawrence Kirby (fred@genesis.demon.co.uk)
+  static unsigned int differ = 0; // guarantee time-based seeds will change
+
+  unsigned int h1 = 0;
+  unsigned char *p = (unsigned char *) & t;
+  for (size_t i = 0; i < sizeof(t); ++i) {
+    h1 *= std::numeric_limits<unsigned char>::max() + 2U;
+    h1 += p[i];
+  }
+  unsigned int h2 = 0;
+  p = (unsigned char *) & c;
+  for (size_t j = 0; j < sizeof(c); ++j) {
+    h2 *= std::numeric_limits<unsigned char>::max() + 2U;
+    h2 += p[j];
+  }
+  return (h1 + differ++) ^ h2;
+}
+
+void Random_Generator::get_state(ivec &out_state)
+{
+  out_state.set_size(625, false);
+  for (int i = 0; i < 624; i++)
+    out_state(i) = state[i];
+
+  out_state(624) = left; // the number of elements left in state before reload
+}
+
+void Random_Generator::set_state(ivec &new_state)
+{
+  it_assert(new_state.size() == 625, "Random_Generator::set_state(): Not a valid state vector");
+
+  for (int i = 0; i < 624; i++)
+    state[i] = new_state(i);
+
+  left = new_state(624);
+  pNext = &state[624-left];
+}
+
+
+// Set the seed of the Global Random Number Generator
+void RNG_reset(unsigned int seed)
+{
+  Random_Generator RNG;
+  RNG.reset(seed);
+}
+
+// Set the seed of the Global Random Number Generator to the same as last time
+void RNG_reset()
+{
+  Random_Generator RNG;
+  RNG.reset();
+}
+
+// Set a random seed for the Global Random Number Generator
+void RNG_randomize()
+{
+  Random_Generator RNG;
+  RNG.randomize();
+}
+
+// Save current full state of generator in memory
+void RNG_get_state(ivec &state)
+{
+  Random_Generator RNG;
+  RNG.get_state(state);
+}
+
+// Resume the state saved in memory
+void RNG_set_state(ivec &state)
+{
+  Random_Generator RNG;
+  RNG.set_state(state);
+}
+
+///////////////////////////////////////////////
+// I_Uniform_RNG
+///////////////////////////////////////////////
+
+I_Uniform_RNG::I_Uniform_RNG(int min, int max)
+{
+  setup(min, max);
+}
+
+void I_Uniform_RNG::setup(int min, int max)
+{
+  if (min <= max) {
+    lo = min;
+    hi = max;
+  }
+  else {
+    lo = max;
+    hi = min;
+  }
+}
+
+void I_Uniform_RNG::get_setup(int &min, int &max) const
+{
+  min = lo;
+  max = hi;
+}
+
+ivec I_Uniform_RNG::operator()(int n)
+{
+  ivec vv(n);
+
+  for (int i=0; i < n; i++)
+    vv(i) = sample();
+
+  return vv;
+}
+
+imat I_Uniform_RNG::operator()(int h, int w)
+{
+  imat mm(h, w);
+  int i, j;
+
+  for (i = 0; i < h; i++)
+    for (j = 0; j < w; j++)
+      mm(i, j) = sample();
+
+  return mm;
+}
+
+///////////////////////////////////////////////
+// Uniform_RNG
+///////////////////////////////////////////////
+
+Uniform_RNG::Uniform_RNG(double min, double max)
+{
+  setup(min, max);
+}
+
+void Uniform_RNG::setup(double min, double max)
+{
+  if (min <= max) {
+    lo_bound = min;
+    hi_bound = max;
+  }
+  else {
+    lo_bound = max;
+    hi_bound = min;
+  }
+}
+
+void Uniform_RNG::get_setup(double &min, double &max) const
+{
+  min = lo_bound;
+  max = hi_bound;
+}
+
+///////////////////////////////////////////////
+// Exp_RNG
+///////////////////////////////////////////////
+
+Exponential_RNG::Exponential_RNG(double lambda)
+{
+  setup(lambda);
+}
+
+vec Exponential_RNG::operator()(int n)
+{
+  vec vv(n);
+
+  for (int i=0; i < n; i++)
+    vv(i) = sample();
+
+  return vv;
+}
+
+mat Exponential_RNG::operator()(int h, int w)
+{
+  mat mm(h, w);
+  int i, j;
+
+  for (i = 0; i < h; i++)
+    for (j = 0; j < w; j++)
+      mm(i, j) = sample();
+
+  return mm;
+}
+
+///////////////////////////////////////////////
+// Normal_RNG
+///////////////////////////////////////////////
+
+void Normal_RNG::get_setup(double &meanval, double &variance) const
+{
+  meanval = mean;
+  variance = sigma * sigma;
+}
+
+// (Ziggurat) tabulated values for the heigt of the Ziggurat levels
+const double Normal_RNG::ytab[128] = {
+  1, 0.963598623011, 0.936280813353, 0.913041104253,
+  0.892278506696, 0.873239356919, 0.855496407634, 0.838778928349,
+  0.822902083699, 0.807732738234, 0.793171045519, 0.779139726505,
+  0.765577436082, 0.752434456248, 0.739669787677, 0.727249120285,
+  0.715143377413, 0.703327646455, 0.691780377035, 0.68048276891,
+  0.669418297233, 0.65857233912, 0.647931876189, 0.637485254896,
+  0.62722199145, 0.617132611532, 0.607208517467, 0.597441877296,
+  0.587825531465, 0.578352913803, 0.569017984198, 0.559815170911,
+  0.550739320877, 0.541785656682, 0.532949739145, 0.524227434628,
+  0.515614886373, 0.507108489253, 0.498704867478, 0.490400854812,
+  0.482193476986, 0.47407993601, 0.466057596125, 0.458123971214,
+  0.450276713467, 0.442513603171, 0.434832539473, 0.427231532022,
+  0.419708693379, 0.41226223212, 0.404890446548, 0.397591718955,
+  0.390364510382, 0.383207355816, 0.376118859788, 0.369097692334,
+  0.362142585282, 0.355252328834, 0.348425768415, 0.341661801776,
+  0.334959376311, 0.328317486588, 0.321735172063, 0.31521151497,
+  0.308745638367, 0.302336704338, 0.29598391232, 0.289686497571,
+  0.283443729739, 0.27725491156, 0.271119377649, 0.265036493387,
+  0.259005653912, 0.253026283183, 0.247097833139, 0.241219782932,
+  0.235391638239, 0.229612930649, 0.223883217122, 0.218202079518,
+  0.212569124201, 0.206983981709, 0.201446306496, 0.195955776745,
+  0.190512094256, 0.185114984406, 0.179764196185, 0.174459502324,
+  0.169200699492, 0.1639876086, 0.158820075195, 0.153697969964,
+  0.148621189348, 0.143589656295, 0.138603321143, 0.133662162669,
+  0.128766189309, 0.123915440582, 0.119109988745, 0.114349940703,
+  0.10963544023, 0.104966670533, 0.100343857232, 0.0957672718266,
+  0.0912372357329, 0.0867541250127, 0.082318375932, 0.0779304915295,
+  0.0735910494266, 0.0693007111742, 0.065060233529, 0.0608704821745,
+  0.056732448584, 0.05264727098, 0.0486162607163, 0.0446409359769,
+  0.0407230655415, 0.0368647267386, 0.0330683839378, 0.0293369977411,
+  0.0256741818288, 0.0220844372634, 0.0185735200577, 0.0151490552854,
+  0.0118216532614, 0.00860719483079, 0.00553245272614, 0.00265435214565
+};
+
+/*
+ * (Ziggurat) tabulated values for 2^24 times x[i]/x[i+1], used to accept
+ * for U*x[i+1]<=x[i] without any floating point operations
+ */
+const unsigned int Normal_RNG::ktab[128] = {
+  0, 12590644, 14272653, 14988939,
+  15384584, 15635009, 15807561, 15933577,
+  16029594, 16105155, 16166147, 16216399,
+  16258508, 16294295, 16325078, 16351831,
+  16375291, 16396026, 16414479, 16431002,
+  16445880, 16459343, 16471578, 16482744,
+  16492970, 16502368, 16511031, 16519039,
+  16526459, 16533352, 16539769, 16545755,
+  16551348, 16556584, 16561493, 16566101,
+  16570433, 16574511, 16578353, 16581977,
+  16585398, 16588629, 16591685, 16594575,
+  16597311, 16599901, 16602354, 16604679,
+  16606881, 16608968, 16610945, 16612818,
+  16614592, 16616272, 16617861, 16619363,
+  16620782, 16622121, 16623383, 16624570,
+  16625685, 16626730, 16627708, 16628619,
+  16629465, 16630248, 16630969, 16631628,
+  16632228, 16632768, 16633248, 16633671,
+  16634034, 16634340, 16634586, 16634774,
+  16634903, 16634972, 16634980, 16634926,
+  16634810, 16634628, 16634381, 16634066,
+  16633680, 16633222, 16632688, 16632075,
+  16631380, 16630598, 16629726, 16628757,
+  16627686, 16626507, 16625212, 16623794,
+  16622243, 16620548, 16618698, 16616679,
+  16614476, 16612071, 16609444, 16606571,
+  16603425, 16599973, 16596178, 16591995,
+  16587369, 16582237, 16576520, 16570120,
+  16562917, 16554758, 16545450, 16534739,
+  16522287, 16507638, 16490152, 16468907,
+  16442518, 16408804, 16364095, 16301683,
+  16207738, 16047994, 15704248, 15472926
+};
+
+// (Ziggurat) tabulated values of 2^{-24}*x[i]
+const double Normal_RNG::wtab[128] = {
+  1.62318314817e-08, 2.16291505214e-08, 2.54246305087e-08, 2.84579525938e-08,
+  3.10340022482e-08, 3.33011726243e-08, 3.53439060345e-08, 3.72152672658e-08,
+  3.8950989572e-08, 4.05763964764e-08, 4.21101548915e-08, 4.35664624904e-08,
+  4.49563968336e-08, 4.62887864029e-08, 4.75707945735e-08, 4.88083237257e-08,
+  5.00063025384e-08, 5.11688950428e-08, 5.22996558616e-08, 5.34016475624e-08,
+  5.44775307871e-08, 5.55296344581e-08, 5.65600111659e-08, 5.75704813695e-08,
+  5.85626690412e-08, 5.95380306862e-08, 6.04978791776e-08, 6.14434034901e-08,
+  6.23756851626e-08, 6.32957121259e-08, 6.42043903937e-08, 6.51025540077e-08,
+  6.59909735447e-08, 6.68703634341e-08, 6.77413882848e-08, 6.8604668381e-08,
+  6.94607844804e-08, 7.03102820203e-08, 7.11536748229e-08, 7.1991448372e-08,
+  7.2824062723e-08, 7.36519550992e-08, 7.44755422158e-08, 7.52952223703e-08,
+  7.61113773308e-08, 7.69243740467e-08, 7.77345662086e-08, 7.85422956743e-08,
+  7.93478937793e-08, 8.01516825471e-08, 8.09539758128e-08, 8.17550802699e-08,
+  8.25552964535e-08, 8.33549196661e-08, 8.41542408569e-08, 8.49535474601e-08,
+  8.57531242006e-08, 8.65532538723e-08, 8.73542180955e-08, 8.8156298059e-08,
+  8.89597752521e-08, 8.97649321908e-08, 9.05720531451e-08, 9.138142487e-08,
+  9.21933373471e-08, 9.30080845407e-08, 9.38259651738e-08, 9.46472835298e-08,
+  9.54723502847e-08, 9.63014833769e-08, 9.71350089201e-08, 9.79732621669e-08,
+  9.88165885297e-08, 9.96653446693e-08, 1.00519899658e-07, 1.0138063623e-07,
+  1.02247952126e-07, 1.03122261554e-07, 1.04003996769e-07, 1.04893609795e-07,
+  1.05791574313e-07, 1.06698387725e-07, 1.07614573423e-07, 1.08540683296e-07,
+  1.09477300508e-07, 1.1042504257e-07, 1.11384564771e-07, 1.12356564007e-07,
+  1.13341783071e-07, 1.14341015475e-07, 1.15355110887e-07, 1.16384981291e-07,
+  1.17431607977e-07, 1.18496049514e-07, 1.19579450872e-07, 1.20683053909e-07,
+  1.21808209468e-07, 1.2295639141e-07, 1.24129212952e-07, 1.25328445797e-07,
+  1.26556042658e-07, 1.27814163916e-07, 1.29105209375e-07, 1.30431856341e-07,
+  1.31797105598e-07, 1.3320433736e-07, 1.34657379914e-07, 1.36160594606e-07,
+  1.37718982103e-07, 1.39338316679e-07, 1.41025317971e-07, 1.42787873535e-07,
+  1.44635331499e-07, 1.4657889173e-07, 1.48632138436e-07, 1.50811780719e-07,
+  1.53138707402e-07, 1.55639532047e-07, 1.58348931426e-07, 1.61313325908e-07,
+  1.64596952856e-07, 1.68292495203e-07, 1.72541128694e-07, 1.77574279496e-07,
+  1.83813550477e-07, 1.92166040885e-07, 2.05295471952e-07, 2.22600839893e-07
+};
+
+// (Ziggurat) position of right-most step
+const double Normal_RNG::PARAM_R = 3.44428647676;
+
+// Get a Normal distributed (0,1) sample
+double Normal_RNG::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;
+}
+
+
+///////////////////////////////////////////////
+// Laplace_RNG
+///////////////////////////////////////////////
+
+Laplace_RNG::Laplace_RNG(double meanval, double variance)
+{
+  setup(meanval, variance);
+}
+
+void Laplace_RNG::setup(double meanval, double variance)
+{
+  mean = meanval;
+  var = variance;
+  sqrt_12var = std::sqrt(variance / 2.0);
+}
+
+void Laplace_RNG::get_setup(double &meanval, double &variance) const
+{
+  meanval = mean;
+  variance = var;
+}
+
+
+
+vec Laplace_RNG::operator()(int n)
+{
+  vec vv(n);
+
+  for (int i=0; i < n; i++)
+    vv(i) = sample();
+
+  return vv;
+}
+
+mat Laplace_RNG::operator()(int h, int w)
+{
+  mat mm(h, w);
+  int i, j;
+
+  for (i = 0; i < h; i++)
+    for (j = 0; j < w; j++)
+      mm(i, j) = sample();
+
+  return mm;
+}
+
+///////////////////////////////////////////////
+// AR1_Normal_RNG
+///////////////////////////////////////////////
+
+AR1_Normal_RNG::AR1_Normal_RNG(double meanval, double variance, double rho)
+{
+  setup(meanval, variance, rho);
+}
+
+void AR1_Normal_RNG::setup(double meanval, double variance, double rho)
+{
+  mean = meanval;
+  var = variance;
+  r = rho;
+  factr = -2.0 * var * (1.0 - rho * rho);
+  mem = 0.0;
+  odd = true;
+}
+
+void AR1_Normal_RNG::get_setup(double &meanval, double &variance,
+                               double &rho) const
+{
+  meanval = mean;
+  variance = var;
+  rho = r;
+}
+
+vec AR1_Normal_RNG::operator()(int n)
+{
+  vec vv(n);
+
+  for (int i=0; i < n; i++)
+    vv(i) = sample();
+
+  return vv;
+}
+
+mat AR1_Normal_RNG::operator()(int h, int w)
+{
+  mat mm(h, w);
+  int i, j;
+
+  for (i = 0; i < h; i++)
+    for (j = 0; j < w; j++)
+      mm(i, j) = sample();
+
+  return mm;
+}
+
+void AR1_Normal_RNG::reset()
+{
+  mem = 0.0;
+}
+
+///////////////////////////////////////////////
+// Weibull_RNG
+///////////////////////////////////////////////
+
+Weibull_RNG::Weibull_RNG(double lambda, double beta)
+{
+  setup(lambda, beta);
+}
+
+void Weibull_RNG::setup(double lambda, double beta)
+{
+  l = lambda;
+  b = beta;
+  mean = tgamma(1.0 + 1.0 / b) / l;
+  var = tgamma(1.0 + 2.0 / b) / (l * l) - mean;
+}
+
+
+vec Weibull_RNG::operator()(int n)
+{
+  vec vv(n);
+
+  for (int i=0; i < n; i++)
+    vv(i) = sample();
+
+  return vv;
+}
+
+mat Weibull_RNG::operator()(int h, int w)
+{
+  mat mm(h, w);
+  int i, j;
+
+  for (i = 0; i < h; i++)
+    for (j = 0; j < w; j++)
+      mm(i, j) = sample();
+
+  return mm;
+}
+
+///////////////////////////////////////////////
+// Rayleigh_RNG
+///////////////////////////////////////////////
+
+Rayleigh_RNG::Rayleigh_RNG(double sigma)
+{
+  setup(sigma);
+}
+
+vec Rayleigh_RNG::operator()(int n)
+{
+  vec vv(n);
+
+  for (int i=0; i < n; i++)
+    vv(i) = sample();
+
+  return vv;
+}
+
+mat Rayleigh_RNG::operator()(int h, int w)
+{
+  mat mm(h, w);
+  int i, j;
+
+  for (i = 0; i < h; i++)
+    for (j = 0; j < w; j++)
+      mm(i, j) = sample();
+
+  return mm;
+}
+
+///////////////////////////////////////////////
+// Rice_RNG
+///////////////////////////////////////////////
+
+Rice_RNG::Rice_RNG(double lambda, double beta)
+{
+  setup(lambda, beta);
+}
+
+vec Rice_RNG::operator()(int n)
+{
+  vec vv(n);
+
+  for (int i=0; i < n; i++)
+    vv(i) = sample();
+
+  return vv;
+}
+
+mat Rice_RNG::operator()(int h, int w)
+{
+  mat mm(h, w);
+  int i, j;
+
+  for (i = 0; i < h; i++)
+    for (j = 0; j < w; j++)
+      mm(i, j) = sample();
+
+  return mm;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/mat.cpp
===================================================================
--- library/bdm/base/itpp/base/mat.cpp (revision 812)
+++ library/bdm/base/itpp/base/mat.cpp (revision 812)
@@ -0,0 +1,348 @@
+/*!
+ * \file
+ * \brief Matrix Class Implementation
+ * \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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/mat.h>
+
+#if defined (HAVE_BLAS)
+#  include <itpp/base/blas.h>
+#endif
+
+//! \cond
+
+namespace itpp
+{
+
+template<>
+cmat cmat::hermitian_transpose() const
+{
+  cmat temp(no_cols, no_rows);
+  for (int i = 0; i < no_rows; i++)
+    for (int j = 0; j < no_cols; j++)
+      temp(j, i) = std::conj(operator()(i,j));
+
+  return temp;
+}
+
+
+// -------- Multiplication operator -------------
+
+#if defined(HAVE_BLAS)
+
+template<>
+mat& mat::operator*=(const mat &m)
+{
+  it_assert_debug(no_cols == m.no_rows, "mat::operator*=(): Wrong sizes");
+  mat r(no_rows, m.no_cols); // unnecessary memory??
+  double alpha = 1.0;
+  double beta = 0.0;
+  char trans = 'n';
+  blas::dgemm_(&trans, &trans, &no_rows, &m.no_cols, &no_cols, &alpha, data,
+               &no_rows, m.data, &m.no_rows, &beta, r.data, &r.no_rows);
+  operator=(r); // time consuming
+  return *this;
+}
+
+template<>
+cmat& cmat::operator*=(const cmat &m)
+{
+  it_assert_debug(no_cols == m.no_rows, "cmat::operator*=(): Wrong sizes");
+  cmat r(no_rows, m.no_cols); // unnecessary memory??
+  std::complex<double> alpha = std::complex<double>(1.0);
+  std::complex<double> beta = std::complex<double>(0.0);
+  char trans = 'n';
+  blas::zgemm_(&trans, &trans, &no_rows, &m.no_cols, &no_cols, &alpha, data,
+               &no_rows, m.data, &m.no_rows, &beta, r.data, &r.no_rows);
+  operator=(r); // time consuming
+  return *this;
+}
+
+template<>
+mat operator*(const mat &m1, const mat &m2)
+{
+  it_assert_debug(m1.no_cols == m2.no_rows, "mat::operator*(): Wrong sizes");
+  mat r(m1.no_rows, m2.no_cols);
+  double alpha = 1.0;
+  double beta = 0.0;
+  char trans = 'n';
+  blas::dgemm_(&trans, &trans, &m1.no_rows, &m2.no_cols, &m1.no_cols, &alpha,
+               m1.data, &m1.no_rows, m2.data, &m2.no_rows, &beta, r.data,
+               &r.no_rows);
+  return r;
+}
+
+template<>
+cmat operator*(const cmat &m1, const cmat &m2)
+{
+  it_assert_debug(m1.no_cols == m2.no_rows, "cmat::operator*(): Wrong sizes");
+  cmat r(m1.no_rows, m2.no_cols);
+  std::complex<double> alpha = std::complex<double>(1.0);
+  std::complex<double> beta = std::complex<double>(0.0);
+  char trans = 'n';
+  blas::zgemm_(&trans, &trans, &m1.no_rows, &m2.no_cols, &m1.no_cols, &alpha,
+               m1.data, &m1.no_rows, m2.data, &m2.no_rows, &beta, r.data,
+               &r.no_rows);
+  return r;
+}
+
+template<>
+vec operator*(const mat &m, const vec &v)
+{
+  it_assert_debug(m.no_cols == v.size(), "mat::operator*(): Wrong sizes");
+  vec r(m.no_rows);
+  double alpha = 1.0;
+  double beta = 0.0;
+  char trans = 'n';
+  int incr = 1;
+  blas::dgemv_(&trans, &m.no_rows, &m.no_cols, &alpha, m.data, &m.no_rows,
+               v._data(), &incr, &beta, r._data(), &incr);
+  return r;
+}
+
+template<>
+cvec operator*(const cmat &m, const cvec &v)
+{
+  it_assert_debug(m.no_cols == v.size(), "cmat::operator*(): Wrong sizes");
+  cvec r(m.no_rows);
+  std::complex<double> alpha = std::complex<double>(1.0);
+  std::complex<double> beta = std::complex<double>(0.0);
+  char trans = 'n';
+  int incr = 1;
+  blas::zgemv_(&trans, &m.no_rows, &m.no_cols, &alpha, m.data, &m.no_rows,
+               v._data(), &incr, &beta, r._data(), &incr);
+  return r;
+}
+
+#endif // HAVE_BLAS
+
+
+//---------------------------------------------------------------------
+// Instantiations
+//---------------------------------------------------------------------
+
+// class instantiations
+
+template class Mat<double>;
+template class Mat<std::complex<double> >;
+template class Mat<int>;
+template class Mat<short int>;
+template class Mat<bin>;
+
+// addition operators
+
+template mat operator+(const mat &m1, const mat &m2);
+template cmat operator+(const cmat &m1, const cmat &m2);
+template imat operator+(const imat &m1, const imat &m2);
+template smat operator+(const smat &m1, const smat &m2);
+template bmat operator+(const bmat &m1, const bmat &m2);
+
+template mat operator+(const mat &m, double t);
+template cmat operator+(const cmat &m, std::complex<double> t);
+template imat operator+(const imat &m, int t);
+template smat operator+(const smat &m, short t);
+template bmat operator+(const bmat &m, bin t);
+
+template mat operator+(double t, const mat &m);
+template cmat operator+(std::complex<double> t, const cmat &m);
+template imat operator+(int t, const imat &m);
+template smat operator+(short t, const smat &m);
+template bmat operator+(bin t, const bmat &m);
+
+// subraction operators
+
+template mat operator-(const mat &m1, const mat &m2);
+template cmat operator-(const cmat &m1, const cmat &m2);
+template imat operator-(const imat &m1, const imat &m2);
+template smat operator-(const smat &m1, const smat &m2);
+template bmat operator-(const bmat &m1, const bmat &m2);
+
+template mat operator-(const mat &m, double t);
+template cmat operator-(const cmat &m, std::complex<double> t);
+template imat operator-(const imat &m, int t);
+template smat operator-(const smat &m, short t);
+template bmat operator-(const bmat &m, bin t);
+
+template mat operator-(double t, const mat &m);
+template cmat operator-(std::complex<double> t, const cmat &m);
+template imat operator-(int t, const imat &m);
+template smat operator-(short t, const smat &m);
+template bmat operator-(bin t, const bmat &m);
+
+// unary minus
+
+template mat operator-(const mat &m);
+template cmat operator-(const cmat &m);
+template imat operator-(const imat &m);
+template smat operator-(const smat &m);
+template bmat operator-(const bmat &m);
+
+// multiplication operators
+
+#if !defined(HAVE_BLAS)
+template mat operator*(const mat &m1, const mat &m2);
+template cmat operator*(const cmat &m1, const cmat &m2);
+#endif
+template imat operator*(const imat &m1, const imat &m2);
+template smat operator*(const smat &m1, const smat &m2);
+template bmat operator*(const bmat &m1, const bmat &m2);
+
+#if !defined(HAVE_BLAS)
+template vec operator*(const mat &m, const vec &v);
+template cvec operator*(const cmat &m, const cvec &v);
+#endif
+
+template ivec operator*(const imat &m, const ivec &v);
+template svec operator*(const smat &m, const svec &v);
+template bvec operator*(const bmat &m, const bvec &v);
+
+template mat operator*(const vec &v, const mat &m);
+template cmat operator*(const cvec &v, const cmat &m);
+template imat operator*(const ivec &v, const imat &m);
+template smat operator*(const svec &v, const smat &m);
+template bmat operator*(const bvec &v, const bmat &m);
+
+template mat operator*(const mat &m, double t);
+template cmat operator*(const cmat &m, std::complex<double> t);
+template imat operator*(const imat &m, int t);
+template smat operator*(const smat &m, short t);
+template bmat operator*(const bmat &m, bin t);
+
+template mat operator*(double t, const mat &m);
+template cmat operator*(std::complex<double> t, const cmat &m);
+template imat operator*(int t, const imat &m);
+template smat operator*(short t, const smat &m);
+template bmat operator*(bin t, const bmat &m);
+
+// elementwise multiplication
+
+template mat elem_mult(const mat &m1, const mat &m2);
+template cmat elem_mult(const cmat &m1, const cmat &m2);
+template imat elem_mult(const imat &m1, const imat &m2);
+template smat elem_mult(const smat &m1, const smat &m2);
+template bmat elem_mult(const bmat &m1, const bmat &m2);
+
+template void elem_mult_out(const mat &m1, const mat &m2, mat &out);
+template void elem_mult_out(const cmat &m1, const cmat &m2, cmat &out);
+template void elem_mult_out(const imat &m1, const imat &m2, imat &out);
+template void elem_mult_out(const smat &m1, const smat &m2, smat &out);
+template void elem_mult_out(const bmat &m1, const bmat &m2, bmat &out);
+
+template void elem_mult_out(const mat &m1, const mat &m2,
+                            const mat &m3, mat &out);
+template void elem_mult_out(const cmat &m1, const cmat &m2,
+                            const cmat &m3, cmat &out);
+template void elem_mult_out(const imat &m1, const imat &m2,
+                            const imat &m3, imat &out);
+template void elem_mult_out(const smat &m1, const smat &m2,
+                            const smat &m3, smat &out);
+template void elem_mult_out(const bmat &m1, const bmat &m2,
+                            const bmat &m3, bmat &out);
+
+template void elem_mult_out(const mat &m1, const mat &m2, const mat &m3,
+                            const mat &m4, mat &out);
+template void elem_mult_out(const cmat &m1, const cmat &m2,
+                            const cmat &m3, const cmat &m4, cmat &out);
+template void elem_mult_out(const imat &m1, const imat &m2,
+                            const imat &m3, const imat &m4, imat &out);
+template void elem_mult_out(const smat &m1, const smat &m2,
+                            const smat &m3, const smat &m4, smat &out);
+template void elem_mult_out(const bmat &m1, const bmat &m2,
+                            const bmat &m3, const bmat &m4, bmat &out);
+
+template void elem_mult_inplace(const mat &m1, mat &m2);
+template void elem_mult_inplace(const cmat &m1, cmat &m2);
+template void elem_mult_inplace(const imat &m1, imat &m2);
+template void elem_mult_inplace(const smat &m1, smat &m2);
+template void elem_mult_inplace(const bmat &m1, bmat &m2);
+
+template double elem_mult_sum(const mat &m1, const mat &m2);
+template std::complex<double> elem_mult_sum(const cmat &m1, const cmat &m2);
+template int elem_mult_sum(const imat &m1, const imat &m2);
+template short elem_mult_sum(const smat &m1, const smat &m2);
+template bin elem_mult_sum(const bmat &m1, const bmat &m2);
+
+// division operator
+
+template mat operator/(const mat &m, double t);
+template cmat operator/(const cmat &m, std::complex<double> t);
+template imat operator/(const imat &m, int t);
+template smat operator/(const smat &m, short t);
+template bmat operator/(const bmat &m, bin t);
+
+// elementwise division
+
+template mat elem_div(const mat &m1, const mat &m2);
+template cmat elem_div(const cmat &m1, const cmat &m2);
+template imat elem_div(const imat &m1, const imat &m2);
+template smat elem_div(const smat &m1, const smat &m2);
+template bmat elem_div(const bmat &m1, const bmat &m2);
+
+template void elem_div_out(const mat &m1, const mat &m2, mat &out);
+template void elem_div_out(const cmat &m1, const cmat &m2, cmat &out);
+template void elem_div_out(const imat &m1, const imat &m2, imat &out);
+template void elem_div_out(const smat &m1, const smat &m2, smat &out);
+template void elem_div_out(const bmat &m1, const bmat &m2, bmat &out);
+
+template double elem_div_sum(const mat &m1, const mat &m2);
+template std::complex<double> elem_div_sum(const cmat &m1,
+    const cmat &m2);
+template int elem_div_sum(const imat &m1, const imat &m2);
+template short elem_div_sum(const smat &m1, const smat &m2);
+template bin elem_div_sum(const bmat &m1, const bmat &m2);
+
+// concatenation
+
+template mat concat_horizontal(const mat &m1, const mat &m2);
+template cmat concat_horizontal(const cmat &m1, const cmat &m2);
+template imat concat_horizontal(const imat &m1, const imat &m2);
+template smat concat_horizontal(const smat &m1, const smat &m2);
+template bmat concat_horizontal(const bmat &m1, const bmat &m2);
+
+template mat concat_vertical(const mat &m1, const mat &m2);
+template cmat concat_vertical(const cmat &m1, const cmat &m2);
+template imat concat_vertical(const imat &m1, const imat &m2);
+template smat concat_vertical(const smat &m1, const smat &m2);
+template bmat concat_vertical(const bmat &m1, const bmat &m2);
+
+// I/O streams
+
+template std::ostream &operator<<(std::ostream &os, const mat  &m);
+template std::ostream &operator<<(std::ostream &os, const cmat &m);
+template std::ostream &operator<<(std::ostream &os, const imat  &m);
+template std::ostream &operator<<(std::ostream &os, const smat  &m);
+template std::ostream &operator<<(std::ostream &os, const bmat  &m);
+
+template std::istream &operator>>(std::istream &is, mat  &m);
+template std::istream &operator>>(std::istream &is, cmat &m);
+template std::istream &operator>>(std::istream &is, imat  &m);
+template std::istream &operator>>(std::istream &is, smat  &m);
+template std::istream &operator>>(std::istream &is, bmat  &m);
+
+} // namespace itpp
+
+//! \endcond
Index: library/bdm/base/itpp/base/bessel.h
===================================================================
--- library/bdm/base/itpp/base/bessel.h (revision 812)
+++ library/bdm/base/itpp/base/bessel.h (revision 812)
@@ -0,0 +1,140 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/array.h
===================================================================
--- library/bdm/base/itpp/base/array.h (revision 812)
+++ library/bdm/base/itpp/base/array.h (revision 812)
@@ -0,0 +1,620 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/gf2mat.h
===================================================================
--- library/bdm/base/itpp/base/gf2mat.h (revision 812)
+++ library/bdm/base/itpp/base/gf2mat.h (revision 812)
@@ -0,0 +1,503 @@
+/*!
+ * \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-2010  (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
+    triangular.  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: library/bdm/base/itpp/base/blas.h
===================================================================
--- library/bdm/base/itpp/base/blas.h (revision 812)
+++ library/bdm/base/itpp/base/blas.h (revision 812)
@@ -0,0 +1,187 @@
+/*!
+ * \file
+ * \brief BLAS header functions. For internal use only.
+ * \author Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 BLAS_H
+#define BLAS_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <complex>
+
+//! \cond
+
+#if defined(_MSC_VER) && (defined(HAVE_ACML) || defined(HAVE_MKL))
+#  define dswap_ DSWAP
+#  define zswap_ ZSWAP
+#  define dscal_ DSCAL
+#  define zscal_ ZSCAL
+#  define dcopy_ DCOPY
+#  define zcopy_ ZCOPY
+#  define daxpy_ DAXPY
+#  define zaxpy_ ZAXPY
+#  define ddot_  DDOT
+#  define dgemv_ DGEMV
+#  define zgemv_ ZGEMV
+#  define dger_  DGER
+#  define zgeru_ ZGERU
+#  define zgerc_ ZGERC
+#  define dgemm_ DGEMM
+#  define zgemm_ ZGEMM
+#endif // #if defined(_MSC_VER) && (defined(HAVE_ACML) || defined(HAVE_MKL))
+
+
+namespace blas
+{
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+
+  // ----------------------------------------------------------------------
+  // BLAS 1 functions
+  // ----------------------------------------------------------------------
+
+  void dswap_(const int *n,
+              double *x, const int *incx,
+              double *y, const int *incy);
+
+  void zswap_(const int *n,
+              std::complex<double> *x, const int *incx,
+              std::complex<double> *y, const int *incy);
+
+  void dscal_(const int *n,
+              const double *alpha,
+              double *x, const int *incx);
+
+  void zscal_(const int *n,
+              const std::complex<double> *alpha,
+              std::complex<double> *x, const int *incx);
+
+  void dcopy_(const int *n,
+              const double *x, const int *incx,
+              double *y, const int *incy);
+
+  void zcopy_(const int *n,
+              const std::complex<double> *x, const int *incx,
+              std::complex<double> *y, const int *incy);
+
+  void daxpy_(const int *n,
+              const double *alpha,
+              const double *x, const int *incx,
+              double *y, const int *incy);
+
+  void zaxpy_(const int *n,
+              const std::complex<double> *alpha,
+              const std::complex<double> *x, const int *incx,
+              std::complex<double> *y, const int *incy);
+
+  double ddot_(const int *n,
+               const double *x, const int *incx,
+               const double *y, const int *incy);
+
+#if defined(HAVE_ZDOTUSUB) || defined(HAVE_ZDOTU_VOID)
+#if defined(HAVE_ZDOTU_VOID)
+#  define zdotusub_ zdotu_
+#endif // HAVE_ZDOTU_VOID
+  void zdotusub_(std::complex<double> *dot,
+                 const int *n,
+                 const std::complex<double> *x, const int *incx,
+                 const std::complex<double> *y, const int *incy);
+#endif // HAVE_ZDOTUSUB || HAVE_ZDOTU_VOID
+
+  // ----------------------------------------------------------------------
+  // BLAS 2 functions
+  // ----------------------------------------------------------------------
+
+  void dgemv_(const char *transA, const int *m, const int *n,
+              const double *alpha,
+              const double *A, const int *ldA,
+              const double *x, const int *incx,
+              const double *beta,
+              double *y, const int *incy);
+
+  void zgemv_(const char *transA, const int *m, const int *n,
+              const std::complex<double> *alpha,
+              const std::complex<double> *A, const int *ldA,
+              const std::complex<double> *x, const int *incx,
+              const std::complex<double> *beta,
+              std::complex<double> *y, const int *incy);
+
+  void dger_(const int *m, const int *n,
+             const double *alpha,
+             const double *x, const int *incx,
+             const double *y, const int *incy,
+             double *A, const int *ldA);
+
+  void zgeru_(const int *m, const int *n,
+              const std::complex<double> *alpha,
+              const std::complex<double> *x, const int *inxx,
+              const std::complex<double> *y, const int *incy,
+              std::complex<double> *A, const int *ldA);
+
+  void zgerc_(const int *m, const int *n,
+              const std::complex<double> *alpha,
+              const std::complex<double> *x, const int *inxx,
+              const std::complex<double> *y, const int *incy,
+              std::complex<double> *A, const int *ldA);
+
+  // ----------------------------------------------------------------------
+  // BLAS 3 functions
+  // ----------------------------------------------------------------------
+
+  void dgemm_(const char *transA, const char *transB,
+              const int *m, const int *n, const int *k,
+              const double *alpha,
+              const double *A, const int *ldA,
+              const double *B, const int *ldB,
+              const double *beta,
+              double *C, const int *ldC);
+
+  void zgemm_(const char *transA, const char *transB,
+              const int *m, const int *n, const int *k,
+              const std::complex<double> *alpha,
+              const std::complex<double> *A, const int *ldA,
+              const std::complex<double> *B, const int *ldB,
+              const std::complex<double> *beta,
+              std::complex<double> *C, const int *ldC);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+} // namespace blas
+
+//! \endcond
+
+#endif // #ifndef BLAS_H
Index: library/bdm/base/itpp/base/timing.cpp
===================================================================
--- library/bdm/base/itpp/base/timing.cpp (revision 812)
+++ library/bdm/base/itpp/base/timing.cpp (revision 812)
@@ -0,0 +1,183 @@
+/*!
+ * \file
+ * \brief Implementation of Timing classes
+ * \author Thomas Eriksson, Tony Ottosson, Tobias Ringstrom and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#ifdef TIME_WITH_SYS_TIME
+#  include <sys/time.h>
+#  include <ctime>
+#else
+#  ifdef HAVE_SYS_TIME_H
+#    include <sys/time.h>
+#  else
+#    include <ctime>
+#  endif
+#endif
+
+#include <itpp/base/timing.h>
+#include <cstdio>
+#include <iostream>
+#include <cmath>
+
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+#include <windows.h>
+
+int gettimeofday(struct timeval* p, void*)
+{
+  union {
+    long long ns100; /* time since 1 Jan 1601 in 100ns units */
+    FILETIME ft;
+  } _now;
+
+  GetSystemTimeAsFileTime(&(_now.ft));
+  p->tv_usec = (long)((_now.ns100 / 10LL) % 1000000LL);
+  /* time since 1 Jan 1970 */
+  p->tv_sec = (long)((_now.ns100 - 116444736000000000LL) / 10000000LL);
+  return 0;
+}
+#endif
+
+
+namespace itpp
+{
+
+//! Global object for tic and toc functions
+Real_Timer __tic_toc_timer;
+
+//----------------------------------------------------------------------------
+// class Timer
+//----------------------------------------------------------------------------
+Timer::Timer()
+{
+  reset();
+}
+
+void Timer::start(void)
+{
+  if (!running) {
+    start_time = get_current_time();
+    running = true;
+  }
+}
+
+double Timer::stop(void)
+{
+  if (running) {
+    stop_time = get_current_time();
+    elapsed_time += stop_time - start_time;
+    running = false;
+  }
+
+  return elapsed_time;
+}
+
+void Timer::reset(double t)
+{
+  elapsed_time = t;
+  start_time = 0;
+  stop_time = 0;
+  running = false;
+}
+
+double Timer::get_time() const
+{
+  return running ?
+         elapsed_time + get_current_time() - start_time :
+         elapsed_time;
+}
+
+void Timer::tic(void)
+{
+  reset();
+  start();
+}
+
+double Timer::toc(void)
+{
+  return get_time() ;
+}
+
+void Timer::toc_print(void)
+{
+  std::cout << "Elapsed time = " << get_time() << " seconds" << std::endl;
+}
+
+//----------------------------------------------------------------------------
+// class CPU_Timer
+//----------------------------------------------------------------------------
+double CPU_Timer::get_current_time() const
+{
+  return static_cast<double>(clock()) / CLOCKS_PER_SEC;
+}
+
+//----------------------------------------------------------------------------
+// class Real_Timer
+//----------------------------------------------------------------------------
+double Real_Timer::get_current_time() const
+{
+  struct timeval t;
+  gettimeofday(&t, 0);
+  return t.tv_sec + t.tv_usec * 1.0e-6;
+}
+
+
+void tic()
+{
+  __tic_toc_timer.tic();
+}
+
+double toc()
+{
+  return __tic_toc_timer.toc();
+}
+
+void toc_print()
+{
+  __tic_toc_timer.toc_print();
+}
+
+void pause(double t)
+{
+  if (t == -1) {
+    std::cout << "(Press enter to continue)" << std::endl;
+    getchar();
+  }
+  else {
+    Real_Timer T;
+    T.start();
+    while (T.get_time() < t);
+  }
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/binary.h
===================================================================
--- library/bdm/base/itpp/base/binary.h (revision 812)
+++ library/bdm/base/itpp/base/binary.h (revision 812)
@@ -0,0 +1,192 @@
+/*!
+ * \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-2010  (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 arithmetic 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: library/bdm/base/itpp/base/specmat.cpp
===================================================================
--- library/bdm/base/itpp/base/specmat.cpp (revision 812)
+++ library/bdm/base/itpp/base/specmat.cpp (revision 812)
@@ -0,0 +1,394 @@
+/*!
+ * \file
+ * \brief Implementation 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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/specmat.h>
+#include <itpp/base/math/elem_math.h>
+#include <itpp/base/math/log_exp.h>
+#include <itpp/base/matfunc.h>
+
+
+namespace itpp
+{
+
+ivec find(const bvec &invector)
+{
+  it_assert(invector.size() > 0, "find(): vector cannot be empty");
+  ivec temp(invector.size());
+  int pos = 0;
+  for (int i = 0;i < invector.size();i++) {
+    if (invector(i) == bin(1)) {
+      temp(pos) = i;
+      pos++;
+    }
+  }
+  temp.set_size(pos, true);
+  return temp;
+}
+
+//! \cond
+
+#define CREATE_SET_FUNS(typef,typem,name,value) \
+  typef name(int size)    \
+  {      \
+    typef t(size);    \
+    t = value;     \
+    return t;     \
+  }      \
+      \
+    typem name(int rows, int cols)  \
+    {      \
+      typem t(rows, cols);   \
+      t = value;    \
+      return t;     \
+    }
+
+#define CREATE_EYE_FUN(type,name,zero,one) \
+  type name(int size) {    \
+    type t(size,size);    \
+    t = zero;     \
+    for (int i=0; i<size; i++)   \
+      t(i,i) = one;    \
+    return t;     \
+  }
+
+CREATE_SET_FUNS(vec, mat, ones, 1.0)
+CREATE_SET_FUNS(bvec, bmat, ones_b, bin(1))
+CREATE_SET_FUNS(ivec, imat, ones_i, 1)
+CREATE_SET_FUNS(cvec, cmat, ones_c, std::complex<double>(1.0))
+
+CREATE_SET_FUNS(vec, mat, zeros, 0.0)
+CREATE_SET_FUNS(bvec, bmat, zeros_b, bin(0))
+CREATE_SET_FUNS(ivec, imat, zeros_i, 0)
+CREATE_SET_FUNS(cvec, cmat, zeros_c, std::complex<double>(0.0))
+
+CREATE_EYE_FUN(mat, eye, 0.0, 1.0)
+CREATE_EYE_FUN(bmat, eye_b, bin(0), bin(1))
+CREATE_EYE_FUN(imat, eye_i, 0, 1)
+CREATE_EYE_FUN(cmat, eye_c, std::complex<double>(0.0), std::complex<double>(1.0))
+
+template <class T>
+void eye(int size, Mat<T> &m)
+{
+  m.set_size(size, size, false);
+  m = T(0);
+  for (int i = size - 1; i >= 0; i--)
+    m(i, i) = T(1);
+}
+
+//! \endcond
+
+vec impulse(int size)
+{
+  vec t(size);
+  t.clear();
+  t[0] = 1.0;
+  return t;
+}
+
+vec linspace(double from, double to, int points)
+{
+  if (points < 2) {
+    // This is the "Matlab definition" of linspace
+    vec output(1);
+    output(0) = to;
+    return output;
+  }
+  else {
+    vec output(points);
+    double step = (to - from) / double(points - 1);
+    int i;
+    for (i = 0; i < points; i++)
+      output(i) = from + i * step;
+    return output;
+  }
+}
+
+vec zigzag_space(double t0, double t1, int K)
+{
+  it_assert(K > 0, "zigzag_space:() K must be positive");
+  ivec N = "0 1";
+
+  int n = 2;
+  for (int k = 0; k < K; k++) {
+    ivec Nn = 2 * N;
+    for (int i = 1; i < length(Nn); i += 2)  {
+      Nn = concat(Nn, i);
+      n++;
+    }
+    N = Nn;
+  }
+
+  vec T0 = linspace(t0, t1, n);
+  vec Tt = zeros(n);
+  for (int i = 0; i < n; i++) {
+    Tt(i) = T0(N(i));
+  }
+  return Tt;
+}
+
+// Construct a Hadamard-imat of size "size"
+imat hadamard(int size)
+{
+  it_assert(size > 0, "hadamard(): size is not a power of 2");
+  int logsize = ceil_i(::log2(static_cast<double>(size)));
+  it_assert(pow2i(logsize) == size, "hadamard(): size is not a power of 2");
+
+  imat H(size, size);
+  H(0, 0) = 1;
+
+  for (int i = 0; i < logsize; ++i) {
+    int pow2 = 1 << i;
+    for (int k = 0; k < pow2; ++k) {
+      for (int l = 0; l < pow2; ++l) {
+        H(k, l) = H(k, l);
+        H(k + pow2, l) = H(k, l);
+        H(k, l + pow2) = H(k, l);
+        H(k + pow2, l + pow2) = (-1) * H(k, l);
+      }
+    }
+  }
+  return H;
+}
+
+imat jacobsthal(int p)
+{
+  int quadratic_residue;
+  imat out(p, p);
+  int i, j;
+
+  out = -1; // start with all elements equal to "-1"
+
+  // Generate a complete list of quadratic residues
+  for (i = 0; i < (p - 1) / 2; i++) {
+    quadratic_residue = ((i + 1) * (i + 1)) % p;
+    // set this element in all rows (col-row) = quadratic_residue
+    for (j = 0; j < p; j++) {
+      out(j, (j + quadratic_residue) % p) = 1;
+    }
+  }
+
+  // set diagonal elements to zero
+  for (i = 0; i < p; i++) {
+    out(i, i) = 0;
+  }
+  return out;
+}
+
+imat conference(int n)
+{
+  it_assert_debug(n % 4 == 2, "conference(int n); wrong size");
+  int pm = n - 1; // p must be odd prime, not checked
+  imat out(n, n);
+
+  out.set_submatrix(1, n - 1, 1, n - 1, jacobsthal(pm));
+  out.set_submatrix(0, 0, 1, n - 1, 1);
+  out.set_submatrix(1, n - 1, 0, 0, 1);
+  out(0, 0) = 0;
+
+  return out;
+}
+
+
+template <>
+const cmat toeplitz(const cvec &c)
+{
+  int s = c.size();
+  cmat output(s, s);
+  cvec c_conj = conj(c);
+  for (int i = 1; i < s; ++i) {
+    for (int j = 0; j < s - i; ++j) {
+      output(i + j, j) = c_conj(i);
+    }
+  }
+  // start from j = 0 here, because the main diagonal is not conjugated
+  for (int j = 0; j < s; ++j) {
+    for (int i = 0; i < s - j; ++i) {
+      output(i, i + j) = c(j);
+    }
+  }
+  return output;
+}
+
+
+mat rotation_matrix(int dim, int plane1, int plane2, double angle)
+{
+  mat m;
+  double c = std::cos(angle), s = std::sin(angle);
+
+  it_assert(plane1 >= 0 && plane2 >= 0 &&
+            plane1 < dim && plane2 < dim && plane1 != plane2,
+            "Invalid arguments to rotation_matrix()");
+
+  m.set_size(dim, dim, false);
+  m = 0.0;
+  for (int i = 0; i < dim; i++)
+    m(i, i) = 1.0;
+
+  m(plane1, plane1) = c;
+  m(plane1, plane2) = -s;
+  m(plane2, plane1) = s;
+  m(plane2, plane2) = c;
+
+  return m;
+}
+
+void house(const vec &x, vec &v, double &beta)
+{
+  double sigma, mu;
+  int n = x.size();
+
+  v = x;
+  if (n == 1) {
+    v(0) = 1.0;
+    beta = 0.0;
+    return;
+  }
+  sigma = sum(sqr(x(1, n - 1)));
+  v(0) = 1.0;
+  if (sigma == 0.0)
+    beta = 0.0;
+  else {
+    mu = std::sqrt(sqr(x(0)) + sigma);
+    if (x(0) <= 0.0)
+      v(0) = x(0) - mu;
+    else
+      v(0) = -sigma / (x(0) + mu);
+    beta = 2 * sqr(v(0)) / (sigma + sqr(v(0)));
+    v /= v(0);
+  }
+}
+
+void givens(double a, double b, double &c, double &s)
+{
+  double t;
+
+  if (b == 0) {
+    c = 1.0;
+    s = 0.0;
+  }
+  else {
+    if (fabs(b) > fabs(a)) {
+      t = -a / b;
+      s = -1.0 / std::sqrt(1 + t * t);
+      c = s * t;
+    }
+    else {
+      t = -b / a;
+      c = 1.0 / std::sqrt(1 + t * t);
+      s = c * t;
+    }
+  }
+}
+
+void givens(double a, double b, mat &m)
+{
+  double t, c, s;
+
+  m.set_size(2, 2);
+
+  if (b == 0) {
+    m(0, 0) = 1.0;
+    m(1, 1) = 1.0;
+    m(1, 0) = 0.0;
+    m(0, 1) = 0.0;
+  }
+  else {
+    if (fabs(b) > fabs(a)) {
+      t = -a / b;
+      s = -1.0 / std::sqrt(1 + t * t);
+      c = s * t;
+    }
+    else {
+      t = -b / a;
+      c = 1.0 / std::sqrt(1 + t * t);
+      s = c * t;
+    }
+    m(0, 0) = c;
+    m(1, 1) = c;
+    m(0, 1) = s;
+    m(1, 0) = -s;
+  }
+}
+
+mat givens(double a, double b)
+{
+  mat m(2, 2);
+  givens(a, b, m);
+  return m;
+}
+
+
+void givens_t(double a, double b, mat &m)
+{
+  double t, c, s;
+
+  m.set_size(2, 2);
+
+  if (b == 0) {
+    m(0, 0) = 1.0;
+    m(1, 1) = 1.0;
+    m(1, 0) = 0.0;
+    m(0, 1) = 0.0;
+  }
+  else {
+    if (fabs(b) > fabs(a)) {
+      t = -a / b;
+      s = -1.0 / std::sqrt(1 + t * t);
+      c = s * t;
+    }
+    else {
+      t = -b / a;
+      c = 1.0 / std::sqrt(1 + t * t);
+      s = c * t;
+    }
+    m(0, 0) = c;
+    m(1, 1) = c;
+    m(0, 1) = -s;
+    m(1, 0) = s;
+  }
+}
+
+mat givens_t(double a, double b)
+{
+  mat m(2, 2);
+  givens_t(a, b, m);
+  return m;
+}
+
+//! Template instantiation of eye
+template void eye(int, mat &);
+//! Template instantiation of eye
+template void eye(int, bmat &);
+//! Template instantiation of eye
+template void eye(int, imat &);
+//! Template instantiation of eye
+template void eye(int, cmat &);
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/parser.cpp
===================================================================
--- library/bdm/base/itpp/base/parser.cpp (revision 812)
+++ library/bdm/base/itpp/base/parser.cpp (revision 812)
@@ -0,0 +1,683 @@
+/*!
+ * \file
+ * \brief Implementation 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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/parser.h>
+#include <fstream>
+#include <sstream>
+
+
+using std::cout;
+using std::endl;
+
+namespace itpp
+{
+
+Parser::Parser()
+{
+  VERBOSE = true;
+}
+
+Parser::Parser(const std::string &filename)
+{
+  VERBOSE = true;
+  init(filename);
+}
+
+Parser::Parser(int argc, char *argv[])
+{
+  VERBOSE = true;
+  init(argc, argv);
+}
+
+Parser::Parser(const std::string &filename, int argc, char *argv[])
+{
+  VERBOSE = true;
+  init(filename, argc, argv);
+}
+
+Parser::Parser(const Array<std::string> &setup)
+{
+  VERBOSE = true;
+  init(setup);
+}
+
+void Parser::pre_parsing(void)
+{
+  int i, j, n, k;
+  int count = 0;
+  int size = SetupStrings.size();
+  bool cont_line;
+  std::string Line, NewLine;
+  Array<std::string> TempSetupStrings;
+
+  // Remove lines starting with '%' or have zero length:
+  for (i = 0; i < size; i++) {
+    Line = SetupStrings(i);
+    if ((Line[0] != '%') && (Line.length() != 0)) {
+      SetupStrings(count) = Line;
+      count++;
+    }
+  }
+  SetupStrings.set_size(count, true);
+  size = SetupStrings.size();
+
+  //Check for '...' continuation as in Matlab:
+  count = 0;
+  NewLine = "";
+  for (i = 0; i < SetupStrings.size(); i++) {
+    Line = SetupStrings(i);
+    n = Line.size();
+    cont_line = false;
+    for (k = 0; k < (n - 2); k++) {
+      if ((Line[k] == '.') && (Line[k+1] == '.') && (Line[k+2] == '.')) {
+        cont_line = true;
+        break;
+      }
+    }
+    if (cont_line) {
+      for (j = 0; j < k; j++) { NewLine += Line[j]; }
+    }
+    else {
+      NewLine += Line;
+      SetupStrings(count) = NewLine;
+      count++;
+      NewLine = "";
+    }
+  }
+  SetupStrings.set_size(count, true);
+
+  //Strip unneccesary blanks, tabs, and newlines:
+  size = SetupStrings.size();
+  for (i = 0; i < size; i++) {
+    NewLine = "";
+    Line = SetupStrings(i);
+    n = Line.length();
+    j = 0; //counter in Line
+    while (j < n) {
+      switch (Line[j]) {
+      case '\n':
+        //Remove newlines
+        j++;
+        break;
+      case ' ':
+        //Remove blanks
+        j++;
+        break;
+      case '\t':
+        //Remove tabs
+        j++;
+        break;
+      case '[':
+        //Don't remove blanks between '[' and ']'
+        while ((Line[j] != ']') && (j < n)) { NewLine += Line[j]; j++; }
+        if (j < n) { NewLine += Line[j]; j++; }
+        break;
+      case '{':
+        //Don't remove blanks between '{' and '}'
+        while ((Line[j] != '}') && (j < n)) { NewLine += Line[j]; j++; }
+        if (j < n) { NewLine += Line[j]; j++; }
+        break;
+      case '"':
+        //Don't remove blanks between '"' and '"'
+        NewLine += Line[j];
+        j++; //Read in the first '"'
+        while ((Line[j] != '"') && (j < n)) { NewLine += Line[j]; j++; }
+        NewLine += Line[j];
+        j++;
+        break;
+      case '\'':
+        //Don't remove blanks between '\'' and '\''
+        NewLine += Line[j];
+        j++; //Read in the first '\''
+        while ((Line[j] != '\'') && (j < n)) { NewLine += Line[j]; j++; }
+        NewLine += Line[j];
+        j++;
+        break;
+      case '%':
+        //Remove trailing comments
+        j = n;
+        break;
+      default:
+        //Keep the current character:
+        NewLine += Line[j];
+        j++;
+        break;
+      }
+    }
+    SetupStrings(i) = NewLine;
+  }
+
+  // Split lines with several expressions (i.e. a=3;b=[1 2 3],c="Hello World") on the same line
+  // (separated by comma or semicolon)
+  TempSetupStrings.set_size(size, false);
+  count = 0; //Counter in TempSetupStrings
+  for (i = 0; i < size; i++) {
+
+    NewLine = "";
+    Line = SetupStrings(i);
+    n = Line.length();
+    j = 0;
+
+    while (j < n) {
+
+      switch (Line[j]) {
+
+      case '[':
+        //A vector or a matrix
+        while ((Line[j] != ']') && (j < n)) { NewLine += Line[j]; j++; }
+        if (Line[j] == ']') { NewLine += Line[j]; j++; }
+        if (j == n) {
+          if (count >= TempSetupStrings.size()) { TempSetupStrings.set_size(2*count, true); }
+          TempSetupStrings(count) = NewLine;
+          NewLine = "";
+          count++;
+        }
+        break;
+
+      case '"':
+        //A string
+        NewLine += Line[j];
+        j++; //Read in the first '"'
+        while ((Line[j] != '"') && (j < n)) { NewLine += Line[j]; j++; }
+        if (Line[j] == '"') { NewLine += Line[j]; j++; }
+        if (j == n) {
+          if (count >= TempSetupStrings.size()) { TempSetupStrings.set_size(2*count, true); }
+          TempSetupStrings(count) = NewLine;
+          NewLine = "";
+          count++;
+        }
+        break;
+
+
+      case '\'':
+        //A string
+        NewLine += Line[j];
+        j++; //Read in the first '\''
+        while ((Line[j] != '\'') && (j < n)) { NewLine += Line[j]; j++; }
+        if (Line[j] == '\'') { NewLine += Line[j]; j++; }
+        if (j == n) {
+          if (count >= TempSetupStrings.size()) { TempSetupStrings.set_size(2*count, true); }
+          TempSetupStrings(count) = NewLine;
+          NewLine = "";
+          count++;
+        }
+        break;
+
+      case ',':
+        //Expression ends here
+        if (count >= TempSetupStrings.size()) { TempSetupStrings.set_size(2*count, true); }
+        TempSetupStrings(count) = NewLine;
+        NewLine = "";
+        count++;
+        j++;
+        break;
+
+      case ';':
+        //Expression ends here
+        if (count >= TempSetupStrings.size()) { TempSetupStrings.set_size(2*count, true); }
+        TempSetupStrings(count) = NewLine + ';';
+        NewLine = "";
+        count++;
+        j++;
+        break;
+
+      default:
+        //Copy the current character:
+        NewLine += Line[j];
+        j++;
+        if (j == n) {
+          if (count >= TempSetupStrings.size()) { TempSetupStrings.set_size(2*count, true); }
+          TempSetupStrings(count) = NewLine;
+          NewLine = "";
+          count++;
+        }
+        break;
+
+      }
+
+    }
+
+  }
+  TempSetupStrings.set_size(count, true);
+  SetupStrings = TempSetupStrings;
+}
+
+void Parser::init(const std::string &filename)
+{
+  std::string Line;
+  SetupStrings.set_size(0, false);
+  std::ifstream SetupFile(filename.c_str());
+  it_assert(SetupFile.is_open(),
+            "Parser::init(): Could not open `" + filename + "' file");
+
+  while (getline(SetupFile, Line, '\n')) {
+    SetupStrings.set_size(SetupStrings.size() + 1, true);
+    SetupStrings(SetupStrings.size() - 1) = Line;
+  }
+
+  SetupFile.close();
+  pre_parsing();
+}
+
+void Parser::init(int argc, char *argv[])
+{
+  SetupStrings.set_size(argc);
+  int i;
+
+  for (i = 0; i < argc; i++) {
+    SetupStrings(i) = argv[i];
+  }
+  pre_parsing();
+}
+
+void Parser::init(const std::string &filename, int argc, char *argv[])
+{
+  std::string Line;
+  int i;
+  std::ifstream SetupFile(filename.c_str());
+  it_assert(SetupFile.is_open(),
+            "Parser::init(): Could not open `" + filename + "' file");
+
+  //Read the command line parameters:
+  SetupStrings.set_size(argc);
+  for (i = 0; i < argc; i++) {
+    SetupStrings(i) = argv[i];
+  }
+
+  //Read the file parameters:
+  while (getline(SetupFile, Line, '\n')) {
+    SetupStrings.set_size(SetupStrings.size() + 1, true);
+    SetupStrings(SetupStrings.size() - 1) = Line;
+  }
+
+  SetupFile.close();
+  pre_parsing();
+}
+
+void Parser::init(const Array<std::string> &setup)
+{
+  SetupStrings = setup;
+  pre_parsing();
+}
+
+void Parser::set_silentmode(bool v)
+{
+  VERBOSE = !v;
+}
+
+bool Parser::exist(const std::string &name)
+{
+  bool error_flag, print_flag;
+  std::string temp = findname(name, error_flag, print_flag);
+  if (error_flag) {
+    return false;
+  }
+  else {
+    return true;
+  }
+}
+
+template<>
+bool Parser::get(std::string &var, const std::string &name, int num)
+{
+  bool error_flag, print_flag;
+  std::string str = findname(name, error_flag, print_flag, num);
+  if (error_flag) {
+    if (VERBOSE) {
+      cout << name << " = '" << var << "';" << endl;
+    }
+  }
+  else {
+    var = str;
+    if (print_flag) {
+      cout << name << " = '" << var << "'" << endl;
+    }
+    else if (VERBOSE) {
+      cout << name << " = '" << var << "';" << endl;
+    }
+  }
+  return !error_flag;
+}
+
+template<>
+bool Parser::get(int &var, const std::string &name, int num)
+{
+  ivec out;
+  bool error_flag, print_flag;
+  out = ivec(findname(name, error_flag, print_flag, num));
+  if (error_flag) {
+    if (VERBOSE) {
+      cout << name << " = " << var << ";" << endl;
+    }
+  }
+  else {
+    it_assert(out.size() == 1, "Parser::get(int): Improper variable string: "
+              + name);
+    var = out(0);
+    if (print_flag) {
+      cout << name << " = " << var << endl;
+    }
+    else if (VERBOSE) {
+      cout << name << " = " << var << ";" << endl;
+    }
+  }
+  return !error_flag;
+}
+
+template<>
+bool Parser::get(bool &var, const std::string &name, int num)
+{
+  std::string ss;
+  bool error_flag, print_flag;
+  ss = findname(name, error_flag, print_flag, num);
+  if (error_flag) {
+    if (VERBOSE) {
+      cout << name << " = " << var << ";" << endl;
+    }
+  }
+  else {
+    if ((ss == "true") || (ss == "1")) {
+      var = true;
+    }
+    else if ((ss == "false") || (ss == "0")) {
+      var = false;
+    }
+    else {
+      it_error("Parser::get(bool): Improper variable string: " + name);
+    }
+    if (print_flag) {
+      cout << name << " = " << var << endl;
+    }
+    else if (VERBOSE) {
+      cout << name << " = " << var << ";" << endl;
+    }
+  }
+  return !error_flag;
+}
+
+bool Parser::get_bool(const std::string &name, int num)
+{
+  std::string ss;
+  bool out = false;
+  bool error_flag, print_flag;
+  ss = findname(name, error_flag, print_flag, num);
+  it_assert(!error_flag, "Parser::get_bool(): Can not find variable: " + name);
+  if ((ss == "true") || (ss == "1")) {
+    out = true;
+  }
+  else if ((ss == "false") || (ss == "0")) {
+    out = false;
+  }
+  else {
+    it_error("Parser::get_bool(): Improper variable string: " + name);
+  }
+  if (print_flag) { cout << "Parsing bool   : " << name << " = " << out << endl; }
+  return out;
+}
+
+int Parser::get_int(const std::string &name, int num)
+{
+  ivec out;
+  bool error_flag, print_flag;
+  out = ivec(findname(name, error_flag, print_flag, num));
+  it_assert(!error_flag, "Parser::get_int(): Can not find variable: " + name);
+  it_assert(out.size() == 1, "Parser::get_int(): Improper variable string: "
+            + name);
+  if (print_flag) {
+    cout << "Parsing int   : " << name << " = " << out(0) << endl;
+  }
+  return out(0);
+}
+
+double Parser::get_double(const std::string &name, int num)
+{
+  double out;
+  bool error_flag, print_flag;
+  std::istringstream ss(findname(name, error_flag, print_flag, num));
+  ss >> out;
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing double: " << name << " = " << out << endl; }
+  return out;
+}
+
+std::string Parser::get_string(const std::string &name, int num)
+{
+  std::string out;
+  bool error_flag, print_flag;
+  out = findname(name, error_flag, print_flag, num);
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing string: " << name << " = " << out << endl; }
+  return out;
+}
+
+vec Parser::get_vec(const std::string &name, int num)
+{
+  vec out;
+  bool error_flag, print_flag;
+  out = vec(findname(name, error_flag, print_flag, num));
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing vec   : " << name << " = " << out << endl; }
+  return out;
+}
+
+ivec Parser::get_ivec(const std::string &name, int num)
+{
+  ivec out;
+  bool error_flag, print_flag;
+  out = ivec(findname(name, error_flag, print_flag, num));
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing ivec  : " << name << " = " << out << endl; }
+  return out;
+}
+
+svec Parser::get_svec(const std::string &name, int num)
+{
+  svec out;
+  bool error_flag, print_flag;
+  out = svec(findname(name, error_flag, print_flag, num));
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing svec  : " << name << " = " << out << endl; }
+  return out;
+}
+
+bvec Parser::get_bvec(const std::string &name, int num)
+{
+  bvec out;
+  bool error_flag, print_flag;
+  out = bvec(findname(name, error_flag, print_flag, num));
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing bvec  : " << name << " = " << out << endl; }
+  return out;
+}
+
+mat Parser::get_mat(const std::string &name, int num)
+{
+  mat out;
+  bool error_flag, print_flag;
+  out = mat(findname(name, error_flag, print_flag, num));
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing mat   : " << name << " = " << out << endl; }
+  return out;
+}
+
+imat Parser::get_imat(const std::string &name, int num)
+{
+  imat out;
+  bool error_flag, print_flag;
+  out = imat(findname(name, error_flag, print_flag, num));
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing imat  : " << name << " = " << out << endl; }
+  return out;
+}
+
+smat Parser::get_smat(const std::string &name, int num)
+{
+  smat out;
+  bool error_flag, print_flag;
+  out = smat(findname(name, error_flag, print_flag, num));
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing smat  : " << name << " = " << out << endl; }
+  return out;
+}
+
+bmat Parser::get_bmat(const std::string &name, int num)
+{
+  bmat out;
+  bool error_flag, print_flag;
+  out = bmat(findname(name, error_flag, print_flag, num));
+  if (error_flag) { it_error("Parser: Can not find variable: " + name); }
+  if (print_flag) { cout << "Parsing bmat  : " << name << " = " << out << endl; }
+  return out;
+}
+
+std::string Parser::findname(const std::string &name, bool &error_flag, bool &print_flag, int num, bool keep_brackets)
+{
+  std::string Name, Out, Line, Temp;
+  int n, j = 0, i = 0, index = -1;
+  bool found = false, vec_mat = false;
+
+  error_flag = false;
+  print_flag = false;
+  if (num < 0) { num = 0; }
+  Name = "";
+
+  // Go through all words in input string to find a match
+  while (i < SetupStrings.size()) {
+    Line = SetupStrings(i);
+    i++;
+
+    // Find equal sign "=", and take the left part to be the Name
+    if (Line.find_first_of("=") != std::string::npos) {
+      Name = Line.substr(0, Line.find_first_of("="));
+    }
+    else {
+      Name = "";
+    }
+
+    if (Name == name) {
+      if (found) {
+        //cout << "Parser Warning: Duplicate Entry of variable " << name << endl;
+      } else {
+        found = true;
+        index = i - 1;
+      }
+    }
+  }
+
+  // if we have a match
+  if ((found) && (index + num <= SetupStrings.size())) {
+    Line = SetupStrings(index + num);
+    if (num != 0) {
+      Temp = Line;
+    }
+    else {
+      Temp = Line.substr(Line.find_first_of("=") + 1);
+    }
+  }
+  else {
+    error_flag = true;
+    return "";
+  }
+
+  //Remove [, ],",' and ending ;. Set the print_flag:
+  n = Temp.size();
+  Out = "";
+  for (i = 0; i < n; i++) {
+    switch (Temp[i]) {
+    case '[':
+      vec_mat = true;
+      if (keep_brackets) { Out += Temp[i]; }
+      if (i == (n - 1)) { print_flag = true; }
+      break;
+    case ']':
+      if (keep_brackets) { Out += Temp[i]; }
+      if (i == (n - 1)) { print_flag = true; }
+      break;
+    case '"':
+      if (i == (n - 1)) { print_flag = true; }
+      break;
+    case '\'':
+      if (i == (n - 1)) { print_flag = true; }
+      break;
+    case ';':
+      if (i == (n - 1)) { print_flag = false; }
+      else { Out += Temp[i]; }
+      break;
+    default:
+      Out += Temp[i];
+      if (i == (n - 1)) { print_flag = true; }
+      break;
+    }
+  }
+
+  //Final parsing of vectors and matrices:
+  if (vec_mat) {
+
+    Temp = Out;
+    Out  = "";
+    n    = Temp.size();
+    j    = 0;
+
+    while ((Temp[j]   == ' ') || (Temp[j]   == '\t') || (Temp[j]   == '\n')) { j++; } //Remove spaces/tabs/newline in beginning
+    while ((Temp[n-1] == ' ') || (Temp[n-1] == '\t') || (Temp[n-1] == '\n')) { n--; } //Remove spaces/tabs/newline at the end
+
+    while (j < n) {
+
+      //Read in data element:
+      while ((Temp[j] != ' ') && (Temp[j] != '\t') && (Temp[j] != '\n') && (Temp[j] != ',') && (Temp[j] != ';') && (j < n)) {
+        Out += Temp[j];
+        j++;
+      }
+
+      //Read separator:
+      if (j < (n - 1)) {
+        //Remove spaces before separator
+        while (((Temp[j] == ' ') || (Temp[j] == '\t') || (Temp[j] == '\n')) && (j < n)) { j++; }
+        //Insert Separator:
+        if (j < n) {
+          if (Temp[j] == ';') { Out += ';'; j++; }
+          else if (Temp[j] == ',') { Out += ' '; j++; }
+          else if (Temp[j] == '+') { Out += ' '; Out += Temp[j]; j++; }
+          else if (Temp[j] == '-') { Out += ' '; Out += Temp[j]; j++; }
+          else { Out += ' '; }
+        }
+        //Remove spaces after separator:
+        while (((Temp[j] == ' ') || (Temp[j] == '\t') || (Temp[j] == '\n')) && (j < n)) { j++; }
+      }
+
+    }
+
+  }
+  if (!VERBOSE) print_flag = false;
+  return Out;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/converters.h
===================================================================
--- library/bdm/base/itpp/base/converters.h (revision 812)
+++ library/bdm/base/itpp/base/converters.h (revision 812)
@@ -0,0 +1,504 @@
+/*!
+ * \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-2010  (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>
+
+
+#ifndef HAVE_RINT
+//! Round to nearest integer using the current rounding direction
+double rint(double x);
+#endif
+
+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;
+}
+
+//! \cond
+template<> inline
+cvec to_cvec(const cvec& v)
+{
+  return v;
+}
+//! \endcond
+
+/*!
+  \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;
+}
+
+//! \cond
+template<> inline
+cmat to_cmat(const cmat& m)
+{
+  return m;
+}
+//! \endcond
+
+/*!
+  \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); }
+
+//! 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>(::rint, x); }
+//! Round to nearest integer
+inline mat round(const mat &x) { return apply_function<double>(::rint, 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: library/bdm/base/itpp/base/svec.cpp
===================================================================
--- library/bdm/base/itpp/base/svec.cpp (revision 812)
+++ library/bdm/base/itpp/base/svec.cpp (revision 812)
@@ -0,0 +1,83 @@
+/*!
+ * \file
+ * \brief Sparse Vector Class implementation
+ * \author Tony Ottosson and Tobias Ringstrom
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/svec.h>
+
+//! \cond
+
+namespace itpp
+{
+
+// ---------------------------------------------------------------------
+// Instantiations
+// ---------------------------------------------------------------------
+
+template class Sparse_Vec<int>;
+template class Sparse_Vec<double>;
+template class Sparse_Vec<std::complex<double> >;
+
+template sparse_ivec operator+(const sparse_ivec &, const sparse_ivec &);
+template sparse_vec operator+(const sparse_vec &, const sparse_vec &);
+template sparse_cvec operator+(const sparse_cvec &, const sparse_cvec &);
+
+template int operator*(const sparse_ivec &, const sparse_ivec &);
+template double operator*(const sparse_vec &, const sparse_vec &);
+template std::complex<double> operator*(const sparse_cvec &, const sparse_cvec &);
+
+template int operator*(const sparse_ivec &, const ivec &);
+template double operator*(const sparse_vec &, const vec &);
+template std::complex<double> operator*(const sparse_cvec &, const cvec &);
+
+template int operator*(const ivec &, const sparse_ivec &);
+template double operator*(const vec &, const sparse_vec &);
+template std::complex<double> operator*(const cvec &, const sparse_cvec &);
+
+template sparse_ivec elem_mult(const sparse_ivec &, const sparse_ivec &);
+template sparse_vec elem_mult(const sparse_vec &, const sparse_vec &);
+template sparse_cvec elem_mult(const sparse_cvec &, const sparse_cvec &);
+
+template ivec elem_mult(const sparse_ivec &, const ivec &);
+template vec elem_mult(const sparse_vec &, const vec &);
+template cvec elem_mult(const sparse_cvec &, const cvec &);
+
+template sparse_ivec elem_mult_s(const sparse_ivec &, const ivec &);
+template sparse_vec elem_mult_s(const sparse_vec &, const vec &);
+template sparse_cvec elem_mult_s(const sparse_cvec &, const cvec &);
+
+template ivec elem_mult(const ivec &, const sparse_ivec &);
+template vec elem_mult(const vec &, const sparse_vec &);
+template cvec elem_mult(const cvec &, const sparse_cvec &);
+
+template sparse_ivec elem_mult_s(const ivec &, const sparse_ivec &);
+template sparse_vec elem_mult_s(const vec &, const sparse_vec &);
+template sparse_cvec elem_mult_s(const cvec &, const sparse_cvec &);
+
+} // namespace itpp
+
+//! \endcond
Index: library/bdm/base/itpp/base/circular_buffer.h
===================================================================
--- library/bdm/base/itpp/base/circular_buffer.h (revision 812)
+++ library/bdm/base/itpp/base/circular_buffer.h (revision 812)
@@ -0,0 +1,602 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/matfunc.h
===================================================================
--- library/bdm/base/itpp/base/matfunc.h (revision 812)
+++ library/bdm/base/itpp/base/matfunc.h (revision 812)
@@ -0,0 +1,1022 @@
+/*!
+ * \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-2010  (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>
+#include <itpp/base/algebra/inv.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: library/bdm/base/itpp/base/itassert.h
===================================================================
--- library/bdm/base/itpp/base/itassert.h (revision 812)
+++ library/bdm/base/itpp/base/itassert.h (revision 812)
@@ -0,0 +1,186 @@
+/*!
+ * \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-2010  (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
+
+#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 preferred 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 without \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: library/bdm/base/itpp/base/smat.cpp
===================================================================
--- library/bdm/base/itpp/base/smat.cpp (revision 812)
+++ library/bdm/base/itpp/base/smat.cpp (revision 812)
@@ -0,0 +1,83 @@
+/*!
+ * \file
+ * \brief Sparse Matrix Class implementation
+ * \author Tony Ottosson and Tobias Ringstrom
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/smat.h>
+
+//! \cond
+
+namespace itpp
+{
+
+// ---------------------------------------------------------------------
+// Instantiations
+// ---------------------------------------------------------------------
+
+template class Sparse_Mat<int>;
+template class Sparse_Mat<double>;
+template class Sparse_Mat<std::complex<double> >;
+
+template sparse_imat operator+(const sparse_imat &, const sparse_imat &);
+template sparse_mat operator+(const sparse_mat &, const sparse_mat &);
+template sparse_cmat operator+(const sparse_cmat &, const sparse_cmat &);
+
+template sparse_imat operator*(const sparse_imat &, const sparse_imat &);
+template sparse_mat operator*(const sparse_mat &, const sparse_mat &);
+template sparse_cmat operator*(const sparse_cmat &, const sparse_cmat &);
+
+template ivec operator*(const ivec &, const sparse_imat &);
+template vec operator*(const vec &, const sparse_mat &);
+template cvec operator*(const cvec &, const sparse_cmat &);
+
+template ivec operator*(const sparse_imat &, const ivec &);
+template vec operator*(const sparse_mat &, const vec &);
+template cvec operator*(const sparse_cmat &, const cvec &);
+
+template imat trans_mult(const sparse_imat &);
+template mat trans_mult(const sparse_mat &);
+template cmat trans_mult(const sparse_cmat &);
+
+template sparse_imat trans_mult_s(const sparse_imat &);
+template sparse_mat trans_mult_s(const sparse_mat &);
+template sparse_cmat trans_mult_s(const sparse_cmat &);
+
+template sparse_imat trans_mult(const sparse_imat &, const sparse_imat &);
+template sparse_mat trans_mult(const sparse_mat &, const sparse_mat &);
+template sparse_cmat trans_mult(const sparse_cmat &, const sparse_cmat &);
+
+template ivec trans_mult(const sparse_imat &, const ivec &);
+template vec trans_mult(const sparse_mat &, const vec &);
+template cvec trans_mult(const sparse_cmat &, const cvec &);
+
+template sparse_imat mult_trans(const sparse_imat &, const sparse_imat &);
+template sparse_mat mult_trans(const sparse_mat &, const sparse_mat &);
+template sparse_cmat mult_trans(const sparse_cmat &, const sparse_cmat &);
+
+} // namespace itpp
+
+//! \endcond
Index: library/bdm/base/itpp/base/ittypes.h
===================================================================
--- library/bdm/base/itpp/base/ittypes.h (revision 812)
+++ library/bdm/base/itpp/base/ittypes.h (revision 812)
@@ -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-2010  (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 architectures
+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: library/bdm/base/itpp/base/binfile.cpp
===================================================================
--- library/bdm/base/itpp/base/binfile.cpp (revision 812)
+++ library/bdm/base/itpp/base/binfile.cpp (revision 812)
@@ -0,0 +1,477 @@
+/*!
+ * \file
+ * \brief Binary file formats implementations
+ * \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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/binfile.h>
+#include <itpp/base/math/misc.h>
+#include <cstring>
+
+
+using std::ofstream;
+using std::ifstream;
+using std::fstream;
+using std::ios;
+
+
+namespace itpp
+{
+
+//! Read binary data and optionally switch endianness
+template<typename T1, typename T2> inline
+void read_endian(T1& st, T2& data, bool switch_endian = false)
+{
+  int bytes = sizeof(T2);
+  char *c = reinterpret_cast<char *>(&data);
+  if (!switch_endian)
+    st.read(c, bytes);
+  else
+    for (int i = bytes - 1; i >= 0; i--)
+      st.get(c[i]);
+}
+
+//! Write binary data and optionally switch endianness
+template<typename T1, typename T2> inline
+void write_endian(T1& st, T2 data, bool switch_endian = false)
+{
+  int bytes = sizeof(T2);
+  char *c = reinterpret_cast<char *>(&data);
+  if (!switch_endian)
+    st.write(c, bytes);
+  else
+    for (int i = bytes - 1; i >= 0; i--)
+      st.put(c[i]);
+}
+
+// ----------------------------------------------------------------------
+
+bool exist(const std::string& name)
+{
+  bool file_exists = false;
+  ifstream file(name.c_str(), ios::in);
+  if (file.is_open()) {
+    file_exists = true;
+  }
+  file.close();
+  return file_exists;
+}
+
+// ----------------------------------------------------------------------
+// bfstream_base
+// ----------------------------------------------------------------------
+
+bfstream_base::bfstream_base(endian e):
+    switch_endianity(false),
+    native_endianity(check_big_endianness() ? b_endian : l_endian)
+{
+  if (native_endianity != e)
+    switch_endianity = true;
+}
+
+// ----------------------------------------------------------------------
+// bofstream
+// ----------------------------------------------------------------------
+
+bofstream::bofstream(const std::string& name, endian e) :
+    bfstream_base(e), ofstream(name.c_str(), ios::out | ios::binary) {}
+
+bofstream::bofstream() : bfstream_base(), ofstream() {}
+
+void bofstream::open(const std::string& name, endian e)
+{
+  if (native_endianity != e)
+    switch_endianity = true;
+  else
+    switch_endianity = false;
+  ofstream::open(name.c_str(), ios::out | ios::binary);
+}
+
+bofstream& bofstream::operator<<(char a)
+{
+  put(a);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(unsigned char a)
+{
+  put(static_cast<char>(a));
+  return *this;
+}
+
+bofstream& bofstream::operator<<(int16_t a)
+{
+  write_endian<bofstream, int16_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(uint16_t a)
+{
+  write_endian<bofstream, uint16_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(int32_t a)
+{
+  write_endian<bofstream, int32_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(uint32_t a)
+{
+  write_endian<bofstream, uint32_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(int64_t a)
+{
+  write_endian<bofstream, int64_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(uint64_t a)
+{
+  write_endian<bofstream, uint64_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(float a)
+{
+  write_endian<bofstream, float>(*this, a, switch_endianity);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(double a)
+{
+  write_endian<bofstream, double>(*this, a, switch_endianity);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(const char *a)
+{
+  write(a, strlen(a) + 1);
+  return *this;
+}
+
+bofstream& bofstream::operator<<(const std::string& a)
+{
+  write(a.c_str(), a.size() + 1);
+  return *this;
+}
+
+// ----------------------------------------------------------------------
+// bifstream
+// ----------------------------------------------------------------------
+
+bifstream::bifstream(const std::string& name, endian e) :
+    bfstream_base(e), ifstream(name.c_str(), ios::in | ios::binary) {}
+
+bifstream::bifstream() : bfstream_base(), ifstream() {}
+
+void bifstream::open(const std::string& name, endian e)
+{
+  if (native_endianity != e)
+    switch_endianity = true;
+  else
+    switch_endianity = false;
+  ifstream::open(name.c_str(), ios::in | ios::binary);
+}
+
+int bifstream::length() // in bytes
+{
+  std::streampos pos1, len;
+  pos1 = tellg();
+  seekg(0, ios::end);
+  len = tellg();
+  seekg(pos1);
+  return len;
+}
+
+bifstream& bifstream::operator>>(char& a)
+{
+  get(a);
+  return *this;
+}
+
+bifstream& bifstream::operator>>(unsigned char& a)
+{
+  char tmp;
+  get(tmp);
+  a = tmp;
+  return *this;
+}
+
+bifstream& bifstream::operator>>(int16_t& a)
+{
+  read_endian<bifstream, int16_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bifstream& bifstream::operator>>(uint16_t& a)
+{
+  read_endian<bifstream, uint16_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bifstream& bifstream::operator>>(int32_t& a)
+{
+  read_endian<bifstream, int32_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bifstream& bifstream::operator>>(uint32_t& a)
+{
+  read_endian<bifstream, uint32_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bifstream& bifstream::operator>>(int64_t& a)
+{
+  read_endian<bifstream, int64_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bifstream& bifstream::operator>>(uint64_t& a)
+{
+  read_endian<bifstream, uint64_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bifstream& bifstream::operator>>(float& a)
+{
+  read_endian<bifstream, float>(*this, a, switch_endianity);
+  return *this;
+}
+
+bifstream& bifstream::operator>>(double& a)
+{
+  read_endian<bifstream, double>(*this, a, switch_endianity);
+  return *this;
+}
+
+bifstream& bifstream::operator>>(char *a)
+{
+  getline(a, '\0');
+  return *this;
+}
+
+bifstream& bifstream::operator>>(std::string& a)
+{
+  std::getline(*this, a, '\0');
+  return *this;
+}
+
+// ----------------------------------------------------------------------
+// bfstream
+// ----------------------------------------------------------------------
+
+bfstream::bfstream(const std::string& name, endian e) :
+    bfstream_base(e), fstream(name.c_str(), ios::in | ios::out | ios::binary)
+{}
+
+bfstream::bfstream() : bfstream_base(), fstream() {}
+
+void bfstream::open(const std::string& name, bool trnc, endian e)
+{
+  if (native_endianity != e)
+    switch_endianity = true;
+  else
+    switch_endianity = false;
+
+  if (trnc)
+    fstream::open(name.c_str(), ios::in | ios::out | ios::binary
+                  | ios::trunc);
+  else
+    fstream::open(name.c_str(), ios::in | ios::out | ios::binary);
+}
+
+void bfstream::open_readonly(const std::string& name, endian e)
+{
+  if (native_endianity != e)
+    switch_endianity = true;
+  else
+    switch_endianity = false;
+  fstream::open(name.c_str(), ios::in | ios::binary);
+}
+
+int bfstream::length() // in bytes
+{
+  std::streampos pos1, len;
+  pos1 = tellg();
+  seekg(0, ios::end);
+  len = tellg();
+  seekg(pos1);
+  return len;
+}
+
+bfstream& bfstream::operator<<(char a)
+{
+  put(a);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(unsigned char a)
+{
+  put(static_cast<char>(a));
+  return *this;
+}
+
+bfstream& bfstream::operator<<(int16_t a)
+{
+  write_endian<bfstream, int16_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(uint16_t a)
+{
+  write_endian<bfstream, uint16_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(int32_t a)
+{
+  write_endian<bfstream, int32_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(uint32_t a)
+{
+  write_endian<bfstream, uint32_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(int64_t a)
+{
+  write_endian<bfstream, int64_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(uint64_t a)
+{
+  write_endian<bfstream, uint64_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(float a)
+{
+  write_endian<bfstream, float>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(double a)
+{
+  write_endian<bfstream, double>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(const char *a)
+{
+  write(a, strlen(a) + 1);
+  return *this;
+}
+
+bfstream& bfstream::operator<<(const std::string& a)
+{
+  write(a.c_str(), a.size() + 1);
+  return *this;
+}
+
+
+bfstream& bfstream::operator>>(char& a)
+{
+  get(a);
+  return *this;
+}
+
+bfstream& bfstream::operator>>(unsigned char& a)
+{
+  char tmp;
+  get(tmp);
+  a = tmp;
+  return *this;
+}
+
+bfstream& bfstream::operator>>(int16_t& a)
+{
+  read_endian<bfstream, int16_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator>>(uint16_t& a)
+{
+  read_endian<bfstream, uint16_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator>>(int32_t& a)
+{
+  read_endian<bfstream, int32_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator>>(uint32_t& a)
+{
+  read_endian<bfstream, uint32_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator>>(int64_t& a)
+{
+  read_endian<bfstream, int64_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator>>(uint64_t& a)
+{
+  read_endian<bfstream, uint64_t>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator>>(float& a)
+{
+  read_endian<bfstream, float>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator>>(double& a)
+{
+  read_endian<bfstream, double>(*this, a, switch_endianity);
+  return *this;
+}
+
+bfstream& bfstream::operator>>(char *a)
+{
+  getline(a, '\0');
+  return *this;
+}
+
+bfstream& bfstream::operator>>(std::string& a)
+{
+  std::getline(*this, a, '\0');
+  return *this;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/fastmath.h
===================================================================
--- library/bdm/base/itpp/base/fastmath.h (revision 812)
+++ library/bdm/base/itpp/base/fastmath.h (revision 812)
@@ -0,0 +1,55 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/algebra/lapack.h
===================================================================
--- library/bdm/base/itpp/base/algebra/lapack.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/lapack.h (revision 812)
@@ -0,0 +1,254 @@
+/*!
+ * \file
+ * \brief Lapack header functions. For internal use only.
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 LAPACK_H
+#define LAPACK_H
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#include <complex>
+
+// Note: HAVE_MKL and HAVE_ACML are hard-defined in <itpp/config_msvc.h>
+#if defined(_MSC_VER) && (defined(HAVE_ACML) || defined(HAVE_MKL))
+#  define dgetrf_ DGETRF
+#  define zgetrf_ ZGETRF
+#  define dgetri_ DGETRI
+#  define zgetri_ ZGETRI
+#  define dgesvd_ DGESVD
+#  define zgesvd_ ZGESVD
+#  define dsyev_  DSYEV
+#  define zheev_  ZHEEV
+#  define dgeev_  DGEEV
+#  define zgeev_  ZGEEV
+#  define dpotrf_ DPOTRF
+#  define zpotrf_ ZPOTRF
+#  define dgeqrf_ DGEQRF
+#  define zgeqrf_ ZGEQRF
+#  define dgeqp3_ DGEQP3
+#  define zgeqp3_ ZGEQP3
+#  define dorgqr_ DORGQR
+#  define zungqr_ ZUNGQR
+#  define dormqr_ DORMQR
+#  define zunmqr_ ZUNMQR
+#  define dgesv_  DGESV
+#  define zgesv_  ZGESV
+#  define dposv_  DPOSV
+#  define zposv_  ZPOSV
+#  define dtrtrs_ DTRTRS
+#  define ztrtrs_ ZTRTRS
+#  define dgels_  DGELS
+#  define zgels_  ZGELS
+#  define dgees_  DGEES
+#  define zgees_  ZGEES
+#endif // #if defined(_MSC_VER) && (defined(HAVE_ACML) || defined(HAVE_MKL))
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif /* __cplusplus */
+  // Exists in ATLAS
+  /* LU factorization
+   * a is of size m*n and with lda rows.
+   * ipiv is the permutation vector of rows. Row i should be replaced by row
+   * ipiv(i).
+   * info=0 if OK. info=-i if ith value is illegal. info=i factorization OK
+   * but the system is singular if solved.
+   */
+  void dgetrf_(int *m, int *n, double *a, int *lda, int *ipiv, int *info);
+  void zgetrf_(int *m, int *n, std::complex<double> *a, int *lda, int *ipiv,
+               int *info);
+
+  // In ATLAS
+  /* Inverting a matrix of an LU-factored general matrix (first call xGETRF)
+   * a is of square size n*n with lda rows containing the factorization as
+   * returned by xGETRF
+   * ipiv is vector as returned by xGETRF
+   * lwork >= n
+   * output: a is overwritten by the inverse
+   * info=0 if OK. info=-i if ith parameter is illegal. info=i the ith
+   * diagonal element = 0 and U is singular.
+   */
+  void dgetri_(int *n, double *a, int *lda, int *ipiv, double *work, int *lwork,
+               int *info);
+  void zgetri_(int *n, std::complex<double> *a, int *lda, int *ipiv,
+               std::complex<double> *work, int *lwork, int *info);
+
+  /* SVD of a general rectangular matrix A = U S V^H
+     a is of size m*n and with lda rows.
+     Output: s with sorted singular values (vector)
+     u, and vt (for U and V^H). U is m*m, and V^H is n*n
+     jobu='A','S','O','N'. Different versions. 'A' = all columns of U
+     calculated and returned in u.
+     jobvt='A','S','O','N'. Different versions. 'A' = all columns of V^H
+     calculated and returned in vt.
+     ldu = no rows in U
+     ldvt = no rows in V^H
+     info = 0 successful, = -i ith parameter is illegal, = i did not converge
+
+     work is a workspace vector of size lwork.
+     lwork >= max(3*min(m,n)+max(m,n), 5*min(m,n)) for double
+     lwork >= 2*min(m,n)+max(m,n) for std::complex<double>
+     Good performance. Make lwork larger!
+     rwork is a workspace array for complex version. Size max(1, 5*min(m,n)).
+   */
+  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);
+  void zgesvd_(char *jobu, char *jobvt, int *m, int *n, std::complex<double> *a,
+               int *lda, double *s, std::complex<double> *u, int *ldu,
+               std::complex<double> *vt, int *ldvt, std::complex<double> *work,
+               int *lwork, double *rwork, int *info);
+
+  /* Eigenvalues and eigenvectors of a symmetric/hermitian matrix A */
+  void dsyev_(char *jobz, char *uplo, int *n, double *a, int *lda, double *w,
+              double *work, int *lwork, int *info);
+  void zheev_(char *jobz, char *uplo, int *n, std::complex<double> *a, int *lda,
+              double *w, std::complex<double> *work, int *lwork, double *rwork,
+              int *info);
+
+  /* Eigenvalues and eigenvectors of a general matrix A */
+  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);
+  void zgeev_(char *jobvl, char *jobvr, int *n, std::complex<double> *a,
+              int *lda, std::complex<double> *w, std::complex<double> *vl,
+              int *ldvl, std::complex<double> *vr, int *ldvr,
+              std::complex<double> *work, int *lwork, double *rwork, int *info);
+
+  // In ATLAS
+  /* Cholesky factorization */
+  void dpotrf_(char *uplo, int *n, double *a, int *lda, int *info);
+  void zpotrf_(char *uplo, int *n, std::complex<double> *a, int *lda,
+               int *info);
+
+  /* QR factorization of a general matrix A  */
+  void dgeqrf_(int *m, int *n, double *a, int *lda, double *tau, double *work,
+               int *lwork, int *info);
+  void zgeqrf_(int *m, int *n, std::complex<double> *a, int *lda,
+               std::complex<double> *tau, std::complex<double> *work,
+               int *lwork, int *info);
+
+  /* QR factorization of a general matrix A with pivoting */
+  void dgeqp3_(int *m, int *n, double *a, int *lda, int *jpvt, double *tau,
+               double *work, int *lwork, int *info);
+  void zgeqp3_(int *m, int *n, std::complex<double> *a, int *lda, int *jpvt,
+               std::complex<double> *tau, std::complex<double> *work,
+               int *lwork, double *rwork, int *info);
+
+  /* Calculation of Q matrix from QR-factorization */
+  void dorgqr_(int *m, int *n, int *k, double *a, int *lda, double *tau,
+               double *work, int *lwork, int *info);
+  void zungqr_(int *m, int *n, int *k, std::complex<double> *a, int *lda,
+               std::complex<double> *tau, std::complex<double> *work,
+               int *lwork, int *info);
+
+  /*
+   * Multiplies a real matrix by the orthogonal matix Q of the QR
+   * factorization formed by dgeqp3_()
+   */
+  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);
+  /*
+   * Multiplies a complex matrix by the unitary matix Q of the QR
+   * factorization formed by zgeqp3_()
+   */
+  void zunmqr_(char *side, char *trans, int *m, int *n, int *k,
+               std::complex<double> *a, int *lda, std::complex<double> *tau,
+               std::complex<double> *c, int *ldc, std::complex<double> *work,
+               int *lwork, int *info);
+
+  // In ATLAS
+  /*
+   * Solves a system on linear equations, Ax=b, with a square matrix A,
+   * Using LU-factorization
+   */
+  void dgesv_(int *n, int *nrhs, double *a, int *lda, int *ipiv, double *b,
+              int *ldb, int *info);
+  void zgesv_(int *n, int *nrhs, std::complex<double> *a, int *lda, int *ipiv,
+              std::complex<double> *b, int *ldb, int *info);
+
+  // In ATLAS
+  /*
+   * Solves a system on linear equations, Ax=b, with a square
+   * symmetric/hermitian positive definite matrix A, using
+   * Cholesky-factorization
+   */
+  void dposv_(char *uplo, int *n, int *nrhs, double *a, int *lda, double *b,
+              int *ldb, int *info);
+  void zposv_(char *uplo, int *n, int *nrhs, std::complex<double> *a, int *lda,
+              std::complex<double> *b, int *ldb, int *info);
+
+  /*
+   * Solves a system of linear equations with a triangular matrix with
+   * multiple right-hand sides
+   */
+  void dtrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs,
+               double *a, int *lda, double *b, int *ldb, int *info);
+  void ztrtrs_(char *uplo, char *trans, char *diag, int *n, int *nrhs,
+               std::complex<double> *a, int *lda, std::complex<double> *b,
+               int *ldb, int *info);
+
+  /*
+   * Solves a linear over/underdetermined system using QR or LQ
+   * factorization. Assumes a full rank matrix
+   */
+  void dgels_(char *trans, int *m, int *n, int *nrhs, double *a, int *lda,
+              double *b, int *ldb, double *work, int *lwork, int *info);
+  void zgels_(char *trans, int *m, int *n, int *nrhs, std::complex<double> *a,
+              int *lda, std::complex<double> *b, int *ldb,
+              std::complex<double> *work, int *lwork, int *info);
+
+  /*
+   * Compute for an N-by-N real nonsymmetric matrix A, the eigenvalues,
+   * the real Schur form T, and, optionally, the matrix of Schur vectors Z
+   */
+  void dgees_(char *jobvs, char *sort, int* 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);
+
+  /*
+   * Compute for an N-by-N complex nonsymmetric matrix A, the eigenvalues,
+   * the Schur form T, and, optionally, the matrix of Schur vectors Z
+   */
+  void zgees_(char *jobvs, char *sort, int* select, int *n,
+              std::complex<double> *a, int *lda, int *sdim,
+              std::complex<double> *w, std::complex<double> *vs, int *ldvs,
+              std::complex<double> *work, int *lwork, double *rwork,
+              int *bwork, int *info);
+
+#ifdef __cplusplus
+} // extern C
+#endif /* __cplusplus */
+
+#endif // #ifndef LAPACK_H
Index: library/bdm/base/itpp/base/algebra/svd.h
===================================================================
--- library/bdm/base/itpp/base/algebra/svd.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/svd.h (revision 812)
@@ -0,0 +1,185 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/algebra/inv.h
===================================================================
--- library/bdm/base/itpp/base/algebra/inv.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/inv.h (revision 812)
@@ -0,0 +1,87 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/algebra/det.cpp
===================================================================
--- library/bdm/base/itpp/base/algebra/det.cpp (revision 812)
+++ library/bdm/base/itpp/base/algebra/det.cpp (revision 812)
@@ -0,0 +1,102 @@
+/*!
+ * \file
+ * \brief Implementation of determinant calculations
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/algebra/det.h>
+#include <itpp/base/algebra/lu.h>
+
+
+namespace itpp
+{
+
+
+/* Determinant of square matrix.
+   Calculate determinant of inmatrix (Uses LU-factorisation)
+   (See Theorem 3.2.1 p. 97 in Golub & van Loan, "Matrix Computations").
+
+   det(X) = det(P')*det(L)*det(U) = det(P')*1*prod(diag(U))
+*/
+double det(const mat &X)
+{
+  it_assert_debug(X.rows() == X.cols(), "det : Only square matrices");
+
+  mat L, U;
+  ivec p;
+  double s = 1.0;
+  int i;
+
+  lu(X, L, U, p); // calculate LU-factorisation
+
+  double temp = U(0, 0);
+  for (i = 1;i < X.rows();i++) {
+    temp *= U(i, i);
+  }
+
+  // Calculate det(P'). Equal to (-1)^(no row changes)
+  for (i = 0; i < p.size(); i++)
+    if (i != p(i))
+      s *= -1.0;
+
+  return temp*s;
+}
+
+
+/* Determinant of complex square matrix.
+   Calculate determinant of inmatrix (Uses LU-factorisation)
+   (See Theorem 3.2.1 p. 97 in Golub & van Loan, "Matrix Computations").
+
+   det(X) = det(P')*det(L)*det(U) = det(P')*1*prod(diag(U))
+
+   Needs LU-factorization of complex matrices (LAPACK)
+*/
+std::complex<double> det(const cmat &X)
+{
+  it_assert_debug(X.rows() == X.cols(), "det : Only square matrices");
+
+  int i;
+  cmat L, U;
+  ivec p;
+  double s = 1.0;
+
+  lu(X, L, U, p); // calculate LU-factorisation
+
+  std::complex<double> temp = U(0, 0);
+  for (i = 1;i < X.rows();i++) {
+    temp *= U(i, i);
+  }
+
+  // Calculate det(P'). Equal to (-1)^(no row changes)
+  for (i = 0; i < p.size(); i++)
+    if (i != p(i))
+      s *= -1.0;
+
+  return temp*s;
+}
+
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/algebra/lu.cpp
===================================================================
--- library/bdm/base/itpp/base/algebra/lu.cpp (revision 812)
+++ library/bdm/base/itpp/base/algebra/lu.cpp (revision 812)
@@ -0,0 +1,175 @@
+/*!
+ * \file
+ * \brief Implementation of LU factorisation functions.
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#if defined(HAVE_LAPACK)
+#  include <itpp/base/algebra/lapack.h>
+#endif
+
+#include <itpp/base/algebra/lu.h>
+#include <itpp/base/specmat.h>
+
+
+namespace itpp
+{
+
+#if defined(HAVE_LAPACK)
+
+bool lu(const mat &X, mat &L, mat &U, ivec &p)
+{
+  it_assert_debug(X.rows() == X.cols(), "lu: matrix is not quadratic");
+  //int m, n, lda, info;
+  //m = n = lda = X.rows();
+  int m = X.rows(), info;
+
+  mat A(X);
+  L.set_size(m, m, false);
+  U.set_size(m, m, false);
+  p.set_size(m, false);
+
+  dgetrf_(&m, &m, A._data(), &m, p._data(), &info);
+
+  for (int i = 0; i < m; i++) {
+    for (int j = i; j < m; j++) {
+      if (i == j) { // diagonal
+        L(i, j) = 1;
+        U(i, j) = A(i, j);
+      }
+      else { // upper and lower triangular parts
+        L(i, j) = U(j, i) = 0;
+        L(j, i) = A(j, i);
+        U(i, j) = A(i, j);
+      }
+    }
+  }
+
+  p = p - 1; // Fortran counts from 1
+
+  return (info == 0);
+}
+
+// Slower than not using LAPACK when matrix size smaller than approx 20.
+bool lu(const cmat &X, cmat &L, cmat &U, ivec &p)
+{
+  it_assert_debug(X.rows() == X.cols(), "lu: matrix is not quadratic");
+  //int m, n, lda, info;
+  //m = n = lda = X.rows();
+  int m = X.rows(), info;
+
+  cmat A(X);
+  L.set_size(m, m, false);
+  U.set_size(m, m, false);
+  p.set_size(m, false);
+
+  zgetrf_(&m, &m, A._data(), &m, p._data(), &info);
+
+  for (int i = 0; i < m; i++) {
+    for (int j = i; j < m; j++) {
+      if (i == j) { // diagonal
+        L(i, j) = 1;
+        U(i, j) = A(i, j);
+      }
+      else { // upper and lower triangular parts
+        L(i, j) = U(j, i) = 0;
+        L(j, i) = A(j, i);
+        U(i, j) = A(i, j);
+      }
+    }
+  }
+
+  p = p - 1; // Fortran counts from 1
+
+  return (info == 0);
+}
+
+#else
+
+bool lu(const mat &X, mat &L, mat &U, ivec &p)
+{
+  it_error("LAPACK library is needed to use lu() function");
+  return false;
+}
+
+bool lu(const cmat &X, cmat &L, cmat &U, ivec &p)
+{
+  it_error("LAPACK library is needed to use lu() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+
+void interchange_permutations(vec &b, const ivec &p)
+{
+  it_assert(b.size() == p.size(), "interchange_permutations(): dimension mismatch");
+  double temp;
+
+  for (int k = 0; k < b.size(); k++) {
+    temp = b(k);
+    b(k) = b(p(k));
+    b(p(k)) = temp;
+  }
+}
+
+bmat permutation_matrix(const ivec &p)
+{
+  it_assert(p.size() > 0, "permutation_matrix(): vector must have nonzero size");
+  int n = p.size(), k;
+  bmat P, identity;
+  bvec row_k, row_pk;
+  identity = eye_b(n);
+
+
+  for (k = n - 1; k >= 0; k--) {
+    // swap rows k and p(k) in identity
+    row_k = identity.get_row(k);
+    row_pk = identity.get_row(p(k));
+    identity.set_row(k, row_pk);
+    identity.set_row(p(k), row_k);
+
+    if (k == n - 1) {
+      P = identity;
+    }
+    else {
+      P *= identity;
+    }
+
+    // swap back
+    identity.set_row(k, row_k);
+    identity.set_row(p(k), row_pk);
+  }
+  return P;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/algebra/cholesky.cpp
===================================================================
--- library/bdm/base/itpp/base/algebra/cholesky.cpp (revision 812)
+++ library/bdm/base/itpp/base/algebra/cholesky.cpp (revision 812)
@@ -0,0 +1,122 @@
+/*!
+ * \file
+ * \brief Implementation of Cholesky factorisation functions
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#if defined(HAVE_LAPACK)
+#  include <itpp/base/algebra/lapack.h>
+#endif
+
+#include <itpp/base/algebra/cholesky.h>
+
+
+namespace itpp
+{
+
+#if defined(HAVE_LAPACK)
+
+bool chol(const mat &X, mat &F)
+{
+
+  char uplo = 'U';
+  int n, lda, info;
+  n = lda = X.rows();
+
+  F = X; // input matrix is overwritten
+
+  dpotrf_(&uplo, &n, F._data(), &lda, &info);
+
+  // Set lower part to zero
+  for (int i = 0; i < n; i++)
+    for (int j = i + 1; j < n; j++)
+      F(j, i) = 0;
+
+  return (info == 0);
+}
+
+bool chol(const cmat &X, cmat &F)
+{
+  char uplo = 'U';
+  int n, lda, info;
+  n = lda = X.rows();
+
+  F = X; // input matrix is overwritten
+
+  zpotrf_(&uplo, &n, F._data(), &lda, &info);
+
+  // Set lower part to zero
+  for (int i = 0; i < n; i++)
+    for (int j = i + 1; j < n; j++)
+      F(j, i) = 0;
+
+  return (info == 0);
+}
+
+#else // HAVE_LAPACK
+
+bool chol(const mat &X, mat &F)
+{
+  it_error("LAPACK library is needed to use chol() function");
+  return false;
+}
+
+bool chol(const cmat &X, cmat &F)
+{
+
+  it_error("LAPACK library is needed to use chol() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+cmat chol(const cmat &X)
+{
+  cmat F;
+  if (!chol(X, F)) {
+    it_warning("cholesky factorization didn't succeed");
+  }
+
+  return F;
+}
+
+mat chol(const mat &X)
+{
+  mat F;
+  if (!chol(X, F)) {
+    it_warning("cholesky factorization didn't succeed");
+  }
+
+  return F;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/algebra/det.h
===================================================================
--- library/bdm/base/itpp/base/algebra/det.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/det.h (revision 812)
@@ -0,0 +1,71 @@
+/*!
+ * \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-2010  (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$ depending on the number of row permutations
+*/
+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$ depending on the number of row permutations
+*/
+std::complex<double> det(const cmat &X);
+
+
+} // namespace itpp
+
+#endif // #ifndef DET_H
Index: library/bdm/base/itpp/base/algebra/qr.cpp
===================================================================
--- library/bdm/base/itpp/base/algebra/qr.cpp (revision 812)
+++ library/bdm/base/itpp/base/algebra/qr.cpp (revision 812)
@@ -0,0 +1,270 @@
+/*!
+ * \file
+ * \brief Implementation of QR factorisation functions
+ * \author Tony Ottosson, Simon Wood and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#if defined(HAVE_LAPACK)
+#  include <itpp/base/algebra/lapack.h>
+#endif
+
+#include <itpp/base/algebra/qr.h>
+#include <itpp/base/specmat.h>
+
+
+namespace itpp
+{
+
+#if defined(HAVE_LAPACK)
+
+bool qr(const mat &A, mat &Q, mat &R)
+{
+  int info;
+  int m = A.rows();
+  int n = A.cols();
+  int lwork = n;
+  int k = std::min(m, n);
+  vec tau(k);
+  vec work(lwork);
+
+  R = A;
+
+  // perform workspace query for optimum lwork value
+  int lwork_tmp = -1;
+  dgeqrf_(&m, &n, R._data(), &m, tau._data(), work._data(), &lwork_tmp,
+          &info);
+  if (info == 0) {
+    lwork = static_cast<int>(work(0));
+    work.set_size(lwork, false);
+  }
+  dgeqrf_(&m, &n, R._data(), &m, tau._data(), work._data(), &lwork, &info);
+  Q = R;
+  Q.set_size(m, m, true);
+
+  // construct R
+  for (int i = 0; i < m; i++)
+    for (int j = 0; j < std::min(i, n); j++)
+      R(i, j) = 0;
+
+  // perform workspace query for optimum lwork value
+  lwork_tmp = -1;
+  dorgqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork_tmp,
+          &info);
+  if (info == 0) {
+    lwork = static_cast<int>(work(0));
+    work.set_size(lwork, false);
+  }
+  dorgqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork,
+          &info);
+
+  return (info == 0);
+}
+
+bool qr(const mat &A, mat &Q, mat &R, bmat &P)
+{
+  int info;
+  int m = A.rows();
+  int n = A.cols();
+  int lwork = n;
+  int k = std::min(m, n);
+  vec tau(k);
+  vec work(lwork);
+  ivec jpvt(n);
+  jpvt.zeros();
+
+  R = A;
+
+  // perform workspace query for optimum lwork value
+  int lwork_tmp = -1;
+  dgeqp3_(&m, &n, R._data(), &m, jpvt._data(), tau._data(), work._data(),
+          &lwork_tmp, &info);
+  if (info == 0) {
+    lwork = static_cast<int>(work(0));
+    work.set_size(lwork, false);
+  }
+  dgeqp3_(&m, &n, R._data(), &m, jpvt._data(), tau._data(), work._data(),
+          &lwork, &info);
+  Q = R;
+  Q.set_size(m, m, true);
+
+  // construct permutation matrix
+  P = zeros_b(n, n);
+  for (int j = 0; j < n; j++)
+    P(jpvt(j) - 1, j) = 1;
+
+  // construct R
+  for (int i = 0; i < m; i++)
+    for (int j = 0; j < std::min(i, n); j++)
+      R(i, j) = 0;
+
+  // perform workspace query for optimum lwork value
+  lwork_tmp = -1;
+  dorgqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork_tmp,
+          &info);
+  if (info == 0) {
+    lwork = static_cast<int>(work(0));
+    work.set_size(lwork, false);
+  }
+  dorgqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork,
+          &info);
+
+  return (info == 0);
+}
+
+
+
+bool qr(const cmat &A, cmat &Q, cmat &R)
+{
+  int info;
+  int m = A.rows();
+  int n = A.cols();
+  int lwork = n;
+  int k = std::min(m, n);
+  cvec tau(k);
+  cvec work(lwork);
+
+  R = A;
+
+  // perform workspace query for optimum lwork value
+  int lwork_tmp = -1;
+  zgeqrf_(&m, &n, R._data(), &m, tau._data(), work._data(), &lwork_tmp,
+          &info);
+  if (info == 0) {
+    lwork = static_cast<int>(real(work(0)));
+    work.set_size(lwork, false);
+  }
+  zgeqrf_(&m, &n, R._data(), &m, tau._data(), work._data(), &lwork, &info);
+
+  Q = R;
+  Q.set_size(m, m, true);
+
+  // construct R
+  for (int i = 0; i < m; i++)
+    for (int j = 0; j < std::min(i, n); j++)
+      R(i, j) = 0;
+
+  // perform workspace query for optimum lwork value
+  lwork_tmp = -1;
+  zungqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork_tmp,
+          &info);
+  if (info == 0) {
+    lwork = static_cast<int>(real(work(0)));
+    work.set_size(lwork, false);
+  }
+  zungqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork,
+          &info);
+
+  return (info == 0);
+}
+
+bool qr(const cmat &A, cmat &Q, cmat &R, bmat &P)
+{
+  int info;
+  int m = A.rows();
+  int n = A.cols();
+  int lwork = n;
+  int k = std::min(m, n);
+  cvec tau(k);
+  cvec work(lwork);
+  vec rwork(std::max(1, 2*n));
+  ivec jpvt(n);
+  jpvt.zeros();
+
+  R = A;
+
+  // perform workspace query for optimum lwork value
+  int lwork_tmp = -1;
+  zgeqp3_(&m, &n, R._data(), &m, jpvt._data(), tau._data(), work._data(),
+          &lwork_tmp, rwork._data(), &info);
+  if (info == 0) {
+    lwork = static_cast<int>(real(work(0)));
+    work.set_size(lwork, false);
+  }
+  zgeqp3_(&m, &n, R._data(), &m, jpvt._data(), tau._data(), work._data(),
+          &lwork, rwork._data(), &info);
+
+  Q = R;
+  Q.set_size(m, m, true);
+
+  // construct permutation matrix
+  P = zeros_b(n, n);
+  for (int j = 0; j < n; j++)
+    P(jpvt(j) - 1, j) = 1;
+
+  // construct R
+  for (int i = 0; i < m; i++)
+    for (int j = 0; j < std::min(i, n); j++)
+      R(i, j) = 0;
+
+  // perform workspace query for optimum lwork value
+  lwork_tmp = -1;
+  zungqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork_tmp,
+          &info);
+  if (info == 0) {
+    lwork = static_cast<int>(real(work(0)));
+    work.set_size(lwork, false);
+  }
+  zungqr_(&m, &m, &k, Q._data(), &m, tau._data(), work._data(), &lwork,
+          &info);
+
+  return (info == 0);
+}
+
+#else
+
+bool qr(const mat &A, mat &Q, mat &R)
+{
+  it_error("LAPACK library is needed to use qr() function");
+  return false;
+}
+
+bool qr(const mat &A, mat &Q, mat &R, bmat &P)
+{
+  it_error("LAPACK library is needed to use qr() function");
+  return false;
+}
+
+bool qr(const cmat &A, cmat &Q, cmat &R)
+{
+  it_error("LAPACK library is needed to use qr() function");
+  return false;
+}
+
+bool qr(const cmat &A, cmat &Q, cmat &R, bmat &P)
+{
+  it_error("LAPACK library is needed to use qr() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/algebra/schur.cpp
===================================================================
--- library/bdm/base/itpp/base/algebra/schur.cpp (revision 812)
+++ library/bdm/base/itpp/base/algebra/schur.cpp (revision 812)
@@ -0,0 +1,135 @@
+/*!
+ * \file
+ * \brief Schur decomposition functions
+ * \author Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#if defined(HAVE_LAPACK)
+#  include <itpp/base/algebra/lapack.h>
+#endif
+
+#include <itpp/base/algebra/schur.h>
+
+
+namespace itpp
+{
+
+#if defined(HAVE_LAPACK)
+
+bool schur(const mat &A, mat &U, mat &T)
+{
+  it_assert_debug(A.rows() == A.cols(), "schur(): Matrix is not square");
+
+  char jobvs = 'V';
+  char sort = 'N';
+  int info;
+  int n = A.rows();
+  int lda = n;
+  int ldvs = n;
+  int lwork = 3 * n; // This may be choosen better!
+  int sdim = 0;
+  vec wr(n);
+  vec wi(n);
+  vec work(lwork);
+
+  T.set_size(lda, n, false);
+  U.set_size(ldvs, n, false);
+
+  T = A; // The routine overwrites input matrix with eigenvectors
+
+  dgees_(&jobvs, &sort, 0, &n, T._data(), &lda, &sdim, wr._data(), wi._data(),
+         U._data(), &ldvs, work._data(), &lwork, 0, &info);
+
+  return (info == 0);
+}
+
+
+bool schur(const cmat &A, cmat &U, cmat &T)
+{
+  it_assert_debug(A.rows() == A.cols(), "schur(): Matrix is not square");
+
+  char jobvs = 'V';
+  char sort = 'N';
+  int info;
+  int n = A.rows();
+  int lda = n;
+  int ldvs = n;
+  int lwork = 2 * n; // This may be choosen better!
+  int sdim = 0;
+  vec rwork(n);
+  cvec w(n);
+  cvec work(lwork);
+
+  T.set_size(lda, n, false);
+  U.set_size(ldvs, n, false);
+
+  T = A; // The routine overwrites input matrix with eigenvectors
+
+  zgees_(&jobvs, &sort, 0, &n, T._data(), &lda, &sdim, w._data(), U._data(),
+         &ldvs, work._data(), &lwork, rwork._data(), 0, &info);
+
+  return (info == 0);
+}
+
+#else
+
+bool schur(const mat &A, mat &U, mat &T)
+{
+  it_error("LAPACK library is needed to use schur() function");
+  return false;
+}
+
+
+bool schur(const cmat &A, cmat &U, cmat &T)
+{
+  it_error("LAPACK library is needed to use schur() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+mat schur(const mat &A)
+{
+  mat U, T;
+  schur(A, U, T);
+  return T;
+}
+
+
+cmat schur(const cmat &A)
+{
+  cmat U, T;
+  schur(A, U, T);
+  return T;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/algebra/lu.h
===================================================================
--- library/bdm/base/itpp/base/algebra/lu.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/lu.h (revision 812)
@@ -0,0 +1,108 @@
+/*!
+ * \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-2010  (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 permutation matrix can be constructed using the
+  function
+  \code
+  bmat permutation_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 triangular, \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 permutation matrix can be constructed using the
+  function
+  \code
+  bmat permutation_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 triangular, \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 interchange 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: library/bdm/base/itpp/base/algebra/cholesky.h
===================================================================
--- library/bdm/base/itpp/base/algebra/cholesky.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/cholesky.h (revision 812)
@@ -0,0 +1,104 @@
+/*!
+ * \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-2010  (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 triangular \f$n \times n\f$ matrix.
+
+  Returns true if calculation 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 triangular \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 triangular \f$n \times n\f$ matrix.
+
+  Returns true if calculation 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 triangular \f$n \times n\f$ matrix.
+*/
+cmat chol(const cmat &X);
+
+//!@}
+
+} // namespace itpp
+
+#endif // #ifndef CHOLESKY_H
Index: library/bdm/base/itpp/base/algebra/ls_solve.cpp
===================================================================
--- library/bdm/base/itpp/base/algebra/ls_solve.cpp (revision 812)
+++ library/bdm/base/itpp/base/algebra/ls_solve.cpp (revision 812)
@@ -0,0 +1,867 @@
+/*!
+ * \file
+ * \brief Implementation 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-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#if defined(HAVE_LAPACK)
+#  include <itpp/base/algebra/lapack.h>
+#endif
+
+#include <itpp/base/algebra/ls_solve.h>
+
+
+namespace itpp
+{
+
+// ----------- ls_solve_chol -----------------------------------------------------------
+
+#if defined(HAVE_LAPACK)
+
+bool ls_solve_chol(const mat &A, const vec &b, vec &x)
+{
+  int n, lda, ldb, nrhs, info;
+  n = lda = ldb = A.rows();
+  nrhs = 1;
+  char uplo = 'U';
+
+  it_assert_debug(A.cols() == n, "ls_solve_chol: System-matrix is not square");
+  it_assert_debug(n == b.size(), "The number of rows in A must equal the length of b!");
+
+  ivec ipiv(n);
+  x = b;
+  mat Chol = A;
+
+  dposv_(&uplo, &n, &nrhs, Chol._data(), &lda, x._data(), &ldb, &info);
+
+  return (info == 0);
+}
+
+
+bool ls_solve_chol(const mat &A, const mat &B, mat &X)
+{
+  int n, lda, ldb, nrhs, info;
+  n = lda = ldb = A.rows();
+  nrhs = B.cols();
+  char uplo = 'U';
+
+  it_assert_debug(A.cols() == n, "ls_solve_chol: System-matrix is not square");
+  it_assert_debug(n == B.rows(), "The number of rows in A must equal the length of B!");
+
+  ivec ipiv(n);
+  X = B;
+  mat Chol = A;
+
+  dposv_(&uplo, &n, &nrhs, Chol._data(), &lda, X._data(), &ldb, &info);
+
+  return (info == 0);
+}
+
+bool ls_solve_chol(const cmat &A, const cvec &b, cvec &x)
+{
+  int n, lda, ldb, nrhs, info;
+  n = lda = ldb = A.rows();
+  nrhs = 1;
+  char uplo = 'U';
+
+  it_assert_debug(A.cols() == n, "ls_solve_chol: System-matrix is not square");
+  it_assert_debug(n == b.size(), "The number of rows in A must equal the length of b!");
+
+  ivec ipiv(n);
+  x = b;
+  cmat Chol = A;
+
+  zposv_(&uplo, &n, &nrhs, Chol._data(), &lda, x._data(), &ldb, &info);
+
+  return (info == 0);
+}
+
+bool ls_solve_chol(const cmat &A, const cmat &B, cmat &X)
+{
+  int n, lda, ldb, nrhs, info;
+  n = lda = ldb = A.rows();
+  nrhs = B.cols();
+  char uplo = 'U';
+
+  it_assert_debug(A.cols() == n, "ls_solve_chol: System-matrix is not square");
+  it_assert_debug(n == B.rows(), "The number of rows in A must equal the length of B!");
+
+  ivec ipiv(n);
+  X = B;
+  cmat Chol = A;
+
+  zposv_(&uplo, &n, &nrhs, Chol._data(), &lda, X._data(), &ldb, &info);
+
+  return (info == 0);
+}
+
+#else
+
+bool ls_solve_chol(const mat &A, const vec &b, vec &x)
+{
+  it_error("LAPACK library is needed to use ls_solve_chol() function");
+  return false;
+}
+
+bool ls_solve_chol(const mat &A, const mat &B, mat &X)
+{
+  it_error("LAPACK library is needed to use ls_solve_chol() function");
+  return false;
+}
+
+bool ls_solve_chol(const cmat &A, const cvec &b, cvec &x)
+{
+  it_error("LAPACK library is needed to use ls_solve_chol() function");
+  return false;
+}
+
+bool ls_solve_chol(const cmat &A, const cmat &B, cmat &X)
+{
+  it_error("LAPACK library is needed to use ls_solve_chol() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+vec ls_solve_chol(const mat &A, const vec &b)
+{
+  vec x;
+  bool info;
+  info = ls_solve_chol(A, b, x);
+  it_assert_debug(info, "ls_solve_chol: Failed solving the system");
+  return x;
+}
+
+mat ls_solve_chol(const mat &A, const mat &B)
+{
+  mat X;
+  bool info;
+  info = ls_solve_chol(A, B, X);
+  it_assert_debug(info, "ls_solve_chol: Failed solving the system");
+  return X;
+}
+
+cvec ls_solve_chol(const cmat &A, const cvec &b)
+{
+  cvec x;
+  bool info;
+  info = ls_solve_chol(A, b, x);
+  it_assert_debug(info, "ls_solve_chol: Failed solving the system");
+  return x;
+}
+
+cmat ls_solve_chol(const cmat &A, const cmat &B)
+{
+  cmat X;
+  bool info;
+  info = ls_solve_chol(A, B, X);
+  it_assert_debug(info, "ls_solve_chol: Failed solving the system");
+  return X;
+}
+
+
+// --------- ls_solve ---------------------------------------------------------------
+#if defined(HAVE_LAPACK)
+
+bool ls_solve(const mat &A, const vec &b, vec &x)
+{
+  int n, lda, ldb, nrhs, info;
+  n = lda = ldb = A.rows();
+  nrhs = 1;
+
+  it_assert_debug(A.cols() == n, "ls_solve: System-matrix is not square");
+  it_assert_debug(n == b.size(), "The number of rows in A must equal the length of b!");
+
+  ivec ipiv(n);
+  x = b;
+  mat LU = A;
+
+  dgesv_(&n, &nrhs, LU._data(), &lda, ipiv._data(), x._data(), &ldb, &info);
+
+  return (info == 0);
+}
+
+bool ls_solve(const mat &A, const mat &B, mat &X)
+{
+  int n, lda, ldb, nrhs, info;
+  n = lda = ldb = A.rows();
+  nrhs = B.cols();
+
+  it_assert_debug(A.cols() == n, "ls_solve: System-matrix is not square");
+  it_assert_debug(n == B.rows(), "The number of rows in A must equal the length of B!");
+
+  ivec ipiv(n);
+  X = B;
+  mat LU = A;
+
+  dgesv_(&n, &nrhs, LU._data(), &lda, ipiv._data(), X._data(), &ldb, &info);
+
+  return (info == 0);
+}
+
+bool ls_solve(const cmat &A, const cvec &b, cvec &x)
+{
+  int n, lda, ldb, nrhs, info;
+  n = lda = ldb = A.rows();
+  nrhs = 1;
+
+  it_assert_debug(A.cols() == n, "ls_solve: System-matrix is not square");
+  it_assert_debug(n == b.size(), "The number of rows in A must equal the length of b!");
+
+  ivec ipiv(n);
+  x = b;
+  cmat LU = A;
+
+  zgesv_(&n, &nrhs, LU._data(), &lda, ipiv._data(), x._data(), &ldb, &info);
+
+  return (info == 0);
+}
+
+bool ls_solve(const cmat &A, const cmat &B, cmat &X)
+{
+  int n, lda, ldb, nrhs, info;
+  n = lda = ldb = A.rows();
+  nrhs = B.cols();
+
+  it_assert_debug(A.cols() == n, "ls_solve: System-matrix is not square");
+  it_assert_debug(n == B.rows(), "The number of rows in A must equal the length of B!");
+
+  ivec ipiv(n);
+  X = B;
+  cmat LU = A;
+
+  zgesv_(&n, &nrhs, LU._data(), &lda, ipiv._data(), X._data(), &ldb, &info);
+
+  return (info == 0);
+}
+
+#else
+
+bool ls_solve(const mat &A, const vec &b, vec &x)
+{
+  it_error("LAPACK library is needed to use ls_solve() function");
+  return false;
+}
+
+bool ls_solve(const mat &A, const mat &B, mat &X)
+{
+  it_error("LAPACK library is needed to use ls_solve() function");
+  return false;
+}
+
+bool ls_solve(const cmat &A, const cvec &b, cvec &x)
+{
+  it_error("LAPACK library is needed to use ls_solve() function");
+  return false;
+}
+
+bool ls_solve(const cmat &A, const cmat &B, cmat &X)
+{
+  it_error("LAPACK library is needed to use ls_solve() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+vec ls_solve(const mat &A, const vec &b)
+{
+  vec x;
+  bool info;
+  info = ls_solve(A, b, x);
+  it_assert_debug(info, "ls_solve: Failed solving the system");
+  return x;
+}
+
+mat ls_solve(const mat &A, const mat &B)
+{
+  mat X;
+  bool info;
+  info = ls_solve(A, B, X);
+  it_assert_debug(info, "ls_solve: Failed solving the system");
+  return X;
+}
+
+cvec ls_solve(const cmat &A, const cvec &b)
+{
+  cvec x;
+  bool info;
+  info = ls_solve(A, b, x);
+  it_assert_debug(info, "ls_solve: Failed solving the system");
+  return x;
+}
+
+cmat ls_solve(const cmat &A, const cmat &B)
+{
+  cmat X;
+  bool info;
+  info = ls_solve(A, B, X);
+  it_assert_debug(info, "ls_solve: Failed solving the system");
+  return X;
+}
+
+
+// ----------------- ls_solve_od ------------------------------------------------------------------
+#if defined(HAVE_LAPACK)
+
+bool ls_solve_od(const mat &A, const vec &b, vec &x)
+{
+  int m, n, lda, ldb, nrhs, lwork, info;
+  char trans = 'N';
+  m = lda = ldb = A.rows();
+  n = A.cols();
+  nrhs = 1;
+  lwork = n + std::max(m, nrhs);
+
+  it_assert_debug(m >= n, "The system is under-determined!");
+  it_assert_debug(m == b.size(), "The number of rows in A must equal the length of b!");
+
+  vec work(lwork);
+  x = b;
+  mat QR = A;
+
+  dgels_(&trans, &m, &n, &nrhs, QR._data(), &lda, x._data(), &ldb, work._data(), &lwork, &info);
+  x.set_size(n, true);
+
+  return (info == 0);
+}
+
+bool ls_solve_od(const mat &A, const mat &B, mat &X)
+{
+  int m, n, lda, ldb, nrhs, lwork, info;
+  char trans = 'N';
+  m = lda = ldb = A.rows();
+  n = A.cols();
+  nrhs = B.cols();
+  lwork = n + std::max(m, nrhs);
+
+  it_assert_debug(m >= n, "The system is under-determined!");
+  it_assert_debug(m == B.rows(), "The number of rows in A must equal the length of b!");
+
+  vec work(lwork);
+  X = B;
+  mat QR = A;
+
+  dgels_(&trans, &m, &n, &nrhs, QR._data(), &lda, X._data(), &ldb, work._data(), &lwork, &info);
+  X.set_size(n, nrhs, true);
+
+  return (info == 0);
+}
+
+bool ls_solve_od(const cmat &A, const cvec &b, cvec &x)
+{
+  int m, n, lda, ldb, nrhs, lwork, info;
+  char trans = 'N';
+  m = lda = ldb = A.rows();
+  n = A.cols();
+  nrhs = 1;
+  lwork = n + std::max(m, nrhs);
+
+  it_assert_debug(m >= n, "The system is under-determined!");
+  it_assert_debug(m == b.size(), "The number of rows in A must equal the length of b!");
+
+  cvec work(lwork);
+  x = b;
+  cmat QR = A;
+
+  zgels_(&trans, &m, &n, &nrhs, QR._data(), &lda, x._data(), &ldb, work._data(), &lwork, &info);
+  x.set_size(n, true);
+
+  return (info == 0);
+}
+
+bool ls_solve_od(const cmat &A, const cmat &B, cmat &X)
+{
+  int m, n, lda, ldb, nrhs, lwork, info;
+  char trans = 'N';
+  m = lda = ldb = A.rows();
+  n = A.cols();
+  nrhs = B.cols();
+  lwork = n + std::max(m, nrhs);
+
+  it_assert_debug(m >= n, "The system is under-determined!");
+  it_assert_debug(m == B.rows(), "The number of rows in A must equal the length of b!");
+
+  cvec work(lwork);
+  X = B;
+  cmat QR = A;
+
+  zgels_(&trans, &m, &n, &nrhs, QR._data(), &lda, X._data(), &ldb, work._data(), &lwork, &info);
+  X.set_size(n, nrhs, true);
+
+  return (info == 0);
+}
+
+#else
+
+bool ls_solve_od(const mat &A, const vec &b, vec &x)
+{
+  it_error("LAPACK library is needed to use ls_solve_od() function");
+  return false;
+}
+
+bool ls_solve_od(const mat &A, const mat &B, mat &X)
+{
+  it_error("LAPACK library is needed to use ls_solve_od() function");
+  return false;
+}
+
+bool ls_solve_od(const cmat &A, const cvec &b, cvec &x)
+{
+  it_error("LAPACK library is needed to use ls_solve_od() function");
+  return false;
+}
+
+bool ls_solve_od(const cmat &A, const cmat &B, cmat &X)
+{
+  it_error("LAPACK library is needed to use ls_solve_od() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+vec ls_solve_od(const mat &A, const vec &b)
+{
+  vec x;
+  bool info;
+  info = ls_solve_od(A, b, x);
+  it_assert_debug(info, "ls_solve_od: Failed solving the system");
+  return x;
+}
+
+mat ls_solve_od(const mat &A, const mat &B)
+{
+  mat X;
+  bool info;
+  info = ls_solve_od(A, B, X);
+  it_assert_debug(info, "ls_solve_od: Failed solving the system");
+  return X;
+}
+
+cvec ls_solve_od(const cmat &A, const cvec &b)
+{
+  cvec x;
+  bool info;
+  info = ls_solve_od(A, b, x);
+  it_assert_debug(info, "ls_solve_od: Failed solving the system");
+  return x;
+}
+
+cmat ls_solve_od(const cmat &A, const cmat &B)
+{
+  cmat X;
+  bool info;
+  info = ls_solve_od(A, B, X);
+  it_assert_debug(info, "ls_solve_od: Failed solving the system");
+  return X;
+}
+
+// ------------------- ls_solve_ud -----------------------------------------------------------
+#if defined(HAVE_LAPACK)
+
+bool ls_solve_ud(const mat &A, const vec &b, vec &x)
+{
+  int m, n, lda, ldb, nrhs, lwork, info;
+  char trans = 'N';
+  m = lda = A.rows();
+  n = A.cols();
+  ldb = n;
+  nrhs = 1;
+  lwork = m + std::max(n, nrhs);
+
+  it_assert_debug(m < n, "The system is over-determined!");
+  it_assert_debug(m == b.size(), "The number of rows in A must equal the length of b!");
+
+  vec work(lwork);
+  x = b;
+  x.set_size(n, true);
+  mat QR = A;
+
+  dgels_(&trans, &m, &n, &nrhs, QR._data(), &lda, x._data(), &ldb, work._data(), &lwork, &info);
+
+  return (info == 0);
+}
+
+bool ls_solve_ud(const mat &A, const mat &B, mat &X)
+{
+  int m, n, lda, ldb, nrhs, lwork, info;
+  char trans = 'N';
+  m = lda = A.rows();
+  n = A.cols();
+  ldb = n;
+  nrhs = B.cols();
+  lwork = m + std::max(n, nrhs);
+
+  it_assert_debug(m < n, "The system is over-determined!");
+  it_assert_debug(m == B.rows(), "The number of rows in A must equal the length of b!");
+
+  vec work(lwork);
+  X = B;
+  X.set_size(n, std::max(m, nrhs), true);
+  mat QR = A;
+
+  dgels_(&trans, &m, &n, &nrhs, QR._data(), &lda, X._data(), &ldb, work._data(), &lwork, &info);
+  X.set_size(n, nrhs, true);
+
+  return (info == 0);
+}
+
+bool ls_solve_ud(const cmat &A, const cvec &b, cvec &x)
+{
+  int m, n, lda, ldb, nrhs, lwork, info;
+  char trans = 'N';
+  m = lda = A.rows();
+  n = A.cols();
+  ldb = n;
+  nrhs = 1;
+  lwork = m + std::max(n, nrhs);
+
+  it_assert_debug(m < n, "The system is over-determined!");
+  it_assert_debug(m == b.size(), "The number of rows in A must equal the length of b!");
+
+  cvec work(lwork);
+  x = b;
+  x.set_size(n, true);
+  cmat QR = A;
+
+  zgels_(&trans, &m, &n, &nrhs, QR._data(), &lda, x._data(), &ldb, work._data(), &lwork, &info);
+
+  return (info == 0);
+}
+
+bool ls_solve_ud(const cmat &A, const cmat &B, cmat &X)
+{
+  int m, n, lda, ldb, nrhs, lwork, info;
+  char trans = 'N';
+  m = lda = A.rows();
+  n = A.cols();
+  ldb = n;
+  nrhs = B.cols();
+  lwork = m + std::max(n, nrhs);
+
+  it_assert_debug(m < n, "The system is over-determined!");
+  it_assert_debug(m == B.rows(), "The number of rows in A must equal the length of b!");
+
+  cvec work(lwork);
+  X = B;
+  X.set_size(n, std::max(m, nrhs), true);
+  cmat QR = A;
+
+  zgels_(&trans, &m, &n, &nrhs, QR._data(), &lda, X._data(), &ldb, work._data(), &lwork, &info);
+  X.set_size(n, nrhs, true);
+
+  return (info == 0);
+}
+
+#else
+
+bool ls_solve_ud(const mat &A, const vec &b, vec &x)
+{
+  it_error("LAPACK library is needed to use ls_solve_ud() function");
+  return false;
+}
+
+bool ls_solve_ud(const mat &A, const mat &B, mat &X)
+{
+  it_error("LAPACK library is needed to use ls_solve_ud() function");
+  return false;
+}
+
+bool ls_solve_ud(const cmat &A, const cvec &b, cvec &x)
+{
+  it_error("LAPACK library is needed to use ls_solve_ud() function");
+  return false;
+}
+
+bool ls_solve_ud(const cmat &A, const cmat &B, cmat &X)
+{
+  it_error("LAPACK library is needed to use ls_solve_ud() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+
+vec ls_solve_ud(const mat &A, const vec &b)
+{
+  vec x;
+  bool info;
+  info = ls_solve_ud(A, b, x);
+  it_assert_debug(info, "ls_solve_ud: Failed solving the system");
+  return x;
+}
+
+mat ls_solve_ud(const mat &A, const mat &B)
+{
+  mat X;
+  bool info;
+  info = ls_solve_ud(A, B, X);
+  it_assert_debug(info, "ls_solve_ud: Failed solving the system");
+  return X;
+}
+
+cvec ls_solve_ud(const cmat &A, const cvec &b)
+{
+  cvec x;
+  bool info;
+  info = ls_solve_ud(A, b, x);
+  it_assert_debug(info, "ls_solve_ud: Failed solving the system");
+  return x;
+}
+
+cmat ls_solve_ud(const cmat &A, const cmat &B)
+{
+  cmat X;
+  bool info;
+  info = ls_solve_ud(A, B, X);
+  it_assert_debug(info, "ls_solve_ud: Failed solving the system");
+  return X;
+}
+
+
+// ---------------------- backslash -----------------------------------------
+
+bool backslash(const mat &A, const vec &b, vec &x)
+{
+  int m = A.rows(), n = A.cols();
+  bool info;
+
+  if (m == n)
+    info = ls_solve(A, b, x);
+  else if (m > n)
+    info = ls_solve_od(A, b, x);
+  else
+    info = ls_solve_ud(A, b, x);
+
+  return info;
+}
+
+
+vec backslash(const mat &A, const vec &b)
+{
+  vec x;
+  bool info;
+  info = backslash(A, b, x);
+  it_assert_debug(info, "backslash(): solution was not found");
+  return x;
+}
+
+
+bool backslash(const mat &A, const mat &B, mat &X)
+{
+  int m = A.rows(), n = A.cols();
+  bool info;
+
+  if (m == n)
+    info = ls_solve(A, B, X);
+  else if (m > n)
+    info = ls_solve_od(A, B, X);
+  else
+    info = ls_solve_ud(A, B, X);
+
+  return info;
+}
+
+
+mat backslash(const mat &A, const mat &B)
+{
+  mat X;
+  bool info;
+  info = backslash(A, B, X);
+  it_assert_debug(info, "backslash(): solution was not found");
+  return X;
+}
+
+
+bool backslash(const cmat &A, const cvec &b, cvec &x)
+{
+  int m = A.rows(), n = A.cols();
+  bool info;
+
+  if (m == n)
+    info = ls_solve(A, b, x);
+  else if (m > n)
+    info = ls_solve_od(A, b, x);
+  else
+    info = ls_solve_ud(A, b, x);
+
+  return info;
+}
+
+
+cvec backslash(const cmat &A, const cvec &b)
+{
+  cvec x;
+  bool info;
+  info = backslash(A, b, x);
+  it_assert_debug(info, "backslash(): solution was not found");
+  return x;
+}
+
+
+bool backslash(const cmat &A, const cmat &B, cmat &X)
+{
+  int m = A.rows(), n = A.cols();
+  bool info;
+
+  if (m == n)
+    info = ls_solve(A, B, X);
+  else if (m > n)
+    info = ls_solve_od(A, B, X);
+  else
+    info = ls_solve_ud(A, B, X);
+
+  return info;
+}
+
+cmat backslash(const cmat &A, const cmat &B)
+{
+  cmat X;
+  bool info;
+  info = backslash(A, B, X);
+  it_assert_debug(info, "backslash(): solution was not found");
+  return X;
+}
+
+
+// --------------------------------------------------------------------------
+
+vec forward_substitution(const mat &L, const vec &b)
+{
+  int n = L.rows();
+  vec x(n);
+
+  forward_substitution(L, b, x);
+
+  return x;
+}
+
+void forward_substitution(const mat &L, const vec &b, vec &x)
+{
+  it_assert(L.rows() == L.cols() && L.cols() == b.size() && b.size() == x.size(),
+            "forward_substitution: dimension mismatch");
+  int n = L.rows(), i, j;
+  double temp;
+
+  x(0) = b(0) / L(0, 0);
+  for (i = 1;i < n;i++) {
+    // Should be: x(i)=((b(i)-L(i,i,0,i-1)*x(0,i-1))/L(i,i))(0); but this is to slow.
+    //i_pos=i*L._row_offset();
+    temp = 0;
+    for (j = 0; j < i; j++) {
+      temp += L._elem(i, j) * x(j);
+      //temp+=L._data()[i_pos+j]*x(j);
+    }
+    x(i) = (b(i) - temp) / L._elem(i, i);
+    //x(i)=(b(i)-temp)/L._data()[i_pos+i];
+  }
+}
+
+vec forward_substitution(const mat &L, int p, const vec &b)
+{
+  int n = L.rows();
+  vec x(n);
+
+  forward_substitution(L, p, b, x);
+
+  return x;
+}
+
+void forward_substitution(const mat &L, int p, const vec &b, vec &x)
+{
+  it_assert(L.rows() == L.cols() && L.cols() == b.size() && b.size() == x.size() && p <= L.rows() / 2,
+            "forward_substitution: dimension mismatch");
+  int n = L.rows(), i, j;
+
+  x = b;
+
+  for (j = 0;j < n;j++) {
+    x(j) /= L(j, j);
+    for (i = j + 1;i < std::min(j + p + 1, n);i++) {
+      x(i) -= L(i, j) * x(j);
+    }
+  }
+}
+
+vec backward_substitution(const mat &U, const vec &b)
+{
+  vec x(U.rows());
+  backward_substitution(U, b, x);
+
+  return x;
+}
+
+void backward_substitution(const mat &U, const vec &b, vec &x)
+{
+  it_assert(U.rows() == U.cols() && U.cols() == b.size() && b.size() == x.size(),
+            "backward_substitution: dimension mismatch");
+  int n = U.rows(), i, j;
+  double temp;
+
+  x(n - 1) = b(n - 1) / U(n - 1, n - 1);
+  for (i = n - 2; i >= 0; i--) {
+    // Should be: x(i)=((b(i)-U(i,i,i+1,n-1)*x(i+1,n-1))/U(i,i))(0); but this is too slow.
+    temp = 0;
+    //i_pos=i*U._row_offset();
+    for (j = i + 1; j < n; j++) {
+      temp += U._elem(i, j) * x(j);
+      //temp+=U._data()[i_pos+j]*x(j);
+    }
+    x(i) = (b(i) - temp) / U._elem(i, i);
+    //x(i)=(b(i)-temp)/U._data()[i_pos+i];
+  }
+}
+
+vec backward_substitution(const mat &U, int q, const vec &b)
+{
+  vec x(U.rows());
+  backward_substitution(U, q, b, x);
+
+  return x;
+}
+
+void backward_substitution(const mat &U, int q, const vec &b, vec &x)
+{
+  it_assert(U.rows() == U.cols() && U.cols() == b.size() && b.size() == x.size() && q <= U.rows() / 2,
+            "backward_substitution: dimension mismatch");
+  int n = U.rows(), i, j;
+
+  x = b;
+
+  for (j = n - 1; j >= 0; j--) {
+    x(j) /= U(j, j);
+    for (i = std::max(0, j - q); i < j; i++) {
+      x(i) -= U(i, j) * x(j);
+    }
+  }
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/algebra/eigen.cpp
===================================================================
--- library/bdm/base/itpp/base/algebra/eigen.cpp (revision 812)
+++ library/bdm/base/itpp/base/algebra/eigen.cpp (revision 812)
@@ -0,0 +1,333 @@
+/*!
+ * \file
+ * \brief Eigenvalue decomposition functions.
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#if defined(HAVE_LAPACK)
+#  include <itpp/base/algebra/lapack.h>
+#endif
+
+#include <itpp/base/algebra/eigen.h>
+#include <itpp/base/converters.h>
+
+
+namespace itpp
+{
+
+#if defined(HAVE_LAPACK)
+
+bool eig_sym(const mat &A, vec &d, mat &V)
+{
+  it_assert_debug(A.rows() == A.cols(), "eig_sym: Matrix is not symmetric");
+
+  // Test for symmetric?
+
+  char jobz = 'V', uplo = 'U';
+  int n, lda, lwork, info;
+  n = lda = A.rows();
+  lwork = std::max(1, 3 * n - 1); // This may be choosen better!
+
+  d.set_size(n, false);
+  vec work(lwork);
+
+  V = A; // The routine overwrites input matrix with eigenvectors
+
+  dsyev_(&jobz, &uplo, &n, V._data(), &lda, d._data(), work._data(), &lwork, &info);
+
+  return (info == 0);
+}
+
+bool eig_sym(const mat &A, vec &d)
+{
+  it_assert_debug(A.rows() == A.cols(), "eig_sym: Matrix is not symmetric");
+
+  // Test for symmetric?
+
+  char jobz = 'N', uplo = 'U';
+  int n, lda, lwork, info;
+  n = lda = A.rows();
+  lwork = std::max(1, 3 * n - 1); // This may be choosen better!
+
+  d.set_size(n, false);
+  vec work(lwork);
+
+  mat B(A); // The routine overwrites input matrix
+
+  dsyev_(&jobz, &uplo, &n, B._data(), &lda, d._data(), work._data(), &lwork, &info);
+
+  return (info == 0);
+}
+
+bool eig_sym(const cmat &A, vec &d, cmat &V)
+{
+  it_assert_debug(A.rows() == A.cols(), "eig_sym: Matrix is not hermitian");
+
+  // Test for symmetric?
+
+  char jobz = 'V', uplo = 'U';
+  int n, lda, lwork, info;
+  n = lda = A.rows();
+  lwork = std::max(1, 2 * n - 1); // This may be choosen better!
+
+  d.set_size(n, false);
+  cvec work(lwork);
+  vec rwork(std::max(1, 3*n - 2)); // This may be choosen better!
+
+  V = A; // The routine overwrites input matrix with eigenvectors
+
+  zheev_(&jobz, &uplo, &n, V._data(), &lda, d._data(), work._data(), &lwork, rwork._data(), &info);
+
+  return (info == 0);
+}
+
+bool eig_sym(const cmat &A, vec &d)
+{
+  it_assert_debug(A.rows() == A.cols(), "eig_sym: Matrix is not hermitian");
+
+  // Test for symmetric?
+
+  char jobz = 'N', uplo = 'U';
+  int n, lda, lwork, info;
+  n = lda = A.rows();
+  lwork = std::max(1, 2 * n - 1); // This may be choosen better!
+
+  d.set_size(n, false);
+  cvec work(lwork);
+  vec rwork(std::max(1, 3*n - 2)); // This may be choosen better!
+
+  cmat B(A); // The routine overwrites input matrix
+
+  zheev_(&jobz, &uplo, &n, B._data(), &lda, d._data(), work._data(), &lwork, rwork._data(), &info);
+
+  return (info == 0);
+}
+
+
+// Non-symmetric matrix
+bool eig(const mat &A, cvec &d, cmat &V)
+{
+  it_assert_debug(A.rows() == A.cols(), "eig: Matrix is not square");
+
+  char jobvl = 'N', jobvr = 'V';
+  int n, lda, ldvl, ldvr, lwork, info;
+  n = lda = A.rows();
+  ldvl = 1;
+  ldvr = n;
+  lwork = std::max(1, 4 * n); // This may be choosen better!
+
+  vec work(lwork);
+  vec rwork(std::max(1, 2*n)); // This may be choosen better
+  vec wr(n), wi(n);
+  mat vl, vr(n, n);
+
+  mat B(A); // The routine overwrites input matrix
+
+  dgeev_(&jobvl, &jobvr, &n, B._data(), &lda, wr._data(), wi._data(), vl._data(), &ldvl, vr._data(), &ldvr, work._data(), &lwork, &info);
+
+  d = to_cvec(wr, wi);
+
+  // Fix V
+  V.set_size(n, n, false);
+  for (int j = 0; j < n; j++) {
+    // if d(j) and d(j+1) are complex conjugate pairs, treat special
+    if ((j < n - 1) && d(j) == std::conj(d(j + 1))) {
+      V.set_col(j, to_cvec(vr.get_col(j), vr.get_col(j + 1)));
+      V.set_col(j + 1, to_cvec(vr.get_col(j), -vr.get_col(j + 1)));
+      j++;
+    }
+    else {
+      V.set_col(j, to_cvec(vr.get_col(j)));
+    }
+  }
+
+  return (info == 0);
+}
+
+// Non-symmetric matrix
+bool eig(const mat &A, cvec &d)
+{
+  it_assert_debug(A.rows() == A.cols(), "eig: Matrix is not square");
+
+  char jobvl = 'N', jobvr = 'N';
+  int n, lda, ldvl, ldvr, lwork, info;
+  n = lda = A.rows();
+  ldvl = 1;
+  ldvr = 1;
+  lwork = std::max(1, 4 * n); // This may be choosen better!
+
+  vec work(lwork);
+  vec rwork(std::max(1, 2*n)); // This may be choosen better
+  vec wr(n), wi(n);
+  mat vl, vr;
+
+  mat B(A); // The routine overwrites input matrix
+
+  dgeev_(&jobvl, &jobvr, &n, B._data(), &lda, wr._data(), wi._data(), vl._data(), &ldvl, vr._data(), &ldvr, work._data(), &lwork, &info);
+
+  d = to_cvec(wr, wi);
+
+  return (info == 0);
+}
+
+bool eig(const cmat &A, cvec &d, cmat &V)
+{
+  it_assert_debug(A.rows() == A.cols(), "eig: Matrix is not square");
+
+  char jobvl = 'N', jobvr = 'V';
+  int n, lda, ldvl, ldvr, lwork, info;
+  n = lda = A.rows();
+  ldvl = 1;
+  ldvr = n;
+  lwork = std::max(1, 2 * n); // This may be choosen better!
+
+  d.set_size(n, false);
+  V.set_size(n, n, false);
+  cvec work(lwork);
+  vec rwork(std::max(1, 2*n)); // This may be choosen better!
+  cmat vl;
+
+  cmat B(A); // The routine overwrites input matrix
+
+  zgeev_(&jobvl, &jobvr, &n, B._data(), &lda, d._data(), vl._data(), &ldvl, V._data(), &ldvr, work._data(), &lwork, rwork._data(), &info);
+
+
+  return (info == 0);
+}
+
+bool eig(const cmat &A, cvec &d)
+{
+  it_assert_debug(A.rows() == A.cols(), "eig: Matrix is not square");
+
+  char jobvl = 'N', jobvr = 'N';
+  int n, lda, ldvl, ldvr, lwork, info;
+  n = lda = A.rows();
+  ldvl = 1;
+  ldvr = 1;
+  lwork = std::max(1, 2 * n); // This may be choosen better!
+
+  d.set_size(n, false);
+  cvec work(lwork);
+  vec rwork(std::max(1, 2*n)); // This may be choosen better!
+  cmat vl, vr;
+
+  cmat B(A); // The routine overwrites input matrix
+
+  zgeev_(&jobvl, &jobvr, &n, B._data(), &lda, d._data(), vl._data(), &ldvl, vr._data(), &ldvr, work._data(), &lwork, rwork._data(), &info);
+
+
+  return (info == 0);
+}
+
+#else
+
+bool eig_sym(const mat &A, vec &d, mat &V)
+{
+  it_error("LAPACK library is needed to use eig_sym() function");
+  return false;
+}
+
+bool eig_sym(const mat &A, vec &d)
+{
+  it_error("LAPACK library is needed to use eig_sym() function");
+  return false;
+}
+
+bool eig_sym(const cmat &A, vec &d, cmat &V)
+{
+  it_error("LAPACK library is needed to use eig_sym() function");
+  return false;
+}
+
+bool eig_sym(const cmat &A, vec &d)
+{
+  it_error("LAPACK library is needed to use eig_sym() function");
+  return false;
+}
+
+
+bool eig(const mat &A, cvec &d, cmat &V)
+{
+  it_error("LAPACK library is needed to use eig() function");
+  return false;
+}
+
+bool eig(const mat &A, cvec &d)
+{
+  it_error("LAPACK library is needed to use eig() function");
+  return false;
+}
+
+bool eig(const cmat &A, cvec &d, cmat &V)
+{
+  it_error("LAPACK library is needed to use eig() function");
+  return false;
+}
+
+bool eig(const cmat &A, cvec &d)
+{
+  it_error("LAPACK library is needed to use eig() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+vec eig_sym(const mat &A)
+{
+  vec d;
+  eig_sym(A, d);
+  return d;
+}
+
+vec eig_sym(const cmat &A)
+{
+  vec d;
+  eig_sym(A, d);
+  return d;
+}
+
+
+cvec eig(const mat &A)
+{
+  cvec d;
+  eig(A, d);
+  return d;
+}
+
+cvec eig(const cmat &A)
+{
+  cvec d;
+  eig(A, d);
+  return d;
+}
+
+} //namespace itpp
Index: library/bdm/base/itpp/base/algebra/qr.h
===================================================================
--- library/bdm/base/itpp/base/algebra/qr.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/qr.h (revision 812)
@@ -0,0 +1,110 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/algebra/schur.h
===================================================================
--- library/bdm/base/itpp/base/algebra/schur.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/schur.h (revision 812)
@@ -0,0 +1,117 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/algebra/ls_solve.h
===================================================================
--- library/bdm/base/itpp/base/algebra/ls_solve.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/ls_solve.h (revision 812)
@@ -0,0 +1,412 @@
+/*!
+ * \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-2010  (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 positive 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 positive 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 positive 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 positive 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 positive 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 positive 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 positive 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 positive 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 matrices.
+
+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 matrices.
+
+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: library/bdm/base/itpp/base/algebra/inv.cpp
===================================================================
--- library/bdm/base/itpp/base/algebra/inv.cpp (revision 812)
+++ library/bdm/base/itpp/base/algebra/inv.cpp (revision 812)
@@ -0,0 +1,117 @@
+/*!
+ * \file
+ * \brief Implementation of matrix inversion routines
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#if defined(HAVE_LAPACK)
+#  include <itpp/base/algebra/lapack.h>
+#endif
+
+#include <itpp/base/algebra/inv.h>
+
+
+namespace itpp
+{
+
+#if defined(HAVE_LAPACK)
+
+bool inv(const mat &X, mat &Y)
+{
+  it_assert_debug(X.rows() == X.cols(), "inv: matrix is not square");
+
+  int m = X.rows(), info, lwork;
+  lwork = m; // may be choosen better
+
+  ivec p(m);
+  Y = X;
+  vec work(lwork);
+
+  dgetrf_(&m, &m, Y._data(), &m, p._data(), &info); // LU-factorization
+  if (info != 0)
+    return false;
+
+  dgetri_(&m, Y._data(), &m, p._data(), work._data(), &lwork, &info);
+  return (info == 0);
+}
+
+bool inv(const cmat &X, cmat &Y)
+{
+  it_assert_debug(X.rows() == X.cols(), "inv: matrix is not square");
+
+  int m = X.rows(), info, lwork;
+  lwork = m; // may be choosen better
+
+  ivec p(m);
+  Y = X;
+  cvec work(lwork);
+
+  zgetrf_(&m, &m, Y._data(), &m, p._data(), &info); // LU-factorization
+  if (info != 0)
+    return false;
+
+  zgetri_(&m, Y._data(), &m, p._data(), work._data(), &lwork, &info);
+  return (info == 0);
+}
+
+#else
+
+bool inv(const mat &X, mat &Y)
+{
+  it_error("LAPACK library is needed to use inv() function");
+  return false;
+}
+
+bool inv(const cmat &X, cmat &Y)
+{
+  it_error("LAPACK library is needed to use inv() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+cmat inv(const cmat &X)
+{
+  cmat Y;
+  inv(X, Y);
+  return Y;
+}
+
+
+mat inv(const mat &X)
+{
+  mat Y;
+  inv(X, Y);
+  return Y;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/algebra/eigen.h
===================================================================
--- library/bdm/base/itpp/base/algebra/eigen.h (revision 812)
+++ library/bdm/base/itpp/base/algebra/eigen.h (revision 812)
@@ -0,0 +1,233 @@
+/*!
+ * \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-2010  (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 Calculates 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 Calculates 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 Calculates 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: library/bdm/base/itpp/base/algebra/svd.cpp
===================================================================
--- library/bdm/base/itpp/base/algebra/svd.cpp (revision 812)
+++ library/bdm/base/itpp/base/algebra/svd.cpp (revision 812)
@@ -0,0 +1,226 @@
+/*!
+ * \file
+ * \brief Implementation of Singular Value Decompositions
+ * \author Tony Ottosson, Simon Wood and Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+#if defined(HAVE_LAPACK)
+#  include <itpp/base/algebra/lapack.h>
+#endif
+
+#include <itpp/base/algebra/svd.h>
+
+
+namespace itpp
+{
+
+#if defined(HAVE_LAPACK)
+
+bool svd(const mat &A, vec &S)
+{
+  char jobu = 'N', jobvt = 'N';
+  int m, n, lda, ldu, ldvt, lwork, info;
+  m = lda = ldu = A.rows();
+  n = ldvt = A.cols();
+  lwork = std::max(3 * std::min(m, n) + std::max(m, n), 5 * std::min(m, n));
+
+  mat U, V;
+  S.set_size(std::min(m, n), false);
+  vec work(lwork);
+
+  mat B(A);
+
+  // The theoretical calculation of lwork above results in the minimum size
+  // needed for dgesvd_ to run to completion without having memory errors.
+  // For speed improvement it is best to set lwork=-1 and have dgesvd_
+  // calculate the best workspace requirement.
+  int lwork_tmp = -1;
+  dgesvd_(&jobu, &jobvt, &m, &n, B._data(), &lda, S._data(), U._data(), &ldu,
+          V._data(), &ldvt, work._data(), &lwork_tmp, &info);
+  if (info == 0) {
+    lwork = static_cast<int>(work(0));
+    work.set_size(lwork, false);
+  }
+
+  dgesvd_(&jobu, &jobvt, &m, &n, B._data(), &lda, S._data(), U._data(), &ldu,
+          V._data(), &ldvt, work._data(), &lwork, &info);
+
+  return (info == 0);
+}
+
+bool svd(const cmat &A, vec &S)
+{
+  char jobu = 'N', jobvt = 'N';
+  int m, n, lda, ldu, ldvt, lwork, info;
+  m = lda = ldu = A.rows();
+  n = ldvt = A.cols();
+  lwork = 2 * std::min(m, n) + std::max(m, n);
+
+  cvec U, V;
+  S.set_size(std::min(m, n), false);
+  cvec work(lwork);
+  vec rwork(5*std::min(m, n));
+
+  cmat B(A);
+
+  // The theoretical calculation of lwork above results in the minimum size
+  // needed for zgesvd_ to run to completion without having memory errors.
+  // For speed improvement it is best to set lwork=-1 and have zgesvd_
+  // calculate the best workspace requirement.
+  int lwork_tmp = -1;
+  zgesvd_(&jobu, &jobvt, &m, &n, B._data(), &lda, S._data(), U._data(), &ldu,
+          V._data(), &ldvt, work._data(), &lwork_tmp, rwork._data(), &info);
+  if (info == 0) {
+    lwork = static_cast<int>(real(work(0)));
+    work.set_size(lwork, false);
+  }
+
+  zgesvd_(&jobu, &jobvt, &m, &n, B._data(), &lda, S._data(), U._data(), &ldu,
+          V._data(), &ldvt, work._data(), &lwork, rwork._data(), &info);
+
+  return (info == 0);
+}
+
+bool svd(const mat &A, mat &U, vec &S, mat &V)
+{
+  char jobu = 'A', jobvt = 'A';
+  int m, n, lda, ldu, ldvt, lwork, info;
+  m = lda = ldu = A.rows();
+  n = ldvt = A.cols();
+  lwork = std::max(3 * std::min(m, n) + std::max(m, n), 5 * std::min(m, n));
+
+  U.set_size(m, m, false);
+  V.set_size(n, n, false);
+  S.set_size(std::min(m, n), false);
+  vec work(lwork);
+
+  mat B(A);
+
+  // The theoretical calculation of lwork above results in the minimum size
+  // needed for dgesvd_ to run to completion without having memory errors.
+  // For speed improvement it is best to set lwork=-1 and have dgesvd_
+  // calculate the best workspace requirement.
+  int lwork_tmp = -1;
+  dgesvd_(&jobu, &jobvt, &m, &n, B._data(), &lda, S._data(), U._data(), &ldu,
+          V._data(), &ldvt, work._data(), &lwork_tmp, &info);
+  if (info == 0) {
+    lwork = static_cast<int>(work(0));
+    work.set_size(lwork, false);
+  }
+
+  dgesvd_(&jobu, &jobvt, &m, &n, B._data(), &lda, S._data(), U._data(), &ldu,
+          V._data(), &ldvt, work._data(), &lwork, &info);
+
+  V = V.T(); // This is probably slow!!!
+
+  return (info == 0);
+}
+
+bool svd(const cmat &A, cmat &U, vec &S, cmat &V)
+{
+  char jobu = 'A', jobvt = 'A';
+  int m, n, lda, ldu, ldvt, lwork, info;
+  m = lda = ldu = A.rows();
+  n = ldvt = A.cols();
+  lwork = 2 * std::min(m, n) + std::max(m, n);
+
+  U.set_size(m, m, false);
+  V.set_size(n, n, false);
+  S.set_size(std::min(m, n), false);
+  cvec work(lwork);
+  vec rwork(5 * std::min(m, n));
+
+  cmat B(A);
+
+  // The theoretical calculation of lwork above results in the minimum size
+  // needed for zgesvd_ to run to completion without having memory errors.
+  // For speed improvement it is best to set lwork=-1 and have zgesvd_
+  // calculate the best workspace requirement.
+  int lwork_tmp = -1;
+  zgesvd_(&jobu, &jobvt, &m, &n, B._data(), &lda, S._data(), U._data(), &ldu,
+          V._data(), &ldvt, work._data(), &lwork_tmp, rwork._data(), &info);
+  if (info == 0) {
+    lwork = static_cast<int>(real(work(0)));
+    work.set_size(lwork, false);
+  }
+
+  zgesvd_(&jobu, &jobvt, &m, &n, B._data(), &lda, S._data(), U._data(), &ldu,
+          V._data(), &ldvt, work._data(), &lwork, rwork._data(), &info);
+
+  V = V.H(); // This is slow!!!
+
+  return (info == 0);
+}
+
+#else
+
+bool svd(const mat &A, vec &S)
+{
+  it_error("LAPACK library is needed to use svd() function");
+  return false;
+}
+
+bool svd(const cmat &A, vec &S)
+{
+  it_error("LAPACK library is needed to use svd() function");
+  return false;
+}
+
+bool svd(const mat &A, mat &U, vec &S, mat &V)
+{
+  it_error("LAPACK library is needed to use svd() function");
+  return false;
+}
+
+bool svd(const cmat &A, cmat &U, vec &S, cmat &V)
+{
+  it_error("LAPACK library is needed to use svd() function");
+  return false;
+}
+
+#endif // HAVE_LAPACK
+
+vec svd(const mat &A)
+{
+  vec S;
+  svd(A, S);
+  return S;
+}
+
+vec svd(const cmat &A)
+{
+  vec S;
+  svd(A, S);
+  return S;
+}
+
+} //namespace itpp
Index: library/bdm/base/itpp/base/factory.h
===================================================================
--- library/bdm/base/itpp/base/factory.h (revision 812)
+++ library/bdm/base/itpp/base/factory.h (revision 812)
@@ -0,0 +1,327 @@
+/*!
+ * \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-2010  (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> inline
+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<> inline
+void create_elements<unsigned char>(unsigned char* &ptr, int n,
+                                    const Factory &)
+{
+  void *p = operator new(sizeof(unsigned char) * n);
+  ptr = reinterpret_cast<unsigned char*>(p);
+}
+
+//! Specialization for binary data arrays
+template<> inline
+void create_elements<bin>(bin* &ptr, int n, const Factory &)
+{
+  void *p = operator new(sizeof(bin) * n);
+  ptr = reinterpret_cast<bin*>(p);
+}
+
+//! Specialization for short integer data arrays
+template<> inline
+void create_elements<short int>(short int* &ptr, int n, const Factory &)
+{
+  void *p = operator new(sizeof(short int) * n);
+  ptr = reinterpret_cast<short int*>(p);
+}
+
+//! Specialization for integer data arrays
+template<> inline
+void create_elements<int>(int* &ptr, int n, const Factory &)
+{
+  void *p = operator new(sizeof(int) * n);
+  ptr = reinterpret_cast<int*>(p);
+}
+
+//! Specialization for 16-byte aligned double data arrays
+template<> inline
+void create_elements<double>(double* &ptr, int n, const Factory &)
+{
+  void *p0 = operator new(sizeof(double) * n + 16);
+  void *p1 = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(p0) + 16)
+                                     & (~(std::size_t(15))));
+  *(reinterpret_cast<void**>(p1) - 1) = p0;
+  ptr = reinterpret_cast<double*>(p1);
+}
+
+//! Specialization for 16-byte aligned complex double data arrays
+template<> inline
+void create_elements<std::complex<double> >(std::complex<double>* &ptr,
+    int n, const Factory &)
+{
+  void *p0 = operator new(sizeof(std::complex<double>) * n + 16);
+  void *p1 = reinterpret_cast<void*>((reinterpret_cast<std::size_t>(p0) + 16)
+                                     & (~(std::size_t(15))));
+  *(reinterpret_cast<void**>(p1) - 1) = p0;
+  ptr = reinterpret_cast<std::complex<double>*>(p1);
+}
+
+
+
+//! Destroy an array of Array, Vec or Mat elements
+template<class T> inline
+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<> inline
+void destroy_elements<unsigned char>(unsigned char* &ptr, int)
+{
+  if (ptr) {
+    void *p = reinterpret_cast<void*>(ptr);
+    operator delete(p);
+	ptr = 0;
+  }
+}
+
+//! Specialization for binary data arrays
+template<> inline
+void destroy_elements<bin>(bin* &ptr, int)
+{
+  if (ptr) {
+    void *p = reinterpret_cast<void*>(ptr);
+    operator delete(p);
+    ptr = 0;
+  }
+}
+//! Specialization for short integer data arrays
+template<> inline
+void destroy_elements<short int>(short int* &ptr, int)
+{
+  if (ptr) {
+    void *p = reinterpret_cast<void*>(ptr);
+    operator delete(p);
+    ptr = 0;
+  }
+}
+
+//! Specialization for integer data arrays
+template<> inline
+void destroy_elements<int>(int* &ptr, int)
+{
+  if (ptr) {
+    void *p = reinterpret_cast<void*>(ptr);
+    operator delete(p);
+    ptr = 0;
+  }
+}
+
+//! Specialisation for 16-byte aligned double data arrays
+template<> inline
+void destroy_elements<double>(double* &ptr, int)
+{
+  if (ptr) {
+    void *p = *(reinterpret_cast<void**>(ptr) - 1);
+    operator delete(p);
+    ptr = 0;
+  }
+}
+
+//! Specialisation for 16-byte aligned complex double data arrays
+template<> inline
+void destroy_elements<std::complex<double> >(std::complex<double>* &ptr, int)
+{
+  if (ptr) {
+    void *p = *(reinterpret_cast<void**>(ptr) - 1);
+    operator delete(p);
+    ptr = 0;
+  }
+}
+
+
+//! 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: library/bdm/base/itpp/base/bessel.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel.cpp (revision 812)
@@ -0,0 +1,114 @@
+/*!
+ * \file
+ * \brief Implementation of Bessel functions
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/bessel.h>
+#include <itpp/base/bessel/bessel_internal.h>
+
+#ifndef _MSC_VER
+#  include <itpp/config.h>
+#else
+#  include <itpp/config_msvc.h>
+#endif
+
+
+namespace itpp
+{
+
+// Bessel function of order nu
+double besselj(int nu, double x) { return jn(nu, x); }
+
+vec besselj(int nu, const vec &x)
+{
+  vec out(x.size());
+  for (int i = 0; i < x.size(); i++)
+    out(i) = jn(nu, x(i));
+
+  return out;
+}
+
+// Bessel function of order nu. nu is real.
+double besselj(double nu, double x) { return jv(nu, x); }
+
+vec besselj(double nu, const vec &x)
+{
+  vec out(x.size());
+  for (int i = 0; i < x.size(); i++)
+    out(i) = jv(nu, x(i));
+
+  return out;
+}
+
+// Bessel function of second kind of order nu
+double bessely(int nu, double x) { return yn(nu, x); }
+
+vec bessely(int nu, const vec &x)
+{
+  vec out(x.size());
+  for (int i = 0; i < x.size(); i++)
+    out(i) = yn(nu, x(i));
+
+  return out;
+}
+// Bessel function of second kind of order nu
+double bessely(double nu, double x) { return yv(nu, x); }
+
+vec bessely(double nu, const vec &x)
+{
+  vec out(x.size());
+  for (int i = 0; i < x.size(); i++)
+    out(i) = yv(nu, x(i));
+
+  return out;
+}
+
+// Modified Bessel function of order nu
+double besseli(double nu, double x) { return iv(nu, x); }
+
+vec besseli(double nu, const vec &x)
+{
+  vec out(x.size());
+  for (int i = 0; i < x.size(); i++)
+    out(i) = iv(nu, x(i));
+
+  return out;
+}
+
+// Modified Bessel function of second kind of order n
+double besselk(int n, double x) { return kn(n, x); }
+
+vec besselk(int nu, const vec &x)
+{
+  vec out(x.size());
+  for (int i = 0; i < x.size(); i++)
+    out(i) = kn(nu, x(i));
+
+  return out;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/gf2mat.cpp
===================================================================
--- library/bdm/base/itpp/base/gf2mat.cpp (revision 812)
+++ library/bdm/base/itpp/base/gf2mat.cpp (revision 812)
@@ -0,0 +1,1081 @@
+/*!
+ * \file
+ * \brief Implementation 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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/gf2mat.h>
+#include <itpp/base/specmat.h>
+#include <itpp/base/matfunc.h>
+#include <itpp/base/converters.h>
+#include <iostream>
+
+namespace itpp
+{
+
+// ====== IMPLEMENTATION OF THE ALIST CLASS ==========
+
+GF2mat_sparse_alist::GF2mat_sparse_alist(const std::string &fname)
+    : data_ok(false)
+{
+  read(fname);
+}
+
+void GF2mat_sparse_alist::read(const std::string &fname)
+{
+  std::ifstream file;
+  std::string line;
+  std::stringstream ss;
+
+  file.open(fname.c_str());
+  it_assert(file.is_open(),
+            "GF2mat_sparse_alist::read(): Could not open file \""
+            << fname << "\" for reading");
+
+  // parse N and M:
+  getline(file, line);
+  ss << line;
+  ss >> N >> M;
+  it_assert(!ss.fail(),
+            "GF2mat_sparse_alist::read(): Wrong alist data (N or M)");
+  it_assert((N > 0) && (M > 0),
+            "GF2mat_sparse_alist::read(): Wrong alist data");
+  ss.seekg(0, std::ios::end);
+  ss.clear();
+
+  // parse max_num_n and max_num_m
+  getline(file, line);
+  ss << line;
+  ss >> max_num_n >> max_num_m;
+  it_assert(!ss.fail(),
+            "GF2mat_sparse_alist::read(): Wrong alist data (max_num_{n,m})");
+  it_assert((max_num_n >= 0) && (max_num_n <= N) &&
+            (max_num_m >= 0) && (max_num_m <= M),
+            "GF2mat_sparse_alist::read(): Wrong alist data");
+  ss.seekg(0, std::ios::end);
+  ss.clear();
+
+  // parse weight of each column n
+  num_nlist.set_size(N);
+  num_nlist.clear();
+  getline(file, line);
+  ss << line;
+  for (int i = 0; i < N; i++) {
+    ss >> num_nlist(i);
+    it_assert(!ss.fail(),
+              "GF2mat_sparse_alist::read(): Wrong alist data (num_nlist("
+              << i << "))");
+    it_assert((num_nlist(i) >= 0) && (num_nlist(i) <= M),
+              "GF2mat_sparse_alist::read(): Wrong alist data (num_nlist("
+              << i << "))");
+  }
+  ss.seekg(0, std::ios::end);
+  ss.clear();
+
+  // parse weight of each row m
+  num_mlist.set_size(M);
+  num_mlist.clear();
+  getline(file, line);
+  ss << line;
+  for (int i = 0; i < M; i++) {
+    ss >> num_mlist(i);
+    it_assert(!ss.fail(),
+              "GF2mat_sparse_alist::read(): Wrong alist data (num_mlist("
+              << i << "))");
+    it_assert((num_mlist(i) >= 0) && (num_mlist(i) <= N),
+              "GF2mat_sparse_alist::read(): Wrong alist data (num_mlist("
+              << i << "))");
+  }
+  ss.seekg(0, std::ios::end);
+  ss.clear();
+
+  // parse coordinates in the n direction with non-zero entries
+  nlist.set_size(N, max_num_n);
+  nlist.clear();
+  for (int i = 0; i < N; i++) {
+    getline(file, line);
+    ss << line;
+    for (int j = 0; j < num_nlist(i); j++) {
+      ss >> nlist(i, j);
+      it_assert(!ss.fail(),
+                "GF2mat_sparse_alist::read(): Wrong alist data (nlist("
+                << i << "," << j << "))");
+      it_assert((nlist(i, j) >= 0) && (nlist(i, j) <= M),
+                "GF2mat_sparse_alist::read(): Wrong alist data (nlist("
+                << i << "," << j << "))");
+    }
+    ss.seekg(0, std::ios::end);
+    ss.clear();
+  }
+
+  // parse coordinates in the m direction with non-zero entries
+  mlist.set_size(M, max_num_m);
+  mlist.clear();
+  for (int i = 0; i < M; i++) {
+    getline(file, line);
+    ss << line;
+    for (int j = 0; j < num_mlist(i); j++) {
+      ss >> mlist(i, j);
+      it_assert(!ss.fail(),
+                "GF2mat_sparse_alist::read(): Wrong alist data (mlist("
+                << i << "," << j << "))");
+      it_assert((mlist(i, j) >= 0) && (mlist(i, j) <= N),
+                "GF2mat_sparse_alist::read(): Wrong alist data (mlist("
+                << i << "," << j << "))");
+    }
+    ss.seekg(0, std::ios::end);
+    ss.clear();
+  }
+
+  file.close();
+  data_ok = true;
+}
+
+void GF2mat_sparse_alist::write(const std::string &fname) const
+{
+  it_assert(data_ok,
+            "GF2mat_sparse_alist::write(): alist data not ready for writing");
+
+  std::ofstream file(fname.c_str(), std::ofstream::out);
+  it_assert(file.is_open(),
+            "GF2mat_sparse_alist::write(): Could not open file \""
+            << fname << "\" for writing");
+
+  file << N << " " << M << std::endl;
+  file << max_num_n << " " << max_num_m << std::endl;
+
+  for (int i = 0; i < num_nlist.length() - 1; i++)
+    file << num_nlist(i) << " ";
+  file << num_nlist(num_nlist.length() - 1) << std::endl;
+
+  for (int i = 0; i < num_mlist.length() - 1; i++)
+    file << num_mlist(i) << " ";
+  file << num_mlist(num_mlist.length() - 1) << std::endl;
+
+  for (int i = 0; i < N; i++) {
+    for (int j = 0; j < num_nlist(i) - 1; j++)
+      file << nlist(i, j) << " ";
+    file << nlist(i, num_nlist(i) - 1) << std::endl;
+  }
+
+  for (int i = 0; i < M; i++) {
+    for (int j = 0; j < num_mlist(i) - 1; j++)
+      file << mlist(i, j) << " ";
+    file << mlist(i, num_mlist(i) - 1) << std::endl;
+  }
+
+  file.close();
+}
+
+
+GF2mat_sparse GF2mat_sparse_alist::to_sparse(bool transpose) const
+{
+  GF2mat_sparse sbmat(M, N, max_num_m);
+
+  for (int i = 0; i < M; i++) {
+    for (int j = 0; j < num_mlist(i); j++) {
+      sbmat.set_new(i, mlist(i, j) - 1, bin(1));
+    }
+  }
+  sbmat.compact();
+
+  if (transpose) {
+    return sbmat.transpose();
+  }
+  else {
+    return sbmat;
+  }
+}
+
+
+// ----------------------------------------------------------------------
+// WARNING: This method is very slow. Sparse_Mat has to be extended with
+// some extra functions to improve the performance of this.
+// ----------------------------------------------------------------------
+void GF2mat_sparse_alist::from_sparse(const GF2mat_sparse &sbmat,
+                                      bool transpose)
+{
+  if (transpose) {
+    from_sparse(sbmat.transpose(), false);
+  }
+  else {
+    // check matrix dimension
+    M = sbmat.rows();
+    N = sbmat.cols();
+
+    num_mlist.set_size(M);
+    num_nlist.set_size(N);
+
+    // fill mlist matrix, num_mlist vector and max_num_m
+    mlist.set_size(0, 0);
+    int tmp_cols = 0; // initial number of allocated columns
+    for (int i = 0; i < M; i++) {
+      ivec temp_row(0);
+      for (int j = 0; j < N; j++) {
+        if (sbmat(i, j) == bin(1)) {
+          temp_row = concat(temp_row, j + 1);
+        }
+      }
+      int trs = temp_row.size();
+      if (trs > tmp_cols) {
+        tmp_cols = trs;
+        mlist.set_size(M, tmp_cols, true);
+      }
+      else if (trs < tmp_cols) {
+        temp_row.set_size(tmp_cols, true);
+      }
+      mlist.set_row(i, temp_row);
+      num_mlist(i) = trs;
+    }
+    max_num_m = max(num_mlist);
+
+    // fill nlist matrix, num_nlist vector and max_num_n
+    nlist.set_size(0, 0);
+    tmp_cols = 0; // initial number of allocated columns
+    for (int j = 0; j < N; j++) {
+      ivec temp_row = sbmat.get_col(j).get_nz_indices() + 1;
+      int trs = temp_row.size();
+      if (trs > tmp_cols) {
+        tmp_cols = trs;
+        nlist.set_size(N, tmp_cols, true);
+      }
+      else if (trs < tmp_cols) {
+        temp_row.set_size(tmp_cols, true);
+      }
+      nlist.set_row(j, temp_row);
+      num_nlist(j) = trs;
+    }
+    max_num_n = max(num_nlist);
+
+    data_ok = true;
+  }
+}
+
+
+// ----------------------------------------------------------------------
+// Implementation of a dense GF2 matrix class
+// ----------------------------------------------------------------------
+
+GF2mat::GF2mat(int i, int j): nrows(i), ncols(j),
+    nwords((j >> shift_divisor) + 1)
+{
+  data.set_size(nrows, nwords);
+  data.clear();
+}
+
+GF2mat::GF2mat(): nrows(1), ncols(1), nwords(1)
+{
+  data.set_size(nrows, nwords);
+  data.clear();
+}
+
+GF2mat::GF2mat(const bvec &x, bool is_column)
+{
+  if (is_column) {     // create column vector
+    nrows = length(x);
+    ncols = 1;
+    nwords = 1;
+    data.set_size(nrows, nwords);
+    data.clear();
+    for (int i = 0; i < nrows; i++) {
+      set(i, 0, x(i));
+    }
+  }
+  else {    // create row vector
+    nrows = 1;
+    ncols = length(x);
+    nwords = (ncols >> shift_divisor) + 1;
+    data.set_size(nrows, nwords);
+    data.clear();
+    for (int i = 0; i < ncols; i++) {
+      set(0, i, x(i));
+    }
+  }
+}
+
+
+GF2mat::GF2mat(const bmat &X): nrows(X.rows()), ncols(X.cols())
+{
+  nwords = (ncols >> shift_divisor) + 1;
+  data.set_size(nrows, nwords);
+  data.clear();
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < ncols; j++) {
+      set(i, j, X(i, j));
+    }
+  }
+}
+
+
+GF2mat::GF2mat(const GF2mat_sparse &X)
+{
+  nrows = X.rows();
+  ncols = X.cols();
+  nwords = (ncols >> shift_divisor) + 1;
+  data.set_size(nrows, nwords);
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < nwords; j++) {
+      data(i, j) = 0;
+    }
+  }
+
+  for (int j = 0; j < ncols; j++) {
+    for (int i = 0; i < X.get_col(j).nnz(); i++)   {
+      bin b = X.get_col(j).get_nz_data(i);
+      set(X.get_col(j).get_nz_index(i), j, b);
+    }
+  }
+}
+
+GF2mat::GF2mat(const GF2mat_sparse &X, int m1, int n1, int m2, int n2)
+{
+  it_assert(X.rows() > m2, "GF2mat(): indexes out of range");
+  it_assert(X.cols() > n2, "GF2mat(): indexes out of range");
+  it_assert(m1 >= 0 && n1 >= 0 && m2 >= m1 && n2 >= n1,
+            "GF2mat::GF2mat(): indexes out of range");
+
+  nrows = m2 - m1 + 1;
+  ncols = n2 - n1 + 1;
+  nwords = (ncols >> shift_divisor) + 1;
+  data.set_size(nrows, nwords);
+
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < nwords; j++) {
+      data(i, j) = 0;
+    }
+  }
+
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < ncols; j++)   {
+      bin b = X(i + m1, j + n1);
+      set(i, j, b);
+    }
+  }
+}
+
+
+GF2mat::GF2mat(const GF2mat_sparse &X, const ivec &columns)
+{
+  it_assert(X.cols() > max(columns),
+            "GF2mat::GF2mat(): index out of range");
+  it_assert(min(columns) >= 0,
+            "GF2mat::GF2mat(): column index must be positive");
+
+  nrows = X.rows();
+  ncols = length(columns);
+  nwords = (ncols >> shift_divisor) + 1;
+  data.set_size(nrows, nwords);
+
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < nwords; j++) {
+      data(i, j) = 0;
+    }
+  }
+
+  for (int j = 0; j < ncols; j++) {
+    for (int i = 0; i < X.get_col(columns(j)).nnz(); i++)   {
+      bin b = X.get_col(columns(j)).get_nz_data(i);
+      set(X.get_col(columns(j)).get_nz_index(i), j, b);
+    }
+  }
+}
+
+
+void GF2mat::set_size(int m, int n, bool copy)
+{
+  nrows = m;
+  ncols = n;
+  nwords = (ncols >> shift_divisor) + 1;
+  data.set_size(nrows, nwords, copy);
+  if (!copy)
+    data.clear();
+}
+
+
+GF2mat_sparse GF2mat::sparsify() const
+{
+  GF2mat_sparse Z(nrows, ncols);
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < ncols; j++) {
+      if (get(i, j) == 1) {
+        Z.set(i, j, 1);
+      }
+    }
+  }
+
+  return Z;
+}
+
+bvec GF2mat::bvecify() const
+{
+  it_assert(nrows == 1 || ncols == 1,
+            "GF2mat::bvecify() matrix must be a vector");
+  int n = (nrows == 1 ? ncols : nrows);
+  bvec result(n);
+  if (nrows == 1) {
+    for (int i = 0; i < n; i++) {
+      result(i) = get(0, i);
+    }
+  }
+  else {
+    for (int i = 0; i < n; i++) {
+      result(i) = get(i, 0);
+    }
+  }
+  return result;
+}
+
+
+void GF2mat::set_row(int i, bvec x)
+{
+  it_assert(length(x) == ncols,
+            "GF2mat::set_row(): dimension mismatch");
+  for (int j = 0; j < ncols; j++) {
+    set(i, j, x(j));
+  }
+}
+
+void GF2mat::set_col(int j, bvec x)
+{
+  it_assert(length(x) == nrows,
+            "GF2mat::set_col(): dimension mismatch");
+  for (int i = 0; i < nrows; i++) {
+    set(i, j, x(i));
+  }
+}
+
+
+GF2mat gf2dense_eye(int m)
+{
+  GF2mat Z(m, m);
+  for (int i = 0; i < m; i++) {
+    Z.set(i, i, 1);
+  }
+  return Z;
+}
+
+GF2mat GF2mat::get_submatrix(int m1, int n1, int m2, int n2) const
+{
+  it_assert(m1 >= 0 && n1 >= 0 && m2 >= m1 && n2 >= n1
+            && m2 < nrows && n2 < ncols,
+            "GF2mat::get_submatrix() index out of range");
+  GF2mat result(m2 - m1 + 1, n2 - n1 + 1);
+
+  for (int i = m1; i <= m2; i++) {
+    for (int j = n1; j <= n2; j++) {
+      result.set(i - m1, j - n1, get(i, j));
+    }
+  }
+
+  return result;
+}
+
+
+GF2mat GF2mat::concatenate_vertical(const GF2mat &X) const
+{
+  it_assert(X.ncols == ncols,
+            "GF2mat::concatenate_vertical(): dimension mismatch");
+  it_assert(X.nwords == nwords,
+            "GF2mat::concatenate_vertical(): dimension mismatch");
+
+  GF2mat result(nrows + X.nrows, ncols);
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < nwords; j++) {
+      result.data(i, j) = data(i, j);
+    }
+  }
+
+  for (int i = 0; i < X.nrows; i++) {
+    for (int j = 0; j < nwords; j++) {
+      result.data(i + nrows, j) = X.data(i, j);
+    }
+  }
+
+  return result;
+}
+
+GF2mat GF2mat::concatenate_horizontal(const GF2mat &X) const
+{
+  it_assert(X.nrows == nrows,
+            "GF2mat::concatenate_horizontal(): dimension mismatch");
+
+  GF2mat result(nrows, X.ncols + ncols);
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < ncols; j++) {
+      result.set(i, j, get(i, j));
+    }
+  }
+
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < X.ncols; j++) {
+      result.set(i, j + ncols, X.get(i, j));
+    }
+  }
+
+  return result;
+}
+
+bvec GF2mat::get_row(int i) const
+{
+  bvec result(ncols);
+  for (int j = 0; j < ncols; j++) {
+    result(j) = get(i, j);
+  }
+
+  return result;
+}
+
+bvec GF2mat::get_col(int j) const
+{
+  bvec result(nrows);
+  for (int i = 0; i < nrows; i++) {
+    result(i) = get(i, j);
+  }
+
+  return result;
+}
+
+
+int GF2mat::T_fact(GF2mat &T, GF2mat &U, ivec &perm) const
+{
+  T = gf2dense_eye(nrows);
+  U = *this;
+
+  perm = zeros_i(ncols);
+  for (int i = 0; i < ncols; i++) {
+    perm(i) = i;
+  }
+
+  if (nrows > 250) {   // avoid cluttering output ...
+    it_info_debug("Performing T-factorization of GF(2) matrix...  rows: "
+                  << nrows << " cols: "  << ncols << " .... " << std::endl);
+  }
+  int pdone = 0;
+  for (int j = 0; j < nrows; j++) {
+    // Now working on diagonal element j,j
+    // First try find a row with a 1 in column i
+    int i1, j1;
+    for (i1 = j; i1 < nrows; i1++) {
+      for (j1 = j; j1 < ncols; j1++) {
+        if (U.get(i1, j1) == 1) { goto found; }
+      }
+    }
+
+    return j;
+
+  found:
+    U.swap_rows(i1, j);
+    T.swap_rows(i1, j);
+    U.swap_cols(j1, j);
+
+    int temp = perm(j);
+    perm(j) = perm(j1);
+    perm(j1) = temp;
+
+    // now subtract row i from remaining rows
+    for (int i1 = j + 1; i1 < nrows; i1++)  {
+      if (U.get(i1, j) == 1) {
+        int ptemp = floor_i(100.0 * (i1 + j * nrows) / (nrows * nrows));
+        if (nrows > 250 && ptemp > pdone + 10) {
+          it_info_debug(ptemp << "% done.");
+          pdone = ptemp;
+        }
+        U.add_rows(i1, j);
+        T.add_rows(i1, j);
+      }
+    }
+  }
+  return nrows;
+}
+
+
+int GF2mat::T_fact_update_bitflip(GF2mat &T, GF2mat &U,
+                                  ivec &perm, int rank,
+                                  int r, int c) const
+{
+  // First, update U (before re-triangulization)
+  int c0 = c;
+  for (c = 0; c < ncols; c++) {
+    if (perm(c) == c0) {
+      goto foundidx;
+    }
+  }
+  it_error("GF2mat::T_fact_update_bitflip() - internal error");
+
+foundidx:
+  for (int i = 0; i < nrows; i++) {
+    if (T.get(i, r) == 1) {
+      U.addto_element(i, c, 1);
+    }
+  }
+
+  // first move column c to the end
+  bvec lastcol = U.get_col(c);
+  int temp_perm = perm(c);
+  for (int j = c; j < ncols - 1; j++) {
+    U.set_col(j, U.get_col(j + 1));
+    perm(j) = perm(j + 1);
+  }
+  U.set_col(ncols - 1, lastcol);
+  perm(ncols - 1) = temp_perm;
+
+  // then, if the matrix is tall, also move row c to the end
+  if (nrows >= ncols) {
+    bvec lastrow_U = U.get_row(c);
+    bvec lastrow_T = T.get_row(c);
+    for (int i = c; i < nrows - 1; i++) {
+      U.set_row(i, U.get_row(i + 1));
+      T.set_row(i, T.get_row(i + 1));
+    }
+    U.set_row(nrows - 1, lastrow_U);
+    T.set_row(nrows - 1, lastrow_T);
+
+    // Do Gaussian elimination on the last row
+    for (int j = c; j < ncols; j++)  {
+      if (U.get(nrows - 1, j) == 1) {
+        U.add_rows(nrows - 1, j);
+        T.add_rows(nrows - 1, j);
+      }
+    }
+  }
+
+  // Now, continue T-factorization from the point (rank-1,rank-1)
+  for (int j = rank - 1; j < nrows; j++) {
+    int i1, j1;
+    for (i1 = j; i1 < nrows; i1++) {
+      for (j1 = j; j1 < ncols; j1++) {
+        if (U.get(i1, j1) == 1) {
+          goto found;
+        }
+      }
+    }
+
+    return j;
+
+  found:
+    U.swap_rows(i1, j);
+    T.swap_rows(i1, j);
+    U.swap_cols(j1, j);
+
+    int temp = perm(j);
+    perm(j) = perm(j1);
+    perm(j1) = temp;
+
+    for (int i1 = j + 1; i1 < nrows; i1++)  {
+      if (U.get(i1, j) == 1) {
+        U.add_rows(i1, j);
+        T.add_rows(i1, j);
+      }
+    }
+  }
+
+  return nrows;
+}
+
+bool GF2mat::T_fact_update_addcol(GF2mat &T, GF2mat &U,
+                                  ivec &perm, bvec newcol) const
+{
+  int i0 = T.rows();
+  int j0 = U.cols();
+  it_assert(j0 > 0, "GF2mat::T_fact_update_addcol(): dimension mismatch");
+  it_assert(i0 == T.cols(),
+            "GF2mat::T_fact_update_addcol(): dimension mismatch");
+  it_assert(i0 == U.rows(),
+            "GF2mat::T_fact_update_addcol(): dimension mismatch");
+  it_assert(length(perm) == j0,
+            "GF2mat::T_fact_update_addcol(): dimension mismatch");
+  it_assert(U.get(j0 - 1, j0 - 1) == 1,
+            "GF2mat::T_fact_update_addcol(): dimension mismatch");
+  // The following test is VERY TIME-CONSUMING
+  it_assert_debug(U.row_rank() == j0,
+                  "GF2mat::T_fact_update_addcol(): factorization has incorrect rank");
+
+  bvec z = T * newcol;
+  GF2mat Utemp = U.concatenate_horizontal(GF2mat(z, 1));
+
+  // start working on position (j0,j0)
+  int i;
+  for (i = j0; i < i0; i++) {
+    if (Utemp.get(i, j0) == 1) {
+      goto found;
+    }
+  }
+  return (false); // adding the new column would not improve the rank
+
+found:
+  perm.set_length(j0 + 1, true);
+  perm(j0) = j0;
+
+  Utemp.swap_rows(i, j0);
+  T.swap_rows(i, j0);
+
+  for (int i1 = j0 + 1; i1 < i0; i1++)  {
+    if (Utemp.get(i1, j0) == 1) {
+      Utemp.add_rows(i1, j0);
+      T.add_rows(i1, j0);
+    }
+  }
+
+  U = Utemp;
+  return (true); // the new column was successfully added
+}
+
+
+
+
+GF2mat GF2mat::inverse() const
+{
+  it_assert(nrows == ncols, "GF2mat::inverse(): Matrix must be square");
+
+  // first compute the T-factorization
+  GF2mat T, U;
+  ivec perm;
+  int rank = T_fact(T, U, perm);
+  it_assert(rank == ncols, "GF2mat::inverse(): Matrix is not full rank");
+
+  // backward substitution
+  for (int i = ncols - 2; i >= 0; i--) {
+    for (int j = ncols - 1; j > i; j--) {
+      if (U.get(i, j) == 1) {
+        U.add_rows(i, j);
+        T.add_rows(i, j);
+      }
+    }
+  }
+  T.permute_rows(perm, 1);
+  return T;
+}
+
+int GF2mat::row_rank() const
+{
+  GF2mat T, U;
+  ivec perm;
+  int rank = T_fact(T, U, perm);
+  return rank;
+}
+
+bool GF2mat::is_zero() const
+{
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < nwords; j++) {
+      if (data(i, j) != 0) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+bool GF2mat::operator==(const GF2mat &X) const
+{
+  if (X.nrows != nrows) { return false; }
+  if (X.ncols != ncols) { return false; }
+  it_assert(X.nwords == nwords, "GF2mat::operator==() dimension mismatch");
+
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < nwords; j++) {
+      //      if (X.get(i,j)!=get(i,j)) {
+      if (X.data(i, j) != data(i, j)) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+
+void GF2mat::add_rows(int i, int j)
+{
+  it_assert(i >= 0 && i < nrows, "GF2mat::add_rows(): out of range");
+  it_assert(j >= 0 && j < nrows, "GF2mat::add_rows(): out of range");
+  for (int k = 0; k < nwords; k++)   {
+    data(i, k) ^= data(j, k);
+  }
+}
+
+void GF2mat::swap_rows(int i, int j)
+{
+  it_assert(i >= 0 && i < nrows, "GF2mat::swap_rows(): index out of range");
+  it_assert(j >= 0 && j < nrows, "GF2mat::swap_rows(): index out of range");
+  for (int k = 0; k < nwords; k++) {
+    unsigned char temp = data(i, k);
+    data(i, k) = data(j, k);
+    data(j, k) = temp;
+  }
+}
+
+void GF2mat::swap_cols(int i, int j)
+{
+  it_assert(i >= 0 && i < ncols, "GF2mat::swap_cols(): index out of range");
+  it_assert(j >= 0 && j < ncols, "GF2mat::swap_cols(): index out of range");
+  bvec temp = get_col(i);
+  set_col(i, get_col(j));
+  set_col(j, temp);
+}
+
+
+void GF2mat::operator=(const GF2mat &X)
+{
+  nrows = X.nrows;
+  ncols = X.ncols;
+  nwords = X.nwords;
+  data = X.data;
+}
+
+GF2mat operator*(const GF2mat &X, const GF2mat &Y)
+{
+  it_assert(X.ncols == Y.nrows, "GF2mat::operator*(): dimension mismatch");
+  it_assert(X.nwords > 0, "Gfmat::operator*(): dimension mismatch");
+  it_assert(Y.nwords > 0, "Gfmat::operator*(): dimension mismatch");
+
+  /*
+  // this can be done more efficiently?
+  GF2mat result(X.nrows,Y.ncols);
+  for (int i=0; i<X.nrows; i++) {
+  for (int j=0; j<Y.ncols; j++) {
+  bin b=0;
+  for (int k=0; k<X.ncols; k++) {
+  bin x = X.get(i,k);
+  bin y = Y.get(k,j);
+  b ^= (x&y);
+  }
+  result.set(i,j,b);
+  }
+  }
+  return result; */
+
+  // is this better?
+  return mult_trans(X, Y.transpose());
+}
+
+bvec operator*(const GF2mat &X, const bvec &y)
+{
+  it_assert(length(y) == X.ncols, "GF2mat::operator*(): dimension mismatch");
+  it_assert(X.nwords > 0, "Gfmat::operator*(): dimension mismatch");
+
+  /*
+  // this can be done more efficiently?
+  bvec result = zeros_b(X.nrows);
+  for (int i=0; i<X.nrows; i++) {
+  // do the nwords-1 data columns first
+  for (int j=0; j<X.nwords-1; j++) {
+  int ind = j<<shift_divisor;
+  unsigned char r=X.data(i,j);
+  while (r) {
+  result(i) ^= (r & y(ind));
+  r >>= 1;
+  ind++;
+  }
+  }
+  // do the last column separately
+  for (int j=(X.nwords-1)<<shift_divisor; j<X.ncols; j++) {
+  result(i) ^= (X.get(i,j) & y(j));
+  }
+  }
+  return result; */
+
+  // is this better?
+  return (mult_trans(X, GF2mat(y, 0))).bvecify();
+}
+
+GF2mat mult_trans(const GF2mat &X, const GF2mat &Y)
+{
+  it_assert(X.ncols == Y.ncols, "GF2mat::mult_trans(): dimension mismatch");
+  it_assert(X.nwords > 0, "GF2mat::mult_trans(): dimension mismatch");
+  it_assert(Y.nwords > 0, "GF2mat::mult_trans(): dimension mismatch");
+  it_assert(X.nwords == Y.nwords, "GF2mat::mult_trans(): dimension mismatch");
+
+  GF2mat result(X.nrows, Y.nrows);
+
+  for (int i = 0; i < X.nrows; i++) {
+    for (int j = 0; j < Y.nrows; j++) {
+      bin b = 0;
+      int kindx = i;
+      int kindy = j;
+      for (int k = 0; k < X.nwords; k++) {
+        unsigned char r = X.data(kindx) & Y.data(kindy);
+        /* The following can be speeded up by using a small lookup
+           table for the number of ones and shift only a few times (or
+           not at all if table is large) */
+        while (r) {
+          b ^= r & 1;
+          r >>= 1;
+        };
+        kindx += X.nrows;
+        kindy += Y.nrows;
+      }
+      result.set(i, j, b);
+    }
+  }
+  return result;
+}
+
+GF2mat GF2mat::transpose() const
+{
+  // CAN BE SPEEDED UP
+  GF2mat result(ncols, nrows);
+
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < ncols; j++) {
+      result.set(j, i, get(i, j));
+    }
+  }
+  return result;
+}
+
+GF2mat operator+(const GF2mat &X, const GF2mat &Y)
+{
+  it_assert(X.nrows == Y.nrows, "GF2mat::operator+(): dimension mismatch");
+  it_assert(X.ncols == Y.ncols, "GF2mat::operator+(): dimension mismatch");
+  it_assert(X.nwords == Y.nwords, "GF2mat::operator+(): dimension mismatch");
+  GF2mat result(X.nrows, X.ncols);
+
+  for (int i = 0; i < X.nrows; i++) {
+    for (int j = 0; j < X.nwords; j++) {
+      result.data(i, j) = X.data(i, j) ^ Y.data(i, j);
+    }
+  }
+
+  return result;
+}
+
+void GF2mat::permute_cols(ivec &perm, bool I)
+{
+  it_assert(length(perm) == ncols,
+            "GF2mat::permute_cols(): dimensions do not match");
+
+  GF2mat temp = (*this);
+  for (int j = 0; j < ncols; j++) {
+    if (I == 0) {
+      set_col(j, temp.get_col(perm(j)));
+    }
+    else {
+      set_col(perm(j), temp.get_col(j));
+    }
+  }
+}
+
+void GF2mat::permute_rows(ivec &perm, bool I)
+{
+  it_assert(length(perm) == nrows,
+            "GF2mat::permute_rows(): dimensions do not match");
+
+  GF2mat temp = (*this);
+  for (int i = 0; i < nrows; i++) {
+    if (I == 0) {
+      for (int j = 0; j < nwords; j++) {
+        data(i, j) = temp.data(perm(i), j);
+      }
+    }
+    else {
+      for (int j = 0; j < nwords; j++) {
+        data(perm(i), j) = temp.data(i, j);
+      }
+    }
+  }
+}
+
+
+std::ostream &operator<<(std::ostream &os, const GF2mat &X)
+{
+  int i, j;
+  os << "---- GF(2) matrix of dimension " << X.nrows << "*" << X.ncols
+  << " -- Density: " << X.density() << " ----" << std::endl;
+
+  for (i = 0; i < X.nrows; i++) {
+    os << "      ";
+    for (j = 0; j < X.ncols; j++) {
+      os << X.get(i, j) << " ";
+    }
+    os << std::endl;
+  }
+
+  return os;
+}
+
+double GF2mat::density() const
+{
+  int no_of_ones = 0;
+
+  for (int i = 0; i < nrows; i++) {
+    for (int j = 0; j < ncols; j++) {
+      no_of_ones += (get(i, j) == 1 ? 1 : 0);
+    }
+  }
+
+  return ((double) no_of_ones) / (nrows*ncols);
+}
+
+
+it_file &operator<<(it_file &f, const GF2mat &X)
+{
+  // 3 64-bit unsigned words for: nrows, ncols and nwords + rest for char data
+  uint64_t bytecount = 3 * sizeof(uint64_t)
+                       + X.nrows * X.nwords * sizeof(char);
+  f.write_data_header("GF2mat", bytecount);
+
+  f.low_level_write(static_cast<uint64_t>(X.nrows));
+  f.low_level_write(static_cast<uint64_t>(X.ncols));
+  f.low_level_write(static_cast<uint64_t>(X.nwords));
+  for (int i = 0; i < X.nrows; i++) {
+    for (int j = 0; j < X.nwords; j++) {
+      f.low_level_write(static_cast<char>(X.data(i, j)));
+    }
+  }
+  return f;
+}
+
+it_ifile &operator>>(it_ifile &f, GF2mat &X)
+{
+  it_file::data_header h;
+
+  f.read_data_header(h);
+  if (h.type == "GF2mat") {
+    uint64_t tmp;
+    f.low_level_read(tmp);
+    X.nrows = static_cast<int>(tmp);
+    f.low_level_read(tmp);
+    X.ncols = static_cast<int>(tmp);
+    f.low_level_read(tmp);
+    X.nwords = static_cast<int>(tmp);
+    X.data.set_size(X.nrows, X.nwords);
+    for (int i = 0; i < X.nrows; i++) {
+      for (int j = 0; j < X.nwords; j++) {
+        char r;
+        f.low_level_read(r);
+        X.data(i, j) = static_cast<unsigned char>(r);
+      }
+    }
+  }
+  else {
+    it_error("it_ifile &operator>>() - internal error");
+  }
+
+  return f;
+}
+
+} // namespace itpp
+
Index: library/bdm/base/itpp/base/itfile.h
===================================================================
--- library/bdm/base/itpp/base/itfile.h (revision 812)
+++ library/bdm/base/itpp/base/itfile.h (revision 812)
@@ -0,0 +1,1158 @@
+/*!
+ * \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-2010  (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);
+
+  //!ACTION: 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) {}
+  //! Dummy assignment operator - MSVC++ warning C4512
+  Name &operator=(const Name&) { return *this; }
+  //! The name string
+  const std::string& name;
+  //! The description
+  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);
+
+  //!ACTION: 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: library/bdm/base/itpp/base/vec.h
===================================================================
--- library/bdm/base/itpp/base/vec.h (revision 812)
+++ library/bdm/base/itpp/base/vec.h (revision 812)
@@ -0,0 +1,2090 @@
+/*!
+ * \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-2010  (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>
+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>
+Vec<Num_T> operator+(const Vec<Num_T> &v, Num_T t);
+//! Addition of a scalar and a vector
+template<class Num_T>
+Vec<Num_T> operator+(Num_T t, const Vec<Num_T> &v);
+
+//! Subtraction of a vector from a vector
+template<class Num_T>
+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>
+Vec<Num_T> operator-(const Vec<Num_T> &v, Num_T t);
+//! Subtraction of vector from scalar. Results in a vector
+template<class Num_T>
+Vec<Num_T> operator-(Num_T t, const Vec<Num_T> &v);
+//! Negation of vector
+template<class Num_T>
+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>
+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>
+Vec<Num_T> operator*(const Vec<Num_T> &v, Num_T t);
+//! Multiplication of a scalar and a vector. Results in a vector
+template<class Num_T>
+Vec<Num_T> operator*(Num_T t, const Vec<Num_T> &v);
+
+//! Element-wise multiplication of two vectors
+template<class Num_T>
+Vec<Num_T> elem_mult(const Vec<Num_T> &a, const Vec<Num_T> &b);
+//! Element-wise multiplication of three vectors
+template<class Num_T>
+Vec<Num_T> elem_mult(const Vec<Num_T> &a, const Vec<Num_T> &b,
+                     const Vec<Num_T> &c);
+//! Element-wise multiplication of four vectors
+template<class Num_T>
+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 two vectors, storing the result in vector \c out
+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 three vectors, storing the result in vector \c out
+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 four vectors, storing the result in vector \c out
+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. Faster 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>
+Vec<Num_T> operator/(const Vec<Num_T> &v, Num_T t);
+//! Division of \c t with all elements in \c v
+template<class Num_T>
+Vec<Num_T> operator/(Num_T t, const Vec<Num_T> &v);
+
+//! Elementwise division of two vectors
+template<class Num_T>
+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>
+Vec<Num_T> elem_div(Num_T t, const Vec<Num_T> &v);
+//! Elementwise division of two vectors, storing the result in vector \c out
+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>
+Vec<Num_T> concat(const Vec<Num_T> &v, Num_T a);
+//! Concat element \c a to the beginning of the vector \c v
+template<class Num_T>
+Vec<Num_T> concat(Num_T a, const Vec<Num_T> &v);
+//! Concat vectors \c v1 and \c v2
+template<class Num_T>
+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>
+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>
+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>
+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 arbitrary 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 is 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
+  are not copied. If you would 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 leftmost elements (the first)
+  a.right(10); // The 10 rightmost 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 in e.g.
+  \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 common linear algebra
+  operations, 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
+  also 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, bool copy = false);
+  //! Set length of vector. if copy = true then keeping the old values
+  void set_length(int size, 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;
+  //! Get the elements from \c i1 to \c i2. Index -1 indicates the last element.
+  Vec<Num_T> get(int i1, int i2) const;
+  //! Get the elements in the vector where \c binlist is \c 1
+  Vec<Num_T> get(const Vec<bin> &binlist) const;
+
+  //! Modifier-style method. First element is 0.
+  void set(int i, Num_T t);
+
+  //! 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+=(Num_T t);
+  //! Addition of two vectors
+  friend Vec<Num_T> operator+<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+  //! Addition of a vector and a scalar
+  friend Vec<Num_T> operator+<>(const Vec<Num_T> &v, Num_T t);
+  //! Addition of a scalar and a vector
+  friend Vec<Num_T> operator+<>(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-=(Num_T t);
+  //! Subtraction of \c v2 from \c v1
+  friend Vec<Num_T> operator-<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+  //! Subtraction of scalar from vector
+  friend Vec<Num_T> operator-<>(const Vec<Num_T> &v, Num_T t);
+  //! Subtraction of vector from scalar
+  friend Vec<Num_T> operator-<>(Num_T t, const Vec<Num_T> &v);
+  //! Negation of vector
+  friend Vec<Num_T> operator-<>(const Vec<Num_T> &v);
+
+  //! Multiply with a scalar
+  Vec<Num_T>& operator*=(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 Mat<Num_T> outer_product<>(const Vec<Num_T> &v1,
+                                    const Vec<Num_T> &v2, bool hermitian);
+  //! Elementwise multiplication of vector and scalar
+  friend Vec<Num_T> operator*<>(const Vec<Num_T> &v, Num_T t);
+  //! Elementwise multiplication of vector and scalar
+  friend Vec<Num_T> operator*<>(Num_T t, const Vec<Num_T> &v);
+
+  //! Elementwise multiplication
+  friend Vec<Num_T> elem_mult<>(const Vec<Num_T> &a, const Vec<Num_T> &b);
+  //! Elementwise multiplication of three vectors
+  friend 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 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
+  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
+  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
+  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/=(Num_T t);
+  //! Elementwise division
+  Vec<Num_T>& operator/=(const Vec<Num_T> &v);
+
+  //! Elementwise division
+  friend Vec<Num_T> operator/<>(const Vec<Num_T> &v, Num_T t);
+  //! Elementwise division
+  friend Vec<Num_T> operator/<>(Num_T t, const Vec<Num_T> &v);
+
+  //! Elementwise division
+  friend Vec<Num_T> elem_div<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+  //! Elementwise division
+  friend Vec<Num_T> elem_div<>(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 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;
+  /*!
+   * \brief Split the vector into two parts at element \c pos.
+   *
+   * Return the first part containing elements 0 to \c pos-1, and keep the
+   * second part containing the remaining elements starting from \c pos
+   * (empty vector if \c pos is equal to the length of the vector).
+   */
+  Vec<Num_T> split(int pos);
+  //! Shift in element \c t at position 0 \c n times
+  void shift_right(Num_T t, int n = 1);
+  //! Shift in vector \c v at position 0
+  void shift_right(const Vec<Num_T> &v);
+  //! Shift out the \c n left elements and at the same time shift in the element \c t at last position \c n times
+  void shift_left(Num_T t, int n = 1);
+  //! Shift in vector \c v at last positions
+  void shift_left(const Vec<Num_T> &v);
+
+  //! Append element \c t to the end of the vector \c v
+  friend Vec<Num_T> concat<>(const Vec<Num_T> &v, Num_T t);
+  //! Insert element \c t at the beginning of the vector \c v
+  friend Vec<Num_T> concat<>(Num_T t, const Vec<Num_T> &v);
+  //! Concatenate vectors \c v1 and \c v2
+  friend Vec<Num_T> concat<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2);
+  //! Concatenate vectors \c v1, \c v2 and \c v3
+  friend Vec<Num_T> concat<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+                             const Vec<Num_T> &v3);
+  //! Concatenate vectors \c v1, \c v2, \c v3 and \c v4
+  friend Vec<Num_T> concat<>(const Vec<Num_T> &v1, const Vec<Num_T> &v2,
+                             const Vec<Num_T> &v3, const Vec<Num_T> &v4);
+  //! Concatenate vectors \c v1, \c v2, \c v3, \c v4 and \c v5
+  friend 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 to elements of vector \c v starting from element \c i
+  void set_subvector(int i, const Vec<Num_T> &v);
+  //! Set subvector defined by indices \c i1 and \c i2 to \c t
+  void set_subvector(int i1, int i2, Num_T t);
+  //! An alias function of set_subvector(i, &v)
+  void replace_mid(int i, const Vec<Num_T> &v);
+  //! Delete element number \c i
+  void del(int i);
+  //! Delete elements from \c i1 to \c i2
+  void del(int i1, int i2);
+  //! Insert element \c t before element with index \c i (0 <= i <= datasize)
+  void ins(int i, Num_T t);
+  //! Insert vector \c v before element with index \c i (0 <= i <= datasize)
+  void ins(int i, const Vec<Num_T> &v);
+
+  //! Assign all elements in vector to \c t
+  Vec<Num_T>& operator=(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 \c t
+  Vec<bin> operator==(Num_T t) const;
+  //! Elementwise not-equal to the scalar \c t
+  Vec<bin> operator!=(Num_T t) const;
+  //! Elementwise less than the scalar \c t
+  Vec<bin> operator<(Num_T t) const;
+  //! Elementwise less than and equal to the scalar \c t
+  Vec<bin> operator<=(Num_T t) const;
+  //! Elementwise greater than the scalar \c t
+  Vec<bin> operator>(Num_T t) const;
+  //! Elementwise greater than and equal to the scalar \c t
+  Vec<bin> operator>=(Num_T t) const;
+
+  //! Compare with vector \c v. Return false if sizes or values differ.
+  bool operator==(const Vec<Num_T> &v) const;
+  //! Compare with vector \c v. Return true if sizes or values differ.
+  bool operator!=(const Vec<Num_T> &v) const;
+
+  //! Index operator without boundary check. Not recommended for use.
+  Num_T &_elem(int i) { return data[i]; }
+  //! Index operator without boundary check. Not recommended for use.
+  const Num_T &_elem(int i) const { return data[i]; }
+
+  //! Get the pointer to the internal structure. Not recommended for use.
+  Num_T *_data() { return data; }
+  //! Get the pointer to the internal structure. Not recommended for 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);
+  //! Check whether index \c i is in the allowed range
+  bool in_range(int i) const { return ((i < datasize) && (i >= 0)); }
+};
+
+//-----------------------------------------------------------------------------------
+// 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(in_range(i), "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(in_range(i), "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(in_range(i), "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(in_range(i), "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
+{
+  if (i1 == -1) i1 = datasize - 1;
+  if (i2 == -1) i2 = datasize - 1;
+
+  it_assert_debug((i1 >= 0) && (i1 <= i2) && (i2 < datasize),
+                  "Vec<>::operator()(i1, i2): Indexing out of range");
+
+  Vec<Num_T> s(i2 - i1 + 1);
+  copy_vector(s.datasize, data + i1, 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_debug(in_range(indexlist(i)), "Vec<>::operator()(ivec &): "
+                    "Index i=" << i << " out of 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(in_range(i), "Vec<>::get(): Index out of range");
+  return data[i];
+}
+
+template<class Num_T> inline
+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, Num_T t)
+{
+  it_assert_debug(in_range(i), "Vec<>::set(i, t): Index out of range");
+  data[i] = t;
+}
+
+//! \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> inline
+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;
+}
+
+//! \cond
+template<>
+Mat<std::complex<double> > Vec<std::complex<double> >::hermitian_transpose() const;
+//! \endcond
+
+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>
+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+=(Num_T t)
+{
+  for (int i = 0;i < datasize;i++)
+    data[i] += t;
+  return *this;
+}
+
+template<class Num_T>
+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>
+Vec<Num_T> operator+(const Vec<Num_T> &v, 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>
+Vec<Num_T> operator+(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>
+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-=(Num_T t)
+{
+  for (int i = 0;i < datasize;i++)
+    data[i] -= t;
+  return *this;
+}
+
+template<class Num_T>
+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>
+Vec<Num_T> operator-(const Vec<Num_T> &v, 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>
+Vec<Num_T> operator-(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>
+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*=(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);
+}
+
+#if defined(HAVE_ZDOTUSUB) || defined(HAVE_ZDOTU_VOID)
+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;
+  blas::zdotusub_(&output, &v1.datasize, v1.data, &incr, v2.data, &incr);
+  return output;
+}
+#endif // HAVE_ZDOTUSUB || HAVE_ZDOTU_VOID
+#endif // HAVE_BLAS
+
+template<class Num_T>
+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
+mat outer_product(const vec &v1, const vec &v2, bool)
+{
+  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
+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
+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>
+Mat<Num_T> outer_product(const Vec<Num_T> &v1, const Vec<Num_T> &v2, bool)
+{
+  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>
+Vec<Num_T> operator*(const Vec<Num_T> &v, 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
+Vec<Num_T> operator*(Num_T t, const Vec<Num_T> &v)
+{
+  return operator*(v, t);
+}
+
+template<class Num_T> inline
+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
+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
+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>
+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");
+  out.set_size(a.datasize);
+  for (int i = 0; i < a.datasize; i++)
+    out.data[i] = a.data[i] * b.data[i];
+}
+
+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)
+{
+  it_assert_debug((a.datasize == b.datasize) && (a.datasize == c.datasize),
+                  "Vec<>::elem_mult_out(): Wrong sizes");
+  out.set_size(a.datasize);
+  for (int i = 0; i < a.datasize; i++)
+    out.data[i] = a.data[i] * b.data[i] * c.data[i];
+}
+
+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)
+{
+  it_assert_debug((a.datasize == b.datasize) && (a.datasize == c.datasize)
+                  && (a.datasize == d.datasize),
+                  "Vec<>::elem_mult_out(): Wrong sizes");
+  out.set_size(a.datasize);
+  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>
+#ifndef _MSC_VER
+inline
+#endif
+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>
+Vec<Num_T> operator/(const Vec<Num_T> &v, 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>
+Vec<Num_T> operator/(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/=(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
+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>
+Vec<Num_T> elem_div(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>
+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,
+                  "Vec<>::elem_div_out(): Wrong sizes");
+  out.set_size(a.datasize);
+  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>
+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>
+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>
+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);
+  if (pos > 0) {
+    copy_vector(pos, data, temp1.data);
+    if (pos < datasize) {
+      Vec<Num_T> temp2(datasize - pos);
+      copy_vector(datasize - pos, &data[pos], temp2.data);
+      (*this) = temp2;
+    }
+    else {
+      set_size(0);
+    }
+  }
+  return temp1;
+}
+
+template<class Num_T>
+void Vec<Num_T>::shift_right(Num_T t, 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--] = t;
+}
+
+template<class Num_T>
+void Vec<Num_T>::shift_right(const Vec<Num_T> &v)
+{
+  for (int i = datasize - 1; i >= v.datasize; i--)
+    data[i] = data[i-v.datasize];
+  for (int i = 0; i < v.datasize; i++)
+    data[i] = v[i];
+}
+
+template<class Num_T>
+void Vec<Num_T>::shift_left(Num_T t, 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++] = t;
+}
+
+template<class Num_T>
+void Vec<Num_T>::shift_left(const Vec<Num_T> &v)
+{
+  for (int i = 0; i < datasize - v.datasize; i++)
+    data[i] = data[i+v.datasize];
+  for (int i = datasize - v.datasize; i < datasize; i++)
+    data[i] = v[i-datasize+v.datasize];
+}
+
+template<class Num_T>
+Vec<Num_T> concat(const Vec<Num_T> &v, Num_T t)
+{
+  int size = v.size();
+  Vec<Num_T> temp(size + 1);
+  copy_vector(size, v.data, temp.data);
+  temp(size) = t;
+  return temp;
+}
+
+template<class Num_T>
+Vec<Num_T> concat(Num_T t, const Vec<Num_T> &v)
+{
+  int size = v.size();
+  Vec<Num_T> temp(size + 1);
+  temp(0) = t;
+  copy_vector(size, v.data, &temp.data[1]);
+  return temp;
+}
+
+template<class Num_T>
+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>
+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>
+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>
+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>
+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) && (i + v.datasize <= datasize),
+                  "Vec<>::set_subvector(int, const Vec<> &): "
+                  "Index out of range or too long input vector");
+  copy_vector(v.datasize, v.data, data + i);
+}
+
+template<class Num_T> inline
+void Vec<Num_T>::set_subvector(int i1, int i2, Num_T t)
+{
+  if (i1 == -1) i1 = datasize - 1;
+  if (i2 == -1) i2 = datasize - 1;
+  it_assert_debug((i1 >= 0) && (i1 <= i2) && (i2 < datasize),
+                  "Vec<>::set_subvector(int, int, Num_T): Indexing out "
+                  "of range");
+  for (int i = i1; i <= i2; i++)
+    data[i] = t;
+}
+
+template<class Num_T> inline
+void Vec<Num_T>::replace_mid(int i, const Vec<Num_T> &v)
+{
+  it_assert_debug((i >= 0) && ((i + v.length()) <= datasize),
+                  "Vec<>::replace_mid(): Indexing out of range");
+  copy_vector(v.datasize, v.data, &data[i]);
+}
+
+template<class Num_T>
+void Vec<Num_T>::del(int index)
+{
+  it_assert_debug(in_range(index), "Vec<>::del(int): 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)
+{
+  if (i1 == -1) i1 = datasize - 1;
+  if (i2 == -1) i2 = datasize - 1;
+  it_assert_debug((i1 >= 0) && (i1 <= i2) && (i2 < datasize),
+                  "Vec<>::del(int, int): Indexing 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 t)
+{
+  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] = t;
+  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> &v)
+{
+  it_assert_debug((index >= 0) && (index <= datasize),
+                  "Vec<>::ins(): Index out of range");
+  Vec<Num_T> Temp(*this);
+
+  set_size(datasize + v.length(), false);
+  copy_vector(index, Temp.data, data);
+  copy_vector(v.size(), v.data, &data[index]);
+  copy_vector(Temp.datasize - index, Temp.data + index, data + index + v.size());
+}
+
+template<class Num_T> inline
+Vec<Num_T>& Vec<Num_T>::operator=(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>
+Vec<Num_T>& Vec<Num_T>::operator=(const Mat<Num_T> &m)
+{
+  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 of input matrix");
+  return *this;
+}
+
+template<class Num_T> inline
+Vec<Num_T>& Vec<Num_T>::operator=(const char *values)
+{
+  set(values);
+  return *this;
+}
+
+template<class Num_T>
+bvec Vec<Num_T>::operator==(Num_T t) const
+{
+  it_assert_debug(datasize > 0, "Vec<>::operator==(): Wrong size");
+  bvec temp(datasize);
+  for (int i = 0; i < datasize; i++)
+    temp(i) = (data[i] == t);
+  return temp;
+}
+
+template<class Num_T>
+bvec Vec<Num_T>::operator!=(Num_T t) const
+{
+  it_assert_debug(datasize > 0, "Vec<>::operator!=(): Wrong size");
+  bvec temp(datasize);
+  for (int i = 0; i < datasize; i++)
+    temp(i) = (data[i] != t);
+  return temp;
+}
+
+//! \cond
+template<>
+bvec Vec<std::complex<double> >::operator<(std::complex<double>) const;
+//! \endcond
+
+template<class Num_T>
+bvec Vec<Num_T>::operator<(Num_T t) const
+{
+  it_assert_debug(datasize > 0, "Vec<>::operator<(): Wrong size");
+  bvec temp(datasize);
+  for (int i = 0; i < datasize; i++)
+    temp(i) = (data[i] < t);
+  return temp;
+}
+
+//! \cond
+template<>
+bvec Vec<std::complex<double> >::operator<=(std::complex<double>) const;
+//! \endcond
+
+template<class Num_T>
+bvec Vec<Num_T>::operator<=(Num_T t) const
+{
+  it_assert_debug(datasize > 0, "Vec<>::operator<=(): Wrong size");
+  bvec temp(datasize);
+  for (int i = 0; i < datasize; i++)
+    temp(i) = (data[i] <= t);
+  return temp;
+}
+
+//! \cond
+template<>
+bvec Vec<std::complex<double> >::operator>(std::complex<double>) const;
+//! \endcond
+
+template<class Num_T>
+bvec Vec<Num_T>::operator>(Num_T t) const
+{
+  it_assert_debug(datasize > 0, "Vec<>::operator>(): Wrong size");
+  bvec temp(datasize);
+  for (int i = 0; i < datasize; i++)
+    temp(i) = (data[i] > t);
+  return temp;
+}
+
+//! \cond
+template<>
+bvec Vec<std::complex<double> >::operator>=(std::complex<double>) const;
+//! \endcond
+
+template<class Num_T>
+bvec Vec<Num_T>::operator>=(Num_T t) const
+{
+  it_assert_debug(datasize > 0, "Vec<>::operator>=(): Wrong size");
+  bvec temp(datasize);
+  for (int i = 0; i < datasize; i++)
+    temp(i) = (data[i] >= t);
+  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 {
+      is.get(c);
+
+      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 = static_cast<char>(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 vec operator+(const vec &v1, const vec &v2);
+extern template cvec operator+(const cvec &v1, const cvec &v2);
+extern template ivec operator+(const ivec &v1, const ivec &v2);
+extern template svec operator+(const svec &v1, const svec &v2);
+extern template bvec operator+(const bvec &v1, const bvec &v2);
+
+extern template vec operator+(const vec &v1, double t);
+extern template cvec operator+(const cvec &v1, std::complex<double> t);
+extern template ivec operator+(const ivec &v1, int t);
+extern template svec operator+(const svec &v1, short t);
+extern template bvec operator+(const bvec &v1, bin t);
+
+extern template vec operator+(double t, const vec &v1);
+extern template cvec operator+(std::complex<double> t, const cvec &v1);
+extern template ivec operator+(int t, const ivec &v1);
+extern template svec operator+(short t, const svec &v1);
+extern template bvec operator+(bin t, const bvec &v1);
+
+// subtraction operator
+
+extern template vec operator-(const vec &v1, const vec &v2);
+extern template cvec operator-(const cvec &v1, const cvec &v2);
+extern template ivec operator-(const ivec &v1, const ivec &v2);
+extern template svec operator-(const svec &v1, const svec &v2);
+extern template bvec operator-(const bvec &v1, const bvec &v2);
+
+extern template vec operator-(const vec &v, double t);
+extern template cvec operator-(const cvec &v, std::complex<double> t);
+extern template ivec operator-(const ivec &v, int t);
+extern template svec operator-(const svec &v, short t);
+extern template bvec operator-(const bvec &v, bin t);
+
+extern template vec operator-(double t, const vec &v);
+extern template cvec operator-(std::complex<double> t, const cvec &v);
+extern template ivec operator-(int t, const ivec &v);
+extern template svec operator-(short t, const svec &v);
+extern template bvec operator-(bin t, const bvec &v);
+
+// unary minus
+
+extern template vec operator-(const vec &v);
+extern template cvec operator-(const cvec &v);
+extern template ivec operator-(const ivec &v);
+extern template svec operator-(const svec &v);
+extern template bvec operator-(const bvec &v);
+
+// multiplication operator
+
+#if !defined(HAVE_BLAS)
+extern template double dot(const vec &v1, const vec &v2);
+#if !(defined(HAVE_ZDOTUSUB) || defined(HAVE_ZDOTU_VOID))
+extern template std::complex<double> dot(const cvec &v1, const cvec &v2);
+#endif // !(HAVE_ZDOTUSUB || HAVE_ZDOTU_VOID)
+#endif // HAVE_BLAS
+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 mat outer_product(const vec &v1, const vec &v2,
+                                    bool hermitian);
+#endif
+extern template imat outer_product(const ivec &v1, const ivec &v2,
+                                     bool hermitian);
+extern template smat outer_product(const svec &v1, const svec &v2,
+                                     bool hermitian);
+extern template bmat outer_product(const bvec &v1, const bvec &v2,
+                                     bool hermitian);
+
+extern template vec operator*(const vec &v, double t);
+extern template cvec operator*(const cvec &v, std::complex<double> t);
+extern template ivec operator*(const ivec &v, int t);
+extern template svec operator*(const svec &v, short t);
+extern template bvec operator*(const bvec &v, bin t);
+
+extern template vec operator*(double t, const vec &v);
+extern template cvec operator*(std::complex<double> t, const cvec &v);
+extern template ivec operator*(int t, const ivec &v);
+extern template svec operator*(short t, const svec &v);
+extern template bvec operator*(bin t, const bvec &v);
+
+// elementwise multiplication
+
+extern template vec elem_mult(const vec &a, const vec &b);
+extern template cvec elem_mult(const cvec &a, const cvec &b);
+extern template ivec elem_mult(const ivec &a, const ivec &b);
+extern template svec elem_mult(const svec &a, const svec &b);
+extern template 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 vec elem_mult(const vec &a, const vec &b, const vec &c);
+extern template cvec elem_mult(const cvec &a, const cvec &b, const cvec &c);
+extern template ivec elem_mult(const ivec &a, const ivec &b, const ivec &c);
+extern template svec elem_mult(const svec &a, const svec &b, const svec &c);
+extern template 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 vec elem_mult(const vec &a, const vec &b,
+                                const vec &c, const vec &d);
+extern template cvec elem_mult(const cvec &a, const cvec &b,
+                                 const cvec &c, const cvec &d);
+extern template ivec elem_mult(const ivec &a, const ivec &b,
+                                 const ivec &c, const ivec &d);
+extern template svec elem_mult(const svec &a, const svec &b,
+                                 const svec &c, const svec &d);
+extern template 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 vec operator/(const vec &v, double t);
+extern template cvec operator/(const cvec &v, std::complex<double> t);
+extern template ivec operator/(const ivec &v, int t);
+extern template svec operator/(const svec &v, short t);
+extern template bvec operator/(const bvec &v, bin t);
+
+extern template vec operator/(double t, const vec &v);
+extern template cvec operator/(std::complex<double> t, const cvec &v);
+extern template ivec operator/(int t, const ivec &v);
+extern template svec operator/(short t, const svec &v);
+extern template bvec operator/(bin t, const bvec &v);
+
+// elementwise division operator
+
+extern template vec elem_div(const vec &a, const vec &b);
+extern template cvec elem_div(const cvec &a, const cvec &b);
+extern template ivec elem_div(const ivec &a, const ivec &b);
+extern template svec elem_div(const svec &a, const svec &b);
+extern template bvec elem_div(const bvec &a, const bvec &b);
+
+extern template vec elem_div(double t, const vec &v);
+extern template cvec elem_div(std::complex<double> t, const cvec &v);
+extern template ivec elem_div(int t, const ivec &v);
+extern template svec elem_div(short t, const svec &v);
+extern template 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 vec concat(const vec &v, double a);
+extern template cvec concat(const cvec &v, std::complex<double> a);
+extern template ivec concat(const ivec &v, int a);
+extern template svec concat(const svec &v, short a);
+extern template bvec concat(const bvec &v, bin a);
+
+extern template vec concat(double a, const vec &v);
+extern template cvec concat(std::complex<double> a, const cvec &v);
+extern template ivec concat(int a, const ivec &v);
+extern template svec concat(short a, const svec &v);
+extern template bvec concat(bin a, const bvec &v);
+
+extern template vec concat(const vec &v1, const vec &v2);
+extern template cvec concat(const cvec &v1, const cvec &v2);
+extern template ivec concat(const ivec &v1, const ivec &v2);
+extern template svec concat(const svec &v1, const svec &v2);
+extern template bvec concat(const bvec &v1, const bvec &v2);
+
+extern template vec concat(const vec &v1, const vec &v2, const vec &v3);
+extern template cvec concat(const cvec &v1, const cvec &v2, const cvec &v3);
+extern template ivec concat(const ivec &v1, const ivec &v2, const ivec &v3);
+extern template svec concat(const svec &v1, const svec &v2, const svec &v3);
+extern template bvec concat(const bvec &v1, const bvec &v2, const bvec &v3);
+
+extern template vec concat(const vec &v1, const vec &v2,
+                             const vec &v3, const vec &v4);
+extern template cvec concat(const cvec &v1, const cvec &v2,
+                              const cvec &v3, const cvec &v4);
+extern template ivec concat(const ivec &v1, const ivec &v2,
+                              const ivec &v3, const ivec &v4);
+extern template svec concat(const svec &v1, const svec &v2,
+                              const svec &v3, const svec &v4);
+extern template bvec concat(const bvec &v1, const bvec &v2,
+                              const bvec &v3, const bvec &v4);
+
+extern template vec concat(const vec &v1, const vec &v2, const vec &v3,
+                             const vec &v4, const vec &v5);
+extern template cvec concat(const cvec &v1, const cvec &v2, const cvec &v3,
+                              const cvec &v4, const cvec &v5);
+extern template ivec concat(const ivec &v1, const ivec &v2, const ivec &v3,
+                              const ivec &v4, const ivec &v5);
+extern template svec concat(const svec &v1, const svec &v2, const svec &v3,
+                              const svec &v4, const svec &v5);
+extern template 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: library/bdm/base/itpp/base/zdotusub.f
===================================================================
--- library/bdm/base/itpp/base/zdotusub.f (revision 812)
+++ library/bdm/base/itpp/base/zdotusub.f (revision 812)
@@ -0,0 +1,16 @@
+c     zdotusub.f
+c
+c     The program is a fortran wrapper for zdotu.
+c     Witten by Keita Teranishi.  2/11/1998
+c     Interface modified by Adam Piatyszek to match ACML zdotusub_()
+c
+      subroutine zdotusub(dotu,n,x,incx,y,incy)
+c
+      external zdotu
+      double complex zdotu,dotu
+      integer n,incx,incy
+      double complex x(*),y(*)
+c
+      dotu=zdotu(n,x,incx,y,incy)
+      return
+      end
Index: library/bdm/base/itpp/base/operators.h
===================================================================
--- library/bdm/base/itpp/base/operators.h (revision 812)
+++ library/bdm/base/itpp/base/operators.h (revision 812)
@@ -0,0 +1,1100 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/binary.cpp
===================================================================
--- library/bdm/base/itpp/base/binary.cpp (revision 812)
+++ library/bdm/base/itpp/base/binary.cpp (revision 812)
@@ -0,0 +1,53 @@
+/*!
+ * \file
+ * \brief Binary class implemenations
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/binary.h>
+#include <iostream>
+
+
+namespace itpp
+{
+
+std::ostream &operator<<(std::ostream &output, const bin &inbin)
+{
+  output << static_cast<int>(inbin);
+  return output;
+}
+
+std::istream &operator>>(std::istream &input, bin &outbin)
+{
+  int tmp;
+  input >> tmp;
+  it_assert((tmp == 0) || (tmp == 1),
+            "bin::operator>>(): input value must be 0 or 1");
+  outbin = tmp;
+  return input;
+}
+
+} // namespace itpp
Index: library/bdm/base/itpp/base/help_functions.h
===================================================================
--- library/bdm/base/itpp/base/help_functions.h (revision 812)
+++ library/bdm/base/itpp/base/help_functions.h (revision 812)
@@ -0,0 +1,264 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/random.h
===================================================================
--- library/bdm/base/itpp/base/random.h (revision 812)
+++ library/bdm/base/itpp/base/random.h (revision 812)
@@ -0,0 +1,805 @@
+/*!
+ * \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-2010  (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();
+
+  //! 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();
+  }
+
+  //! Dummy assignment operator - MSVC++ warning C4512
+  Complex_Normal_RNG & operator=(const Complex_Normal_RNG&) { return *this; }
+
+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: library/bdm/base/itpp/base/mat.h
===================================================================
--- library/bdm/base/itpp/base/mat.h (revision 812)
+++ library/bdm/base/itpp/base/mat.h (revision 812)
@@ -0,0 +1,2090 @@
+/*!
+ * \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-2010  (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>
+Mat<Num_T> concat_horizontal(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+//! Vertical concatenation of two matrices
+template<class Num_T>
+Mat<Num_T> concat_vertical(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+
+//! Addition of two matrices
+template<class Num_T>
+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>
+Mat<Num_T> operator+(const Mat<Num_T> &m, Num_T t);
+//! Addition of a scalar and a matrix
+template<class Num_T>
+Mat<Num_T> operator+(Num_T t, const Mat<Num_T> &m);
+
+//! Subtraction of two matrices
+template<class Num_T>
+Mat<Num_T> operator-(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+//! Subtraction of matrix and scalar
+template<class Num_T>
+Mat<Num_T> operator-(const Mat<Num_T> &m, Num_T t);
+//! Subtraction of scalar and matrix
+template<class Num_T>
+Mat<Num_T> operator-(Num_T t, const Mat<Num_T> &m);
+//! Negation of matrix
+template<class Num_T>
+Mat<Num_T> operator-(const Mat<Num_T> &m);
+
+//! Multiplication of two matrices
+template<class Num_T>
+Mat<Num_T> operator*(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+//! Multiplication of matrix and vector
+template<class Num_T>
+Vec<Num_T> operator*(const Mat<Num_T> &m, const Vec<Num_T> &v);
+//! Multiplication of vector and matrix (matrix must be a row vector)
+template<class Num_T>
+Mat<Num_T> operator*(const Vec<Num_T> &v, const Mat<Num_T> &m);
+//! Multiplication of matrix and scalar
+template<class Num_T>
+Mat<Num_T> operator*(const Mat<Num_T> &m, Num_T t);
+//! Multiplication of scalar and matrix
+template<class Num_T>
+Mat<Num_T> operator*(Num_T t, const Mat<Num_T> &m);
+
+//! Element wise multiplication of two matrices
+template<class Num_T>
+Mat<Num_T> elem_mult(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+//! Element wise multiplication of two matrices, storing the result in matrix \c out
+template<class Num_T>
+void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                   Mat<Num_T> &out);
+//! Element wise multiplication of three matrices, storing the result in matrix \c out
+template<class Num_T>
+void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                   const Mat<Num_T> &m3, Mat<Num_T> &out);
+//! Element wise multiplication of four matrices, storing the result in matrix \c out
+template<class Num_T>
+void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                   const Mat<Num_T> &m3, const Mat<Num_T> &m4,
+                   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> &m1, Mat<Num_T> &m2);
+//! 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> &m1, const Mat<Num_T> &m2);
+
+//! Division of matrix and scalar
+template<class Num_T>
+Mat<Num_T> operator/(const Mat<Num_T> &m, Num_T t);
+
+//! Element wise division of two matrices
+template<class Num_T>
+Mat<Num_T> elem_div(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+//! Element wise division of two matrices, storing the result in matrix \c out
+template<class Num_T>
+void elem_div_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                  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> &m1, const Mat<Num_T> &m2);
+
+// -------------------------------------------------------------------------------------
+// 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 (rows, cols). An element factory \c f can be specified.
+  Mat(int rows, int cols, 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);
+  //! Construct a matrix from a column vector \c v. An element factory \c f can be specified.
+  Mat(const Vec<Num_T> &v, const Factory &f = DEFAULT_FACTORY);
+  //! Set matrix equal to values in string \c str. 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 \c str. 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. An element factory \c f
+   * can be specified.
+   *
+   * By default the matrix is stored as a row-major matrix (i.e. listing
+   * elements in sequence beginning with the first column).
+   */
+  Mat(const Num_T *c_array, int rows, int cols, bool row_major = 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 rows, int cols, 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 i using linear addressing (by rows)
+  const Num_T &operator()(int i) const;
+  //! Get element \c i using linear addressing (by rows)
+  Num_T &operator()(int i);
+  //! 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, Num_T t);
+
+  /*!
+    \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.
+  */
+  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.
+  */
+  Mat<Num_T> get(int r1, int r2, int c1, int c2) const;
+
+  //! Get row \c r
+  Vec<Num_T> get_row(int r) const;
+  //! Get rows \c r1 through \c r2
+  Mat<Num_T> get_rows(int r1, int r2) const;
+  //! Get the rows specified by \c indexlist
+  Mat<Num_T> get_rows(const Vec<int> &indexlist) const;
+  //! Get column \c c
+  Vec<Num_T> get_col(int c) const;
+  //! Get columns \c c1 through \c c2
+  Mat<Num_T> get_cols(int c1, int c2) const;
+  //! Get the columns specified by \c indexlist
+  Mat<Num_T> get_cols(const Vec<int> &indexlist) const;
+  //! Set row \c r to vector \c v
+  void set_row(int r, const Vec<Num_T> &v);
+  //! Set column \c c to vector \c v
+  void set_col(int c, const Vec<Num_T> &v);
+  //! Set rows to matrix \c m, staring from row \c r
+  void set_rows(int r, const Mat<Num_T> &m);
+  //! Set columns 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, 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 v at row number \c r. The matrix can be empty.
+  void ins_row(int r, const Vec<Num_T> &v);
+  //! Insert vector \c v at column number \c c. The matrix can be empty.
+  void ins_col(int c, const Vec<Num_T> &v);
+  //! Append vector \c v to the bottom of the matrix. The matrix can be empty.
+  void append_row(const Vec<Num_T> &v);
+  //! Append vector \c v to the right side of the matrix. The matrix can be empty.
+  void append_col(const Vec<Num_T> &v);
+
+  //! Matrix transpose
+  Mat<Num_T> transpose() const;
+  //! Matrix transpose
+  Mat<Num_T> T() const { return this->transpose(); }
+  //! Hermitian matrix transpose (conjugate transpose)
+  Mat<Num_T> hermitian_transpose() const;
+  //! Hermitian matrix transpose (conjugate transpose)
+  Mat<Num_T> H() const { return this->hermitian_transpose(); }
+
+  //! Concatenate the matrices \c m1 and \c m2 horizontally
+  friend 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 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 *str);
+
+  //! 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 Mat<Num_T> operator+<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+  //! Addition of matrix and scalar
+  friend Mat<Num_T> operator+<>(const Mat<Num_T> &m, Num_T t);
+  //! Addition of scalar and matrix
+  friend 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 Mat<Num_T> operator-<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+  //! Subtraction of scalar from matrix
+  friend Mat<Num_T> operator-<>(const Mat<Num_T> &m, Num_T t);
+  //! Subtract matrix from scalar
+  friend Mat<Num_T> operator-<>(Num_T t, const Mat<Num_T> &m);
+  //! Subtraction of matrix
+  friend 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 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 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 Mat<Num_T> operator*<>(const Vec<Num_T> &v, const Mat<Num_T> &m);
+  //! Multiplication of matrix and scalar
+  friend Mat<Num_T> operator*<>(const Mat<Num_T> &m, Num_T t);
+  //! Multiplication of scalar and matrix
+  friend Mat<Num_T> operator*<>(Num_T t, const Mat<Num_T> &m);
+
+  //! Element wise multiplication of two matrices
+  friend Mat<Num_T> elem_mult<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+  //! Element wise multiplication of two matrices, storing the result in matrix \c out
+  friend void elem_mult_out<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                              Mat<Num_T> &out);
+  //! Element wise multiplication of three matrices, storing the result in matrix \c out
+  friend void elem_mult_out<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                              const Mat<Num_T> &m3, Mat<Num_T> &out);
+  //! Element wise multiplication of four matrices, storing the result in matrix \c out
+  friend void elem_mult_out<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                              const Mat<Num_T> &m3, const Mat<Num_T> &m4,
+                              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> &m1, Mat<Num_T> &m2);
+  //! 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> &m1, const Mat<Num_T> &m2);
+
+  //! Division by a scalar
+  Mat<Num_T>& operator/=(Num_T t);
+  //! Division of matrix with scalar
+  friend Mat<Num_T> operator/<>(const Mat<Num_T> &m, Num_T t);
+  //! Element-wise division with the current matrix
+  Mat<Num_T>& operator/=(const Mat<Num_T> &m);
+
+  //! Element wise division of two matrices
+  friend Mat<Num_T> elem_div<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2);
+  //! Element wise division of two matrices, storing the result in matrix \c out
+  friend void elem_div_out<>(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                             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> &m1, const Mat<Num_T> &m2);
+
+  //! 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 i using linear addressing (by rows) without boundary check (not recommended to use)
+  Num_T &_elem(int i) { return data[i]; }
+  //! Get element \c i using linear addressing (by rows) without boundary check (not recommended to use)
+  const Num_T &_elem(int i) const { return data[i]; }
+
+  //! Access of the internal data structure (not recommended to use)
+  Num_T *_data() { return data; }
+  //! Access to the internal data structure (not recommended to use)
+  const Num_T *_data() const { return data; }
+  //! Access to the internal data structure (not recommended to use)
+  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;
+
+private:
+  //! Check whether element (r,c) is within the matrix
+  bool in_range(int r, int c) const {
+    return ((r >= 0) && (r < no_rows) && (c >= 0) && (c < no_cols));
+  }
+  //! Check whether row \c r is in the allowed range
+  bool row_in_range(int r) const { return ((r >= 0) && (r < no_rows)); }
+  //! Check whether column \c c is in the allowed range
+  bool col_in_range(int c) const { return ((c >= 0) && (c < no_cols)); }
+  //! Check whether element \c i is in the allowed range
+  bool in_range(int i) const { return ((i >= 0) && (i < datasize)); }
+};
+
+// -------------------------------------------------------------------------------------
+// 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 rows, int cols, const Factory &f) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
+{
+  it_assert_debug((rows >= 0) && (cols >= 0), "Mat<>::Mat(): Wrong size");
+  alloc(rows, cols);
+}
+
+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> &v, const Factory &f) :
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
+{
+  int size = v.size();
+  alloc(size, 1);
+  copy_vector(size, v._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>
+Mat<Num_T>::Mat(const Num_T *c_array, int rows, int cols, bool row_major,
+                const Factory &f):
+    datasize(0), no_rows(0), no_cols(0), data(0), factory(f)
+{
+  alloc(rows, cols);
+  if (!row_major)
+    copy_vector(datasize, c_array, data);
+  else
+    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 rows, int cols, bool copy)
+{
+  it_assert_debug((rows >= 0) && (cols >= 0),
+                  "Mat<>::set_size(): Wrong size");
+  // check if we have to resize the current matrix
+  if ((no_rows == rows) && (no_cols == cols))
+    return;
+  // check if one of dimensions is zero
+  if ((rows == 0) || (cols == 0)) {
+    free();
+    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 < rows) ? no_rows : rows;
+    int min_c = (no_cols < cols) ? no_cols : cols;
+    // allocate new memory
+    alloc(rows, cols);
+    // 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 < rows; ++i)
+      for (int j = 0; j < cols; ++j)
+        data[i+j*rows] = Num_T(0);
+    for (int j = min_c; j < cols; ++j)
+      for (int i = 0; i < min_r; ++i)
+        data[i+j*rows] = Num_T(0);
+    // delete old elements
+    destroy_elements(tmp, old_datasize);
+  }
+  // if possible, reuse the allocated memory
+  else if (datasize == rows * cols) {
+    no_rows = rows;
+    no_cols = cols;
+  }
+  // finally release old memory and allocate a new one
+  else {
+    free();
+    alloc(rows, cols);
+  }
+}
+
+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(in_range(r, c),
+                  "Mat<>::operator(): Indexing 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(in_range(r, c),
+                  "Mat<>::operator(): Indexing out of range");
+  return data[r+c*no_rows];
+}
+
+template<class Num_T> inline
+Num_T& Mat<Num_T>::operator()(int i)
+{
+  it_assert_debug(in_range(i), "Mat<>::operator(): Index out of range");
+  return data[i];
+}
+
+template<class Num_T> inline
+const Num_T& Mat<Num_T>::operator()(int i) const
+{
+  it_assert_debug(in_range(i), "Mat<>::operator(): Index out of range");
+  return data[i];
+}
+
+template<class Num_T> inline
+const Num_T& Mat<Num_T>::get(int r, int c) const
+{
+  it_assert_debug(in_range(r, c), "Mat<>::get(): Indexing out of range");
+  return data[r+c*no_rows];
+}
+
+template<class Num_T> inline
+void Mat<Num_T>::set(int r, int c, Num_T t)
+{
+  it_assert_debug(in_range(r, c), "Mat<>::set(): Indexing out of range");
+  data[r+c*no_rows] = t;
+}
+
+
+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 occurrence 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 we need to add new columns
+          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 columns
+            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
+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) && (r1 <= r2) && (r2 < no_rows) &&
+                  (c1 >= 0) && (c1 <= c2) && (c2 < no_cols),
+                  "Mat<>::operator()(r1, r2, c1, c2): Wrong indexing");
+
+  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
+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
+Vec<Num_T> Mat<Num_T>::get_row(int r) const
+{
+  it_assert_debug(row_in_range(r), "Mat<>::get_row(): Index out of range");
+  Vec<Num_T> a(no_cols);
+
+  copy_vector(no_cols, data + r, no_rows, a._data(), 1);
+  return a;
+}
+
+template<class Num_T>
+Mat<Num_T> Mat<Num_T>::get_rows(int r1, int r2) const
+{
+  it_assert_debug((r1 >= 0) && (r1 <= r2) && (r2 < no_rows),
+                  "Mat<>::get_rows(): Wrong indexing");
+  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>
+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(row_in_range(indexlist(i)),
+                    "Mat<>::get_rows(indexlist): Indexing 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
+Vec<Num_T> Mat<Num_T>::get_col(int c) const
+{
+  it_assert_debug(col_in_range(c), "Mat<>::get_col(): Index out of range");
+  Vec<Num_T> a(no_rows);
+
+  copy_vector(no_rows, data + c*no_rows, a._data());
+
+  return a;
+}
+
+template<class Num_T>
+Mat<Num_T> Mat<Num_T>::get_cols(int c1, int c2) const
+{
+  it_assert_debug((c1 >= 0) && (c1 <= c2) && (c2 < no_cols),
+                  "Mat<>::get_cols(): Wrong indexing");
+  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>
+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(col_in_range(indexlist(i)),
+                    "Mat<>::get_cols(indexlist): Indexing 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 r, const Vec<Num_T> &v)
+{
+  it_assert_debug(row_in_range(r), "Mat<>::set_row(): Index out of range");
+  it_assert_debug(v.size() == no_cols,
+                  "Mat<>::set_row(): Wrong size of input vector");
+  copy_vector(v.size(), v._data(), 1, data + r, no_rows);
+}
+
+template<class Num_T> inline
+void Mat<Num_T>::set_col(int c, const Vec<Num_T> &v)
+{
+  it_assert_debug(col_in_range(c), "Mat<>::set_col(): Index out of range");
+  it_assert_debug(v.size() == no_rows,
+                  "Mat<>::set_col(): Wrong size of input vector");
+  copy_vector(v.size(), v._data(), data + c*no_rows);
+}
+
+
+template<class Num_T>
+void Mat<Num_T>::set_rows(int r, const Mat<Num_T> &m)
+{
+  it_assert_debug(row_in_range(r), "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>
+void Mat<Num_T>::set_cols(int c, const Mat<Num_T> &m)
+{
+  it_assert_debug(col_in_range(c), "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(row_in_range(to) && row_in_range(from),
+                  "Mat<>::copy_row(): Indexing 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(col_in_range(to) && col_in_range(from),
+                  "Mat<>::copy_col(): Indexing 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(row_in_range(r1) && row_in_range(r2),
+                  "Mat<>::swap_rows(): Indexing 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(col_in_range(c1) && col_in_range(c2),
+                  "Mat<>::swap_cols(): Indexing out of range");
+  if (c1 == c2)
+    return;
+
+  swap_vector(no_rows, data + c1*no_rows, data + c2*no_rows);
+}
+
+template<class Num_T>
+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<>::set_submatrix(): Indexing out of range "
+                  "or wrong input matrix");
+  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, 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) && (r1 <= r2) && (r2 < no_rows) &&
+                  (c1 >= 0) && (c1 <= c2) && (c2 < no_cols),
+                  "Mat<>::set_submatrix(): Wrong indexing");
+
+  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>
+void Mat<Num_T>::del_row(int r)
+{
+  it_assert_debug(row_in_range(r), "Mat<>::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>
+void Mat<Num_T>::del_rows(int r1, int r2)
+{
+  it_assert_debug((r1 >= 0) && (r1 <= r2) && (r2 < no_rows),
+                  "Mat<>::del_rows(): Indexing 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>
+void Mat<Num_T>::del_col(int c)
+{
+  it_assert_debug(col_in_range(c), "Mat<>::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>
+void Mat<Num_T>::del_cols(int c1, int c2)
+{
+  it_assert_debug((c1 >= 0) && (c1 <= c2) && (c2 < no_cols),
+                  "Mat<>::del_cols(): Indexing 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>
+void Mat<Num_T>::ins_row(int r, const Vec<Num_T> &v)
+{
+  it_assert_debug((r >= 0) && (r <= no_rows),
+                  "Mat<>::ins_row(): Index out of range");
+  it_assert_debug((v.size() == no_cols) || (no_rows == 0),
+                  "Mat<>::ins_row(): Wrong size of the input vector");
+
+  if (no_cols == 0) {
+    no_cols = v.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, v._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>
+void Mat<Num_T>::ins_col(int c, const Vec<Num_T> &v)
+{
+  it_assert_debug((c >= 0) && (c <= no_cols),
+                  "Mat<>::ins_col(): Index out of range");
+  it_assert_debug((v.size() == no_rows) || (no_cols == 0),
+                  "Mat<>::ins_col(): Wrong size of the input vector");
+
+  if (no_rows == 0) {
+    no_rows = v.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, v._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> &v)
+{
+  ins_row(no_rows, v);
+}
+
+template<class Num_T> inline
+void Mat<Num_T>::append_col(const Vec<Num_T> &v)
+{
+  ins_col(no_cols, v);
+}
+
+template<class Num_T>
+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<>
+cmat cmat::hermitian_transpose() const;
+//! \endcond
+
+template<class Num_T>
+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>
+Mat<Num_T> concat_horizontal(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+{
+  // if one of the input matrix is empty just copy the other one as a result
+  if (m1.no_cols == 0)
+    return m2;
+  if (m2.no_cols == 0)
+    return m1;
+  it_assert_debug(m1.no_rows == m2.no_rows,
+                  "Mat<>::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>
+Mat<Num_T> concat_vertical(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+{
+  // if one of the input matrix is empty just copy the other one as a result
+  if (m1.no_rows == 0)
+    return m2;
+  if (m2.no_rows == 0)
+    return m1;
+  it_assert_debug(m1.no_cols == m2.no_cols,
+                  "Mat<>::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<>::operator=(): Wrong size of the input vector");
+  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 *str)
+{
+  set(str);
+  return *this;
+}
+
+//-------------------- Templated friend functions --------------------------
+
+template<class Num_T>
+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>
+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<>::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>
+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>
+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>
+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<>::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>
+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<>::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>
+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>
+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>
+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::operator*=(const mat &m);
+template<> cmat& cmat::operator*=(const cmat &m);
+#endif
+
+template<class Num_T>
+Mat<Num_T>& Mat<Num_T>::operator*=(const Mat<Num_T> &m)
+{
+  it_assert_debug(no_cols == m.no_rows, "Mat<>::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<> mat operator*(const mat &m1, const mat &m2);
+template<> cmat operator*(const cmat &m1, const cmat &m2);
+#endif
+
+
+template<class Num_T>
+Mat<Num_T> operator*(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+{
+  it_assert_debug(m1.no_cols == m2.no_rows,
+                  "Mat<>::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<> vec operator*(const mat &m, const vec &v);
+template<> cvec operator*(const cmat &m, const cvec &v);
+#endif
+
+template<class Num_T>
+Vec<Num_T> operator*(const Mat<Num_T> &m, const Vec<Num_T> &v)
+{
+  it_assert_debug(m.no_cols == v.size(),
+                  "Mat<>::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>
+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>
+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> operator*(Num_T t, const Mat<Num_T> &m)
+{
+  return operator*(m, t);
+}
+
+template<class Num_T> inline
+Mat<Num_T> elem_mult(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+{
+  Mat<Num_T> out;
+  elem_mult_out(m1, m2, out);
+  return out;
+}
+
+template<class Num_T>
+void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                   Mat<Num_T> &out)
+{
+  it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols),
+                  "Mat<>::elem_mult_out(): Wrong sizes");
+  out.set_size(m1.no_rows, m1.no_cols);
+  for (int i = 0; i < out.datasize; i++)
+    out.data[i] = m1.data[i] * m2.data[i];
+}
+
+template<class Num_T>
+void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                   const Mat<Num_T> &m3, Mat<Num_T> &out)
+{
+  it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_rows == m3.no_rows)
+                  && (m1.no_cols == m2.no_cols) && (m1.no_cols == m3.no_cols),
+                  "Mat<>::elem_mult_out(): Wrong sizes");
+  out.set_size(m1.no_rows, m1.no_cols);
+  for (int i = 0; i < out.datasize; i++)
+    out.data[i] = m1.data[i] * m2.data[i] * m3.data[i];
+}
+
+template<class Num_T>
+void elem_mult_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                   const Mat<Num_T> &m3, const Mat<Num_T> &m4,
+                   Mat<Num_T> &out)
+{
+  it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_rows == m3.no_rows)
+                  && (m1.no_rows == m4.no_rows) && (m1.no_cols == m2.no_cols)
+                  && (m1.no_cols == m3.no_cols) && (m1.no_cols == m4.no_cols),
+                  "Mat<>::elem_mult_out(): Wrong sizes");
+  out.set_size(m1.no_rows, m1.no_cols);
+  for (int i = 0; i < out.datasize; i++)
+    out.data[i] = m1.data[i] * m2.data[i] * m3.data[i] * m4.data[i];
+}
+
+template<class Num_T>
+#ifndef _MSC_VER
+inline
+#endif
+void elem_mult_inplace(const Mat<Num_T> &m1, Mat<Num_T> &m2)
+{
+  it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols),
+                  "Mat<>::elem_mult_inplace(): Wrong sizes");
+  for (int i = 0; i < m2.datasize; i++)
+    m2.data[i] *= m1.data[i];
+}
+
+template<class Num_T> inline
+Num_T elem_mult_sum(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+{
+  it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols),
+                  "Mat<>::elem_mult_sum(): Wrong sizes");
+  Num_T acc = 0;
+
+  for (int i = 0; i < m1.datasize; i++)
+    acc += m1.data[i] * m2.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>
+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<>::operator/=(): Wrong sizes");
+  for (int i = 0; i < datasize; i++)
+    data[i] /= m.data[i];
+  return *this;
+}
+
+template<class Num_T> inline
+Mat<Num_T> elem_div(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+{
+  Mat<Num_T> out;
+  elem_div_out(m1, m2, out);
+  return out;
+}
+
+template<class Num_T>
+void elem_div_out(const Mat<Num_T> &m1, const Mat<Num_T> &m2,
+                  Mat<Num_T> &out)
+{
+  it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols),
+                  "Mat<>::elem_div_out(): Wrong sizes");
+
+  if ((out.no_rows != m1.no_rows) || (out.no_cols != m1.no_cols))
+    out.set_size(m1.no_rows, m1.no_cols);
+
+  for (int i = 0; i < out.datasize; i++)
+    out.data[i] = m1.data[i] / m2.data[i];
+}
+
+template<class Num_T> inline
+Num_T elem_div_sum(const Mat<Num_T> &m1, const Mat<Num_T> &m2)
+{
+  it_assert_debug((m1.no_rows == m2.no_rows) && (m1.no_cols == m2.no_cols),
+                  "Mat<>::elem_div_sum(): Wrong sizes");
+  Num_T acc = 0;
+
+  for (int i = 0; i < m1.datasize; i++)
+    acc += m1.data[i] / m2.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 {
+      is.get(c);
+
+      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 = static_cast<char>(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 mat operator+(const mat &m1, const mat &m2);
+extern template cmat operator+(const cmat &m1, const cmat &m2);
+extern template imat operator+(const imat &m1, const imat &m2);
+extern template smat operator+(const smat &m1, const smat &m2);
+extern template bmat operator+(const bmat &m1, const bmat &m2);
+
+extern template mat operator+(const mat &m, double t);
+extern template cmat operator+(const cmat &m, std::complex<double> t);
+extern template imat operator+(const imat &m, int t);
+extern template smat operator+(const smat &m, short t);
+extern template bmat operator+(const bmat &m, bin t);
+
+extern template mat operator+(double t, const mat &m);
+extern template cmat operator+(std::complex<double> t, const cmat &m);
+extern template imat operator+(int t, const imat &m);
+extern template smat operator+(short t, const smat &m);
+extern template bmat operator+(bin t, const bmat &m);
+
+// subtraction operators
+
+extern template mat operator-(const mat &m1, const mat &m2);
+extern template cmat operator-(const cmat &m1, const cmat &m2);
+extern template imat operator-(const imat &m1, const imat &m2);
+extern template smat operator-(const smat &m1, const smat &m2);
+extern template bmat operator-(const bmat &m1, const bmat &m2);
+
+extern template mat operator-(const mat &m, double t);
+extern template cmat operator-(const cmat &m, std::complex<double> t);
+extern template imat operator-(const imat &m, int t);
+extern template smat operator-(const smat &m, short t);
+extern template bmat operator-(const bmat &m, bin t);
+
+extern template mat operator-(double t, const mat &m);
+extern template cmat operator-(std::complex<double> t, const cmat &m);
+extern template imat operator-(int t, const imat &m);
+extern template smat operator-(short t, const smat &m);
+extern template bmat operator-(bin t, const bmat &m);
+
+// unary minus
+
+extern template mat operator-(const mat &m);
+extern template cmat operator-(const cmat &m);
+extern template imat operator-(const imat &m);
+extern template smat operator-(const smat &m);
+extern template bmat operator-(const bmat &m);
+
+// multiplication operators
+
+#if !defined(HAVE_BLAS)
+extern template mat operator*(const mat &m1, const mat &m2);
+extern template cmat operator*(const cmat &m1, const cmat &m2);
+#endif
+extern template imat operator*(const imat &m1, const imat &m2);
+extern template smat operator*(const smat &m1, const smat &m2);
+extern template bmat operator*(const bmat &m1, const bmat &m2);
+
+#if !defined(HAVE_BLAS)
+extern template vec operator*(const mat &m, const vec &v);
+extern template cvec operator*(const cmat &m, const cvec &v);
+#endif
+extern template ivec operator*(const imat &m, const ivec &v);
+extern template svec operator*(const smat &m, const svec &v);
+extern template bvec operator*(const bmat &m, const bvec &v);
+
+extern template mat operator*(const vec &v, const mat &m);
+extern template cmat operator*(const cvec &v, const cmat &m);
+extern template imat operator*(const ivec &v, const imat &m);
+extern template smat operator*(const svec &v, const smat &m);
+extern template bmat operator*(const bvec &v, const bmat &m);
+
+extern template mat operator*(const mat &m, double t);
+extern template cmat operator*(const cmat &m, std::complex<double> t);
+extern template imat operator*(const imat &m, int t);
+extern template smat operator*(const smat &m, short t);
+extern template bmat operator*(const bmat &m, bin t);
+
+extern template mat operator*(double t, const mat &m);
+extern template cmat operator*(std::complex<double> t, const cmat &m);
+extern template imat operator*(int t, const imat &m);
+extern template smat operator*(short t, const smat &m);
+extern template bmat operator*(bin t, const bmat &m);
+
+// element-wise multiplication
+
+extern template mat elem_mult(const mat &m1, const mat &m2);
+extern template cmat elem_mult(const cmat &m1, const cmat &m2);
+extern template imat elem_mult(const imat &m1, const imat &m2);
+extern template smat elem_mult(const smat &m1, const smat &m2);
+extern template bmat elem_mult(const bmat &m1, const bmat &m2);
+
+extern template void elem_mult_out(const mat &m1, const mat &m2, mat &out);
+extern template void elem_mult_out(const cmat &m1, const cmat &m2,
+                                     cmat &out);
+extern template void elem_mult_out(const imat &m1, const imat &m2,
+                                     imat &out);
+extern template void elem_mult_out(const smat &m1, const smat &m2,
+                                     smat &out);
+extern template void elem_mult_out(const bmat &m1, const bmat &m2,
+                                     bmat &out);
+
+extern template void elem_mult_out(const mat &m1, const mat &m2,
+                                     const mat &m3, mat &out);
+extern template void elem_mult_out(const cmat &m1, const cmat &m2,
+                                     const cmat &m3, cmat &out);
+extern template void elem_mult_out(const imat &m1, const imat &m2,
+                                     const imat &m3, imat &out);
+extern template void elem_mult_out(const smat &m1, const smat &m2,
+                                     const smat &m3, smat &out);
+extern template void elem_mult_out(const bmat &m1, const bmat &m2,
+                                     const bmat &m3, bmat &out);
+
+extern template void elem_mult_out(const mat &m1, const mat &m2,
+                                     const mat &m3, const mat &m4, mat &out);
+extern template void elem_mult_out(const cmat &m1, const cmat &m2,
+                                     const cmat &m3, const cmat &m4,
+                                     cmat &out);
+extern template void elem_mult_out(const imat &m1, const imat &m2,
+                                     const imat &m3, const imat &m4,
+                                     imat &out);
+extern template void elem_mult_out(const smat &m1, const smat &m2,
+                                     const smat &m3, const smat &m4,
+                                     smat &out);
+extern template void elem_mult_out(const bmat &m1, const bmat &m2,
+                                     const bmat &m3, const bmat &m4,
+                                     bmat &out);
+
+extern template void elem_mult_inplace(const mat &m1, mat &m2);
+extern template void elem_mult_inplace(const cmat &m1, cmat &m2);
+extern template void elem_mult_inplace(const imat &m1, imat &m2);
+extern template void elem_mult_inplace(const smat &m1, smat &m2);
+extern template void elem_mult_inplace(const bmat &m1, bmat &m2);
+
+extern template double elem_mult_sum(const mat &m1, const mat &m2);
+extern template std::complex<double> elem_mult_sum(const cmat &m1,
+    const cmat &m2);
+extern template int elem_mult_sum(const imat &m1, const imat &m2);
+extern template short elem_mult_sum(const smat &m1, const smat &m2);
+extern template bin elem_mult_sum(const bmat &m1, const bmat &m2);
+
+// division operator
+
+extern template mat operator/(const mat &m, double t);
+extern template cmat operator/(const cmat &m, std::complex<double> t);
+extern template imat operator/(const imat &m, int t);
+extern template smat operator/(const smat &m, short t);
+extern template bmat operator/(const bmat &m, bin t);
+
+// element-wise division
+
+extern template mat elem_div(const mat &m1, const mat &m2);
+extern template cmat elem_div(const cmat &m1, const cmat &m2);
+extern template imat elem_div(const imat &m1, const imat &m2);
+extern template smat elem_div(const smat &m1, const smat &m2);
+extern template bmat elem_div(const bmat &m1, const bmat &m2);
+
+extern template void elem_div_out(const mat &m1, const mat &m2, mat &out);
+extern template void elem_div_out(const cmat &m1, const cmat &m2, cmat &out);
+extern template void elem_div_out(const imat &m1, const imat &m2, imat &out);
+extern template void elem_div_out(const smat &m1, const smat &m2, smat &out);
+extern template void elem_div_out(const bmat &m1, const bmat &m2, bmat &out);
+
+extern template double elem_div_sum(const mat &m1, const mat &m2);
+extern template std::complex<double> elem_div_sum(const cmat &m1,
+    const cmat &m2);
+extern template int elem_div_sum(const imat &m1, const imat &m2);
+extern template short elem_div_sum(const smat &m1, const smat &m2);
+extern template bin elem_div_sum(const bmat &m1, const bmat &m2);
+
+// concatenation
+
+extern template mat concat_horizontal(const mat &m1, const mat &m2);
+extern template cmat concat_horizontal(const cmat &m1, const cmat &m2);
+extern template imat concat_horizontal(const imat &m1, const imat &m2);
+extern template smat concat_horizontal(const smat &m1, const smat &m2);
+extern template bmat concat_horizontal(const bmat &m1, const bmat &m2);
+
+extern template mat concat_vertical(const mat &m1, const mat &m2);
+extern template cmat concat_vertical(const cmat &m1, const cmat &m2);
+extern template imat concat_vertical(const imat &m1, const imat &m2);
+extern template smat concat_vertical(const smat &m1, const smat &m2);
+extern template 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: library/bdm/base/itpp/base/converters.cpp
===================================================================
--- library/bdm/base/itpp/base/converters.cpp (revision 812)
+++ library/bdm/base/itpp/base/converters.cpp (revision 812)
@@ -0,0 +1,294 @@
+/*!
+ * \file
+ * \brief Implementation 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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/converters.h>
+#include <itpp/base/matfunc.h>
+#include <itpp/base/math/log_exp.h>
+
+//! \cond
+
+#ifndef HAVE_RINT
+double rint(double x)
+{
+  // zero or NaN case
+  if ((x == 0.0) || (x != x))
+    return x;
+
+  // negative case
+  bool neg = false;
+  if (x < 0.0) {
+    x = -x;
+    neg = true;
+  }
+
+  double y = std::floor(x + 0.5);
+  int i = static_cast<int>(y);
+  if ((y - x >= 0.5) && (i & 1))
+    --y;
+
+  return neg ? -y : y;
+}
+#endif // HAVE_RINT
+
+
+namespace itpp
+{
+
+// ----------------------------------------------------------------------
+// Vector converters
+// ----------------------------------------------------------------------
+
+ivec to_ivec(int s) { ivec out(1); out(0) = s; return out; }
+
+vec to_vec(double s) { vec out(1); out(0) = s; return out; }
+
+cvec to_cvec(double real, double imag)
+{
+  cvec out(1);
+  out(0) = std::complex<double>(real, imag);
+  return out;
+}
+
+// ----------------------------------------------------------------------
+// Miscellaneous converters
+// ----------------------------------------------------------------------
+
+bvec dec2bin(int length, int index)
+{
+  int i, bintemp = index;
+  bvec temp(length);
+
+  for (i = length - 1; i >= 0; i--) {
+    temp(i) = bin(bintemp & 1);
+    bintemp = (bintemp >> 1);
+  }
+  return temp;
+}
+
+bvec dec2bin(int index, bool msb_first)
+{
+  int length = int2bits(index);
+  int i, bintemp = index;
+  bvec temp(length);
+
+  for (i = length - 1; i >= 0; i--) {
+    temp(i) = bin(bintemp & 1);
+    bintemp = (bintemp >> 1);
+  }
+  if (msb_first) {
+    return temp;
+  }
+  else {
+    return reverse(temp);
+  }
+}
+
+void dec2bin(int index, bvec &v)
+{
+  int i, bintemp = index;
+  v.set_size(int2bits(index), false);
+
+  for (i = v.size() - 1; i >= 0; i--) {
+    v(i) = bin(bintemp & 1);
+    bintemp = (bintemp >> 1);
+  }
+}
+
+int bin2dec(const bvec &inbvec, bool msb_first)
+{
+  int i, temp = 0;
+  int sizebvec = inbvec.length();
+  if (msb_first) {
+    for (i = 0; i < sizebvec; i++) {
+      temp += pow2i(sizebvec - i - 1) * int(inbvec(i));
+    }
+  }
+  else {
+    for (i = 0; i < sizebvec; i++) {
+      temp += pow2i(i) * int(inbvec(i));
+    }
+  }
+  return temp;
+}
+
+bvec oct2bin(const ivec &octalindex, short keepzeros)
+{
+  int length = octalindex.length(), i;
+  bvec out(3*length);
+  for (i = 0; i < length; i++) {
+    out.replace_mid(3*i, dec2bin(3, octalindex(i)));
+  }
+  //remove zeros if keepzeros = 0
+  if (keepzeros == 0) {
+    for (i = 0; i < out.length(); i++) {
+      if ((short)out(i) != 0) {
+        return out.right(out.length() - i);
+        break;
+      }
+    }
+    return bvec("0");
+  }
+  else {
+    return out;
+  }
+}
+
+ivec bin2oct(const bvec &inbits)
+{
+  int start, Itterations = ceil_i(inbits.length() / 3.0);
+  ivec out(Itterations);
+  for (int i = Itterations - 1; i > 0; i--) {
+    start = 3 * i - (3 * Itterations - inbits.length());
+    out(i) = bin2dec(inbits.mid(start, 3));
+  }
+  out(0) = bin2dec(inbits.left(inbits.length() - ((Itterations - 1) * 3)));
+  return out;
+}
+
+ivec bin2pol(const bvec &inbvec)
+{
+  return 1 -2*to_ivec(inbvec);
+}
+
+bvec pol2bin(const ivec &inpol)
+{
+  return to_bvec((1 -inpol) / 2);
+}
+
+
+// Round to nearest integer and return ivec
+ivec round_i(const vec &x) { return to_ivec(round(x)); }
+// Round to nearest integer and return imat
+imat round_i(const mat &x) { return to_imat(round(x)); }
+
+// Round to nearest upper integer
+ivec ceil_i(const vec &x) { return to_ivec(ceil(x)); }
+// Round to nearest upper integer
+imat ceil_i(const mat &x) { return to_imat(ceil(x)); }
+
+// Round to nearest lower integer
+ivec floor_i(const vec &x) { return to_ivec(floor(x)); }
+// Round to nearest lower integer
+imat floor_i(const mat &x) { return to_imat(floor(x)); }
+
+
+cvec round_to_zero(const cvec &x, double threshold)
+{
+  cvec temp(x.length());
+
+  for (int i = 0; i < x.length(); i++)
+    temp(i) = round_to_zero(x(i), threshold);
+
+  return temp;
+}
+
+cmat round_to_zero(const cmat &x, double threshold)
+{
+  cmat temp(x.rows(), x.cols());
+
+  for (int i = 0; i < x.rows(); i++) {
+    for (int j = 0; j < x.cols(); j++) {
+      temp(i, j) = round_to_zero(x(i, j), threshold);
+    }
+  }
+
+  return temp;
+}
+
+
+std::string to_str(const double &i, const int precision)
+{
+  std::ostringstream ss;
+  ss.precision(precision);
+  ss.setf(std::ostringstream::scientific, std::ostringstream::floatfield);
+  ss << i;
+  return ss.str();
+}
+
+// ----------------------------------------------------------------------
+// Instantiations
+// ----------------------------------------------------------------------
+
+template bvec to_bvec(const svec &v);
+template bvec to_bvec(const ivec &v);
+
+template svec to_svec(const bvec &v);
+template svec to_svec(const ivec &v);
+template svec to_svec(const vec &v);
+
+#if (GCC_VERSION >= 30400)
+template ivec to_ivec(const bvec &v);
+#endif
+template ivec to_ivec(const svec &v);
+template ivec to_ivec(const vec &v);
+
+template vec to_vec(const bvec &v);
+template vec to_vec(const svec &v);
+template vec to_vec(const ivec &v);
+
+template cvec to_cvec(const bvec &v);
+template cvec to_cvec(const svec &v);
+template cvec to_cvec(const ivec &v);
+template cvec to_cvec(const vec &v);
+
+template cvec to_cvec(const bvec &real, const bvec &imag);
+template cvec to_cvec(const svec &real, const svec &imag);
+template cvec to_cvec(const ivec &real, const ivec &imag);
+template cvec to_cvec(const vec &real, const vec &imag);
+
+template bmat to_bmat(const smat &m);
+template bmat to_bmat(const imat &m);
+
+template smat to_smat(const bmat &m);
+template smat to_smat(const imat &m);
+template smat to_smat(const mat &m);
+
+template imat to_imat(const bmat &m);
+template imat to_imat(const smat &m);
+template imat to_imat(const mat &m);
+
+template mat to_mat(const bmat &m);
+#if (GCC_VERSION >= 30400)
+template mat to_mat(const smat &m);
+template mat to_mat(const imat &m);
+#endif
+
+template cmat to_cmat(const bmat &m);
+template cmat to_cmat(const smat &m);
+template cmat to_cmat(const imat &m);
+template cmat to_cmat(const mat &m);
+
+template cmat to_cmat(const bmat &real, const bmat &imag);
+template cmat to_cmat(const smat &real, const smat &imag);
+template cmat to_cmat(const imat &real, const imat &imag);
+template cmat to_cmat(const mat &real, const mat &imag);
+
+} // namespace itpp
+
+//! \endcond
Index: library/bdm/base/itpp/base/bessel/bessel_internal.h
===================================================================
--- library/bdm/base/itpp/base/bessel/bessel_internal.h (revision 812)
+++ library/bdm/base/itpp/base/bessel/bessel_internal.h (revision 812)
@@ -0,0 +1,64 @@
+/*!
+ * \file
+ * \brief Bessel help functions header. For internal use only.
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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_INTERNAL_H
+#define BESSEL_INTERNAL_H
+
+//! \cond
+
+#include <cmath>
+
+double chbevl(double x, double array[], int n);
+double hyperg(double a, double b, double x);
+int airy(double x, double *ai, double *aip, double *bi, double *bip);
+double polevl(double x, double coef[], int N);
+double p1evl(double x, double coef[], int N);
+
+double i0(double x);
+double i0e(double x);
+double i1(double x);
+double i1e(double x);
+
+double k0(double x);
+double k0e(double x);
+double k1(double x);
+double k1e(double x);
+
+double iv(double nu, double x);
+double jv(double nu, double x);
+double yv(double nu, double x);
+double kn(int n, double x);
+
+double gam(double x);
+double lgam(double x);
+extern int sgngam;
+
+//! \endcond
+
+#endif // #ifndef BESSEL_INTERNAL_H
Index: library/bdm/base/itpp/base/bessel/hyperg.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/hyperg.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/hyperg.cpp (revision 812)
@@ -0,0 +1,376 @@
+/*!
+ * \file
+ * \brief Implementation of confluent hypergeometric function
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+#include <itpp/base/itassert.h>
+
+
+/*
+ * Confluent hypergeometric function
+ *
+ * double a, b, x, y, hyperg();
+ *
+ * y = hyperg( a, b, x );
+ *
+ * DESCRIPTION:
+ *
+ * Computes the confluent hypergeometric function
+ *
+ *                          1           2
+ *                       a x    a(a+1) x
+ *   F ( a,b;x )  =  1 + ---- + --------- + ...
+ *  1 1                  b 1!   b(b+1) 2!
+ *
+ * Many higher transcendental functions are special cases of
+ * this power series.
+ *
+ * As is evident from the formula, b must not be a negative
+ * integer or zero unless a is an integer with 0 >= a > b.
+ *
+ * The routine attempts both a direct summation of the series
+ * and an asymptotic expansion.  In each case error due to
+ * roundoff, cancellation, and nonconvergence is estimated.
+ * The result with smaller estimated error is returned.
+ *
+ * ACCURACY:
+ *
+ * Tested at random points (a, b, x), all three variables
+ * ranging from 0 to 30.
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    DEC       0,30         2000       1.2e-15     1.3e-16
+ qtst1:
+ 21800   max =  1.4200E-14   rms =  1.0841E-15  ave = -5.3640E-17
+ ltstd:
+ 25500   max = 1.2759e-14   rms = 3.7155e-16  ave = 1.5384e-18
+ *    IEEE      0,30        30000       1.8e-14     1.1e-15
+ *
+ * Larger errors can be observed when b is near a negative
+ * integer or zero.  Certain combinations of arguments yield
+ * serious cancellation error in the power series summation
+ * and also are not in the region of near convergence of the
+ * asymptotic series.  An error message is printed if the
+ * self-estimated relative error is greater than 1.0e-12.
+ */
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier
+*/
+
+
+double hyp2f0(double, double, double, int, double *);
+static double hy1f1p(double, double, double, double *);
+static double hy1f1a(double, double, double, double *);
+
+#define MAXNUM 1.79769313486231570815E308    /* 2**1024*(1-MACHEP) */
+#define MACHEP 1.11022302462515654042E-16   /* 2**-53 */
+
+double hyperg(double a, double b, double x)
+{
+  double asum, psum, acanc, pcanc = 0, temp;
+
+  /* See if a Kummer transformation will help */
+  temp = b - a;
+  if (fabs(temp) < 0.001 * fabs(a))
+    return(exp(x) * hyperg(temp, b, -x));
+
+
+  psum = hy1f1p(a, b, x, &pcanc);
+  if (pcanc < 1.0e-15)
+    goto done;
+
+
+  /* try asymptotic series */
+
+  asum = hy1f1a(a, b, x, &acanc);
+
+
+  /* Pick the result with less estimated error */
+
+  if (acanc < pcanc) {
+    pcanc = acanc;
+    psum = asum;
+  }
+
+done:
+  if (pcanc > 1.0e-12) {
+    it_warning("hyperg(): partial loss of precision");
+  }
+
+  return(psum);
+}
+
+
+/* Power series summation for confluent hypergeometric function */
+static double hy1f1p(double a, double b, double x, double *err)
+{
+  double n, a0, sum, t, u, temp;
+  double an, bn, maxt, pcanc;
+
+
+  /* set up for power series summation */
+  an = a;
+  bn = b;
+  a0 = 1.0;
+  sum = 1.0;
+  n = 1.0;
+  t = 1.0;
+  maxt = 0.0;
+
+
+  while (t > MACHEP) {
+    if (bn == 0) {  /* check bn first since if both */
+      it_warning("hy1f1p(): function singularity");
+      return(MAXNUM);   /* an and bn are zero it is */
+    }
+    if (an == 0)    /* a singularity  */
+      return(sum);
+    if (n > 200)
+      goto pdone;
+    u = x * (an / (bn * n));
+
+    /* check for blowup */
+    temp = fabs(u);
+    if ((temp > 1.0) && (maxt > (MAXNUM / temp))) {
+      pcanc = 1.0; /* estimate 100% error */
+      goto blowup;
+    }
+
+    a0 *= u;
+    sum += a0;
+    t = fabs(a0);
+    if (t > maxt)
+      maxt = t;
+    /*
+    if( (maxt/fabs(sum)) > 1.0e17 )
+    {
+    pcanc = 1.0;
+    goto blowup;
+    }
+    */
+    an += 1.0;
+    bn += 1.0;
+    n += 1.0;
+  }
+
+pdone:
+
+  /* estimate error due to roundoff and cancellation */
+  if (sum != 0.0)
+    maxt /= fabs(sum);
+  maxt *= MACHEP;  /* this way avoids multiply overflow */
+  pcanc = fabs(MACHEP * n  +  maxt);
+
+blowup:
+
+  *err = pcanc;
+
+  return(sum);
+}
+
+
+/*       hy1f1a() */
+/* asymptotic formula for hypergeometric function:
+ *
+ *        (    -a
+ *  --    ( |z|
+ * |  (b) ( -------- 2f0( a, 1+a-b, -1/x )
+ *        (  --
+ *        ( |  (b-a)
+ *
+ *
+ *                                x    a-b                     )
+ *                               e  |x|                        )
+ *                             + -------- 2f0( b-a, 1-a, 1/x ) )
+ *                                --                           )
+ *                               |  (a)                        )
+ */
+
+static double hy1f1a(double a, double b, double x, double *err)
+{
+  double h1, h2, t, u, temp, acanc, asum, err1, err2;
+
+  if (x == 0) {
+    acanc = 1.0;
+    asum = MAXNUM;
+    goto adone;
+  }
+  temp = log(fabs(x));
+  t = x + temp * (a - b);
+  u = -temp * a;
+
+  if (b > 0) {
+    temp = lgam(b);
+    t += temp;
+    u += temp;
+  }
+
+  h1 = hyp2f0(a, a - b + 1, -1.0 / x, 1, &err1);
+
+  temp = exp(u) / gam(b - a);
+  h1 *= temp;
+  err1 *= temp;
+
+  h2 = hyp2f0(b - a, 1.0 - a, 1.0 / x, 2, &err2);
+
+  if (a < 0)
+    temp = exp(t) / gam(a);
+  else
+    temp = exp(t - lgam(a));
+
+  h2 *= temp;
+  err2 *= temp;
+
+  if (x < 0.0)
+    asum = h1;
+  else
+    asum = h2;
+
+  acanc = fabs(err1) + fabs(err2);
+
+
+  if (b < 0) {
+    temp = gam(b);
+    asum *= temp;
+    acanc *= fabs(temp);
+  }
+
+
+  if (asum != 0.0)
+    acanc /= fabs(asum);
+
+  acanc *= 30.0; /* fudge factor, since error of asymptotic formula
+    * often seems this much larger than advertised */
+
+adone:
+
+
+  *err = acanc;
+  return(asum);
+}
+
+
+double hyp2f0(double a, double b, double x, int type, double *err)
+{
+  double a0, alast, t, tlast, maxt;
+  double n, an, bn, u, sum, temp;
+
+  an = a;
+  bn = b;
+  a0 = 1.0e0;
+  alast = 1.0e0;
+  sum = 0.0;
+  n = 1.0e0;
+  t = 1.0e0;
+  tlast = 1.0e9;
+  maxt = 0.0;
+
+  do {
+    if (an == 0)
+      goto pdone;
+    if (bn == 0)
+      goto pdone;
+
+    u = an * (bn * x / n);
+
+    /* check for blowup */
+    temp = fabs(u);
+    if ((temp > 1.0) && (maxt > (MAXNUM / temp)))
+      goto error;
+
+    a0 *= u;
+    t = fabs(a0);
+
+    /* terminating condition for asymptotic series */
+    if (t > tlast)
+      goto ndone;
+
+    tlast = t;
+    sum += alast; /* the sum is one term behind */
+    alast = a0;
+
+    if (n > 200)
+      goto ndone;
+
+    an += 1.0e0;
+    bn += 1.0e0;
+    n += 1.0e0;
+    if (t > maxt)
+      maxt = t;
+  }
+  while (t > MACHEP);
+
+
+pdone: /* series converged! */
+
+  /* estimate error due to roundoff and cancellation */
+  *err = fabs(MACHEP * (n + maxt));
+
+  alast = a0;
+  goto done;
+
+ndone: /* series did not converge */
+
+  /* The following "Converging factors" are supposed to improve accuracy,
+   * but do not actually seem to accomplish very much. */
+
+  n -= 1.0;
+  x = 1.0 / x;
+
+  switch (type) { /* "type" given as subroutine argument */
+  case 1:
+    alast *= (0.5 + (0.125 + 0.25 * b - 0.5 * a + 0.25 * x - 0.25 * n) / x);
+    break;
+
+  case 2:
+    alast *= 2.0 / 3.0 - b + 2.0 * a + x - n;
+    break;
+
+  default:
+    ;
+  }
+
+  /* estimate error due to roundoff, cancellation, and nonconvergence */
+  *err = MACHEP * (n + maxt)  +  fabs(a0);
+
+
+done:
+  sum += alast;
+  return(sum);
+
+  /* series blew up: */
+error:
+  *err = MAXNUM;
+  it_warning("hy1f1a(): total loss of precision");
+  return(sum);
+}
Index: library/bdm/base/itpp/base/bessel/iv.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/iv.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/iv.cpp (revision 812)
@@ -0,0 +1,124 @@
+/*!
+ * \file
+ * \brief Implementation of modified Bessel functions of noninteager order
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+#include <itpp/base/itassert.h>
+
+
+/*
+ * Modified Bessel function of noninteger order
+ *
+ * double v, x, y, iv();
+ *
+ * y = iv( v, x );
+ *
+ * DESCRIPTION:
+ *
+ * Returns modified Bessel function of order v of the
+ * argument.  If x is negative, v must be integer valued.
+ *
+ * The function is defined as Iv(x) = Jv( ix ).  It is
+ * here computed in terms of the confluent hypergeometric
+ * function, according to the formula
+ *
+ *              v  -x
+ * Iv(x) = (x/2)  e   hyperg( v+0.5, 2v+1, 2x ) / gamma(v+1)
+ *
+ * If v is a negative integer, then v is replaced by -v.
+ *
+ *
+ * ACCURACY:
+ *
+ * Tested at random points (v, x), with v between 0 and
+ * 30, x between 0 and 28.
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0,30         10000      1.7e-14     2.7e-15
+ *
+ * Accuracy is diminished if v is near a negative integer.
+ *
+ * See also hyperg.c.
+ */
+
+/* Mdified Bessel function of noninteger order */
+/* If x < 0, then v must be an integer. */
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier
+*/
+
+
+#define MAXNUM 1.79769313486231570815E308    /* 2**1024*(1-MACHEP) */
+
+double iv(double v, double x)
+{
+  int sign;
+  double t, ax;
+
+  /* If v is a negative integer, invoke symmetry */
+  t = floor(v);
+  if (v < 0.0) {
+    if (t == v) {
+      v = -v; /* symmetry */
+      t = -t;
+    }
+  }
+  /* If x is negative, require v to be an integer */
+  sign = 1;
+  if (x < 0.0) {
+    if (t != v) {
+      it_warning("iv(): argument domain error");
+      return(0.0);
+    }
+    if (v != 2.0 * floor(v / 2.0))
+      sign = -1;
+  }
+
+  /* Avoid logarithm singularity */
+  if (x == 0.0) {
+    if (v == 0.0)
+      return(1.0);
+    if (v < 0.0) {
+      it_warning("iv(): overflow range error");
+      return(MAXNUM);
+    }
+    else
+      return(0.0);
+  }
+
+  ax = fabs(x);
+  t = v * log(0.5 * ax)  -  x;
+  t = sign * exp(t) / gam(v + 1.0);
+  ax = v + 0.5;
+  return(t * hyperg(ax,  2.0 * ax,  2.0 * x));
+}
Index: library/bdm/base/itpp/base/bessel/jv.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/jv.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/jv.cpp (revision 812)
@@ -0,0 +1,778 @@
+/*!
+ * \file
+ * \brief Implementation of Bessel functions of noninteager order
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+#include <itpp/base/math/elem_math.h>
+#include <itpp/base/itassert.h>
+
+
+/*
+ * Bessel function of noninteger order
+ *
+ * double v, x, y, jv();
+ *
+ * y = jv( v, x );
+ *
+ * DESCRIPTION:
+ *
+ * Returns Bessel function of order v of the argument,
+ * where v is real.  Negative x is allowed if v is an integer.
+ *
+ * Several expansions are included: the ascending power
+ * series, the Hankel expansion, and two transitional
+ * expansions for large v.  If v is not too large, it
+ * is reduced by recurrence to a region of best accuracy.
+ * The transitional expansions give 12D accuracy for v > 500.
+ *
+ * ACCURACY:
+ * Results for integer v are indicated by *, where x and v
+ * both vary from -125 to +125.  Otherwise,
+ * x ranges from 0 to 125, v ranges as indicated by "domain."
+ * Error criterion is absolute, except relative when |jv()| > 1.
+ *
+ * arithmetic  v domain  x domain    # trials      peak       rms
+ *    IEEE      0,125     0,125      100000      4.6e-15    2.2e-16
+ *    IEEE   -125,0       0,125       40000      5.4e-11    3.7e-13
+ *    IEEE      0,500     0,500       20000      4.4e-15    4.0e-16
+ * Integer v:
+ *    IEEE   -125,125   -125,125      50000      3.5e-15*   1.9e-16*
+ */
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+*/
+
+static double recur(double *, double, double *, int);
+static double jvs(double, double);
+static double hankel(double, double);
+static double jnx(double, double);
+static double jnt(double, double);
+
+#define MAXGAM 171.624376956302725
+#define MAXNUM 1.79769313486231570815E308    /* 2**1024*(1-MACHEP) */
+#define MACHEP 1.11022302462515654042E-16   /* 2**-53 */
+#define MAXLOG 7.08396418532264106224E2     /* log 2**1022 */
+#define MINLOG -7.08396418532264106224E2    /* log 2**-1022 */
+#define PI 3.14159265358979323846       /* pi */
+
+#define BIG  1.44115188075855872E+17
+
+
+
+// ---------------------------- jv() -------------------------------------------------------
+double jv(double n, double x)
+{
+  double k, q, t, y, an;
+  int i, sign, nint;
+
+  nint = 0; /* Flag for integer n */
+  sign = 1; /* Flag for sign inversion */
+  an = fabs(n);
+  y = floor(an);
+  if (y == an) {
+    nint = 1;
+    i = int(an - 16384.0 * floor(an / 16384.0));
+    if (n < 0.0) {
+      if (i & 1)
+        sign = -sign;
+      n = an;
+    }
+    if (x < 0.0) {
+      if (i & 1)
+        sign = -sign;
+      x = -x;
+    }
+    if (n == 0.0)  // use 0th order bessel function
+      return j0(x);
+    if (n == 1.0)  // use 1th order bessel function
+      return (sign * j1(x));
+  }
+
+  it_error_if((x < 0.0) && (y != an), "besselj:: negative values only allowed for integer orders.");
+
+  y = fabs(x);
+
+  if (y < MACHEP)
+    goto underf;
+
+  k = 3.6 * sqrt(y);
+  t = 3.6 * sqrt(an);
+  if ((y < t) && (an > 21.0))
+    return(sign * jvs(n, x));
+  if ((an < k) && (y > 21.0))
+    return(sign * hankel(n, x));
+
+  if (an < 500.0) {
+    /* Note: if x is too large, the continued
+     * fraction will fail; but then the
+     * Hankel expansion can be used.
+     */
+    if (nint != 0) {
+      k = 0.0;
+      q = recur(&n, x, &k, 1);
+      if (k == 0.0) {
+        y = j0(x) / q;
+        goto done;
+      }
+      if (k == 1.0) {
+        y = j1(x) / q;
+        goto done;
+      }
+    }
+
+    if (an > 2.0 * y)
+      goto rlarger;
+
+    if ((n >= 0.0) && (n < 20.0)
+        && (y > 6.0) && (y < 20.0)) {
+      /* Recur backwards from a larger value of n
+       */
+    rlarger:
+      k = n;
+
+      y = y + an + 1.0;
+      if (y < 30.0)
+        y = 30.0;
+      y = n + floor(y - n);
+      q = recur(&y, x, &k, 0);
+      y = jvs(y, x) * q;
+      goto done;
+    }
+
+    if (k <= 30.0) {
+      k = 2.0;
+    }
+    else if (k < 90.0) {
+      k = (3 * k) / 4;
+    }
+    if (an > (k + 3.0)) {
+      if (n < 0.0)
+        k = -k;
+      q = n - floor(n);
+      k = floor(k) + q;
+      if (n > 0.0)
+        q = recur(&n, x, &k, 1);
+      else {
+        t = k;
+        k = n;
+        q = recur(&t, x, &k, 1);
+        k = t;
+      }
+      if (q == 0.0) {
+      underf:
+        y = 0.0;
+        goto done;
+      }
+    }
+    else {
+      k = n;
+      q = 1.0;
+    }
+
+    /* boundary between convergence of
+     * power series and Hankel expansion
+     */
+    y = fabs(k);
+    if (y < 26.0)
+      t = (0.0083 * y + 0.09) * y + 12.9;
+    else
+      t = 0.9 * y;
+
+    if (x > t)
+      y = hankel(k, x);
+    else
+      y = jvs(k, x);
+
+    if (n > 0.0)
+      y /= q;
+    else
+      y *= q;
+  }
+
+  else {
+    /* For large n, use the uniform expansion
+     * or the transitional expansion.
+     * But if x is of the order of n**2,
+     * these may blow up, whereas the
+     * Hankel expansion will then work.
+     */
+
+    if (n < 0.0) {
+      it_warning("jv(): partial loss of precision");
+      y = 0.0;
+      goto done;
+    }
+    t = x / n;
+    t /= n;
+    if (t > 0.3)
+      y = hankel(n, x);
+    else
+      y = jnx(n, x);
+  }
+
+done:
+  return(sign * y);
+}
+
+/* Reduce the order by backward recurrence.
+ * AMS55 #9.1.27 and 9.1.73.
+ */
+
+static double recur(double *n, double x, double *newn, int cancel)
+{
+  double pkm2, pkm1, pk, qkm2, qkm1;
+  /* double pkp1; */
+  double k, ans, qk, xk, yk, r, t, kf;
+  static double big = BIG;
+  int nflag, ctr;
+
+  /* continued fraction for Jn(x)/Jn-1(x)  */
+  if (*n < 0.0)
+    nflag = 1;
+  else
+    nflag = 0;
+
+fstart:
+  pkm2 = 0.0;
+  qkm2 = 1.0;
+  pkm1 = x;
+  qkm1 = *n + *n;
+  xk = -x * x;
+  yk = qkm1;
+  ans = 1.0;
+  ctr = 0;
+  do {
+    yk += 2.0;
+    pk = pkm1 * yk +  pkm2 * xk;
+    qk = qkm1 * yk +  qkm2 * xk;
+    pkm2 = pkm1;
+    pkm1 = pk;
+    qkm2 = qkm1;
+    qkm1 = qk;
+    if (qk != 0)
+      r = pk / qk;
+    else
+      r = 0.0;
+    if (r != 0) {
+      t = fabs((ans - r) / r);
+      ans = r;
+    }
+    else
+      t = 1.0;
+
+    if (++ctr > 1000) {
+      it_warning("recur(): underflow range error");
+      goto done;
+    }
+
+    if (t < MACHEP)
+      goto done;
+
+    if (fabs(pk) > big) {
+      pkm2 /= big;
+      pkm1 /= big;
+      qkm2 /= big;
+      qkm1 /= big;
+    }
+  }
+  while (t > MACHEP);
+
+done:
+
+  /* Change n to n-1 if n < 0 and the continued fraction is small
+   */
+  if (nflag > 0) {
+    if (fabs(ans) < 0.125) {
+      nflag = -1;
+      *n = *n - 1.0;
+      goto fstart;
+    }
+  }
+
+
+  kf = *newn;
+
+  /* backward recurrence
+   *              2k
+   *  J   (x)  =  --- J (x)  -  J   (x)
+   *   k-1         x   k         k+1
+   */
+
+  pk = 1.0;
+  pkm1 = 1.0 / ans;
+  k = *n - 1.0;
+  r = 2 * k;
+  do {
+    pkm2 = (pkm1 * r  -  pk * x) / x;
+    /* pkp1 = pk; */
+    pk = pkm1;
+    pkm1 = pkm2;
+    r -= 2.0;
+    /*
+    t = fabs(pkp1) + fabs(pk);
+    if( (k > (kf + 2.5)) && (fabs(pkm1) < 0.25*t) )
+    {
+    k -= 1.0;
+    t = x*x;
+    pkm2 = ( (r*(r+2.0)-t)*pk - r*x*pkp1 )/t;
+    pkp1 = pk;
+    pk = pkm1;
+    pkm1 = pkm2;
+    r -= 2.0;
+    }
+    */
+    k -= 1.0;
+  }
+  while (k > (kf + 0.5));
+
+  /* Take the larger of the last two iterates
+   * on the theory that it may have less cancellation error.
+   */
+
+  if (cancel) {
+    if ((kf >= 0.0) && (fabs(pk) > fabs(pkm1))) {
+      k += 1.0;
+      pkm2 = pk;
+    }
+  }
+  *newn = k;
+
+  return(pkm2);
+}
+
+
+
+/* Ascending power series for Jv(x).
+ * AMS55 #9.1.10.
+ */
+
+
+static double jvs(double n, double x)
+{
+  double t, u, y, z, k;
+  int ex;
+
+  z = -x * x / 4.0;
+  u = 1.0;
+  y = u;
+  k = 1.0;
+  t = 1.0;
+
+  while (t > MACHEP) {
+    u *= z / (k * (n + k));
+    y += u;
+    k += 1.0;
+    if (y != 0)
+      t = fabs(u / y);
+  }
+
+  t = frexp(0.5 * x, &ex);
+  ex = int(ex * n);
+  if ((ex > -1023)
+      && (ex < 1023)
+      && (n > 0.0)
+      && (n < (MAXGAM - 1.0))) {
+    t = pow(0.5 * x, n) / gam(n + 1.0);
+
+    y *= t;
+  }
+  else {
+    t = n * log(0.5 * x) - lgam(n + 1.0);
+    if (y < 0) {
+      sgngam = -sgngam;
+      y = -y;
+    }
+    t += log(y);
+
+    if (t < -MAXLOG) {
+      return(0.0);
+    }
+
+    if (t > MAXLOG) {
+      it_warning("jvs(): overflow range error");
+      return(MAXNUM);
+    }
+    y = sgngam * exp(t);
+  }
+  return(y);
+}
+
+/* Hankel's asymptotic expansion
+ * for large x.
+ * AMS55 #9.2.5.
+ */
+static double hankel(double n, double x)
+{
+  double t, u, z, k, sign, conv;
+  double p, q, j, m, pp, qq;
+  int flag;
+
+  m = 4.0 * n * n;
+  j = 1.0;
+  z = 8.0 * x;
+  k = 1.0;
+  p = 1.0;
+  u = (m - 1.0) / z;
+  q = u;
+  sign = 1.0;
+  conv = 1.0;
+  flag = 0;
+  t = 1.0;
+  pp = 1.0e38;
+  qq = 1.0e38;
+
+  while (t > MACHEP) {
+    k += 2.0;
+    j += 1.0;
+    sign = -sign;
+    u *= (m - k * k) / (j * z);
+    p += sign * u;
+    k += 2.0;
+    j += 1.0;
+    u *= (m - k * k) / (j * z);
+    q += sign * u;
+    t = fabs(u / p);
+    if (t < conv) {
+      conv = t;
+      qq = q;
+      pp = p;
+      flag = 1;
+    }
+    /* stop if the terms start getting larger */
+    if ((flag != 0) && (t > conv)) {
+      goto hank1;
+    }
+  }
+
+hank1:
+  u = x - (0.5 * n + 0.25) * PI;
+  t = sqrt(2.0 / (PI * x)) * (pp * cos(u) - qq * sin(u));
+
+  return(t);
+}
+
+
+/* Asymptotic expansion for large n.
+ * AMS55 #9.3.35.
+ */
+
+static double lambda[] = {
+  1.0,
+  1.041666666666666666666667E-1,
+  8.355034722222222222222222E-2,
+  1.282265745563271604938272E-1,
+  2.918490264641404642489712E-1,
+  8.816272674437576524187671E-1,
+  3.321408281862767544702647E+0,
+  1.499576298686255465867237E+1,
+  7.892301301158651813848139E+1,
+  4.744515388682643231611949E+2,
+  3.207490090890661934704328E+3
+};
+static double mu[] = {
+  1.0,
+  -1.458333333333333333333333E-1,
+  -9.874131944444444444444444E-2,
+  -1.433120539158950617283951E-1,
+  -3.172272026784135480967078E-1,
+  -9.424291479571202491373028E-1,
+  -3.511203040826354261542798E+0,
+  -1.572726362036804512982712E+1,
+  -8.228143909718594444224656E+1,
+  -4.923553705236705240352022E+2,
+  -3.316218568547972508762102E+3
+};
+static double P1[] = {
+  -2.083333333333333333333333E-1,
+  1.250000000000000000000000E-1
+};
+static double P2[] = {
+  3.342013888888888888888889E-1,
+  -4.010416666666666666666667E-1,
+  7.031250000000000000000000E-2
+};
+static double P3[] = {
+  -1.025812596450617283950617E+0,
+  1.846462673611111111111111E+0,
+  -8.912109375000000000000000E-1,
+  7.324218750000000000000000E-2
+};
+static double P4[] = {
+  4.669584423426247427983539E+0,
+  -1.120700261622299382716049E+1,
+  8.789123535156250000000000E+0,
+  -2.364086914062500000000000E+0,
+  1.121520996093750000000000E-1
+};
+static double P5[] = {
+  -2.8212072558200244877E1,
+  8.4636217674600734632E1,
+  -9.1818241543240017361E1,
+  4.2534998745388454861E1,
+  -7.3687943594796316964E0,
+  2.27108001708984375E-1
+};
+static double P6[] = {
+  2.1257013003921712286E2,
+  -7.6525246814118164230E2,
+  1.0599904525279998779E3,
+  -6.9957962737613254123E2,
+  2.1819051174421159048E2,
+  -2.6491430486951555525E1,
+  5.7250142097473144531E-1
+};
+static double P7[] = {
+  -1.9194576623184069963E3,
+  8.0617221817373093845E3,
+  -1.3586550006434137439E4,
+  1.1655393336864533248E4,
+  -5.3056469786134031084E3,
+  1.2009029132163524628E3,
+  -1.0809091978839465550E2,
+  1.7277275025844573975E0
+};
+
+
+static double jnx(double n, double x)
+{
+  double zeta, sqz, zz, zp, np;
+  double cbn, n23, t, z, sz;
+  double pp, qq, z32i, zzi;
+  double ak, bk, akl, bkl;
+  int sign, doa, dob, nflg, k, s, tk, tkp1, m;
+  static double u[8];
+  static double ai, aip, bi, bip;
+
+  /* Test for x very close to n.
+   * Use expansion for transition region if so.
+   */
+  cbn = cbrt(n);
+  z = (x - n) / cbn;
+  if (fabs(z) <= 0.7)
+    return(jnt(n, x));
+
+  z = x / n;
+  zz = 1.0 - z * z;
+  if (zz == 0.0)
+    return(0.0);
+
+  if (zz > 0.0) {
+    sz = sqrt(zz);
+    t = 1.5 * (log((1.0 + sz) / z) - sz); /* zeta ** 3/2  */
+    zeta = cbrt(t * t);
+    nflg = 1;
+  }
+  else {
+    sz = sqrt(-zz);
+    t = 1.5 * (sz - acos(1.0 / z));
+    zeta = -cbrt(t * t);
+    nflg = -1;
+  }
+  z32i = fabs(1.0 / t);
+  sqz = cbrt(t);
+
+  /* Airy function */
+  n23 = cbrt(n * n);
+  t = n23 * zeta;
+
+  airy(t, &ai, &aip, &bi, &bip);
+
+  /* polynomials in expansion */
+  u[0] = 1.0;
+  zzi = 1.0 / zz;
+  u[1] = polevl(zzi, P1, 1) / sz;
+  u[2] = polevl(zzi, P2, 2) / zz;
+  u[3] = polevl(zzi, P3, 3) / (sz * zz);
+  pp = zz * zz;
+  u[4] = polevl(zzi, P4, 4) / pp;
+  u[5] = polevl(zzi, P5, 5) / (pp * sz);
+  pp *= zz;
+  u[6] = polevl(zzi, P6, 6) / pp;
+  u[7] = polevl(zzi, P7, 7) / (pp * sz);
+
+  pp = 0.0;
+  qq = 0.0;
+  np = 1.0;
+  /* flags to stop when terms get larger */
+  doa = 1;
+  dob = 1;
+  akl = MAXNUM;
+  bkl = MAXNUM;
+
+  for (k = 0; k <= 3; k++) {
+    tk = 2 * k;
+    tkp1 = tk + 1;
+    zp = 1.0;
+    ak = 0.0;
+    bk = 0.0;
+    for (s = 0; s <= tk; s++) {
+      if (doa) {
+        if ((s & 3) > 1)
+          sign = nflg;
+        else
+          sign = 1;
+        ak += sign * mu[s] * zp * u[tk-s];
+      }
+
+      if (dob) {
+        m = tkp1 - s;
+        if (((m + 1) & 3) > 1)
+          sign = nflg;
+        else
+          sign = 1;
+        bk += sign * lambda[s] * zp * u[m];
+      }
+      zp *= z32i;
+    }
+
+    if (doa) {
+      ak *= np;
+      t = fabs(ak);
+      if (t < akl) {
+        akl = t;
+        pp += ak;
+      }
+      else
+        doa = 0;
+    }
+
+    if (dob) {
+      bk += lambda[tkp1] * zp * u[0];
+      bk *= -np / sqz;
+      t = fabs(bk);
+      if (t < bkl) {
+        bkl = t;
+        qq += bk;
+      }
+      else
+        dob = 0;
+    }
+
+    if (np < MACHEP)
+      break;
+    np /= n * n;
+  }
+
+  /* normalizing factor ( 4*zeta/(1 - z**2) )**1/4 */
+  t = 4.0 * zeta / zz;
+  t = sqrt(sqrt(t));
+
+  t *= ai * pp / cbrt(n)  +  aip * qq / (n23 * n);
+  return(t);
+}
+
+/* Asymptotic expansion for transition region,
+ * n large and x close to n.
+ * AMS55 #9.3.23.
+ */
+
+static double PF2[] = {
+  -9.0000000000000000000e-2,
+  8.5714285714285714286e-2
+};
+static double PF3[] = {
+  1.3671428571428571429e-1,
+  -5.4920634920634920635e-2,
+  -4.4444444444444444444e-3
+};
+static double PF4[] = {
+  1.3500000000000000000e-3,
+  -1.6036054421768707483e-1,
+  4.2590187590187590188e-2,
+  2.7330447330447330447e-3
+};
+static double PG1[] = {
+  -2.4285714285714285714e-1,
+  1.4285714285714285714e-2
+};
+static double PG2[] = {
+  -9.0000000000000000000e-3,
+  1.9396825396825396825e-1,
+  -1.1746031746031746032e-2
+};
+static double PG3[] = {
+  1.9607142857142857143e-2,
+  -1.5983694083694083694e-1,
+  6.3838383838383838384e-3
+};
+
+
+static double jnt(double n, double x)
+{
+  double z, zz, z3;
+  double cbn, n23, cbtwo;
+  double ai, aip, bi, bip; /* Airy functions */
+  double nk, fk, gk, pp, qq;
+  double F[5], G[4];
+  int k;
+
+  cbn = cbrt(n);
+  z = (x - n) / cbn;
+  cbtwo = cbrt(2.0);
+
+  /* Airy function */
+  zz = -cbtwo * z;
+  airy(zz, &ai, &aip, &bi, &bip);
+
+  /* polynomials in expansion */
+  zz = z * z;
+  z3 = zz * z;
+  F[0] = 1.0;
+  F[1] = -z / 5.0;
+  F[2] = polevl(z3, PF2, 1) * zz;
+  F[3] = polevl(z3, PF3, 2);
+  F[4] = polevl(z3, PF4, 3) * z;
+  G[0] = 0.3 * zz;
+  G[1] = polevl(z3, PG1, 1);
+  G[2] = polevl(z3, PG2, 2) * z;
+  G[3] = polevl(z3, PG3, 2) * zz;
+
+  pp = 0.0;
+  qq = 0.0;
+  nk = 1.0;
+  n23 = cbrt(n * n);
+
+  for (k = 0; k <= 4; k++) {
+    fk = F[k] * nk;
+    pp += fk;
+    if (k != 4) {
+      gk = G[k] * nk;
+      qq += gk;
+    }
+
+    nk /= n23;
+  }
+
+  fk = cbtwo * ai * pp / cbn  +  cbrt(4.0) * aip * qq / n;
+  return(fk);
+}
Index: library/bdm/base/itpp/base/bessel/polevl.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/polevl.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/polevl.cpp (revision 812)
@@ -0,0 +1,112 @@
+/*!
+ * \file
+ * \brief Implementation of polynomial evaluation function
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+
+
+/*
+ * Evaluate polynomial
+ *
+ * int N;
+ * double x, y, coef[N+1], polevl[];
+ *
+ * y = polevl( x, coef, N );
+ *
+ * DESCRIPTION:
+ *
+ * Evaluates polynomial of degree N:
+ *
+ *                     2          N
+ * y  =  C  + C x + C x  +...+ C x
+ *        0    1     2          N
+ *
+ * Coefficients are stored in reverse order:
+ *
+ * coef[0] = C  , ..., coef[N] = C  .
+ *            N                   0
+ *
+ *  The function p1evl() assumes that coef[N] = 1.0 and is
+ * omitted from the array.  Its calling arguments are
+ * otherwise the same as polevl().
+ *
+ * SPEED:
+ *
+ * In the interest of speed, there are no checks for out
+ * of bounds arithmetic.  This routine is used by most of
+ * the functions in the library.  Depending on available
+ * equipment features, the user may wish to rewrite the
+ * program in microcode or assembly language.
+ */
+
+/*
+  Cephes Math Library Release 2.1:  December, 1988
+  Copyright 1984, 1987, 1988 by Stephen L. Moshier
+*/
+
+double polevl(double x, double coef[], int N)
+{
+  double ans;
+  int i;
+  double *p;
+
+  p = coef;
+  ans = *p++;
+  i = N;
+
+  do
+    ans = ans * x  +  *p++;
+  while (--i);
+
+  return(ans);
+}
+
+/*                                          N
+ * Evaluate polynomial when coefficient of x  is 1.0.
+ * Otherwise same as polevl.
+ */
+
+double p1evl(double x, double coef[], int N)
+{
+  double ans;
+  double *p;
+  int i;
+
+  p = coef;
+  ans = x + *p++;
+  i = N - 1;
+
+  do
+    ans = ans * x  + *p++;
+  while (--i);
+
+  return(ans);
+}
Index: library/bdm/base/itpp/base/bessel/gamma.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/gamma.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/gamma.cpp (revision 812)
@@ -0,0 +1,393 @@
+/*!
+ * \file
+ * \brief Implementation of gamma functions
+ * \author Adam Piatyszek
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+#include <itpp/base/itassert.h>
+#include <itpp/base/math/misc.h>
+
+
+/*
+ * Gamma function
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double x, y, gam();
+ * extern int sgngam;
+ *
+ * y = gam( x );
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns gamma function of the argument.  The result is
+ * correctly signed, and the sign (+1 or -1) is also
+ * returned in a global (extern) variable named sgngam.
+ * This variable is also filled in by the logarithmic gamma
+ * function lgam().
+ *
+ * Arguments |x| <= 34 are reduced by recurrence and the function
+ * approximated by a rational function of degree 6/7 in the
+ * interval (2,3).  Large arguments are handled by Stirling's
+ * formula. Large negative arguments are made positive using
+ * a reflection formula.
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE    -170,-33      20000       2.3e-15     3.3e-16
+ *    IEEE     -33,  33     20000       9.4e-16     2.2e-16
+ *    IEEE      33, 171.6   20000       2.3e-15     3.2e-16
+ *
+ * Error for arguments outside the test range will be larger
+ * owing to error amplification by the exponential function.
+ */
+
+/*
+ * Natural logarithm of gamma function
+ *
+ *
+ * SYNOPSIS:
+ *
+ * double x, y, lgam();
+ * extern int sgngam;
+ *
+ * y = lgam( x );
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the base e (2.718...) logarithm of the absolute
+ * value of the gamma function of the argument.
+ * The sign (+1 or -1) of the gamma function is returned in a
+ * global (extern) variable named sgngam.
+ *
+ * For arguments greater than 13, the logarithm of the gamma
+ * function is approximated by the logarithmic version of
+ * Stirling's formula using a polynomial approximation of
+ * degree 4. Arguments between -33 and +33 are reduced by
+ * recurrence to the interval [2,3] of a rational approximation.
+ * The cosecant reflection formula is employed for arguments
+ * less than -33.
+ *
+ * Arguments greater than MAXLGM return INFINITY and an error
+ * message.  MAXLGM = 2.556348e305 for IEEE arithmetic.
+ *
+ *
+ * ACCURACY:
+ *
+ * arithmetic      domain        # trials     peak         rms
+ *    IEEE    0, 3                 28000     5.4e-16     1.1e-16
+ *    IEEE    2.718, 2.556e305     40000     3.5e-16     8.3e-17
+ * The error criterion was relative when the function magnitude
+ * was greater than one but absolute when it was less than one.
+ *
+ * The following test used the relative error criterion, though
+ * at certain points the relative error could be much higher than
+ * indicated.
+ *    IEEE    -200, -4             10000     4.8e-16     1.3e-16
+ */
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1984, 1987, 1989, 1992, 2000 by Stephen L. Moshier
+*/
+
+#ifndef INFINITY
+#  define INFINITY 1.79769313486231570815E308 /* 2**1024*(1-MACHEP) */
+#endif
+#ifndef NAN
+#  define NAN 0.0
+#endif
+
+static double P[] = {
+  1.60119522476751861407E-4,
+  1.19135147006586384913E-3,
+  1.04213797561761569935E-2,
+  4.76367800457137231464E-2,
+  2.07448227648435975150E-1,
+  4.94214826801497100753E-1,
+  9.99999999999999996796E-1
+};
+static double Q[] = {
+  -2.31581873324120129819E-5,
+  5.39605580493303397842E-4,
+  -4.45641913851797240494E-3,
+  1.18139785222060435552E-2,
+  3.58236398605498653373E-2,
+  -2.34591795718243348568E-1,
+  7.14304917030273074085E-2,
+  1.00000000000000000320E0
+};
+static double LOGPI = 1.14472988584940017414;
+
+/* Stirling's formula for the gamma function */
+static double STIR[5] = {
+  7.87311395793093628397E-4,
+  -2.29549961613378126380E-4,
+  -2.68132617805781232825E-3,
+  3.47222221605458667310E-3,
+  8.33333333333482257126E-2,
+};
+static double MAXSTIR = 143.01608;
+static double SQTPI = 2.50662827463100050242E0;
+static double MAXLGM = 2.556348e305;
+
+int sgngam = 0;
+
+/*!
+ * \brief Gamma function computed by Stirling's formula.
+ * The polynomial STIR is valid for 33 <= x <= 172.
+ */
+static double stirf(double x)
+{
+  double y, w, v;
+
+  w = 1.0 / x;
+  w = 1.0 + w * polevl(w, STIR, 4);
+  y = exp(x);
+  if (x > MAXSTIR) { /* Avoid overflow in pow() */
+    v = pow(x, 0.5 * x - 0.25);
+    y = v * (v / y);
+  }
+  else {
+    y = pow(x, x - 0.5) / y;
+  }
+  y = SQTPI * y * w;
+  return(y);
+}
+
+
+
+double gam(double x)
+{
+  double p, q, z;
+  int i;
+
+  sgngam = 1;
+  if (std::isnan(x))
+    return(x);
+
+  if (std::isinf(x) == 1)
+    return(x);
+  if (std::isinf(x) == -1)
+    return(NAN);
+
+  q = fabs(x);
+
+  if (q > 33.0) {
+    if (x < 0.0) {
+      p = floor(q);
+      if (p == q) {
+      gamnan:
+        it_warning("gam(): argument domain error");
+        return (NAN);
+      }
+      i = int(p);
+      if ((i & 1) == 0)
+        sgngam = -1;
+      z = q - p;
+      if (z > 0.5) {
+        p += 1.0;
+        z = q - p;
+      }
+      z = q * sin(itpp::pi * z);
+      if (z == 0.0) {
+        return(sgngam * INFINITY);
+      }
+      z = fabs(z);
+      z = itpp::pi / (z * stirf(q));
+    }
+    else {
+      z = stirf(x);
+    }
+    return(sgngam * z);
+  }
+
+  z = 1.0;
+  while (x >= 3.0) {
+    x -= 1.0;
+    z *= x;
+  }
+
+  while (x < 0.0) {
+    if (x > -1.E-9)
+      goto small;
+    z /= x;
+    x += 1.0;
+  }
+
+  while (x < 2.0) {
+    if (x < 1.e-9)
+      goto small;
+    z /= x;
+    x += 1.0;
+  }
+
+  if (x == 2.0)
+    return(z);
+
+  x -= 2.0;
+  p = polevl(x, P, 6);
+  q = polevl(x, Q, 7);
+  return(z * p / q);
+
+small:
+  if (x == 0.0) {
+    goto gamnan;
+  }
+  else
+    return(z / ((1.0 + 0.5772156649015329 * x) * x));
+}
+
+
+
+/* A[]: Stirling's formula expansion of log gamma
+ * B[], C[]: log gamma function between 2 and 3
+ */
+static double A[] = {
+  8.11614167470508450300E-4,
+  -5.95061904284301438324E-4,
+  7.93650340457716943945E-4,
+  -2.77777777730099687205E-3,
+  8.33333333333331927722E-2
+};
+static double B[] = {
+  -1.37825152569120859100E3,
+  -3.88016315134637840924E4,
+  -3.31612992738871184744E5,
+  -1.16237097492762307383E6,
+  -1.72173700820839662146E6,
+  -8.53555664245765465627E5
+};
+static double C[] = {
+  /* 1.00000000000000000000E0, */
+  -3.51815701436523470549E2,
+  -1.70642106651881159223E4,
+  -2.20528590553854454839E5,
+  -1.13933444367982507207E6,
+  -2.53252307177582951285E6,
+  -2.01889141433532773231E6
+};
+/* log( sqrt( 2*pi ) ) */
+static double LS2PI  =  0.91893853320467274178;
+
+
+/*! Logarithm of gamma function */
+double lgam(double x)
+{
+  double p, q, u, w, z;
+  int i;
+
+  sgngam = 1;
+  if (std::isnan(x))
+    return(x);
+
+  if (!std::isfinite(x))
+    return(INFINITY);
+
+  if (x < -34.0) {
+    q = -x;
+    w = lgam(q); /* note this modifies sgngam! */
+    p = floor(q);
+    if (p == q) {
+    lgsing:
+      it_warning("lgam(): function singularity");
+      return (INFINITY);
+    }
+    i = int(p);
+    if ((i & 1) == 0)
+      sgngam = -1;
+    else
+      sgngam = 1;
+    z = q - p;
+    if (z > 0.5) {
+      p += 1.0;
+      z = p - q;
+    }
+    z = q * sin(itpp::pi * z);
+    if (z == 0.0)
+      goto lgsing;
+    /*      z = log(PI) - log( z ) - w;*/
+    z = LOGPI - log(z) - w;
+    return(z);
+  }
+
+  if (x < 13.0) {
+    z = 1.0;
+    p = 0.0;
+    u = x;
+    while (u >= 3.0) {
+      p -= 1.0;
+      u = x + p;
+      z *= u;
+    }
+    while (u < 2.0) {
+      if (u == 0.0)
+        goto lgsing;
+      z /= u;
+      p += 1.0;
+      u = x + p;
+    }
+    if (z < 0.0) {
+      sgngam = -1;
+      z = -z;
+    }
+    else
+      sgngam = 1;
+    if (u == 2.0)
+      return(log(z));
+    p -= 2.0;
+    x = x + p;
+    p = x * polevl(x, B, 5) / p1evl(x, C, 6);
+    return(log(z) + p);
+  }
+
+  if (x > MAXLGM) {
+    return(sgngam * INFINITY);
+  }
+
+  q = (x - 0.5) * log(x) - x + LS2PI;
+  if (x > 1.0e8)
+    return(q);
+
+  p = 1.0 / (x * x);
+  if (x >= 1000.0)
+    q += ((7.9365079365079365079365e-4 * p
+           - 2.7777777777777777777778e-3) * p
+          + 0.0833333333333333333333) / x;
+  else
+    q += polevl(p, A, 4) / x;
+  return(q);
+}
Index: library/bdm/base/itpp/base/bessel/chbevl.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/chbevl.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/chbevl.cpp (revision 812)
@@ -0,0 +1,102 @@
+/*!
+ * \file
+ * \brief Implementation of Chebyshev series evaluation function
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+
+
+/*
+ * Evaluate Chebyshev series
+ *
+ * int N;
+ * double x, y, coef[N], chebevl();
+ *
+ * y = chbevl( x, coef, N );
+ *
+ * DESCRIPTION:
+ *
+ * Evaluates the series
+ *
+ *        N-1
+ *         - '
+ *  y  =   >   coef[i] T (x/2)
+ *         -            i
+ *        i=0
+ *
+ * of Chebyshev polynomials Ti at argument x/2.
+ *
+ * Coefficients are stored in reverse order, i.e. the zero
+ * order term is last in the array.  Note N is the number of
+ * coefficients, not the order.
+ *
+ * If coefficients are for the interval a to b, x must
+ * have been transformed to x -> 2(2x - b - a)/(b-a) before
+ * entering the routine.  This maps x from (a, b) to (-1, 1),
+ * over which the Chebyshev polynomials are defined.
+ *
+ * If the coefficients are for the inverted interval, in
+ * which (a, b) is mapped to (1/b, 1/a), the transformation
+ * required is x -> 2(2ab/x - b - a)/(b-a).  If b is infinity,
+ * this becomes x -> 4a/x - 1.
+ *
+ * SPEED:
+ *
+ * Taking advantage of the recurrence properties of the
+ * Chebyshev polynomials, the routine requires one more
+ * addition per loop than evaluating a nested polynomial of
+ * the same degree.
+ */
+
+/*
+  Cephes Math Library Release 2.0:  April, 1987
+  Copyright 1985, 1987 by Stephen L. Moshier
+*/
+
+
+double chbevl(double x, double array[], int n)
+{
+  double b0, b1, b2, *p;
+  int i;
+
+  p = array;
+  b0 = *p++;
+  b1 = 0.0;
+  i = n - 1;
+
+  do {
+    b2 = b1;
+    b1 = b0;
+    b0 = x * b1  -  b2  + *p++;
+  }
+  while (--i);
+
+  return(0.5*(b0 - b2));
+}
Index: library/bdm/base/itpp/base/bessel/airy.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/airy.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/airy.cpp (revision 812)
@@ -0,0 +1,387 @@
+/*!
+ * \file
+ * \brief Implementation of Airy function
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+
+
+/*
+ * Airy function
+ *
+ * double x, ai, aip, bi, bip;
+ * int airy();
+ *
+ * airy( x, _&ai, _&aip, _&bi, _&bip );
+ *
+ * DESCRIPTION:
+ *
+ * Solution of the differential equation
+ *
+ * y"(x) = xy.
+ *
+ * The function returns the two independent solutions Ai, Bi
+ * and their first derivatives Ai'(x), Bi'(x).
+ *
+ * Evaluation is by power series summation for small x,
+ * by rational minimax approximations for large x.
+ *
+ * ACCURACY:
+ * Error criterion is absolute when function <= 1, relative
+ * when function > 1, except * denotes relative error criterion.
+ * For large negative x, the absolute error increases as x^1.5.
+ * For large positive x, the relative error increases as x^1.5.
+ *
+ * Arithmetic  domain   function  # trials      peak         rms
+ * IEEE        -10, 0     Ai        10000       1.6e-15     2.7e-16
+ * IEEE          0, 10    Ai        10000       2.3e-14*    1.8e-15*
+ * IEEE        -10, 0     Ai'       10000       4.6e-15     7.6e-16
+ * IEEE          0, 10    Ai'       10000       1.8e-14*    1.5e-15*
+ * IEEE        -10, 10    Bi        30000       4.2e-15     5.3e-16
+ * IEEE        -10, 10    Bi'       30000       4.9e-15     7.3e-16
+ */
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier
+*/
+
+static double c1 = 0.35502805388781723926;
+static double c2 = 0.258819403792806798405;
+static double sqrt3 = 1.732050807568877293527;
+static double sqpii = 5.64189583547756286948E-1;
+
+#define MAXAIRY 25.77
+
+#define PI 3.14159265358979323846       /* pi */
+#define MAXNUM 1.79769313486231570815E308    /* 2**1024*(1-MACHEP) */
+#define MACHEP 1.11022302462515654042E-16   /* 2**-53 */
+
+static double AN[8] = {
+  3.46538101525629032477E-1,
+  1.20075952739645805542E1,
+  7.62796053615234516538E1,
+  1.68089224934630576269E2,
+  1.59756391350164413639E2,
+  7.05360906840444183113E1,
+  1.40264691163389668864E1,
+  9.99999999999999995305E-1,
+};
+static double AD[8] = {
+  5.67594532638770212846E-1,
+  1.47562562584847203173E1,
+  8.45138970141474626562E1,
+  1.77318088145400459522E2,
+  1.64234692871529701831E2,
+  7.14778400825575695274E1,
+  1.40959135607834029598E1,
+  1.00000000000000000470E0,
+};
+
+static double APN[8] = {
+  6.13759184814035759225E-1,
+  1.47454670787755323881E1,
+  8.20584123476060982430E1,
+  1.71184781360976385540E2,
+  1.59317847137141783523E2,
+  6.99778599330103016170E1,
+  1.39470856980481566958E1,
+  1.00000000000000000550E0,
+};
+static double APD[8] = {
+  3.34203677749736953049E-1,
+  1.11810297306158156705E1,
+  7.11727352147859965283E1,
+  1.58778084372838313640E2,
+  1.53206427475809220834E2,
+  6.86752304592780337944E1,
+  1.38498634758259442477E1,
+  9.99999999999999994502E-1,
+};
+
+
+static double BN16[5] = {
+  -2.53240795869364152689E-1,
+  5.75285167332467384228E-1,
+  -3.29907036873225371650E-1,
+  6.44404068948199951727E-2,
+  -3.82519546641336734394E-3,
+};
+static double BD16[5] = {
+  /* 1.00000000000000000000E0,*/
+  -7.15685095054035237902E0,
+  1.06039580715664694291E1,
+  -5.23246636471251500874E0,
+  9.57395864378383833152E-1,
+  -5.50828147163549611107E-2,
+};
+
+
+static double BPPN[5] = {
+  4.65461162774651610328E-1,
+  -1.08992173800493920734E0,
+  6.38800117371827987759E-1,
+  -1.26844349553102907034E-1,
+  7.62487844342109852105E-3,
+};
+static double BPPD[5] = {
+  /* 1.00000000000000000000E0,*/
+  -8.70622787633159124240E0,
+  1.38993162704553213172E1,
+  -7.14116144616431159572E0,
+  1.34008595960680518666E0,
+  -7.84273211323341930448E-2,
+};
+
+static double AFN[9] = {
+  -1.31696323418331795333E-1,
+  -6.26456544431912369773E-1,
+  -6.93158036036933542233E-1,
+  -2.79779981545119124951E-1,
+  -4.91900132609500318020E-2,
+  -4.06265923594885404393E-3,
+  -1.59276496239262096340E-4,
+  -2.77649108155232920844E-6,
+  -1.67787698489114633780E-8,
+};
+static double AFD[9] = {
+  /* 1.00000000000000000000E0,*/
+  1.33560420706553243746E1,
+  3.26825032795224613948E1,
+  2.67367040941499554804E1,
+  9.18707402907259625840E0,
+  1.47529146771666414581E0,
+  1.15687173795188044134E-1,
+  4.40291641615211203805E-3,
+  7.54720348287414296618E-5,
+  4.51850092970580378464E-7,
+};
+
+static double AGN[11] = {
+  1.97339932091685679179E-2,
+  3.91103029615688277255E-1,
+  1.06579897599595591108E0,
+  9.39169229816650230044E-1,
+  3.51465656105547619242E-1,
+  6.33888919628925490927E-2,
+  5.85804113048388458567E-3,
+  2.82851600836737019778E-4,
+  6.98793669997260967291E-6,
+  8.11789239554389293311E-8,
+  3.41551784765923618484E-10,
+};
+static double AGD[10] = {
+  /*  1.00000000000000000000E0,*/
+  9.30892908077441974853E0,
+  1.98352928718312140417E1,
+  1.55646628932864612953E1,
+  5.47686069422975497931E0,
+  9.54293611618961883998E-1,
+  8.64580826352392193095E-2,
+  4.12656523824222607191E-3,
+  1.01259085116509135510E-4,
+  1.17166733214413521882E-6,
+  4.91834570062930015649E-9,
+};
+
+
+static double APFN[9] = {
+  1.85365624022535566142E-1,
+  8.86712188052584095637E-1,
+  9.87391981747398547272E-1,
+  4.01241082318003734092E-1,
+  7.10304926289631174579E-2,
+  5.90618657995661810071E-3,
+  2.33051409401776799569E-4,
+  4.08718778289035454598E-6,
+  2.48379932900442457853E-8,
+};
+static double APFD[9] = {
+  /*  1.00000000000000000000E0,*/
+  1.47345854687502542552E1,
+  3.75423933435489594466E1,
+  3.14657751203046424330E1,
+  1.09969125207298778536E1,
+  1.78885054766999417817E0,
+  1.41733275753662636873E-1,
+  5.44066067017226003627E-3,
+  9.39421290654511171663E-5,
+  5.65978713036027009243E-7,
+};
+
+static double APGN[11] = {
+  -3.55615429033082288335E-2,
+  -6.37311518129435504426E-1,
+  -1.70856738884312371053E0,
+  -1.50221872117316635393E0,
+  -5.63606665822102676611E-1,
+  -1.02101031120216891789E-1,
+  -9.48396695961445269093E-3,
+  -4.60325307486780994357E-4,
+  -1.14300836484517375919E-5,
+  -1.33415518685547420648E-7,
+  -5.63803833958893494476E-10,
+};
+static double APGD[11] = {
+  /*  1.00000000000000000000E0,*/
+  9.85865801696130355144E0,
+  2.16401867356585941885E1,
+  1.73130776389749389525E1,
+  6.17872175280828766327E0,
+  1.08848694396321495475E0,
+  9.95005543440888479402E-2,
+  4.78468199683886610842E-3,
+  1.18159633322838625562E-4,
+  1.37480673554219441465E-6,
+  5.79912514929147598821E-9,
+};
+
+
+int airy(double x, double *ai, double *aip, double *bi, double *bip)
+{
+  double z, zz, t, f, g, uf, ug, k, zeta, theta;
+  int domflg;
+
+  domflg = 0;
+  if (x > MAXAIRY) {
+    *ai = 0;
+    *aip = 0;
+    *bi = MAXNUM;
+    *bip = MAXNUM;
+    return(-1);
+  }
+
+  if (x < -2.09) {
+    domflg = 15;
+    t = sqrt(-x);
+    zeta = -2.0 * x * t / 3.0;
+    t = sqrt(t);
+    k = sqpii / t;
+    z = 1.0 / zeta;
+    zz = z * z;
+    uf = 1.0 + zz * polevl(zz, AFN, 8) / p1evl(zz, AFD, 9);
+    ug = z * polevl(zz, AGN, 10) / p1evl(zz, AGD, 10);
+    theta = zeta + 0.25 * PI;
+    f = sin(theta);
+    g = cos(theta);
+    *ai = k * (f * uf - g * ug);
+    *bi = k * (g * uf + f * ug);
+    uf = 1.0 + zz * polevl(zz, APFN, 8) / p1evl(zz, APFD, 9);
+    ug = z * polevl(zz, APGN, 10) / p1evl(zz, APGD, 10);
+    k = sqpii * t;
+    *aip = -k * (g * uf + f * ug);
+    *bip = k * (f * uf - g * ug);
+    return(0);
+  }
+
+  if (x >= 2.09) { /* cbrt(9) */
+    domflg = 5;
+    t = sqrt(x);
+    zeta = 2.0 * x * t / 3.0;
+    g = exp(zeta);
+    t = sqrt(t);
+    k = 2.0 * t * g;
+    z = 1.0 / zeta;
+    f = polevl(z, AN, 7) / polevl(z, AD, 7);
+    *ai = sqpii * f / k;
+    k = -0.5 * sqpii * t / g;
+    f = polevl(z, APN, 7) / polevl(z, APD, 7);
+    *aip = f * k;
+
+    if (x > 8.3203353) { /* zeta > 16 */
+      f = z * polevl(z, BN16, 4) / p1evl(z, BD16, 5);
+      k = sqpii * g;
+      *bi = k * (1.0 + f) / t;
+      f = z * polevl(z, BPPN, 4) / p1evl(z, BPPD, 5);
+      *bip = k * t * (1.0 + f);
+      return(0);
+    }
+  }
+
+  f = 1.0;
+  g = x;
+  t = 1.0;
+  uf = 1.0;
+  ug = x;
+  k = 1.0;
+  z = x * x * x;
+  while (t > MACHEP) {
+    uf *= z;
+    k += 1.0;
+    uf /= k;
+    ug *= z;
+    k += 1.0;
+    ug /= k;
+    uf /= k;
+    f += uf;
+    k += 1.0;
+    ug /= k;
+    g += ug;
+    t = fabs(uf / f);
+  }
+  uf = c1 * f;
+  ug = c2 * g;
+  if ((domflg & 1) == 0)
+    *ai = uf - ug;
+  if ((domflg & 2) == 0)
+    *bi = sqrt3 * (uf + ug);
+
+  /* the deriviative of ai */
+  k = 4.0;
+  uf = x * x / 2.0;
+  ug = z / 3.0;
+  f = uf;
+  g = 1.0 + ug;
+  uf /= 3.0;
+  t = 1.0;
+
+  while (t > MACHEP) {
+    uf *= z;
+    ug /= k;
+    k += 1.0;
+    ug *= z;
+    uf /= k;
+    f += uf;
+    k += 1.0;
+    ug /= k;
+    uf /= k;
+    g += ug;
+    k += 1.0;
+    t = fabs(ug / g);
+  }
+
+  uf = c1 * f;
+  ug = c2 * g;
+  if ((domflg & 4) == 0)
+    *aip = uf - ug;
+  if ((domflg & 8) == 0)
+    *bip = sqrt3 * (uf + ug);
+  return(0);
+}
Index: library/bdm/base/itpp/base/bessel/i0.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/i0.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/i0.cpp (revision 812)
@@ -0,0 +1,199 @@
+/*!
+ * \file
+ * \brief Implementation of modified Bessel functions of order zero
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+
+
+/*
+ *
+ * Modified Bessel function of order zero
+ *
+ * double x, y, i0();
+ *
+ * y = i0( x );
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns modified Bessel function of order zero of the
+ * argument.
+ *
+ * The function is defined as i0(x) = j0( ix ).
+ *
+ * The range is partitioned into the two intervals [0,8] and
+ * (8, infinity).  Chebyshev polynomial expansions are employed
+ * in each interval.
+ *
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0,30        30000       5.8e-16     1.4e-16
+ *
+ */
+
+/*
+ * Modified Bessel function of order zero,
+ * exponentially scaled
+ *
+ * double x, y, i0e();
+ *
+ * y = i0e( x );
+ *
+ * DESCRIPTION:
+ *
+ * Returns exponentially scaled modified Bessel function
+ * of order zero of the argument.
+ *
+ * The function is defined as i0e(x) = exp(-|x|) j0( ix ).
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0,30        30000       5.4e-16     1.2e-16
+ * See i0().
+ */
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1984, 1987, 2000 by Stephen L. Moshier
+*/
+
+
+/* Chebyshev coefficients for exp(-x) I0(x)
+ * in the interval [0,8].
+ *
+ * lim(x->0){ exp(-x) I0(x) } = 1.
+ */
+
+static double A[] = {
+  -4.41534164647933937950E-18,
+  3.33079451882223809783E-17,
+  -2.43127984654795469359E-16,
+  1.71539128555513303061E-15,
+  -1.16853328779934516808E-14,
+  7.67618549860493561688E-14,
+  -4.85644678311192946090E-13,
+  2.95505266312963983461E-12,
+  -1.72682629144155570723E-11,
+  9.67580903537323691224E-11,
+  -5.18979560163526290666E-10,
+  2.65982372468238665035E-9,
+  -1.30002500998624804212E-8,
+  6.04699502254191894932E-8,
+  -2.67079385394061173391E-7,
+  1.11738753912010371815E-6,
+  -4.41673835845875056359E-6,
+  1.64484480707288970893E-5,
+  -5.75419501008210370398E-5,
+  1.88502885095841655729E-4,
+  -5.76375574538582365885E-4,
+  1.63947561694133579842E-3,
+  -4.32430999505057594430E-3,
+  1.05464603945949983183E-2,
+  -2.37374148058994688156E-2,
+  4.93052842396707084878E-2,
+  -9.49010970480476444210E-2,
+  1.71620901522208775349E-1,
+  -3.04682672343198398683E-1,
+  6.76795274409476084995E-1
+};
+
+
+
+/* Chebyshev coefficients for exp(-x) sqrt(x) I0(x)
+ * in the inverted interval [8,infinity].
+ *
+ * lim(x->inf){ exp(-x) sqrt(x) I0(x) } = 1/sqrt(2pi).
+ */
+
+static double B[] = {
+  -7.23318048787475395456E-18,
+  -4.83050448594418207126E-18,
+  4.46562142029675999901E-17,
+  3.46122286769746109310E-17,
+  -2.82762398051658348494E-16,
+  -3.42548561967721913462E-16,
+  1.77256013305652638360E-15,
+  3.81168066935262242075E-15,
+  -9.55484669882830764870E-15,
+  -4.15056934728722208663E-14,
+  1.54008621752140982691E-14,
+  3.85277838274214270114E-13,
+  7.18012445138366623367E-13,
+  -1.79417853150680611778E-12,
+  -1.32158118404477131188E-11,
+  -3.14991652796324136454E-11,
+  1.18891471078464383424E-11,
+  4.94060238822496958910E-10,
+  3.39623202570838634515E-9,
+  2.26666899049817806459E-8,
+  2.04891858946906374183E-7,
+  2.89137052083475648297E-6,
+  6.88975834691682398426E-5,
+  3.36911647825569408990E-3,
+  8.04490411014108831608E-1
+};
+
+
+double i0(double x)
+{
+  double y;
+
+  if (x < 0)
+    x = -x;
+  if (x <= 8.0) {
+    y = (x / 2.0) - 2.0;
+    return(exp(x) * chbevl(y, A, 30));
+  }
+
+  return(exp(x) * chbevl(32.0 / x - 2.0, B, 25) / sqrt(x));
+
+}
+
+
+double i0e(double x)
+{
+  double y;
+
+  if (x < 0)
+    x = -x;
+  if (x <= 8.0) {
+    y = (x / 2.0) - 2.0;
+    return(chbevl(y, A, 30));
+  }
+
+  return(chbevl(32.0 / x - 2.0, B, 25) / sqrt(x));
+
+}
Index: library/bdm/base/itpp/base/bessel/kn.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/kn.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/kn.cpp (revision 812)
@@ -0,0 +1,263 @@
+/*!
+ * \file
+ * \brief Implementation of modified Bessel functions of third kind
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+#include <itpp/base/itassert.h>
+
+
+/*
+ * Modified Bessel function, third kind, integer order
+ *
+ * double x, y, kn();
+ * int n;
+ *
+ * y = kn( n, x );
+ *
+ * DESCRIPTION:
+ *
+ * Returns modified Bessel function of the third kind
+ * of order n of the argument.
+ *
+ * The range is partitioned into the two intervals [0,9.55] and
+ * (9.55, infinity).  An ascending power series is used in the
+ * low range, and an asymptotic expansion in the high range.
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0,30        90000       1.8e-8      3.0e-10
+ *
+ *  Error is high only near the crossover point x = 9.55
+ * between the two expansions used.
+ */
+
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1984, 1987, 1988, 2000 by Stephen L. Moshier
+*/
+
+
+/*
+Algorithm for Kn.
+                       n-1
+                   -n   -  (n-k-1)!    2   k
+K (x)  =  0.5 (x/2)     >  -------- (-x /4)
+ n                      -     k!
+                       k=0
+
+                    inf.                                   2   k
+       n         n   -                                   (x /4)
+ + (-1)  0.5(x/2)    >  {p(k+1) + p(n+k+1) - 2log(x/2)} ---------
+                     -                                  k! (n+k)!
+                    k=0
+
+where  p(m) is the psi function: p(1) = -EUL and
+
+                      m-1
+                       -
+      p(m)  =  -EUL +  >  1/k
+                       -
+                      k=1
+
+For large x,
+                                         2        2     2
+                                      u-1     (u-1 )(u-3 )
+K (z)  =  sqrt(pi/2z) exp(-z) { 1 + ------- + ------------ + ...}
+ v                                        1            2
+                                    1! (8z)     2! (8z)
+asymptotically, where
+
+           2
+    u = 4 v .
+
+*/
+
+
+#define EUL 5.772156649015328606065e-1
+#define MAXFAC 31
+
+#define MACHEP 1.11022302462515654042E-16   /* 2**-53 */
+#define MAXLOG 7.08396418532264106224E2     /* log 2**1022 */
+#define MINLOG -7.08396418532264106224E2    /* log 2**-1022 */
+#define MAXNUM 1.79769313486231570815E308    /* 2**1024*(1-MACHEP) */
+#define PI 3.14159265358979323846       /* pi */
+
+
+double kn(int nn, double x)
+{
+  double k, kf, nk1f, nkf, zn, t, s, z0, z;
+  double ans, fn, pn, pk, zmn, tlg, tox;
+  int i, n;
+
+  if (nn < 0)
+    n = -nn;
+  else
+    n = nn;
+
+  if (n > MAXFAC) {
+  overf:
+    it_warning("kn(): overflow range error");
+    return(MAXNUM);
+  }
+
+  if (x <= 0.0) {
+    if (x < 0.0)
+      it_warning("kn(): argument domain error");
+    else
+      it_warning("kn(): function singularity");
+    return(MAXNUM);
+  }
+
+
+  if (x > 9.55)
+    goto asymp;
+
+  ans = 0.0;
+  z0 = 0.25 * x * x;
+  fn = 1.0;
+  pn = 0.0;
+  zmn = 1.0;
+  tox = 2.0 / x;
+
+  if (n > 0) {
+    /* compute factorial of n and psi(n) */
+    pn = -EUL;
+    k = 1.0;
+    for (i = 1; i < n; i++) {
+      pn += 1.0 / k;
+      k += 1.0;
+      fn *= k;
+    }
+
+    zmn = tox;
+
+    if (n == 1) {
+      ans = 1.0 / x;
+    }
+    else {
+      nk1f = fn / n;
+      kf = 1.0;
+      s = nk1f;
+      z = -z0;
+      zn = 1.0;
+      for (i = 1; i < n; i++) {
+        nk1f = nk1f / (n - i);
+        kf = kf * i;
+        zn *= z;
+        t = nk1f * zn / kf;
+        s += t;
+        if ((MAXNUM - fabs(t)) < fabs(s))
+          goto overf;
+        if ((tox > 1.0) && ((MAXNUM / tox) < zmn))
+          goto overf;
+        zmn *= tox;
+      }
+      s *= 0.5;
+      t = fabs(s);
+      if ((zmn > 1.0) && ((MAXNUM / zmn) < t))
+        goto overf;
+      if ((t > 1.0) && ((MAXNUM / t) < zmn))
+        goto overf;
+      ans = s * zmn;
+    }
+  }
+
+
+  tlg = 2.0 * log(0.5 * x);
+  pk = -EUL;
+  if (n == 0) {
+    pn = pk;
+    t = 1.0;
+  }
+  else {
+    pn = pn + 1.0 / n;
+    t = 1.0 / fn;
+  }
+  s = (pk + pn - tlg) * t;
+  k = 1.0;
+  do {
+    t *= z0 / (k * (k + n));
+    pk += 1.0 / k;
+    pn += 1.0 / (k + n);
+    s += (pk + pn - tlg) * t;
+    k += 1.0;
+  }
+  while (fabs(t / s) > MACHEP);
+
+  s = 0.5 * s / zmn;
+  if (n & 1)
+    s = -s;
+  ans += s;
+
+  return(ans);
+
+
+
+  /* Asymptotic expansion for Kn(x) */
+  /* Converges to 1.4e-17 for x > 18.4 */
+
+asymp:
+
+  if (x > MAXLOG) {
+    it_warning("kn(): underflow range error");
+    return(0.0);
+  }
+  k = n;
+  pn = 4.0 * k * k;
+  pk = 1.0;
+  z0 = 8.0 * x;
+  fn = 1.0;
+  t = 1.0;
+  s = t;
+  nkf = MAXNUM;
+  i = 0;
+  do {
+    z = pn - pk * pk;
+    t = t * z / (fn * z0);
+    nk1f = fabs(t);
+    if ((i >= n) && (nk1f > nkf)) {
+      goto adone;
+    }
+    nkf = nk1f;
+    s += t;
+    fn += 1.0;
+    pk += 2.0;
+    i += 1;
+  }
+  while (fabs(t / s) > MACHEP);
+
+adone:
+  ans = exp(-x) * sqrt(PI / (2.0 * x)) * s;
+  return(ans);
+}
Index: library/bdm/base/itpp/base/bessel/struve.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/struve.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/struve.cpp (revision 812)
@@ -0,0 +1,270 @@
+/*!
+ * \file
+ * \brief Implementation of struve function
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+
+
+/*
+ * Struve function
+ *
+ * double v, x, y, struve();
+ *
+ * y = struve( v, x );
+ *
+ * DESCRIPTION:
+ *
+ * Computes the Struve function Hv(x) of order v, argument x.
+ * Negative x is rejected unless v is an integer.
+ *
+ * This module also contains the hypergeometric functions 1F2
+ * and 3F0 and a routine for the Bessel function Yv(x) with
+ * noninteger v.
+ *
+ * ACCURACY:
+ *
+ * Not accurately characterized, but spot checked against tables.
+ */
+
+/*
+  Cephes Math Library Release 2.81:  June, 2000
+  Copyright 1984, 1987, 1989, 2000 by Stephen L. Moshier
+*/
+
+static double stop = 1.37e-17;
+
+#define MACHEP 1.11022302462515654042E-16   /* 2**-53 */
+
+double onef2(double a, double b, double c, double x, double *err)
+{
+  double n, a0, sum, t;
+  double an, bn, cn, max, z;
+
+  an = a;
+  bn = b;
+  cn = c;
+  a0 = 1.0;
+  sum = 1.0;
+  n = 1.0;
+  t = 1.0;
+  max = 0.0;
+
+  do {
+    if (an == 0)
+      goto done;
+    if (bn == 0)
+      goto error;
+    if (cn == 0)
+      goto error;
+    if ((a0 > 1.0e34) || (n > 200))
+      goto error;
+    a0 *= (an * x) / (bn * cn * n);
+    sum += a0;
+    an += 1.0;
+    bn += 1.0;
+    cn += 1.0;
+    n += 1.0;
+    z = fabs(a0);
+    if (z > max)
+      max = z;
+    if (sum != 0)
+      t = fabs(a0 / sum);
+    else
+      t = z;
+  }
+  while (t > stop);
+
+done:
+
+  *err = fabs(MACHEP * max / sum);
+
+  goto xit;
+
+error:
+  *err = 1.0e38;
+
+xit:
+  return(sum);
+}
+
+
+double threef0(double a, double b, double c, double x, double *err)
+{
+  double n, a0, sum, t, conv, conv1;
+  double an, bn, cn, max, z;
+
+  an = a;
+  bn = b;
+  cn = c;
+  a0 = 1.0;
+  sum = 1.0;
+  n = 1.0;
+  t = 1.0;
+  max = 0.0;
+  conv = 1.0e38;
+  conv1 = conv;
+
+  do {
+    if (an == 0.0)
+      goto done;
+    if (bn == 0.0)
+      goto done;
+    if (cn == 0.0)
+      goto done;
+    if ((a0 > 1.0e34) || (n > 200))
+      goto error;
+    a0 *= (an * bn * cn * x) / n;
+    an += 1.0;
+    bn += 1.0;
+    cn += 1.0;
+    n += 1.0;
+    z = fabs(a0);
+    if (z > max)
+      max = z;
+    if (z >= conv) {
+      if ((z < max) && (z > conv1))
+        goto done;
+    }
+    conv1 = conv;
+    conv = z;
+    sum += a0;
+    if (sum != 0)
+      t = fabs(a0 / sum);
+    else
+      t = z;
+  }
+  while (t > stop);
+
+done:
+
+  t = fabs(MACHEP * max / sum);
+
+  max = fabs(conv / sum);
+  if (max > t)
+    t = max;
+
+  goto xit;
+
+error:
+  t = 1.0e38;
+
+xit:
+
+  *err = t;
+  return(sum);
+}
+
+#define PI 3.14159265358979323846       /* pi */
+
+double struve(double v, double x)
+{
+  double y, ya, f, g, h, t;
+  double onef2err, threef0err;
+
+  f = floor(v);
+  if ((v < 0) && (v - f == 0.5)) {
+    y = jv(-v, x);
+    f = 1.0 - f;
+    g =  2.0 * floor(f / 2.0);
+    if (g != f)
+      y = -y;
+    return(y);
+  }
+  t = 0.25 * x * x;
+  f = fabs(x);
+  g = 1.5 * fabs(v);
+  if ((f > 30.0) && (f > g)) {
+    onef2err = 1.0e38;
+    y = 0.0;
+  }
+  else {
+    y = onef2(1.0, 1.5, 1.5 + v, -t, &onef2err);
+  }
+
+  if ((f < 18.0) || (x < 0.0)) {
+    threef0err = 1.0e38;
+    ya = 0.0;
+  }
+  else {
+    ya = threef0(1.0, 0.5, 0.5 - v, -1.0 / t, &threef0err);
+  }
+
+  f = sqrt(PI);
+  h = pow(0.5 * x, v - 1.0);
+
+  if (onef2err <= threef0err) {
+    g = gam(v + 1.5);
+    y = y * h * t / (0.5 * f * g);
+    return(y);
+  }
+  else {
+    g = gam(v + 0.5);
+    ya = ya * h / (f * g);
+    ya = ya + yv(v, x);
+    return(ya);
+  }
+}
+
+
+/*
+ * Bessel function of noninteger order
+ */
+double yv(double v, double x)
+{
+  double y, t;
+  int n;
+
+  y = floor(v);
+  if (y == v) {
+    n = int(v);
+    y = yn(n, x);
+    return(y);
+  }
+  t = PI * v;
+  y = (cos(t) * jv(v, x) - jv(-v, x)) / sin(t);
+  return(y);
+}
+
+/* Crossover points between ascending series and asymptotic series
+ * for Struve function
+ *
+ *  v  x
+ *
+ *  0 19.2
+ *  1 18.95
+ *  2 19.15
+ *  3 19.3
+ *  5 19.7
+ * 10 21.35
+ * 20 26.35
+ * 30 32.31
+ * 40 40.0
+ */
Index: library/bdm/base/itpp/base/bessel/i1.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/i1.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/i1.cpp (revision 812)
@@ -0,0 +1,195 @@
+/*!
+ * \file
+ * \brief Implementation of modified Bessel functions of order one
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+
+
+/*
+ * Modfied Bessel function of order one
+ *
+ * double x, y, i1();
+ *
+ * y = i1( x );
+ *
+ * DESCRIPTION:
+ *
+ * Returns modified Bessel function of order one of the
+ * argument.
+ *
+ * The function is defined as i1(x) = -i j1( ix ).
+ *
+ * The range is partitioned into the two intervals [0,8] and
+ * (8, infinity).  Chebyshev polynomial expansions are employed
+ * in each interval.
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0, 30       30000       1.9e-15     2.1e-16
+ */
+
+/*
+ * Modified Bessel function of order one, exponentially scaled
+ *
+ * double x, y, i1e();
+ *
+ * y = i1e( x );
+ *
+ * DESCRIPTION:
+ *
+ * Returns exponentially scaled modified Bessel function
+ * of order one of the argument.
+ *
+ * The function is defined as i1(x) = -i exp(-|x|) j1( ix ).
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0, 30       30000       2.0e-15     2.0e-16
+ * See i1().
+ */
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1985, 1987, 2000 by Stephen L. Moshier
+*/
+
+
+/* Chebyshev coefficients for exp(-x) I1(x) / x
+ * in the interval [0,8].
+ *
+ * lim(x->0){ exp(-x) I1(x) / x } = 1/2.
+ */
+
+static double A[] = {
+  2.77791411276104639959E-18,
+  -2.11142121435816608115E-17,
+  1.55363195773620046921E-16,
+  -1.10559694773538630805E-15,
+  7.60068429473540693410E-15,
+  -5.04218550472791168711E-14,
+  3.22379336594557470981E-13,
+  -1.98397439776494371520E-12,
+  1.17361862988909016308E-11,
+  -6.66348972350202774223E-11,
+  3.62559028155211703701E-10,
+  -1.88724975172282928790E-9,
+  9.38153738649577178388E-9,
+  -4.44505912879632808065E-8,
+  2.00329475355213526229E-7,
+  -8.56872026469545474066E-7,
+  3.47025130813767847674E-6,
+  -1.32731636560394358279E-5,
+  4.78156510755005422638E-5,
+  -1.61760815825896745588E-4,
+  5.12285956168575772895E-4,
+  -1.51357245063125314899E-3,
+  4.15642294431288815669E-3,
+  -1.05640848946261981558E-2,
+  2.47264490306265168283E-2,
+  -5.29459812080949914269E-2,
+  1.02643658689847095384E-1,
+  -1.76416518357834055153E-1,
+  2.52587186443633654823E-1
+};
+
+
+/* Chebyshev coefficients for exp(-x) sqrt(x) I1(x)
+ * in the inverted interval [8,infinity].
+ *
+ * lim(x->inf){ exp(-x) sqrt(x) I1(x) } = 1/sqrt(2pi).
+ */
+
+static double B[] = {
+  7.51729631084210481353E-18,
+  4.41434832307170791151E-18,
+  -4.65030536848935832153E-17,
+  -3.20952592199342395980E-17,
+  2.96262899764595013876E-16,
+  3.30820231092092828324E-16,
+  -1.88035477551078244854E-15,
+  -3.81440307243700780478E-15,
+  1.04202769841288027642E-14,
+  4.27244001671195135429E-14,
+  -2.10154184277266431302E-14,
+  -4.08355111109219731823E-13,
+  -7.19855177624590851209E-13,
+  2.03562854414708950722E-12,
+  1.41258074366137813316E-11,
+  3.25260358301548823856E-11,
+  -1.89749581235054123450E-11,
+  -5.58974346219658380687E-10,
+  -3.83538038596423702205E-9,
+  -2.63146884688951950684E-8,
+  -2.51223623787020892529E-7,
+  -3.88256480887769039346E-6,
+  -1.10588938762623716291E-4,
+  -9.76109749136146840777E-3,
+  7.78576235018280120474E-1
+};
+
+
+double i1(double x)
+{
+  double y, z;
+
+  z = fabs(x);
+  if (z <= 8.0) {
+    y = (z / 2.0) - 2.0;
+    z = chbevl(y, A, 29) * z * exp(z);
+  }
+  else {
+    z = exp(z) * chbevl(32.0 / z - 2.0, B, 25) / sqrt(z);
+  }
+  if (x < 0.0)
+    z = -z;
+  return(z);
+}
+
+double i1e(double x)
+{
+  double y, z;
+
+  z = fabs(x);
+  if (z <= 8.0) {
+    y = (z / 2.0) - 2.0;
+    z = chbevl(y, A, 29) * z;
+  }
+  else {
+    z = chbevl(32.0 / z - 2.0, B, 25) / sqrt(z);
+  }
+  if (x < 0.0)
+    z = -z;
+  return(z);
+}
Index: library/bdm/base/itpp/base/bessel/k0.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/k0.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/k0.cpp (revision 812)
@@ -0,0 +1,190 @@
+/*!
+ * \file
+ * \brief Implementation of modified Bessel functions of third kind
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+#include <itpp/base/itassert.h>
+
+
+/*
+ * Modified Bessel function, third kind, order zero
+ *
+ * doule x, y, k0();
+ *
+ * y = k0( x );
+ *
+ * DESCRIPTION:
+ *
+ * Returns modified Bessel function of the third kind
+ * of order zero of the argument.
+ *
+ * The range is partitioned into the two intervals [0,8] and
+ * (8, infinity).  Chebyshev polynomial expansions are employed
+ * in each interval.
+ *
+ * ACCURACY:
+ *
+ * Tested at 2000 random points between 0 and 8.  Peak absolute
+ * error (relative when K0 > 1) was 1.46e-14; rms, 4.26e-15.
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0, 30       30000       1.2e-15     1.6e-16
+ *
+ * ERROR MESSAGES:
+ *
+ *   message         condition      value returned
+ *  K0 domain          x <= 0          MAXNUM
+ */
+
+/*
+ * Modified Bessel function, third kind, order zero, exponentially scaled
+ *
+ * double x, y, k0e();
+ *
+ * y = k0e( x );
+ *
+ * DESCRIPTION:
+ *
+ * Returns exponentially scaled modified Bessel function
+ * of the third kind of order zero of the argument.
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0, 30       30000       1.4e-15     1.4e-16
+ * See k0().
+ */
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1984, 1987, 2000 by Stephen L. Moshier
+*/
+
+
+/* Chebyshev coefficients for K0(x) + log(x/2) I0(x)
+ * in the interval [0,2].  The odd order coefficients are all
+ * zero; only the even order coefficients are listed.
+ *
+ * lim(x->0){ K0(x) + log(x/2) I0(x) } = -EUL.
+ */
+
+static double A[] = {
+  1.37446543561352307156E-16,
+  4.25981614279661018399E-14,
+  1.03496952576338420167E-11,
+  1.90451637722020886025E-9,
+  2.53479107902614945675E-7,
+  2.28621210311945178607E-5,
+  1.26461541144692592338E-3,
+  3.59799365153615016266E-2,
+  3.44289899924628486886E-1,
+  -5.35327393233902768720E-1
+};
+
+
+/* Chebyshev coefficients for exp(x) sqrt(x) K0(x)
+ * in the inverted interval [2,infinity].
+ *
+ * lim(x->inf){ exp(x) sqrt(x) K0(x) } = sqrt(pi/2).
+ */
+
+static double B[] = {
+  5.30043377268626276149E-18,
+  -1.64758043015242134646E-17,
+  5.21039150503902756861E-17,
+  -1.67823109680541210385E-16,
+  5.51205597852431940784E-16,
+  -1.84859337734377901440E-15,
+  6.34007647740507060557E-15,
+  -2.22751332699166985548E-14,
+  8.03289077536357521100E-14,
+  -2.98009692317273043925E-13,
+  1.14034058820847496303E-12,
+  -4.51459788337394416547E-12,
+  1.85594911495471785253E-11,
+  -7.95748924447710747776E-11,
+  3.57739728140030116597E-10,
+  -1.69753450938905987466E-9,
+  8.57403401741422608519E-9,
+  -4.66048989768794782956E-8,
+  2.76681363944501510342E-7,
+  -1.83175552271911948767E-6,
+  1.39498137188764993662E-5,
+  -1.28495495816278026384E-4,
+  1.56988388573005337491E-3,
+  -3.14481013119645005427E-2,
+  2.44030308206595545468E0
+};
+
+
+#define MAXNUM 1.79769313486231570815E308    /* 2**1024*(1-MACHEP) */
+
+double k0(double x)
+{
+  double y, z;
+
+  if (x <= 0.0) {
+    it_warning("besselk:: argument domain error");
+    //mtherr( "k0", DOMAIN );
+    return(MAXNUM);
+  }
+
+  if (x <= 2.0) {
+    y = x * x - 2.0;
+    y = chbevl(y, A, 10) - log(0.5 * x) * i0(x);
+    return(y);
+  }
+  z = 8.0 / x - 2.0;
+  y = exp(-x) * chbevl(z, B, 25) / sqrt(x);
+  return(y);
+}
+
+
+double k0e(double x)
+{
+  double y;
+
+  if (x <= 0.0) {
+    it_warning("besselk:: argument domain error");
+    //mtherr( "k0e", DOMAIN );
+    return(MAXNUM);
+  }
+
+  if (x <= 2.0) {
+    y = x * x - 2.0;
+    y = chbevl(y, A, 10) - log(0.5 * x) * i0(x);
+    return(y * exp(x));
+  }
+
+  y = chbevl(8.0 / x - 2.0, B, 25) / sqrt(x);
+  return(y);
+}
Index: library/bdm/base/itpp/base/bessel/k1.cpp
===================================================================
--- library/bdm/base/itpp/base/bessel/k1.cpp (revision 812)
+++ library/bdm/base/itpp/base/bessel/k1.cpp (revision 812)
@@ -0,0 +1,188 @@
+/*!
+ * \file
+ * \brief Implementation of modified Bessel functions of third kind
+ * \author Tony Ottosson
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 is slightly modified routine from the Cephes library:
+ * http://www.netlib.org/cephes/
+ */
+
+#include <itpp/base/bessel/bessel_internal.h>
+#include <itpp/base/itassert.h>
+
+
+/*
+ * Modified Bessel function, third kind, order one (should be second kind?)
+ *
+ * double x, y, k1();
+ *
+ * y = k1( x );
+ *
+ * DESCRIPTION:
+ *
+ * Computes the modified Bessel function of the third kind
+ * of order one of the argument.
+ *
+ * The range is partitioned into the two intervals [0,2] and
+ * (2, infinity).  Chebyshev polynomial expansions are employed
+ * in each interval.
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0, 30       30000       1.2e-15     1.6e-16
+ *
+ * ERROR MESSAGES:
+ *
+ *   message         condition      value returned
+ * k1 domain          x <= 0          MAXNUM
+ */
+
+/*
+ * Modified Bessel function, third kind, order one, exponentially scaled
+ *
+ * SYNOPSIS:
+ *
+ * double x, y, k1e();
+ *
+ * y = k1e( x );
+ *
+ * DESCRIPTION:
+ *
+ * Returns exponentially scaled modified Bessel function
+ * of the third kind of order one of the argument:
+ *
+ *      k1e(x) = exp(x) * k1(x).
+ *
+ * ACCURACY:
+ *
+ *                      Relative error:
+ * arithmetic   domain     # trials      peak         rms
+ *    IEEE      0, 30       30000       7.8e-16     1.2e-16
+ * See k1().
+ */
+
+/*
+  Cephes Math Library Release 2.8:  June, 2000
+  Copyright 1984, 1987, 2000 by Stephen L. Moshier
+*/
+
+
+/* Chebyshev coefficients for x(K1(x) - log(x/2) I1(x))
+ * in the interval [0,2].
+ *
+ * lim(x->0){ x(K1(x) - log(x/2) I1(x)) } = 1.
+ */
+
+static double A[] = {
+  -7.02386347938628759343E-18,
+  -2.42744985051936593393E-15,
+  -6.66690169419932900609E-13,
+  -1.41148839263352776110E-10,
+  -2.21338763073472585583E-8,
+  -2.43340614156596823496E-6,
+  -1.73028895751305206302E-4,
+  -6.97572385963986435018E-3,
+  -1.22611180822657148235E-1,
+  -3.53155960776544875667E-1,
+  1.52530022733894777053E0
+};
+
+/* Chebyshev coefficients for exp(x) sqrt(x) K1(x)
+ * in the interval [2,infinity].
+ *
+ * lim(x->inf){ exp(x) sqrt(x) K1(x) } = sqrt(pi/2).
+ */
+
+static double B[] = {
+  -5.75674448366501715755E-18,
+  1.79405087314755922667E-17,
+  -5.68946255844285935196E-17,
+  1.83809354436663880070E-16,
+  -6.05704724837331885336E-16,
+  2.03870316562433424052E-15,
+  -7.01983709041831346144E-15,
+  2.47715442448130437068E-14,
+  -8.97670518232499435011E-14,
+  3.34841966607842919884E-13,
+  -1.28917396095102890680E-12,
+  5.13963967348173025100E-12,
+  -2.12996783842756842877E-11,
+  9.21831518760500529508E-11,
+  -4.19035475934189648750E-10,
+  2.01504975519703286596E-9,
+  -1.03457624656780970260E-8,
+  5.74108412545004946722E-8,
+  -3.50196060308781257119E-7,
+  2.40648494783721712015E-6,
+  -1.93619797416608296024E-5,
+  1.95215518471351631108E-4,
+  -2.85781685962277938680E-3,
+  1.03923736576817238437E-1,
+  2.72062619048444266945E0
+};
+
+
+#define MAXNUM 1.79769313486231570815E308    /* 2**1024*(1-MACHEP) */
+
+double k1(double x)
+{
+  double y, z;
+
+  z = 0.5 * x;
+  if (z <= 0.0) {
+    it_warning("k1(): argument domain error");
+    return(MAXNUM);
+  }
+
+  if (x <= 2.0) {
+    y = x * x - 2.0;
+    y =  log(z) * i1(x)  +  chbevl(y, A, 11) / x;
+    return(y);
+  }
+
+  return(exp(-x) * chbevl(8.0 / x - 2.0, B, 25) / sqrt(x));
+}
+
+
+double k1e(double x)
+{
+  double y;
+
+  if (x <= 0.0) {
+    it_warning("k1e(): argument domain error");
+    return(MAXNUM);
+  }
+
+  if (x <= 2.0) {
+    y = x * x - 2.0;
+    y =  log(0.5 * x) * i1(x)  +  chbevl(y, A, 11) / x;
+    return(y * exp(x));
+  }
+
+  return(chbevl(8.0 / x - 2.0, B, 25) / sqrt(x));
+}
Index: library/bdm/base/itpp/base/sort.h
===================================================================
--- library/bdm/base/itpp/base/sort.h (revision 812)
+++ library/bdm/base/itpp/base/sort.h (revision 812)
@@ -0,0 +1,564 @@
+/*!
+ * \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-2010  (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 Sorting algorithms that can be used in a \a Sort class
+ *
+ * - Introsort (the default and the fastest method in most cases)
+ * - Quicksort
+ * - Heapsort
+ * - Insertion 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 recurrence.
+   */
+  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 recurrence.
+   */
+  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();
+  // Nothing to sort if data vector has only one or zero elements
+  if (N < 2)
+    return;
+
+  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();
+  // Nothing to sort if data vector has only one or zero elements
+  if (N == 1)
+    return ivec("0");
+  else if (N == 0)
+    return ivec();
+
+  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: library/bdm/base/itpp/base/timing.h
===================================================================
--- library/bdm/base/itpp/base/timing.h (revision 812)
+++ library/bdm/base/itpp/base/timing.h (revision 812)
@@ -0,0 +1,179 @@
+/*!
+ * \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-2010  (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: library/bdm/base/itpp/base/matfunc.cpp
===================================================================
--- library/bdm/base/itpp/base/matfunc.cpp (revision 812)
+++ library/bdm/base/itpp/base/matfunc.cpp (revision 812)
@@ -0,0 +1,302 @@
+/*!
+ * \file
+ * \brief Various functions on vectors and matrices - source 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-2010  (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
+ *
+ * -------------------------------------------------------------------------
+ */
+
+#include <itpp/base/matfunc.h>
+#include <itpp/base/algebra/schur.h>
+#include <itpp/base/converters.h>
+#include <limits>
+
+//! \cond
+
+namespace itpp
+{
+
+// Square root of a square matrix (based on Octave sqrtm implementation)
+cmat sqrtm(const mat& A)
+{
+  return sqrtm(to_cmat(A));
+}
+
+// Square root of the complex square matrix A
+cmat sqrtm(const cmat& A)
+{
+  cmat U, T;
+  schur(A, U, T);
+
+  int n = U.rows();
+  cmat R(n, n);
+
+  R.zeros();
+  for (int j = 0; j < n; j++)
+    R(j, j) = std::sqrt(T(j, j));
+
+  const double fudge = std::sqrt(std::numeric_limits<double>::min());
+
+  for (int p = 0; p < n - 1; p++) {
+    for (int i = 0; i < n - (p + 1); i++) {
+      const int j = i + p + 1;
+      std::complex<double> s = T(i, j);
+
+      for (int k = i + 1; k < j; k++)
+        s -= R(i, k) * R(k, j);
+
+      const std::complex<double> d = R(i, i) + R(j, j) + fudge;
+      const std::complex<double> conj_d = conj(d);
+
+      R(i, j) = (s * conj_d) / (d * conj_d);
+    }
+  }
+
+  return U * R * U.H();
+}
+
+
+bool all(const bvec &testvec)
+{
+  for (int i = 0; i < testvec.length(); i++)
+    if (!testvec(i)) return false;
+  return true;
+}
+
+bool any(const bvec &testvec)
+{
+  for (int i = 0; i < testvec.length(); i++)
+    if (testvec(i)) return true;
+  return false;
+}
+
+// ----------------------------------------------------------------------
+// Instantiations
+// ----------------------------------------------------------------------
+
+template int length(const vec &v);
+template int length(const cvec &v);
+template int length(const svec &v);
+template int length(const ivec &v);
+template int length(const bvec &v);
+
+template double sum(const vec &v);
+template std::complex<double> sum(const cvec &v);
+template short sum(const svec &v);
+template int sum(const ivec &v);
+template bin sum(const bvec &v);
+
+template double sum_sqr(const vec &v);
+template std::complex<double> sum_sqr(const cvec &v);
+template short sum_sqr(const svec &v);
+template int sum_sqr(const ivec &v);
+template bin sum_sqr(const bvec &v);
+
+template vec cumsum(const vec &v);
+template cvec cumsum(const cvec &v);
+template svec cumsum(const svec &v);
+template ivec cumsum(const ivec &v);
+template bvec cumsum(const bvec &v);
+
+template double prod(const vec &v);
+template std::complex<double> prod(const cvec &v);
+template short prod(const svec &v);
+template int prod(const ivec &v);
+template bin prod(const bvec &v);
+
+template vec cross(const vec &v1, const vec &v2);
+template cvec cross(const cvec &v1, const cvec &v2);
+template ivec cross(const ivec &v1, const ivec &v2);
+template svec cross(const svec &v1, const svec &v2);
+template bvec cross(const bvec &v1, const bvec &v2);
+
+template vec reverse(const vec &in);
+template cvec reverse(const cvec &in);
+template svec reverse(const svec &in);
+template ivec reverse(const ivec &in);
+template bvec reverse(const bvec &in);
+
+template vec zero_pad(const vec &v, int n);
+template cvec zero_pad(const cvec &v, int n);
+template ivec zero_pad(const ivec &v, int n);
+template svec zero_pad(const svec &v, int n);
+template bvec zero_pad(const bvec &v, int n);
+
+template vec zero_pad(const vec &v);
+template cvec zero_pad(const cvec &v);
+template ivec zero_pad(const ivec &v);
+template svec zero_pad(const svec &v);
+template bvec zero_pad(const bvec &v);
+
+template mat  zero_pad(const mat &, int, int);
+template cmat zero_pad(const cmat &, int, int);
+template imat zero_pad(const imat &, int, int);
+template smat zero_pad(const smat &, int, int);
+template bmat zero_pad(const bmat &, int, int);
+
+template vec sum(const mat &m, int dim);
+template cvec sum(const cmat &m, int dim);
+template svec sum(const smat &m, int dim);
+template ivec sum(const imat &m, int dim);
+template bvec sum(const bmat &m, int dim);
+
+template double sumsum(const mat &X);
+template std::complex<double> sumsum(const cmat &X);
+template short sumsum(const smat &X);
+template int sumsum(const imat &X);
+template bin sumsum(const bmat &X);
+
+template vec sum_sqr(const mat & m, int dim);
+template cvec sum_sqr(const cmat &m, int dim);
+template svec sum_sqr(const smat &m, int dim);
+template ivec sum_sqr(const imat &m, int dim);
+template bvec sum_sqr(const bmat &m, int dim);
+
+template mat cumsum(const mat &m, int dim);
+template cmat cumsum(const cmat &m, int dim);
+template smat cumsum(const smat &m, int dim);
+template imat cumsum(const imat &m, int dim);
+template bmat cumsum(const bmat &m, int dim);
+
+template vec prod(const mat &m, int dim);
+template cvec prod(const cmat &v, int dim);
+template svec prod(const smat &m, int dim);
+template ivec prod(const imat &m, int dim);
+template bvec prod(const bmat &m, int dim);
+
+template vec diag(const mat &in);
+template cvec diag(const cmat &in);
+
+template void diag(const vec &in, mat &m);
+template void diag(const cvec &in, cmat &m);
+
+template mat diag(const vec &v, const int K);
+template cmat diag(const cvec &v, const int K);
+
+template mat bidiag(const vec &, const vec &);
+template cmat bidiag(const cvec &, const cvec &);
+
+template void bidiag(const vec &, const vec &, mat &);
+template void bidiag(const cvec &, const cvec &, cmat &);
+
+template void bidiag(const mat &, vec &, vec &);
+template void bidiag(const cmat &, cvec &, cvec &);
+
+template mat tridiag(const vec &main, const vec &, const vec &);
+template cmat tridiag(const cvec &main, const cvec &, const cvec &);
+
+template void tridiag(const vec &main, const vec &, const vec &, mat &);
+template void tridiag(const cvec &main, const cvec &, const cvec &, cmat &);
+
+template void tridiag(const mat &m, vec &, vec &, vec &);
+template void tridiag(const cmat &m, cvec &, cvec &, cvec &);
+
+template double trace(const mat &in);
+template std::complex<double> trace(const cmat &in);
+template short trace(const smat &in);
+template int trace(const imat &in);
+template bin trace(const bmat &in);
+
+template void transpose(const mat &m, mat &out);
+template void transpose(const cmat &m, cmat &out);
+template void transpose(const smat &m, smat &out);
+template void transpose(const imat &m, imat &out);
+template void transpose(const bmat &m, bmat &out);
+
+template mat transpose(const mat &m);
+template cmat transpose(const cmat &m);
+template smat transpose(const smat &m);
+template imat transpose(const imat &m);
+template bmat transpose(const bmat &m);
+
+template void hermitian_transpose(const mat &m, mat &out);
+template void hermitian_transpose(const cmat &m, cmat &out);
+template void hermitian_transpose(const smat &m, smat &out);
+template void hermitian_transpose(const imat &m, imat &out);
+template void hermitian_transpose(const bmat &m, bmat &out);
+
+template mat hermitian_transpose(const mat &m);
+template cmat hermitian_transpose(const cmat &m);
+template smat hermitian_transpose(const smat &m);
+template imat hermitian_transpose(const imat &m);
+template bmat hermitian_transpose(const bmat &m);
+
+template bool is_hermitian(const mat &X);
+template bool is_hermitian(const cmat &X);
+
+template bool is_unitary(const mat &X);
+template bool is_unitary(const cmat &X);
+
+template vec rvectorize(const mat &m);
+template cvec rvectorize(const cmat &m);
+template ivec rvectorize(const imat &m);
+template svec rvectorize(const smat &m);
+template bvec rvectorize(const bmat &m);
+
+template vec cvectorize(const mat &m);
+template cvec cvectorize(const cmat &m);
+template ivec cvectorize(const imat &m);
+template svec cvectorize(const smat &m);
+template bvec cvectorize(const bmat &m);
+
+template mat reshape(const mat &m, int rows, int cols);
+template cmat reshape(const cmat &m, int rows, int cols);
+template imat reshape(const imat &m, int rows, int cols);
+template smat reshape(const smat &m, int rows, int cols);
+template bmat reshape(const bmat &m, int rows, int cols);
+
+template mat reshape(const vec &m, int rows, int cols);
+template cmat reshape(const cvec &m, int rows, int cols);
+template imat reshape(const ivec &m, int rows, int cols);
+template smat reshape(const svec &m, int rows, int cols);
+template bmat reshape(const bvec &m, int rows, int cols);
+
+template mat kron(const mat &X, const mat &Y);
+template cmat kron(const cmat &X, const cmat &Y);
+template imat kron(const imat &X, const imat &Y);
+template smat kron(const smat &X, const smat &Y);
+template bmat kron(const bmat &X, const bmat &Y);
+
+template vec repmat(const vec &v, int n);
+template cvec repmat(const cvec &v, int n);
+template ivec repmat(const ivec &v, int n);
+template svec repmat(const svec &v, int n);
+template bvec repmat(const bvec &v, int n);
+
+template mat repmat(const vec &v, int m, int n, bool transpose);
+template cmat repmat(const cvec &v, int m, int n, bool transpose);
+template imat repmat(const ivec &v, int m, int n, bool transpose);
+template smat repmat(const svec &v, int m, int n, bool transpose);
+template bmat repmat(const bvec &v, int m, int n, bool transpose);
+
+template mat repmat(const mat &data, int m, int n);
+template cmat repmat(const cmat &data, int m, int n);
+template imat repmat(const imat &data, int m, int n);
+template smat repmat(const smat &data, int m, int n);
+template bmat repmat(const bmat &data, int m, int n);
+
+} // namespace itpp
+
+//! \endcond
Index: library/bdm/base/itpp/config.h
===================================================================
--- library/bdm/base/itpp/config.h (revision 812)
+++ library/bdm/base/itpp/config.h (revision 812)
@@ -0,0 +1,264 @@
+/* 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. */
+#define HAVE_ACOSH 1
+
+/* Define to 1 if you have the `asinh' function. */
+#define HAVE_ASINH 1
+
+/* Define to 1 if you have the `atanh' function. */
+#define HAVE_ATANH 1
+
+/* Define if you have a BLAS library. */
+#define HAVE_BLAS 1
+
+/* Define if you have an ACML BLAS library. */
+/* #undef HAVE_BLAS_ACML */
+
+/* Define if you have an ATLAS BLAS library. */
+/* #undef HAVE_BLAS_ATLAS */
+
+/* Define if you have an MKL BLAS library. */
+/* #undef HAVE_BLAS_MKL */
+
+/* Define to 1 if you have the `cbrt' function. */
+#define HAVE_CBRT 1
+
+/* 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 1
+
+/* Define to 1 if you have the declaration of `isnan', and to 0 if you don't.
+   */
+#define HAVE_DECL_ISNAN 1
+
+/* Define to 1 if you have the declaration of `signgam', and to 0 if you
+   don't. */
+#define HAVE_DECL_SIGNGAM 1
+
+/* 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. */
+#define HAVE_ERF 1
+
+/* Define to 1 if you have the `erfc' function. */
+#define HAVE_ERFC 1
+
+/* Define if the compiler supports extern template */
+#define HAVE_EXTERN_TEMPLATE 1
+
+/* Define if you have FFT library. */
+/* #undef HAVE_FFT */
+
+/* Define if you have FFTW3 library. */
+/* #undef HAVE_FFTW3 */
+
+/* Define if you have ACML FFT library. */
+/* #undef HAVE_FFT_ACML */
+
+/* Define if you have MKL FFT library. */
+/* #undef HAVE_FFT_MKL */
+
+/* Define to 1 if you have the `finite' function. */
+#define HAVE_FINITE 1
+
+/* 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. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `isfinite' function. */
+/* #undef HAVE_ISFINITE */
+
+/* Define to 1 if you have the `isinf' function. */
+#define HAVE_ISINF 1
+
+/* Define to 1 if you have the `isnan' function. */
+#define HAVE_ISNAN 1
+
+/* Define if you have LAPACK library. */
+#define HAVE_LAPACK 1
+
+/* Define to 1 if you have the `lgamma' function. */
+#define HAVE_LGAMMA 1
+
+/* Define to 1 if you have the `log1p' function. */
+#define HAVE_LOG1P 1
+
+/* Define to 1 if you have the `log2' function. */
+#define HAVE_LOG2 1
+
+/* 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. */
+#define HAVE_RINT 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* 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. */
+#define HAVE_STD_ISFINITE 1
+
+/* Define to 1 if you have the `std::isinf' function. */
+#define HAVE_STD_ISINF 1
+
+/* Define to 1 if you have the `std::isnan' function. */
+#define HAVE_STD_ISNAN 1
+
+/* 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. */
+#define HAVE_TGAMMA 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to use zdotusub_ Fortran wrapper. */
+#define HAVE_ZDOTUSUB 1
+
+/* Define to use "void zdotu_()". */
+/* #undef HAVE_ZDOTU_VOID */
+
+/* Define if you want exceptions handling */
+#define ITPP_EXCEPTIONS 1
+
+/* Define to the sub-directory in which libtool stores uninstalled libraries.
+   */
+#define LT_OBJDIR ".libs/"
+
+/* Name of package */
+#define PACKAGE "itpp"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "http://sourceforge.net/projects/itpp/forums/forum/115656"
+
+/* 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.7.r1749"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "itpp"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.0.7.r1749"
+
+/* The size of `int', as computed by sizeof. */
+#define SIZEOF_INT 4
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* 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 8
+
+/* 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>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Version number of package */
+#define VERSION "4.0.7.r1749"
+
+
+#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) */
+
+/* Represent GCC version in a concise form */
+#define GCC_VERSION (__GNUC__ * 10000           \
+                     + __GNUC_MINOR__ * 100     \
+                     + __GNUC_PATCHLEVEL__)
+
+#endif /* #ifndef CONFIG_H */
+
Index: library/bdm/base/itpp/itmex.h
===================================================================
--- library/bdm/base/itpp/itmex.h (revision 812)
+++ library/bdm/base/itpp/itmex.h (revision 812)
@@ -0,0 +1,919 @@
+/*!
+ * \file
+ * \brief Conversion routines between IT++ and Matlab
+ * \author Tony Ottosson and Pal Frenger
+ *
+ * -------------------------------------------------------------------------
+ *
+ * IT++ - C++ library of mathematical, signal processing, speech processing,
+ *        and communications classes and functions
+ *
+ * Copyright (C) 1995-2010  (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 ITMEX_H
+#define ITMEX_H
+
+#include <itpp/itbase.h>
+#include <mex.h>
+
+
+namespace itpp
+{
+
+//--------------------------------------------------------
+// mex -> it++
+//--------------------------------------------------------
+
+/*!
+  \addtogroup mexfiles
+  \brief Conversions between IT++ and Matlab for writing mex-files.
+  \author Tony Ottosson and Pal Frenger
+
+  These routines are used to help writng mex-files for speeding up
+  matlab simulations.
+  A simple mex-file that performs QPSK modulation is given below.
+
+  \code
+  #include <itpp/itcomm.h>
+  #include <itpp/itmex.h>
+
+  using namespace itpp;
+
+  void mexFunction(int n_output, mxArray *output[], int n_input, const mxArray *input[])
+  {
+  // Check the number of inputs and output arguments
+  if(n_output!=1) mexErrMsgTxt("Wrong number of output variables!");
+  if(n_input!=1) mexErrMsgTxt("Wrong number of input variables!");
+
+  // Convert input variables to IT++ format
+  bvec input_bits = mxArray2bvec(input[0]);
+
+  // ------------------ Start of routine ---------------------------
+  cvec output_symbols;
+  QPSK qpsk;
+
+  output_symbols = qpsk.modulate_bits(input_bits);
+  // ------------------ End of routine -----------------------------
+
+  // Create output vectors
+  output[0] = mxCreateDoubleMatrix(1,output_symbols.size(), mxCOMPLEX);
+
+  // Convert the IT++ format to Matlab format for output
+  cvec2mxArray(output_symbols, output[0]);
+  }
+  \endcode
+*/
+
+/*!
+ * \addtogroup mexfiles
+ * @{
+ */
+
+// --------------------------------------------------------
+// mex -> IT++
+// --------------------------------------------------------
+
+//! Convert the matlab-format mxArray to bin
+bin mxArray2bin(const mxArray *in);
+//! Convert the matlab-format mxArray to short
+short mxArray2short(const mxArray *in);
+//! Convert the matlab-format mxArray to int
+int mxArray2int(const mxArray *in);
+//! Convert the matlab-format mxArray to double
+double mxArray2double(const mxArray *in);
+//! Convert the matlab-format mxArray to complex<double>
+std::complex<double> mxArray2double_complex(const mxArray *in);
+//! Convert the matlab-format mxArray to string
+std::string mxArray2string(const mxArray *in);
+
+//! Convert the matlab-format mxArray to bvec
+bvec mxArray2bvec(const mxArray *in);
+//! Convert the matlab-format mxArray to svec
+svec mxArray2svec(const mxArray *in);
+//! Convert the matlab-format mxArray to ivec
+ivec mxArray2ivec(const mxArray *in);
+//! Convert the matlab-format mxArray to vec
+vec mxArray2vec(const mxArray *in);
+//! Convert the matlab-format mxArray to cvec
+cvec mxArray2cvec(const mxArray *in);
+
+//! Convert the matlab-format mxArray to bmat
+bmat mxArray2bmat(const mxArray *in);
+//! Convert the matlab-format mxArray to smat
+smat mxArray2smat(const mxArray *in);
+//! Convert the matlab-format mxArray to imat
+imat mxArray2imat(const mxArray *in);
+//! Convert the matlab-format mxArray to mat
+mat mxArray2mat(const mxArray *in);
+//! Convert the matlab-format mxArray to cmat
+cmat mxArray2cmat(const mxArray *in);
+
+// --------------------------------------------------------
+// IT++ -> mex
+// --------------------------------------------------------
+
+//! Convert bin to the matlab-format mxArray
+void bin2mxArray(const bin &in, mxArray *out);
+//! Convert short to the matlab-format mxArray
+void short2mxArray(const short &in, mxArray *out);
+//! Convert int to the matlab-format mxArray
+void int2mxArray(const int &in, mxArray *out);
+//! Convert double to the matlab-format mxArray
+void double2mxArray(const double &in, mxArray *out);
+//! Convert complex<double> to the matlab-format mxArray
+void double_complex2mxArray(const std::complex<double> &in, mxArray *out);
+//! Convert string to the matlab-format mxArray
+void string2mxArray(const std::string &in, mxArray* &out);
+
+//! Convert bvec to the matlab-format mxArray
+void bvec2mxArray(const bvec &in, mxArray *out);
+//! Convert svec to the matlab-format mxArray
+void svec2mxArray(const svec &in, mxArray *out);
+//! Convert ivec to the matlab-format mxArray
+void ivec2mxArray(const ivec &in, mxArray *out);
+//! Convert vec to the matlab-format mxArray
+void vec2mxArray(const vec &in, mxArray *out);
+//! Convert cvec to the matlab-format mxArray
+void cvec2mxArray(const cvec &in, mxArray *out);
+
+//! Convert bmat to the matlab-format mxArray
+void bmat2mxArray(const bmat &in, mxArray *out);
+//! Convert smat to the matlab-format mxArray
+void smat2mxArray(const smat &in, mxArray *out);
+//! Convert imat to the matlab-format mxArray
+void imat2mxArray(const imat &in, mxArray *out);
+//! Convert mat to the matlab-format mxArray
+void mat2mxArray(const mat &in, mxArray *out);
+//! Convert cmat to the matlab-format mxArray
+void cmat2mxArray(const cmat &in, mxArray *out);
+
+// --------------------------------------------------------
+// mex -> C
+// --------------------------------------------------------
+
+//! Convert the matlab-format mxArray to C-format pointer to short
+void mxArray2Csvec(const mxArray *in, short *out);
+//! Convert the matlab-format mxArray to C-format pointer to int
+void mxArray2Civec(const mxArray *in, int *out);
+//! Convert the matlab-format mxArray to C-format pointer to double
+void mxArray2Cvec(const mxArray *in, double *out);
+//! Convert the matlab-format mxArray to C-format pointers to double (real and imaginary parts)
+void mxArray2Ccvec(const mxArray *in, double *out_real, double *out_imag);
+
+//! Convert the matlab-format mxArray to C-format pointer to pointer to short
+void mxArray2Csmat(const mxArray *in, short **out);
+//! Convert the matlab-format mxArray to C-format pointer to pointer to int
+void mxArray2Cimat(const mxArray *in, int **out);
+//! Convert the matlab-format mxArray to C-format pointer to pointer to double
+void mxArray2Cmat(const mxArray *in, double **out);
+//! Convert the matlab-format mxArray to C-format pointer to pointer to double (real and imaginary parts)
+void mxArray2Ccmat(const mxArray *in, double **out_real, double **out_imag);
+
+// --------------------------------------------------------
+// C -> mex
+// --------------------------------------------------------
+
+//! Convert C-format pointer to short to matlab-format mxArray
+void Csvec2mxArray(short *in, mxArray *out);
+//! Convert C-format pointer to int to matlab-format mxArray
+void Civec2mxArray(int *in, mxArray *out);
+//! Convert C-format pointer to double to matlab-format mxArray
+void Cvec2mxArray(double *in, mxArray *out);
+//! Convert C-format pointers to double (real and imaginary parts) to matlab-format mxArray
+void Ccvec2mxArray(double *in_real, double *in_imag, mxArray *out);
+
+//! Convert C-format pointer to pointer to short to matlab-format mxArray
+void Csmat2mxArray(short **in, mxArray *out);
+//! Convert C-format pointer to pointer to int to matlab-format mxArray
+void Cimat2mxArray(int **in, mxArray *out);
+//! Convert C-format pointer to pointer to double to matlab-format mxArray
+void Cmat2mxArray(double **in, mxArray *out);
+//! Convert C-format pointer to pointer to double (real and imaginary parts) to matlab-format mxArray
+void Ccmat2mxArray(double **in_real, double **in_imag, mxArray *out);
+
+/*!
+ * @}
+ */
+
+
+bin mxArray2bin(const mxArray *in)
+{
+  int size;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2bin: Pointer to data is NULL");
+  size = mxGetNumberOfElements(in);
+  if (size != 1) mexErrMsgTxt("mxArray2bin: Size of data is not equal to one");
+
+  return (((*temp) > 0.0) ? bin(1) : bin(0));
+}
+
+short mxArray2short(const mxArray *in)
+{
+  int size;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2short: Pointer to data is NULL");
+  size = mxGetNumberOfElements(in);
+  if (size != 1) mexErrMsgTxt("mxArray2short: Size of data is not equal to one");
+
+  return (short)(*temp);
+}
+
+int mxArray2int(const mxArray *in)
+{
+  int size;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2int: Pointer to data is NULL");
+  size = mxGetNumberOfElements(in);
+  if (size != 1) mexErrMsgTxt("mxArray2int: Size of data is not equal to one");
+
+  return (int)(*temp);
+}
+
+double mxArray2double(const mxArray *in)
+{
+  int size;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2double: Pointer to data is NULL");
+  size = mxGetNumberOfElements(in);
+  if (size != 1) mexErrMsgTxt("mxArray2double: Size of data is not equal to one");
+
+  return (*temp);
+}
+
+std::complex<double> mxArray2double_complex(const mxArray *in)
+{
+  int size;
+  double* tempR = (double*) mxGetPr(in);
+  double* tempI = (double*) mxGetPi(in);
+
+  if ((tempR == 0) && (tempI == 0)) mexErrMsgTxt("mxArray2double_complex: Pointer to data is NULL");
+
+  size = mxGetNumberOfElements(in);
+  if (size != 1) mexErrMsgTxt("mxArray2double_complex: Size of data is not equal to one");
+
+  if (tempR == 0) {
+    return std::complex<double>(0.0 , (*tempI));
+  }
+  else if (tempI == 0) {
+    return std::complex<double>((*tempR), 0.0);
+  }
+  else {
+    return std::complex<double>((*tempR), (*tempI));
+  }
+
+}
+
+std::string mxArray2string(const mxArray *in)
+{
+  if (in == 0)
+    mexErrMsgTxt("mxArray2string: Pointer to data is NULL");
+  std::string str = mxArrayToString(in);
+  if (str.data() == 0)
+    mexErrMsgTxt("mxArray2string: Could not convert mxArray to string");
+  return str;
+}
+
+bvec mxArray2bvec(const mxArray *in)
+{
+  bvec out;
+  int i, size;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2bvec: Pointer to data is NULL");
+
+  size = mxGetNumberOfElements(in);
+  if (size == 0) mexErrMsgTxt("mxArray2bvec: Size of data is zero");
+
+  out.set_size(size, false);
+
+  for (i = 0; i < size; i++) {
+    out(i) = (((*temp++) > 1e-5) ? bin(1) : bin(0));
+  }
+
+  return out;
+
+}
+
+svec mxArray2svec(const mxArray *in)
+{
+  svec out;
+  int i, size;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2svec: Pointer to data is NULL");
+
+  size = mxGetNumberOfElements(in);
+  if (size == 0) mexErrMsgTxt("mxArray2svec: Size of data is zero");
+
+  out.set_size(size, false);
+
+  for (i = 0; i < size; i++) {
+    out(i) = (short)(*temp++);
+  }
+
+  return out;
+
+}
+
+ivec mxArray2ivec(const mxArray *in)
+{
+  ivec out;
+  int i, size;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2ivec: Pointer to data is NULL");
+
+  size = mxGetNumberOfElements(in);
+  if (size == 0) mexErrMsgTxt("mxArray2ivec: Size of data is zero");
+
+  out.set_size(size, false);
+
+  for (i = 0; i < size; i++) {
+    out(i) = (int)(*temp++);
+  }
+
+  return out;
+
+}
+
+vec mxArray2vec(const mxArray *in)
+{
+  vec out;
+  int i, size;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2vec: Pointer to data is NULL");
+
+  size = mxGetNumberOfElements(in);
+  if (size == 0) mexErrMsgTxt("mxArray2vec: Size of data is zero");
+
+  out.set_size(size, false);
+
+  for (i = 0; i < size; i++) {
+    out(i) = (*temp++);
+  }
+
+  return out;
+
+}
+
+cvec mxArray2cvec(const mxArray *in)
+{
+  cvec out;
+  int i, size;
+  double* tempR = (double*) mxGetPr(in);
+  double* tempI = (double*) mxGetPi(in);
+
+  if ((tempR == 0) && (tempI == 0)) mexErrMsgTxt("mxArray2cvec: Pointer data is NULL");
+
+  size = mxGetNumberOfElements(in);
+  if (size == 0) mexErrMsgTxt("mxArray2cvec: Size of data is zero");
+
+  out.set_size(size, false);
+
+  if (tempR == 0) {
+    for (i = 0; i < size; i++) { out(i) = std::complex<double>(0.0, (*tempI++)); }
+  }
+  else if (tempI == 0) {
+    for (i = 0; i < size; i++) { out(i) = std::complex<double>((*tempR++), 0.0); }
+  }
+  else {
+    for (i = 0; i < size; i++) { out(i) = std::complex<double>((*tempR++), (*tempI++)); }
+  }
+
+  return out;
+
+}
+
+bmat mxArray2bmat(const mxArray *in)
+{
+  bmat out;
+  int r, c, rows, cols;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2bmat: Pointer to data is NULL");
+
+  rows = mxGetM(in);
+  if (rows == 0) mexErrMsgTxt("mxArray2bmat: Data has zero rows");
+  cols = mxGetN(in);
+  if (cols == 0) mexErrMsgTxt("mxArray2bmat: Data has zero columns");
+
+  out.set_size(rows, cols, false);
+
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      out(r, c) = (((*temp++) > 0.0) ? bin(1) : bin(0));
+    }
+  }
+
+  return out;
+
+}
+
+smat mxArray2smat(const mxArray *in)
+{
+  smat out;
+  int r, c, rows, cols;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2smat: Pointer to data is NULL");
+
+  rows = mxGetM(in);
+  if (rows == 0) mexErrMsgTxt("mxArray2smat: Data has zero rows");
+  cols = mxGetN(in);
+  if (cols == 0) mexErrMsgTxt("mxArray2smat: Data has zero columns");
+
+  out.set_size(rows, cols, false);
+
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      out(r, c) = (short)(*temp++);
+    }
+  }
+
+  return out;
+
+}
+
+imat mxArray2imat(const mxArray *in)
+{
+  imat out;
+  int r, c, rows, cols;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2imat: Pointer to data is NULL");
+
+  rows = mxGetM(in);
+  if (rows == 0) mexErrMsgTxt("mxArray2imat: Data has zero rows");
+  cols = mxGetN(in);
+  if (cols == 0) mexErrMsgTxt("mxArray2imat: Data has zero columns");
+  out.set_size(rows, cols, false);
+
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      out(r, c) = (int)(*temp++);
+    }
+  }
+
+  return out;
+
+}
+
+mat mxArray2mat(const mxArray *in)
+{
+  mat out;
+  int r, c, rows, cols;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2mat: Pointer to data is NULL");
+
+  rows = mxGetM(in);
+  if (rows == 0) mexErrMsgTxt("mxArray2mat: Data has zero rows");
+  cols = mxGetN(in);
+  if (cols == 0) mexErrMsgTxt("mxArray2mat: Data has zero columns");
+  out.set_size(rows, cols, false);
+
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      out(r, c) = (*temp++);
+    }
+  }
+
+  return out;
+
+}
+
+cmat mxArray2cmat(const mxArray *in)
+{
+  cmat out;
+  int r, c, rows, cols;
+  double* tempR = (double*) mxGetPr(in);
+  double* tempI = (double*) mxGetPi(in);
+
+  if ((tempR == 0) && (tempI == 0)) mexErrMsgTxt("mxArray2cmat: Pointer to data is NULL");
+
+  rows = mxGetM(in);
+  if (rows == 0) mexErrMsgTxt("mxArray2cmat: Data has zero rows");
+  cols = mxGetN(in);
+  if (cols == 0) mexErrMsgTxt("mxArray2cmat: Data has zero columns");
+  out.set_size(rows, cols, false);
+
+  if (tempR == 0) {
+    for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { out(r, c) = std::complex<double>(0.0 , (*tempI++)); } }
+  }
+  else if (tempI == 0) {
+    for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { out(r, c) = std::complex<double>((*tempR++), 0.0); } }
+  }
+  else {
+    for (c = 0; c < cols; c++) { for (r = 0; r < rows; r++) { out(r, c) = std::complex<double>((*tempR++), (*tempI++)); } }
+  }
+
+  return out;
+
+}
+
+void double2mxArray(const double &in, mxArray *out)
+{
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("double2mxArray: Pointer to data is NULL");
+
+  *temp = (double) in;
+}
+
+void double_complex2mxArray(const std::complex<double> &in, mxArray *out)
+{
+  double* tempR = (double *) mxGetPr(out);
+  double* tempI = (double *) mxGetPi(out);
+  if (tempR == 0) mexErrMsgTxt("double_complex2mxArray: Pointer to real valued part is NULL");
+  if (tempI == 0) mexErrMsgTxt("double_complex2mxArray: Pointer to imaginary valued part is NULL");
+
+  *tempR = (double) in.real();
+  *tempI = (double) in.imag();
+}
+
+void string2mxArray(const std::string &in, mxArray* &out)
+{
+  if (in.data() == 0)
+    mexErrMsgTxt("string2mxArray: Pointer to string is NULL");
+  out = mxCreateString(in.data());
+  if (out == 0)
+    mexErrMsgTxt("string2mxArray: Could not convert string to mxArray");
+}
+
+void bvec2mxArray(const bvec &in, mxArray *out)
+{
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("bvec2mxArray: Pointer to data is NULL");
+  if (in.size() == 0) mexErrMsgTxt("bvec2mxArray: Size of data is zero");
+  for (int i = 0; i < in.size(); i++) {
+    if (in(i))
+      *temp++ = 1.0;
+    else
+      *temp++ = 0.0;
+  }
+}
+
+void ivec2mxArray(const ivec &in, mxArray *out)
+{
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("ivec2mxArray: Pointer to data is NULL");
+  if (in.size() == 0) mexErrMsgTxt("ivec2mxArray: Size of data is zero");
+
+  for (int i = 0; i < in.size(); i++) {
+    *temp++ = (double) in(i);
+  }
+}
+
+void vec2mxArray(const vec &in, mxArray *out)
+{
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("vec2mxArray: Pointer to data is NULL");
+  if (in.size() == 0) mexErrMsgTxt("vec2mxArray: Size of data is zero");
+
+  for (int i = 0; i < in.size(); i++) {
+    *temp++ = (double) in(i);
+  }
+}
+
+void cvec2mxArray(const cvec &in, mxArray *out)
+{
+  double* tempR = (double *) mxGetPr(out);
+  double* tempI = (double *) mxGetPi(out);
+  if (tempR == 0) mexErrMsgTxt("cvec2mxArray: Pointer to real valued part is NULL");
+  if (tempI == 0) mexErrMsgTxt("cvec2mxArray: Pointer to imaginary valued part is NULL");
+  if (in.size() == 0) mexErrMsgTxt("cvec2mxArray: Size of data is zero");
+
+  for (int i = 0; i < in.size(); i++) {
+    *tempR++ = (double) in(i).real();
+    *tempI++ = (double) in(i).imag();
+  }
+}
+
+void bmat2mxArray(const bmat &in, mxArray *out)
+{
+  int rows, cols, r, c;
+
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("bmat2mxArray: Pointer to data is NULL");
+
+  rows = in.rows();
+  cols = in.cols();
+  if (rows == 0) mexErrMsgTxt("bmat2mxArray: Data has zero rows");
+  if (cols == 0) mexErrMsgTxt("bmat2mxArray: Data has zero columns");
+
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      if (in(r, c))
+        *temp++ = 1.0;
+      else
+        *temp++ = 0.0;
+    }
+  }
+
+}
+
+void smat2mxArray(const smat &in, mxArray *out)
+{
+  int rows, cols, r, c;
+
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("smat2mxArray: Pointer to data is NULL");
+
+  rows = in.rows();
+  cols = in.cols();
+  if (rows == 0) mexErrMsgTxt("smat2mxArray: Data has zero rows");
+  if (cols == 0) mexErrMsgTxt("smat2mxArray: Data has zero columns");
+
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      *temp++ = (double) in(r, c);
+    }
+  }
+
+}
+
+void imat2mxArray(const imat &in, mxArray *out)
+{
+  int rows, cols, r, c;
+
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("imat2mxArray: Pointer to data is NULL");
+
+  rows = in.rows();
+  cols = in.cols();
+  if (rows == 0) mexErrMsgTxt("imat2mxArray: Data has zero rows");
+  if (cols == 0) mexErrMsgTxt("imat2mxArray: Data has zero columns");
+
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      *temp++ = (double) in(r, c);
+    }
+  }
+
+}
+
+void mat2mxArray(const mat &in, mxArray *out)
+{
+  int rows, cols, r, c;
+
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("mat2mxArray: Pointer to data is NULL");
+
+  rows = in.rows();
+  cols = in.cols();
+  if (rows == 0) mexErrMsgTxt("mat2mxArray: Data has zero rows");
+  if (cols == 0) mexErrMsgTxt("mat2mxArray: Data has zero columns");
+
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      *temp++ = in(r, c);
+    }
+  }
+
+}
+
+void cmat2mxArray(const cmat &in, mxArray *out)
+{
+  int rows, cols, r, c;
+
+  double* tempR = (double *) mxGetPr(out);
+  double* tempI = (double *) mxGetPi(out);
+  if (tempR == 0) mexErrMsgTxt("cvec2mxArray: Pointer to real valued part is NULL");
+  if (tempI == 0) mexErrMsgTxt("cvec2mxArray: Pointer to imaginary valued part is NULL");
+
+  rows = in.rows();
+  cols = in.cols();
+  if (rows == 0) mexErrMsgTxt("cvec2mxArray: Data has zero rows");
+  if (cols == 0) mexErrMsgTxt("cvec2mxArray: Data has zero columns");
+
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      *tempR++ = (double) in(r, c).real();
+      *tempI++ = (double) in(r, c).imag();
+    }
+  }
+
+}
+
+void mxArray2Csvec(const mxArray *in, short *out)
+{
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2Csvec: Pointer to data is NULL");
+  int size = mxGetNumberOfElements(in);
+  if (size == 0) mexErrMsgTxt("mxArray2Csvec: Size of data is zero");
+  for (int i = 0; i < size; i++) { out[i] = (short)(*temp++); }
+}
+
+void mxArray2Civec(const mxArray *in, int *out)
+{
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2Civec: Pointer to data is NULL");
+  int size = mxGetNumberOfElements(in);
+  if (size == 0) mexErrMsgTxt("mxArray2Civec: Size of data is zero");
+  for (int i = 0; i < size; i++) { out[i] = (int)(*temp++); }
+}
+
+void mxArray2Cvec(const mxArray *in, double *out)
+{
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2Cvec: Pointer to data is NULL");
+  int size = mxGetNumberOfElements(in);
+  if (size == 0) mexErrMsgTxt("mxArray2Cvec: Size of data is zero");
+  for (int i = 0; i < size; i++) { out[i] = (*temp++); }
+}
+
+void mxArray2Ccvec(const mxArray *in, double *out_real, double *out_imag)
+{
+  double* tempR = (double*) mxGetPr(in);
+  double* tempI = (double*) mxGetPi(in);
+  if (tempR == 0) mexErrMsgTxt("mxArray2Ccvec: Pointer to real valued part is NULL");
+  if (tempI == 0) mexErrMsgTxt("mxArray2Ccvec: Pointer to imaginary valued part is NULL");
+  int size = mxGetNumberOfElements(in);
+  if (size == 0) mexErrMsgTxt("mxArray2Ccvec: Size of data is zero");
+  for (int i = 0; i < size; i++) { out_real[i] = (*tempR++); out_imag[i] = (*tempI++); }
+}
+
+void mxArray2Csmat(const mxArray *in, short **out)
+{
+  int r, c;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2Csmat: Pointer to data is NULL");
+  int rows = mxGetM(in);
+  if (rows == 0) mexErrMsgTxt("mxArray2Csmat: Data has zero rows");
+  int cols = mxGetN(in);
+  if (cols == 0) mexErrMsgTxt("mxArray2Csmat: Data has zero columns");
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      out[r][c] = (short)(*temp++);
+    }
+  }
+}
+
+void mxArray2Cimat(const mxArray *in, int **out)
+{
+  int r, c;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2Cimat: Pointer to data is NULL");
+  int rows = mxGetM(in);
+  if (rows == 0) mexErrMsgTxt("mxArray2Cimat: Data has zero rows");
+  int cols = mxGetN(in);
+  if (cols == 0) mexErrMsgTxt("mxArray2Cimat: Data has zero columns");
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      out[r][c] = (int)(*temp++);
+    }
+  }
+}
+
+void mxArray2Cmat(const mxArray *in, double **out)
+{
+  int r, c;
+  double* temp = (double*) mxGetPr(in);
+  if (temp == 0) mexErrMsgTxt("mxArray2Cmat: Pointer to data is NULL");
+  int rows = mxGetM(in);
+  if (rows == 0) mexErrMsgTxt("mxArray2Cmat: Data has zero rows");
+  int cols = mxGetN(in);
+  if (cols == 0) mexErrMsgTxt("mxArray2Cmat: Data has zero columns");
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      out[r][c] = (*temp++);
+    }
+  }
+}
+
+void mxArray2Ccmat(const mxArray *in, double **out_real, double **out_imag)
+{
+  int r, c;
+  double* tempR = (double*) mxGetPr(in);
+  double* tempI = (double*) mxGetPi(in);
+  if (tempR == 0) mexErrMsgTxt("mxArray2Cmat: Pointer to real valued part is NULL");
+  if (tempI == 0) mexErrMsgTxt("mxArray2Cmat: Pointer to imaginary valued part is NULL");
+  int rows = mxGetM(in);
+  if (rows == 0) mexErrMsgTxt("mxArray2Cmat: Data has zero rows");
+  int cols = mxGetN(in);
+  if (cols == 0) mexErrMsgTxt("mxArray2Cmat: Data has zero columns");
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      out_real[r][c] = (*tempR++);
+      out_imag[r][c] = (*tempI++);
+    }
+  }
+}
+
+void Csvec2mxArray(short *in, mxArray *out)
+{
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("Csvec2mxArray: Pointer to data is NULL");
+  int size = mxGetNumberOfElements(out);
+  if (size == 0) mexErrMsgTxt("Csvec2mxArray: Size of data is zero");
+  for (int i = 0; i < size; i++) { *temp++ = (double) in[i]; }
+}
+
+void Civec2mxArray(int *in, mxArray *out)
+{
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("Civec2mxArray: Pointer to data is NULL");
+  int size = mxGetNumberOfElements(out);
+  if (size == 0) mexErrMsgTxt("Civec2mxArray: Size of data is zero");
+  for (int i = 0; i < size; i++) { *temp++ = (double) in[i]; }
+}
+
+void Cvec2mxArray(double *in, mxArray *out)
+{
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("Cvec2mxArray: Pointer to data is NULL");
+  int size = mxGetNumberOfElements(out);
+  if (size == 0) mexErrMsgTxt("Cvec2mxArray: Size of data is zero");
+  for (int i = 0; i < size; i++) { *temp++ = in[i]; }
+}
+
+void Ccvec2mxArray(double *in_real, double *in_imag, mxArray *out)
+{
+  double* tempR = (double *) mxGetPr(out);
+  double* tempI = (double *) mxGetPi(out);
+  if (tempR == 0) mexErrMsgTxt("Ccvec2mxArray: Pointer to real valued part is NULL");
+  if (tempI == 0) mexErrMsgTxt("Ccvec2mxArray: Pointer to imaginary valued part is NULL");
+  int size = mxGetNumberOfElements(out);
+  if (size == 0) mexErrMsgTxt("Ccvec2mxArray: Size of data is zero");
+  for (int i = 0; i < size; i++) { *tempR++ = in_real[i]; *tempI++ = in_imag[i]; }
+}
+
+void Csmat2mxArray(short **in, mxArray *out)
+{
+  int r, c;
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("Csmat2mxArray: Pointer to data is NULL");
+  int rows = mxGetM(out);
+  if (rows == 0) mexErrMsgTxt("Csmat2mxArray: Data has zero rows");
+  int cols = mxGetN(out);
+  if (cols == 0) mexErrMsgTxt("Csmat2mxArray: Data has zero columns");
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      *temp++ = (short) in[r][c];
+    }
+  }
+}
+
+void Cimat2mxArray(int **in, mxArray *out)
+{
+  int r, c;
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("Cimat2mxArray: Pointer to data is NULL");
+  int rows = mxGetM(out);
+  if (rows == 0) mexErrMsgTxt("Cimat2mxArray: Data has zero rows");
+  int cols = mxGetN(out);
+  if (cols == 0) mexErrMsgTxt("Cimat2mxArray: Data has zero columns");
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      *temp++ = (int) in[r][c];
+    }
+  }
+}
+
+void Cmat2mxArray(double **in, mxArray *out)
+{
+  int r, c;
+  double* temp = (double *) mxGetPr(out);
+  if (temp == 0) mexErrMsgTxt("Cmat2mxArray: Pointer to data is NULL");
+  int rows = mxGetM(out);
+  if (rows == 0) mexErrMsgTxt("Cmat2mxArray: Data has zero rows");
+  int cols = mxGetN(out);
+  if (cols == 0) mexErrMsgTxt("Cmat2mxArray: Data has zero columns");
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      *temp++ = in[r][c];
+    }
+  }
+}
+
+void Ccmat2mxArray(double **in_real, double **in_imag, mxArray *out)
+{
+  int r, c;
+  double* tempR = (double *) mxGetPr(out);
+  double* tempI = (double *) mxGetPi(out);
+  if (tempR == 0) mexErrMsgTxt("Ccmat2mxArray: Pointer to real valued part is NULL");
+  if (tempI == 0) mexErrMsgTxt("Ccmat2mxArray: Pointer to imaginary valued part is NULL");
+  int rows = mxGetM(out);
+  if (rows == 0) mexErrMsgTxt("Ccmat2mxArray: Data has zero rows");
+  int cols = mxGetN(out);
+  if (cols == 0) mexErrMsgTxt("Ccmat2mxArray: Data has zero columns");
+  for (c = 0; c < cols; c++) {
+    for (r = 0; r < rows; r++) {
+      *tempR++ = in_real[r][c];
+      *tempI++ = in_imag[r][c];
+    }
+  }
+}
+
+} // namespace itpp
+
+#endif // #ifndef ITMEX_H
Index: library/bdm/base/itpp/CMakeLists.txt
===================================================================
--- library/bdm/base/itpp/CMakeLists.txt (revision 812)
+++ library/bdm/base/itpp/CMakeLists.txt (revision 812)
@@ -0,0 +1,19 @@
+# Create a library called "bdm" which includes sources from all subdirectories
+
+SET(itpp_base base/bessel.cpp   base/converters.cpp  base/help_functions.cpp  base/mat.cpp        base/parser.cpp  base/specmat.cpp  base/vec.cpp
+base/binary.cpp   base/fastmath.cpp    base/itassert.cpp        base/matfunc.cpp    base/random.cpp  base/svec.cpp
+base/binfile.cpp  base/gf2mat.cpp      base/itfile.cpp          base/operators.cpp  base/smat.cpp    base/timing.cpp)
+
+SET(itpp_algebra base/algebra/cholesky.cpp  base/algebra/eigen.cpp  base/algebra/ls_solve.cpp  base/algebra/qr.cpp     base/algebra/svd.cpp
+base/algebra/det.cpp       base/algebra/inv.cpp    base/algebra/lu.cpp        base/algebra/schur.cpp )
+
+SET(itpp_bessel base/bessel/airy.cpp    base/bessel/gamma.cpp   base/bessel/i0.cpp  base/bessel/iv.cpp  base/bessel/k0.cpp  base/bessel/kn.cpp      base/bessel/struve.cpp
+base/bessel/chbevl.cpp  base/bessel/hyperg.cpp  base/bessel/i1.cpp  base/bessel/jv.cpp  base/bessel/k1.cpp  base/bessel/polevl.cpp)
+
+SET(itpp_math base/math/elem_math.cpp  base/math/error.cpp  base/math/integration.cpp  base/math/misc.cpp)
+
+# add BDMLIB compile flag
+#ADD_DEFINITIONS(-DNDEBUG)
+
+# Normal BDM library
+add_library (itpp STATIC ${itpp_base} ${itpp_algebra} ${itpp_bessel} ${itpp_math})
Index: library/bdm/base/itpp/itbase.h
===================================================================
--- library/bdm/base/itpp/itbase.h (revision 812)
+++ library/bdm/base/itpp/itbase.h (revision 812)
@@ -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-2010  (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
