Index: trunk/BNC/newmat/bandmat.cpp
===================================================================
--- trunk/BNC/newmat/bandmat.cpp	(revision 2013)
+++ trunk/BNC/newmat/bandmat.cpp	(revision 2013)
@@ -0,0 +1,717 @@
+/// \ingroup newmat
+///@{
+
+/// \file bandmat.cpp
+/// Band-matrix member functions.
+
+
+// Copyright (C) 1991,2,3,4,9: R B Davies
+
+#define WANT_MATH                    // include.h will get math fns
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,10); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+static inline int my_min(int x, int y) { return x < y ? x : y; }
+static inline int my_max(int x, int y) { return x > y ? x : y; }
+
+
+BandMatrix::BandMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::BM);
+   GetMatrix(gmx); CornerClear();
+}
+
+void BandMatrix::SetParameters(const GeneralMatrix* gmx)
+{
+   REPORT
+   MatrixBandWidth bw = gmx->bandwidth();
+   lower_val = bw.lower_val; upper_val = bw.upper_val;
+}
+
+void BandMatrix::resize(int n, int lb, int ub)
+{
+   REPORT
+   Tracer tr("BandMatrix::resize");
+   if (lb<0 || ub<0) Throw(ProgramException("Undefined bandwidth"));
+   lower_val = (lb<=n) ? lb : n-1; upper_val = (ub<=n) ? ub : n-1;
+   GeneralMatrix::resize(n,n,n*(lower_val+1+upper_val)); CornerClear();
+}
+
+// SimpleAddOK shows when we can add etc two matrices by a simple vector add
+// and when we can add one matrix into another
+//
+// *gm must be the same type as *this
+// - return 0 if simple add is OK
+// - return 1 if we can add into *gm only
+// - return 2 if we can add into *this only
+// - return 3 if we can't add either way
+//
+// For SP this will still be valid if we swap 1 and 2
+
+/// \brief can we add two band matrices with simple vector add
+///
+/// For band matrices the bandwidths must agree
+
+short BandMatrix::SimpleAddOK(const GeneralMatrix* gm)
+{
+   const BandMatrix* bm = (const BandMatrix*)gm;
+   if (bm->lower_val == lower_val && bm->upper_val == upper_val)
+      { REPORT return 0; }
+   else if (bm->lower_val >= lower_val && bm->upper_val >= upper_val)
+      { REPORT return 1; }
+   else if (bm->lower_val <= lower_val && bm->upper_val <= upper_val)
+      { REPORT return 2; }
+   else { REPORT return 3; }
+}
+
+/// \brief can we add two symmetric band matrices with simple vector add
+///
+/// Sufficient to check lower bandwidths agree
+
+short SymmetricBandMatrix::SimpleAddOK(const GeneralMatrix* gm)
+{
+   const SymmetricBandMatrix* bm = (const SymmetricBandMatrix*)gm;
+   if (bm->lower_val == lower_val) { REPORT return 0; }
+   else if (bm->lower_val > lower_val) { REPORT return 1; }
+   else { REPORT return 2; }
+}
+
+/// \brief resize UpperBandMatrix
+void UpperBandMatrix::resize(int n, int lb, int ub)
+{
+   REPORT
+   if (lb != 0)
+   {
+      Tracer tr("UpperBandMatrix::resize");
+      Throw(ProgramException("UpperBandMatrix with non-zero lower band" ));
+   }
+   BandMatrix::resize(n, lb, ub);
+}
+
+/// \brief resize LowerBandMatrix
+void LowerBandMatrix::resize(int n, int lb, int ub)
+{
+   REPORT
+   if (ub != 0)
+   {
+      Tracer tr("LowerBandMatrix::resize");
+      Throw(ProgramException("LowerBandMatrix with non-zero upper band" ));
+   }
+   BandMatrix::resize(n, lb, ub);
+}
+
+/// \brief resize BandMatrix
+void BandMatrix::resize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("BandMatrix::resize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   MatrixBandWidth mbw = A.bandwidth();
+   resize(n, mbw.Lower(), mbw.Upper());
+}
+
+/*
+bool BandMatrix::SameStorageType(const GeneralMatrix& A) const
+{
+   if (type() != A.type()) { REPORT return false; }
+   REPORT
+   return bandwidth() == A.bandwidth();
+}
+
+void BandMatrix::resizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B)
+{
+   REPORT
+   Tracer tr("BandMatrix::resizeForAdd");
+   MatrixBandWidth A_BW = A.bandwidth(); MatrixBandWidth B_BW = B.bandwidth();
+   if ((A_BW.Lower() < 0) | (A_BW.Upper() < 0) | (B_BW.Lower() < 0)
+      | (A_BW.Upper() < 0))
+         Throw(ProgramException("Can't resize to BandMatrix" ));
+   // already know A and B are square
+   resize(A.Nrows(), my_max(A_BW.Lower(), B_BW.Lower()),
+      my_max(A_BW.Upper(), B_BW.Upper()));
+}
+
+void BandMatrix::resizeForSP(const GeneralMatrix& A, const GeneralMatrix& B)
+{
+   REPORT
+   Tracer tr("BandMatrix::resizeForSP");
+   MatrixBandWidth A_BW = A.bandwidth(); MatrixBandWidth B_BW = B.bandwidth();
+   if ((A_BW.Lower() < 0) | (A_BW.Upper() < 0) | (B_BW.Lower() < 0)
+      | (A_BW.Upper() < 0))
+         Throw(ProgramException("Can't resize to BandMatrix" ));
+   // already know A and B are square
+   resize(A.Nrows(), my_min(A_BW.Lower(), B_BW.Lower()),
+      my_min(A_BW.Upper(), B_BW.Upper()));
+}
+*/
+
+/// \brief assignment operator for BandMatrix
+void BandMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::BM); CornerClear();
+}
+
+/// \brief set unused parts of BandMatrix to zero
+void BandMatrix::CornerClear() const
+{
+   REPORT
+   int i = lower_val; Real* s = store; int bw = lower_val + 1 + upper_val;
+   while (i)
+      { int j = i--; Real* sj = s; s += bw; while (j--) *sj++ = 0.0; }
+   i = upper_val; s = store + storage;
+   while (i)
+      { int j = i--; Real* sj = s; s -= bw; while (j--) *(--sj) = 0.0; }
+}
+
+MatrixBandWidth MatrixBandWidth::operator+(const MatrixBandWidth& bw) const
+{
+   REPORT
+   int l = bw.lower_val; int u = bw.upper_val;
+   l = (lower_val < 0 || l < 0) ? -1 : (lower_val > l) ? lower_val : l;
+   u = (upper_val < 0 || u < 0) ? -1 : (upper_val > u) ? upper_val : u;
+   return MatrixBandWidth(l,u);
+}
+
+MatrixBandWidth MatrixBandWidth::operator*(const MatrixBandWidth& bw) const
+{
+   REPORT
+   int l = bw.lower_val; int u = bw.upper_val;
+   l = (lower_val < 0 || l < 0) ? -1 : lower_val+l;
+   u = (upper_val < 0 || u < 0) ? -1 : upper_val+u;
+   return MatrixBandWidth(l,u);
+}
+
+MatrixBandWidth MatrixBandWidth::minimum(const MatrixBandWidth& bw) const
+{
+   REPORT
+   int l = bw.lower_val; int u = bw.upper_val;
+   if ((lower_val >= 0) && ( (l < 0) || (l > lower_val) )) l = lower_val;
+   if ((upper_val >= 0) && ( (u < 0) || (u > upper_val) )) u = upper_val;
+   return MatrixBandWidth(l,u);
+}
+
+UpperBandMatrix::UpperBandMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::UB);
+   GetMatrix(gmx); CornerClear();
+}
+
+void UpperBandMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::UB); CornerClear();
+}
+
+LowerBandMatrix::LowerBandMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::LB);
+   GetMatrix(gmx); CornerClear();
+}
+
+void LowerBandMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::LB); CornerClear();
+}
+
+BandLUMatrix::BandLUMatrix(const BaseMatrix& m)
+{
+   REPORT
+   Tracer tr("BandLUMatrix");
+   storage2 = 0; store2 = 0; indx = 0; // in event of exception during build
+   GeneralMatrix* gm = ((BaseMatrix&)m).Evaluate();
+   if (gm->nrows() != gm->ncols())
+      { gm->tDelete(); Throw(NotSquareException(*this)); }
+   if (gm->type() == MatrixType::BC)
+      { REPORT  ((BandLUMatrix*)gm)->get_aux(*this); GetMatrix(gm); }
+   else
+   {
+      REPORT
+      BandMatrix* gm1 = (BandMatrix*)(gm->Evaluate(MatrixType::BM));
+      m1 = gm1->lower_val; m2 = gm1->upper_val;
+      GetMatrix(gm1);
+      d = true; sing = false;
+      indx = new int [nrows_val]; MatrixErrorNoSpace(indx);
+      MONITOR_INT_NEW("Index (BndLUMat)",nrows_val,indx)
+      storage2 = nrows_val * m1;
+      store2 = new Real [storage2]; MatrixErrorNoSpace(store2);
+      MONITOR_REAL_NEW("Make (BandLUMat)",storage2,store2)
+      ludcmp();
+   }
+}
+
+GeneralMatrix* BandLUMatrix::Evaluate(MatrixType mt)
+{
+   if (Compare(this->Type(),mt)) { REPORT return this; }
+   REPORT
+   Tracer et("BandLUMatrix::Evaluate");
+   bool dummy = true;
+   if (dummy) Throw(ProgramException("Illegal use of BandLUMatrix", *this));
+   return this;
+}
+
+// could we use SetParameters instead of this
+void BandLUMatrix::get_aux(BandLUMatrix& X)
+{
+   X.d = d; X.sing = sing; X.storage2 = storage2; X.m1 = m1; X.m2 = m2;   
+   if (tag_val == 0 || tag_val == 1) // reuse the array 
+   {
+      REPORT
+      X.indx = indx; indx = 0;
+      X.store2 = store2; store2 = 0;
+      d = true; sing = true; storage2 = 0; m1 = 0; m2 = 0;
+      return;
+   }
+   else if (nrows_val == 0)
+   {
+      REPORT
+      indx = 0; store2 = 0; storage2 = 0;
+      d = true; sing = true; m1 = m2 = 0;
+      return;
+   }
+   else                              // copy the array
+   {
+      REPORT
+      Tracer tr("BandLUMatrix::get_aux");
+      int *ix = new int [nrows_val]; MatrixErrorNoSpace(ix);
+      MONITOR_INT_NEW("Index (BLUM::get_aux)", nrows_val, ix)
+      int n = nrows_val; int* i = ix; int* j = indx;
+      while(n--) *i++ = *j++;
+      X.indx = ix;
+      Real *rx = new Real [storage2]; MatrixErrorNoSpace(indx);
+      MONITOR_REAL_NEW("Index (BLUM::get_aux)", storage2, rx)
+      newmat_block_copy(storage2, store2, rx);
+      X.store2 = rx;
+   }
+}
+
+BandLUMatrix::BandLUMatrix(const BandLUMatrix& gm) : GeneralMatrix()
+{
+   REPORT
+   Tracer tr("BandLUMatrix(const BandLUMatrix&)");
+   ((BandLUMatrix&)gm).get_aux(*this);
+   GetMatrix(&gm);
+}
+
+void BandLUMatrix::operator=(const BandLUMatrix& gm)
+{
+   if (&gm == this) { REPORT tag_val = -1; return; }
+   REPORT
+   delete [] indx; indx = 0;
+   delete [] store2; store2 = 0; storage2 = 0;
+   ((BandLUMatrix&)gm).get_aux(*this);
+   Eq(gm);
+}
+   
+
+
+
+
+
+
+
+BandLUMatrix::~BandLUMatrix()
+{
+   REPORT
+   MONITOR_INT_DELETE("Index (BndLUMat)",nrows_val,indx)
+   MONITOR_REAL_DELETE("Delete (BndLUMt)",storage2,store2)
+   delete [] indx; delete [] store2;
+}
+
+MatrixType BandLUMatrix::type() const { REPORT return MatrixType::BC; }
+
+
+LogAndSign BandLUMatrix::log_determinant() const
+{
+   REPORT
+   if (sing) return 0.0;
+   Real* a = store; int w = m1+1+m2; LogAndSign sum; int i = nrows_val;
+   // while (i--) { sum *= *a; a += w; }
+   if (i) for (;;) { sum *= *a; if (!(--i)) break; a += w; }
+   if (!d) sum.ChangeSign(); return sum;
+}
+
+GeneralMatrix* BandMatrix::MakeSolver()
+{
+   REPORT
+   GeneralMatrix* gm = new BandLUMatrix(*this);
+   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
+}
+
+
+void BandLUMatrix::ludcmp()
+{
+   REPORT
+   Real* a = store2; int i = storage2;
+   // clear store2 - so unused locations are always zero -
+   // required by operator==
+   while (i--) *a++ = 0.0;
+   a = store;
+   i = m1; int j = m2; int k; int n = nrows_val; int w = m1 + 1 + m2;
+   while (i)
+   {
+      Real* ai = a + i;
+      k = ++j; while (k--) *a++ = *ai++;
+      k = i--; while (k--) *a++ = 0.0;
+   }
+
+   a = store; int l = m1;
+   for (k=0; k<n; k++)
+   {
+      Real x = *a; i = k; Real* aj = a;
+      if (l < n) l++;
+      for (j=k+1; j<l; j++)
+         { aj += w; if (fabs(x) < fabs(*aj)) { x = *aj; i = j; } }
+      indx[k] = i;
+      if (x==0) { sing = true; return; }
+      if (i!=k)
+      {
+         d = !d; Real* ak = a; Real* ai = store + i * w; j = w;
+         while (j--) { x = *ak; *ak++ = *ai; *ai++ = x; }
+      }
+      aj = a + w; Real* m = store2 + m1 * k;
+      for (j=k+1; j<l; j++)
+      {
+         *m++ = x = *aj / *a; i = w; Real* ak = a;
+         while (--i) { Real* aj1 = aj++; *aj1 = *aj - x * *(++ak); }
+         *aj++ = 0.0;
+      }
+      a += w;
+   }
+}
+
+void BandLUMatrix::lubksb(Real* B, int mini)
+{
+   REPORT
+   Tracer tr("BandLUMatrix::lubksb");
+   if (sing) Throw(SingularException(*this));
+   int n = nrows_val; int l = m1; int w = m1 + 1 + m2;
+
+   for (int k=0; k<n; k++)
+   {
+      int i = indx[k];
+      if (i!=k) { Real x=B[k]; B[k]=B[i]; B[i]=x; }
+      if (l<n) l++;
+      Real* m = store2 + k*m1; Real* b = B+k; Real* bi = b;
+      for (i=k+1; i<l; i++)  *(++bi) -= *m++ * *b;
+   }
+
+   l = -m1;
+   for (int i = n-1; i>=mini; i--)
+   {
+      Real* b = B + i; Real* bk = b; Real x = *bk;
+      Real* a = store + w*i; Real y = *a;
+      int k = l+m1; while (k--) x -=  *(++a) * *(++bk);
+      *b = x / y;
+      if (l < m2) l++;
+   }
+}
+
+void BandLUMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip; Real* el = mcin.data-i; Real* el1=el;
+   while (i--) *el++ = 0.0;
+   el += mcin.storage; i = nrows_val - mcin.skip - mcin.storage;
+   while (i--) *el++ = 0.0;
+   lubksb(el1, mcout.skip);
+}
+
+// Do we need check for entirely zero output?
+
+
+void UpperBandMatrix::Solver(MatrixColX& mcout,
+   const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
+   while (i-- > 0) *elx++ = 0.0;
+   int nr = mcin.skip+mcin.storage;
+   elx = mcin.data+mcin.storage; Real* el = elx;
+   int j = mcout.skip+mcout.storage-nr; i = nr-mcout.skip;
+   while (j-- > 0) *elx++ = 0.0;
+
+   Real* Ael = store + (upper_val+1)*(i-1)+1; j = 0;
+   if (i > 0) for(;;)
+   {
+      elx = el; Real sum = 0.0; int jx = j;
+      while (jx--) sum += *(--Ael) * *(--elx);
+      elx--; *elx = (*elx - sum) / *(--Ael);
+      if (--i <= 0) break;
+      if (j<upper_val) Ael -= upper_val - (++j); else el--;
+   }
+}
+
+void LowerBandMatrix::Solver(MatrixColX& mcout,
+   const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
+   while (i-- > 0) *elx++ = 0.0;
+   int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage;
+   int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc;
+   while (j-- > 0) *elx++ = 0.0;
+
+   Real* el = mcin.data;
+   Real* Ael = store + (lower_val+1)*nc + lower_val;
+   j = 0;
+   if (i > 0) for(;;)
+   {
+      elx = el; Real sum = 0.0; int jx = j;
+      while (jx--) sum += *Ael++ * *elx++;
+      *elx = (*elx - sum) / *Ael++;
+      if (--i <= 0) break;
+      if (j<lower_val) Ael += lower_val - (++j); else el++;
+   }
+}
+
+
+LogAndSign BandMatrix::log_determinant() const
+{
+   REPORT
+   BandLUMatrix C(*this); return C.log_determinant();
+}
+
+LogAndSign LowerBandMatrix::log_determinant() const
+{
+   REPORT
+   int i = nrows_val; LogAndSign sum;
+   Real* s = store + lower_val; int j = lower_val + 1;
+//   while (i--) { sum *= *s; s += j; }
+   if (i) for (;;) { sum *= *s; if (!(--i)) break; s += j; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign UpperBandMatrix::log_determinant() const
+{
+   REPORT
+   int i = nrows_val; LogAndSign sum; Real* s = store; int j = upper_val + 1;
+//   while (i--) { sum *= *s; s += j; }
+   if (i) for (;;) { sum *= *s; if (!(--i)) break; s += j; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+GeneralMatrix* SymmetricBandMatrix::MakeSolver()
+{
+   REPORT
+   GeneralMatrix* gm = new BandLUMatrix(*this);
+   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
+}
+
+SymmetricBandMatrix::SymmetricBandMatrix(const BaseMatrix& M)
+{
+   REPORT  // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::SB);
+   GetMatrix(gmx);
+}
+
+GeneralMatrix* SymmetricBandMatrix::Transpose(TransposedMatrix*, MatrixType mt)
+{ REPORT  return Evaluate(mt); }
+
+LogAndSign SymmetricBandMatrix::log_determinant() const
+{
+   REPORT
+   BandLUMatrix C(*this); return C.log_determinant();
+}
+
+void SymmetricBandMatrix::SetParameters(const GeneralMatrix* gmx)
+{ REPORT lower_val = gmx->bandwidth().lower_val; }
+
+void SymmetricBandMatrix::resize(int n, int lb)
+{
+   REPORT
+   Tracer tr("SymmetricBandMatrix::resize");
+   if (lb<0) Throw(ProgramException("Undefined bandwidth"));
+   lower_val = (lb<=n) ? lb : n-1;
+   GeneralMatrix::resize(n,n,n*(lower_val+1));
+}
+
+void SymmetricBandMatrix::resize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("SymmetricBandMatrix::resize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   MatrixBandWidth mbw = A.bandwidth(); int b = mbw.Lower();
+   if (b != mbw.Upper())
+   {
+      Tracer tr("SymmetricBandMatrix::resize(GM)");
+      Throw(ProgramException("Upper and lower band-widths not equal"));
+   }
+   resize(n, b);
+}
+/*
+bool SymmetricBandMatrix::SameStorageType(const GeneralMatrix& A) const
+{
+   if (type() != A.type()) { REPORT return false; }
+   REPORT
+   return bandwidth() == A.bandwidth();
+}
+
+void SymmetricBandMatrix::resizeForAdd(const GeneralMatrix& A,
+   const GeneralMatrix& B)
+{
+   REPORT
+   Tracer tr("SymmetricBandMatrix::resizeForAdd");
+   MatrixBandWidth A_BW = A.bandwidth(); MatrixBandWidth B_BW = B.bandwidth();
+   if ((A_BW.Lower() < 0) | (B_BW.Lower() < 0))
+         Throw(ProgramException("Can't resize to SymmetricBandMatrix" ));
+   // already know A and B are square
+   resize(A.Nrows(), my_max(A_BW.Lower(), B_BW.Lower()));
+}
+
+void SymmetricBandMatrix::resizeForSP(const GeneralMatrix& A,
+   const GeneralMatrix& B)
+{
+   REPORT
+   Tracer tr("SymmetricBandMatrix::resizeForSP");
+   MatrixBandWidth A_BW = A.bandwidth(); MatrixBandWidth B_BW = B.bandwidth();
+   if ((A_BW.Lower() < 0) | (B_BW.Lower() < 0))
+         Throw(ProgramException("Can't resize to SymmetricBandMatrix" ));
+   // already know A and B are square
+   resize(A.Nrows(), my_min(A_BW.Lower(), B_BW.Lower()));
+}
+*/
+
+void SymmetricBandMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::SB);
+}
+
+void SymmetricBandMatrix::CornerClear() const
+{
+   // set unused parts of BandMatrix to zero
+   REPORT
+   int i = lower_val; Real* s = store; int bw = lower_val + 1;
+   if (i) for(;;)
+   {
+      int j = i;
+      Real* sj = s;
+      while (j--) *sj++ = 0.0;
+      if (!(--i)) break;
+      s += bw;
+   }
+}
+
+MatrixBandWidth SymmetricBandMatrix::bandwidth() const
+   { REPORT return MatrixBandWidth(lower_val,lower_val); }
+
+GeneralMatrix* BandMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new BandMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* UpperBandMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new UpperBandMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* LowerBandMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new LowerBandMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* SymmetricBandMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new SymmetricBandMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* BandLUMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new BandLUMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+
+inline Real square(Real x) { return x*x; }
+
+Real SymmetricBandMatrix::sum_square() const
+{
+   REPORT
+   CornerClear();
+   Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows_val;
+   int l=lower_val;
+   while (i--)
+      { int j = l; while (j--) sum2 += square(*s++); sum1 += square(*s++); }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real SymmetricBandMatrix::sum_absolute_value() const
+{
+   REPORT
+   CornerClear();
+   Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows_val;
+   int l=lower_val;
+   while (i--)
+      { int j = l; while (j--) sum2 += fabs(*s++); sum1 += fabs(*s++); }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real SymmetricBandMatrix::sum() const
+{
+   REPORT
+   CornerClear();
+   Real sum1=0.0; Real sum2=0.0; Real* s=store; int i=nrows_val;
+   int l=lower_val;
+   while (i--)
+      { int j = l; while (j--) sum2 += *s++; sum1 += *s++; }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
+
+
Index: trunk/BNC/newmat/cholesky.cpp
===================================================================
--- trunk/BNC/newmat/cholesky.cpp	(revision 2013)
+++ trunk/BNC/newmat/cholesky.cpp	(revision 2013)
@@ -0,0 +1,289 @@
+/// \ingroup newmat
+///@{
+
+/// \file cholesky.cpp
+/// Cholesky decomposition.
+/// Cholesky decomposition of symmetric and band symmetric matrices,
+/// update, downdate, manipulate a Cholesky decomposition
+
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrm.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,14); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+/********* Cholesky decomposition of a positive definite matrix *************/
+
+// Suppose S is symmetrix and positive definite. Then there exists a unique
+// lower triangular matrix L such that L L.t() = S;
+
+
+ReturnMatrix Cholesky(const SymmetricMatrix& S)
+{
+   REPORT
+   Tracer trace("Cholesky");
+   int nr = S.Nrows();
+   LowerTriangularMatrix T(nr);
+   Real* s = S.Store(); Real* t = T.Store(); Real* ti = t;
+   for (int i=0; i<nr; i++)
+   {
+      Real* tj = t; Real sum; int k;
+      for (int j=0; j<i; j++)
+      {
+         Real* tk = ti; sum = 0.0; k = j;
+         while (k--) { sum += *tj++ * *tk++; }
+         *tk = (*s++ - sum) / *tj++;
+      }
+      sum = 0.0; k = i;
+      while (k--) { sum += square(*ti++); }
+      Real d = *s++ - sum;
+      if (d<=0.0)  Throw(NPDException(S));
+      *ti++ = sqrt(d);
+   }
+   T.release(); return T.for_return();
+}
+
+ReturnMatrix Cholesky(const SymmetricBandMatrix& S)
+{
+   REPORT
+   Tracer trace("Band-Cholesky");
+   int nr = S.Nrows(); int m = S.lower_val;
+   LowerBandMatrix T(nr,m);
+   Real* s = S.Store(); Real* t = T.Store(); Real* ti = t;
+
+   for (int i=0; i<nr; i++)
+   {
+      Real* tj = t; Real sum; int l;
+      if (i<m) { REPORT l = m-i; s += l; ti += l; l = i; }
+      else { REPORT t += (m+1); l = m; }
+
+      for (int j=0; j<l; j++)
+      {
+         Real* tk = ti; sum = 0.0; int k = j; tj += (m-j);
+         while (k--) { sum += *tj++ * *tk++; }
+         *tk = (*s++ - sum) / *tj++;
+      }
+      sum = 0.0;
+      while (l--) { sum += square(*ti++); }
+      Real d = *s++ - sum;
+      if (d<=0.0)  Throw(NPDException(S));
+      *ti++ = sqrt(d);
+   }
+
+   T.release(); return T.for_return();
+}
+
+
+
+
+// Contributed by Nick Bennett of Schlumberger-Doll Research; modified by RBD
+
+// The enclosed routines can be used to update the Cholesky decomposition of
+// a positive definite symmetric matrix.  A good reference for this routines
+// can be found in
+// LINPACK User's Guide, Chapter 10, Dongarra et. al., SIAM, Philadelphia, 1979
+
+// produces the Cholesky decomposition of A + x.t() * x where A = chol.t() * chol
+void update_Cholesky(UpperTriangularMatrix &chol, RowVector x)
+{
+   int nc = chol.Nrows();
+   ColumnVector cGivens(nc); cGivens = 0.0;
+   ColumnVector sGivens(nc); sGivens = 0.0;
+	
+   for(int j = 1; j <= nc; ++j) // process the jth column of chol
+   {
+      // apply the previous Givens rotations k = 1,...,j-1 to column j
+      for(int k = 1; k < j; ++k)
+         GivensRotation(cGivens(k), sGivens(k), chol(k,j), x(j));
+
+      // determine the jth Given's rotation
+      pythag(chol(j,j), x(j), cGivens(j), sGivens(j));
+
+      // apply the jth Given's rotation
+      {
+         Real tmp0 = cGivens(j) * chol(j,j) + sGivens(j) * x(j);
+         chol(j,j) = tmp0; x(j) = 0.0;
+      }
+
+   }
+
+}
+
+
+// produces the Cholesky decomposition of A - x.t() * x where A = chol.t() * chol
+void downdate_Cholesky(UpperTriangularMatrix &chol, RowVector x)
+{
+   int nRC = chol.Nrows();
+	
+   // solve R^T a = x
+   LowerTriangularMatrix L = chol.t();
+   ColumnVector a(nRC); a = 0.0;
+   int i, j;
+	
+   for (i = 1; i <= nRC; ++i)
+   {
+      // accumulate subtr sum
+      Real subtrsum = 0.0;
+      for(int k = 1; k < i; ++k) subtrsum += a(k) * L(i,k);
+
+      a(i) = (x(i) - subtrsum) / L(i,i);
+   }
+
+   // test that l2 norm of a is < 1
+   Real squareNormA = a.SumSquare();
+   if (squareNormA >= 1.0)
+      Throw(ProgramException("downdate_Cholesky() fails", chol));
+
+   Real alpha = sqrt(1.0 - squareNormA);
+
+   // compute and apply Givens rotations to the vector a
+   ColumnVector cGivens(nRC);  cGivens = 0.0;
+   ColumnVector sGivens(nRC);  sGivens = 0.0;
+   for(i = nRC; i >= 1; i--)
+      alpha = pythag(alpha, a(i), cGivens(i), sGivens(i));
+
+   // apply Givens rotations to the jth column of chol
+   ColumnVector xtilde(nRC); xtilde = 0.0;
+   for(j = nRC; j >= 1; j--)
+   {
+      // only the first j rotations have an affect on chol,0
+      for(int k = j; k >= 1; k--)
+         GivensRotation(cGivens(k), -sGivens(k), chol(k,j), xtilde(j));
+   }
+}
+
+
+
+// produces the Cholesky decomposition of EAE where A = chol.t() * chol
+// and E produces a RIGHT circular shift of the rows and columns from
+// 1,...,k-1,k,k+1,...l,l+1,...,p to
+// 1,...,k-1,l,k,k+1,...l-1,l+1,...p
+void right_circular_update_Cholesky(UpperTriangularMatrix &chol, int k, int l)
+{
+   int nRC = chol.Nrows();
+   int i, j;
+	
+   // I. compute shift of column l to the kth position
+   Matrix cholCopy = chol;
+   // a. grab column l
+   ColumnVector columnL = cholCopy.Column(l);
+   // b. shift columns k,...l-1 to the RIGHT
+   for(j = l-1; j >= k; --j)
+      cholCopy.Column(j+1) = cholCopy.Column(j);
+   // c. copy the top k-1 elements of columnL into the kth column of cholCopy
+   cholCopy.Column(k) = 0.0;
+   for(i = 1; i < k; ++i) cholCopy(i,k) = columnL(i);
+
+    // II. determine the l-k Given's rotations
+   int nGivens = l-k;
+   ColumnVector cGivens(nGivens); cGivens = 0.0;
+   ColumnVector sGivens(nGivens); sGivens = 0.0;
+   for(i = l; i > k; i--)
+   {
+      int givensIndex = l-i+1;
+      columnL(i-1) = pythag(columnL(i-1), columnL(i),
+         cGivens(givensIndex), sGivens(givensIndex));
+      columnL(i) = 0.0;
+   }
+   // the kth entry of columnL is the new diagonal element in column k of cholCopy
+   cholCopy(k,k) = columnL(k);
+	
+   // III. apply these Given's rotations to subsequent columns
+   // for columns k+1,...,l-1 we only need to apply the last nGivens-(j-k) rotations
+   for(j = k+1; j <= nRC; ++j)
+   {
+      ColumnVector columnJ = cholCopy.Column(j);
+      int imin = nGivens - (j-k) + 1; if (imin < 1) imin = 1;
+      for(int gIndex = imin; gIndex <= nGivens; ++gIndex)
+      {
+         // apply gIndex Given's rotation
+         int topRowIndex = k + nGivens - gIndex;
+         GivensRotationR(cGivens(gIndex), sGivens(gIndex),
+            columnJ(topRowIndex), columnJ(topRowIndex+1));
+      }
+      cholCopy.Column(j) = columnJ;
+   }
+
+   chol << cholCopy;
+}
+
+
+
+// produces the Cholesky decomposition of EAE where A = chol.t() * chol
+// and E produces a LEFT circular shift of the rows and columns from
+// 1,...,k-1,k,k+1,...l,l+1,...,p to
+// 1,...,k-1,k+1,...l,k,l+1,...,p to
+void left_circular_update_Cholesky(UpperTriangularMatrix &chol, int k, int l)
+{
+   int nRC = chol.Nrows();
+   int i, j;
+
+   // I. compute shift of column k to the lth position
+   Matrix cholCopy = chol;
+   // a. grab column k
+   ColumnVector columnK = cholCopy.Column(k);
+   // b. shift columns k+1,...l to the LEFT
+   for(j = k+1; j <= l; ++j)
+      cholCopy.Column(j-1) = cholCopy.Column(j);
+   // c. copy the elements of columnK into the lth column of cholCopy
+   cholCopy.Column(l) = 0.0;
+   for(i = 1; i <= k; ++i)
+      cholCopy(i,l) = columnK(i);
+
+   // II. apply and compute Given's rotations
+   int nGivens = l-k;
+   ColumnVector cGivens(nGivens); cGivens = 0.0;
+   ColumnVector sGivens(nGivens); sGivens = 0.0;
+   for(j = k; j <= nRC; ++j)
+   {
+      ColumnVector columnJ = cholCopy.Column(j);
+
+      // apply the previous Givens rotations to columnJ
+      int imax = j - k; if (imax > nGivens) imax = nGivens;
+      for(int i = 1; i <= imax; ++i)
+      {
+         int gIndex = i;
+         int topRowIndex = k + i - 1;
+         GivensRotationR(cGivens(gIndex), sGivens(gIndex),
+            columnJ(topRowIndex), columnJ(topRowIndex+1));
+      }
+
+      // compute a new Given's rotation when j < l
+      if(j < l)
+      {
+         int gIndex = j-k+1;
+         columnJ(j) = pythag(columnJ(j), columnJ(j+1), cGivens(gIndex),
+            sGivens(gIndex));
+         columnJ(j+1) = 0.0;
+      }
+
+      cholCopy.Column(j) = columnJ;
+   }
+
+   chol << cholCopy;
+	
+}
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
Index: trunk/BNC/newmat/controlw.h
===================================================================
--- trunk/BNC/newmat/controlw.h	(revision 2013)
+++ trunk/BNC/newmat/controlw.h	(revision 2013)
@@ -0,0 +1,56 @@
+/// \ingroup newmat
+///@{
+
+/// \file controlw.h
+/// Control word class.
+/// Manipulate bits used for setting options.
+
+
+#ifndef CONTROL_WORD_LIB
+#define CONTROL_WORD_LIB 0
+
+/// Organise an int as a series of bits to set options.
+/// \internal
+class ControlWord
+{
+protected:
+   int cw;                                      // the control word
+public:
+   ControlWord() : cw(0) {}                     // do nothing
+   ControlWord(int i) : cw(i) {}                // load an integer
+
+      // select specific bits (for testing at least one set)
+   ControlWord operator*(ControlWord i) const
+      { return ControlWord(cw & i.cw); }
+   void operator*=(ControlWord i)  { cw &= i.cw; }
+
+      // set bits
+   ControlWord operator+(ControlWord i) const
+      { return ControlWord(cw | i.cw); }
+   void operator+=(ControlWord i)  { cw |= i.cw; }
+
+      // reset bits
+   ControlWord operator-(ControlWord i) const
+      { return ControlWord(cw - (cw & i.cw)); }
+   void operator-=(ControlWord i) { cw -= (cw & i.cw); }
+
+      // check if all of selected bits set or reset
+   bool operator>=(ControlWord i) const { return (cw & i.cw) == i.cw; }
+   bool operator<=(ControlWord i) const { return (cw & i.cw) == cw; }
+
+      // flip selected bits
+   ControlWord operator^(ControlWord i) const
+      { return ControlWord(cw ^ i.cw); }
+   ControlWord operator~() const { return ControlWord(~cw); }
+
+      // convert to integer
+   int operator+() const { return cw; }
+   int operator!() const { return cw==0; }
+   FREE_CHECK(ControlWord)
+};
+
+
+#endif
+
+///@}
+
Index: trunk/BNC/newmat/evalue.cpp
===================================================================
--- trunk/BNC/newmat/evalue.cpp	(revision 2013)
+++ trunk/BNC/newmat/evalue.cpp	(revision 2013)
@@ -0,0 +1,303 @@
+/// \ingroup newmat
+///@{
+
+/// \file evalue.cpp
+/// Eigen-value decomposition (Householder method).
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+
+#include "include.h"
+#include "newmatap.h"
+#include "newmatrm.h"
+#include "precisio.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,17); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+
+static void tred2(const SymmetricMatrix& A, DiagonalMatrix& D,
+   DiagonalMatrix& E, Matrix& Z)
+{
+   Tracer et("Evalue(tred2)");
+   REPORT
+   Real tol =
+      FloatingPointPrecision::Minimum()/FloatingPointPrecision::Epsilon();
+   int n = A.Nrows(); Z.resize(n,n); Z.Inject(A);
+   D.resize(n); E.resize(n);
+   Real* z = Z.Store(); int i;
+
+   for (i=n-1; i > 0; i--)                   // i=0 is excluded
+   {
+      Real f = Z.element(i,i-1); Real g = 0.0;
+      int k = i-1; Real* zik = z + i*n;
+      while (k--) g += square(*zik++);
+      Real h = g + square(f);
+      if (g <= tol) { REPORT E.element(i) = f; h = 0.0; }
+      else
+      {
+         REPORT
+         g = sign(-sqrt(h), f); E.element(i) = g; h -= f*g;
+         Z.element(i,i-1) = f-g; f = 0.0;
+         Real* zji = z + i; Real* zij = z + i*n; Real* ej = E.Store();
+         int j;
+         for (j=0; j<i; j++)
+         {
+            *zji = (*zij++)/h; g = 0.0;
+            Real* zjk = z + j*n; zik = z + i*n;
+            k = j; while (k--) g += *zjk++ * (*zik++);
+            k = i-j;
+            if (k) for(;;)
+               { g += *zjk * (*zik++); if (!(--k)) break; zjk += n; }
+            *ej++ = g/h; f += g * (*zji); zji += n;
+         }
+         Real hh = f / (h + h); zij = z + i*n; ej = E.Store();
+         for (j=0; j<i; j++)
+         {
+            f = *zij++; g = *ej - hh * f; *ej++ = g;
+            Real* zjk = z + j*n; Real* zik = z + i*n;
+            Real* ek = E.Store(); k = j+1;
+            while (k--)  *zjk++ -= ( f*(*ek++) + g*(*zik++) ); 
+         }
+      }
+      D.element(i) = h;
+   }
+
+   D.element(0) = 0.0; E.element(0) = 0.0;
+   for (i=0; i<n; i++)
+   {
+      if (D.element(i) != 0.0)
+      {
+         REPORT
+         for (int j=0; j<i; j++)
+         {
+            Real g = 0.0;
+            Real* zik = z + i*n; Real* zkj = z + j;
+            int k = i;
+            if (k) for (;;)
+               { g += *zik++ * (*zkj); if (!(--k)) break; zkj += n; }
+            Real* zki = z + i; zkj = z + j;
+            k = i;
+            if (k) for (;;)
+               { *zkj -= g * (*zki); if (!(--k)) break; zkj += n; zki += n; }
+         }
+      }
+      Real* zij = z + i*n; Real* zji = z + i;
+      int j = i;
+      if (j) for (;;)
+         { *zij++ = 0.0; *zji = 0.0; if (!(--j)) break; zji += n; }
+      D.element(i) = *zij; *zij = 1.0;
+   }
+}
+
+static void tql2(DiagonalMatrix& D, DiagonalMatrix& E, Matrix& Z)
+{
+   Tracer et("Evalue(tql2)");
+   REPORT
+   Real eps = FloatingPointPrecision::Epsilon();
+   int n = D.Nrows(); Real* z = Z.Store(); int l;
+   for (l=1; l<n; l++) E.element(l-1) = E.element(l);
+   Real b = 0.0; Real f = 0.0; E.element(n-1) = 0.0;
+   for (l=0; l<n; l++)
+   {
+      int i,j;
+      Real& dl = D.element(l); Real& el = E.element(l);
+      Real h = eps * ( fabs(dl) + fabs(el) );
+      if (b < h) { REPORT b = h; }
+      int m;
+      for (m=l; m<n; m++) if (fabs(E.element(m)) <= b) break;
+      bool test = false;
+      for (j=0; j<30; j++)
+      {
+         if (m==l) { REPORT test = true; break; }
+         Real& dl1 = D.element(l+1);
+         Real g = dl; Real p = (dl1-g) / (2.0*el); Real r = sqrt(p*p + 1.0);
+         dl = el / (p < 0.0 ? p-r : p+r); Real h = g - dl; f += h;
+         Real* dlx = &dl1; i = n-l-1; while (i--) *dlx++ -= h;
+
+         p = D.element(m); Real c = 1.0; Real s = 0.0;
+         for (i=m-1; i>=l; i--)
+         {
+            Real ei = E.element(i); Real di = D.element(i);
+            Real& ei1 = E.element(i+1);
+            g = c * ei; h = c * p;
+            if ( fabs(p) >= fabs(ei))
+            {
+               REPORT
+               c = ei / p; r = sqrt(c*c + 1.0);
+               ei1 = s*p*r; s = c/r; c = 1.0/r;
+            }
+            else
+            {
+               REPORT
+               c = p / ei; r = sqrt(c*c + 1.0);
+               ei1 = s * ei * r; s = 1.0/r; c /= r;
+            }
+            p = c * di - s*g; D.element(i+1) = h + s * (c*g + s*di);
+
+            Real* zki = z + i; Real* zki1 = zki + 1; int k = n;
+            if (k) for (;;)
+            {
+               REPORT
+               h = *zki1; *zki1 = s*(*zki) + c*h; *zki = c*(*zki) - s*h;
+               if (!(--k)) break;
+               zki += n; zki1 += n;
+            }
+         }
+         el = s*p; dl = c*p;
+         if (fabs(el) <= b) { REPORT; test = true; break; }
+      }
+      if (!test) Throw ( ConvergenceException(D) );
+      dl += f;
+   }
+/*
+   for (int i=0; i<n; i++)
+   {
+      int k = i; Real p = D.element(i);
+      for (int j=i+1; j<n; j++)
+         { if (D.element(j) < p) { k = j; p = D.element(j); } }
+      if (k != i)
+      {
+         D.element(k) = D.element(i); D.element(i) = p; int j = n;
+         Real* zji = z + i; Real* zjk = z + k;
+         if (j) for(;;)
+         {
+            p = *zji; *zji = *zjk; *zjk = p;
+            if (!(--j)) break;
+            zji += n; zjk += n;
+         }
+      }
+   }
+*/
+}
+
+static void tred3(const SymmetricMatrix& X, DiagonalMatrix& D,
+   DiagonalMatrix& E, SymmetricMatrix& A)
+{
+   Tracer et("Evalue(tred3)");
+   REPORT
+   Real tol =
+      FloatingPointPrecision::Minimum()/FloatingPointPrecision::Epsilon();
+   int n = X.Nrows(); A = X; D.resize(n); E.resize(n);
+   Real* ei = E.Store() + n;
+   for (int i = n-1; i >= 0; i--)
+   {
+      Real h = 0.0; Real f = - FloatingPointPrecision::Maximum();
+      Real* d = D.Store(); Real* a = A.Store() + (i*(i+1))/2; int k = i;
+      while (k--) { f = *a++; *d++ = f; h += square(f); }
+      if (h <= tol) { REPORT *(--ei) = 0.0; h = 0.0; }
+      else
+      {
+         REPORT
+         Real g = sign(-sqrt(h), f); *(--ei) = g; h -= f*g;
+         f -= g; *(d-1) = f; *(a-1) = f; f = 0.0;
+         Real* dj = D.Store(); Real* ej = E.Store(); int j;
+         for (j = 0; j < i; j++)
+         {
+            Real* dk = D.Store(); Real* ak = A.Store()+(j*(j+1))/2;
+            Real g = 0.0; k = j;
+            while (k--)  g += *ak++ * *dk++;
+            k = i-j; int l = j; 
+            if (k) for (;;) { g += *ak * *dk++; if (!(--k)) break; ak += ++l; }
+            g /= h; *ej++ = g; f += g * *dj++;
+         }  
+         Real hh = f / (2 * h); Real* ak = A.Store();
+         dj = D.Store(); ej = E.Store();
+         for (j = 0; j < i; j++)
+         {
+            f = *dj++; g = *ej - hh * f; *ej++ = g;
+            Real* dk = D.Store(); Real* ek = E.Store(); k = j+1;
+            while (k--) { *ak++ -= (f * *ek++ + g * *dk++); }
+         }
+      }
+      *d = *a; *a = h;
+   }
+}
+
+static void tql1(DiagonalMatrix& D, DiagonalMatrix& E)
+{
+   Tracer et("Evalue(tql1)");
+   REPORT
+   Real eps = FloatingPointPrecision::Epsilon();
+   int n = D.Nrows(); int l;
+   for (l=1; l<n; l++) E.element(l-1) = E.element(l);
+   Real b = 0.0; Real f = 0.0; E.element(n-1) = 0.0;
+   for (l=0; l<n; l++)
+   {
+      int i,j;
+      Real& dl = D.element(l); Real& el = E.element(l);
+      Real h = eps * ( fabs(dl) + fabs(el) );
+      if (b < h) b = h;
+      int m;
+      for (m=l; m<n; m++) if (fabs(E.element(m)) <= b) break;
+      bool test = false;
+      for (j=0; j<30; j++)
+      {
+         if (m==l) { REPORT test = true; break; }
+         Real& dl1 = D.element(l+1);
+         Real g = dl; Real p = (dl1-g) / (2.0*el); Real r = sqrt(p*p + 1.0);
+         dl = el / (p < 0.0 ? p-r : p+r); Real h = g - dl; f += h;
+         Real* dlx = &dl1; i = n-l-1; while (i--) *dlx++ -= h;
+
+         p = D.element(m); Real c = 1.0; Real s = 0.0;
+         for (i=m-1; i>=l; i--)
+         {
+            Real ei = E.element(i); Real di = D.element(i);
+            Real& ei1 = E.element(i+1);
+            g = c * ei; h = c * p;
+            if ( fabs(p) >= fabs(ei))
+            {
+               REPORT
+               c = ei / p; r = sqrt(c*c + 1.0);
+               ei1 = s*p*r; s = c/r; c = 1.0/r;
+            }
+            else
+            {
+               REPORT
+               c = p / ei; r = sqrt(c*c + 1.0);
+               ei1 = s * ei * r; s = 1.0/r; c /= r;
+            }
+            p = c * di - s*g; D.element(i+1) = h + s * (c*g + s*di);
+         }
+         el = s*p; dl = c*p;
+         if (fabs(el) <= b) { REPORT test = true; break; }
+      }
+      if (!test) Throw ( ConvergenceException(D) );
+      Real p = dl + f;
+      test = false;
+      for (i=l; i>0; i--)
+      {
+         if (p < D.element(i-1)) { REPORT D.element(i) = D.element(i-1); }
+         else { REPORT test = true; break; }
+      }
+      if (!test) i=0;
+      D.element(i) = p;
+   }
+}
+
+void eigenvalues(const SymmetricMatrix& A, DiagonalMatrix& D, Matrix& Z)
+{ REPORT DiagonalMatrix E; tred2(A, D, E, Z); tql2(D, E, Z); SortSV(D,Z,true); }
+
+void eigenvalues(const SymmetricMatrix& X, DiagonalMatrix& D)
+{ REPORT DiagonalMatrix E; SymmetricMatrix A; tred3(X,D,E,A); tql1(D,E); }
+
+void eigenvalues(const SymmetricMatrix& X, DiagonalMatrix& D,
+   SymmetricMatrix& A)
+{ REPORT DiagonalMatrix E; tred3(X,D,E,A); tql1(D,E); }
+
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
+
Index: trunk/BNC/newmat/fft.cpp
===================================================================
--- trunk/BNC/newmat/fft.cpp	(revision 2013)
+++ trunk/BNC/newmat/fft.cpp	(revision 2013)
@@ -0,0 +1,480 @@
+/// \ingroup newmat
+///@{
+
+/// \file fft.cpp
+/// \brief Fast Fourier (Carl de Boor) and trig transforms.
+
+
+// Copyright (C) 1991,2,3,4,8: R B Davies
+
+
+#define WANT_MATH
+// #define WANT_STREAM
+
+#include "include.h"
+
+#include "newmatap.h"
+
+// #include "newmatio.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,19); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+static void cossin(int n, int d, Real& c, Real& s)
+// calculate cos(twopi*n/d) and sin(twopi*n/d)
+// minimise roundoff error
+{
+   REPORT
+   long n4 = n * 4; int sector = (int)floor( (Real)n4 / (Real)d + 0.5 );
+   n4 -= sector * d;
+   if (sector < 0) { REPORT sector = 3 - (3 - sector) % 4; }
+   else  { REPORT sector %= 4; }
+   Real ratio = 1.5707963267948966192 * (Real)n4 / (Real)d;
+
+   switch (sector)
+   {
+   case 0: REPORT c =  cos(ratio); s =  sin(ratio); break;
+   case 1: REPORT c = -sin(ratio); s =  cos(ratio); break;
+   case 2: REPORT c = -cos(ratio); s = -sin(ratio); break;
+   case 3: REPORT c =  sin(ratio); s = -cos(ratio); break;
+   }
+}
+
+static void fftstep(ColumnVector& A, ColumnVector& B, ColumnVector& X,
+   ColumnVector& Y, int after, int now, int before)
+{
+   REPORT
+   Tracer trace("FFT(step)");
+   // const Real twopi = 6.2831853071795864769;
+   const int gamma = after * before;  const int delta = now * after;
+   // const Real angle = twopi / delta;  Real temp;
+   // Real r_omega = cos(angle);  Real i_omega = -sin(angle);
+   Real r_arg = 1.0;  Real i_arg = 0.0;
+   Real* x = X.Store();  Real* y = Y.Store();   // pointers to array storage
+   const int m = A.Nrows() - gamma;
+
+   for (int j = 0; j < now; j++)
+   {
+      Real* a = A.Store(); Real* b = B.Store(); // pointers to array storage
+      Real* x1 = x; Real* y1 = y; x += after; y += after;
+      for (int ia = 0; ia < after; ia++)
+      {
+         // generate sins & cosines explicitly rather than iteratively
+         // for more accuracy; but slower
+         cossin(-(j*after+ia), delta, r_arg, i_arg);
+
+         Real* a1 = a++; Real* b1 = b++; Real* x2 = x1++; Real* y2 = y1++;
+         if (now==2)
+         {
+            REPORT int ib = before;
+            if (ib) for (;;)
+            {
+               REPORT
+               Real* a2 = m + a1; Real* b2 = m + b1; a1 += after; b1 += after;
+               Real r_value = *a2; Real i_value = *b2;
+               *x2 = r_value * r_arg - i_value * i_arg + *(a2-gamma);
+               *y2 = r_value * i_arg + i_value * r_arg + *(b2-gamma);
+               if (!(--ib)) break;
+               x2 += delta; y2 += delta;
+            }
+         }
+         else
+         {
+            REPORT int ib = before;
+            if (ib) for (;;)
+            {
+               REPORT
+               Real* a2 = m + a1; Real* b2 = m + b1; a1 += after; b1 += after;
+               Real r_value = *a2; Real i_value = *b2;
+               int in = now-1; while (in--)
+               {
+                  // it should be possible to make this faster
+                  // hand code for now = 2,3,4,5,8
+                  // use symmetry to halve number of operations
+                  a2 -= gamma; b2 -= gamma;  Real temp = r_value;
+                  r_value = r_value * r_arg - i_value * i_arg + *a2;
+                  i_value = temp    * i_arg + i_value * r_arg + *b2;
+               }
+               *x2 = r_value; *y2 = i_value;
+               if (!(--ib)) break;
+               x2 += delta; y2 += delta;
+            }
+         }
+
+         // temp = r_arg;
+         // r_arg = r_arg * r_omega - i_arg * i_omega;
+         // i_arg = temp  * i_omega + i_arg * r_omega;
+
+      }
+   }
+}
+
+
+void FFTI(const ColumnVector& U, const ColumnVector& V,
+   ColumnVector& X, ColumnVector& Y)
+{
+   // Inverse transform
+   Tracer trace("FFTI");
+   REPORT
+   FFT(U,-V,X,Y);
+   const Real n = X.Nrows(); X /= n; Y /= (-n);
+}
+
+void RealFFT(const ColumnVector& U, ColumnVector& X, ColumnVector& Y)
+{
+   // Fourier transform of a real series
+   Tracer trace("RealFFT");
+   REPORT
+   const int n = U.Nrows();                     // length of arrays
+   const int n2 = n / 2;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", U));
+   ColumnVector A(n2), B(n2);
+   Real* a = A.Store(); Real* b = B.Store(); Real* u = U.Store(); int i = n2;
+   while (i--) { *a++ = *u++; *b++ = *u++; }
+   FFT(A,B,A,B);
+   int n21 = n2 + 1;
+   X.resize(n21); Y.resize(n21);
+   i = n2 - 1;
+   a = A.Store(); b = B.Store();              // first els of A and B
+   Real* an = a + i; Real* bn = b + i;        // last els of A and B
+   Real* x = X.Store(); Real* y = Y.Store();  // first els of X and Y
+   Real* xn = x + n2; Real* yn = y + n2;      // last els of X and Y
+
+   *x++ = *a + *b; *y++ = 0.0;                // first complex element
+   *xn-- = *a++ - *b++; *yn-- = 0.0;          // last complex element
+
+   int j = -1; i = n2/2;
+   while (i--)
+   {
+      Real c,s; cossin(j--,n,c,s);
+      Real am = *a - *an; Real ap = *a++ + *an--;
+      Real bm = *b - *bn; Real bp = *b++ + *bn--;
+      Real samcbp = s * am + c * bp; Real sbpcam = s * bp - c * am;
+      *x++  =  0.5 * ( ap + samcbp); *y++  =  0.5 * ( bm + sbpcam);
+      *xn-- =  0.5 * ( ap - samcbp); *yn-- =  0.5 * (-bm + sbpcam);
+   }
+}
+
+void RealFFTI(const ColumnVector& A, const ColumnVector& B, ColumnVector& U)
+{
+   // inverse of a Fourier transform of a real series
+   Tracer trace("RealFFTI");
+   REPORT
+   const int n21 = A.Nrows();                     // length of arrays
+   if (n21 != B.Nrows() || n21 == 0)
+      Throw(ProgramException("Vector lengths unequal or zero", A, B));
+   const int n2 = n21 - 1;  const int n = 2 * n2;  int i = n2 - 1;
+
+   ColumnVector X(n2), Y(n2);
+   Real* a = A.Store(); Real* b = B.Store();  // first els of A and B
+   Real* an = a + n2;   Real* bn = b + n2;    // last els of A and B
+   Real* x = X.Store(); Real* y = Y.Store();  // first els of X and Y
+   Real* xn = x + i;    Real* yn = y + i;     // last els of X and Y
+
+   Real hn = 0.5 / n2;
+   *x++  = hn * (*a + *an);  *y++  = - hn * (*a - *an);
+   a++; an--; b++; bn--;
+   int j = -1;  i = n2/2;
+   while (i--)
+   {
+      Real c,s; cossin(j--,n,c,s);
+      Real am = *a - *an; Real ap = *a++ + *an--;
+      Real bm = *b - *bn; Real bp = *b++ + *bn--;
+      Real samcbp = s * am - c * bp; Real sbpcam = s * bp + c * am;
+      *x++  =  hn * ( ap + samcbp); *y++  =  - hn * ( bm + sbpcam);
+      *xn-- =  hn * ( ap - samcbp); *yn-- =  - hn * (-bm + sbpcam);
+   }
+   FFT(X,Y,X,Y);             // have done inverting elsewhere
+   U.resize(n); i = n2;
+   x = X.Store(); y = Y.Store(); Real* u = U.Store();
+   while (i--) { *u++ = *x++; *u++ = - *y++; }
+}
+
+void FFT(const ColumnVector& U, const ColumnVector& V,
+   ColumnVector& X, ColumnVector& Y)
+{
+   // from Carl de Boor (1980), Siam J Sci Stat Comput, 1 173-8
+   // but first try Sande and Gentleman
+   Tracer trace("FFT");
+   REPORT
+   const int n = U.Nrows();                     // length of arrays
+   if (n != V.Nrows() || n == 0)
+      Throw(ProgramException("Vector lengths unequal or zero", U, V));
+   if (n == 1) { REPORT X = U; Y = V; return; }
+
+   // see if we can use the newfft routine
+   if (!FFT_Controller::OnlyOldFFT && FFT_Controller::CanFactor(n))
+   {
+      REPORT
+      X = U; Y = V;
+      if ( FFT_Controller::ar_1d_ft(n,X.Store(),Y.Store()) ) return;
+   }
+
+   ColumnVector B = V;
+   ColumnVector A = U;
+   X.resize(n); Y.resize(n);
+   const int nextmx = 8;
+   int prime[8] = { 2,3,5,7,11,13,17,19 };
+   int after = 1; int before = n; int next = 0; bool inzee = true;
+   int now = 0; int b1;             // initialised to keep gnu happy
+
+   do
+   {
+      for (;;)
+      {
+	 if (next < nextmx) { REPORT now = prime[next]; }
+	 b1 = before / now;  if (b1 * now == before) { REPORT break; }
+	 next++; now += 2;
+      }
+      before = b1;
+
+      if (inzee) { REPORT fftstep(A, B, X, Y, after, now, before); }
+      else { REPORT fftstep(X, Y, A, B, after, now, before); }
+
+      inzee = !inzee; after *= now;
+   }
+   while (before != 1);
+
+   if (inzee) { REPORT A.release(); X = A; B.release(); Y = B; }
+}
+
+// Trigonometric transforms
+// see Charles Van Loan (1992) "Computational frameworks for the fast
+// Fourier transform" published by SIAM; section 4.4.
+
+void DCT_II(const ColumnVector& U, ColumnVector& V)
+{
+   // Discrete cosine transform, type II, of a real series
+   Tracer trace("DCT_II");
+   REPORT
+   const int n = U.Nrows();                     // length of arrays
+   const int n2 = n / 2; const int n4 = n * 4;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", U));
+   ColumnVector A(n);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store();
+   int i = n2;
+   while (i--) { *a++ = *u++; *(--b) = *u++; }
+   ColumnVector X, Y;
+   RealFFT(A, X, Y); A.cleanup();
+   V.resize(n);
+   Real* x = X.Store(); Real* y = Y.Store();
+   Real* v = V.Store(); Real* w = v + n;
+   *v = *x;
+   int k = 0; i = n2;
+   while (i--)
+   {
+      Real c, s; cossin(++k, n4, c, s);
+      Real xi = *(++x); Real yi = *(++y);
+      *(++v) = xi * c + yi * s; *(--w) = xi * s - yi * c;
+   }
+}
+
+void DCT_II_inverse(const ColumnVector& V, ColumnVector& U)
+{
+   // Inverse of discrete cosine transform, type II
+   Tracer trace("DCT_II_inverse");
+   REPORT
+   const int n = V.Nrows();                     // length of array
+   const int n2 = n / 2; const int n4 = n * 4; const int n21 = n2 + 1;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", V));
+   ColumnVector X(n21), Y(n21);
+   Real* x = X.Store(); Real* y = Y.Store();
+   Real* v = V.Store(); Real* w = v + n;
+   *x = *v; *y = 0.0;
+   int i = n2; int k = 0;
+   while (i--)
+   {
+      Real c, s; cossin(++k, n4, c, s);
+      Real vi = *(++v); Real wi = *(--w);
+      *(++x) = vi * c + wi * s; *(++y) = vi * s - wi * c;
+   }
+   ColumnVector A; RealFFTI(X, Y, A);
+   X.cleanup(); Y.cleanup(); U.resize(n);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store();
+   i = n2;
+   while (i--) { *u++ = *a++; *u++ = *(--b); }
+}
+
+void DST_II(const ColumnVector& U, ColumnVector& V)
+{
+   // Discrete sine transform, type II, of a real series
+   Tracer trace("DST_II");
+   REPORT
+   const int n = U.Nrows();                     // length of arrays
+   const int n2 = n / 2; const int n4 = n * 4;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", U));
+   ColumnVector A(n);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store();
+   int i = n2;
+   while (i--) { *a++ = *u++; *(--b) = -(*u++); }
+   ColumnVector X, Y;
+   RealFFT(A, X, Y); A.cleanup();
+   V.resize(n);
+   Real* x = X.Store(); Real* y = Y.Store();
+   Real* v = V.Store(); Real* w = v + n;
+   *(--w) = *x;
+   int k = 0; i = n2;
+   while (i--)
+   {
+      Real c, s; cossin(++k, n4, c, s);
+      Real xi = *(++x); Real yi = *(++y);
+      *v++ = xi * s - yi * c; *(--w) = xi * c + yi * s;
+   }
+}
+
+void DST_II_inverse(const ColumnVector& V, ColumnVector& U)
+{
+   // Inverse of discrete sine transform, type II
+   Tracer trace("DST_II_inverse");
+   REPORT
+   const int n = V.Nrows();                     // length of array
+   const int n2 = n / 2; const int n4 = n * 4; const int n21 = n2 + 1;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", V));
+   ColumnVector X(n21), Y(n21);
+   Real* x = X.Store(); Real* y = Y.Store();
+   Real* v = V.Store(); Real* w = v + n;
+   *x = *(--w); *y = 0.0;
+   int i = n2; int k = 0;
+   while (i--)
+   {
+      Real c, s; cossin(++k, n4, c, s);
+      Real vi = *v++; Real wi = *(--w);
+      *(++x) = vi * s + wi * c; *(++y) = - vi * c + wi * s;
+   }
+   ColumnVector A; RealFFTI(X, Y, A);
+   X.cleanup(); Y.cleanup(); U.resize(n);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store();
+   i = n2;
+   while (i--) { *u++ = *a++; *u++ = -(*(--b)); }
+}
+
+void DCT_inverse(const ColumnVector& V, ColumnVector& U)
+{
+   // Inverse of discrete cosine transform, type I
+   Tracer trace("DCT_inverse");
+   REPORT
+   const int n = V.Nrows()-1;                     // length of transform
+   const int n2 = n / 2; const int n21 = n2 + 1;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", V));
+   ColumnVector X(n21), Y(n21);
+   Real* x = X.Store(); Real* y = Y.Store(); Real* v = V.Store();
+   Real vi = *v++; *x++ = vi; *y++ = 0.0;
+   Real sum1 = vi / 2.0; Real sum2 = sum1; vi = *v++;
+   int i = n2-1;
+   while (i--)
+   {
+      Real vi2 = *v++; sum1 += vi2 + vi; sum2 += vi2 - vi;
+      *x++ = vi2; vi2 = *v++; *y++ = vi - vi2; vi = vi2;
+   }
+   sum1 += vi; sum2 -= vi;
+   vi = *v; *x = vi; *y = 0.0; vi /= 2.0; sum1 += vi; sum2 += vi;
+   ColumnVector A; RealFFTI(X, Y, A);
+   X.cleanup(); Y.cleanup(); U.resize(n+1);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); v = u + n;
+   i = n2; int k = 0; *u++ = sum1 / n2; *v-- = sum2 / n2;
+   while (i--)
+   {
+      Real s = sin(1.5707963267948966192 * (++k) / n2);
+      Real ai = *(++a); Real bi = *(--b);
+      Real bz = (ai - bi) / 4 / s; Real az = (ai + bi) / 2;
+      *u++ = az - bz; *v-- = az + bz;
+   }
+}
+
+void DCT(const ColumnVector& U, ColumnVector& V)
+{
+   // Discrete cosine transform, type I
+   Tracer trace("DCT");
+   REPORT
+   DCT_inverse(U, V);
+   V *= (V.Nrows()-1)/2;
+}
+
+void DST_inverse(const ColumnVector& V, ColumnVector& U)
+{
+   // Inverse of discrete sine transform, type I
+   Tracer trace("DST_inverse");
+   REPORT
+   const int n = V.Nrows()-1;                     // length of transform
+   const int n2 = n / 2; const int n21 = n2 + 1;
+   if (n != 2 * n2)
+      Throw(ProgramException("Vector length not multiple of 2", V));
+   ColumnVector X(n21), Y(n21);
+   Real* x = X.Store(); Real* y = Y.Store(); Real* v = V.Store();
+   Real vi = *(++v); *x++ = 2 * vi; *y++ = 0.0;
+   int i = n2-1;
+   while (i--) { *y++ = *(++v); Real vi2 = *(++v); *x++ = vi2 - vi; vi = vi2; }
+   *x = -2 * vi; *y = 0.0;
+   ColumnVector A; RealFFTI(X, Y, A);
+   X.cleanup(); Y.cleanup(); U.resize(n+1);
+   Real* a = A.Store(); Real* b = a + n; Real* u = U.Store(); v = u + n;
+   i = n2; int k = 0; *u++ = 0.0; *v-- = 0.0;
+   while (i--)
+   {
+      Real s = sin(1.5707963267948966192 * (++k) / n2);
+      Real ai = *(++a); Real bi = *(--b);
+      Real az = (ai + bi) / 4 / s; Real bz = (ai - bi) / 2;
+      *u++ = az - bz; *v-- = az + bz;
+   }
+}
+
+void DST(const ColumnVector& U, ColumnVector& V)
+{
+   // Discrete sine transform, type I
+   Tracer trace("DST");
+   REPORT
+   DST_inverse(U, V);
+   V *= (V.Nrows()-1)/2;
+}
+
+// Two dimensional FFT
+void FFT2(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y)
+{
+   Tracer trace("FFT2");
+   REPORT
+   int m = U.Nrows(); int n = U.Ncols();
+   if (m != V.Nrows() || n != V.Ncols() || m == 0 || n == 0)
+      Throw(ProgramException("Matrix dimensions unequal or zero", U, V));
+   X = U; Y = V;
+   int i; ColumnVector CVR; ColumnVector CVI;
+   for (i = 1; i <= m; ++i)
+   {
+      FFT(X.Row(i).t(), Y.Row(i).t(), CVR, CVI);
+      X.Row(i) = CVR.t(); Y.Row(i) = CVI.t();
+   }
+   for (i = 1; i <= n; ++i)
+   {
+      FFT(X.Column(i), Y.Column(i), CVR, CVI);
+      X.Column(i) = CVR; Y.Column(i) = CVI;
+   }
+}
+
+void FFT2I(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y)
+{
+   // Inverse transform
+   Tracer trace("FFT2I");
+   REPORT
+   FFT2(U,-V,X,Y);
+   const Real n = X.Nrows() * X.Ncols(); X /= n; Y /= (-n);
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+///@}
Index: trunk/BNC/newmat/hholder.cpp
===================================================================
--- trunk/BNC/newmat/hholder.cpp	(revision 2013)
+++ trunk/BNC/newmat/hholder.cpp	(revision 2013)
@@ -0,0 +1,376 @@
+/// \ingroup newmat
+///@{
+
+/// \file hholder.cpp
+/// QR related decompositions
+/// QRZ, QRZT decompositions
+/// QR update and extend orthogonal functions
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmatap.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,16); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/*************************** QR decompositions ***************************/
+
+inline Real square(Real x) { return x*x; }
+
+void QRZT(Matrix& X, LowerTriangularMatrix& L)
+{
+   REPORT
+	 Tracer et("QRZT(1)");
+   int n = X.Ncols(); int s = X.Nrows(); L.resize(s);
+   if (n == 0 || s == 0) { L = 0.0; return; }
+   Real* xi = X.Store(); int k;
+   for (int i=0; i<s; i++)
+   {
+      Real sum = 0.0;
+      Real* xi0=xi; k=n; while(k--) { sum += square(*xi++); }
+      sum = sqrt(sum);
+      if (sum == 0.0)
+      {
+         REPORT
+         k=n; while(k--) { *xi0++ = 0.0; }
+         for (int j=i; j<s; j++) L.element(j,i) = 0.0;
+      }
+      else
+      {
+         L.element(i,i) = sum;
+         Real* xj0=xi0; k=n; while(k--) { *xj0++ /= sum; }
+         for (int j=i+1; j<s; j++)
+         {
+            sum=0.0;
+            xi=xi0; Real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; }
+            xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; }
+            L.element(j,i) = sum;
+         }
+      }
+   }
+}
+
+void QRZT(const Matrix& X, Matrix& Y, Matrix& M)
+{
+   REPORT
+   Tracer et("QRZT(2)");
+   int n = X.Ncols(); int s = X.Nrows(); int t = Y.Nrows();
+   if (Y.Ncols() != n)
+      { Throw(ProgramException("Unequal row lengths",X,Y)); }
+   M.resize(t,s);
+   Real* xi = X.Store(); int k;
+   for (int i=0; i<s; i++)
+   {
+      Real* xj0 = Y.Store(); Real* xi0 = xi;
+      for (int j=0; j<t; j++)
+      {
+         Real sum=0.0;
+         xi=xi0; Real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; }
+         xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; }
+         M.element(j,i) = sum;
+      }
+   }
+}
+
+/*
+void QRZ(Matrix& X, UpperTriangularMatrix& U)
+{
+	Tracer et("QRZ(1)");
+	int n = X.Nrows(); int s = X.Ncols(); U.resize(s);
+	Real* xi0 = X.Store(); int k;
+	for (int i=0; i<s; i++)
+	{
+		Real sum = 0.0;
+		Real* xi = xi0; k=n; while(k--) { sum += square(*xi); xi+=s; }
+		sum = sqrt(sum);
+		U.element(i,i) = sum;
+		if (sum==0.0) Throw(SingularException(U));
+		Real* xj0=xi0; k=n; while(k--) { *xj0 /= sum; xj0+=s; }
+		xj0 = xi0;
+		for (int j=i+1; j<s; j++)
+		{
+			sum=0.0;
+			xi=xi0; k=n; xj0++; Real* xj=xj0;
+			while(k--) { sum += *xi * *xj; xi+=s; xj+=s; }
+			xi=xi0; k=n; xj=xj0;
+			while(k--) { *xj -= sum * *xi; xj+=s; xi+=s; }
+			U.element(i,j) = sum;
+		}
+		xi0++;
+	}
+}
+*/
+
+void QRZ(Matrix& X, UpperTriangularMatrix& U)
+{
+   REPORT
+   Tracer et("QRZ(1)");
+   int n = X.Nrows(); int s = X.Ncols(); U.resize(s); U = 0.0;
+   if (n == 0 || s == 0) return;
+   Real* xi0 = X.Store(); Real* u0 = U.Store(); Real* u;
+   int j, k; int J = s; int i = s;
+   while (i--)
+   {
+      Real* xj0 = xi0; Real* xi = xi0; k = n;
+      if (k) for (;;)
+      {
+         u = u0; Real Xi = *xi; Real* xj = xj0;
+         j = J; while(j--) *u++ += Xi * *xj++;
+         if (!(--k)) break;
+         xi += s; xj0 += s;
+      }
+
+      Real sum = sqrt(*u0); *u0 = sum; u = u0+1;
+      if (sum == 0.0)
+      {
+         REPORT
+         j = J - 1; while(j--) *u++ = 0.0;
+
+         xj0 = xi0++; k = n;
+         if (k) for (;;)
+         {
+            *xj0 = 0.0;
+            if (!(--k)) break;
+	          xj0 += s;
+         }
+         u0 += J--;
+      }
+      else
+      {
+         int J1 = J-1; j = J1; while(j--) *u++ /= sum;
+
+         xj0 = xi0; xi = xi0++; k = n;
+         if (k) for (;;)
+         {
+            u = u0+1; Real Xi = *xi; Real* xj = xj0;
+            Xi /= sum; *xj++ = Xi;
+            j = J1; while(j--) *xj++ -= *u++ * Xi;
+            if (!(--k)) break;
+	          xi += s; xj0 += s;
+         }
+         u0 += J--;
+      }
+   }
+}
+
+void QRZ(const Matrix& X, Matrix& Y, Matrix& M)
+{
+   REPORT
+   Tracer et("QRZ(2)");
+   int n = X.Nrows(); int s = X.Ncols(); int t = Y.Ncols();
+   if (Y.Nrows() != n)
+      { Throw(ProgramException("Unequal column lengths",X,Y)); }
+   M.resize(s,t); M = 0;Real* m0 = M.Store(); Real* m;
+   Real* xi0 = X.Store();
+   int j, k; int i = s;
+   while (i--)
+   {
+      Real* xj0 = Y.Store(); Real* xi = xi0; k = n;
+      if (k) for (;;)
+      {
+         m = m0; Real Xi = *xi; Real* xj = xj0;
+         j = t; while(j--) *m++ += Xi * *xj++;
+         if (!(--k)) break;
+         xi += s; xj0 += t;
+      }
+
+      xj0 = Y.Store(); xi = xi0++; k = n;
+      if (k) for (;;)
+      {
+         m = m0; Real Xi = *xi; Real* xj = xj0;
+         j = t; while(j--) *xj++ -= *m++ * Xi;
+         if (!(--k)) break;
+         xi += s; xj0 += t;
+      }
+      m0 += t;
+   }
+}
+
+/*
+
+void QRZ(const Matrix& X, Matrix& Y, Matrix& M)
+{
+	Tracer et("QRZ(2)");
+	int n = X.Nrows(); int s = X.Ncols(); int t = Y.Ncols();
+	if (Y.Nrows() != n)
+	{ Throw(ProgramException("Unequal column lengths",X,Y)); }
+	M.resize(s,t);
+	Real* xi0 = X.Store(); int k;
+	for (int i=0; i<s; i++)
+	{
+		Real* xj0 = Y.Store();
+		for (int j=0; j<t; j++)
+		{
+			Real sum=0.0;
+			Real* xi=xi0; Real* xj=xj0; k=n;
+			while(k--) { sum += *xi * *xj; xi+=s; xj+=t; }
+			xi=xi0; k=n; xj=xj0++;
+			while(k--) { *xj -= sum * *xi; xj+=t; xi+=s; }
+			M.element(i,j) = sum;
+		}
+		xi0++;
+	}
+}
+*/
+
+void updateQRZT(Matrix& X, LowerTriangularMatrix& L)
+{
+   REPORT
+	 Tracer et("updateQRZT");
+   int n = X.Ncols(); int s = X.Nrows();
+   if (s != L.Nrows())
+      Throw(ProgramException("Incompatible dimensions",X,L)); 
+   if (n == 0 || s == 0) return;
+   Real* xi = X.Store(); int k;
+   for (int i=0; i<s; i++)
+   {
+      Real r = L.element(i,i); 
+      Real sum = 0.0;
+      Real* xi0=xi; k=n; while(k--) { sum += square(*xi++); }
+      sum = sqrt(sum + square(r));
+      if (sum == 0.0)
+      {
+         REPORT
+         k=n; while(k--) { *xi0++ = 0.0; }
+         for (int j=i; j<s; j++) L.element(j,i) = 0.0;
+      }
+      else
+      {
+         Real frs = fabs(r) + sum;
+         Real a0 = sqrt(frs / sum); Real alpha = a0 / frs;
+         if (r <= 0) { REPORT L.element(i,i) = sum; alpha = -alpha; }
+         else { REPORT L.element(i,i) = -sum; }
+         Real* xj0=xi0; k=n; while(k--) { *xj0++ *= alpha; }
+         for (int j=i+1; j<s; j++)
+         {
+            sum = 0.0;
+            xi=xi0; Real* xj=xj0; k=n; while(k--) { sum += *xi++ * *xj++; }
+            sum += a0 * L.element(j,i);
+            xi=xi0; k=n; while(k--) { *xj0++ -= sum * *xi++; }
+            L.element(j,i) -= sum * a0;
+         }
+      }
+   }
+}
+
+void updateQRZ(Matrix& X, UpperTriangularMatrix& U)
+{
+   REPORT
+   Tracer et("updateQRZ");
+   int n = X.Nrows(); int s = X.Ncols();
+   if (s != U.Ncols())
+      Throw(ProgramException("Incompatible dimensions",X,U));
+   if (n == 0 || s == 0) return; 
+   Real* xi0 = X.Store(); Real* u0 = U.Store(); Real* u;
+   RowVector V(s); Real* v0 = V.Store(); Real* v; V = 0.0;
+   int j, k; int J = s; int i = s;
+   while (i--)
+   {
+      Real* xj0 = xi0; Real* xi = xi0; k = n;
+      if (k) for (;;)
+      {
+         v = v0; Real Xi = *xi; Real* xj = xj0;
+         j = J; while(j--) *v++ += Xi * *xj++;
+         if (!(--k)) break;
+         xi += s; xj0 += s;
+      }
+
+      Real r = *u0;
+      Real sum = sqrt(*v0 + square(r));
+      
+      if (sum == 0.0)
+      {
+         REPORT
+         u = u0; v = v0;
+         j = J; while(j--) { *u++ = 0.0; *v++ = 0.0; }
+         xj0 = xi0++; k = n;
+         if (k) for (;;)
+         {
+            *xj0 = 0.0;
+            if (!(--k)) break;
+	          xj0 += s;
+         }
+         u0 += J--;
+      }
+      else
+      {
+         Real frs = fabs(r) + sum;
+         Real a0 = sqrt(frs / sum); Real alpha = a0 / frs;
+         if (r <= 0) { REPORT alpha = -alpha; *u0 = sum; }
+         else { REPORT *u0 = -sum; }
+      
+         j = J - 1; v = v0 + 1; u = u0 + 1;     
+         while (j--)
+            { *v = a0 * *u + alpha * *v; *u -= a0 * *v; ++v; ++u; }
+
+         xj0 = xi0; xi = xi0++; k = n;
+         if (k) for (;;)
+         {
+            v = v0 + 1; Real Xi = *xi; Real* xj = xj0;
+            Xi *= alpha; *xj++ = Xi;
+            j = J - 1; while(j--) *xj++ -= *v++ * Xi;
+            if (!(--k)) break;
+	          xi += s; xj0 += s;
+         }
+         
+         j = J; v = v0;
+         while (j--) *v++ = 0.0;
+         
+         u0 += J--;
+      }
+   }
+}
+
+// Matrix A's first n columns are orthonormal
+// so A.Columns(1,n).t() * A.Columns(1,n) is the identity matrix.
+// Fill out the remaining columns of A to make them orthonormal
+// so A.t() * A is the identity matrix 
+void extend_orthonormal(Matrix& A, int n)
+{
+   REPORT
+   Tracer et("extend_orthonormal");
+   int nr = A.nrows(); int nc = A.ncols();
+   if (nc > nr) Throw(IncompatibleDimensionsException(A));
+   if (n > nc) Throw(IncompatibleDimensionsException(A));
+   ColumnVector SSR;
+   { Matrix A1 = A.Columns(1,n); SSR = A1.sum_square_rows(); }
+   for (int i = n; i < nc; ++i)
+   {
+      // pick row with smallest SSQ
+      int k; SSR.minimum1(k);
+      // orthogonalise column with 1 at element k, 0 elsewhere
+      // next line is rather inefficient
+      ColumnVector X = - A.Columns(1, i) * A.SubMatrix(k, k, 1, i).t();
+      X(k) += 1.0;
+      // normalise
+      X /= sqrt(X.SumSquare());
+      // update row sums of squares
+      for (k = 1; k <= nr; ++k) SSR(k) += square(X(k));
+      // load new column into matrix
+      A.Column(i+1) = X;
+   }
+}
+   
+   
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+///@}
Index: trunk/BNC/newmat/include.h
===================================================================
--- trunk/BNC/newmat/include.h	(revision 2013)
+++ trunk/BNC/newmat/include.h	(revision 2013)
@@ -0,0 +1,349 @@
+/// \defgroup rbd_common RBD common library 
+///@{
+
+/// \file include.h
+/// Set options and and details of include files.
+
+#ifndef INCLUDE_LIB
+#define INCLUDE_LIB
+
+//#define use_namespace                   // define name spaces
+
+#define SETUP_C_SUBSCRIPTS              // allow element access via A[i][j]
+
+//#define OPT_COMPATIBLE                  // for use with opt++
+
+// Activate just one of the following 3 statements
+
+//#define SimulateExceptions              // use simulated exceptions
+#define UseExceptions                   // use C++ exceptions
+//#define DisableExceptions               // do not use exceptions
+
+
+//#define TEMPS_DESTROYED_QUICKLY         // for compilers that delete
+					// temporaries too quickly
+
+//#define TEMPS_DESTROYED_QUICKLY_R       // the same thing but applied
+					// to return from functions only
+
+//#define DO_FREE_CHECK                   // check news and deletes balance
+
+#define USING_DOUBLE                    // elements of type double
+//#define USING_FLOAT                   // elements of type float
+
+#define bool_LIB 0                      // for compatibility with my older libraries
+
+//#define ios_format_flags ios::fmtflags  // for Gnu 3 and Intel for Linux
+
+
+//#define _STANDARD_                    // using standard library
+
+//#define use_float_h                   // use float.h for precision data
+
+
+//#define HAS_INT64                     // if unsigned _int64 is recognised
+                                        // used by newran03
+                                        
+// comment out next line if Exception causes a problem
+#define TypeDefException
+
+//*********************** end of options set by user ********************
+
+
+// for Gnu C++ version 3
+#if defined __GNUG__ && __GNUG__ >= 3
+   #define _STANDARD_                   // use standard library
+   #define ios_format_flags ios::fmtflags
+#endif
+
+// for Intel C++ for Linux
+#if defined __ICC
+   #define _STANDARD_                   // use standard library
+   #define ios_format_flags ios::fmtflags
+#endif
+
+// for Microsoft Visual C++ 7 and above (and Intel simulating these)
+#if defined _MSC_VER && _MSC_VER >= 1300
+   #define _STANDARD_                   // use standard library
+#endif
+
+
+#ifdef _STANDARD_                       // using standard library
+   #include <cstdlib>
+   #if defined _MSC_VER && _MSC_VER == 1200
+      #include <limits>              // for VC++6
+   #endif
+   #ifdef WANT_STREAM
+      #include <iostream>
+      #include <iomanip>
+   #endif
+   #ifdef WANT_MATH
+      #include <cmath>
+   #endif
+   #ifdef WANT_STRING
+      #include <cstring>
+   #endif
+   #ifdef WANT_TIME
+      #include <ctime>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream>
+   #endif
+   ////using namespace std;
+   #define USE_STD_NAMESPACE
+#else
+
+#define DEFAULT_HEADER                  // use AT&T style header
+                                        // if no other compiler is recognised
+
+#ifdef _MSC_VER                         // Microsoft
+   #include <stdlib.h>
+
+//   reactivate these statements to run under MSC version 7.0
+//   typedef int jmp_buf[9];
+//   extern "C"
+//   {
+//      int __cdecl setjmp(jmp_buf);
+//      void __cdecl longjmp(jmp_buf, int);
+//   }
+
+   #ifdef WANT_STREAM
+      #include <iostream.h>
+      #include <iomanip.h>
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+#ifdef __ZTC__                          // Zortech
+   #include <stdlib.h>
+   #ifdef WANT_STREAM
+      #include <iostream.hpp>
+      #include <iomanip.hpp>
+      #define flush ""                  // not defined in iomanip?
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+#if defined __BCPLUSPLUS__ || defined __TURBOC__  // Borland or Turbo
+   #include <stdlib.h>
+   #ifdef WANT_STREAM
+      #include <iostream.h>
+      #include <iomanip.h>
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>            // Borland has both float and values
+                                    // but values.h returns +INF for
+                                    // MAXDOUBLE in BC5
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+#ifdef __GNUG__                         // Gnu C++
+   #include <stdlib.h>
+   #ifdef WANT_STREAM
+      #include <iostream.h>
+      #include <iomanip.h>
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+#ifdef __WATCOMC__                      // Watcom C/C++
+   #include <stdlib.h>
+   #ifdef WANT_STREAM
+      #include <iostream.h>
+      #include <iomanip.h>
+   #endif
+   #ifdef WANT_MATH
+      #include <math.h>
+      #include <float.h>
+   #endif
+   #ifdef WANT_STRING
+      #include <string.h>
+   #endif
+   #ifdef WANT_TIME
+      #include <time.h>
+   #endif
+   #ifdef WANT_FSTREAM
+      #include <fstream.h>
+   #endif
+   #undef DEFAULT_HEADER
+#endif
+
+
+#ifdef macintosh                        // MPW C++ on the Mac
+#include <stdlib.h>
+#ifdef WANT_STREAM
+#include <iostream.h>
+#include <iomanip.h>
+#endif
+#ifdef WANT_MATH
+#include <float.h>
+#include <math.h>
+#endif
+#ifdef WANT_STRING
+#include <string.h>
+#endif
+#ifdef WANT_TIME
+#include <time.h>
+#endif
+#ifdef WANT_FSTREAM
+#include <fstream.h>
+#endif
+#undef DEFAULT_HEADER
+#endif
+
+#ifdef use_float_h                      // use float.h for precision values
+#include <stdlib.h>
+#ifdef WANT_STREAM
+#include <iostream.h>
+#include <iomanip.h>
+#endif
+#ifdef WANT_MATH
+#include <float.h>
+#include <math.h>
+#endif
+#ifdef WANT_STRING
+#include <string.h>
+#endif
+#ifdef WANT_TIME
+#include <time.h>
+#endif
+#ifdef WANT_FSTREAM
+#include <fstream.h>
+#endif
+#undef DEFAULT_HEADER
+#endif
+
+
+#ifdef DEFAULT_HEADER                   // for example AT&T
+#define ATandT
+#include <stdlib.h>
+#ifdef WANT_STREAM
+#include <iostream.h>
+#include <iomanip.h>
+#endif
+#ifdef WANT_MATH
+#include <math.h>
+#define SystemV                         // use System V
+#include <values.h>
+#endif
+#ifdef WANT_STRING
+#include <string.h>
+#endif
+#ifdef WANT_TIME
+#include <time.h>
+#endif
+#ifdef WANT_FSTREAM
+#include <fstream.h>
+#endif
+#endif                                  // DEFAULT_HEADER
+
+#endif                                  // _STANDARD_
+
+#ifdef use_namespace
+namespace RBD_COMMON {
+#endif
+
+
+#ifdef USING_FLOAT                      // set precision type to float
+typedef float Real;
+typedef double long_Real;
+#endif
+
+#ifdef USING_DOUBLE                     // set precision type to double
+typedef double Real;
+typedef long double long_Real;
+#endif
+
+
+// This is for (very old) compilers that do not have bool automatically defined
+
+#ifndef bool_LIB
+#define bool_LIB 0
+
+class bool
+{
+	int value;
+public:
+	bool(const int b) { value = b ? 1 : 0; }
+	bool(const void* b) { value = b ? 1 : 0; }
+	bool() {}
+	operator int() const { return value; }
+	int operator!() const { return !value; }
+};
+
+
+const bool true = 1;
+const bool false = 0;
+
+#endif
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+#ifdef use_namespace
+namespace RBD_COMMON {}
+namespace RBD_LIBRARIES                 // access all my libraries
+{
+   using namespace RBD_COMMON;
+}
+#endif
+
+
+#endif
+
+
+///@}
+
Index: trunk/BNC/newmat/jacobi.cpp
===================================================================
--- trunk/BNC/newmat/jacobi.cpp	(revision 2013)
+++ trunk/BNC/newmat/jacobi.cpp	(revision 2013)
@@ -0,0 +1,130 @@
+/// \ingroup newmat
+///@{
+
+/// \file jacobi.cpp
+/// Eigen value decomposition using Jacobi method.
+
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+
+//#define WANT_STREAM
+
+
+#define WANT_MATH
+
+#include "include.h"
+#include "newmatap.h"
+#include "precisio.h"
+#include "newmatrm.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,18); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D, SymmetricMatrix& A,
+   Matrix& V, bool eivec)
+{
+   Real epsilon = FloatingPointPrecision::Epsilon();
+   Tracer et("Jacobi");
+   REPORT
+   int n = X.Nrows(); DiagonalMatrix B(n), Z(n); D.resize(n); A = X;
+   if (eivec) { REPORT V.resize(n,n); D = 1.0; V = D; }
+   B << A; D = B; Z = 0.0; A.Inject(Z);
+   bool converged = false;
+   for (int i=1; i<=50; i++)
+   {
+      Real sm=0.0; Real* a = A.Store(); int p = A.Storage();
+      while (p--) sm += fabs(*a++);            // have previously zeroed diags
+      if (sm==0.0) { REPORT converged = true; break; }
+      Real tresh = (i<4) ? 0.2 * sm / square(n) : 0.0; a = A.Store();
+      for (p = 0; p < n; p++)
+      {
+         Real* ap1 = a + (p*(p+1))/2;
+         Real& zp = Z.element(p); Real& dp = D.element(p);
+         for (int q = p+1; q < n; q++)
+         {
+            Real* ap = ap1; Real* aq = a + (q*(q+1))/2;
+            Real& zq = Z.element(q); Real& dq = D.element(q);
+            Real& apq = A.element(q,p);
+            Real g = 100 * fabs(apq); Real adp = fabs(dp); Real adq = fabs(dq);
+
+            if (i>4 && g < epsilon*adp && g < epsilon*adq) { REPORT apq = 0.0; }
+            else if (fabs(apq) > tresh)
+            {
+               REPORT
+               Real t; Real h = dq - dp; Real ah = fabs(h);
+               if (g < epsilon*ah) { REPORT t = apq / h; }
+               else
+               {
+                  REPORT
+                  Real theta = 0.5 * h / apq;
+                  t = 1.0 / ( fabs(theta) + sqrt(1.0 + square(theta)) );
+                  if (theta<0.0) { REPORT t = -t; }
+               }
+               Real c = 1.0 / sqrt(1.0 + square(t)); Real s = t * c;
+               Real tau = s / (1.0 + c); h = t * apq;
+               zp -= h; zq += h; dp -= h; dq += h; apq = 0.0;
+               int j = p;
+               while (j--)
+               {
+                  g = *ap; h = *aq;
+                  *ap++ = g-s*(h+g*tau); *aq++ = h+s*(g-h*tau);
+               }
+               int ip = p+1; j = q-ip; ap += ip++; aq++;
+               while (j--)
+               {
+                  g = *ap; h = *aq;
+                  *ap = g-s*(h+g*tau); *aq++ = h+s*(g-h*tau);
+                  ap += ip++;
+               }
+               if (q < n-1)             // last loop is non-empty
+               {
+                  int iq = q+1; j = n-iq; ap += ip++; aq += iq++;
+                  for (;;)
+                  {
+                     g = *ap; h = *aq;
+                     *ap = g-s*(h+g*tau); *aq = h+s*(g-h*tau);
+                     if (!(--j)) break;
+                     ap += ip++; aq += iq++;
+                  }
+               }
+               if (eivec)
+               {
+                  REPORT
+                  RectMatrixCol VP(V,p); RectMatrixCol VQ(V,q);
+                  Rotate(VP, VQ, tau, s);
+               }
+            }
+         }
+      }
+      B = B + Z; D = B; Z = 0.0;
+   }
+   if (!converged) Throw(ConvergenceException(X));
+   if (eivec) SortSV(D, V, true);
+   else SortAscending(D);
+}
+
+void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D)
+{ REPORT SymmetricMatrix A; Matrix V; Jacobi(X,D,A,V,false); }
+
+void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D, SymmetricMatrix& A)
+{ REPORT Matrix V; Jacobi(X,D,A,V,false); }
+
+void Jacobi(const SymmetricMatrix& X, DiagonalMatrix& D, Matrix& V)
+{ REPORT SymmetricMatrix A; Jacobi(X,D,A,V,true); }
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+///@}
Index: trunk/BNC/newmat/myexcept.cpp
===================================================================
--- trunk/BNC/newmat/myexcept.cpp	(revision 2013)
+++ trunk/BNC/newmat/myexcept.cpp	(revision 2013)
@@ -0,0 +1,499 @@
+/// \ingroup rbd_common
+///@{
+
+/// \file myexcept.cpp
+/// Exception handler.
+/// The low level classes for
+/// - my exception class hierarchy
+/// - the functions needed for my simulated exceptions
+/// - the Tracer mechanism
+/// - routines for checking whether new and delete calls are balanced
+///
+
+// Copyright (C) 1993,4,6: R B Davies
+
+
+#define WANT_STREAM                    // include.h will get stream fns
+#define WANT_STRING
+
+#include "include.h"                   // include standard files
+
+
+#include "myexcept.h"                  // for exception handling
+
+#ifdef use_namespace
+namespace RBD_COMMON {
+#endif
+
+#ifdef USE_STD_NAMESPACE
+using namespace std;
+#endif
+
+//#define REG_DEREG                    // for print out uses of new/delete
+//#define CLEAN_LIST                   // to print entries being added to
+                                       // or deleted from cleanup list
+
+#ifdef SimulateExceptions
+
+void Throw()
+{
+   for (Janitor* jan = JumpBase::jl->janitor; jan; jan = jan->NextJanitor)
+      jan->CleanUp();
+   JumpItem* jx = JumpBase::jl->ji;    // previous jumpbase;
+   if ( !jx ) { Terminate(); }         // jl was initial JumpItem
+   JumpBase::jl = jx;                  // drop down a level; cannot be in front
+                                       // of previous line
+   Tracer::last = JumpBase::jl->trace;
+   longjmp(JumpBase::jl->env, 1);
+}
+
+#endif                                 // end of simulate exceptions
+
+
+unsigned long BaseException::Select;
+char* BaseException::what_error;
+int BaseException::SoFar;
+int BaseException::LastOne;
+
+BaseException::BaseException(const char* a_what)
+{
+   Select++; SoFar = 0;
+   if (!what_error)                   // make space for exception message
+   {
+      LastOne = 511;
+      what_error = new char[512];
+      if (!what_error)                // fail to make space
+      {
+         LastOne = 0;
+         what_error = (char *)"No heap space for exception message\n";
+      }
+   }
+   AddMessage("\n\nAn exception has been thrown\n");
+   AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+void BaseException::AddMessage(const char* a_what)
+{
+   if (a_what)
+   {
+      int l = strlen(a_what); int r = LastOne - SoFar;
+      if (l < r) { strcpy(what_error+SoFar, a_what); SoFar += l; }
+      else if (r > 0)
+      {
+         strncpy(what_error+SoFar, a_what, r);
+         what_error[LastOne] = 0;
+         SoFar = LastOne;
+      }
+   }
+}
+
+void BaseException::AddInt(int value)
+{
+   bool negative;
+   if (value == 0) { AddMessage("0"); return; }
+   else if (value < 0) { value = -value; negative = true; }
+   else negative = false;
+   int n = 0; int v = value;        // how many digits will we need?
+   while (v > 0) { v /= 10; n++; }
+   if (negative) n++;
+   if (LastOne-SoFar < n) { AddMessage("***"); return; }
+
+   SoFar += n; n = SoFar; what_error[n] = 0;
+   while (value > 0)
+   {
+      int nv = value / 10; int rm = value - nv * 10;  value = nv;
+      what_error[--n] = (char)(rm + '0');
+   }
+   if (negative) what_error[--n] = '-';
+   return;
+}
+
+void Tracer::PrintTrace()
+{
+   cout << "\n";
+   for (Tracer* et = last; et; et=et->previous)
+      cout << "  * " << et->entry << "\n";
+}
+
+void Tracer::AddTrace()
+{
+   if (last)
+   {
+      BaseException::AddMessage("Trace: ");
+      BaseException::AddMessage(last->entry);
+      for (Tracer* et = last->previous; et; et=et->previous)
+      {
+         BaseException::AddMessage("; ");
+         BaseException::AddMessage(et->entry);
+      }
+      BaseException::AddMessage(".\n");
+   }
+}
+
+#ifdef SimulateExceptions
+
+
+Janitor::Janitor()
+{
+   if (do_not_link)
+   {
+      do_not_link = false; NextJanitor = 0; OnStack = false;
+#ifdef CLEAN_LIST
+      cout << "Not added to clean-list " << (unsigned long)this << "\n";
+#endif
+   }
+   else
+   {
+      OnStack = true;
+#ifdef CLEAN_LIST
+      cout << "Add to       clean-list " << (unsigned long)this << "\n";
+#endif
+      NextJanitor = JumpBase::jl->janitor; JumpBase::jl->janitor=this;
+   }
+}
+
+Janitor::~Janitor()
+{
+   // expect the item to be deleted to be first on list
+   // but must be prepared to search list
+   if (OnStack)
+   {
+#ifdef CLEAN_LIST
+      cout << "Delete from  clean-list " << (unsigned long)this << "\n";
+#endif
+      Janitor* lastjan = JumpBase::jl->janitor;
+      if (this == lastjan) JumpBase::jl->janitor = NextJanitor;
+      else
+      {
+	 for (Janitor* jan = lastjan->NextJanitor; jan;
+	    jan = lastjan->NextJanitor)
+	 {
+	    if (jan==this)
+	       { lastjan->NextJanitor = jan->NextJanitor; return; }
+	    lastjan=jan;
+	 }
+
+	 Throw(BaseException(
+"Cannot resolve memory linked list\nSee notes in myexcept.cpp for details\n"
+         ));
+
+
+// This message occurs when a call to ~Janitor() occurs, apparently
+// without a corresponding call to Janitor(). This could happen if my
+// way of deciding whether a constructor is being called by new
+// fails.
+
+// It may happen if you are using my simulated exceptions and also have
+// your compiler s exceptions turned on.
+
+// It can also happen if you have a class derived from Janitor
+// which does not include a copy constructor [ eg X(const &X) ].
+// Possibly also if delete is applied an object on the stack (ie not
+// called by new). Otherwise, it is a bug in myexcept or your compiler.
+// If you do not #define TEMPS_DESTROYED_QUICKLY you will get this
+// error with Microsoft C 7.0. There are probably situations where
+// you will get this when you do define TEMPS_DESTROYED_QUICKLY. This
+// is a bug in MSC. Beware of "operator" statements for defining
+// conversions; particularly for converting from a Base class to a
+// Derived class.
+
+// You may get away with simply deleting this error message and Throw
+// statement if you can not find a better way of overcoming the
+// problem. In any case please tell me if you get this error message,
+// particularly for compilers apart from Microsoft C 7.0.
+
+
+      }
+   }
+}
+
+JumpItem* JumpBase::jl;              // will be set to zero
+jmp_buf JumpBase::env;
+bool Janitor::do_not_link;           // will be set to false
+
+
+int JanitorInitializer::ref_count;
+
+JanitorInitializer::JanitorInitializer()
+{
+   if (ref_count++ == 0) new JumpItem;
+                                    // need JumpItem at head of list
+}
+
+#endif                              // end of SimulateExceptions
+
+Tracer* Tracer::last;               // will be set to zero
+
+
+void Terminate()
+{
+   cout << "\n\nThere has been an exception with no handler - exiting";
+   const char* what = BaseException::what();
+   if (what) cout << what << "\n";
+   exit(1);
+}
+
+
+
+#ifdef DO_FREE_CHECK
+// Routines for tracing whether new and delete calls are balanced
+
+FreeCheckLink::FreeCheckLink() : next(FreeCheck::next)
+   { FreeCheck::next = this; }
+
+FCLClass::FCLClass(void* t, char* name) : ClassName(name) { ClassStore=t; }
+
+FCLRealArray::FCLRealArray(void* t, char* o, int s)
+  : Operation(o), size(s) { ClassStore=t; }
+
+FCLIntArray::FCLIntArray(void* t, char* o, int s)
+  : Operation(o), size(s) { ClassStore=t; }
+
+FreeCheckLink* FreeCheck::next;
+int FreeCheck::BadDelete;
+
+void FCLClass::Report()
+{ cout << "   " << ClassName << "   " << (unsigned long)ClassStore << "\n"; }
+
+void FCLRealArray::Report()
+{
+   cout << "   " << Operation << "   " << (unsigned long)ClassStore <<
+      "   " << size << "\n";
+}
+
+void FCLIntArray::Report()
+{
+   cout << "   " << Operation << "   " << (unsigned long)ClassStore <<
+      "   " << size << "\n";
+}
+
+void FreeCheck::Register(void* t, char* name)
+{
+   FCLClass* f = new FCLClass(t,name);
+   if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
+#ifdef REG_DEREG
+   cout << "Registering   " << name << "   " << (unsigned long)t << "\n";
+#endif
+}
+
+void FreeCheck::RegisterR(void* t, char* o, int s)
+{
+   FCLRealArray* f = new FCLRealArray(t,o,s);
+   if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
+#ifdef REG_DEREG
+   cout << o << "   " << s << "   " << (unsigned long)t << "\n";
+#endif
+}
+
+void FreeCheck::RegisterI(void* t, char* o, int s)
+{
+   FCLIntArray* f = new FCLIntArray(t,o,s);
+   if (!f) { cout << "Out of memory in FreeCheck\n"; exit(1); }
+#ifdef REG_DEREG
+   cout << o << "   " << s << "   " << (unsigned long)t << "\n";
+#endif
+}
+
+void FreeCheck::DeRegister(void* t, char* name)
+{
+   FreeCheckLink* last = 0;
+#ifdef REG_DEREG
+   cout << "Deregistering " << name << "   " << (unsigned long)t << "\n";
+#endif
+   for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
+   {
+      if (fcl->ClassStore==t)
+      {
+	 if (last) last->next = fcl->next; else next = fcl->next;
+	 delete fcl; return;
+      }
+      last = fcl;
+   }
+   cout << "\nRequest to delete non-existent object of class and location:\n";
+   cout << "   " << name << "   " << (unsigned long)t << "\n";
+   BadDelete++;
+   Tracer::PrintTrace();
+   cout << "\n";
+}
+
+void FreeCheck::DeRegisterR(void* t, char* o, int s)
+{
+   FreeCheckLink* last = 0;
+#ifdef REG_DEREG
+   cout << o << "   " << s << "   " << (unsigned long)t << "\n";
+#endif
+   for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
+   {
+      if (fcl->ClassStore==t)
+      {
+	 if (last) last->next = fcl->next; else next = fcl->next;
+	 if (s >= 0 && ((FCLRealArray*)fcl)->size != s)
+	 {
+	    cout << "\nArray sizes do not agree:\n";
+	    cout << "   " << o << "   " << (unsigned long)t
+	       << "   " << ((FCLRealArray*)fcl)->size << "   " << s << "\n";
+	    Tracer::PrintTrace();
+	    cout << "\n";
+	 }
+	 delete fcl; return;
+      }
+      last = fcl;
+   }
+   cout << "\nRequest to delete non-existent real array:\n";
+   cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
+   BadDelete++;
+   Tracer::PrintTrace();
+   cout << "\n";
+}
+
+void FreeCheck::DeRegisterI(void* t, char* o, int s)
+{
+   FreeCheckLink* last = 0;
+#ifdef REG_DEREG
+   cout << o << "   " << s << "   " << (unsigned long)t << "\n";
+#endif
+   for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next)
+   {
+      if (fcl->ClassStore==t)
+      {
+	 if (last) last->next = fcl->next; else next = fcl->next;
+	 if (s >= 0 && ((FCLIntArray*)fcl)->size != s)
+	 {
+	    cout << "\nArray sizes do not agree:\n";
+	    cout << "   " << o << "   " << (unsigned long)t
+	       << "   " << ((FCLIntArray*)fcl)->size << "   " << s << "\n";
+	    Tracer::PrintTrace();
+	    cout << "\n";
+	 }
+	 delete fcl; return;
+      }
+      last = fcl;
+   }
+   cout << "\nRequest to delete non-existent int array:\n";
+   cout << "   " << o << "   " << (unsigned long)t << "   " << s << "\n";
+   BadDelete++;
+   Tracer::PrintTrace();
+   cout << "\n";
+}
+
+void FreeCheck::Status()
+{
+   if (next)
+   {
+      cout << "\nObjects of the following classes remain undeleted:\n";
+      for (FreeCheckLink* fcl = next; fcl; fcl = fcl->next) fcl->Report();
+      cout << "\n";
+   }
+   else cout << "\nNo objects remain undeleted\n\n";
+   if (BadDelete)
+   {
+      cout << "\nThere were " << BadDelete << 
+         " requests to delete non-existent items\n\n";
+   }
+}
+
+#endif                            // end of DO_FREE_CHECK
+
+// derived exception bodies
+
+Logic_error::Logic_error(const char* a_what) : BaseException()
+{
+   Select = BaseException::Select;
+   AddMessage("Logic error:- "); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Runtime_error::Runtime_error(const char* a_what)
+   : BaseException()
+{
+   Select = BaseException::Select;
+   AddMessage("Runtime error:- "); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Domain_error::Domain_error(const char* a_what) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("domain error\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Invalid_argument::Invalid_argument(const char* a_what) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("invalid argument\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Length_error::Length_error(const char* a_what) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("length error\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Out_of_range::Out_of_range(const char* a_what) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("out of range\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+//Bad_cast::Bad_cast(const char* a_what) : Logic_error()
+//{
+//   Select = BaseException::Select;
+//   AddMessage("bad cast\n"); AddMessage(a_what);
+//   if (a_what) Tracer::AddTrace();
+//}
+
+//Bad_typeid::Bad_typeid(const char* a_what) : Logic_error()
+//{
+//   Select = BaseException::Select;
+//   AddMessage("bad type id.\n"); AddMessage(a_what);
+//   if (a_what) Tracer::AddTrace();
+//}
+
+Range_error::Range_error(const char* a_what) : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("range error\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Overflow_error::Overflow_error(const char* a_what) : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("overflow error\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+Bad_alloc::Bad_alloc(const char* a_what) : BaseException()
+{
+   Select = BaseException::Select;
+   AddMessage("bad allocation\n"); AddMessage(a_what);
+   if (a_what) Tracer::AddTrace();
+}
+
+
+
+
+unsigned long Logic_error::Select;
+unsigned long Runtime_error::Select;
+unsigned long Domain_error::Select;
+unsigned long Invalid_argument::Select;
+unsigned long Length_error::Select;
+unsigned long Out_of_range::Select;
+//unsigned long Bad_cast::Select;
+//unsigned long Bad_typeid::Select;
+unsigned long Range_error::Select;
+unsigned long Overflow_error::Select;
+unsigned long Bad_alloc::Select;
+
+#ifdef use_namespace
+}
+#endif
+
+
+///@}
+
Index: trunk/BNC/newmat/myexcept.h
===================================================================
--- trunk/BNC/newmat/myexcept.h	(revision 2013)
+++ trunk/BNC/newmat/myexcept.h	(revision 2013)
@@ -0,0 +1,446 @@
+/// \ingroup rbd_common
+///@{
+
+/// \file myexcept.h
+/// Exception handler.
+/// The low level classes for
+/// - my exception class hierarchy
+/// - the functions needed for my simulated exceptions
+/// - the Tracer mechanism
+/// - routines for checking whether new and delete calls are balanced
+///
+
+
+// A set of classes to simulate exceptions in C++
+//
+//   Partially copied from Carlos Vidal s article in the C users  journal
+//   September 1992, pp 19-28
+//
+//   Operations defined
+//      Try {     }
+//      Throw ( exception object )
+//      ReThrow
+//      Catch ( exception class ) {      }
+//      CatchAll {      }
+//      CatchAndThrow
+//
+//   All catch lists must end with a CatchAll or CatchAndThrow statement
+//   but not both.
+//
+//   When exceptions are finally implemented replace Try, Throw(E), Rethrow,
+//   Catch, CatchAll, CatchAndThrow by try, throw E, throw, catch,
+//   catch(...), and {}.
+//
+//   All exception classes must be derived from BaseException, have no
+//   non-static variables and must include the statement
+//
+//      static unsigned long Select;
+//
+//   Any constructor in one of these exception classes must include
+//
+//      Select = BaseException::Select;
+//
+//   For each exceptions class, EX_1, some .cpp file must include
+//
+//      unsigned long EX_1::Select;
+//
+
+
+#ifndef EXCEPTION_LIB
+#define EXCEPTION_LIB
+
+#include "include.h"
+
+#ifdef use_namespace
+namespace RBD_COMMON {
+#endif
+
+
+void Terminate();
+
+
+//********** classes for setting up exceptions and reporting ************//
+
+class BaseException;
+
+class Tracer                             // linked list showing how
+{                                        // we got here
+   const char* entry;
+   Tracer* previous;
+public:
+   Tracer(const char*);
+   ~Tracer();
+   void ReName(const char*);
+   static void PrintTrace();             // for printing trace
+   static void AddTrace();               // insert trace in exception record
+   static Tracer* last;                  // points to Tracer list
+   friend class BaseException;
+};
+
+
+class BaseException                          // The base exception class
+{
+protected:
+   static char* what_error;              // error message
+   static int SoFar;                     // no. characters already entered
+   static int LastOne;                   // last location in error buffer
+public:
+   static void AddMessage(const char* a_what);
+                                         // messages about exception
+   static void AddInt(int value);        // integer to error message
+   static unsigned long Select;          // for identifying exception
+   BaseException(const char* a_what = 0);
+   static const char* what() { return what_error; }
+                                         // for getting error message
+};
+
+#ifdef TypeDefException
+typedef BaseException Exception;        // for compatibility with my older libraries
+#endif
+
+inline Tracer::Tracer(const char* e)
+   : entry(e), previous(last) { last = this; }
+
+inline Tracer::~Tracer() { last = previous; }
+
+inline void Tracer::ReName(const char* e) { entry=e; }
+
+#ifdef SimulateExceptions                // SimulateExceptions
+
+#include <setjmp.h>
+
+
+//************* the definitions of Try, Throw and Catch *****************//
+
+
+class JumpItem;
+class Janitor;
+
+class JumpBase         // pointer to a linked list of jmp_buf s
+{
+public:
+   static JumpItem *jl;
+   static jmp_buf env;
+};
+
+class JumpItem         // an item in a linked list of jmp_buf s
+{
+public:
+   JumpItem *ji;
+   jmp_buf env;
+   Tracer* trace;                     // to keep check on Tracer items
+   Janitor* janitor;                  // list of items for cleanup
+   JumpItem() : ji(JumpBase::jl), trace(0), janitor(0)
+      { JumpBase::jl = this; }
+   ~JumpItem() { JumpBase::jl = ji; }
+};
+
+void Throw();
+
+inline void Throw(const BaseException&) { Throw(); }
+
+#define Try                                             \
+   if (!setjmp( JumpBase::jl->env )) {                  \
+   JumpBase::jl->trace = Tracer::last;               \
+   JumpItem JI387256156;
+
+#define ReThrow Throw()
+
+#define Catch(EXCEPTION)                                \
+   } else if (BaseException::Select == EXCEPTION::Select) {
+
+#define CatchAll } else
+
+#define CatchAndThrow  } else Throw();
+
+
+//****************** cleanup heap following Throw ***********************//
+
+class Janitor
+{
+protected:
+   static bool do_not_link;                  // set when new is called
+   bool OnStack;                             // false if created by new
+public:
+   Janitor* NextJanitor;
+   virtual void CleanUp() {}
+   Janitor();
+   virtual ~Janitor();
+};
+
+
+// The tiresome old trick for initializing the Janitor class
+// this is needed for classes derived from Janitor which have objects
+// declared globally
+
+class JanitorInitializer
+{
+public:
+   JanitorInitializer();
+private:
+   static int ref_count;
+};
+
+static JanitorInitializer JanInit;
+
+#endif                                // end of SimulateExceptions
+
+#ifdef UseExceptions
+
+#define Try try
+#define Throw(E) throw E
+#define ReThrow throw
+#define Catch catch
+#define CatchAll catch(...)
+#define CatchAndThrow {}
+
+#endif                                // end of UseExceptions
+
+
+#ifdef DisableExceptions              // Disable exceptions
+
+#define Try {
+#define ReThrow Throw()
+#define Catch(EXCEPTION) } if (false) {
+#define CatchAll } if (false)
+#define CatchAndThrow }
+
+inline void Throw() { Terminate(); }
+inline void Throw(const BaseException&) { Terminate(); }
+
+
+#endif                                // end of DisableExceptions
+
+#ifndef SimulateExceptions            // ! SimulateExceptions
+
+class Janitor                         // a dummy version
+{
+public:
+   virtual void CleanUp() {}
+   Janitor() {}
+   virtual ~Janitor() {}
+};
+
+#endif                                // end of ! SimulateExceptions
+
+
+//******************** FREE_CHECK and NEW_DELETE ***********************//
+
+#ifdef DO_FREE_CHECK                          // DO_FREE_CHECK
+// Routines for tracing whether new and delete calls are balanced
+
+class FreeCheck;
+
+class FreeCheckLink
+{
+protected:
+   FreeCheckLink* next;
+   void* ClassStore;
+   FreeCheckLink();
+   virtual void Report()=0;                   // print details of link
+   friend class FreeCheck;
+};
+
+class FCLClass : public FreeCheckLink         // for registering objects
+{
+   char* ClassName;
+   FCLClass(void* t, char* name);
+   void Report();
+   friend class FreeCheck;
+};
+
+class FCLRealArray : public FreeCheckLink     // for registering real arrays
+{
+   char* Operation;
+   int size;
+   FCLRealArray(void* t, char* o, int s);
+   void Report();
+   friend class FreeCheck;
+};
+
+class FCLIntArray : public FreeCheckLink     // for registering int arrays
+{
+   char* Operation;
+   int size;
+   FCLIntArray(void* t, char* o, int s);
+   void Report();
+   friend class FreeCheck;
+};
+
+
+class FreeCheck
+{
+   static FreeCheckLink* next;
+   static int BadDelete;
+public:
+   static void Register(void*, char*);
+   static void DeRegister(void*, char*);
+   static void RegisterR(void*, char*, int);
+   static void DeRegisterR(void*, char*, int);
+   static void RegisterI(void*, char*, int);
+   static void DeRegisterI(void*, char*, int);
+   static void Status();
+   friend class FreeCheckLink;
+   friend class FCLClass;
+   friend class FCLRealArray;
+   friend class FCLIntArray;
+};
+
+#define FREE_CHECK(Class)                                                  \
+public:                                                                    \
+   void* operator new(size_t size)                                         \
+   {                                                                       \
+      void* t = ::operator new(size); FreeCheck::Register(t,#Class);       \
+      return t;                                                            \
+   }                                                                       \
+   void operator delete(void* t)                                           \
+   { FreeCheck::DeRegister(t,#Class); ::operator delete(t); }
+
+
+#ifdef SimulateExceptions         // SimulateExceptions
+
+#define NEW_DELETE(Class)                                                  \
+public:                                                                    \
+   void* operator new(size_t size)                                         \
+   {                                                                       \
+      do_not_link=true;                                                    \
+      void* t = ::operator new(size); FreeCheck::Register(t,#Class);       \
+      return t;                                                            \
+   }                                                                       \
+   void operator delete(void* t)                                           \
+   { FreeCheck::DeRegister(t,#Class); ::operator delete(t); }
+
+
+#endif                           // end of SimulateExceptions
+
+
+#define MONITOR_REAL_NEW(Operation, Size, Pointer)                         \
+	FreeCheck::RegisterR(Pointer, Operation, Size);
+#define MONITOR_INT_NEW(Operation, Size, Pointer)                          \
+	FreeCheck::RegisterI(Pointer, Operation, Size);
+#define MONITOR_REAL_DELETE(Operation, Size, Pointer)                      \
+	FreeCheck::DeRegisterR(Pointer, Operation, Size);
+#define MONITOR_INT_DELETE(Operation, Size, Pointer)                       \
+	FreeCheck::DeRegisterI(Pointer, Operation, Size);
+
+#else                            // DO_FREE_CHECK not defined
+
+#define FREE_CHECK(Class) public:
+#define MONITOR_REAL_NEW(Operation, Size, Pointer) {}
+#define MONITOR_INT_NEW(Operation, Size, Pointer) {}
+#define MONITOR_REAL_DELETE(Operation, Size, Pointer) {}
+#define MONITOR_INT_DELETE(Operation, Size, Pointer) {}
+
+
+#ifdef SimulateExceptions         // SimulateExceptions
+
+
+#define NEW_DELETE(Class)                                                  \
+public:                                                                    \
+	void* operator new(size_t size)                                    \
+	{ do_not_link=true; void* t = ::operator new(size); return t; }    \
+	void operator delete(void* t) { ::operator delete(t); }
+
+#endif                            // end of SimulateExceptions
+
+#endif                            // end of ! DO_FREE_CHECK
+
+#ifndef SimulateExceptions        // ! SimulateExceptions
+
+#define NEW_DELETE(Class) FREE_CHECK(Class)
+
+#endif                            // end of ! SimulateExceptions
+
+
+//********************* derived exceptions ******************************//
+
+class Logic_error : public BaseException
+{
+public:
+   static unsigned long Select;
+   Logic_error(const char* a_what = 0);
+};
+
+class Runtime_error : public BaseException
+{
+public:
+   static unsigned long Select;
+   Runtime_error(const char* a_what = 0);
+};
+
+class Domain_error : public Logic_error
+{
+public:
+   static unsigned long Select;
+   Domain_error(const char* a_what = 0);
+};
+
+class Invalid_argument : public Logic_error
+{
+public:
+   static unsigned long Select;
+   Invalid_argument(const char* a_what = 0);
+};
+
+class Length_error : public Logic_error
+{
+public:
+   static unsigned long Select;
+   Length_error(const char* a_what = 0);
+};
+
+class Out_of_range : public Logic_error
+{
+public:
+   static unsigned long Select;
+   Out_of_range(const char* a_what = 0);
+};
+
+//class Bad_cast : public Logic_error
+//{
+//public:
+//   static unsigned long Select;
+//   Bad_cast(const char* a_what = 0);
+//};
+
+//class Bad_typeid : public Logic_error
+//{
+//public:
+//   static unsigned long Select;
+//   Bad_typeid(const char* a_what = 0);
+//};
+
+class Range_error : public Runtime_error
+{
+public:
+   static unsigned long Select;
+   Range_error(const char* a_what = 0);
+};
+
+class Overflow_error : public Runtime_error
+{
+public:
+   static unsigned long Select;
+   Overflow_error(const char* a_what = 0);
+};
+
+class Bad_alloc : public BaseException
+{
+public:
+   static unsigned long Select;
+   Bad_alloc(const char* a_what = 0);
+};
+
+#ifdef use_namespace
+}
+#endif
+
+
+#endif                            // end of EXCEPTION_LIB
+
+
+// body file: myexcept.cpp
+
+
+///@}
+
Index: trunk/BNC/newmat/newfft.cpp
===================================================================
--- trunk/BNC/newmat/newfft.cpp	(revision 2013)
+++ trunk/BNC/newmat/newfft.cpp	(revision 2013)
@@ -0,0 +1,1065 @@
+/// \ingroup newmat
+///@{
+
+/// \file newfft.cpp
+/// Fast Fourier transform using Sande and Gentleman method.
+
+
+// This is originally by Sande and Gentleman in 1967! I have translated from
+// Fortran into C and a little bit of C++.
+
+// It takes about twice as long as fftw
+// (http://theory.lcs.mit.edu/~fftw/homepage.html)
+// but is much shorter than fftw  and so despite its age
+// might represent a reasonable
+// compromise between speed and complexity.
+// If you really need the speed get fftw.
+
+
+//    THIS SUBROUTINE WAS WRITTEN BY G.SANDE OF PRINCETON UNIVERSITY AND
+//    W.M.GENTLMAN OF THE BELL TELEPHONE LAB.  IT WAS BROUGHT TO LONDON
+//    BY DR. M.D. GODFREY AT THE IMPERIAL COLLEGE AND WAS ADAPTED FOR
+//    BURROUGHS 6700 BY D. R. BRILLINGER AND J. PEMBERTON
+//    IT REPRESENTS THE STATE OF THE ART OF COMPUTING COMPLETE FINITE
+//    DISCRETE FOURIER TRANSFORMS AS OF NOV.1967.
+//    OTHER PROGRAMS REQUIRED.
+//                                 ONLY THOSE SUBROUTINES INCLUDED HERE.
+//                      USAGE.
+//       CALL AR1DFT(N,X,Y)
+//            WHERE  N IS THE NUMBER OF POINTS IN THE SEQUENCE .
+//                   X - IS A ONE-DIMENSIONAL ARRAY CONTAINING THE REAL
+//                       PART OF THE SEQUENCE.
+//                   Y - IS A ONE-DIMENSIONAL ARRAY CONTAINING THE
+//                       IMAGINARY PART OF THE SEQUENCE.
+//    THE TRANSFORM IS RETURNED IN X AND Y.
+//            METHOD
+//               FOR A GENERAL DISCUSSION OF THESE TRANSFORMS AND OF
+//    THE FAST METHOD FOR COMPUTING THEM, SEE GENTLEMAN AND SANDE,
+//    @FAST FOURIER TRANSFORMS - FOR FUN AND PROFIT,@ 1966 FALL JOINT
+//    COMPUTER CONFERENCE.
+//    THIS PROGRAM COMPUTES THIS FOR A COMPLEX SEQUENCE Z(T) OF LENGTH
+//    N WHOSE ELEMENTS ARE STORED AT(X(I) , Y(I)) AND RETURNS THE
+//    TRANSFORM COEFFICIENTS AT (X(I), Y(I)).
+//        DESCRIPTION
+//    AR1DFT IS A HIGHLY MODULAR ROUTINE CAPABLE OF COMPUTING IN PLACE
+//    THE COMPLETE FINITE DISCRETE FOURIER TRANSFORM  OF A ONE-
+//    DIMENSIONAL SEQUENCE OF RATHER GENERAL LENGTH N.
+//       THE MAIN ROUTINE , AR1DFT ITSELF, FACTORS N. IT THEN CALLS ON
+//    ON GR 1D FT TO COMPUTE THE ACTUAL TRANSFORMS, USING THESE FACTORS.
+//    THIS GR 1D FT DOES, CALLING AT EACH STAGE ON THE APPROPRIATE KERN
+//    EL R2FTK, R4FTK, R8FTK, R16FTK, R3FTK, R5FTK, OR RPFTK TO PERFORM
+//    THE COMPUTATIONS FOR THIS PASS OVER THE SEQUENCE, DEPENDING ON
+//    WHETHER THE CORRESPONDING FACTOR IS 2, 4, 8, 16, 3, 5, OR SOME
+//    MORE GENERAL PRIME P. WHEN GR1DFT IS FINISHED THE TRANSFORM IS
+//    COMPUTED, HOWEVER, THE RESULTS ARE STORED IN "DIGITS REVERSED"
+//    ORDER. AR1DFT THEREFORE, CALLS UPON GR 1S FS TO SORT THEM OUT.
+//    TO RETURN TO THE FACTORIZATION, SINGLETON HAS POINTED OUT THAT
+//    THE TRANSFORMS ARE MORE EFFICIENT IF THE SAMPLE SIZE N, IS OF THE
+//    FORM B*A**2 AND B CONSISTS OF A SINGLE FACTOR.  IN SUCH A CASE
+//    IF WE PROCESS THE FACTORS IN THE ORDER ABA  THEN
+//    THE REORDERING CAN BE DONE AS FAST IN PLACE, AS WITH SCRATCH
+//    STORAGE.  BUT AS B BECOMES MORE COMPLICATED, THE COST OF THE DIGIT
+//    REVERSING DUE TO B PART BECOMES VERY EXPENSIVE IF WE TRY TO DO IT
+//    IN PLACE.  IN SUCH A CASE IT MIGHT BE BETTER TO USE EXTRA STORAGE
+//    A ROUTINE TO DO THIS IS, HOWEVER, NOT INCLUDED HERE.
+//    ANOTHER FEATURE INFLUENCING THE FACTORIZATION IS THAT FOR ANY FIXED
+//    FACTOR N WE CAN PREPARE A SPECIAL KERNEL WHICH WILL COMPUTE
+//    THAT STAGE OF THE TRANSFORM MORE EFFICIENTLY THAN WOULD A KERNEL
+//    FOR GENERAL FACTORS, ESPECIALLY IF THE GENERAL KERNEL HAD TO BE
+//    APPLIED SEVERAL TIMES. FOR EXAMPLE, FACTORS OF 4 ARE MORE
+//    EFFICIENT THAN FACTORS OF 2, FACTORS OF 8 MORE EFFICIENT THAN 4,ETC
+//    ON THE OTHER HAND DIMINISHING RETURNS RAPIDLY SET IN, ESPECIALLY
+//    SINCE THE LENGTH OF THE KERNEL FOR A SPECIAL CASE IS ROUGHLY
+//    PROPORTIONAL TO THE FACTOR IT DEALS WITH. HENCE THESE PROBABLY ARE
+//    ALL THE KERNELS WE WISH TO HAVE.
+//            RESTRICTIONS.
+//    AN UNFORTUNATE FEATURE OF THE SORTING PROBLEM IS THAT THE MOST
+//    EFFICIENT WAY TO DO IT IS WITH NESTED DO LOOPS, ONE FOR EACH
+//    FACTOR. THIS PUTS A RESTRICTION ON N AS TO HOW MANY FACTORS IT
+//    CAN HAVE.  CURRENTLY THE LIMIT IS 16, BUT THE LIMIT CAN BE READILY
+//    RAISED IF NECESSARY.
+//    A SECOND RESTRICTION OF THE PROGRAM IS THAT LOCAL STORAGE OF THE
+//    THE ORDER P**2 IS REQUIRED BY THE GENERAL KERNEL RPFTK, SO SOME
+//    LIMIT MUST BE SET ON P.  CURRENTLY THIS IS 19, BUT IT CAN BE INCRE
+//    INCREASED BY TRIVIAL CHANGES.
+//       OTHER COMMENTS.
+//(1) THE ROUTINE IS ADAPTED TO CHECK WHETHER A GIVEN N WILL MEET THE
+//    ABOVE FACTORING REQUIREMENTS AN, IF NOT, TO RETURN THE NEXT HIGHER
+//    NUMBER, NX, SAY, WHICH WILL MEET THESE REQUIREMENTS.
+//    THIS CAN BE ACCHIEVED BY   A STATEMENT OF THE FORM
+//            CALL FACTR(N,X,Y).
+//    IF A DIFFERENT N, SAY NX, IS RETURNED THEN THE TRANSFORMS COULD BE
+//    OBTAINED BY EXTENDING THE SIZE OF THE X-ARRAY AND Y-ARRAY TO NX,
+//    AND SETTING X(I) = Y(I) = 0., FOR I = N+1, NX.
+//(2) IF THE SEQUENCE Z IS ONLY A REAL SEQUENCE, THEN THE IMAGINARY PART
+//    Y(I)=0., THIS WILL RETURN THE COSINE TRANSFORM OF THE REAL SEQUENCE
+//    IN X, AND THE SINE TRANSFORM IN Y.
+
+
+#define WANT_STREAM
+
+#define WANT_MATH
+
+#include "newmatap.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,20); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+inline Real square(Real x) { return x*x; }
+inline int square(int x) { return x*x; }
+
+static void GR_1D_FS (int PTS, int N_SYM, int N_UN_SYM,
+   const SimpleIntArray& SYM, int P_SYM, const SimpleIntArray& UN_SYM,
+   Real* X, Real* Y);
+static void GR_1D_FT (int N, int N_FACTOR, const SimpleIntArray& FACTOR,
+   Real* X, Real* Y);
+static void R_P_FTK (int N, int M, int P, Real* X, Real* Y);
+static void R_2_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1);
+static void R_3_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2);
+static void R_4_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3);
+static void R_5_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1, Real* X2, Real* Y2,
+   Real* X3, Real* Y3, Real* X4, Real* Y4);
+static void R_8_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3,
+   Real* X4, Real* Y4, Real* X5, Real* Y5,
+   Real* X6, Real* Y6, Real* X7, Real* Y7);
+static void R_16_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3,
+   Real* X4, Real* Y4, Real* X5, Real* Y5,
+   Real* X6, Real* Y6, Real* X7, Real* Y7,
+   Real* X8, Real* Y8, Real* X9, Real* Y9,
+   Real* X10, Real* Y10, Real* X11, Real* Y11,
+   Real* X12, Real* Y12, Real* X13, Real* Y13,
+   Real* X14, Real* Y14, Real* X15, Real* Y15);
+static int BitReverse(int x, int prod, int n, const SimpleIntArray& f);
+
+
+bool FFT_Controller::ar_1d_ft (int PTS, Real* X, Real *Y)
+{
+//    ARBITRARY RADIX ONE DIMENSIONAL FOURIER TRANSFORM
+
+   REPORT
+
+   int  F,J,N,NF,P,PMAX,P_SYM,P_TWO,Q,R,TWO_GRP;
+
+   // NP is maximum number of squared factors allows PTS up to 2**32 at least
+   // NQ is number of not-squared factors - increase if we increase PMAX
+   const int NP = 16, NQ = 10;
+   SimpleIntArray PP(NP), QQ(NQ);
+
+   TWO_GRP=16; PMAX=19;
+
+   // PMAX is the maximum factor size
+   // TWO_GRP is the maximum power of 2 handled as a single factor
+   // Doesn't take advantage of combining powers of 2 when calculating
+   // number of factors
+
+   if (PTS<=1) return true;
+   N=PTS; P_SYM=1; F=2; P=0; Q=0;
+
+   // P counts the number of squared factors
+   // Q counts the number of the rest
+   // R = 0 for no non-squared factors; 1 otherwise
+
+   // FACTOR holds all the factors - non-squared ones in the middle
+   //   - length is 2*P+Q
+   // SYM also holds all the factors but with the non-squared ones
+   //   multiplied together - length is 2*P+R
+   // PP holds the values of the squared factors - length is P
+   // QQ holds the values of the rest - length is Q
+
+   // P_SYM holds the product of the squared factors
+
+   // find the factors - load into PP and QQ
+   while (N > 1)
+   {
+      bool fail = true;
+      for (J=F; J<=PMAX; J++)
+         if (N % J == 0) { fail = false; F=J; break; }
+      if (fail || P >= NP || Q >= NQ) return false; // can't factor
+      N /= F;
+      if (N % F != 0) QQ[Q++] = F;
+      else { N /= F; PP[P++] = F; P_SYM *= F; }
+   }
+
+   R = (Q == 0) ? 0 : 1;  // R = 0 if no not-squared factors, 1 otherwise
+
+   NF = 2*P + Q;
+   SimpleIntArray FACTOR(NF + 1), SYM(2*P + R);
+   FACTOR[NF] = 0;                // we need this in the "combine powers of 2"
+
+   // load into SYM and FACTOR
+   for (J=0; J<P; J++)
+      { SYM[J]=FACTOR[J]=PP[P-1-J]; FACTOR[P+Q+J]=SYM[P+R+J]=PP[J]; }
+
+   if (Q>0)
+   {
+      REPORT
+      for (J=0; J<Q; J++) FACTOR[P+J]=QQ[J];
+      SYM[P]=PTS/square(P_SYM);
+   }
+
+   // combine powers of 2
+   P_TWO = 1;
+   for (J=0; J < NF; J++)
+   {
+      if (FACTOR[J]!=2) continue;
+      P_TWO=P_TWO*2; FACTOR[J]=1;
+      if (P_TWO<TWO_GRP && FACTOR[J+1]==2) continue;
+      FACTOR[J]=P_TWO; P_TWO=1;
+   }
+
+   if (P==0) R=0;
+   if (Q<=1) Q=0;
+
+   // do the analysis
+   GR_1D_FT(PTS,NF,FACTOR,X,Y);                 // the transform
+   GR_1D_FS(PTS,2*P+R,Q,SYM,P_SYM,QQ,X,Y);      // the reshuffling
+
+   return true;
+
+}
+
+static void GR_1D_FS (int PTS, int N_SYM, int N_UN_SYM,
+   const SimpleIntArray& SYM, int P_SYM, const SimpleIntArray& UN_SYM,
+   Real* X, Real* Y)
+{
+//    GENERAL RADIX ONE DIMENSIONAL FOURIER SORT
+
+// PTS = number of points
+// N_SYM = length of SYM
+// N_UN_SYM = length of UN_SYM
+// SYM: squared factors + product of non-squared factors + squared factors
+// P_SYM = product of squared factors (each included only once)
+// UN_SYM: not-squared factors
+
+   REPORT
+
+   Real T;
+   int  JJ,KK,P_UN_SYM;
+
+   // I have replaced the multiple for-loop used by Sande-Gentleman code
+   // by the following code which does not limit the number of factors
+
+   if (N_SYM > 0)
+   {
+      REPORT
+      SimpleIntArray U(N_SYM);
+      for(MultiRadixCounter MRC(N_SYM, SYM, U); !MRC.Finish(); ++MRC)
+      {
+         if (MRC.Swap())
+         {
+            int P = MRC.Reverse(); int JJ = MRC.Counter(); Real T;
+            T=X[JJ]; X[JJ]=X[P]; X[P]=T; T=Y[JJ]; Y[JJ]=Y[P]; Y[P]=T;
+         }
+      }
+   }
+
+   int J,JL,K,L,M,MS;
+
+   // UN_SYM contains the non-squared factors
+   // I have replaced the Sande-Gentleman code as it runs into
+   // integer overflow problems
+   // My code (and theirs) would be improved by using a bit array
+   // as suggested by Van Loan
+
+   if (N_UN_SYM==0) { REPORT return; }
+   P_UN_SYM=PTS/square(P_SYM); JL=(P_UN_SYM-3)*P_SYM; MS=P_UN_SYM*P_SYM;
+
+   for (J = P_SYM; J<=JL; J+=P_SYM)
+   {
+      K=J;
+      do K = P_SYM * BitReverse(K / P_SYM, P_UN_SYM, N_UN_SYM, UN_SYM);
+      while (K<J);
+
+      if (K!=J)
+      {
+         REPORT
+         for (L=0; L<P_SYM; L++) for (M=L; M<PTS; M+=MS)
+         {
+            JJ=M+J; KK=M+K;
+            T=X[JJ]; X[JJ]=X[KK]; X[KK]=T; T=Y[JJ]; Y[JJ]=Y[KK]; Y[KK]=T;
+         }
+      }
+   }
+
+   return;
+}
+
+static void GR_1D_FT (int N, int N_FACTOR, const SimpleIntArray& FACTOR,
+   Real* X, Real* Y)
+{
+//    GENERAL RADIX ONE DIMENSIONAL FOURIER TRANSFORM;
+
+   REPORT
+
+   int  M = N;
+
+   for (int i = 0; i < N_FACTOR; i++)
+   {
+      int P = FACTOR[i]; M /= P;
+
+      switch(P)
+      {
+      case 1: REPORT break;
+      case 2: REPORT R_2_FTK (N,M,X,Y,X+M,Y+M); break;
+      case 3: REPORT R_3_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M); break;
+      case 4: REPORT R_4_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,X+3*M,Y+3*M); break;
+      case 5:
+         REPORT
+         R_5_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,X+3*M,Y+3*M,X+4*M,Y+4*M);
+         break;
+      case 8:
+         REPORT
+         R_8_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,
+            X+3*M,Y+3*M,X+4*M,Y+4*M,X+5*M,Y+5*M,
+            X+6*M,Y+6*M,X+7*M,Y+7*M);
+         break;
+      case 16:
+         REPORT
+         R_16_FTK (N,M,X,Y,X+M,Y+M,X+2*M,Y+2*M,
+            X+3*M,Y+3*M,X+4*M,Y+4*M,X+5*M,Y+5*M,
+            X+6*M,Y+6*M,X+7*M,Y+7*M,X+8*M,Y+8*M,
+            X+9*M,Y+9*M,X+10*M,Y+10*M,X+11*M,Y+11*M,
+            X+12*M,Y+12*M,X+13*M,Y+13*M,X+14*M,Y+14*M,
+            X+15*M,Y+15*M);
+         break;
+      default: REPORT R_P_FTK (N,M,P,X,Y); break;
+      }
+   }
+
+}
+
+static void R_P_FTK (int N, int M, int P, Real* X, Real* Y)
+//    RADIX PRIME FOURIER TRANSFORM KERNEL;
+// X and Y are treated as M * P matrices with Fortran storage
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   Real ANGLE,IS,IU,RS,RU,T,TWOPI,XT,YT;
+   int  J,JJ,K0,K,M_OVER_2,MP,PM,PP,U,V;
+
+   Real AA [9][9], BB [9][9];
+   Real A [18], B [18], C [18], S [18];
+   Real IA [9], IB [9], RA [9], RB [9];
+
+   TWOPI=8.0*atan(1.0);
+   M_OVER_2=M/2+1; MP=M*P; PP=P/2; PM=P-1;
+
+   for (U=0; U<PP; U++)
+   {
+      ANGLE=TWOPI*Real(U+1)/Real(P);
+      JJ=P-U-2;
+      A[U]=cos(ANGLE); B[U]=sin(ANGLE);
+      A[JJ]=A[U]; B[JJ]= -B[U];
+   }
+
+   for (U=1; U<=PP; U++)
+   {
+      for (V=1; V<=PP; V++)
+         { JJ=U*V-U*V/P*P; AA[V-1][U-1]=A[JJ-1]; BB[V-1][U-1]=B[JJ-1]; }
+   }
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(MP); ZERO=ANGLE==0.0;
+      C[0]=cos(ANGLE); S[0]=sin(ANGLE);
+      for (U=1; U<PM; U++)
+      {
+         C[U]=C[U-1]*C[0]-S[U-1]*S[0];
+         S[U]=S[U-1]*C[0]+C[U-1]*S[0];
+      }
+      goto L700;
+   L500:
+      REPORT
+      if (NO_FOLD) { REPORT goto L1500; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      for (U=0; U<PM; U++)
+         { T=C[U]*A[U]+S[U]*B[U]; S[U]= -S[U]*A[U]+C[U]*B[U]; C[U]=T; }
+   L700:
+      REPORT
+      for (K=K0; K<N; K+=MP)
+      {
+         XT=X[K]; YT=Y[K];
+         for (U=1; U<=PP; U++)
+         {
+            RA[U-1]=XT; IA[U-1]=YT;
+            RB[U-1]=0.0; IB[U-1]=0.0;
+         }
+         for (U=1; U<=PP; U++)
+         {
+            JJ=P-U;
+            RS=X[K+M*U]+X[K+M*JJ]; IS=Y[K+M*U]+Y[K+M*JJ];
+            RU=X[K+M*U]-X[K+M*JJ]; IU=Y[K+M*U]-Y[K+M*JJ];
+            XT=XT+RS; YT=YT+IS;
+            for (V=0; V<PP; V++)
+            {
+               RA[V]=RA[V]+RS*AA[V][U-1]; IA[V]=IA[V]+IS*AA[V][U-1];
+               RB[V]=RB[V]+RU*BB[V][U-1]; IB[V]=IB[V]+IU*BB[V][U-1];
+            }
+         }
+         X[K]=XT; Y[K]=YT;
+         for (U=1; U<=PP; U++)
+         {
+            if (!ZERO)
+            {
+               REPORT
+               XT=RA[U-1]+IB[U-1]; YT=IA[U-1]-RB[U-1];
+               X[K+M*U]=XT*C[U-1]+YT*S[U-1]; Y[K+M*U]=YT*C[U-1]-XT*S[U-1];
+               JJ=P-U;
+               XT=RA[U-1]-IB[U-1]; YT=IA[U-1]+RB[U-1];
+               X[K+M*JJ]=XT*C[JJ-1]+YT*S[JJ-1];
+               Y[K+M*JJ]=YT*C[JJ-1]-XT*S[JJ-1];
+            }
+            else
+            {
+               REPORT
+               X[K+M*U]=RA[U-1]+IB[U-1]; Y[K+M*U]=IA[U-1]-RB[U-1];
+               JJ=P-U;
+               X[K+M*JJ]=RA[U-1]-IB[U-1]; Y[K+M*JJ]=IA[U-1]+RB[U-1];
+            }
+         }
+      }
+      goto L500;
+L1500: ;
+   }
+   return;
+}
+
+static void R_2_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1)
+//    RADIX TWO FOURIER TRANSFORM KERNEL;
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M2,M_OVER_2;
+   Real ANGLE,C,IS,IU,RS,RU,S,TWOPI;
+
+   M2=M*2; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M2); ZERO=ANGLE==0.0;
+      C=cos(ANGLE); S=sin(ANGLE);
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J; C= -C;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M2)
+      {
+         RS=X0[K]+X1[K]; IS=Y0[K]+Y1[K];
+         RU=X0[K]-X1[K]; IU=Y0[K]-Y1[K];
+         X0[K]=RS; Y0[K]=IS;
+         if (!ZERO) { X1[K]=RU*C+IU*S; Y1[K]=IU*C-RU*S; }
+         else { X1[K]=RU; Y1[K]=IU; }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_3_FTK (int N, int M, Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2)
+//    RADIX THREE FOURIER TRANSFORM KERNEL
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M3,M_OVER_2;
+   Real ANGLE,A,B,C1,C2,S1,S2,T,TWOPI;
+   Real I0,I1,I2,IA,IB,IS,R0,R1,R2,RA,RB,RS;
+
+   M3=M*3; M_OVER_2=M/2+1; TWOPI=8.0*atan(1.0);
+   A=cos(TWOPI/3.0); B=sin(TWOPI/3.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M3); ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=S1*C1+C1*S1;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=C1*A+S1*B; S1=C1*B-S1*A; C1=T;
+      T=C2*A-S2*B; S2= -C2*B-S2*A; C2=T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M3)
+      {
+         R0 = X0[K]; I0 = Y0[K];
+         RS=X1[K]+X2[K]; IS=Y1[K]+Y2[K];
+         X0[K]=R0+RS; Y0[K]=I0+IS;
+         RA=R0+RS*A; IA=I0+IS*A;
+         RB=(X1[K]-X2[K])*B; IB=(Y1[K]-Y2[K])*B;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RA+IB; I1=IA-RB; R2=RA-IB; I2=IA+RB;
+            X1[K]=R1*C1+I1*S1; Y1[K]=I1*C1-R1*S1;
+            X2[K]=R2*C2+I2*S2; Y2[K]=I2*C2-R2*S2;
+         }
+         else { REPORT X1[K]=RA+IB; Y1[K]=IA-RB; X2[K]=RA-IB; Y2[K]=IA+RB; }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_4_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3)
+//    RADIX FOUR FOURIER TRANSFORM KERNEL
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M4,M_OVER_2;
+   Real ANGLE,C1,C2,C3,S1,S2,S3,T,TWOPI;
+   Real I1,I2,I3,IS0,IS1,IU0,IU1,R1,R2,R3,RS0,RS1,RU0,RU1;
+
+   M4=M*4; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M4); ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=S1*C1+C1*S1;
+      C3=C2*C1-S2*S1; S3=S2*C1+C2*S1;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=C1; C1=S1; S1=T;
+      C2= -C2;
+      T=C3; C3= -S3; S3= -T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M4)
+      {
+         RS0=X0[K]+X2[K]; IS0=Y0[K]+Y2[K];
+         RU0=X0[K]-X2[K]; IU0=Y0[K]-Y2[K];
+         RS1=X1[K]+X3[K]; IS1=Y1[K]+Y3[K];
+         RU1=X1[K]-X3[K]; IU1=Y1[K]-Y3[K];
+         X0[K]=RS0+RS1; Y0[K]=IS0+IS1;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RU0+IU1; I1=IU0-RU1;
+            R2=RS0-RS1; I2=IS0-IS1;
+            R3=RU0-IU1; I3=IU0+RU1;
+            X2[K]=R1*C1+I1*S1; Y2[K]=I1*C1-R1*S1;
+            X1[K]=R2*C2+I2*S2; Y1[K]=I2*C2-R2*S2;
+            X3[K]=R3*C3+I3*S3; Y3[K]=I3*C3-R3*S3;
+         }
+         else
+         {
+            REPORT
+            X2[K]=RU0+IU1; Y2[K]=IU0-RU1;
+            X1[K]=RS0-RS1; Y1[K]=IS0-IS1;
+            X3[K]=RU0-IU1; Y3[K]=IU0+RU1;
+         }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_5_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1, Real* X2, Real* Y2,
+   Real* X3, Real* Y3, Real* X4, Real* Y4)
+//    RADIX FIVE FOURIER TRANSFORM KERNEL
+
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M5,M_OVER_2;
+   Real ANGLE,A1,A2,B1,B2,C1,C2,C3,C4,S1,S2,S3,S4,T,TWOPI;
+   Real R0,R1,R2,R3,R4,RA1,RA2,RB1,RB2,RS1,RS2,RU1,RU2;
+   Real I0,I1,I2,I3,I4,IA1,IA2,IB1,IB2,IS1,IS2,IU1,IU2;
+
+   M5=M*5; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0);
+   A1=cos(TWOPI/5.0); B1=sin(TWOPI/5.0);
+   A2=cos(2.0*TWOPI/5.0); B2=sin(2.0*TWOPI/5.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M5); ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=S1*C1+C1*S1;
+      C3=C2*C1-S2*S1; S3=S2*C1+C2*S1;
+      C4=C2*C2-S2*S2; S4=S2*C2+C2*S2;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=C1*A1+S1*B1; S1=C1*B1-S1*A1; C1=T;
+      T=C2*A2+S2*B2; S2=C2*B2-S2*A2; C2=T;
+      T=C3*A2-S3*B2; S3= -C3*B2-S3*A2; C3=T;
+      T=C4*A1-S4*B1; S4= -C4*B1-S4*A1; C4=T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M5)
+      {
+         R0=X0[K]; I0=Y0[K];
+         RS1=X1[K]+X4[K]; IS1=Y1[K]+Y4[K];
+         RU1=X1[K]-X4[K]; IU1=Y1[K]-Y4[K];
+         RS2=X2[K]+X3[K]; IS2=Y2[K]+Y3[K];
+         RU2=X2[K]-X3[K]; IU2=Y2[K]-Y3[K];
+         X0[K]=R0+RS1+RS2; Y0[K]=I0+IS1+IS2;
+         RA1=R0+RS1*A1+RS2*A2; IA1=I0+IS1*A1+IS2*A2;
+         RA2=R0+RS1*A2+RS2*A1; IA2=I0+IS1*A2+IS2*A1;
+         RB1=RU1*B1+RU2*B2; IB1=IU1*B1+IU2*B2;
+         RB2=RU1*B2-RU2*B1; IB2=IU1*B2-IU2*B1;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RA1+IB1; I1=IA1-RB1;
+            R2=RA2+IB2; I2=IA2-RB2;
+            R3=RA2-IB2; I3=IA2+RB2;
+            R4=RA1-IB1; I4=IA1+RB1;
+            X1[K]=R1*C1+I1*S1; Y1[K]=I1*C1-R1*S1;
+            X2[K]=R2*C2+I2*S2; Y2[K]=I2*C2-R2*S2;
+            X3[K]=R3*C3+I3*S3; Y3[K]=I3*C3-R3*S3;
+            X4[K]=R4*C4+I4*S4; Y4[K]=I4*C4-R4*S4;
+         }
+         else
+         {
+            REPORT
+            X1[K]=RA1+IB1; Y1[K]=IA1-RB1;
+            X2[K]=RA2+IB2; Y2[K]=IA2-RB2;
+            X3[K]=RA2-IB2; Y3[K]=IA2+RB2;
+            X4[K]=RA1-IB1; Y4[K]=IA1+RB1;
+         }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_8_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3,
+   Real* X4, Real* Y4, Real* X5, Real* Y5,
+   Real* X6, Real* Y6, Real* X7, Real* Y7)
+//    RADIX EIGHT FOURIER TRANSFORM KERNEL
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M8,M_OVER_2;
+   Real ANGLE,C1,C2,C3,C4,C5,C6,C7,E,S1,S2,S3,S4,S5,S6,S7,T,TWOPI;
+   Real R1,R2,R3,R4,R5,R6,R7,RS0,RS1,RS2,RS3,RU0,RU1,RU2,RU3;
+   Real I1,I2,I3,I4,I5,I6,I7,IS0,IS1,IS2,IS3,IU0,IU1,IU2,IU3;
+   Real RSS0,RSS1,RSU0,RSU1,RUS0,RUS1,RUU0,RUU1;
+   Real ISS0,ISS1,ISU0,ISU1,IUS0,IUS1,IUU0,IUU1;
+
+   M8=M*8; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0); E=cos(TWOPI/8.0);
+
+   for (J=0;J<M_OVER_2;J++)
+   {
+      NO_FOLD= (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M8); ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=C1*S1+S1*C1;
+      C3=C2*C1-S2*S1; S3=S2*C1+C2*S1;
+      C4=C2*C2-S2*S2; S4=S2*C2+C2*S2;
+      C5=C4*C1-S4*S1; S5=S4*C1+C4*S1;
+      C6=C4*C2-S4*S2; S6=S4*C2+C4*S2;
+      C7=C4*C3-S4*S3; S7=S4*C3+C4*S3;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=(C1+S1)*E; S1=(C1-S1)*E; C1=T;
+      T=S2; S2=C2; C2=T;
+      T=(-C3+S3)*E; S3=(C3+S3)*E; C3=T;
+      C4= -C4;
+      T= -(C5+S5)*E; S5=(-C5+S5)*E; C5=T;
+      T= -S6; S6= -C6; C6=T;
+      T=(C7-S7)*E; S7= -(C7+S7)*E; C7=T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M8)
+      {
+         RS0=X0[K]+X4[K]; IS0=Y0[K]+Y4[K];
+         RU0=X0[K]-X4[K]; IU0=Y0[K]-Y4[K];
+         RS1=X1[K]+X5[K]; IS1=Y1[K]+Y5[K];
+         RU1=X1[K]-X5[K]; IU1=Y1[K]-Y5[K];
+         RS2=X2[K]+X6[K]; IS2=Y2[K]+Y6[K];
+         RU2=X2[K]-X6[K]; IU2=Y2[K]-Y6[K];
+         RS3=X3[K]+X7[K]; IS3=Y3[K]+Y7[K];
+         RU3=X3[K]-X7[K]; IU3=Y3[K]-Y7[K];
+         RSS0=RS0+RS2; ISS0=IS0+IS2;
+         RSU0=RS0-RS2; ISU0=IS0-IS2;
+         RSS1=RS1+RS3; ISS1=IS1+IS3;
+         RSU1=RS1-RS3; ISU1=IS1-IS3;
+         RUS0=RU0-IU2; IUS0=IU0+RU2;
+         RUU0=RU0+IU2; IUU0=IU0-RU2;
+         RUS1=RU1-IU3; IUS1=IU1+RU3;
+         RUU1=RU1+IU3; IUU1=IU1-RU3;
+         T=(RUS1+IUS1)*E; IUS1=(IUS1-RUS1)*E; RUS1=T;
+         T=(RUU1+IUU1)*E; IUU1=(IUU1-RUU1)*E; RUU1=T;
+         X0[K]=RSS0+RSS1; Y0[K]=ISS0+ISS1;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RUU0+RUU1; I1=IUU0+IUU1;
+            R2=RSU0+ISU1; I2=ISU0-RSU1;
+            R3=RUS0+IUS1; I3=IUS0-RUS1;
+            R4=RSS0-RSS1; I4=ISS0-ISS1;
+            R5=RUU0-RUU1; I5=IUU0-IUU1;
+            R6=RSU0-ISU1; I6=ISU0+RSU1;
+            R7=RUS0-IUS1; I7=IUS0+RUS1;
+            X4[K]=R1*C1+I1*S1; Y4[K]=I1*C1-R1*S1;
+            X2[K]=R2*C2+I2*S2; Y2[K]=I2*C2-R2*S2;
+            X6[K]=R3*C3+I3*S3; Y6[K]=I3*C3-R3*S3;
+            X1[K]=R4*C4+I4*S4; Y1[K]=I4*C4-R4*S4;
+            X5[K]=R5*C5+I5*S5; Y5[K]=I5*C5-R5*S5;
+            X3[K]=R6*C6+I6*S6; Y3[K]=I6*C6-R6*S6;
+            X7[K]=R7*C7+I7*S7; Y7[K]=I7*C7-R7*S7;
+         }
+         else
+         {
+            REPORT
+            X4[K]=RUU0+RUU1; Y4[K]=IUU0+IUU1;
+            X2[K]=RSU0+ISU1; Y2[K]=ISU0-RSU1;
+            X6[K]=RUS0+IUS1; Y6[K]=IUS0-RUS1;
+            X1[K]=RSS0-RSS1; Y1[K]=ISS0-ISS1;
+            X5[K]=RUU0-RUU1; Y5[K]=IUU0-IUU1;
+            X3[K]=RSU0-ISU1; Y3[K]=ISU0+RSU1;
+            X7[K]=RUS0-IUS1; Y7[K]=IUS0+RUS1;
+         }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+static void R_16_FTK (int N, int M,
+   Real* X0, Real* Y0, Real* X1, Real* Y1,
+   Real* X2, Real* Y2, Real* X3, Real* Y3,
+   Real* X4, Real* Y4, Real* X5, Real* Y5,
+   Real* X6, Real* Y6, Real* X7, Real* Y7,
+   Real* X8, Real* Y8, Real* X9, Real* Y9,
+   Real* X10, Real* Y10, Real* X11, Real* Y11,
+   Real* X12, Real* Y12, Real* X13, Real* Y13,
+   Real* X14, Real* Y14, Real* X15, Real* Y15)
+//    RADIX SIXTEEN FOURIER TRANSFORM KERNEL
+{
+   REPORT
+   bool NO_FOLD,ZERO;
+   int  J,K,K0,M16,M_OVER_2;
+   Real ANGLE,EI1,ER1,E2,EI3,ER3,EI5,ER5,T,TWOPI;
+   Real RS0,RS1,RS2,RS3,RS4,RS5,RS6,RS7;
+   Real IS0,IS1,IS2,IS3,IS4,IS5,IS6,IS7;
+   Real RU0,RU1,RU2,RU3,RU4,RU5,RU6,RU7;
+   Real IU0,IU1,IU2,IU3,IU4,IU5,IU6,IU7;
+   Real RUS0,RUS1,RUS2,RUS3,RUU0,RUU1,RUU2,RUU3;
+   Real ISS0,ISS1,ISS2,ISS3,ISU0,ISU1,ISU2,ISU3;
+   Real RSS0,RSS1,RSS2,RSS3,RSU0,RSU1,RSU2,RSU3;
+   Real IUS0,IUS1,IUS2,IUS3,IUU0,IUU1,IUU2,IUU3;
+   Real RSSS0,RSSS1,RSSU0,RSSU1,RSUS0,RSUS1,RSUU0,RSUU1;
+   Real ISSS0,ISSS1,ISSU0,ISSU1,ISUS0,ISUS1,ISUU0,ISUU1;
+   Real RUSS0,RUSS1,RUSU0,RUSU1,RUUS0,RUUS1,RUUU0,RUUU1;
+   Real IUSS0,IUSS1,IUSU0,IUSU1,IUUS0,IUUS1,IUUU0,IUUU1;
+   Real R1,R2,R3,R4,R5,R6,R7,R8,R9,R10,R11,R12,R13,R14,R15;
+   Real I1,I2,I3,I4,I5,I6,I7,I8,I9,I10,I11,I12,I13,I14,I15;
+   Real C1,C2,C3,C4,C5,C6,C7,C8,C9,C10,C11,C12,C13,C14,C15;
+   Real S1,S2,S3,S4,S5,S6,S7,S8,S9,S10,S11,S12,S13,S14,S15;
+
+   M16=M*16; M_OVER_2=M/2+1;
+   TWOPI=8.0*atan(1.0);
+   ER1=cos(TWOPI/16.0); EI1=sin(TWOPI/16.0);
+   E2=cos(TWOPI/8.0);
+   ER3=cos(3.0*TWOPI/16.0); EI3=sin(3.0*TWOPI/16.0);
+   ER5=cos(5.0*TWOPI/16.0); EI5=sin(5.0*TWOPI/16.0);
+
+   for (J=0; J<M_OVER_2; J++)
+   {
+      NO_FOLD = (J==0 || 2*J==M);
+      K0=J;
+      ANGLE=TWOPI*Real(J)/Real(M16);
+      ZERO=ANGLE==0.0;
+      C1=cos(ANGLE); S1=sin(ANGLE);
+      C2=C1*C1-S1*S1; S2=C1*S1+S1*C1;
+      C3=C2*C1-S2*S1; S3=S2*C1+C2*S1;
+      C4=C2*C2-S2*S2; S4=S2*C2+C2*S2;
+      C5=C4*C1-S4*S1; S5=S4*C1+C4*S1;
+      C6=C4*C2-S4*S2; S6=S4*C2+C4*S2;
+      C7=C4*C3-S4*S3; S7=S4*C3+C4*S3;
+      C8=C4*C4-S4*S4; S8=C4*S4+S4*C4;
+      C9=C8*C1-S8*S1; S9=S8*C1+C8*S1;
+      C10=C8*C2-S8*S2; S10=S8*C2+C8*S2;
+      C11=C8*C3-S8*S3; S11=S8*C3+C8*S3;
+      C12=C8*C4-S8*S4; S12=S8*C4+C8*S4;
+      C13=C8*C5-S8*S5; S13=S8*C5+C8*S5;
+      C14=C8*C6-S8*S6; S14=S8*C6+C8*S6;
+      C15=C8*C7-S8*S7; S15=S8*C7+C8*S7;
+      goto L200;
+   L100:
+      REPORT
+      if (NO_FOLD) { REPORT goto L600; }
+      REPORT
+      NO_FOLD=true; K0=M-J;
+      T=C1*ER1+S1*EI1; S1= -S1*ER1+C1*EI1; C1=T;
+      T=(C2+S2)*E2; S2=(C2-S2)*E2; C2=T;
+      T=C3*ER3+S3*EI3; S3= -S3*ER3+C3*EI3; C3=T;
+      T=S4; S4=C4; C4=T;
+      T=S5*ER1-C5*EI1; S5=C5*ER1+S5*EI1; C5=T;
+      T=(-C6+S6)*E2; S6=(C6+S6)*E2; C6=T;
+      T=S7*ER3-C7*EI3; S7=C7*ER3+S7*EI3; C7=T;
+      C8= -C8;
+      T= -(C9*ER1+S9*EI1); S9=S9*ER1-C9*EI1; C9=T;
+      T= -(C10+S10)*E2; S10=(-C10+S10)*E2; C10=T;
+      T= -(C11*ER3+S11*EI3); S11=S11*ER3-C11*EI3; C11=T;
+      T= -S12; S12= -C12; C12=T;
+      T= -S13*ER1+C13*EI1; S13= -(C13*ER1+S13*EI1); C13=T;
+      T=(C14-S14)*E2; S14= -(C14+S14)*E2; C14=T;
+      T= -S15*ER3+C15*EI3; S15= -(C15*ER3+S15*EI3); C15=T;
+   L200:
+      REPORT
+      for (K=K0; K<N; K+=M16)
+      {
+         RS0=X0[K]+X8[K]; IS0=Y0[K]+Y8[K];
+         RU0=X0[K]-X8[K]; IU0=Y0[K]-Y8[K];
+         RS1=X1[K]+X9[K]; IS1=Y1[K]+Y9[K];
+         RU1=X1[K]-X9[K]; IU1=Y1[K]-Y9[K];
+         RS2=X2[K]+X10[K]; IS2=Y2[K]+Y10[K];
+         RU2=X2[K]-X10[K]; IU2=Y2[K]-Y10[K];
+         RS3=X3[K]+X11[K]; IS3=Y3[K]+Y11[K];
+         RU3=X3[K]-X11[K]; IU3=Y3[K]-Y11[K];
+         RS4=X4[K]+X12[K]; IS4=Y4[K]+Y12[K];
+         RU4=X4[K]-X12[K]; IU4=Y4[K]-Y12[K];
+         RS5=X5[K]+X13[K]; IS5=Y5[K]+Y13[K];
+         RU5=X5[K]-X13[K]; IU5=Y5[K]-Y13[K];
+         RS6=X6[K]+X14[K]; IS6=Y6[K]+Y14[K];
+         RU6=X6[K]-X14[K]; IU6=Y6[K]-Y14[K];
+         RS7=X7[K]+X15[K]; IS7=Y7[K]+Y15[K];
+         RU7=X7[K]-X15[K]; IU7=Y7[K]-Y15[K];
+         RSS0=RS0+RS4; ISS0=IS0+IS4;
+         RSS1=RS1+RS5; ISS1=IS1+IS5;
+         RSS2=RS2+RS6; ISS2=IS2+IS6;
+         RSS3=RS3+RS7; ISS3=IS3+IS7;
+         RSU0=RS0-RS4; ISU0=IS0-IS4;
+         RSU1=RS1-RS5; ISU1=IS1-IS5;
+         RSU2=RS2-RS6; ISU2=IS2-IS6;
+         RSU3=RS3-RS7; ISU3=IS3-IS7;
+         RUS0=RU0-IU4; IUS0=IU0+RU4;
+         RUS1=RU1-IU5; IUS1=IU1+RU5;
+         RUS2=RU2-IU6; IUS2=IU2+RU6;
+         RUS3=RU3-IU7; IUS3=IU3+RU7;
+         RUU0=RU0+IU4; IUU0=IU0-RU4;
+         RUU1=RU1+IU5; IUU1=IU1-RU5;
+         RUU2=RU2+IU6; IUU2=IU2-RU6;
+         RUU3=RU3+IU7; IUU3=IU3-RU7;
+         T=(RSU1+ISU1)*E2; ISU1=(ISU1-RSU1)*E2; RSU1=T;
+         T=(RSU3+ISU3)*E2; ISU3=(ISU3-RSU3)*E2; RSU3=T;
+         T=RUS1*ER3+IUS1*EI3; IUS1=IUS1*ER3-RUS1*EI3; RUS1=T;
+         T=(RUS2+IUS2)*E2; IUS2=(IUS2-RUS2)*E2; RUS2=T;
+         T=RUS3*ER5+IUS3*EI5; IUS3=IUS3*ER5-RUS3*EI5; RUS3=T;
+         T=RUU1*ER1+IUU1*EI1; IUU1=IUU1*ER1-RUU1*EI1; RUU1=T;
+         T=(RUU2+IUU2)*E2; IUU2=(IUU2-RUU2)*E2; RUU2=T;
+         T=RUU3*ER3+IUU3*EI3; IUU3=IUU3*ER3-RUU3*EI3; RUU3=T;
+         RSSS0=RSS0+RSS2; ISSS0=ISS0+ISS2;
+         RSSS1=RSS1+RSS3; ISSS1=ISS1+ISS3;
+         RSSU0=RSS0-RSS2; ISSU0=ISS0-ISS2;
+         RSSU1=RSS1-RSS3; ISSU1=ISS1-ISS3;
+         RSUS0=RSU0-ISU2; ISUS0=ISU0+RSU2;
+         RSUS1=RSU1-ISU3; ISUS1=ISU1+RSU3;
+         RSUU0=RSU0+ISU2; ISUU0=ISU0-RSU2;
+         RSUU1=RSU1+ISU3; ISUU1=ISU1-RSU3;
+         RUSS0=RUS0-IUS2; IUSS0=IUS0+RUS2;
+         RUSS1=RUS1-IUS3; IUSS1=IUS1+RUS3;
+         RUSU0=RUS0+IUS2; IUSU0=IUS0-RUS2;
+         RUSU1=RUS1+IUS3; IUSU1=IUS1-RUS3;
+         RUUS0=RUU0+RUU2; IUUS0=IUU0+IUU2;
+         RUUS1=RUU1+RUU3; IUUS1=IUU1+IUU3;
+         RUUU0=RUU0-RUU2; IUUU0=IUU0-IUU2;
+         RUUU1=RUU1-RUU3; IUUU1=IUU1-IUU3;
+         X0[K]=RSSS0+RSSS1; Y0[K]=ISSS0+ISSS1;
+         if (!ZERO)
+         {
+            REPORT
+            R1=RUUS0+RUUS1; I1=IUUS0+IUUS1;
+            R2=RSUU0+RSUU1; I2=ISUU0+ISUU1;
+            R3=RUSU0+RUSU1; I3=IUSU0+IUSU1;
+            R4=RSSU0+ISSU1; I4=ISSU0-RSSU1;
+            R5=RUUU0+IUUU1; I5=IUUU0-RUUU1;
+            R6=RSUS0+ISUS1; I6=ISUS0-RSUS1;
+            R7=RUSS0+IUSS1; I7=IUSS0-RUSS1;
+            R8=RSSS0-RSSS1; I8=ISSS0-ISSS1;
+            R9=RUUS0-RUUS1; I9=IUUS0-IUUS1;
+            R10=RSUU0-RSUU1; I10=ISUU0-ISUU1;
+            R11=RUSU0-RUSU1; I11=IUSU0-IUSU1;
+            R12=RSSU0-ISSU1; I12=ISSU0+RSSU1;
+            R13=RUUU0-IUUU1; I13=IUUU0+RUUU1;
+            R14=RSUS0-ISUS1; I14=ISUS0+RSUS1;
+            R15=RUSS0-IUSS1; I15=IUSS0+RUSS1;
+            X8[K]=R1*C1+I1*S1; Y8[K]=I1*C1-R1*S1;
+            X4[K]=R2*C2+I2*S2; Y4[K]=I2*C2-R2*S2;
+            X12[K]=R3*C3+I3*S3; Y12[K]=I3*C3-R3*S3;
+            X2[K]=R4*C4+I4*S4; Y2[K]=I4*C4-R4*S4;
+            X10[K]=R5*C5+I5*S5; Y10[K]=I5*C5-R5*S5;
+            X6[K]=R6*C6+I6*S6; Y6[K]=I6*C6-R6*S6;
+            X14[K]=R7*C7+I7*S7; Y14[K]=I7*C7-R7*S7;
+            X1[K]=R8*C8+I8*S8; Y1[K]=I8*C8-R8*S8;
+            X9[K]=R9*C9+I9*S9; Y9[K]=I9*C9-R9*S9;
+            X5[K]=R10*C10+I10*S10; Y5[K]=I10*C10-R10*S10;
+            X13[K]=R11*C11+I11*S11; Y13[K]=I11*C11-R11*S11;
+            X3[K]=R12*C12+I12*S12; Y3[K]=I12*C12-R12*S12;
+            X11[K]=R13*C13+I13*S13; Y11[K]=I13*C13-R13*S13;
+            X7[K]=R14*C14+I14*S14; Y7[K]=I14*C14-R14*S14;
+            X15[K]=R15*C15+I15*S15; Y15[K]=I15*C15-R15*S15;
+         }
+         else
+         {
+            REPORT
+            X8[K]=RUUS0+RUUS1; Y8[K]=IUUS0+IUUS1;
+            X4[K]=RSUU0+RSUU1; Y4[K]=ISUU0+ISUU1;
+            X12[K]=RUSU0+RUSU1; Y12[K]=IUSU0+IUSU1;
+            X2[K]=RSSU0+ISSU1; Y2[K]=ISSU0-RSSU1;
+            X10[K]=RUUU0+IUUU1; Y10[K]=IUUU0-RUUU1;
+            X6[K]=RSUS0+ISUS1; Y6[K]=ISUS0-RSUS1;
+            X14[K]=RUSS0+IUSS1; Y14[K]=IUSS0-RUSS1;
+            X1[K]=RSSS0-RSSS1; Y1[K]=ISSS0-ISSS1;
+            X9[K]=RUUS0-RUUS1; Y9[K]=IUUS0-IUUS1;
+            X5[K]=RSUU0-RSUU1; Y5[K]=ISUU0-ISUU1;
+            X13[K]=RUSU0-RUSU1; Y13[K]=IUSU0-IUSU1;
+            X3[K]=RSSU0-ISSU1; Y3[K]=ISSU0+RSSU1;
+            X11[K]=RUUU0-IUUU1; Y11[K]=IUUU0+RUUU1;
+            X7[K]=RSUS0-ISUS1; Y7[K]=ISUS0+RSUS1;
+            X15[K]=RUSS0-IUSS1; Y15[K]=IUSS0+RUSS1;
+         }
+      }
+      goto L100;
+   L600: ;
+   }
+
+   return;
+}
+
+// can the number of points be factorised sufficiently
+// for the fft to run
+
+bool FFT_Controller::CanFactor(int PTS)
+{
+   REPORT
+   const int NP = 16, NQ = 10, PMAX=19;
+
+   if (PTS<=1) { REPORT return true; }
+
+   int N = PTS, F = 2, P = 0, Q = 0;
+
+   while (N > 1)
+   {
+      bool fail = true;
+      for (int J = F; J <= PMAX; J++)
+         if (N % J == 0) { fail = false; F=J; break; }
+      if (fail || P >= NP || Q >= NQ) { REPORT return false; }
+      N /= F;
+      if (N % F != 0) Q++; else { N /= F; P++; }
+   }
+
+   return true;    // can factorise
+
+}
+
+bool FFT_Controller::OnlyOldFFT;         // static variable
+
+// **************************** multi radix counter **********************
+
+MultiRadixCounter::MultiRadixCounter(int nx, const SimpleIntArray& rx,
+   SimpleIntArray& vx)
+   : Radix(rx), Value(vx), n(nx), reverse(0),
+      product(1), counter(0), finish(false)
+{
+   REPORT for (int k = 0; k < n; k++) { Value[k] = 0; product *= Radix[k]; }
+}
+
+void MultiRadixCounter::operator++()
+{
+   REPORT
+   counter++; int p = product;
+   for (int k = 0; k < n; k++)
+   {
+      Value[k]++; int p1 = p / Radix[k]; reverse += p1;
+      if (Value[k] == Radix[k]) { REPORT Value[k] = 0; reverse -= p; p = p1; }
+      else { REPORT return; }
+   }
+   finish = true;
+}
+
+
+static int BitReverse(int x, int prod, int n, const SimpleIntArray& f)
+{
+   // x = c[0]+f[0]*(c[1]+f[1]*(c[2]+...
+   // return c[n-1]+f[n-1]*(c[n-2]+f[n-2]*(c[n-3]+...
+   // prod is the product of the f[i]
+   // n is the number of f[i] (don't assume f has the correct length)
+
+   REPORT
+   const int* d = f.Data() + n; int sum = 0; int q = 1;
+   while (n--)
+   {
+      prod /= *(--d);
+      int c = x / prod; x-= c * prod;
+      sum += q * c; q *= *d;
+   }
+   return sum;
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
+
Index: trunk/BNC/newmat/newmat.h
===================================================================
--- trunk/BNC/newmat/newmat.h	(revision 2013)
+++ trunk/BNC/newmat/newmat.h	(revision 2013)
@@ -0,0 +1,2213 @@
+/// \defgroup newmat Newmat matrix manipulation library
+///@{
+
+/// \file newmat.h
+/// Definition file for matrix library.
+
+// Copyright (C) 2004: R B Davies
+
+#ifndef NEWMAT_LIB
+#define NEWMAT_LIB 0
+
+#include "include.h"
+
+#include "myexcept.h"
+
+
+#ifdef use_namespace
+namespace NEWMAT { using namespace RBD_COMMON; }
+namespace RBD_LIBRARIES { using namespace NEWMAT; }
+namespace NEWMAT {
+#endif
+
+//#define DO_REPORT                     // to activate REPORT
+
+#ifdef NO_LONG_NAMES
+#define UpperTriangularMatrix UTMatrix
+#define LowerTriangularMatrix LTMatrix
+#define SymmetricMatrix SMatrix
+#define DiagonalMatrix DMatrix
+#define BandMatrix BMatrix
+#define UpperBandMatrix UBMatrix
+#define LowerBandMatrix LBMatrix
+#define SymmetricBandMatrix SBMatrix
+#define BandLUMatrix BLUMatrix
+#endif
+
+// ************************** general utilities ****************************/
+
+class GeneralMatrix;                            // defined later
+class BaseMatrix;                               // defined later
+class MatrixInput;                              // defined later
+
+void MatrixErrorNoSpace(const void*);           ///< test for allocation fails
+
+/// Return from LogDeterminant function.
+/// Members are the log of the absolute value and the sign (+1, -1 or 0)
+class LogAndSign
+{
+   Real log_val;
+   int sign_val;
+public:
+   LogAndSign() { log_val=0.0; sign_val=1; }
+   LogAndSign(Real);
+   void operator*=(Real);                       ///< multiply by a real
+   void pow_eq(int k);                          ///< raise to power of k
+   void PowEq(int k) { pow_eq(k); }
+   void ChangeSign() { sign_val = -sign_val; }
+   void change_sign() { sign_val = -sign_val; } ///< change sign
+   Real LogValue() const { return log_val; }
+   Real log_value() const { return log_val; }   ///< log of the absolute value
+   int Sign() const { return sign_val; }
+   int sign() const { return sign_val; }        ///< sign of the value
+   Real value() const;                          ///< the value
+   Real Value() const { return value(); }
+   FREE_CHECK(LogAndSign)
+};
+
+// the following class is for counting the number of times a piece of code
+// is executed. It is used for locating any code not executed by test
+// routines. Use turbo GREP locate all places this code is called and
+// check which ones are not accessed.
+// Somewhat implementation dependent as it relies on "cout" still being
+// present when ExeCounter objects are destructed.
+
+#ifdef DO_REPORT
+
+class ExeCounter
+{
+   int line;                                    // code line number
+   int fileid;                                  // file identifier
+   long nexe;                                   // number of executions
+   static int nreports;                         // number of reports
+public:
+   ExeCounter(int,int);
+   void operator++() { nexe++; }
+   ~ExeCounter();                               // prints out reports
+};
+
+#endif
+
+
+// ************************** class MatrixType *****************************
+
+/// Find the type of a matrix resulting from matrix operations.
+/// Also identify what conversions are permissible.
+/// This class must be updated when new matrix types are added.
+
+class MatrixType
+{
+public:
+   enum Attribute {  Valid     = 1,
+                     Diagonal  = 2,             // order of these is important
+                     Symmetric = 4,
+                     Band      = 8,
+                     Lower     = 16,
+                     Upper     = 32,
+                     Square    = 64,
+                     Skew      = 128,
+                     LUDeco    = 256,
+                     Ones      = 512 };
+
+   enum            { US = 0,
+                     UT = Valid + Upper + Square,
+                     LT = Valid + Lower + Square,
+                     Rt = Valid,
+                     Sq = Valid + Square,
+                     Sm = Valid + Symmetric + Square,
+                     Sk = Valid + Skew + Square,
+                     Dg = Valid + Diagonal + Band + Lower + Upper + Symmetric
+                        + Square,
+                     Id = Valid + Diagonal + Band + Lower + Upper + Symmetric
+                        + Square + Ones,
+                     RV = Valid,     //   do not separate out
+                     CV = Valid,     //   vectors
+                     BM = Valid + Band + Square,
+                     UB = Valid + Band + Upper + Square,
+                     LB = Valid + Band + Lower + Square,
+                     SB = Valid + Band + Symmetric + Square,
+                     KB = Valid + Band + Skew + Square,
+                     Ct = Valid + LUDeco + Square,
+                     BC = Valid + Band + LUDeco + Square,
+                     Mask = ~Square
+                   };
+
+
+   static int nTypes() { return 13; }          // number of different types
+					       // exclude Ct, US, BC
+public:
+   int attribute;
+   bool DataLossOK;                            // true if data loss is OK when
+                                               // this represents a destination
+public:
+   MatrixType () : DataLossOK(false) {}
+   MatrixType (int i) : attribute(i), DataLossOK(false) {}
+   MatrixType (int i, bool dlok) : attribute(i), DataLossOK(dlok) {}
+   MatrixType (const MatrixType& mt)
+      : attribute(mt.attribute), DataLossOK(mt.DataLossOK) {}
+   void operator=(const MatrixType& mt)
+      { attribute = mt.attribute; DataLossOK = mt.DataLossOK; }
+   void SetDataLossOK() { DataLossOK = true; }
+   int operator+() const { return attribute; }
+   MatrixType operator+(MatrixType mt) const
+      { return MatrixType(attribute & mt.attribute); }
+   MatrixType operator*(const MatrixType&) const;
+   MatrixType SP(const MatrixType&) const;
+   MatrixType KP(const MatrixType&) const;
+   MatrixType operator|(const MatrixType& mt) const
+      { return MatrixType(attribute & mt.attribute & Valid); }
+   MatrixType operator&(const MatrixType& mt) const
+      { return MatrixType(attribute & mt.attribute & Valid); }
+   bool operator>=(MatrixType mt) const
+      { return ( attribute & ~mt.attribute & Mask ) == 0; }
+   bool operator<(MatrixType mt) const         // for MS Visual C++ 4
+      { return ( attribute & ~mt.attribute & Mask ) != 0; }
+   bool operator==(MatrixType t) const
+      { return (attribute == t.attribute); }
+   bool operator!=(MatrixType t) const
+      { return (attribute != t.attribute); }
+   bool operator!() const { return (attribute & Valid) == 0; }
+   MatrixType i() const;                       ///< type of inverse
+   MatrixType t() const;                       ///< type of transpose
+   MatrixType AddEqualEl() const               ///< add constant to matrix
+      { return MatrixType(attribute & (Valid + Symmetric + Square)); }
+   MatrixType MultRHS() const;                 ///< type for rhs of multiply
+   MatrixType sub() const                      ///< type of submatrix
+      { return MatrixType(attribute & Valid); }
+   MatrixType ssub() const                     ///< type of sym submatrix
+      { return MatrixType(attribute); }        // not for selection matrix
+   GeneralMatrix* New() const;                 ///< new matrix of given type
+   GeneralMatrix* New(int,int,BaseMatrix*) const;
+                                               ///< new matrix of given type
+   const char* value() const;                  ///< type as char string
+   const char* Value() const { return value(); }
+   friend bool Rectangular(MatrixType a, MatrixType b, MatrixType c);
+   friend bool Compare(const MatrixType&, MatrixType&);
+                                               ///< compare and check conversion
+   bool is_band() const { return (attribute & Band) != 0; }
+   bool is_diagonal() const { return (attribute & Diagonal) != 0; }
+   bool is_symmetric() const { return (attribute & Symmetric) != 0; }
+   bool CannotConvert() const { return (attribute & LUDeco) != 0; }
+                                               // used by operator== 
+   FREE_CHECK(MatrixType)
+};
+
+
+// *********************** class MatrixBandWidth ***********************/
+
+///Upper and lower bandwidths of a matrix.
+///That is number of diagonals strictly above or below main diagonal,
+///e.g. diagonal matrix has 0 upper and lower bandwiths.
+///-1 means the matrix may have the maximum bandwidth. 
+class MatrixBandWidth
+{
+public:
+   int lower_val;
+   int upper_val;
+   MatrixBandWidth(const int l, const int u) : lower_val(l), upper_val(u) {}
+   MatrixBandWidth(const int i) : lower_val(i), upper_val(i) {}
+   MatrixBandWidth operator+(const MatrixBandWidth&) const;
+   MatrixBandWidth operator*(const MatrixBandWidth&) const;
+   MatrixBandWidth minimum(const MatrixBandWidth&) const;
+   MatrixBandWidth t() const { return MatrixBandWidth(upper_val,lower_val); }
+   bool operator==(const MatrixBandWidth& bw) const
+      { return (lower_val == bw.lower_val) && (upper_val == bw.upper_val); }
+   bool operator!=(const MatrixBandWidth& bw) const { return !operator==(bw); }
+   int Upper() const { return upper_val; }
+   int upper() const { return upper_val; }
+   int Lower() const { return lower_val; }
+   int lower() const { return lower_val; }
+   FREE_CHECK(MatrixBandWidth)
+};
+
+
+// ********************* Array length specifier ************************/
+
+/// This class is used to avoid constructors such as
+/// ColumnVector(int) being used for conversions.
+/// Eventually this should be replaced by the use of the keyword "explicit".
+
+class ArrayLengthSpecifier
+{
+   int v;
+public:
+   int Value() const { return v; }
+   int value() const { return v; }
+   ArrayLengthSpecifier(int l) : v(l) {}
+};
+
+// ************************* Matrix routines ***************************/
+
+
+class MatrixRowCol;                             // defined later
+class MatrixRow;
+class MatrixCol;
+class MatrixColX;
+
+class GeneralMatrix;                            // defined later
+class AddedMatrix;
+class MultipliedMatrix;
+class SubtractedMatrix;
+class SPMatrix;
+class KPMatrix;
+class ConcatenatedMatrix;
+class StackedMatrix;
+class SolvedMatrix;
+class ShiftedMatrix;
+class NegShiftedMatrix;
+class ScaledMatrix;
+class TransposedMatrix;
+class ReversedMatrix;
+class NegatedMatrix;
+class InvertedMatrix;
+class RowedMatrix;
+class ColedMatrix;
+class DiagedMatrix;
+class MatedMatrix;
+class GetSubMatrix;
+class ReturnMatrix;
+class Matrix;
+class SquareMatrix;
+class nricMatrix;
+class RowVector;
+class ColumnVector;
+class SymmetricMatrix;
+class UpperTriangularMatrix;
+class LowerTriangularMatrix;
+class DiagonalMatrix;
+class CroutMatrix;
+class BandMatrix;
+class LowerBandMatrix;
+class UpperBandMatrix;
+class SymmetricBandMatrix;
+class LinearEquationSolver;
+class GenericMatrix;
+
+
+#define MatrixTypeUnSp 0
+//static MatrixType MatrixTypeUnSp(MatrixType::US);
+//						// AT&T needs this
+
+/// Base of the matrix classes.
+class BaseMatrix : public Janitor
+{
+protected:
+   virtual int search(const BaseMatrix*) const = 0;
+						// count number of times matrix is referred to
+public:
+   virtual GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp) = 0;
+						// evaluate temporary
+   // for old version of G++
+   //   virtual GeneralMatrix* Evaluate(MatrixType mt) = 0;
+   //   GeneralMatrix* Evaluate() { return Evaluate(MatrixTypeUnSp); }
+   AddedMatrix operator+(const BaseMatrix&) const;    // results of operations
+   MultipliedMatrix operator*(const BaseMatrix&) const;
+   SubtractedMatrix operator-(const BaseMatrix&) const;
+   ConcatenatedMatrix operator|(const BaseMatrix&) const;
+   StackedMatrix operator&(const BaseMatrix&) const;
+   ShiftedMatrix operator+(Real) const;
+   ScaledMatrix operator*(Real) const;
+   ScaledMatrix operator/(Real) const;
+   ShiftedMatrix operator-(Real) const;
+   TransposedMatrix t() const;
+//   TransposedMatrix t;
+   NegatedMatrix operator-() const;                   // change sign of elements
+   ReversedMatrix reverse() const;
+   ReversedMatrix Reverse() const;
+   InvertedMatrix i() const;
+//   InvertedMatrix i;
+   RowedMatrix as_row() const;
+   RowedMatrix AsRow() const;
+   ColedMatrix as_column() const;
+   ColedMatrix AsColumn() const;
+   DiagedMatrix as_diagonal() const;
+   DiagedMatrix AsDiagonal() const;
+   MatedMatrix as_matrix(int,int) const;
+   MatedMatrix AsMatrix(int m, int n) const;
+   GetSubMatrix submatrix(int,int,int,int) const;
+   GetSubMatrix SubMatrix(int fr, int lr, int fc, int lc) const;
+   GetSubMatrix sym_submatrix(int,int) const;
+   GetSubMatrix SymSubMatrix(int f, int l) const;
+   GetSubMatrix row(int) const;
+   GetSubMatrix rows(int,int) const;
+   GetSubMatrix column(int) const;
+   GetSubMatrix columns(int,int) const;
+   GetSubMatrix Row(int f) const;
+   GetSubMatrix Rows(int f, int l) const;
+   GetSubMatrix Column(int f) const;
+   GetSubMatrix Columns(int f, int l) const;
+   Real as_scalar() const;                      // conversion of 1 x 1 matrix
+   Real AsScalar() const;
+   virtual LogAndSign log_determinant() const;
+   LogAndSign LogDeterminant() const { return log_determinant(); }
+   Real determinant() const;
+   Real Determinant() const { return determinant(); }
+   virtual Real sum_square() const;
+   Real SumSquare() const { return sum_square(); }
+   Real norm_Frobenius() const;
+   Real norm_frobenius() const { return norm_Frobenius(); }
+   Real NormFrobenius() const { return norm_Frobenius(); }
+   virtual Real sum_absolute_value() const;
+   Real SumAbsoluteValue() const { return sum_absolute_value(); }
+   virtual Real sum() const;
+   virtual Real Sum() const { return sum(); }
+   virtual Real maximum_absolute_value() const;
+   Real MaximumAbsoluteValue() const { return maximum_absolute_value(); }
+   virtual Real maximum_absolute_value1(int& i) const;
+   Real MaximumAbsoluteValue1(int& i) const
+      { return maximum_absolute_value1(i); }
+   virtual Real maximum_absolute_value2(int& i, int& j) const;
+   Real MaximumAbsoluteValue2(int& i, int& j) const
+      { return maximum_absolute_value2(i,j); }
+   virtual Real minimum_absolute_value() const;
+   Real MinimumAbsoluteValue() const { return minimum_absolute_value(); }
+   virtual Real minimum_absolute_value1(int& i) const;
+   Real MinimumAbsoluteValue1(int& i) const
+      { return minimum_absolute_value1(i); }
+   virtual Real minimum_absolute_value2(int& i, int& j) const;
+   Real MinimumAbsoluteValue2(int& i, int& j) const
+      { return minimum_absolute_value2(i,j); }
+   virtual Real maximum() const;
+   Real Maximum() const { return maximum(); }
+   virtual Real maximum1(int& i) const;
+   Real Maximum1(int& i) const { return maximum1(i); }
+   virtual Real maximum2(int& i, int& j) const;
+   Real Maximum2(int& i, int& j) const { return maximum2(i,j); }
+   virtual Real minimum() const;
+   Real Minimum() const { return minimum(); }
+   virtual Real minimum1(int& i) const;
+   Real Minimum1(int& i) const { return minimum1(i); }
+   virtual Real minimum2(int& i, int& j) const;
+   Real Minimum2(int& i, int& j) const { return minimum2(i,j); }
+   virtual Real trace() const;
+   Real Trace() const { return trace(); }
+   Real norm1() const;
+   Real Norm1() const { return norm1(); }
+   Real norm_infinity() const;
+   Real NormInfinity() const { return norm_infinity(); }
+   virtual MatrixBandWidth bandwidth() const;  // bandwidths of band matrix
+   virtual MatrixBandWidth BandWidth() const { return bandwidth(); }
+   void IEQND() const;                         // called by ineq. ops
+   ReturnMatrix sum_square_columns() const;
+   ReturnMatrix sum_square_rows() const;
+   ReturnMatrix sum_columns() const;
+   ReturnMatrix sum_rows() const;
+   virtual void cleanup() {}
+   void CleanUp() { cleanup(); }
+
+//   virtual ReturnMatrix Reverse() const;       // reverse order of elements
+//protected:
+//   BaseMatrix() : t(this), i(this) {}
+
+   friend class GeneralMatrix;
+   friend class Matrix;
+   friend class SquareMatrix;
+   friend class nricMatrix;
+   friend class RowVector;
+   friend class ColumnVector;
+   friend class SymmetricMatrix;
+   friend class UpperTriangularMatrix;
+   friend class LowerTriangularMatrix;
+   friend class DiagonalMatrix;
+   friend class CroutMatrix;
+   friend class BandMatrix;
+   friend class LowerBandMatrix;
+   friend class UpperBandMatrix;
+   friend class SymmetricBandMatrix;
+   friend class AddedMatrix;
+   friend class MultipliedMatrix;
+   friend class SubtractedMatrix;
+   friend class SPMatrix;
+   friend class KPMatrix;
+   friend class ConcatenatedMatrix;
+   friend class StackedMatrix;
+   friend class SolvedMatrix;
+   friend class ShiftedMatrix;
+   friend class NegShiftedMatrix;
+   friend class ScaledMatrix;
+   friend class TransposedMatrix;
+   friend class ReversedMatrix;
+   friend class NegatedMatrix;
+   friend class InvertedMatrix;
+   friend class RowedMatrix;
+   friend class ColedMatrix;
+   friend class DiagedMatrix;
+   friend class MatedMatrix;
+   friend class GetSubMatrix;
+   friend class ReturnMatrix;
+   friend class LinearEquationSolver;
+   friend class GenericMatrix;
+   NEW_DELETE(BaseMatrix)
+};
+
+
+// ***************************** working classes **************************/
+
+/// The classes for matrices that can contain data are derived from this.
+class GeneralMatrix : public BaseMatrix         // declarable matrix types
+{
+   virtual GeneralMatrix* Image() const;        // copy of matrix
+protected:
+   int tag_val;                                 // shows whether can reuse
+   int nrows_val, ncols_val;                    // dimensions
+   int storage;                                 // total store required
+   Real* store;                                 // point to store (0=not set)
+   GeneralMatrix();                             // initialise with no store
+   GeneralMatrix(ArrayLengthSpecifier);         // constructor getting store
+   void Add(GeneralMatrix*, Real);              // sum of GM and Real
+   void Add(Real);                              // add Real to this
+   void NegAdd(GeneralMatrix*, Real);           // Real - GM
+   void NegAdd(Real);                           // this = this - Real
+   void Multiply(GeneralMatrix*, Real);         // product of GM and Real
+   void Multiply(Real);                         // multiply this by Real
+   void Negate(GeneralMatrix*);                 // change sign
+   void Negate();                               // change sign
+   void ReverseElements();                      // internal reverse of elements
+   void ReverseElements(GeneralMatrix*);        // reverse order of elements
+   void operator=(Real);                        // set matrix to constant
+   Real* GetStore();                            // get store or copy
+   GeneralMatrix* BorrowStore(GeneralMatrix*, MatrixType);
+                                                // temporarily access store
+   void GetMatrix(const GeneralMatrix*);        // used by = and initialise
+   void Eq(const BaseMatrix&, MatrixType);      // used by =
+   void Eq(const GeneralMatrix&);               // version with no conversion
+   void Eq(const BaseMatrix&, MatrixType, bool);// used by <<
+   void Eq2(const BaseMatrix&, MatrixType);     // cut down version of Eq
+   int search(const BaseMatrix*) const;
+   virtual GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void CheckConversion(const BaseMatrix&);     // check conversion OK
+   void resize(int, int, int);                  // change dimensions
+   virtual short SimpleAddOK(const GeneralMatrix*) { return 0; }
+             // see bandmat.cpp for explanation
+   virtual void MiniCleanUp()
+      { store = 0; storage = 0; nrows_val = 0; ncols_val = 0; tag_val = -1;}
+             // CleanUp when the data array has already been deleted
+   void PlusEqual(const GeneralMatrix& gm);
+   void MinusEqual(const GeneralMatrix& gm);
+   void PlusEqual(Real f);
+   void MinusEqual(Real f);
+   void swap(GeneralMatrix& gm);                // swap values
+public:
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   virtual MatrixType type() const = 0;         // type of a matrix
+   MatrixType Type() const { return type(); }
+   int Nrows() const { return nrows_val; }      // get dimensions
+   int Ncols() const { return ncols_val; }
+   int Storage() const { return storage; }
+   Real* Store() const { return store; }
+   // updated names
+   int nrows() const { return nrows_val; }      // get dimensions
+   int ncols() const { return ncols_val; }
+   int size() const { return storage; }
+   Real* data() { return store; }
+   const Real* data() const { return store; }
+   const Real* const_data() const { return store; }
+   virtual ~GeneralMatrix();                    // delete store if set
+   void tDelete();                              // delete if tag_val permits
+   bool reuse();                                // true if tag_val allows reuse
+   void protect() { tag_val=-1; }               // cannot delete or reuse
+   void Protect() { tag_val=-1; }               // cannot delete or reuse
+   int tag() const { return tag_val; }
+   int Tag() const { return tag_val; }
+   bool is_zero() const;                        // test matrix has all zeros
+   bool IsZero() const { return is_zero(); }    // test matrix has all zeros
+   void Release() { tag_val=1; }                // del store after next use
+   void Release(int t) { tag_val=t; }           // del store after t accesses
+   void ReleaseAndDelete() { tag_val=0; }       // delete matrix after use
+   void release() { tag_val=1; }                // del store after next use
+   void release(int t) { tag_val=t; }           // del store after t accesses
+   void release_and_delete() { tag_val=0; }     // delete matrix after use
+   void operator<<(const double*);              // assignment from an array
+   void operator<<(const float*);               // assignment from an array
+   void operator<<(const int*);                 // assignment from an array
+   void operator<<(const BaseMatrix& X)
+      { Eq(X,this->type(),true); }              // = without checking type
+   void inject(const GeneralMatrix&);           // copy stored els only
+   void Inject(const GeneralMatrix& GM) { inject(GM); }
+   void operator+=(const BaseMatrix&);
+   void operator-=(const BaseMatrix&);
+   void operator*=(const BaseMatrix&);
+   void operator|=(const BaseMatrix&);
+   void operator&=(const BaseMatrix&);
+   void operator+=(Real);
+   void operator-=(Real r) { operator+=(-r); }
+   void operator*=(Real);
+   void operator/=(Real r) { operator*=(1.0/r); }
+   virtual GeneralMatrix* MakeSolver();         // for solving
+   virtual void Solver(MatrixColX&, const MatrixColX&) {}
+   virtual void GetRow(MatrixRowCol&) = 0;      // Get matrix row
+   virtual void RestoreRow(MatrixRowCol&) {}    // Restore matrix row
+   virtual void NextRow(MatrixRowCol&);         // Go to next row
+   virtual void GetCol(MatrixRowCol&) = 0;      // Get matrix col
+   virtual void GetCol(MatrixColX&) = 0;        // Get matrix col
+   virtual void RestoreCol(MatrixRowCol&) {}    // Restore matrix col
+   virtual void RestoreCol(MatrixColX&) {}      // Restore matrix col
+   virtual void NextCol(MatrixRowCol&);         // Go to next col
+   virtual void NextCol(MatrixColX&);           // Go to next col
+   Real sum_square() const;
+   Real sum_absolute_value() const;
+   Real sum() const;
+   Real maximum_absolute_value1(int& i) const;
+   Real minimum_absolute_value1(int& i) const;
+   Real maximum1(int& i) const;
+   Real minimum1(int& i) const;
+   Real maximum_absolute_value() const;
+   Real maximum_absolute_value2(int& i, int& j) const;
+   Real minimum_absolute_value() const;
+   Real minimum_absolute_value2(int& i, int& j) const;
+   Real maximum() const;
+   Real maximum2(int& i, int& j) const;
+   Real minimum() const;
+   Real minimum2(int& i, int& j) const;
+   LogAndSign log_determinant() const;
+   virtual bool IsEqual(const GeneralMatrix&) const;
+                                                // same type, same values
+   void CheckStore() const;                     // check store is non-zero
+   virtual void SetParameters(const GeneralMatrix*) {}
+                                                // set parameters in GetMatrix
+   operator ReturnMatrix() const;               // for building a ReturnMatrix
+   ReturnMatrix for_return() const;
+   ReturnMatrix ForReturn() const;
+   //virtual bool SameStorageType(const GeneralMatrix& A) const;
+   //virtual void ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B);
+   //virtual void ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B);
+   virtual void resize(const GeneralMatrix& A);
+   virtual void ReSize(const GeneralMatrix& A) { resize(A); }
+   MatrixInput operator<<(double);                // for loading a list
+   MatrixInput operator<<(float);                // for loading a list
+   MatrixInput operator<<(int f);
+//   ReturnMatrix Reverse() const;                // reverse order of elements
+   void cleanup();                              // to clear store
+
+   friend class Matrix;
+   friend class SquareMatrix;
+   friend class nricMatrix;
+   friend class SymmetricMatrix;
+   friend class UpperTriangularMatrix;
+   friend class LowerTriangularMatrix;
+   friend class DiagonalMatrix;
+   friend class CroutMatrix;
+   friend class RowVector;
+   friend class ColumnVector;
+   friend class BandMatrix;
+   friend class LowerBandMatrix;
+   friend class UpperBandMatrix;
+   friend class SymmetricBandMatrix;
+   friend class BaseMatrix;
+   friend class AddedMatrix;
+   friend class MultipliedMatrix;
+   friend class SubtractedMatrix;
+   friend class SPMatrix;
+   friend class KPMatrix;
+   friend class ConcatenatedMatrix;
+   friend class StackedMatrix;
+   friend class SolvedMatrix;
+   friend class ShiftedMatrix;
+   friend class NegShiftedMatrix;
+   friend class ScaledMatrix;
+   friend class TransposedMatrix;
+   friend class ReversedMatrix;
+   friend class NegatedMatrix;
+   friend class InvertedMatrix;
+   friend class RowedMatrix;
+   friend class ColedMatrix;
+   friend class DiagedMatrix;
+   friend class MatedMatrix;
+   friend class GetSubMatrix;
+   friend class ReturnMatrix;
+   friend class LinearEquationSolver;
+   friend class GenericMatrix;
+   NEW_DELETE(GeneralMatrix)
+};
+
+
+/// The usual rectangular matrix.
+class Matrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   Matrix() {}
+   ~Matrix() {}
+   Matrix(int, int);                            // standard declaration
+   Matrix(const BaseMatrix&);                   // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const Matrix& m) { Eq(m); }
+   MatrixType type() const;
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+m*ncols_val; }
+   const Real* operator[](int m) const { return store+m*ncols_val; }
+   // following for Numerical Recipes in C++
+   Matrix(Real, int, int);
+   Matrix(const Real*, int, int);
+#endif
+   Matrix(const Matrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   GeneralMatrix* MakeSolver();
+   Real trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&);
+   void RestoreCol(MatrixColX&);
+   void NextRow(MatrixRowCol&);
+   void NextCol(MatrixRowCol&);
+   void NextCol(MatrixColX&);
+   virtual void resize(int,int);           // change dimensions
+      // virtual so we will catch it being used in a vector called as a matrix
+   virtual void resize_keep(int,int);
+   virtual void ReSize(int m, int n) { resize(m, n); }
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   Real maximum_absolute_value2(int& i, int& j) const;
+   Real minimum_absolute_value2(int& i, int& j) const;
+   Real maximum2(int& i, int& j) const;
+   Real minimum2(int& i, int& j) const;
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(Matrix& gm) { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   friend Real dotproduct(const Matrix& A, const Matrix& B);
+   NEW_DELETE(Matrix)
+};
+
+/// Square matrix.
+class SquareMatrix : public Matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   SquareMatrix() {}
+   ~SquareMatrix() {}
+   SquareMatrix(ArrayLengthSpecifier);          // standard declaration
+   SquareMatrix(const BaseMatrix&);             // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const SquareMatrix& m) { Eq(m); }
+   void operator=(const Matrix& m);
+   MatrixType type() const;
+   SquareMatrix(const SquareMatrix& gm) : Matrix() { GetMatrix(&gm); }
+   SquareMatrix(const Matrix& gm);
+   void resize(int);                            // change dimensions
+   void ReSize(int m) { resize(m); }
+   void resize_keep(int);
+   void resize_keep(int,int);
+   void resize(int,int);                        // change dimensions
+   void ReSize(int m, int n) { resize(m, n); }
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(SquareMatrix& gm) { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(SquareMatrix)
+};
+
+/// Rectangular matrix for use with Numerical Recipes in C.
+class nricMatrix : public Matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+   Real** row_pointer;                          // points to rows
+   void MakeRowPointer();                       // build rowpointer
+   void DeleteRowPointer();
+public:
+   nricMatrix() {}
+   nricMatrix(int m, int n)                     // standard declaration
+      :  Matrix(m,n) { MakeRowPointer(); }
+   nricMatrix(const BaseMatrix& bm)             // evaluate BaseMatrix
+      :  Matrix(bm) { MakeRowPointer(); }
+   void operator=(const BaseMatrix& bm)
+      { DeleteRowPointer(); Matrix::operator=(bm); MakeRowPointer(); }
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const nricMatrix& m)
+      { DeleteRowPointer(); Eq(m); MakeRowPointer(); }
+   void operator<<(const BaseMatrix& X)
+      { DeleteRowPointer(); Eq(X,this->type(),true); MakeRowPointer(); }
+   nricMatrix(const nricMatrix& gm) : Matrix()
+      { GetMatrix(&gm); MakeRowPointer(); }
+   void resize(int m, int n)               // change dimensions
+      { DeleteRowPointer(); Matrix::resize(m,n); MakeRowPointer(); }
+   void resize_keep(int m, int n)               // change dimensions
+      { DeleteRowPointer(); Matrix::resize_keep(m,n); MakeRowPointer(); }
+   void ReSize(int m, int n)               // change dimensions
+      { DeleteRowPointer(); Matrix::resize(m,n); MakeRowPointer(); }
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   ~nricMatrix() { DeleteRowPointer(); }
+   Real** nric() const { CheckStore(); return row_pointer-1; }
+   void cleanup();                                // to clear store
+   void MiniCleanUp();
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(nricMatrix& gm);
+   NEW_DELETE(nricMatrix)
+};
+
+/// Symmetric matrix.
+class SymmetricMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   SymmetricMatrix() {}
+   ~SymmetricMatrix() {}
+   SymmetricMatrix(ArrayLengthSpecifier);
+   SymmetricMatrix(const BaseMatrix&);
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const SymmetricMatrix& m) { Eq(m); }
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+(m*(m+1))/2; }
+   const Real* operator[](int m) const { return store+(m*(m+1))/2; }
+#endif
+   MatrixType type() const;
+   SymmetricMatrix(const SymmetricMatrix& gm)
+      : GeneralMatrix() { GetMatrix(&gm); }
+   Real sum_square() const;
+   Real sum_absolute_value() const;
+   Real sum() const;
+   Real trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&) {}
+   void RestoreCol(MatrixColX&);
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void resize(int);                           // change dimensions
+   void ReSize(int m) { resize(m); }
+   void resize_keep(int);
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   void operator+=(const SymmetricMatrix& M) { PlusEqual(M); }
+   void operator-=(const SymmetricMatrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(SymmetricMatrix& gm) { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(SymmetricMatrix)
+};
+
+/// Upper triangular matrix.
+class UpperTriangularMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   UpperTriangularMatrix() {}
+   ~UpperTriangularMatrix() {}
+   UpperTriangularMatrix(ArrayLengthSpecifier);
+   void operator=(const BaseMatrix&);
+   void operator=(const UpperTriangularMatrix& m) { Eq(m); }
+   UpperTriangularMatrix(const BaseMatrix&);
+   UpperTriangularMatrix(const UpperTriangularMatrix& gm)
+      : GeneralMatrix() { GetMatrix(&gm); }
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+m*ncols_val-(m*(m+1))/2; }
+   const Real* operator[](int m) const
+      { return store+m*ncols_val-(m*(m+1))/2; }
+#endif
+   MatrixType type() const;
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   void Solver(MatrixColX&, const MatrixColX&);
+   LogAndSign log_determinant() const;
+   Real trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&);
+   void RestoreCol(MatrixColX& c) { RestoreCol((MatrixRowCol&)c); }
+   void NextRow(MatrixRowCol&);
+   void resize(int);                       // change dimensions
+   void ReSize(int m) { resize(m); }
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   void resize_keep(int);
+   MatrixBandWidth bandwidth() const;
+   void operator+=(const UpperTriangularMatrix& M) { PlusEqual(M); }
+   void operator-=(const UpperTriangularMatrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::operator+=(f); }
+   void operator-=(Real f) { GeneralMatrix::operator-=(f); }
+   void swap(UpperTriangularMatrix& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(UpperTriangularMatrix)
+};
+
+/// Lower triangular matrix.
+class LowerTriangularMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   LowerTriangularMatrix() {}
+   ~LowerTriangularMatrix() {}
+   LowerTriangularMatrix(ArrayLengthSpecifier);
+   LowerTriangularMatrix(const LowerTriangularMatrix& gm)
+      : GeneralMatrix() { GetMatrix(&gm); }
+   LowerTriangularMatrix(const BaseMatrix& M);
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const LowerTriangularMatrix& m) { Eq(m); }
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+(m*(m+1))/2; }
+   const Real* operator[](int m) const { return store+(m*(m+1))/2; }
+#endif
+   MatrixType type() const;
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   void Solver(MatrixColX&, const MatrixColX&);
+   LogAndSign log_determinant() const;
+   Real trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&);
+   void RestoreCol(MatrixColX& c) { RestoreCol((MatrixRowCol&)c); }
+   void NextRow(MatrixRowCol&);
+   void resize(int);                       // change dimensions
+   void ReSize(int m) { resize(m); }
+   void resize_keep(int);
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   MatrixBandWidth bandwidth() const;
+   void operator+=(const LowerTriangularMatrix& M) { PlusEqual(M); }
+   void operator-=(const LowerTriangularMatrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::operator+=(f); }
+   void operator-=(Real f) { GeneralMatrix::operator-=(f); }
+   void swap(LowerTriangularMatrix& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(LowerTriangularMatrix)
+};
+
+/// Diagonal matrix.
+class DiagonalMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   DiagonalMatrix() {}
+   ~DiagonalMatrix() {}
+   DiagonalMatrix(ArrayLengthSpecifier);
+   DiagonalMatrix(const BaseMatrix&);
+   DiagonalMatrix(const DiagonalMatrix& gm)
+      : GeneralMatrix() { GetMatrix(&gm); }
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const DiagonalMatrix& m) { Eq(m); }
+   Real& operator()(int, int);                  // access element
+   Real& operator()(int);                       // access element
+   Real operator()(int, int) const;             // access element
+   Real operator()(int) const;
+   Real& element(int, int);                     // access element
+   Real& element(int);                          // access element
+   Real element(int, int) const;                // access element
+   Real element(int) const;                     // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real& operator[](int m) { return store[m]; }
+   const Real& operator[](int m) const { return store[m]; }
+#endif
+   MatrixType type() const;
+
+   LogAndSign log_determinant() const;
+   Real trace() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void NextRow(MatrixRowCol&);
+   void NextCol(MatrixRowCol&);
+   void NextCol(MatrixColX&);
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   void Solver(MatrixColX&, const MatrixColX&);
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void resize(int);                       // change dimensions
+   void ReSize(int m) { resize(m); }
+   void resize_keep(int);
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   Real* nric() const
+      { CheckStore(); return store-1; }         // for use by NRIC
+   MatrixBandWidth bandwidth() const;
+//   ReturnMatrix Reverse() const;                // reverse order of elements
+   void operator+=(const DiagonalMatrix& M) { PlusEqual(M); }
+   void operator-=(const DiagonalMatrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::operator+=(f); }
+   void operator-=(Real f) { GeneralMatrix::operator-=(f); }
+   void swap(DiagonalMatrix& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(DiagonalMatrix)
+};
+
+/// Row vector.
+class RowVector : public Matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   RowVector() { nrows_val = 1; }
+   ~RowVector() {}
+   RowVector(ArrayLengthSpecifier n) : Matrix(1,n.Value()) {}
+   RowVector(const BaseMatrix&);
+   RowVector(const RowVector& gm) : Matrix() { GetMatrix(&gm); }
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const RowVector& m) { Eq(m); }
+   Real& operator()(int);                       // access element
+   Real& element(int);                          // access element
+   Real operator()(int) const;                  // access element
+   Real element(int) const;                     // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real& operator[](int m) { return store[m]; }
+   const Real& operator[](int m) const { return store[m]; }
+   // following for Numerical Recipes in C++
+   RowVector(Real a, int n) : Matrix(a, 1, n) {}
+   RowVector(const Real* a, int n) : Matrix(a, 1, n) {}
+#endif
+   MatrixType type() const;
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void NextCol(MatrixRowCol&);
+   void NextCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&) {}
+   void RestoreCol(MatrixColX& c);
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void resize(int);                       // change dimensions
+   void ReSize(int m) { resize(m); }
+   void resize_keep(int);
+   void resize_keep(int,int);
+   void resize(int,int);                   // in case access is matrix
+   void ReSize(int m,int n) { resize(m, n); }
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   Real* nric() const
+      { CheckStore(); return store-1; }         // for use by NRIC
+   void cleanup();                              // to clear store
+   void MiniCleanUp()
+      { store = 0; storage = 0; nrows_val = 1; ncols_val = 0; tag_val = -1; }
+   // friend ReturnMatrix GetMatrixRow(Matrix& A, int row);
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(RowVector& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(RowVector)
+};
+
+/// Column vector.
+class ColumnVector : public Matrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   ColumnVector() { ncols_val = 1; }
+   ~ColumnVector() {}
+   ColumnVector(ArrayLengthSpecifier n) : Matrix(n.Value(),1) {}
+   ColumnVector(const BaseMatrix&);
+   ColumnVector(const ColumnVector& gm) : Matrix() { GetMatrix(&gm); }
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const ColumnVector& m) { Eq(m); }
+   Real& operator()(int);                       // access element
+   Real& element(int);                          // access element
+   Real operator()(int) const;                  // access element
+   Real element(int) const;                     // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real& operator[](int m) { return store[m]; }
+   const Real& operator[](int m) const { return store[m]; }
+   // following for Numerical Recipes in C++
+   ColumnVector(Real a, int m) : Matrix(a, m, 1) {}
+   ColumnVector(const Real* a, int m) : Matrix(a, m, 1) {}
+#endif
+   MatrixType type() const;
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void resize(int);                       // change dimensions
+   void ReSize(int m) { resize(m); }
+   void resize_keep(int);
+   void resize_keep(int,int);
+   void resize(int,int);                   // in case access is matrix
+   void ReSize(int m,int n) { resize(m, n); }
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   Real* nric() const
+      { CheckStore(); return store-1; }         // for use by NRIC
+   void cleanup();                              // to clear store
+   void MiniCleanUp()
+      { store = 0; storage = 0; nrows_val = 0; ncols_val = 1; tag_val = -1; }
+//   ReturnMatrix Reverse() const;                // reverse order of elements
+   void operator+=(const Matrix& M) { PlusEqual(M); }
+   void operator-=(const Matrix& M) { MinusEqual(M); }
+   void operator+=(Real f) { GeneralMatrix::Add(f); }
+   void operator-=(Real f) { GeneralMatrix::Add(-f); }
+   void swap(ColumnVector& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(ColumnVector)
+};
+
+/// LU matrix.
+/// A square matrix decomposed into upper and lower triangular
+/// in preparation for inverting or solving equations.
+class CroutMatrix : public GeneralMatrix
+{
+   int* indx;
+   bool d;                              // number of row swaps = even or odd
+   bool sing;
+   void ludcmp();
+   void get_aux(CroutMatrix&);                  // for copying indx[] etc
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   CroutMatrix(const BaseMatrix&);
+   CroutMatrix() : indx(0), d(true), sing(true) {}
+   CroutMatrix(const CroutMatrix&);
+   void operator=(const CroutMatrix&);
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixType type() const;
+   void lubksb(Real*, int=0);
+   ~CroutMatrix();
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   LogAndSign log_determinant() const;
+   void Solver(MatrixColX&, const MatrixColX&);
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX& c) { GetCol((MatrixRowCol&)c); }
+   void cleanup();                                // to clear store
+   void MiniCleanUp();
+   bool IsEqual(const GeneralMatrix&) const;
+   bool is_singular() const { return sing; }
+   bool IsSingular() const { return sing; }
+   const int* const_data_indx() const { return indx; }
+   bool even_exchanges() const { return d; }
+   void swap(CroutMatrix& gm);
+   NEW_DELETE(CroutMatrix)
+};
+
+// ***************************** band matrices ***************************/
+
+/// Band matrix.
+class BandMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+protected:
+   void CornerClear() const;                    // set unused elements to zero
+   short SimpleAddOK(const GeneralMatrix* gm);
+public:
+   int lower_val, upper_val;                            // band widths
+   BandMatrix() { lower_val=0; upper_val=0; CornerClear(); }
+   ~BandMatrix() {}
+   BandMatrix(int n,int lb,int ub) { resize(n,lb,ub); CornerClear(); }
+                                                // standard declaration
+   BandMatrix(const BaseMatrix&);               // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const BandMatrix& m) { Eq(m); }
+   MatrixType type() const;
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+(upper_val+lower_val)*m+lower_val; }
+   const Real* operator[](int m) const
+      { return store+(upper_val+lower_val)*m+lower_val; }
+#endif
+   BandMatrix(const BandMatrix& gm) : GeneralMatrix() { GetMatrix(&gm); }
+   LogAndSign log_determinant() const;
+   GeneralMatrix* MakeSolver();
+   Real trace() const;
+   Real sum_square() const
+      { CornerClear(); return GeneralMatrix::sum_square(); }
+   Real sum_absolute_value() const
+      { CornerClear(); return GeneralMatrix::sum_absolute_value(); }
+   Real sum() const
+      { CornerClear(); return GeneralMatrix::sum(); }
+   Real maximum_absolute_value() const
+      { CornerClear(); return GeneralMatrix::maximum_absolute_value(); }
+   Real minimum_absolute_value() const
+      { int i, j; return GeneralMatrix::minimum_absolute_value2(i, j); }
+   Real maximum() const { int i, j; return GeneralMatrix::maximum2(i, j); }
+   Real minimum() const { int i, j; return GeneralMatrix::minimum2(i, j); }
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&);
+   void RestoreCol(MatrixColX& c) { RestoreCol((MatrixRowCol&)c); }
+   void NextRow(MatrixRowCol&);
+   virtual void resize(int, int, int);             // change dimensions
+   virtual void ReSize(int m, int n, int b) { resize(m, n, b); }
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   //bool SameStorageType(const GeneralMatrix& A) const;
+   //void ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B);
+   //void ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B);
+   MatrixBandWidth bandwidth() const;
+   void SetParameters(const GeneralMatrix*);
+   MatrixInput operator<<(double);                // will give error
+   MatrixInput operator<<(float);                // will give error
+   MatrixInput operator<<(int f);
+   void operator<<(const double* r);              // will give error
+   void operator<<(const float* r);              // will give error
+   void operator<<(const int* r);               // will give error
+      // the next is included because Zortech and Borland
+      // cannot find the copy in GeneralMatrix
+   void operator<<(const BaseMatrix& X) { GeneralMatrix::operator<<(X); }
+   void swap(BandMatrix& gm);
+   NEW_DELETE(BandMatrix)
+};
+
+/// Upper triangular band matrix.
+class UpperBandMatrix : public BandMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   UpperBandMatrix() {}
+   ~UpperBandMatrix() {}
+   UpperBandMatrix(int n, int ubw)              // standard declaration
+      : BandMatrix(n, 0, ubw) {}
+   UpperBandMatrix(const BaseMatrix&);          // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const UpperBandMatrix& m) { Eq(m); }
+   MatrixType type() const;
+   UpperBandMatrix(const UpperBandMatrix& gm) : BandMatrix() { GetMatrix(&gm); }
+   GeneralMatrix* MakeSolver() { return this; }
+   void Solver(MatrixColX&, const MatrixColX&);
+   LogAndSign log_determinant() const;
+   void resize(int, int, int);             // change dimensions
+   void ReSize(int m, int n, int b) { resize(m, n, b); }
+   void resize(int n,int ubw)              // change dimensions
+      { BandMatrix::resize(n,0,ubw); }
+   void ReSize(int n,int ubw)              // change dimensions
+      { BandMatrix::resize(n,0,ubw); }
+   void resize(const GeneralMatrix& A) { BandMatrix::resize(A); }
+   void ReSize(const GeneralMatrix& A) { BandMatrix::resize(A); }
+   Real& operator()(int, int);
+   Real operator()(int, int) const;
+   Real& element(int, int);
+   Real element(int, int) const;
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+upper_val*m; }
+   const Real* operator[](int m) const { return store+upper_val*m; }
+#endif
+   void swap(UpperBandMatrix& gm)
+      { BandMatrix::swap((BandMatrix&)gm); }
+   NEW_DELETE(UpperBandMatrix)
+};
+
+/// Lower triangular band matrix.
+class LowerBandMatrix : public BandMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   LowerBandMatrix() {}
+   ~LowerBandMatrix() {}
+   LowerBandMatrix(int n, int lbw)              // standard declaration
+      : BandMatrix(n, lbw, 0) {}
+   LowerBandMatrix(const BaseMatrix&);          // evaluate BaseMatrix
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const LowerBandMatrix& m) { Eq(m); }
+   MatrixType type() const;
+   LowerBandMatrix(const LowerBandMatrix& gm) : BandMatrix() { GetMatrix(&gm); }
+   GeneralMatrix* MakeSolver() { return this; }
+   void Solver(MatrixColX&, const MatrixColX&);
+   LogAndSign log_determinant() const;
+   void resize(int, int, int);             // change dimensions
+   void ReSize(int m, int n, int b) { resize(m, n, b); }
+   void resize(int n,int lbw)             // change dimensions
+      { BandMatrix::resize(n,lbw,0); }
+   void ReSize(int n,int lbw)             // change dimensions
+      { BandMatrix::resize(n,lbw,0); }
+   void resize(const GeneralMatrix& A) { BandMatrix::resize(A); }
+   void ReSize(const GeneralMatrix& A) { BandMatrix::resize(A); }
+   Real& operator()(int, int);
+   Real operator()(int, int) const;
+   Real& element(int, int);
+   Real element(int, int) const;
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+lower_val*(m+1); }
+   const Real* operator[](int m) const { return store+lower_val*(m+1); }
+#endif
+   void swap(LowerBandMatrix& gm)
+      { BandMatrix::swap((BandMatrix&)gm); }
+   NEW_DELETE(LowerBandMatrix)
+};
+
+/// Symmetric band matrix.
+class SymmetricBandMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;                // copy of matrix
+   void CornerClear() const;                    // set unused elements to zero
+   short SimpleAddOK(const GeneralMatrix* gm);
+public:
+   int lower_val;                                   // lower band width
+   SymmetricBandMatrix() { lower_val=0; CornerClear(); }
+   ~SymmetricBandMatrix() {}
+   SymmetricBandMatrix(int n, int lb) { resize(n,lb); CornerClear(); }
+   SymmetricBandMatrix(const BaseMatrix&);
+   void operator=(const BaseMatrix&);
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   void operator=(const SymmetricBandMatrix& m) { Eq(m); }
+   Real& operator()(int, int);                  // access element
+   Real& element(int, int);                     // access element
+   Real operator()(int, int) const;             // access element
+   Real element(int, int) const;                // access element
+#ifdef SETUP_C_SUBSCRIPTS
+   Real* operator[](int m) { return store+lower_val*(m+1); }
+   const Real* operator[](int m) const { return store+lower_val*(m+1); }
+#endif
+   MatrixType type() const;
+   SymmetricBandMatrix(const SymmetricBandMatrix& gm)
+      : GeneralMatrix() { GetMatrix(&gm); }
+   GeneralMatrix* MakeSolver();
+   Real sum_square() const;
+   Real sum_absolute_value() const;
+   Real sum() const;
+   Real maximum_absolute_value() const
+      { CornerClear(); return GeneralMatrix::maximum_absolute_value(); }
+   Real minimum_absolute_value() const
+      { int i, j; return GeneralMatrix::minimum_absolute_value2(i, j); }
+   Real maximum() const { int i, j; return GeneralMatrix::maximum2(i, j); }
+   Real minimum() const { int i, j; return GeneralMatrix::minimum2(i, j); }
+   Real trace() const;
+   LogAndSign log_determinant() const;
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void RestoreCol(MatrixRowCol&) {}
+   void RestoreCol(MatrixColX&);
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void resize(int,int);                       // change dimensions
+   void ReSize(int m,int b) { resize(m, b); }
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   //bool SameStorageType(const GeneralMatrix& A) const;
+   //void ReSizeForAdd(const GeneralMatrix& A, const GeneralMatrix& B);
+   //void ReSizeForSP(const GeneralMatrix& A, const GeneralMatrix& B);
+   MatrixBandWidth bandwidth() const;
+   void SetParameters(const GeneralMatrix*);
+   void operator<<(const double* r);              // will give error
+   void operator<<(const float* r);              // will give error
+   void operator<<(const int* r);               // will give error
+   void operator<<(const BaseMatrix& X) { GeneralMatrix::operator<<(X); }
+   void swap(SymmetricBandMatrix& gm);
+   NEW_DELETE(SymmetricBandMatrix)
+};
+
+/// LU decomposition of a band matrix.
+class BandLUMatrix : public GeneralMatrix
+{
+   int* indx;
+   bool d;
+   bool sing;                                   // true if singular
+   Real* store2;
+   int storage2;
+   int m1,m2;                                   // lower and upper
+   void ludcmp();
+   void get_aux(BandLUMatrix&);                 // for copying indx[] etc
+   GeneralMatrix* Image() const;                // copy of matrix
+public:
+   BandLUMatrix(const BaseMatrix&);
+   BandLUMatrix()
+     : indx(0), d(true), sing(true), store2(0), storage2(0), m1(0), m2(0) {}
+   BandLUMatrix(const BandLUMatrix&);
+   void operator=(const BandLUMatrix&);
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixType type() const;
+   void lubksb(Real*, int=0);
+   ~BandLUMatrix();
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   LogAndSign log_determinant() const;
+   void Solver(MatrixColX&, const MatrixColX&);
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX& c) { GetCol((MatrixRowCol&)c); }
+   void cleanup();                                // to clear store
+   void MiniCleanUp();
+   bool IsEqual(const GeneralMatrix&) const;
+   bool is_singular() const { return sing; }
+   bool IsSingular() const { return sing; }
+   const Real* const_data2() const { return store2; }
+   int size2() const { return storage2; }
+   const int* const_data_indx() const { return indx; }
+   bool even_exchanges() const { return d; }
+   MatrixBandWidth bandwidth() const;
+   void swap(BandLUMatrix& gm);
+   NEW_DELETE(BandLUMatrix)
+};
+
+// ************************** special matrices ****************************
+
+/// Identity matrix.
+class IdentityMatrix : public GeneralMatrix
+{
+   GeneralMatrix* Image() const;          // copy of matrix
+public:
+   IdentityMatrix() {}
+   ~IdentityMatrix() {}
+   IdentityMatrix(ArrayLengthSpecifier n) : GeneralMatrix(1)
+      { nrows_val = ncols_val = n.Value(); *store = 1; }
+   IdentityMatrix(const IdentityMatrix& gm)
+      : GeneralMatrix() { GetMatrix(&gm); }
+   IdentityMatrix(const BaseMatrix&);
+   void operator=(const BaseMatrix&);
+   void operator=(const IdentityMatrix& m) { Eq(m); }
+   void operator=(Real f) { GeneralMatrix::operator=(f); }
+   MatrixType type() const;
+
+   LogAndSign log_determinant() const;
+   Real trace() const;
+   Real sum_square() const;
+   Real sum_absolute_value() const;
+   Real sum() const { return trace(); }
+   void GetRow(MatrixRowCol&);
+   void GetCol(MatrixRowCol&);
+   void GetCol(MatrixColX&);
+   void NextRow(MatrixRowCol&);
+   void NextCol(MatrixRowCol&);
+   void NextCol(MatrixColX&);
+   GeneralMatrix* MakeSolver() { return this; } // for solving
+   void Solver(MatrixColX&, const MatrixColX&);
+   GeneralMatrix* Transpose(TransposedMatrix*, MatrixType);
+   void resize(int n);
+   void ReSize(int n) { resize(n); }
+   void resize(const GeneralMatrix& A);
+   void ReSize(const GeneralMatrix& A) { resize(A); }
+   MatrixBandWidth bandwidth() const;
+//   ReturnMatrix Reverse() const;                // reverse order of elements
+   void swap(IdentityMatrix& gm)
+      { GeneralMatrix::swap((GeneralMatrix&)gm); }
+   NEW_DELETE(IdentityMatrix)
+};
+
+
+
+
+// ************************** GenericMatrix class ************************/
+
+/// A matrix which can be of any GeneralMatrix type.
+class GenericMatrix : public BaseMatrix
+{
+   GeneralMatrix* gm;
+   int search(const BaseMatrix* bm) const;
+   friend class BaseMatrix;
+public:
+   GenericMatrix() : gm(0) {}
+   GenericMatrix(const BaseMatrix& bm)
+      { gm = ((BaseMatrix&)bm).Evaluate(); gm = gm->Image(); }
+   GenericMatrix(const GenericMatrix& bm) : BaseMatrix()
+      { gm = bm.gm->Image(); }
+   void operator=(const GenericMatrix&);
+   void operator=(const BaseMatrix&);
+   void operator+=(const BaseMatrix&);
+   void operator-=(const BaseMatrix&);
+   void operator*=(const BaseMatrix&);
+   void operator|=(const BaseMatrix&);
+   void operator&=(const BaseMatrix&);
+   void operator+=(Real);
+   void operator-=(Real r) { operator+=(-r); }
+   void operator*=(Real);
+   void operator/=(Real r) { operator*=(1.0/r); }
+   ~GenericMatrix() { delete gm; }
+   void cleanup() { delete gm; gm = 0; }
+   void Release() { gm->Release(); }
+   void release() { gm->release(); }
+   GeneralMatrix* Evaluate(MatrixType = MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   void swap(GenericMatrix& x);
+   NEW_DELETE(GenericMatrix)
+};
+
+// *************************** temporary classes *************************/
+
+/// Product of two matrices.
+/// \internal
+class MultipliedMatrix : public BaseMatrix
+{
+protected:
+   // if these union statements cause problems, simply remove them
+   // and declare the items individually
+   union { const BaseMatrix* bm1; GeneralMatrix* gm1; };
+						  // pointers to summands
+   union { const BaseMatrix* bm2; GeneralMatrix* gm2; };
+   MultipliedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : bm1(bm1x),bm2(bm2x) {}
+   int search(const BaseMatrix*) const;
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~MultipliedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(MultipliedMatrix)
+};
+
+/// Sum of two matrices.
+/// \internal
+class AddedMatrix : public MultipliedMatrix
+{
+protected:
+   AddedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : MultipliedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~AddedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(AddedMatrix)
+};
+
+/// Schur (elementwise) product of two matrices.
+/// \internal
+class SPMatrix : public AddedMatrix
+{
+protected:
+   SPMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : AddedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~SPMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+
+   friend SPMatrix SP(const BaseMatrix&, const BaseMatrix&);
+
+   NEW_DELETE(SPMatrix)
+};
+
+/// Kronecker product of two matrices.
+/// \internal
+class KPMatrix : public MultipliedMatrix
+{
+protected:
+   KPMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : MultipliedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~KPMatrix() {}
+   MatrixBandWidth bandwidth() const;
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   friend KPMatrix KP(const BaseMatrix&, const BaseMatrix&);
+   NEW_DELETE(KPMatrix)
+};
+
+/// Two matrices horizontally concatenated.
+/// \internal
+class ConcatenatedMatrix : public MultipliedMatrix
+{
+protected:
+   ConcatenatedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : MultipliedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~ConcatenatedMatrix() {}
+   MatrixBandWidth bandwidth() const;
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   NEW_DELETE(ConcatenatedMatrix)
+};
+
+/// Two matrices vertically concatenated.
+/// \internal
+class StackedMatrix : public ConcatenatedMatrix
+{
+protected:
+   StackedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : ConcatenatedMatrix(bm1x,bm2x) {}
+
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~StackedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   NEW_DELETE(StackedMatrix)
+};
+
+/// Inverted matrix times matrix.
+/// \internal
+class SolvedMatrix : public MultipliedMatrix
+{
+   SolvedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : MultipliedMatrix(bm1x,bm2x) {}
+   friend class BaseMatrix;
+   friend class InvertedMatrix;                        // for operator*
+public:
+   ~SolvedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(SolvedMatrix)
+};
+
+/// Difference between two matrices.
+/// \internal
+class SubtractedMatrix : public AddedMatrix
+{
+   SubtractedMatrix(const BaseMatrix* bm1x, const BaseMatrix* bm2x)
+      : AddedMatrix(bm1x,bm2x) {}
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~SubtractedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   NEW_DELETE(SubtractedMatrix)
+};
+
+/// Any type of matrix plus Real.
+/// \internal
+class ShiftedMatrix : public BaseMatrix
+{
+protected:
+   union { const BaseMatrix* bm; GeneralMatrix* gm; };
+   Real f;
+   ShiftedMatrix(const BaseMatrix* bmx, Real fx) : bm(bmx),f(fx) {}
+   int search(const BaseMatrix*) const;
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~ShiftedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   friend ShiftedMatrix operator+(Real f, const BaseMatrix& BM);
+   NEW_DELETE(ShiftedMatrix)
+};
+
+/// Real minus matrix.
+/// \internal
+class NegShiftedMatrix : public ShiftedMatrix
+{
+protected:
+   NegShiftedMatrix(Real fx, const BaseMatrix* bmx) : ShiftedMatrix(bmx,fx) {}
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~NegShiftedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   friend NegShiftedMatrix operator-(Real, const BaseMatrix&);
+   NEW_DELETE(NegShiftedMatrix)
+};
+
+/// Any type of matrix times Real.
+/// \internal
+class ScaledMatrix : public ShiftedMatrix
+{
+   ScaledMatrix(const BaseMatrix* bmx, Real fx) : ShiftedMatrix(bmx,fx) {}
+   friend class BaseMatrix;
+   friend class GeneralMatrix;
+   friend class GenericMatrix;
+public:
+   ~ScaledMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   friend ScaledMatrix operator*(Real f, const BaseMatrix& BM);
+   NEW_DELETE(ScaledMatrix)
+};
+
+/// Any type of matrix times -1.
+/// \internal
+class NegatedMatrix : public BaseMatrix
+{
+protected:
+   union { const BaseMatrix* bm; GeneralMatrix* gm; };
+   NegatedMatrix(const BaseMatrix* bmx) : bm(bmx) {}
+   int search(const BaseMatrix*) const;
+private:
+   friend class BaseMatrix;
+public:
+   ~NegatedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(NegatedMatrix)
+};
+
+/// Transposed matrix.
+/// \internal
+class TransposedMatrix : public NegatedMatrix
+{
+   TransposedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~TransposedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(TransposedMatrix)
+};
+
+/// Any type of matrix with order of elements reversed.
+/// \internal
+class ReversedMatrix : public NegatedMatrix
+{
+   ReversedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~ReversedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   NEW_DELETE(ReversedMatrix)
+};
+
+/// Inverse of matrix.
+/// \internal
+class InvertedMatrix : public NegatedMatrix
+{
+   InvertedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+public:
+   ~InvertedMatrix() {}
+   SolvedMatrix operator*(const BaseMatrix&) const;       // inverse(A) * B
+   ScaledMatrix operator*(Real t) const { return BaseMatrix::operator*(t); }
+   friend class BaseMatrix;
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(InvertedMatrix)
+};
+
+/// Any type of matrix interpreted as a RowVector.
+/// \internal
+class RowedMatrix : public NegatedMatrix
+{
+   RowedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~RowedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(RowedMatrix)
+};
+
+/// Any type of matrix interpreted as a ColumnVector.
+/// \internal
+class ColedMatrix : public NegatedMatrix
+{
+   ColedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~ColedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(ColedMatrix)
+};
+
+/// Any type of matrix interpreted as a DiagonalMatrix.
+/// \internal
+class DiagedMatrix : public NegatedMatrix
+{
+   DiagedMatrix(const BaseMatrix* bmx) : NegatedMatrix(bmx) {}
+   friend class BaseMatrix;
+public:
+   ~DiagedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(DiagedMatrix)
+};
+
+/// Any type of matrix interpreted as a (rectangular) Matrix.
+/// \internal
+class MatedMatrix : public NegatedMatrix
+{
+   int nr, nc;
+   MatedMatrix(const BaseMatrix* bmx, int nrx, int ncx)
+      : NegatedMatrix(bmx), nr(nrx), nc(ncx) {}
+   friend class BaseMatrix;
+public:
+   ~MatedMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(MatedMatrix)
+};
+
+/// A matrix in an "envelope' for return from a function.
+/// \internal
+class ReturnMatrix : public BaseMatrix
+{
+   GeneralMatrix* gm;
+   int search(const BaseMatrix*) const;
+public:
+   ~ReturnMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   friend class BaseMatrix;
+   ReturnMatrix(const ReturnMatrix& tm) : BaseMatrix(), gm(tm.gm) {}
+   ReturnMatrix(const GeneralMatrix* gmx) : gm((GeneralMatrix*&)gmx) {}
+//   ReturnMatrix(GeneralMatrix&);
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(ReturnMatrix)
+};
+
+
+// ************************** submatrices ******************************/
+
+/// A submatrix of a matrix.
+/// \internal
+class GetSubMatrix : public NegatedMatrix
+{
+   int row_skip;
+   int row_number;
+   int col_skip;
+   int col_number;
+   bool IsSym;
+
+   GetSubMatrix
+      (const BaseMatrix* bmx, int rs, int rn, int cs, int cn, bool is)
+      : NegatedMatrix(bmx),
+      row_skip(rs), row_number(rn), col_skip(cs), col_number(cn), IsSym(is) {}
+   void SetUpLHS();
+   friend class BaseMatrix;
+public:
+   GetSubMatrix(const GetSubMatrix& g)
+      : NegatedMatrix(g.bm), row_skip(g.row_skip), row_number(g.row_number),
+      col_skip(g.col_skip), col_number(g.col_number), IsSym(g.IsSym) {}
+   ~GetSubMatrix() {}
+   GeneralMatrix* Evaluate(MatrixType mt=MatrixTypeUnSp);
+   void operator=(const BaseMatrix&);
+   void operator+=(const BaseMatrix&);
+   void operator-=(const BaseMatrix&);
+   void operator=(const GetSubMatrix& m) { operator=((const BaseMatrix&)m); }
+   void operator<<(const BaseMatrix&);
+   void operator<<(const double*);                // copy from array
+   void operator<<(const float*);                // copy from array
+   void operator<<(const int*);                 // copy from array
+   MatrixInput operator<<(double);                // for loading a list
+   MatrixInput operator<<(float);                // for loading a list
+   MatrixInput operator<<(int f);
+   void operator=(Real);                        // copy from constant
+   void operator+=(Real);                       // add constant
+   void operator-=(Real r) { operator+=(-r); }  // subtract constant
+   void operator*=(Real);                       // multiply by constant
+   void operator/=(Real r) { operator*=(1.0/r); } // divide by constant
+   void inject(const GeneralMatrix&);           // copy stored els only
+   void Inject(const GeneralMatrix& GM) { inject(GM); }
+   MatrixBandWidth bandwidth() const;
+   NEW_DELETE(GetSubMatrix)
+};
+
+// ******************** linear equation solving ****************************/
+
+/// A class for finding A.i() * B.
+/// This is supposed to choose the appropriate method depending on the
+/// type A. Not very satisfactory as it doesn't know about Cholesky for
+/// for positive definite matrices.
+class LinearEquationSolver : public BaseMatrix
+{
+   GeneralMatrix* gm;
+   int search(const BaseMatrix*) const { return 0; }
+   friend class BaseMatrix;
+public:
+   LinearEquationSolver(const BaseMatrix& bm);
+   ~LinearEquationSolver() { delete gm; }
+   void cleanup() { delete gm; } 
+   GeneralMatrix* Evaluate(MatrixType) { return gm; }
+   // probably should have an error message if MatrixType != UnSp
+   NEW_DELETE(LinearEquationSolver)
+};
+
+// ************************** matrix input *******************************/
+
+/// Class for reading values into a (small) matrix within a program.
+/// \internal
+/// Is able to detect a mismatch in the number of elements.
+
+class MatrixInput
+{
+   int n;                  // number values still to be read
+   Real* r;                // pointer to next location to be read to
+public:
+   MatrixInput(const MatrixInput& mi) : n(mi.n), r(mi.r) {}
+   MatrixInput(int nx, Real* rx) : n(nx), r(rx) {}
+   ~MatrixInput();
+   MatrixInput operator<<(double);
+   MatrixInput operator<<(float);
+   MatrixInput operator<<(int f);
+   friend class GeneralMatrix;
+};
+
+
+
+// **************** a very simple integer array class ********************/
+
+/// A very simple integer array class.
+/// A minimal array class to imitate a C style array but giving dynamic storage
+/// mostly intended for internal use by newmat.
+/// Probably to be replaced by a templated class when I start using templates.
+
+class SimpleIntArray : public Janitor
+{
+protected:
+   int* a;                    ///< pointer to the array
+   int n;                     ///< length of the array
+public:
+   SimpleIntArray(int xn);    ///< build an array length xn
+   SimpleIntArray() : a(0), n(0) {}  ///< build an array length 0
+   ~SimpleIntArray();         ///< return the space to memory
+   int& operator[](int i);    ///< access element of the array - start at 0
+   int operator[](int i) const;
+			      ///< access element of constant array
+   void operator=(int ai);    ///< set the array equal to a constant
+   void operator=(const SimpleIntArray& b);
+			      ///< copy the elements of an array
+   SimpleIntArray(const SimpleIntArray& b);
+			      ///< make a new array equal to an existing one
+   int Size() const { return n; }
+			      ///< return the size of the array
+   int size() const { return n; }
+			      ///< return the size of the array
+   int* Data() { return a; }  ///< pointer to the data
+   const int* Data() const { return a; }  ///< pointer to the data
+   int* data() { return a; }  ///< pointer to the data
+   const int* data() const { return a; }  ///< pointer to the data
+   const int* const_data() const { return a; }  ///< pointer to the data
+   void resize(int i, bool keep = false);
+                              ///< change length, keep data if keep = true
+   void ReSize(int i, bool keep = false) { resize(i, keep); }
+                              ///< change length, keep data if keep = true
+   void resize_keep(int i) { resize(i, true); }
+                              ///< change length, keep data
+   void cleanup() { resize(0); }   ///< set length to zero
+   void CleanUp() { resize(0); }   ///< set length to zero
+   NEW_DELETE(SimpleIntArray)
+};
+
+// ********************** C subscript classes ****************************
+
+/// Let matrix simulate a C type two dimensional array
+class RealStarStar
+{
+   Real** a;
+public:
+   RealStarStar(Matrix& A);
+   ~RealStarStar() { delete [] a; }
+   operator Real**() { return a; }
+};
+
+/// Let matrix simulate a C type const two dimensional array
+class ConstRealStarStar
+{
+   const Real** a;
+public:
+   ConstRealStarStar(const Matrix& A);
+   ~ConstRealStarStar() { delete [] a; }
+   operator const Real**() { return a; }
+};
+
+// *************************** exceptions ********************************/
+
+/// Not positive definite exception.
+class NPDException : public Runtime_error
+{
+public:
+   static unsigned long Select;
+   NPDException(const GeneralMatrix&);
+};
+
+/// Covergence failure exception.
+class ConvergenceException : public Runtime_error
+{
+public:
+   static unsigned long Select;
+   ConvergenceException(const GeneralMatrix& A);
+   ConvergenceException(const char* c);
+};
+
+/// Singular matrix exception.
+class SingularException : public Runtime_error
+{
+public:
+   static unsigned long Select;
+   SingularException(const GeneralMatrix& A);
+};
+
+/// Real overflow exception.
+class OverflowException : public Runtime_error
+{
+public:
+   static unsigned long Select;
+   OverflowException(const char* c);
+};
+
+/// Miscellaneous exception (details in character string). 
+class ProgramException : public Logic_error
+{
+protected:
+   ProgramException();
+public:
+   static unsigned long Select;
+   ProgramException(const char* c);
+   ProgramException(const char* c, const GeneralMatrix&);
+   ProgramException(const char* c, const GeneralMatrix&, const GeneralMatrix&);
+   ProgramException(const char* c, MatrixType, MatrixType);
+};
+
+/// Index exception.
+class IndexException : public Logic_error
+{
+public:
+   static unsigned long Select;
+   IndexException(int i, const GeneralMatrix& A);
+   IndexException(int i, int j, const GeneralMatrix& A);
+   // next two are for access via element function
+   IndexException(int i, const GeneralMatrix& A, bool);
+   IndexException(int i, int j, const GeneralMatrix& A, bool);
+};
+
+/// Cannot convert to vector exception.
+class VectorException : public Logic_error
+{
+public:
+   static unsigned long Select;
+   VectorException();
+   VectorException(const GeneralMatrix& A);
+};
+
+/// A matrix is not square exception.
+class NotSquareException : public Logic_error
+{
+public:
+   static unsigned long Select;
+   NotSquareException(const GeneralMatrix& A);
+   NotSquareException();
+};
+
+/// Submatrix dimension exception.
+class SubMatrixDimensionException : public Logic_error
+{
+public:
+   static unsigned long Select;
+   SubMatrixDimensionException();
+};
+
+/// Incompatible dimensions exception.
+class IncompatibleDimensionsException : public Logic_error
+{
+public:
+   static unsigned long Select;
+   IncompatibleDimensionsException();
+   IncompatibleDimensionsException(const GeneralMatrix&);
+   IncompatibleDimensionsException(const GeneralMatrix&, const GeneralMatrix&);
+};
+
+/// Not defined exception.
+class NotDefinedException : public Logic_error
+{
+public:
+   static unsigned long Select;
+   NotDefinedException(const char* op, const char* matrix);
+};
+
+/// Cannot build matrix with these properties exception.
+class CannotBuildException : public Logic_error
+{
+public:
+   static unsigned long Select;
+   CannotBuildException(const char* matrix);
+};
+
+
+/// Internal newmat exception - shouldn't happen.
+class InternalException : public Logic_error
+{
+public:
+   static unsigned long Select;          // for identifying exception
+   InternalException(const char* c);
+};
+
+// ************************ functions ************************************ //
+
+bool operator==(const GeneralMatrix& A, const GeneralMatrix& B);
+bool operator==(const BaseMatrix& A, const BaseMatrix& B);
+inline bool operator!=(const GeneralMatrix& A, const GeneralMatrix& B)
+   { return ! (A==B); }
+inline bool operator!=(const BaseMatrix& A, const BaseMatrix& B)
+   { return ! (A==B); }
+
+   // inequality operators are dummies included for compatibility
+   // with STL. They throw an exception if actually called.
+inline bool operator<=(const BaseMatrix& A, const BaseMatrix&)
+   { A.IEQND(); return true; }
+inline bool operator>=(const BaseMatrix& A, const BaseMatrix&)
+   { A.IEQND(); return true; }
+inline bool operator<(const BaseMatrix& A, const BaseMatrix&)
+   { A.IEQND(); return true; }
+inline bool operator>(const BaseMatrix& A, const BaseMatrix&)
+   { A.IEQND(); return true; }
+
+bool is_zero(const BaseMatrix& A);
+inline bool IsZero(const BaseMatrix& A) { return is_zero(A); }
+
+Real dotproduct(const Matrix& A, const Matrix& B);
+Matrix crossproduct(const Matrix& A, const Matrix& B);
+ReturnMatrix crossproduct_rows(const Matrix& A, const Matrix& B);
+ReturnMatrix crossproduct_columns(const Matrix& A, const Matrix& B);
+
+inline Real DotProduct(const Matrix& A, const Matrix& B)
+   { return dotproduct(A, B); }
+inline Matrix CrossProduct(const Matrix& A, const Matrix& B)
+   { return crossproduct(A, B); }
+inline ReturnMatrix CrossProductRows(const Matrix& A, const Matrix& B)
+   { return crossproduct_rows(A, B); }
+inline ReturnMatrix CrossProductColumns(const Matrix& A, const Matrix& B)
+   { return crossproduct_columns(A, B); }
+   
+void newmat_block_copy(int n, Real* from, Real* to);
+
+// ********************* friend functions ******************************** //
+
+// Functions declared as friends - G++ wants them declared externally as well
+
+bool Rectangular(MatrixType a, MatrixType b, MatrixType c);
+bool Compare(const MatrixType&, MatrixType&);
+Real dotproduct(const Matrix& A, const Matrix& B);
+SPMatrix SP(const BaseMatrix&, const BaseMatrix&);
+KPMatrix KP(const BaseMatrix&, const BaseMatrix&);
+ShiftedMatrix operator+(Real f, const BaseMatrix& BM);
+NegShiftedMatrix operator-(Real, const BaseMatrix&);
+ScaledMatrix operator*(Real f, const BaseMatrix& BM);
+
+// ********************* inline functions ******************************** //
+
+inline LogAndSign log_determinant(const BaseMatrix& B)
+   { return B.log_determinant(); }
+inline LogAndSign LogDeterminant(const BaseMatrix& B)
+   { return B.log_determinant(); }
+inline Real determinant(const BaseMatrix& B)
+   { return B.determinant(); }
+inline Real Determinant(const BaseMatrix& B)
+   { return B.determinant(); }
+inline Real sum_square(const BaseMatrix& B) { return B.sum_square(); }
+inline Real SumSquare(const BaseMatrix& B) { return B.sum_square(); }
+inline Real norm_Frobenius(const BaseMatrix& B) { return B.norm_Frobenius(); }
+inline Real norm_frobenius(const BaseMatrix& B) { return B.norm_Frobenius(); }
+inline Real NormFrobenius(const BaseMatrix& B) { return B.norm_Frobenius(); }
+inline Real trace(const BaseMatrix& B) { return B.trace(); }
+inline Real Trace(const BaseMatrix& B) { return B.trace(); }
+inline Real sum_absolute_value(const BaseMatrix& B)
+   { return B.sum_absolute_value(); }
+inline Real SumAbsoluteValue(const BaseMatrix& B)
+   { return B.sum_absolute_value(); }
+inline Real sum(const BaseMatrix& B)
+   { return B.sum(); }
+inline Real Sum(const BaseMatrix& B)
+   { return B.sum(); }
+inline Real maximum_absolute_value(const BaseMatrix& B)
+   { return B.maximum_absolute_value(); }
+inline Real MaximumAbsoluteValue(const BaseMatrix& B)
+   { return B.maximum_absolute_value(); }
+inline Real minimum_absolute_value(const BaseMatrix& B)
+   { return B.minimum_absolute_value(); }
+inline Real MinimumAbsoluteValue(const BaseMatrix& B)
+   { return B.minimum_absolute_value(); }
+inline Real maximum(const BaseMatrix& B) { return B.maximum(); }
+inline Real Maximum(const BaseMatrix& B) { return B.maximum(); }
+inline Real minimum(const BaseMatrix& B) { return B.minimum(); }
+inline Real Minimum(const BaseMatrix& B) { return B.minimum(); }
+inline Real norm1(const BaseMatrix& B) { return B.norm1(); }
+inline Real Norm1(const BaseMatrix& B) { return B.norm1(); }
+inline Real norm1(RowVector& RV) { return RV.maximum_absolute_value(); }
+inline Real Norm1(RowVector& RV) { return RV.maximum_absolute_value(); }
+inline Real norm_infinity(const BaseMatrix& B) { return B.norm_infinity(); }
+inline Real NormInfinity(const BaseMatrix& B) { return B.norm_infinity(); }
+inline Real norm_infinity(ColumnVector& CV)
+   { return CV.maximum_absolute_value(); }
+inline Real NormInfinity(ColumnVector& CV)
+   { return CV.maximum_absolute_value(); }
+inline bool IsZero(const GeneralMatrix& A) { return A.IsZero(); }
+inline bool is_zero(const GeneralMatrix& A) { return A.is_zero(); }
+
+
+inline MatrixInput MatrixInput::operator<<(int f) { return *this << (Real)f; }
+inline MatrixInput GeneralMatrix::operator<<(int f) { return *this << (Real)f; }
+inline MatrixInput BandMatrix::operator<<(int f) { return *this << (Real)f; }
+inline MatrixInput GetSubMatrix::operator<<(int f) { return *this << (Real)f; }
+
+inline ReversedMatrix BaseMatrix::Reverse() const { return reverse(); }
+inline RowedMatrix BaseMatrix::AsRow() const { return as_row(); }
+inline ColedMatrix BaseMatrix::AsColumn() const { return as_column(); }
+inline DiagedMatrix BaseMatrix::AsDiagonal() const { return as_diagonal(); }
+inline MatedMatrix BaseMatrix::AsMatrix(int m, int n) const
+   { return as_matrix(m, n); }
+inline GetSubMatrix BaseMatrix::SubMatrix(int fr, int lr, int fc, int lc) const
+   { return submatrix(fr, lr, fc, lc); }
+inline GetSubMatrix BaseMatrix::SymSubMatrix(int f, int l) const
+   { return sym_submatrix(f, l); }
+inline GetSubMatrix BaseMatrix::Row(int f) const { return row(f); }
+inline GetSubMatrix BaseMatrix::Rows(int f, int l) const { return rows(f, l); }
+inline GetSubMatrix BaseMatrix::Column(int f) const { return column(f); }
+inline GetSubMatrix BaseMatrix::Columns(int f, int l) const
+   { return columns(f, l); }
+inline Real BaseMatrix::AsScalar() const { return as_scalar(); }
+
+inline ReturnMatrix GeneralMatrix::ForReturn() const { return for_return(); }
+
+inline void swap(Matrix& A, Matrix& B) { A.swap(B); }
+inline void swap(SquareMatrix& A, SquareMatrix& B) { A.swap(B); }
+inline void swap(nricMatrix& A, nricMatrix& B) { A.swap(B); }
+inline void swap(UpperTriangularMatrix& A, UpperTriangularMatrix& B)
+   { A.swap(B); }
+inline void swap(LowerTriangularMatrix& A, LowerTriangularMatrix& B)
+   { A.swap(B); }
+inline void swap(SymmetricMatrix& A, SymmetricMatrix& B) { A.swap(B); }
+inline void swap(DiagonalMatrix& A, DiagonalMatrix& B) { A.swap(B); }
+inline void swap(RowVector& A, RowVector& B) { A.swap(B); }
+inline void swap(ColumnVector& A, ColumnVector& B) { A.swap(B); }
+inline void swap(CroutMatrix& A, CroutMatrix& B) { A.swap(B); }
+inline void swap(BandMatrix& A, BandMatrix& B) { A.swap(B); }
+inline void swap(UpperBandMatrix& A, UpperBandMatrix& B) { A.swap(B); }
+inline void swap(LowerBandMatrix& A, LowerBandMatrix& B) { A.swap(B); }
+inline void swap(SymmetricBandMatrix& A, SymmetricBandMatrix& B) { A.swap(B); }
+inline void swap(BandLUMatrix& A, BandLUMatrix& B) { A.swap(B); }
+inline void swap(IdentityMatrix& A, IdentityMatrix& B) { A.swap(B); }
+inline void swap(GenericMatrix& A, GenericMatrix& B) { A.swap(B); }
+
+#ifdef OPT_COMPATIBLE                    // for compatibility with opt++
+
+inline Real Norm2(const ColumnVector& CV) { return CV.norm_Frobenius(); }
+inline Real Dot(ColumnVector& CV1, ColumnVector& CV2)
+   { return dotproduct(CV1, CV2); }
+
+#endif
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+#endif
+
+// body file: newmat1.cpp
+// body file: newmat2.cpp
+// body file: newmat3.cpp
+// body file: newmat4.cpp
+// body file: newmat5.cpp
+// body file: newmat6.cpp
+// body file: newmat7.cpp
+// body file: newmat8.cpp
+// body file: newmatex.cpp
+// body file: bandmat.cpp
+// body file: submat.cpp
+
+
+
+///@}
+
+
+
+
Index: trunk/BNC/newmat/newmat1.cpp
===================================================================
--- trunk/BNC/newmat/newmat1.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmat1.cpp	(revision 2013)
@@ -0,0 +1,209 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmat1.cpp
+/// MatrixType functions.
+/// Find the type of a matrix resulting from a multiply, add etc
+/// Make a new matrix corresponding to a MatrixType
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+//#define WANT_STREAM
+
+#include "newmat.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,1); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/************************* MatrixType functions *****************************/
+
+
+// Skew needs more work <<<<<<<<<
+
+// all operations to return MatrixTypes which correspond to valid types
+// of matrices.
+// Eg: if it has the Diagonal attribute, then it must also have
+// Upper, Lower, Band, Square and Symmetric.
+
+
+MatrixType MatrixType::operator*(const MatrixType& mt) const
+{
+   REPORT
+   int a = attribute & mt.attribute & ~(Symmetric | Skew);
+   a |= (a & Diagonal) * 63;                   // recognise diagonal
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::SP(const MatrixType& mt) const
+// elementwise product
+// Lower, Upper, Diag, Band if only one is
+// Symmetric, Ones, Valid (and Real) if both are
+// Need to include Lower & Upper => Diagonal
+// Will need to include both Skew => Symmetric
+{
+   REPORT
+   int a = ((attribute | mt.attribute) & ~(Symmetric + Skew + Valid + Ones))
+      | (attribute & mt.attribute);
+   if ((a & Lower) != 0  &&  (a & Upper) != 0) a |= Diagonal;
+   if ((attribute & Skew) != 0)
+   {
+      if ((mt.attribute & Symmetric) != 0) a |= Skew;  
+      if ((mt.attribute & Skew) != 0) { a &= ~Skew; a |= Symmetric; }
+   }
+   else if ((mt.attribute & Skew) != 0 && (attribute & Symmetric) != 0)
+      a |= Skew;  
+   a |= (a & Diagonal) * 63;                   // recognise diagonal
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::KP(const MatrixType& mt) const
+// Kronecker product
+// Lower, Upper, Diag, Symmetric, Band, Valid if both are
+// Band if LHS is band & other is square 
+// Ones is complicated so leave this out
+{
+   REPORT
+   int a = (attribute & mt.attribute)  & ~Ones;
+   if ((attribute & Band) != 0 && (mt.attribute & Square) != 0)
+      a |= Band;
+   //int a = ((attribute & mt.attribute) | (attribute & Band)) & ~Ones;
+
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::i() const               // type of inverse
+{
+   REPORT
+   int a = attribute & ~(Band+LUDeco);
+   a |= (a & Diagonal) * 63;                   // recognise diagonal
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::t() const
+// swap lower and upper attributes
+// assume Upper is in bit above Lower
+{
+   REPORT
+   int a = attribute;
+   a ^= (((a >> 1) ^ a) & Lower) * 3;
+   return MatrixType(a);
+}
+
+MatrixType MatrixType::MultRHS() const
+{
+   REPORT
+   // remove symmetric attribute unless diagonal
+   return (attribute >= Dg) ? attribute : (attribute & ~Symmetric);
+}
+
+// this is used for deciding type of multiplication
+bool Rectangular(MatrixType a, MatrixType b, MatrixType c)
+{
+   REPORT
+   return
+      ((a.attribute | b.attribute | c.attribute)
+      & ~(MatrixType::Valid | MatrixType::Square)) == 0;
+}
+
+const char* MatrixType::value() const
+{
+// make a string with the name of matrix with the given attributes
+   switch (attribute)
+   {
+   case Valid:                              REPORT return "Rect ";
+   case Valid+Square:                       REPORT return "Squ  ";
+   case Valid+Symmetric+Square:             REPORT return "Sym  ";
+   case Valid+Skew+Square:                  REPORT return "Skew ";
+   case Valid+Band+Square:                  REPORT return "Band ";
+   case Valid+Symmetric+Band+Square:        REPORT return "SmBnd";
+   case Valid+Skew+Band+Square:             REPORT return "SkBnd";
+   case Valid+Upper+Square:                 REPORT return "UT   ";
+   case Valid+Diagonal+Symmetric+Band+Upper+Lower+Square:
+                                            REPORT return "Diag ";
+   case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones+Square:
+                                            REPORT return "Ident";
+   case Valid+Band+Upper+Square:            REPORT return "UpBnd";
+   case Valid+Lower+Square:                 REPORT return "LT   ";
+   case Valid+Band+Lower+Square:            REPORT return "LwBnd";
+   default:
+      REPORT
+      if (!(attribute & Valid))             return "UnSp ";
+      if (attribute & LUDeco)
+         return (attribute & Band) ?     "BndLU" : "Crout";
+                                            return "?????";
+   }
+}
+
+
+GeneralMatrix* MatrixType::New(int nr, int nc, BaseMatrix* bm) const
+{
+// make a new matrix with the given attributes
+
+   Tracer tr("New"); GeneralMatrix* gm=0;   // initialised to keep gnu happy
+   switch (attribute)
+   {
+   case Valid:
+      REPORT
+      if (nc==1) { gm = new ColumnVector(nr); break; }
+      if (nr==1) { gm = new RowVector(nc); break; }
+      gm = new Matrix(nr, nc); break;
+
+   case Valid+Square:
+      REPORT
+      if (nc!=nr) { Throw(NotSquareException()); }
+      gm = new SquareMatrix(nr); break;
+
+   case Valid+Symmetric+Square:
+      REPORT gm = new SymmetricMatrix(nr); break;
+
+   case Valid+Band+Square:
+      {
+         REPORT
+         MatrixBandWidth bw = bm->bandwidth();
+         gm = new BandMatrix(nr,bw.lower_val,bw.upper_val); break;
+      }
+
+   case Valid+Symmetric+Band+Square:
+      REPORT gm = new SymmetricBandMatrix(nr,bm->bandwidth().lower_val); break;
+
+   case Valid+Upper+Square:
+      REPORT gm = new UpperTriangularMatrix(nr); break;
+
+   case Valid+Diagonal+Symmetric+Band+Upper+Lower+Square:
+      REPORT gm = new DiagonalMatrix(nr); break;
+
+   case Valid+Band+Upper+Square:
+      REPORT gm = new UpperBandMatrix(nr,bm->bandwidth().upper_val); break;
+
+   case Valid+Lower+Square:
+      REPORT gm = new LowerTriangularMatrix(nr); break;
+
+   case Valid+Band+Lower+Square:
+      REPORT gm = new LowerBandMatrix(nr,bm->bandwidth().lower_val); break;
+
+   case Valid+Diagonal+Symmetric+Band+Upper+Lower+Ones+Square:
+      REPORT gm = new IdentityMatrix(nr); break;
+
+   default:
+      Throw(ProgramException("Invalid matrix type"));
+   }
+   
+   MatrixErrorNoSpace(gm); gm->Protect(); return gm;
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+///@}
Index: trunk/BNC/newmat/newmat2.cpp
===================================================================
--- trunk/BNC/newmat/newmat2.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmat2.cpp	(revision 2013)
@@ -0,0 +1,658 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmat2.cpp
+/// Matrix row and column operations.
+/// The operations on individual rows and columns used to carry out matrix
+/// add, multiply etc.
+
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,2); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+//#define MONITOR(what,storage,store) { cout << what << " " << storage << " at " << (long)store << "\n"; }
+
+#define MONITOR(what,store,storage) {}
+
+/************************** Matrix Row/Col functions ************************/
+
+void MatrixRowCol::Add(const MatrixRowCol& mrc)
+{
+   // THIS += mrc
+   REPORT
+   int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
+   if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
+   if (l<=0) return;
+   Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip);
+   while (l--) *elx++ += *el++;
+}
+
+void MatrixRowCol::AddScaled(const MatrixRowCol& mrc, Real x)
+{
+   REPORT
+   // THIS += (mrc * x)
+   int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
+   if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
+   if (l<=0) return;
+   Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip);
+   while (l--) *elx++ += *el++ * x;
+}
+
+void MatrixRowCol::Sub(const MatrixRowCol& mrc)
+{
+   REPORT
+   // THIS -= mrc
+   int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
+   if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
+   if (l<=0) return;
+   Real* elx=data+(f-skip); Real* el=mrc.data+(f-mrc.skip);
+   while (l--) *elx++ -= *el++;
+}
+
+void MatrixRowCol::Inject(const MatrixRowCol& mrc)
+// copy stored elements only
+{
+   REPORT
+   int f = mrc.skip; int l = f + mrc.storage; int lx = skip + storage;
+   if (f < skip) f = skip; if (l > lx) l = lx; l -= f;
+   if (l<=0) return;
+   Real* elx=data+(f-skip); Real* ely=mrc.data+(f-mrc.skip);
+   while (l--) *elx++ = *ely++;
+}
+
+Real DotProd(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+{
+   REPORT                                         // not accessed
+   int f = mrc1.skip; int f2 = mrc2.skip;
+   int l = f + mrc1.storage; int l2 = f2 + mrc2.storage;
+   if (f < f2) f = f2; if (l > l2) l = l2; l -= f;
+   if (l<=0) return 0.0;
+
+   Real* el1=mrc1.data+(f-mrc1.skip); Real* el2=mrc2.data+(f-mrc2.skip);
+   Real sum = 0.0;
+   while (l--) sum += *el1++ * *el2++;
+   return sum;
+}
+
+void MatrixRowCol::Add(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+{
+   // THIS = mrc1 + mrc2
+   int f = skip; int l = skip + storage;
+   int f1 = mrc1.skip; int l1 = f1 + mrc1.storage;
+   if (f1<f) f1=f; if (l1>l) l1=l;
+   int f2 = mrc2.skip; int l2 = f2 + mrc2.storage;
+   if (f2<f) f2=f; if (l2>l) l2=l;
+   Real* el = data + (f-skip);
+   Real* el1 = mrc1.data+(f1-mrc1.skip); Real* el2 = mrc2.data+(f2-mrc2.skip);
+   if (f1<f2)
+   {
+      int i = f1-f; while (i--) *el++ = 0.0;
+      if (l1<=f2)                              // disjoint
+      {
+         REPORT                                // not accessed
+         i = l1-f1;     while (i--) *el++ = *el1++;
+         i = f2-l1;     while (i--) *el++ = 0.0;
+         i = l2-f2;     while (i--) *el++ = *el2++;
+         i = l-l2;      while (i--) *el++ = 0.0;
+      }
+      else
+      {
+         i = f2-f1;    while (i--) *el++ = *el1++;
+         if (l1<=l2)
+         {
+            REPORT
+            i = l1-f2; while (i--) *el++ = *el1++ + *el2++;
+            i = l2-l1; while (i--) *el++ = *el2++;
+            i = l-l2;  while (i--) *el++ = 0.0;
+         }
+         else
+         {
+            REPORT
+            i = l2-f2; while (i--) *el++ = *el1++ + *el2++;
+            i = l1-l2; while (i--) *el++ = *el1++;
+            i = l-l1;  while (i--) *el++ = 0.0;
+         }
+      }
+   }
+   else
+   {
+      int i = f2-f; while (i--) *el++ = 0.0;
+      if (l2<=f1)                              // disjoint
+      {
+         REPORT                                // not accessed
+         i = l2-f2;     while (i--) *el++ = *el2++;
+         i = f1-l2;     while (i--) *el++ = 0.0;
+         i = l1-f1;     while (i--) *el++ = *el1++;
+         i = l-l1;      while (i--) *el++ = 0.0;
+      }
+      else
+      {
+         i = f1-f2;    while (i--) *el++ = *el2++;
+         if (l2<=l1)
+         {
+            REPORT
+            i = l2-f1; while (i--) *el++ = *el1++ + *el2++;
+            i = l1-l2; while (i--) *el++ = *el1++;
+            i = l-l1;  while (i--) *el++ = 0.0;
+         }
+         else
+         {
+            REPORT
+            i = l1-f1; while (i--) *el++ = *el1++ + *el2++;
+            i = l2-l1; while (i--) *el++ = *el2++;
+            i = l-l2;  while (i--) *el++ = 0.0;
+         }
+      }
+   }
+}
+
+void MatrixRowCol::Sub(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+{
+   // THIS = mrc1 - mrc2
+   int f = skip; int l = skip + storage;
+   int f1 = mrc1.skip; int l1 = f1 + mrc1.storage;
+   if (f1<f) f1=f; if (l1>l) l1=l;
+   int f2 = mrc2.skip; int l2 = f2 + mrc2.storage;
+   if (f2<f) f2=f; if (l2>l) l2=l;
+   Real* el = data + (f-skip);
+   Real* el1 = mrc1.data+(f1-mrc1.skip); Real* el2 = mrc2.data+(f2-mrc2.skip);
+   if (f1<f2)
+   {
+      int i = f1-f; while (i--) *el++ = 0.0;
+      if (l1<=f2)                              // disjoint
+      {
+         REPORT                                // not accessed
+         i = l1-f1;     while (i--) *el++ = *el1++;
+         i = f2-l1;     while (i--) *el++ = 0.0;
+         i = l2-f2;     while (i--) *el++ = - *el2++;
+         i = l-l2;      while (i--) *el++ = 0.0;
+      }
+      else
+      {
+         i = f2-f1;    while (i--) *el++ = *el1++;
+         if (l1<=l2)
+         {
+            REPORT
+            i = l1-f2; while (i--) *el++ = *el1++ - *el2++;
+            i = l2-l1; while (i--) *el++ = - *el2++;
+            i = l-l2;  while (i--) *el++ = 0.0;
+         }
+         else
+         {
+            REPORT
+            i = l2-f2; while (i--) *el++ = *el1++ - *el2++;
+            i = l1-l2; while (i--) *el++ = *el1++;
+            i = l-l1;  while (i--) *el++ = 0.0;
+         }
+      }
+   }
+   else
+   {
+      int i = f2-f; while (i--) *el++ = 0.0;
+      if (l2<=f1)                              // disjoint
+      {
+         REPORT                                // not accessed
+         i = l2-f2;     while (i--) *el++ = - *el2++;
+         i = f1-l2;     while (i--) *el++ = 0.0;
+         i = l1-f1;     while (i--) *el++ = *el1++;
+         i = l-l1;      while (i--) *el++ = 0.0;
+      }
+      else
+      {
+         i = f1-f2;    while (i--) *el++ = - *el2++;
+         if (l2<=l1)
+         {
+            REPORT
+            i = l2-f1; while (i--) *el++ = *el1++ - *el2++;
+            i = l1-l2; while (i--) *el++ = *el1++;
+            i = l-l1;  while (i--) *el++ = 0.0;
+         }
+         else
+         {
+            REPORT
+            i = l1-f1; while (i--) *el++ = *el1++ - *el2++;
+            i = l2-l1; while (i--) *el++ = - *el2++;
+            i = l-l2;  while (i--) *el++ = 0.0;
+         }
+      }
+   }
+}
+
+
+void MatrixRowCol::Add(const MatrixRowCol& mrc1, Real x)
+{
+   // THIS = mrc1 + x
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = x;
+       l1 = l-f;     while (l1--) *elx++ = *ely++ + x;
+       lx -= l;      while (lx--) *elx++ = x;
+}
+
+void MatrixRowCol::NegAdd(const MatrixRowCol& mrc1, Real x)
+{
+   // THIS = x - mrc1
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = x;
+       l1 = l-f;     while (l1--) *elx++ = x - *ely++;
+       lx -= l;      while (lx--) *elx++ = x;
+}
+
+void MatrixRowCol::RevSub(const MatrixRowCol& mrc1)
+{
+   // THIS = mrc - THIS
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) { *elx = - *elx; elx++; }
+       l1 = l-f;     while (l1--) { *elx = *ely++ - *elx; elx++; }
+       lx -= l;      while (lx--) { *elx = - *elx; elx++; }
+}
+
+void MatrixRowCol::ConCat(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+{
+   // THIS = mrc1 | mrc2
+   REPORT
+   int f1 = mrc1.skip; int l1 = f1 + mrc1.storage; int lx = skip + storage;
+   if (f1 < skip) { f1 = skip; if (l1 < f1) l1 = f1; }
+   if (l1 > lx) { l1 = lx; if (f1 > lx) f1 = lx; }
+
+   Real* elx = data;
+
+   int i = f1-skip;  while (i--) *elx++ =0.0;
+   i = l1-f1;
+   if (i)                       // in case f1 would take ely out of range
+      { Real* ely = mrc1.data+(f1-mrc1.skip);  while (i--) *elx++ = *ely++; }
+
+   int f2 = mrc2.skip; int l2 = f2 + mrc2.storage; i = mrc1.length;
+   int skipx = l1 - i; lx -= i; // addresses rel to second seg, maybe -ve
+   if (f2 < skipx) { f2 = skipx; if (l2 < f2) l2 = f2; }
+   if (l2 > lx) { l2 = lx; if (f2 > lx) f2 = lx; }
+
+   i = f2-skipx; while (i--) *elx++ = 0.0;
+   i = l2-f2;
+   if (i)                       // in case f2 would take ely out of range
+      { Real* ely = mrc2.data+(f2-mrc2.skip); while (i--) *elx++ = *ely++; }
+   lx -= l2;     while (lx--) *elx++ = 0.0;
+}
+
+void MatrixRowCol::Multiply(const MatrixRowCol& mrc1)
+// element by element multiply into
+{
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0;
+       l1 = l-f;     while (l1--) *elx++ *= *ely++;
+       lx -= l;      while (lx--) *elx++ = 0;
+}
+
+void MatrixRowCol::Multiply(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+// element by element multiply
+{
+   int f = skip; int l = skip + storage;
+   int f1 = mrc1.skip; int l1 = f1 + mrc1.storage;
+   if (f1<f) f1=f; if (l1>l) l1=l;
+   int f2 = mrc2.skip; int l2 = f2 + mrc2.storage;
+   if (f2<f) f2=f; if (l2>l) l2=l;
+   Real* el = data + (f-skip); int i;
+   if (f1<f2) f1 = f2; if (l1>l2) l1 = l2;
+   if (l1<=f1) { REPORT i = l-f; while (i--) *el++ = 0.0; }  // disjoint
+   else
+   {
+      REPORT
+      Real* el1 = mrc1.data+(f1-mrc1.skip);
+      Real* el2 = mrc2.data+(f1-mrc2.skip);
+      i = f1-f ;    while (i--) *el++ = 0.0;
+      i = l1-f1;    while (i--) *el++ = *el1++ * *el2++;
+      i = l-l1;     while (i--) *el++ = 0.0;
+   }
+}
+
+void MatrixRowCol::KP(const MatrixRowCol& mrc1, const MatrixRowCol& mrc2)
+// row for Kronecker product
+{
+   int f = skip; int s = storage; Real* el = data; int i;
+
+   i = mrc1.skip * mrc2.length;
+   if (i > f)
+   {
+      i -= f; f = 0; if (i > s) { i = s; s = 0; }  else s -= i;
+      while (i--) *el++ = 0.0;
+      if (s == 0) return;
+   }
+   else f -= i;
+
+   i = mrc1.storage; Real* el1 = mrc1.data;
+   int mrc2_skip = mrc2.skip; int mrc2_storage = mrc2.storage;
+   int mrc2_length = mrc2.length;
+   int mrc2_remain = mrc2_length - mrc2_skip - mrc2_storage;
+   while (i--)
+   {
+      int j; Real* el2 = mrc2.data; Real vel1 = *el1;
+      if (f == 0 && mrc2_length <= s)
+      {
+         j = mrc2_skip; s -= j;    while (j--) *el++ = 0.0;
+         j = mrc2_storage; s -= j; while (j--) *el++ = vel1 * *el2++;
+         j = mrc2_remain; s -= j;  while (j--) *el++ = 0.0;
+      }
+      else if (f >= mrc2_length) f -= mrc2_length;
+      else
+      {
+         j = mrc2_skip;
+         if (j > f)
+         {
+            j -= f; f = 0; if (j > s) { j = s; s = 0; } else s -= j;
+            while (j--) *el++ = 0.0;
+         }
+         else f -= j;
+
+         j = mrc2_storage;
+         if (j > f)
+         {
+            j -= f; el2 += f; f = 0; if (j > s) { j = s; s = 0; } else s -= j;
+            while (j--) *el++ = vel1 * *el2++;
+         }
+         else f -= j;
+
+         j = mrc2_remain;
+         if (j > f)
+         {
+            j -= f; f = 0; if (j > s) { j = s; s = 0; } else s -= j;
+            while (j--) *el++ = 0.0;
+         }
+         else f -= j;
+      }
+      if (s == 0) return;
+      ++el1;
+   }
+
+   i = (mrc1.length - mrc1.skip - mrc1.storage) * mrc2.length;
+   if (i > f)
+   {
+      i -= f; if (i > s) i = s;
+      while (i--) *el++ = 0.0;
+   }
+}
+
+
+void MatrixRowCol::Copy(const MatrixRowCol& mrc1)
+{
+   // THIS = mrc1
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = 0;
+
+   if (l-f) ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ = *ely++;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+}
+
+void MatrixRowCol::CopyCheck(const MatrixRowCol& mrc1)
+// Throw an exception if this would lead to a loss of data
+{
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip || l > lx) Throw(ProgramException("Illegal Conversion"));
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ = *ely++;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+}
+
+void MatrixRowCol::Check(const MatrixRowCol& mrc1)
+// Throw an exception if +=, -=, copy etc would lead to a loss of data
+{
+   REPORT
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip || l > lx) Throw(ProgramException("Illegal Conversion"));
+}
+
+void MatrixRowCol::Check()
+// Throw an exception if +=, -= of constant would lead to a loss of data
+// that is: check full row is present
+// may not be appropriate for symmetric matrices
+{
+   REPORT
+   if (skip!=0 || storage!=length)
+      Throw(ProgramException("Illegal Conversion"));
+}
+
+void MatrixRowCol::Negate(const MatrixRowCol& mrc1)
+{
+   // THIS = -mrc1
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ = - *ely++;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+}
+
+void MatrixRowCol::Multiply(const MatrixRowCol& mrc1, Real s)
+{
+   // THIS = mrc1 * s
+   REPORT
+   if (!storage) return;
+   int f = mrc1.skip; int l = f + mrc1.storage; int lx = skip + storage;
+   if (f < skip) { f = skip; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = data; Real* ely = mrc1.data+(f-mrc1.skip);
+
+   int l1 = f-skip;  while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ = *ely++ * s;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+}
+
+void DiagonalMatrix::Solver(MatrixColX& mrc, const MatrixColX& mrc1)
+{
+   // mrc = mrc / mrc1   (elementwise)
+   REPORT
+   int f = mrc1.skip; int f0 = mrc.skip;
+   int l = f + mrc1.storage; int lx = f0 + mrc.storage;
+   if (f < f0) { f = f0; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = mrc.data; Real* eld = store+f;
+
+   int l1 = f-f0;    while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ /= *eld++;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+   // Solver makes sure input and output point to same memory
+}
+
+void IdentityMatrix::Solver(MatrixColX& mrc, const MatrixColX& mrc1)
+{
+   // mrc = mrc / mrc1   (elementwise)
+   REPORT
+   int f = mrc1.skip; int f0 = mrc.skip;
+   int l = f + mrc1.storage; int lx = f0 + mrc.storage;
+   if (f < f0) { f = f0; if (l < f) l = f; }
+   if (l > lx) { l = lx; if (f > lx) f = lx; }
+
+   Real* elx = mrc.data; Real eldv = *store;
+
+   int l1 = f-f0;    while (l1--) *elx++ = 0.0;
+       l1 = l-f;     while (l1--) *elx++ /= eldv;
+       lx -= l;      while (lx--) *elx++ = 0.0;
+   // Solver makes sure input and output point to same memory
+}
+
+void MatrixRowCol::Copy(const double*& r)
+{
+   // THIS = *r
+   REPORT
+   Real* elx = data; const double* ely = r+skip; r += length;
+   int l = storage; while (l--) *elx++ = (Real)*ely++;
+}
+
+void MatrixRowCol::Copy(const float*& r)
+{
+   // THIS = *r
+   REPORT
+   Real* elx = data; const float* ely = r+skip; r += length;
+   int l = storage; while (l--) *elx++ = (Real)*ely++;
+}
+
+void MatrixRowCol::Copy(const int*& r)
+{
+   // THIS = *r
+   REPORT
+   Real* elx = data; const int* ely = r+skip; r += length;
+   int l = storage; while (l--) *elx++ = (Real)*ely++;
+}
+
+void MatrixRowCol::Copy(Real r)
+{
+   // THIS = r
+   REPORT  Real* elx = data; int l = storage; while (l--) *elx++ = r;
+}
+
+void MatrixRowCol::Zero()
+{
+   // THIS = 0
+   REPORT  Real* elx = data; int l = storage; while (l--) *elx++ = 0;
+}
+
+void MatrixRowCol::Multiply(Real r)
+{
+   // THIS *= r
+   REPORT  Real* elx = data; int l = storage; while (l--) *elx++ *= r;
+}
+
+void MatrixRowCol::Add(Real r)
+{
+   // THIS += r
+   REPORT
+   Real* elx = data; int l = storage; while (l--) *elx++ += r;
+}
+
+Real MatrixRowCol::SumAbsoluteValue()
+{
+   REPORT
+   Real sum = 0.0; Real* elx = data; int l = storage;
+   while (l--) sum += fabs(*elx++);
+   return sum;
+}
+
+// max absolute value of r and elements of row/col
+// we use <= or >= in all of these so we are sure of getting
+// r reset at least once.
+Real MatrixRowCol::MaximumAbsoluteValue1(Real r, int& i)
+{
+   REPORT
+   Real* elx = data; int l = storage; int li = -1;
+   while (l--) { Real f = fabs(*elx++); if (r <= f) { r = f; li = l; } }
+   i = (li >= 0) ? storage - li + skip : 0;
+   return r;
+}
+
+// min absolute value of r and elements of row/col
+Real MatrixRowCol::MinimumAbsoluteValue1(Real r, int& i)
+{
+   REPORT
+   Real* elx = data; int l = storage; int li = -1;
+   while (l--) { Real f = fabs(*elx++); if (r >= f) { r = f; li = l; } }
+   i = (li >= 0) ? storage - li + skip : 0;
+   return r;
+}
+
+// max value of r and elements of row/col
+Real MatrixRowCol::Maximum1(Real r, int& i)
+{
+   REPORT
+   Real* elx = data; int l = storage; int li = -1;
+   while (l--) { Real f = *elx++; if (r <= f) { r = f; li = l; } }
+   i = (li >= 0) ? storage - li + skip : 0;
+   return r;
+}
+
+// min value of r and elements of row/col
+Real MatrixRowCol::Minimum1(Real r, int& i)
+{
+   REPORT
+   Real* elx = data; int l = storage; int li = -1;
+   while (l--) { Real f = *elx++; if (r >= f) { r = f; li = l; } }
+   i = (li >= 0) ? storage - li + skip : 0;
+   return r;
+}
+
+Real MatrixRowCol::Sum()
+{
+   REPORT
+   Real sum = 0.0; Real* elx = data; int l = storage;
+   while (l--) sum += *elx++;
+   return sum;
+}
+
+void MatrixRowCol::SubRowCol(MatrixRowCol& mrc, int skip1, int l1) const
+{
+   mrc.length = l1;  int d = skip - skip1;
+   if (d<0) { mrc.skip = 0; mrc.data = data - d; }
+   else  { mrc.skip = d; mrc.data = data; }
+   d = skip + storage - skip1;
+   d = ((l1 < d) ? l1 : d) - mrc.skip;  mrc.storage = (d < 0) ? 0 : d;
+   mrc.cw = 0;
+}
+
+#ifdef use_namespace
+}
+#endif
+
+
+///@}
Index: trunk/BNC/newmat/newmat3.cpp
===================================================================
--- trunk/BNC/newmat/newmat3.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmat3.cpp	(revision 2013)
@@ -0,0 +1,849 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmat3.cpp
+/// Get and restore rows and columns.
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,3); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+//#define MONITOR(what,storage,store)
+//   { cout << what << " " << storage << " at " << (long)store << "\n"; }
+
+#define MONITOR(what,store,storage) {}
+
+
+// Control bits codes for GetRow, GetCol, RestoreRow, RestoreCol
+//
+// LoadOnEntry:
+//    Load data into MatrixRow or Col dummy array under GetRow or GetCol
+// StoreOnExit:
+//    Restore data to original matrix under RestoreRow or RestoreCol
+// DirectPart:
+//    Load or restore only part directly stored; must be set with StoreOnExit
+//    Still have decide how to handle this with symmetric
+// StoreHere:
+//    used in columns only - store data at supplied storage address;
+//    used for GetCol, NextCol & RestoreCol. No need to fill out zeros
+// HaveStore:
+//    dummy array has been assigned (internal use only).
+
+// For symmetric matrices, treat columns as rows unless StoreHere is set;
+// then stick to columns as this will give better performance for doing
+// inverses
+
+// How components are used:
+
+// Use rows wherever possible in preference to columns
+
+// Columns without StoreHere are used in in-exact transpose, sum column,
+// multiply a column vector, and maybe in future access to column,
+// additional multiply functions, add transpose
+
+// Columns with StoreHere are used in exact transpose (not symmetric matrices
+// or vectors, load only)
+
+// Columns with MatrixColX (Store to full column) are used in inverse and solve
+
+// Functions required for each matrix class
+
+// GetRow(MatrixRowCol& mrc)
+// GetCol(MatrixRowCol& mrc)
+// GetCol(MatrixColX& mrc)
+// RestoreRow(MatrixRowCol& mrc)
+// RestoreCol(MatrixRowCol& mrc)
+// RestoreCol(MatrixColX& mrc)
+// NextRow(MatrixRowCol& mrc)
+// NextCol(MatrixRowCol& mrc)
+// NextCol(MatrixColX& mrc)
+
+// The Restore routines assume StoreOnExit has already been checked
+// Defaults for the Next routines are given below
+// Assume cannot have both !DirectPart && StoreHere for MatrixRowCol routines
+
+
+// Default NextRow and NextCol:
+// will work as a default but need to override NextRow for efficiency
+
+void GeneralMatrix::NextRow(MatrixRowCol& mrc)
+{
+   REPORT
+   if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreRow(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<nrows_val) { REPORT this->GetRow(mrc); }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+void GeneralMatrix::NextCol(MatrixRowCol& mrc)
+{
+   REPORT                                                // 423
+   if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreCol(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<ncols_val) { REPORT this->GetCol(mrc); }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+void GeneralMatrix::NextCol(MatrixColX& mrc)
+{
+   REPORT                                                // 423
+   if (+(mrc.cw*StoreOnExit)) { REPORT this->RestoreCol(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<ncols_val) { REPORT this->GetCol(mrc); }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+
+// routines for matrix
+
+void Matrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=0; mrc.storage=mrc.length=ncols_val;
+   mrc.data=store+mrc.rowcol*ncols_val;
+}
+
+
+void Matrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=0; mrc.storage=mrc.length=nrows_val;
+   if ( ncols_val==1 && !(mrc.cw*StoreHere) )      // ColumnVector
+      { REPORT mrc.data=store; }
+   else
+   {
+      Real* ColCopy;
+      if ( !(mrc.cw*(HaveStore+StoreHere)) )
+      {
+         REPORT
+         ColCopy = new Real [nrows_val]; MatrixErrorNoSpace(ColCopy);
+         MONITOR_REAL_NEW("Make (MatGetCol)",nrows_val,ColCopy)
+         mrc.data = ColCopy; mrc.cw += HaveStore;
+      }
+      else { REPORT ColCopy = mrc.data; }
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+mrc.rowcol; int i=nrows_val;
+         //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_val; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_val; }
+      }
+   }
+}
+
+void Matrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=0; mrc.storage=nrows_val; mrc.length=nrows_val;
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT  Real* ColCopy = mrc.data;
+      Real* Mstore = store+mrc.rowcol; int i=nrows_val;
+      //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_val; }
+      if (i) for (;;)
+          { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_val; }
+   }
+}
+
+void Matrix::RestoreCol(MatrixRowCol& mrc)
+{
+   // always check StoreOnExit before calling RestoreCol
+   REPORT                                   // 429
+   if (+(mrc.cw*HaveStore))
+   {
+      REPORT                                // 426
+      Real* Mstore = store+mrc.rowcol; int i=nrows_val;
+      Real* Cstore = mrc.data;
+      // while (i--) { *Mstore = *Cstore++; Mstore+=ncols_val; }
+      if (i) for (;;)
+          { *Mstore = *Cstore++; if (!(--i)) break; Mstore+=ncols_val; }
+   }
+}
+
+void Matrix::RestoreCol(MatrixColX& mrc)
+{
+   REPORT
+   Real* Mstore = store+mrc.rowcol; int i=nrows_val; Real* Cstore = mrc.data;
+   // while (i--) { *Mstore = *Cstore++; Mstore+=ncols_val; }
+   if (i) for (;;)
+      { *Mstore = *Cstore++; if (!(--i)) break; Mstore+=ncols_val; }
+}
+
+void Matrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrMat(); }  // 1808
+
+void Matrix::NextCol(MatrixRowCol& mrc)
+{
+   REPORT                                        // 632
+   if (+(mrc.cw*StoreOnExit)) { REPORT RestoreCol(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<ncols_val)
+   {
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* ColCopy = mrc.data;
+         Real* Mstore = store+mrc.rowcol; int i=nrows_val;
+         //while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_val; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_val; }
+      }
+   }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+void Matrix::NextCol(MatrixColX& mrc)
+{
+   REPORT
+   if (+(mrc.cw*StoreOnExit)) { REPORT RestoreCol(mrc); }
+   mrc.rowcol++;
+   if (mrc.rowcol<ncols_val)
+   {
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* ColCopy = mrc.data;
+         Real* Mstore = store+mrc.rowcol; int i=nrows_val;
+         // while (i--) { *ColCopy++ = *Mstore; Mstore+=ncols_val; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore+=ncols_val; }
+      }
+   }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+// routines for diagonal matrix
+
+void DiagonalMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1;
+   mrc.data=store+mrc.skip; mrc.length=ncols_val;
+}
+
+void DiagonalMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_val;
+   if (+(mrc.cw*StoreHere))              // should not happen
+      Throw(InternalException("DiagonalMatrix::GetCol(MatrixRowCol&)"));
+   else  { REPORT mrc.data=store+mrc.skip; }
+                                                      // not accessed
+}
+
+void DiagonalMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_val;
+   mrc.data = mrc.store+mrc.skip;
+   *(mrc.data)=*(store+mrc.skip);
+}
+
+void DiagonalMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrDiag(); }
+                        // 800
+
+void DiagonalMatrix::NextCol(MatrixRowCol& mrc) { REPORT mrc.IncrDiag(); }
+                        // not accessed
+
+void DiagonalMatrix::NextCol(MatrixColX& mrc)
+{
+   REPORT
+   if (+(mrc.cw*StoreOnExit))
+      { REPORT *(store+mrc.rowcol)=*(mrc.data); }
+   mrc.IncrDiag();
+   int t1 = +(mrc.cw*LoadOnEntry);
+   if (t1 && mrc.rowcol < ncols_val)
+      { REPORT *(mrc.data)=*(store+mrc.rowcol); }
+}
+
+// routines for upper triangular matrix
+
+void UpperTriangularMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int row = mrc.rowcol; mrc.skip=row; mrc.length=ncols_val;
+   mrc.storage=ncols_val-row; mrc.data=store+(row*(2*ncols_val-row+1))/2;
+}
+
+
+void UpperTriangularMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=0; int i=mrc.rowcol+1; mrc.storage=i;
+   mrc.length=nrows_val; Real* ColCopy;
+   if ( !(mrc.cw*(StoreHere+HaveStore)) )
+   {
+      REPORT                                              // not accessed
+      ColCopy = new Real [nrows_val]; MatrixErrorNoSpace(ColCopy);
+      MONITOR_REAL_NEW("Make (UT GetCol)",nrows_val,ColCopy)
+      mrc.data = ColCopy; mrc.cw += HaveStore;
+   }
+   else { REPORT ColCopy = mrc.data; }
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* Mstore = store+mrc.rowcol; int j = ncols_val;
+      // while (i--) { *ColCopy++ = *Mstore; Mstore += --j; }
+      if (i) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += --j; }
+   }
+}
+
+void UpperTriangularMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=0; int i=mrc.rowcol+1; mrc.storage=i;
+   mrc.length=nrows_val;
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* ColCopy = mrc.data;
+      Real* Mstore = store+mrc.rowcol; int j = ncols_val;
+      // while (i--) { *ColCopy++ = *Mstore; Mstore += --j; }
+      if (i) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += --j; }
+   }
+}
+
+void UpperTriangularMatrix::RestoreCol(MatrixRowCol& mrc)
+{
+  REPORT
+  Real* Mstore = store+mrc.rowcol; int i=mrc.rowcol+1; int j = ncols_val;
+  Real* Cstore = mrc.data;
+  // while (i--) { *Mstore = *Cstore++; Mstore += --j; }
+  if (i) for (;;)
+     { *Mstore = *Cstore++; if (!(--i)) break; Mstore += --j; }
+}
+
+void UpperTriangularMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrUT(); }
+						      // 722
+
+// routines for lower triangular matrix
+
+void LowerTriangularMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int row=mrc.rowcol; mrc.skip=0; mrc.storage=row+1; mrc.length=ncols_val;
+   mrc.data=store+(row*(row+1))/2;
+}
+
+void LowerTriangularMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   int col=mrc.rowcol; mrc.skip=col; mrc.length=nrows_val;
+   int i=nrows_val-col; mrc.storage=i; Real* ColCopy;
+   if ( +(mrc.cw*(StoreHere+HaveStore)) )
+      { REPORT  ColCopy = mrc.data; }
+   else
+   {
+      REPORT                                            // not accessed
+      ColCopy = new Real [nrows_val]; MatrixErrorNoSpace(ColCopy);
+      MONITOR_REAL_NEW("Make (LT GetCol)",nrows_val,ColCopy)
+      mrc.cw += HaveStore; mrc.data = ColCopy;
+   }
+
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* Mstore = store+(col*(col+3))/2;
+      // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+      if (i) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+   }
+}
+
+void LowerTriangularMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   int col=mrc.rowcol; mrc.skip=col; mrc.length=nrows_val;
+   int i=nrows_val-col; mrc.storage=i; mrc.data = mrc.store + col;
+
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT  Real* ColCopy = mrc.data;
+      Real* Mstore = store+(col*(col+3))/2;
+      // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+      if (i) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+   }
+}
+
+void LowerTriangularMatrix::RestoreCol(MatrixRowCol& mrc)
+{
+   REPORT
+   int col=mrc.rowcol; Real* Cstore = mrc.data;
+   Real* Mstore = store+(col*(col+3))/2; int i=nrows_val-col;
+   //while (i--) { *Mstore = *Cstore++; Mstore += ++col; }
+   if (i) for (;;)
+      { *Mstore = *Cstore++; if (!(--i)) break; Mstore += ++col; }
+}
+
+void LowerTriangularMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrLT(); }
+					                 //712
+
+// routines for symmetric matrix
+
+void SymmetricMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT                                                //571
+   mrc.skip=0; int row=mrc.rowcol; mrc.length=ncols_val;
+   if (+(mrc.cw*DirectPart))
+      { REPORT mrc.storage=row+1; mrc.data=store+(row*(row+1))/2; }
+   else
+   {
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricMatrix::GetRow(MatrixRowCol&)"));
+      mrc.storage=ncols_val; Real* RowCopy;
+      if (!(mrc.cw*HaveStore))
+      {
+         REPORT
+         RowCopy = new Real [ncols_val]; MatrixErrorNoSpace(RowCopy);
+         MONITOR_REAL_NEW("Make (SymGetRow)",ncols_val,RowCopy)
+         mrc.cw += HaveStore; mrc.data = RowCopy;
+      }
+      else { REPORT RowCopy = mrc.data; }
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT                                         // 544
+         Real* Mstore = store+(row*(row+1))/2; int i = row;
+         while (i--) *RowCopy++ = *Mstore++;
+         i = ncols_val-row;
+         // while (i--) { *RowCopy++ = *Mstore; Mstore += ++row; }
+         if (i) for (;;)
+            { *RowCopy++ = *Mstore; if (!(--i)) break; Mstore += ++row; }
+      }
+   }
+}
+
+void SymmetricMatrix::GetCol(MatrixRowCol& mrc)
+{
+   // do not allow StoreHere
+   if (+(mrc.cw*StoreHere))
+      Throw(InternalException("SymmetricMatrix::GetCol(MatrixRowCol&)"));
+
+   int col=mrc.rowcol; mrc.length=nrows_val;
+   REPORT
+   mrc.skip=0;
+   if (+(mrc.cw*DirectPart))    // actually get row ??
+      { REPORT mrc.storage=col+1; mrc.data=store+(col*(col+1))/2; }
+   else
+   {
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricMatrix::GetCol(MatrixRowCol&)"));
+
+      mrc.storage=ncols_val; Real* ColCopy;
+      if ( +(mrc.cw*HaveStore)) { REPORT ColCopy = mrc.data; }
+      else
+      {
+         REPORT                                      // not accessed
+         ColCopy = new Real [ncols_val]; MatrixErrorNoSpace(ColCopy);
+         MONITOR_REAL_NEW("Make (SymGetCol)",ncols_val,ColCopy)
+         mrc.cw += HaveStore; mrc.data = ColCopy;
+      }
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+(col*(col+1))/2; int i = col;
+         while (i--) *ColCopy++ = *Mstore++;
+         i = ncols_val-col;
+         // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+      }
+   }
+}
+
+void SymmetricMatrix::GetCol(MatrixColX& mrc)
+{
+   int col=mrc.rowcol; mrc.length=nrows_val;
+   if (+(mrc.cw*DirectPart))
+   {
+      REPORT
+      mrc.skip=col; int i=nrows_val-col; mrc.storage=i;
+      mrc.data = mrc.store+col;
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT                           // not accessed
+         Real* ColCopy = mrc.data;
+         Real* Mstore = store+(col*(col+3))/2;
+         // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+      }
+   }
+   else
+   {
+      REPORT
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricMatrix::GetCol(MatrixColX&)"));
+
+      mrc.skip=0; mrc.storage=ncols_val;
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* ColCopy = mrc.data;
+         Real* Mstore = store+(col*(col+1))/2; int i = col;
+         while (i--) *ColCopy++ = *Mstore++;
+         i = ncols_val-col;
+         // while (i--) { *ColCopy++ = *Mstore; Mstore += ++col; }
+         if (i) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--i)) break; Mstore += ++col; }
+      }
+   }
+}
+
+// Do not need RestoreRow because we do not allow !DirectPart && StoreOnExit
+
+void SymmetricMatrix::RestoreCol(MatrixColX& mrc)
+{
+   REPORT
+   // Really do restore column
+   int col=mrc.rowcol; Real* Cstore = mrc.data;
+   Real* Mstore = store+(col*(col+3))/2; int i = nrows_val-col;
+   // while (i--) { *Mstore = *Cstore++; Mstore+= ++col; }
+   if (i) for (;;)
+      { *Mstore = *Cstore++; if (!(--i)) break; Mstore+= ++col; }
+
+}
+
+// routines for row vector
+
+void RowVector::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   // do not allow StoreHere
+   if (+(mrc.cw*StoreHere))
+      Throw(InternalException("RowVector::GetCol(MatrixRowCol&)"));
+
+   mrc.skip=0; mrc.storage=1; mrc.length=nrows_val;
+   mrc.data = store+mrc.rowcol;
+
+}
+
+void RowVector::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=0; mrc.storage=1; mrc.length=nrows_val;
+   if (mrc.cw >= LoadOnEntry)
+      { REPORT *(mrc.data) = *(store+mrc.rowcol); }
+
+}
+
+void RowVector::NextCol(MatrixRowCol& mrc)
+{ REPORT mrc.rowcol++; mrc.data++; }
+
+void RowVector::NextCol(MatrixColX& mrc)
+{
+   if (+(mrc.cw*StoreOnExit)) { REPORT *(store+mrc.rowcol)=*(mrc.data); }
+
+   mrc.rowcol++;
+   if (mrc.rowcol < ncols_val)
+   {
+      if (+(mrc.cw*LoadOnEntry)) { REPORT *(mrc.data)=*(store+mrc.rowcol); }
+   }
+   else { REPORT mrc.cw -= StoreOnExit; }
+}
+
+void RowVector::RestoreCol(MatrixColX& mrc)
+   { REPORT *(store+mrc.rowcol)=*(mrc.data); }           // not accessed
+
+
+// routines for band matrices
+
+void BandMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int r = mrc.rowcol; int w = lower_val+1+upper_val; mrc.length=ncols_val;
+   int s = r-lower_val;
+   if (s<0) { mrc.data = store+(r*w-s); w += s; s = 0; }
+   else mrc.data = store+r*w;
+   mrc.skip = s; s += w-ncols_val; if (s>0) w -= s; mrc.storage = w;
+}
+
+// should make special versions of this for upper and lower band matrices
+
+void BandMatrix::NextRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int r = ++mrc.rowcol;
+   if (r<=lower_val) { mrc.storage++; mrc.data += lower_val+upper_val; }
+   else  { mrc.skip++; mrc.data += lower_val+upper_val+1; }
+   if (r>=ncols_val-upper_val) mrc.storage--;
+}
+
+void BandMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   int c = mrc.rowcol; int n = lower_val+upper_val; int w = n+1;
+   mrc.length=nrows_val; Real* ColCopy;
+   int b; int s = c-upper_val;
+   if (s<=0) { w += s; s = 0; b = c+lower_val; } else b = s*w+n;
+   mrc.skip = s; s += w-nrows_val; if (s>0) w -= s; mrc.storage = w;
+   if ( +(mrc.cw*(StoreHere+HaveStore)) )
+      { REPORT ColCopy = mrc.data; }
+   else
+   {
+      REPORT
+      ColCopy = new Real [n+1]; MatrixErrorNoSpace(ColCopy);
+      MONITOR_REAL_NEW("Make (BMGetCol)",n+1,ColCopy)
+      mrc.cw += HaveStore; mrc.data = ColCopy;
+   }
+
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* Mstore = store+b;
+      // while (w--) { *ColCopy++ = *Mstore; Mstore+=n; }
+      if (w) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--w)) break; Mstore+=n; }
+   }
+}
+
+void BandMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   int c = mrc.rowcol; int n = lower_val+upper_val; int w = n+1;
+   mrc.length=nrows_val; int b; int s = c-upper_val;
+   if (s<=0) { w += s; s = 0; b = c+lower_val; } else b = s*w+n;
+   mrc.skip = s; s += w-nrows_val; if (s>0) w -= s; mrc.storage = w;
+   mrc.data = mrc.store+mrc.skip;
+
+   if (+(mrc.cw*LoadOnEntry))
+   {
+      REPORT
+      Real* ColCopy = mrc.data; Real* Mstore = store+b;
+      // while (w--) { *ColCopy++ = *Mstore; Mstore+=n; }
+      if (w) for (;;)
+         { *ColCopy++ = *Mstore; if (!(--w)) break; Mstore+=n; }
+   }
+}
+
+void BandMatrix::RestoreCol(MatrixRowCol& mrc)
+{
+   REPORT
+   int c = mrc.rowcol; int n = lower_val+upper_val; int s = c-upper_val;
+   Real* Mstore = store + ((s<=0) ? c+lower_val : s*n+s+n);
+   Real* Cstore = mrc.data;
+   int w = mrc.storage;
+   // while (w--) { *Mstore = *Cstore++; Mstore += n; }
+   if (w) for (;;)
+      { *Mstore = *Cstore++; if (!(--w)) break; Mstore += n; }
+}
+
+// routines for symmetric band matrix
+
+void SymmetricBandMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   int r=mrc.rowcol; int s = r-lower_val; int w1 = lower_val+1; int o = r*w1;
+   mrc.length = ncols_val;
+   if (s<0) { w1 += s; o -= s; s = 0; }
+   mrc.skip = s;
+
+   if (+(mrc.cw*DirectPart))
+      { REPORT  mrc.data = store+o; mrc.storage = w1; }
+   else
+   {
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricBandMatrix::GetRow(MatrixRowCol&)"));
+      int w = w1+lower_val; s += w-ncols_val; Real* RowCopy;
+      if (s>0) w -= s; mrc.storage = w; int w2 = w-w1;
+      if (!(mrc.cw*HaveStore))
+      {
+         REPORT
+         RowCopy = new Real [2*lower_val+1]; MatrixErrorNoSpace(RowCopy);
+         MONITOR_REAL_NEW("Make (SmBGetRow)",2*lower_val+1,RowCopy)
+         mrc.cw += HaveStore; mrc.data = RowCopy;
+      }
+      else { REPORT  RowCopy = mrc.data; }
+
+      if (+(mrc.cw*LoadOnEntry) && ncols_val > 0)
+      {
+         REPORT
+         Real* Mstore = store+o;
+         while (w1--) *RowCopy++ = *Mstore++;
+         Mstore--;
+         while (w2--) { Mstore += lower_val; *RowCopy++ = *Mstore; }
+      }
+   }
+}
+
+void SymmetricBandMatrix::GetCol(MatrixRowCol& mrc)
+{
+   // do not allow StoreHere
+   if (+(mrc.cw*StoreHere))
+      Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixRowCol&)"));
+
+   int c=mrc.rowcol; int w1 = lower_val+1; mrc.length=nrows_val;
+   REPORT
+   int s = c-lower_val; int o = c*w1;
+   if (s<0) { w1 += s; o -= s; s = 0; }
+   mrc.skip = s;
+
+   if (+(mrc.cw*DirectPart))
+   { REPORT  mrc.data = store+o; mrc.storage = w1; }
+   else
+   {
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixRowCol&)"));
+      int w = w1+lower_val; s += w-ncols_val; Real* ColCopy;
+      if (s>0) w -= s; mrc.storage = w; int w2 = w-w1;
+
+      if ( +(mrc.cw*HaveStore) ) { REPORT ColCopy = mrc.data; }
+      else
+      {
+         REPORT ColCopy = new Real [2*lower_val+1]; MatrixErrorNoSpace(ColCopy);
+         MONITOR_REAL_NEW("Make (SmBGetCol)",2*lower_val+1,ColCopy)
+         mrc.cw += HaveStore; mrc.data = ColCopy;
+      }
+
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+o;
+         while (w1--) *ColCopy++ = *Mstore++;
+         Mstore--;
+         while (w2--) { Mstore += lower_val; *ColCopy++ = *Mstore; }
+      }
+   }
+}
+
+void SymmetricBandMatrix::GetCol(MatrixColX& mrc)
+{
+   int c=mrc.rowcol; int w1 = lower_val+1; mrc.length=nrows_val;
+   if (+(mrc.cw*DirectPart))
+   {
+      REPORT
+      int b = c*w1+lower_val;
+      mrc.skip = c; c += w1-nrows_val; w1 -= c; mrc.storage = w1;
+      Real* ColCopy = mrc.data = mrc.store+mrc.skip;
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+b;
+         // while (w1--) { *ColCopy++ = *Mstore; Mstore += lower; }
+         if (w1) for (;;)
+            { *ColCopy++ = *Mstore; if (!(--w1)) break; Mstore += lower_val; }
+      }
+   }
+   else
+   {
+      REPORT
+      // do not allow StoreOnExit and !DirectPart
+      if (+(mrc.cw*StoreOnExit))
+         Throw(InternalException("SymmetricBandMatrix::GetCol(MatrixColX&)"));
+      int s = c-lower_val; int o = c*w1;
+      if (s<0) { w1 += s; o -= s; s = 0; }
+      mrc.skip = s;
+
+      int w = w1+lower_val; s += w-ncols_val;
+      if (s>0) w -= s; mrc.storage = w; int w2 = w-w1;
+
+      Real* ColCopy = mrc.data = mrc.store+mrc.skip;
+
+      if (+(mrc.cw*LoadOnEntry))
+      {
+         REPORT
+         Real* Mstore = store+o;
+         while (w1--) *ColCopy++ = *Mstore++;
+         Mstore--;
+         while (w2--) { Mstore += lower_val; *ColCopy++ = *Mstore; }
+      }
+
+   }
+}
+
+void SymmetricBandMatrix::RestoreCol(MatrixColX& mrc)
+{
+   REPORT
+   int c = mrc.rowcol;
+   Real* Mstore = store + c*lower_val+c+lower_val;
+   Real* Cstore = mrc.data; int w = mrc.storage;
+   // while (w--) { *Mstore = *Cstore++; Mstore += lower_val; }
+   if (w) for (;;)
+      { *Mstore = *Cstore++; if (!(--w)) break; Mstore += lower_val; }
+}
+
+// routines for identity matrix
+
+void IdentityMatrix::GetRow(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.data=store; mrc.length=ncols_val;
+}
+
+void IdentityMatrix::GetCol(MatrixRowCol& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_val;
+   if (+(mrc.cw*StoreHere))              // should not happen
+      Throw(InternalException("IdentityMatrix::GetCol(MatrixRowCol&)"));
+   else  { REPORT mrc.data=store; }
+}
+
+void IdentityMatrix::GetCol(MatrixColX& mrc)
+{
+   REPORT
+   mrc.skip=mrc.rowcol; mrc.storage=1; mrc.length=nrows_val;
+   mrc.data = mrc.store+mrc.skip; *(mrc.data)=*store;
+}
+
+void IdentityMatrix::NextRow(MatrixRowCol& mrc) { REPORT mrc.IncrId(); }
+
+void IdentityMatrix::NextCol(MatrixRowCol& mrc) { REPORT mrc.IncrId(); }
+
+void IdentityMatrix::NextCol(MatrixColX& mrc)
+{
+   REPORT
+   if (+(mrc.cw*StoreOnExit)) { REPORT *store=*(mrc.data); }
+   mrc.IncrDiag();            // must increase mrc.data so need IncrDiag
+   int t1 = +(mrc.cw*LoadOnEntry);
+   if (t1 && mrc.rowcol < ncols_val) { REPORT *(mrc.data)=*store; }
+}
+
+
+
+
+// *************************** destructors *******************************
+
+MatrixRowCol::~MatrixRowCol()
+{
+   if (+(cw*HaveStore))
+   {
+      MONITOR_REAL_DELETE("Free    (RowCol)",-1,data)  // do not know length
+      delete [] data;
+   }
+}
+
+MatrixRow::~MatrixRow() { if (+(cw*StoreOnExit)) gm->RestoreRow(*this); }
+
+MatrixCol::~MatrixCol() { if (+(cw*StoreOnExit)) gm->RestoreCol(*this); }
+
+MatrixColX::~MatrixColX() { if (+(cw*StoreOnExit)) gm->RestoreCol(*this); }
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
Index: trunk/BNC/newmat/newmat4.cpp
===================================================================
--- trunk/BNC/newmat/newmat4.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmat4.cpp	(revision 2013)
@@ -0,0 +1,1387 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmat4.cpp
+/// Constructors, resize, basic utilities, SimpleIntArray.
+
+
+// Copyright (C) 1991,2,3,4,8,9: R B Davies
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,4); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+#define DO_SEARCH                   // search for LHS of = in RHS
+
+// ************************* general utilities *************************/
+
+static int tristore(int n)                    // elements in triangular matrix
+{ return (n*(n+1))/2; }
+
+
+// **************************** constructors ***************************/
+
+GeneralMatrix::GeneralMatrix()
+{ store=0; storage=0; nrows_val=0; ncols_val=0; tag_val=-1; }
+
+GeneralMatrix::GeneralMatrix(ArrayLengthSpecifier s)
+{
+   REPORT
+   storage=s.Value(); tag_val=-1;
+   if (storage)
+   {
+      store = new Real [storage]; MatrixErrorNoSpace(store);
+      MONITOR_REAL_NEW("Make (GenMatrix)",storage,store)
+   }
+   else store = 0;
+}
+
+Matrix::Matrix(int m, int n) : GeneralMatrix(m*n)
+{ REPORT nrows_val=m; ncols_val=n; }
+
+SquareMatrix::SquareMatrix(ArrayLengthSpecifier n)
+   : Matrix(n.Value(),n.Value())
+{ REPORT }
+
+SymmetricMatrix::SymmetricMatrix(ArrayLengthSpecifier n)
+   : GeneralMatrix(tristore(n.Value()))
+{ REPORT nrows_val=n.Value(); ncols_val=n.Value(); }
+
+UpperTriangularMatrix::UpperTriangularMatrix(ArrayLengthSpecifier n)
+   : GeneralMatrix(tristore(n.Value()))
+{ REPORT nrows_val=n.Value(); ncols_val=n.Value(); }
+
+LowerTriangularMatrix::LowerTriangularMatrix(ArrayLengthSpecifier n)
+   : GeneralMatrix(tristore(n.Value()))
+{ REPORT nrows_val=n.Value(); ncols_val=n.Value(); }
+
+DiagonalMatrix::DiagonalMatrix(ArrayLengthSpecifier m) : GeneralMatrix(m)
+{ REPORT nrows_val=m.Value(); ncols_val=m.Value(); }
+
+Matrix::Matrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Rt);
+   GetMatrix(gmx);
+}
+
+SquareMatrix::SquareMatrix(const BaseMatrix& M) : Matrix(M)
+{
+   REPORT
+   if (ncols_val != nrows_val)
+   {
+      Tracer tr("SquareMatrix");
+      Throw(NotSquareException(*this));
+   }
+}
+
+
+SquareMatrix::SquareMatrix(const Matrix& gm)
+{
+   REPORT
+   if (gm.ncols_val != gm.nrows_val)
+   {
+      Tracer tr("SquareMatrix(Matrix)");
+      Throw(NotSquareException(gm));
+   }
+   GetMatrix(&gm);
+}
+
+
+RowVector::RowVector(const BaseMatrix& M) : Matrix(M)
+{
+   REPORT
+   if (nrows_val!=1)
+   {
+      Tracer tr("RowVector");
+      Throw(VectorException(*this));
+   }
+}
+
+ColumnVector::ColumnVector(const BaseMatrix& M) : Matrix(M)
+{
+   REPORT
+   if (ncols_val!=1)
+   {
+      Tracer tr("ColumnVector");
+      Throw(VectorException(*this));
+   }
+}
+
+SymmetricMatrix::SymmetricMatrix(const BaseMatrix& M)
+{
+   REPORT  // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Sm);
+   GetMatrix(gmx);
+}
+
+UpperTriangularMatrix::UpperTriangularMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::UT);
+   GetMatrix(gmx);
+}
+
+LowerTriangularMatrix::LowerTriangularMatrix(const BaseMatrix& M)
+{
+   REPORT // CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::LT);
+   GetMatrix(gmx);
+}
+
+DiagonalMatrix::DiagonalMatrix(const BaseMatrix& M)
+{
+   REPORT //CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Dg);
+   GetMatrix(gmx);
+}
+
+IdentityMatrix::IdentityMatrix(const BaseMatrix& M)
+{
+   REPORT //CheckConversion(M);
+   // MatrixConversionCheck mcc;
+   GeneralMatrix* gmx=((BaseMatrix&)M).Evaluate(MatrixType::Id);
+   GetMatrix(gmx);
+}
+
+GeneralMatrix::~GeneralMatrix()
+{
+   if (store)
+   {
+      MONITOR_REAL_DELETE("Free (GenMatrix)",storage,store)
+      delete [] store;
+   }
+}
+
+CroutMatrix::CroutMatrix(const BaseMatrix& m)
+{
+   REPORT
+   Tracer tr("CroutMatrix");
+   indx = 0;                     // in case of exception at next line
+   GeneralMatrix* gm = ((BaseMatrix&)m).Evaluate();
+   if (gm->nrows_val!=gm->ncols_val)
+      { gm->tDelete(); Throw(NotSquareException(*gm)); }
+   if (gm->type() == MatrixType::Ct)
+      { REPORT  ((CroutMatrix*)gm)->get_aux(*this); GetMatrix(gm); }
+   else
+   {
+      REPORT
+      GeneralMatrix* gm1 = gm->Evaluate(MatrixType::Rt);
+      GetMatrix(gm1);
+      d=true; sing=false;
+      indx=new int [nrows_val]; MatrixErrorNoSpace(indx);
+      MONITOR_INT_NEW("Index (CroutMat)",nrows_val,indx)
+      ludcmp();
+   }
+}
+
+// could we use SetParameters instead of this
+void CroutMatrix::get_aux(CroutMatrix& X)
+{
+   X.d = d; X.sing = sing;
+   if (tag_val == 0 || tag_val == 1) // reuse the array 
+      { REPORT  X.indx = indx; indx = 0; d = true; sing = true; return; }
+   else if (nrows_val == 0)
+      { REPORT indx = 0; d = true; sing = true; return; }
+   else                              // copy the array
+   { 
+      REPORT
+      Tracer tr("CroutMatrix::get_aux");
+      int *ix = new int [nrows_val]; MatrixErrorNoSpace(ix);
+      MONITOR_INT_NEW("Index (CM::get_aux)", nrows_val, ix)
+      int n = nrows_val; int* i = ix; int* j = indx;
+      while(n--) *i++ = *j++;
+      X.indx = ix;
+   }
+}
+
+CroutMatrix::CroutMatrix(const CroutMatrix& gm) : GeneralMatrix()
+{
+   REPORT
+   Tracer tr("CroutMatrix(const CroutMatrix&)");
+   ((CroutMatrix&)gm).get_aux(*this);
+   GetMatrix(&gm);
+}
+
+CroutMatrix::~CroutMatrix()
+{
+   MONITOR_INT_DELETE("Index (CroutMat)",nrows_val,indx)
+   delete [] indx;
+}
+
+//ReturnMatrix::ReturnMatrix(GeneralMatrix& gmx)
+//{
+//   REPORT
+//   gm = gmx.Image(); gm->ReleaseAndDelete();
+//}
+
+
+GeneralMatrix::operator ReturnMatrix() const
+{
+   REPORT
+   GeneralMatrix* gm = Image(); gm->ReleaseAndDelete();
+   return ReturnMatrix(gm);
+}
+
+
+
+ReturnMatrix GeneralMatrix::for_return() const
+{
+   REPORT
+   GeneralMatrix* gm = Image(); gm->ReleaseAndDelete();
+   return ReturnMatrix(gm);
+}
+
+// ************ Constructors for use with NR in C++ interface ***********
+
+#ifdef SETUP_C_SUBSCRIPTS
+
+Matrix::Matrix(Real a, int m, int n) : GeneralMatrix(m * n)
+   { REPORT nrows_val=m; ncols_val=n; operator=(a); }
+   
+Matrix::Matrix(const Real* a, int m, int n) : GeneralMatrix(m * n)
+   { REPORT nrows_val=m; ncols_val=n; *this << a; }
+
+#endif
+
+
+
+// ************************** resize matrices ***************************/
+
+void GeneralMatrix::resize(int nr, int nc, int s)
+{
+   REPORT
+   if (store)
+   {
+      MONITOR_REAL_DELETE("Free (ReDimensi)",storage,store)
+      delete [] store;
+   }
+   storage=s; nrows_val=nr; ncols_val=nc; tag_val=-1;
+   if (s)
+   {
+      store = new Real [storage]; MatrixErrorNoSpace(store);
+      MONITOR_REAL_NEW("Make (ReDimensi)",storage,store)
+   }
+   else store = 0;
+}
+
+void Matrix::resize(int nr, int nc)
+{ REPORT GeneralMatrix::resize(nr,nc,nr*nc); }
+
+void SquareMatrix::resize(int n)
+{ REPORT GeneralMatrix::resize(n,n,n*n); }
+
+void SquareMatrix::resize(int nr, int nc)
+{
+   REPORT
+   Tracer tr("SquareMatrix::resize");
+   if (nc != nr) Throw(NotSquareException(*this));
+   GeneralMatrix::resize(nr,nc,nr*nc);
+}
+
+void SymmetricMatrix::resize(int nr)
+{ REPORT GeneralMatrix::resize(nr,nr,tristore(nr)); }
+
+void UpperTriangularMatrix::resize(int nr)
+{ REPORT GeneralMatrix::resize(nr,nr,tristore(nr)); }
+
+void LowerTriangularMatrix::resize(int nr)
+{ REPORT GeneralMatrix::resize(nr,nr,tristore(nr)); }
+
+void DiagonalMatrix::resize(int nr)
+{ REPORT GeneralMatrix::resize(nr,nr,nr); }
+
+void RowVector::resize(int nc)
+{ REPORT GeneralMatrix::resize(1,nc,nc); }
+
+void ColumnVector::resize(int nr)
+{ REPORT GeneralMatrix::resize(nr,1,nr); }
+
+void RowVector::resize(int nr, int nc)
+{
+   Tracer tr("RowVector::resize");
+   if (nr != 1) Throw(VectorException(*this));
+   REPORT GeneralMatrix::resize(1,nc,nc);
+}
+
+void ColumnVector::resize(int nr, int nc)
+{
+   Tracer tr("ColumnVector::resize");
+   if (nc != 1) Throw(VectorException(*this));
+   REPORT GeneralMatrix::resize(nr,1,nr);
+}
+
+void IdentityMatrix::resize(int nr)
+{ REPORT GeneralMatrix::resize(nr,nr,1); *store = 1; }
+
+
+void Matrix::resize(const GeneralMatrix& A)
+{ REPORT  resize(A.Nrows(), A.Ncols()); }
+
+void SquareMatrix::resize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("SquareMatrix::resize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   resize(n);
+}
+
+void nricMatrix::resize(const GeneralMatrix& A)
+{ REPORT  resize(A.Nrows(), A.Ncols()); }
+
+void ColumnVector::resize(const GeneralMatrix& A)
+{ REPORT  resize(A.Nrows(), A.Ncols()); }
+
+void RowVector::resize(const GeneralMatrix& A)
+{ REPORT  resize(A.Nrows(), A.Ncols()); }
+
+void SymmetricMatrix::resize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("SymmetricMatrix::resize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   resize(n);
+}
+
+void DiagonalMatrix::resize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("DiagonalMatrix::resize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   resize(n);
+}
+
+void UpperTriangularMatrix::resize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("UpperTriangularMatrix::resize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   resize(n);
+}
+
+void LowerTriangularMatrix::resize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("LowerTriangularMatrix::resize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   resize(n);
+}
+
+void IdentityMatrix::resize(const GeneralMatrix& A)
+{
+   REPORT
+   int n = A.Nrows();
+   if (n != A.Ncols())
+   {
+      Tracer tr("IdentityMatrix::resize(GM)");
+      Throw(NotSquareException(*this));
+   }
+   resize(n);
+}
+
+void GeneralMatrix::resize(const GeneralMatrix&)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::resize(GM)");
+   Throw(NotDefinedException("resize", "this type of matrix"));
+}
+
+//*********************** resize_keep *******************************
+
+void Matrix::resize_keep(int nr, int nc)
+{
+   Tracer tr("Matrix::resize_keep");
+   if (nr == nrows_val && nc == ncols_val) { REPORT return; }
+   
+   if (nr <= nrows_val && nc <= ncols_val)
+   {
+      REPORT
+      Matrix X = submatrix(1,nr,1,nc);
+      swap(X);
+   }
+   else if (nr >= nrows_val && nc >= ncols_val)
+   {
+      REPORT
+      Matrix X(nr, nc); X = 0;
+      X.submatrix(1,nrows_val,1,ncols_val) = *this;
+      swap(X);
+   }
+   else
+   {
+      REPORT
+      Matrix X(nr, nc); X = 0;
+      if (nr > nrows_val) nr = nrows_val;
+      if (nc > ncols_val) nc = ncols_val;
+      X.submatrix(1,nr,1,nc) = submatrix(1,nr,1,nc);
+      swap(X);
+   }
+} 
+
+void SquareMatrix::resize_keep(int nr)
+{
+   Tracer tr("SquareMatrix::resize_keep");
+   if (nr < nrows_val)
+   {
+      REPORT
+      SquareMatrix X = sym_submatrix(1,nr);
+      swap(X);
+   }
+   else if (nr > nrows_val)
+   {
+      REPORT
+      SquareMatrix X(nr); X = 0;
+      X.sym_submatrix(1,nrows_val) = *this;
+      swap(X);
+   }
+}
+
+void SquareMatrix::resize_keep(int nr, int nc)
+{
+   Tracer tr("SquareMatrix::resize_keep 2");
+   REPORT
+   if (nr != nc) Throw(NotSquareException(*this));
+   resize_keep(nr);
+}
+ 
+
+void SymmetricMatrix::resize_keep(int nr)
+{
+   Tracer tr("SymmetricMatrix::resize_keep");
+   if (nr < nrows_val)
+   {
+      REPORT
+      SymmetricMatrix X = sym_submatrix(1,nr);
+      swap(X);
+   }
+   else if (nr > nrows_val)
+   {
+      REPORT
+      SymmetricMatrix X(nr); X = 0;
+      X.sym_submatrix(1,nrows_val) = *this;
+      swap(X);
+   }
+} 
+
+void UpperTriangularMatrix::resize_keep(int nr)
+{
+   Tracer tr("UpperTriangularMatrix::resize_keep");
+   if (nr < nrows_val)
+   {
+      REPORT
+      UpperTriangularMatrix X = sym_submatrix(1,nr);
+      swap(X);
+   }
+   else if (nr > nrows_val)
+   {
+      REPORT
+      UpperTriangularMatrix X(nr); X = 0;
+      X.sym_submatrix(1,nrows_val) = *this;
+      swap(X);
+   }
+} 
+
+void LowerTriangularMatrix::resize_keep(int nr)
+{
+   Tracer tr("LowerTriangularMatrix::resize_keep");
+   if (nr < nrows_val)
+   {
+      REPORT
+      LowerTriangularMatrix X = sym_submatrix(1,nr);
+      swap(X);
+   }
+   else if (nr > nrows_val)
+   {
+      REPORT
+      LowerTriangularMatrix X(nr); X = 0;
+      X.sym_submatrix(1,nrows_val) = *this;
+      swap(X);
+   }
+} 
+
+void DiagonalMatrix::resize_keep(int nr)
+{
+   Tracer tr("DiagonalMatrix::resize_keep");
+   if (nr < nrows_val)
+   {
+      REPORT
+      DiagonalMatrix X = sym_submatrix(1,nr);
+      swap(X);
+   }
+   else if (nr > nrows_val)
+   {
+      REPORT
+      DiagonalMatrix X(nr); X = 0;
+      X.sym_submatrix(1,nrows_val) = *this;
+      swap(X);
+   }
+} 
+
+void RowVector::resize_keep(int nc)
+{
+   Tracer tr("RowVector::resize_keep");
+   if (nc < ncols_val)
+   {
+      REPORT
+      RowVector X = columns(1,nc);
+      swap(X);
+   }
+   else if (nc > ncols_val)
+   {
+      REPORT
+      RowVector X(nc); X = 0;
+      X.columns(1,ncols_val) = *this;
+      swap(X);
+   }
+}
+
+void RowVector::resize_keep(int nr, int nc)
+{
+   Tracer tr("RowVector::resize_keep 2");
+   REPORT
+   if (nr != 1) Throw(VectorException(*this));
+   resize_keep(nc);
+}
+
+void ColumnVector::resize_keep(int nr)
+{
+   Tracer tr("ColumnVector::resize_keep");
+   if (nr < nrows_val)
+   {
+      REPORT
+      ColumnVector X = rows(1,nr);
+      swap(X);
+   }
+   else if (nr > nrows_val)
+   {
+      REPORT
+      ColumnVector X(nr); X = 0;
+      X.rows(1,nrows_val) = *this;
+      swap(X);
+   }
+} 
+
+void ColumnVector::resize_keep(int nr, int nc)
+{
+   Tracer tr("ColumnVector::resize_keep 2");
+   REPORT
+   if (nc != 1) Throw(VectorException(*this));
+   resize_keep(nr);
+}
+
+
+/*
+void GeneralMatrix::resizeForAdd(const GeneralMatrix& A, const GeneralMatrix&)
+{ REPORT resize(A); }
+
+void GeneralMatrix::resizeForSP(const GeneralMatrix& A, const GeneralMatrix&)
+{ REPORT resize(A); }
+
+
+// ************************* SameStorageType ******************************
+
+// SameStorageType checks A and B have same storage type including bandwidth
+// It does not check same dimensions since we assume this is already done
+
+bool GeneralMatrix::SameStorageType(const GeneralMatrix& A) const
+{
+   REPORT
+   return type() == A.type();
+}
+*/
+
+// ******************* manipulate types, storage **************************/
+
+int GeneralMatrix::search(const BaseMatrix* s) const
+{ REPORT return (s==this) ? 1 : 0; }
+
+int GenericMatrix::search(const BaseMatrix* s) const
+{ REPORT return gm->search(s); }
+
+int MultipliedMatrix::search(const BaseMatrix* s) const
+{ REPORT return bm1->search(s) + bm2->search(s); }
+
+int ShiftedMatrix::search(const BaseMatrix* s) const
+{ REPORT return bm->search(s); }
+
+int NegatedMatrix::search(const BaseMatrix* s) const
+{ REPORT return bm->search(s); }
+
+int ReturnMatrix::search(const BaseMatrix* s) const
+{ REPORT return (s==gm) ? 1 : 0; }
+
+MatrixType Matrix::type() const { return MatrixType::Rt; }
+MatrixType SquareMatrix::type() const { return MatrixType::Sq; }
+MatrixType SymmetricMatrix::type() const { return MatrixType::Sm; }
+MatrixType UpperTriangularMatrix::type() const { return MatrixType::UT; }
+MatrixType LowerTriangularMatrix::type() const { return MatrixType::LT; }
+MatrixType DiagonalMatrix::type() const { return MatrixType::Dg; }
+MatrixType RowVector::type() const { return MatrixType::RV; }
+MatrixType ColumnVector::type() const { return MatrixType::CV; }
+MatrixType CroutMatrix::type() const { return MatrixType::Ct; }
+MatrixType BandMatrix::type() const { return MatrixType::BM; }
+MatrixType UpperBandMatrix::type() const { return MatrixType::UB; }
+MatrixType LowerBandMatrix::type() const { return MatrixType::LB; }
+MatrixType SymmetricBandMatrix::type() const { return MatrixType::SB; }
+
+MatrixType IdentityMatrix::type() const { return MatrixType::Id; }
+
+
+
+MatrixBandWidth BaseMatrix::bandwidth() const { REPORT return -1; }
+MatrixBandWidth DiagonalMatrix::bandwidth() const { REPORT return 0; }
+MatrixBandWidth IdentityMatrix::bandwidth() const { REPORT return 0; }
+
+MatrixBandWidth UpperTriangularMatrix::bandwidth() const
+   { REPORT return MatrixBandWidth(0,-1); }
+
+MatrixBandWidth LowerTriangularMatrix::bandwidth() const
+   { REPORT return MatrixBandWidth(-1,0); }
+
+MatrixBandWidth BandMatrix::bandwidth() const
+   { REPORT return MatrixBandWidth(lower_val,upper_val); }
+
+MatrixBandWidth BandLUMatrix::bandwidth() const
+   { REPORT return MatrixBandWidth(m1,m2); }
+   
+MatrixBandWidth GenericMatrix::bandwidth()const
+   { REPORT return gm->bandwidth(); }
+
+MatrixBandWidth AddedMatrix::bandwidth() const
+   { REPORT return gm1->bandwidth() + gm2->bandwidth(); }
+
+MatrixBandWidth SPMatrix::bandwidth() const
+   { REPORT return gm1->bandwidth().minimum(gm2->bandwidth()); }
+
+MatrixBandWidth KPMatrix::bandwidth() const
+{
+   int lower, upper;
+   MatrixBandWidth bw1 = gm1->bandwidth(), bw2 = gm2->bandwidth();
+   if (bw1.Lower() < 0)
+   {
+      if (bw2.Lower() < 0) { REPORT lower = -1; }
+      else { REPORT lower = bw2.Lower() + (gm1->Nrows() - 1) * gm2->Nrows(); }
+   }
+   else
+   {
+      if (bw2.Lower() < 0)
+         { REPORT lower = (1 + bw1.Lower()) * gm2->Nrows() - 1; }
+      else { REPORT lower = bw2.Lower() + bw1.Lower() * gm2->Nrows(); }
+   }
+   if (bw1.Upper() < 0)
+   {
+      if (bw2.Upper() < 0) { REPORT upper = -1; }
+      else { REPORT upper = bw2.Upper() + (gm1->Nrows() - 1) * gm2->Nrows(); }
+   }
+   else
+   {
+      if (bw2.Upper() < 0)
+         { REPORT upper = (1 + bw1.Upper()) * gm2->Nrows() - 1; }
+      else { REPORT upper = bw2.Upper() + bw1.Upper() * gm2->Nrows(); }
+   }
+   return MatrixBandWidth(lower, upper);
+}
+
+MatrixBandWidth MultipliedMatrix::bandwidth() const
+{ REPORT return gm1->bandwidth() * gm2->bandwidth(); }
+
+MatrixBandWidth ConcatenatedMatrix::bandwidth() const { REPORT return -1; }
+
+MatrixBandWidth SolvedMatrix::bandwidth() const
+{
+   if (+gm1->type() & MatrixType::Diagonal)
+      { REPORT return gm2->bandwidth(); }
+   else { REPORT return -1; }
+}
+
+MatrixBandWidth ScaledMatrix::bandwidth() const
+   { REPORT return gm->bandwidth(); }
+
+MatrixBandWidth NegatedMatrix::bandwidth() const
+   { REPORT return gm->bandwidth(); }
+
+MatrixBandWidth TransposedMatrix::bandwidth() const
+   { REPORT return gm->bandwidth().t(); }
+
+MatrixBandWidth InvertedMatrix::bandwidth() const
+{
+   if (+gm->type() & MatrixType::Diagonal)
+      { REPORT return MatrixBandWidth(0,0); }
+   else { REPORT return -1; }
+}
+
+MatrixBandWidth RowedMatrix::bandwidth() const { REPORT return -1; }
+MatrixBandWidth ColedMatrix::bandwidth() const { REPORT return -1; }
+MatrixBandWidth DiagedMatrix::bandwidth() const { REPORT return 0; }
+MatrixBandWidth MatedMatrix::bandwidth() const { REPORT return -1; }
+MatrixBandWidth ReturnMatrix::bandwidth() const
+   { REPORT return gm->bandwidth(); }
+
+MatrixBandWidth GetSubMatrix::bandwidth() const
+{
+
+   if (row_skip==col_skip && row_number==col_number)
+      { REPORT return gm->bandwidth(); }
+   else { REPORT return MatrixBandWidth(-1); }
+}
+
+// ********************** the memory managment tools **********************/
+
+//  Rules regarding tDelete, reuse, GetStore, BorrowStore
+//    All matrices processed during expression evaluation must be subject
+//    to exactly one of reuse(), tDelete(), GetStore() or BorrowStore().
+//    If reuse returns true the matrix must be reused.
+//    GetMatrix(gm) always calls gm->GetStore()
+//    gm->Evaluate obeys rules
+//    bm->Evaluate obeys rules for matrices in bm structure
+
+//  Meaning of tag_val
+//    tag_val = -1          memory cannot be reused (default situation)
+//    tag_val = -2          memory has been borrowed from another matrix
+//                               (don't change values)
+//    tag_val = i > 0       delete or reuse memory after i operations
+//    tag_val = 0           like value 1 but matrix was created by new
+//                               so delete it
+
+void GeneralMatrix::tDelete()
+{
+   if (tag_val<0)
+   {
+      if (tag_val<-1) { REPORT store = 0; delete this; return; }  // borrowed
+      else { REPORT return; }   // not a temporary matrix - leave alone
+   }
+   if (tag_val==1)
+   {
+      if (store)
+      {
+         REPORT  MONITOR_REAL_DELETE("Free   (tDelete)",storage,store)
+         delete [] store;
+      }
+      MiniCleanUp(); return;                           // CleanUp
+   }
+   if (tag_val==0) { REPORT delete this; return; }
+
+   REPORT tag_val--; return;
+}
+
+void newmat_block_copy(int n, Real* from, Real* to)
+{
+   REPORT
+   int i = (n >> 3);
+   while (i--)
+   {
+      *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++;
+      *to++ = *from++; *to++ = *from++; *to++ = *from++; *to++ = *from++;
+   }
+   i = n & 7; while (i--) *to++ = *from++;
+}
+
+bool GeneralMatrix::reuse()
+{
+   if (tag_val < -1)                 // borrowed storage
+   {
+      if (storage)
+      {
+         REPORT
+         Real* s = new Real [storage]; MatrixErrorNoSpace(s);
+         MONITOR_REAL_NEW("Make     (reuse)",storage,s)
+         newmat_block_copy(storage, store, s); store = s;
+      }
+      else { REPORT MiniCleanUp(); }                // CleanUp
+      tag_val = 0; return true;
+   }
+   if (tag_val < 0 ) { REPORT return false; }
+   if (tag_val <= 1 )  { REPORT return true; }
+   REPORT tag_val--; return false;
+}
+
+Real* GeneralMatrix::GetStore()
+{
+   if (tag_val<0 || tag_val>1)
+   {
+      Real* s;
+      if (storage)
+      {
+         s = new Real [storage]; MatrixErrorNoSpace(s);
+         MONITOR_REAL_NEW("Make  (GetStore)",storage,s)
+         newmat_block_copy(storage, store, s);
+      }
+      else s = 0;
+      if (tag_val > 1) { REPORT tag_val--; }
+      else if (tag_val < -1) { REPORT store = 0; delete this; } // borrowed store
+      else { REPORT }
+      return s;
+   }
+   Real* s = store;                             // cleanup - done later
+   if (tag_val==0) { REPORT store = 0; delete this; }
+   else { REPORT  MiniCleanUp(); }
+   return s;
+}
+
+void GeneralMatrix::GetMatrix(const GeneralMatrix* gmx)
+{
+   REPORT  tag_val=-1; nrows_val=gmx->Nrows(); ncols_val=gmx->Ncols();
+   storage=gmx->storage; SetParameters(gmx);
+   store=((GeneralMatrix*)gmx)->GetStore();
+}
+
+GeneralMatrix* GeneralMatrix::BorrowStore(GeneralMatrix* gmx, MatrixType mt)
+// Copy storage of *this to storage of *gmx. Then convert to type mt.
+// If mt == 0 just let *gmx point to storage of *this if tag_val==-1.
+{
+   if (!mt)
+   {
+      if (tag_val == -1) { REPORT gmx->tag_val = -2; gmx->store = store; }
+      else { REPORT gmx->tag_val = 0; gmx->store = GetStore(); }
+   }
+   else if (Compare(gmx->type(),mt))
+   { REPORT  gmx->tag_val = 0; gmx->store = GetStore(); }
+   else
+   {
+      REPORT gmx->tag_val = -2; gmx->store = store;
+      gmx = gmx->Evaluate(mt); gmx->tag_val = 0; tDelete();
+   }
+
+   return gmx;
+}
+
+void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt)
+// Count number of references to this in X.
+// If zero delete storage in this;
+// otherwise tag this to show when storage can be deleted
+// evaluate X and copy to this
+{
+#ifdef DO_SEARCH
+   int counter=X.search(this);
+   if (counter==0)
+   {
+      REPORT
+      if (store)
+      {
+         MONITOR_REAL_DELETE("Free (operator=)",storage,store)
+         REPORT delete [] store; storage = 0; store = 0;
+      }
+   }
+   else { REPORT Release(counter); }
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt);
+   if (gmx!=this) { REPORT GetMatrix(gmx); }
+   else { REPORT }
+   Protect();
+#else
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt);
+   if (gmx!=this)
+   {
+      REPORT
+      if (store)
+      {
+         MONITOR_REAL_DELETE("Free (operator=)",storage,store)
+         REPORT delete [] store; storage = 0; store = 0;
+      }
+      GetMatrix(gmx);
+   }
+   else { REPORT }
+   Protect();
+#endif
+}
+
+// version with no conversion
+void GeneralMatrix::Eq(const GeneralMatrix& X)
+{
+   GeneralMatrix* gmx = (GeneralMatrix*)&X;
+   if (gmx!=this)
+   {
+      REPORT
+      if (store)
+      {
+         MONITOR_REAL_DELETE("Free (operator=)",storage,store)
+         REPORT delete [] store; storage = 0; store = 0;
+      }
+      GetMatrix(gmx);
+   }
+   else { REPORT }
+   Protect();
+}
+
+// version to work with operator<<
+void GeneralMatrix::Eq(const BaseMatrix& X, MatrixType mt, bool ldok)
+{
+   REPORT
+   if (ldok) mt.SetDataLossOK();
+   Eq(X, mt);
+}
+
+void GeneralMatrix::Eq2(const BaseMatrix& X, MatrixType mt)
+// a cut down version of Eq for use with += etc.
+// we know BaseMatrix points to two GeneralMatrix objects,
+// the first being this (may be the same).
+// we know tag_val has been set correctly in each.
+{
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate(mt);
+   if (gmx!=this) { REPORT GetMatrix(gmx); }  // simplify GetMatrix ?
+   else { REPORT }
+   Protect();
+}
+
+void GeneralMatrix::inject(const GeneralMatrix& X)
+// copy stored values of X; otherwise leave els of *this unchanged
+{
+   REPORT
+   Tracer tr("inject");
+   if (nrows_val != X.nrows_val || ncols_val != X.ncols_val)
+      Throw(IncompatibleDimensionsException());
+   MatrixRow mr((GeneralMatrix*)&X, LoadOnEntry);
+   MatrixRow mrx(this, LoadOnEntry+StoreOnExit+DirectPart);
+   int i=nrows_val;
+   while (i--) { mrx.Inject(mr); mrx.Next(); mr.Next(); }
+}
+
+// ************* checking for data loss during conversion *******************/
+
+bool Compare(const MatrixType& source, MatrixType& destination)
+{
+   if (!destination) { destination=source; return true; }
+   if (destination==source) return true;
+   if (!destination.DataLossOK && !(destination>=source))
+      Throw(ProgramException("Illegal Conversion", source, destination));
+   return false;
+}
+
+// ************* Make a copy of a matrix on the heap *********************/
+
+GeneralMatrix* Matrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new Matrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* SquareMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new SquareMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* SymmetricMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new SymmetricMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* UpperTriangularMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new UpperTriangularMatrix(*this);
+   MatrixErrorNoSpace(gm); return gm;
+}
+
+GeneralMatrix* LowerTriangularMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new LowerTriangularMatrix(*this);
+   MatrixErrorNoSpace(gm); return gm;
+}
+
+GeneralMatrix* DiagonalMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new DiagonalMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* RowVector::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new RowVector(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* ColumnVector::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new ColumnVector(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* nricMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new nricMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* IdentityMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new IdentityMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* CroutMatrix::Image() const
+{
+   REPORT
+   GeneralMatrix* gm = new CroutMatrix(*this); MatrixErrorNoSpace(gm);
+   return gm;
+}
+
+GeneralMatrix* GeneralMatrix::Image() const
+{
+   bool dummy = true;
+   if (dummy)                                   // get rid of warning message
+      Throw(InternalException("Cannot apply Image to this matrix type"));
+   return 0;
+}
+
+
+// *********************** nricMatrix routines *****************************/
+
+void nricMatrix::MakeRowPointer()
+{
+   REPORT
+   if (nrows_val > 0)
+   {
+      row_pointer = new Real* [nrows_val]; MatrixErrorNoSpace(row_pointer);
+      Real* s = Store() - 1; int i = nrows_val; Real** rp = row_pointer;
+      if (i) for (;;) { *rp++ = s; if (!(--i)) break; s+=ncols_val; }
+   }
+   else row_pointer = 0;
+}
+
+void nricMatrix::DeleteRowPointer()
+   { REPORT if (nrows_val) delete [] row_pointer; }
+
+void GeneralMatrix::CheckStore() const
+{
+   REPORT
+   if (!store)
+      Throw(ProgramException("NRIC accessing matrix with unset dimensions"));
+}
+
+
+// *************************** CleanUp routines *****************************/
+
+void GeneralMatrix::cleanup()
+{
+   // set matrix dimensions to zero, delete storage
+   REPORT
+   if (store && storage)
+   {
+      MONITOR_REAL_DELETE("Free (cleanup)    ",storage,store)
+      REPORT delete [] store;
+   }
+   store=0; storage=0; nrows_val=0; ncols_val=0; tag_val = -1;
+}
+
+void nricMatrix::cleanup()
+   { REPORT DeleteRowPointer(); GeneralMatrix::cleanup(); }
+
+void nricMatrix::MiniCleanUp()
+   { REPORT DeleteRowPointer(); GeneralMatrix::MiniCleanUp(); }
+
+void RowVector::cleanup()
+   { REPORT GeneralMatrix::cleanup(); nrows_val=1; }
+
+void ColumnVector::cleanup()
+   { REPORT GeneralMatrix::cleanup(); ncols_val=1; }
+
+void CroutMatrix::cleanup()
+{
+   REPORT
+   if (nrows_val) delete [] indx;
+   GeneralMatrix::cleanup();
+}
+
+void CroutMatrix::MiniCleanUp()
+{
+   REPORT
+   if (nrows_val) delete [] indx;
+   GeneralMatrix::MiniCleanUp();
+}
+
+void BandLUMatrix::cleanup()
+{
+   REPORT
+   if (nrows_val) delete [] indx;
+   if (storage2) delete [] store2;
+   GeneralMatrix::cleanup();
+}
+
+void BandLUMatrix::MiniCleanUp()
+{
+   REPORT
+   if (nrows_val) delete [] indx;
+   if (storage2) delete [] store2;
+   GeneralMatrix::MiniCleanUp();
+}
+
+// ************************ simple integer array class ***********************
+
+// construct a new array of length xn. Check that xn is non-negative and
+// that space is available
+
+SimpleIntArray::SimpleIntArray(int xn) : n(xn)
+{
+   if (n < 0) Throw(Logic_error("invalid array length"));
+   else if (n == 0) { REPORT  a = 0; }
+   else { REPORT  a = new int [n]; if (!a) Throw(Bad_alloc()); }
+}
+
+// destroy an array - return its space to memory
+
+SimpleIntArray::~SimpleIntArray() { REPORT  if (a) delete [] a; }
+
+// access an element of an array; return a "reference" so elements
+// can be modified.
+// check index is within range
+// in this array class the index runs from 0 to n-1
+
+int& SimpleIntArray::operator[](int i)
+{
+   REPORT
+   if (i < 0 || i >= n) Throw(Logic_error("array index out of range"));
+   return a[i];
+}
+
+// same thing again but for arrays declared constant so we can't
+// modify its elements
+
+int SimpleIntArray::operator[](int i) const
+{
+   REPORT
+   if (i < 0 || i >= n) Throw(Logic_error("array index out of range"));
+   return a[i];
+}
+
+// set all the elements equal to a given value
+
+void SimpleIntArray::operator=(int ai)
+   { REPORT  for (int i = 0; i < n; i++) a[i] = ai; }
+
+// set the elements equal to those of another array.
+// now allow length to be changed
+
+void SimpleIntArray::operator=(const SimpleIntArray& b)
+{
+   REPORT
+   if (b.n != n) resize(b.n);
+   for (int i = 0; i < n; i++) a[i] = b.a[i];
+}
+
+// construct a new array equal to an existing array
+// check that space is available
+
+SimpleIntArray::SimpleIntArray(const SimpleIntArray& b) : Janitor(), n(b.n)
+{
+   if (n == 0) { REPORT  a = 0; }
+   else
+   {
+      REPORT
+      a = new int [n]; if (!a) Throw(Bad_alloc());
+      for (int i = 0; i < n; i++) a[i] = b.a[i];
+   }
+}
+
+// change the size of an array; optionally copy data from old array to
+// new array
+
+void SimpleIntArray::resize(int n1, bool keep)
+{
+   if (n1 == n) { REPORT  return; }
+   else if (n1 == 0) { REPORT  n = 0; delete [] a; a = 0; }
+   else if (n == 0)
+   {
+      REPORT
+      a = new int [n1]; if (!a) Throw(Bad_alloc());
+      n = n1;
+      if (keep) operator=(0);
+   }
+   else
+   {
+      int* a1 = a;
+      if (keep)
+      {
+         REPORT
+         int i;
+         a = new int [n1]; if (!a) Throw(Bad_alloc());
+         if (n > n1) n = n1;
+         else for (i = n; i < n1; i++) a[i] = 0;
+         for (i = 0; i < n; i++) a[i] = a1[i];
+         n = n1; delete [] a1;
+      }
+      else
+      {
+         REPORT  n = n1; delete [] a1;
+         a = new int [n]; if (!a) Throw(Bad_alloc());
+      }
+   }
+}
+
+//************************** swap values ********************************
+
+// swap values
+
+void GeneralMatrix::swap(GeneralMatrix& gm)
+{
+   REPORT
+   int t;
+   t = tag_val; tag_val = gm.tag_val; gm.tag_val = t;
+   t = nrows_val; nrows_val = gm.nrows_val; gm.nrows_val = t;
+   t = ncols_val; ncols_val = gm.ncols_val; gm.ncols_val = t;
+   t = storage; storage = gm.storage; gm.storage = t;
+   Real* s = store; store = gm.store; gm.store = s;
+}
+   
+void nricMatrix::swap(nricMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   Real** rp = row_pointer; row_pointer = gm.row_pointer; gm.row_pointer = rp;
+}
+
+void CroutMatrix::swap(CroutMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   int* i = indx; indx = gm.indx; gm.indx = i;
+   bool b;
+   b = d; d = gm.d; gm.d = b;
+   b = sing; sing = gm.sing; gm.sing = b;
+}
+
+void BandMatrix::swap(BandMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   int i;
+   i = lower_val; lower_val = gm.lower_val; gm.lower_val = i;
+   i = upper_val; upper_val = gm.upper_val; gm.upper_val = i;
+}
+
+void SymmetricBandMatrix::swap(SymmetricBandMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   int i;
+   i = lower_val; lower_val = gm.lower_val; gm.lower_val = i;
+}
+
+void BandLUMatrix::swap(BandLUMatrix& gm)
+{
+   REPORT
+   GeneralMatrix::swap((GeneralMatrix&)gm);
+   int* i = indx; indx = gm.indx; gm.indx = i;
+   bool b;
+   b = d; d = gm.d; gm.d = b;
+   b = sing; sing = gm.sing; gm.sing = b;
+   int m;
+   m = storage2; storage2 = gm.storage2; gm.storage2 = m;
+   m = m1; m1 = gm.m1; gm.m1 = m;
+   m = m2; m2 = gm.m2; gm.m2 = m;
+   Real* s = store2; store2 = gm.store2; gm.store2 = s;
+}
+
+void GenericMatrix::swap(GenericMatrix& x)
+{
+   REPORT
+   GeneralMatrix* tgm = gm; gm = x.gm; x.gm = tgm;
+}
+
+// ********************** C subscript classes ****************************
+
+RealStarStar::RealStarStar(Matrix& A)
+{
+   REPORT
+   Tracer tr("RealStarStar");
+   int n = A.ncols();
+   int m = A.nrows();
+   a = new Real*[m];
+   MatrixErrorNoSpace(a);
+   Real* d = A.data();
+   for (int i = 0; i < m; ++i) a[i] = d + i * n;
+} 
+
+ConstRealStarStar::ConstRealStarStar(const Matrix& A)
+{
+   REPORT
+   Tracer tr("ConstRealStarStar");
+   int n = A.ncols();
+   int m = A.nrows();
+   a = new const Real*[m];
+   MatrixErrorNoSpace(a);
+   const Real* d = A.data();
+   for (int i = 0; i < m; ++i) a[i] = d + i * n;
+} 
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+/// \fn GeneralMatrix::SimpleAddOK(const GeneralMatrix* gm)
+/// Can we add two matrices with simple vector add.
+/// SimpleAddOK shows when we can add two matrices by a simple vector add
+/// and when we can add one matrix into another
+///
+/// *gm must be the same type as *this
+/// - return 0 if simple add is OK
+/// - return 1 if we can add into *gm only
+/// - return 2 if we can add into *this only
+/// - return 3 if we can't add either way
+///
+/// Also applies to subtract;
+/// for SP this will still be valid if we swap 1 and 2
+///
+/// For types Matrix, DiagonalMatrix, UpperTriangularMatrix,
+/// LowerTriangularMatrix, SymmetricMatrix etc return 0.
+/// For band matrices we will need to check bandwidths.
+
+
+
+
+
+
+
+///@}
Index: trunk/BNC/newmat/newmat5.cpp
===================================================================
--- trunk/BNC/newmat/newmat5.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmat5.cpp	(revision 2013)
@@ -0,0 +1,557 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmat5.cpp
+/// Transpose, evaluate, operations with scalar, matrix input.
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+//#define WANT_STREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,5); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/************************ carry out operations ******************************/
+
+
+GeneralMatrix* GeneralMatrix::Transpose(TransposedMatrix* tm, MatrixType mt)
+{
+   GeneralMatrix* gm1;
+
+   if (Compare(Type().t(),mt))
+   {
+      REPORT
+      gm1 = mt.New(ncols_val,nrows_val,tm);
+      for (int i=0; i<ncols_val; i++)
+      {
+         MatrixRow mr(gm1, StoreOnExit+DirectPart, i);
+         MatrixCol mc(this, mr.Data(), LoadOnEntry, i);
+      }
+   }
+   else
+   {
+      REPORT
+      gm1 = mt.New(ncols_val,nrows_val,tm);
+      MatrixRow mr(this, LoadOnEntry);
+      MatrixCol mc(gm1, StoreOnExit+DirectPart);
+      int i = nrows_val;
+      while (i--) { mc.Copy(mr); mr.Next(); mc.Next(); }
+   }
+   tDelete(); gm1->ReleaseAndDelete(); return gm1;
+}
+
+GeneralMatrix* SymmetricMatrix::Transpose(TransposedMatrix*, MatrixType mt)
+{ REPORT  return Evaluate(mt); }
+
+
+GeneralMatrix* DiagonalMatrix::Transpose(TransposedMatrix*, MatrixType mt)
+{ REPORT return Evaluate(mt); }
+
+GeneralMatrix* ColumnVector::Transpose(TransposedMatrix*, MatrixType mt)
+{
+   REPORT
+   GeneralMatrix* gmx = new RowVector; MatrixErrorNoSpace(gmx);
+   gmx->nrows_val = 1; gmx->ncols_val = gmx->storage = storage;
+   return BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* RowVector::Transpose(TransposedMatrix*, MatrixType mt)
+{
+   REPORT
+   GeneralMatrix* gmx = new ColumnVector; MatrixErrorNoSpace(gmx);
+   gmx->ncols_val = 1; gmx->nrows_val = gmx->storage = storage;
+   return BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* IdentityMatrix::Transpose(TransposedMatrix*, MatrixType mt)
+{ REPORT return Evaluate(mt); }
+
+GeneralMatrix* GeneralMatrix::Evaluate(MatrixType mt)
+{
+   if (Compare(this->Type(),mt)) { REPORT return this; }
+   REPORT
+   GeneralMatrix* gmx = mt.New(nrows_val,ncols_val,this);
+   MatrixRow mr(this, LoadOnEntry);
+   MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+   int i=nrows_val;
+   while (i--) { mrx.Copy(mr); mrx.Next(); mr.Next(); }
+   tDelete(); gmx->ReleaseAndDelete(); return gmx;
+}
+
+GeneralMatrix* CroutMatrix::Evaluate(MatrixType mt)
+{
+   if (Compare(this->Type(),mt)) { REPORT return this; }
+   REPORT
+   Tracer et("CroutMatrix::Evaluate");
+   bool dummy = true;
+   if (dummy) Throw(ProgramException("Illegal use of CroutMatrix", *this));
+   return this;
+}
+
+GeneralMatrix* GenericMatrix::Evaluate(MatrixType mt)
+   { REPORT  return gm->Evaluate(mt); }
+
+GeneralMatrix* ShiftedMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   int nr=gm->Nrows(); int nc=gm->Ncols();
+   Compare(gm->Type().AddEqualEl(),mt);
+   if (!(mt==gm->Type()))
+   {
+      REPORT
+      GeneralMatrix* gmx = mt.New(nr,nc,this);
+      MatrixRow mr(gm, LoadOnEntry);
+      MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mrx.Add(mr,f); mrx.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm->tDelete();
+      return gmx;
+   }
+   else if (gm->reuse())
+   {
+      REPORT gm->Add(f);
+      return gm;
+   }
+   else
+   {
+      REPORT GeneralMatrix* gmy = gm->Type().New(nr,nc,this);
+      gmy->ReleaseAndDelete(); gmy->Add(gm,f);
+      return gmy;
+   }
+}
+
+GeneralMatrix* NegShiftedMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   int nr=gm->Nrows(); int nc=gm->Ncols();
+   Compare(gm->Type().AddEqualEl(),mt);
+   if (!(mt==gm->Type()))
+   {
+      REPORT
+      GeneralMatrix* gmx = mt.New(nr,nc,this);
+      MatrixRow mr(gm, LoadOnEntry);
+      MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mrx.NegAdd(mr,f); mrx.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm->tDelete();
+      return gmx;
+   }
+   else if (gm->reuse())
+   {
+      REPORT gm->NegAdd(f);
+      return gm;
+   }
+   else
+   {
+      REPORT GeneralMatrix* gmy = gm->Type().New(nr,nc,this);
+      gmy->ReleaseAndDelete(); gmy->NegAdd(gm,f);
+      return gmy;
+   }
+}
+
+GeneralMatrix* ScaledMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   int nr=gm->Nrows(); int nc=gm->Ncols();
+   if (Compare(gm->Type(),mt))
+   {
+      if (gm->reuse())
+      {
+         REPORT gm->Multiply(f);
+         return gm;
+      }
+      else
+      {
+         REPORT GeneralMatrix* gmx = gm->Type().New(nr,nc,this);
+         gmx->ReleaseAndDelete(); gmx->Multiply(gm,f);
+         return gmx;
+      }
+   }
+   else
+   {
+      REPORT
+      GeneralMatrix* gmx = mt.New(nr,nc,this);
+      MatrixRow mr(gm, LoadOnEntry);
+      MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mrx.Multiply(mr,f); mrx.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm->tDelete();
+      return gmx;
+   }
+}
+
+GeneralMatrix* NegatedMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   int nr=gm->Nrows(); int nc=gm->Ncols();
+   if (Compare(gm->Type(),mt))
+   {
+      if (gm->reuse())
+      {
+         REPORT gm->Negate();
+         return gm;
+      }
+      else
+      {
+         REPORT
+         GeneralMatrix* gmx = gm->Type().New(nr,nc,this);
+         gmx->ReleaseAndDelete(); gmx->Negate(gm);
+         return gmx;
+      }
+   }
+   else
+   {
+      REPORT
+      GeneralMatrix* gmx = mt.New(nr,nc,this);
+      MatrixRow mr(gm, LoadOnEntry);
+      MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mrx.Negate(mr); mrx.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm->tDelete();
+      return gmx;
+   }
+}
+
+GeneralMatrix* ReversedMatrix::Evaluate(MatrixType mt)
+{
+   gm=((BaseMatrix*&)bm)->Evaluate(); GeneralMatrix* gmx;
+
+   if ((gm->Type()).is_band() && ! (gm->Type()).is_diagonal())
+   {
+      gm->tDelete();
+      Throw(NotDefinedException("Reverse", "band matrices"));
+   }
+
+   if (gm->reuse()) { REPORT gm->ReverseElements(); gmx = gm; }
+   else
+   {
+      REPORT
+      gmx = gm->Type().New(gm->Nrows(), gm->Ncols(), this);
+      gmx->ReverseElements(gm); gmx->ReleaseAndDelete();
+   }
+   return gmx->Evaluate(mt); // target matrix is different type?
+
+}
+
+GeneralMatrix* TransposedMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   Compare(gm->Type().t(),mt);
+   GeneralMatrix* gmx=gm->Transpose(this, mt);
+   return gmx;
+}
+
+GeneralMatrix* RowedMatrix::Evaluate(MatrixType mt)
+{
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   GeneralMatrix* gmx = new RowVector; MatrixErrorNoSpace(gmx);
+   gmx->nrows_val = 1; gmx->ncols_val = gmx->storage = gm->storage;
+   return gm->BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* ColedMatrix::Evaluate(MatrixType mt)
+{
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   GeneralMatrix* gmx = new ColumnVector; MatrixErrorNoSpace(gmx);
+   gmx->ncols_val = 1; gmx->nrows_val = gmx->storage = gm->storage;
+   return gm->BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* DiagedMatrix::Evaluate(MatrixType mt)
+{
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   GeneralMatrix* gmx = new DiagonalMatrix; MatrixErrorNoSpace(gmx);
+   gmx->nrows_val = gmx->ncols_val = gmx->storage = gm->storage;
+   return gm->BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* MatedMatrix::Evaluate(MatrixType mt)
+{
+   Tracer tr("MatedMatrix::Evaluate");
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   GeneralMatrix* gmx = new Matrix; MatrixErrorNoSpace(gmx);
+   gmx->nrows_val = nr; gmx->ncols_val = nc; gmx->storage = gm->storage;
+   if (nr*nc != gmx->storage)
+      Throw(IncompatibleDimensionsException());
+   return gm->BorrowStore(gmx,mt);
+}
+
+GeneralMatrix* GetSubMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   Tracer tr("SubMatrix(evaluate)");
+   gm = ((BaseMatrix*&)bm)->Evaluate();
+   if (row_number < 0) row_number = gm->Nrows();
+   if (col_number < 0) col_number = gm->Ncols();
+   if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
+   {
+      gm->tDelete();
+      Throw(SubMatrixDimensionException());
+   }
+   if (IsSym) Compare(gm->Type().ssub(), mt);
+   else Compare(gm->Type().sub(), mt);
+   GeneralMatrix* gmx = mt.New(row_number, col_number, this);
+   int i = row_number;
+   MatrixRow mr(gm, LoadOnEntry, row_skip); 
+   MatrixRow mrx(gmx, StoreOnExit+DirectPart);
+   MatrixRowCol sub;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      mrx.Copy(sub); mrx.Next(); mr.Next();
+   }
+   gmx->ReleaseAndDelete(); gm->tDelete();
+   return gmx;
+}
+
+
+GeneralMatrix* ReturnMatrix::Evaluate(MatrixType mt)
+{
+   return gm->Evaluate(mt);
+}
+
+
+void GeneralMatrix::Add(GeneralMatrix* gm1, Real f)
+{
+   REPORT
+   Real* s1=gm1->store; Real* s=store; int i=(storage >> 2);
+   while (i--)
+   { *s++ = *s1++ + f; *s++ = *s1++ + f; *s++ = *s1++ + f; *s++ = *s1++ + f; }
+   i = storage & 3; while (i--) *s++ = *s1++ + f;
+}
+   
+void GeneralMatrix::Add(Real f)
+{
+   REPORT
+   Real* s=store; int i=(storage >> 2);
+   while (i--) { *s++ += f; *s++ += f; *s++ += f; *s++ += f; }
+   i = storage & 3; while (i--) *s++ += f;
+}
+   
+void GeneralMatrix::NegAdd(GeneralMatrix* gm1, Real f)
+{
+   REPORT
+   Real* s1=gm1->store; Real* s=store; int i=(storage >> 2);
+   while (i--)
+   { *s++ = f - *s1++; *s++ = f - *s1++; *s++ = f - *s1++; *s++ = f - *s1++; }
+   i = storage & 3; while (i--) *s++ = f - *s1++;
+}
+   
+void GeneralMatrix::NegAdd(Real f)
+{
+   REPORT
+   Real* s=store; int i=(storage >> 2);
+   while (i--)
+   {
+      *s = f - *s; s++; *s = f - *s; s++;
+      *s = f - *s; s++; *s = f - *s; s++;
+   }
+   i = storage & 3; while (i--)  { *s = f - *s; s++; }
+}
+   
+void GeneralMatrix::Negate(GeneralMatrix* gm1)
+{
+   // change sign of elements
+   REPORT
+   Real* s1=gm1->store; Real* s=store; int i=(storage >> 2);
+   while (i--)
+   { *s++ = -(*s1++); *s++ = -(*s1++); *s++ = -(*s1++); *s++ = -(*s1++); }
+   i = storage & 3; while(i--) *s++ = -(*s1++);
+}
+   
+void GeneralMatrix::Negate()
+{
+   REPORT
+   Real* s=store; int i=(storage >> 2);
+   while (i--)
+   { *s = -(*s); s++; *s = -(*s); s++; *s = -(*s); s++; *s = -(*s); s++; }
+   i = storage & 3; while(i--) { *s = -(*s); s++; }
+}
+   
+void GeneralMatrix::Multiply(GeneralMatrix* gm1, Real f)
+{
+   REPORT
+   Real* s1=gm1->store; Real* s=store;  int i=(storage >> 2);
+   while (i--)
+   { *s++ = *s1++ * f; *s++ = *s1++ * f; *s++ = *s1++ * f; *s++ = *s1++ * f; }
+   i = storage & 3; while (i--) *s++ = *s1++ * f;
+}
+   
+void GeneralMatrix::Multiply(Real f)
+{
+   REPORT
+   Real* s=store; int i=(storage >> 2);
+   while (i--) { *s++ *= f; *s++ *= f; *s++ *= f; *s++ *= f; }
+   i = storage & 3; while (i--) *s++ *= f;
+}
+   
+
+/************************ MatrixInput routines ****************************/
+
+// int MatrixInput::n;          // number values still to be read
+// Real* MatrixInput::r;        // pointer to next location to be read to
+
+MatrixInput MatrixInput::operator<<(double f)
+{
+   REPORT
+   Tracer et("MatrixInput");
+   if (n<=0) Throw(ProgramException("List of values too long"));
+   *r = (Real)f; int n1 = n-1; n=0;   // n=0 so we won't trigger exception
+   return MatrixInput(n1, r+1);
+}
+
+
+MatrixInput GeneralMatrix::operator<<(double f)
+{
+   REPORT
+   Tracer et("MatrixInput");
+   int n = Storage();
+   if (n<=0) Throw(ProgramException("Loading data to zero length matrix"));
+   Real* r; r = Store(); *r = (Real)f; n--;
+   return MatrixInput(n, r+1);
+}
+
+MatrixInput GetSubMatrix::operator<<(double f)
+{
+   REPORT
+   Tracer et("MatrixInput (GetSubMatrix)");
+   SetUpLHS();
+   if (row_number != 1 || col_skip != 0 || col_number != gm->Ncols())
+   {
+      Throw(ProgramException("MatrixInput requires complete rows"));
+   }
+   MatrixRow mr(gm, DirectPart, row_skip);  // to pick up location and length
+   int n = mr.Storage();
+   if (n<=0)
+   {
+      Throw(ProgramException("Loading data to zero length row"));
+   }
+   Real* r; r = mr.Data(); *r = (Real)f; n--;
+   if (+(mr.cw*HaveStore))
+   {
+      Throw(ProgramException("Fails with this matrix type"));
+   }
+   return MatrixInput(n, r+1);
+}
+
+MatrixInput MatrixInput::operator<<(float f)
+{
+   REPORT
+   Tracer et("MatrixInput");
+   if (n<=0) Throw(ProgramException("List of values too long"));
+   *r = (Real)f; int n1 = n-1; n=0;   // n=0 so we won't trigger exception
+   return MatrixInput(n1, r+1);
+}
+
+
+MatrixInput GeneralMatrix::operator<<(float f)
+{
+   REPORT
+   Tracer et("MatrixInput");
+   int n = Storage();
+   if (n<=0) Throw(ProgramException("Loading data to zero length matrix"));
+   Real* r; r = Store(); *r = (Real)f; n--;
+   return MatrixInput(n, r+1);
+}
+
+MatrixInput GetSubMatrix::operator<<(float f)
+{
+   REPORT
+   Tracer et("MatrixInput (GetSubMatrix)");
+   SetUpLHS();
+   if (row_number != 1 || col_skip != 0 || col_number != gm->Ncols())
+   {
+      Throw(ProgramException("MatrixInput requires complete rows"));
+   }
+   MatrixRow mr(gm, DirectPart, row_skip);  // to pick up location and length
+   int n = mr.Storage();
+   if (n<=0)
+   {
+      Throw(ProgramException("Loading data to zero length row"));
+   }
+   Real* r; r = mr.Data(); *r = (Real)f; n--;
+   if (+(mr.cw*HaveStore))
+   {
+      Throw(ProgramException("Fails with this matrix type"));
+   }
+   return MatrixInput(n, r+1);
+}
+MatrixInput::~MatrixInput()
+{
+   REPORT
+   Tracer et("MatrixInput");
+   if (n!=0) Throw(ProgramException("A list of values was too short"));
+}
+
+MatrixInput BandMatrix::operator<<(double)
+{
+   Tracer et("MatrixInput");
+   bool dummy = true;
+   if (dummy)                                   // get rid of warning message
+      Throw(ProgramException("Cannot use list read with a BandMatrix"));
+   return MatrixInput(0, 0);
+}
+
+MatrixInput BandMatrix::operator<<(float)
+{
+   Tracer et("MatrixInput");
+   bool dummy = true;
+   if (dummy)                                   // get rid of warning message
+      Throw(ProgramException("Cannot use list read with a BandMatrix"));
+   return MatrixInput(0, 0);
+}
+
+void BandMatrix::operator<<(const double*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+void BandMatrix::operator<<(const float*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+void BandMatrix::operator<<(const int*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+void SymmetricBandMatrix::operator<<(const double*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+void SymmetricBandMatrix::operator<<(const float*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+void SymmetricBandMatrix::operator<<(const int*)
+{ Throw(ProgramException("Cannot use array read with a BandMatrix")); }
+
+// ************************* Reverse order of elements ***********************
+
+void GeneralMatrix::ReverseElements(GeneralMatrix* gm)
+{
+   // reversing into a new matrix
+   REPORT
+   int n = Storage(); Real* rx = Store() + n; Real* x = gm->Store();
+   while (n--) *(--rx) = *(x++);
+}
+
+void GeneralMatrix::ReverseElements()
+{
+   // reversing in place
+   REPORT
+   int n = Storage(); Real* x = Store(); Real* rx = x + n;
+   n /= 2;
+   while (n--) { Real t = *(--rx); *rx = *x; *(x++) = t; }
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
Index: trunk/BNC/newmat/newmat6.cpp
===================================================================
--- trunk/BNC/newmat/newmat6.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmat6.cpp	(revision 2013)
@@ -0,0 +1,909 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmat6.cpp
+/// Operators, element access.
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,6); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+/*************************** general utilities *************************/
+
+static int tristore(int n)                      // els in triangular matrix
+{ return (n*(n+1))/2; }
+
+
+/****************************** operators *******************************/
+
+Real& Matrix::operator()(int m, int n)
+{
+   REPORT
+   if (m<=0 || m>nrows_val || n<=0 || n>ncols_val)
+      Throw(IndexException(m,n,*this));
+   return store[(m-1)*ncols_val+n-1];
+}
+
+Real& SymmetricMatrix::operator()(int m, int n)
+{
+   REPORT
+   if (m<=0 || n<=0 || m>nrows_val || n>ncols_val)
+      Throw(IndexException(m,n,*this));
+   if (m>=n) return store[tristore(m-1)+n-1];
+   else return store[tristore(n-1)+m-1];
+}
+
+Real& UpperTriangularMatrix::operator()(int m, int n)
+{
+   REPORT
+   if (m<=0 || n<m || n>ncols_val)
+      Throw(IndexException(m,n,*this));
+   return store[(m-1)*ncols_val+n-1-tristore(m-1)];
+}
+
+Real& LowerTriangularMatrix::operator()(int m, int n)
+{
+   REPORT
+   if (n<=0 || m<n || m>nrows_val)
+      Throw(IndexException(m,n,*this));
+   return store[tristore(m-1)+n-1];
+}
+
+Real& DiagonalMatrix::operator()(int m, int n)
+{
+   REPORT
+   if (n<=0 || m!=n || m>nrows_val || n>ncols_val)
+      Throw(IndexException(m,n,*this));
+   return store[n-1];
+}
+
+Real& DiagonalMatrix::operator()(int m)
+{
+   REPORT
+   if (m<=0 || m>nrows_val) Throw(IndexException(m,*this));
+   return store[m-1];
+}
+
+Real& ColumnVector::operator()(int m)
+{
+   REPORT
+   if (m<=0 || m> nrows_val) Throw(IndexException(m,*this));
+   return store[m-1];
+}
+
+Real& RowVector::operator()(int n)
+{
+   REPORT
+   if (n<=0 || n> ncols_val) Throw(IndexException(n,*this));
+   return store[n-1];
+}
+
+Real& BandMatrix::operator()(int m, int n)
+{
+   REPORT
+   int w = upper_val+lower_val+1; int i = lower_val+n-m;
+   if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real& UpperBandMatrix::operator()(int m, int n)
+{
+   REPORT
+   int w = upper_val+1; int i = n-m;
+   if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real& LowerBandMatrix::operator()(int m, int n)
+{
+   REPORT
+   int w = lower_val+1; int i = lower_val+n-m;
+   if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real& SymmetricBandMatrix::operator()(int m, int n)
+{
+   REPORT
+   int w = lower_val+1;
+   if (m>=n)
+   {
+      REPORT
+      int i = lower_val+n-m;
+      if ( m>nrows_val || n<=0 || i<0 )
+         Throw(IndexException(m,n,*this));
+      return store[w*(m-1)+i];
+   }
+   else
+   {
+      REPORT
+      int i = lower_val+m-n;
+      if ( n>nrows_val || m<=0 || i<0 )
+         Throw(IndexException(m,n,*this));
+      return store[w*(n-1)+i];
+   }
+}
+
+
+Real Matrix::operator()(int m, int n) const
+{
+   REPORT
+   if (m<=0 || m>nrows_val || n<=0 || n>ncols_val)
+      Throw(IndexException(m,n,*this));
+   return store[(m-1)*ncols_val+n-1];
+}
+
+Real SymmetricMatrix::operator()(int m, int n) const
+{
+   REPORT
+   if (m<=0 || n<=0 || m>nrows_val || n>ncols_val)
+      Throw(IndexException(m,n,*this));
+   if (m>=n) return store[tristore(m-1)+n-1];
+   else return store[tristore(n-1)+m-1];
+}
+
+Real UpperTriangularMatrix::operator()(int m, int n) const
+{
+   REPORT
+   if (m<=0 || n<m || n>ncols_val)
+      Throw(IndexException(m,n,*this));
+   return store[(m-1)*ncols_val+n-1-tristore(m-1)];
+}
+
+Real LowerTriangularMatrix::operator()(int m, int n) const
+{
+   REPORT
+   if (n<=0 || m<n || m>nrows_val)
+      Throw(IndexException(m,n,*this));
+   return store[tristore(m-1)+n-1];
+}
+
+Real DiagonalMatrix::operator()(int m, int n) const
+{
+   REPORT
+   if (n<=0 || m!=n || m>nrows_val || n>ncols_val)
+      Throw(IndexException(m,n,*this));
+   return store[n-1];
+}
+
+Real DiagonalMatrix::operator()(int m) const
+{
+   REPORT
+   if (m<=0 || m>nrows_val) Throw(IndexException(m,*this));
+   return store[m-1];
+}
+
+Real ColumnVector::operator()(int m) const
+{
+   REPORT
+   if (m<=0 || m> nrows_val) Throw(IndexException(m,*this));
+   return store[m-1];
+}
+
+Real RowVector::operator()(int n) const
+{
+   REPORT
+   if (n<=0 || n> ncols_val) Throw(IndexException(n,*this));
+   return store[n-1];
+}
+
+Real BandMatrix::operator()(int m, int n) const
+{
+   REPORT
+   int w = upper_val+lower_val+1; int i = lower_val+n-m;
+   if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real UpperBandMatrix::operator()(int m, int n) const
+{
+   REPORT
+   int w = upper_val+1; int i = n-m;
+   if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real LowerBandMatrix::operator()(int m, int n) const
+{
+   REPORT
+   int w = lower_val+1; int i = lower_val+n-m;
+   if (m<=0 || m>nrows_val || n<=0 || n>ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this));
+   return store[w*(m-1)+i];
+}
+
+Real SymmetricBandMatrix::operator()(int m, int n) const
+{
+   REPORT
+   int w = lower_val+1;
+   if (m>=n)
+   {
+      REPORT
+      int i = lower_val+n-m;
+      if ( m>nrows_val || n<=0 || i<0 )
+         Throw(IndexException(m,n,*this));
+      return store[w*(m-1)+i];
+   }
+   else
+   {
+      REPORT
+      int i = lower_val+m-n;
+      if ( n>nrows_val || m<=0 || i<0 )
+         Throw(IndexException(m,n,*this));
+      return store[w*(n-1)+i];
+   }
+}
+
+
+Real BaseMatrix::as_scalar() const
+{
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+
+   if (gm->nrows_val!=1 || gm->ncols_val!=1)
+   {
+      Tracer tr("as_scalar");
+      Try
+         { Throw(ProgramException("Cannot convert to scalar", *gm)); }
+      CatchAll { gm->tDelete(); ReThrow; }
+   }
+
+   Real x = *(gm->store); gm->tDelete(); return x;
+}
+
+
+AddedMatrix BaseMatrix::operator+(const BaseMatrix& bm) const
+{ REPORT return AddedMatrix(this, &bm); }
+
+SPMatrix SP(const BaseMatrix& bm1,const BaseMatrix& bm2)
+{ REPORT return SPMatrix(&bm1, &bm2); }
+
+KPMatrix KP(const BaseMatrix& bm1,const BaseMatrix& bm2)
+{ REPORT return KPMatrix(&bm1, &bm2); }
+
+MultipliedMatrix BaseMatrix::operator*(const BaseMatrix& bm) const
+{ REPORT return MultipliedMatrix(this, &bm); }
+
+ConcatenatedMatrix BaseMatrix::operator|(const BaseMatrix& bm) const
+{ REPORT return ConcatenatedMatrix(this, &bm); }
+
+StackedMatrix BaseMatrix::operator&(const BaseMatrix& bm) const
+{ REPORT return StackedMatrix(this, &bm); }
+
+SolvedMatrix InvertedMatrix::operator*(const BaseMatrix& bmx) const
+{ REPORT return SolvedMatrix(bm, &bmx); }
+
+SubtractedMatrix BaseMatrix::operator-(const BaseMatrix& bm) const
+{ REPORT return SubtractedMatrix(this, &bm); }
+
+ShiftedMatrix BaseMatrix::operator+(Real f) const
+{ REPORT return ShiftedMatrix(this, f); }
+
+ShiftedMatrix operator+(Real f, const BaseMatrix& BM)
+{ REPORT return ShiftedMatrix(&BM, f); }
+
+NegShiftedMatrix operator-(Real f, const BaseMatrix& bm)
+{ REPORT return NegShiftedMatrix(f, &bm); }
+
+ScaledMatrix BaseMatrix::operator*(Real f) const
+{ REPORT return ScaledMatrix(this, f); }
+
+ScaledMatrix BaseMatrix::operator/(Real f) const
+{ REPORT return ScaledMatrix(this, 1.0/f); }
+
+ScaledMatrix operator*(Real f, const BaseMatrix& BM)
+{ REPORT return ScaledMatrix(&BM, f); }
+
+ShiftedMatrix BaseMatrix::operator-(Real f) const
+{ REPORT return ShiftedMatrix(this, -f); }
+
+TransposedMatrix BaseMatrix::t() const
+{ REPORT return TransposedMatrix(this); }
+
+NegatedMatrix BaseMatrix::operator-() const
+{ REPORT return NegatedMatrix(this); }
+
+ReversedMatrix BaseMatrix::reverse() const
+{ REPORT return ReversedMatrix(this); }
+
+InvertedMatrix BaseMatrix::i() const
+{ REPORT return InvertedMatrix(this); }
+
+
+RowedMatrix BaseMatrix::as_row() const
+{ REPORT return RowedMatrix(this); }
+
+ColedMatrix BaseMatrix::as_column() const
+{ REPORT return ColedMatrix(this); }
+
+DiagedMatrix BaseMatrix::as_diagonal() const
+{ REPORT return DiagedMatrix(this); }
+
+MatedMatrix BaseMatrix::as_matrix(int nrx, int ncx) const
+{ REPORT return MatedMatrix(this,nrx,ncx); }
+
+
+void GeneralMatrix::operator=(Real f)
+{ REPORT int i=storage; Real* s=store; while (i--) { *s++ = f; } }
+
+void Matrix::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Rt);
+} 
+
+void SquareMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Rt);
+   if (nrows_val != ncols_val)
+      { Tracer tr("SquareMatrix(=)"); Throw(NotSquareException(*this)); }
+}
+
+void SquareMatrix::operator=(const Matrix& m)
+{
+   REPORT
+   if (m.nrows_val != m.ncols_val)
+      { Tracer tr("SquareMatrix(=Matrix)"); Throw(NotSquareException(*this)); }
+   Eq(m);
+}
+
+void RowVector::operator=(const BaseMatrix& X)
+{
+   REPORT  // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::RV);
+   if (nrows_val!=1)
+      { Tracer tr("RowVector(=)"); Throw(VectorException(*this)); }
+}
+
+void ColumnVector::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::CV);
+   if (ncols_val!=1)
+      { Tracer tr("ColumnVector(=)"); Throw(VectorException(*this)); }
+}
+
+void SymmetricMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Sm);
+}
+
+void UpperTriangularMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::UT);
+}
+
+void LowerTriangularMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT //CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::LT);
+}
+
+void DiagonalMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Dg);
+}
+
+void IdentityMatrix::operator=(const BaseMatrix& X)
+{
+   REPORT // CheckConversion(X);
+   // MatrixConversionCheck mcc;
+   Eq(X,MatrixType::Id);
+}
+
+
+void CroutMatrix::operator=(const CroutMatrix& gm)
+{
+   if (&gm == this) { REPORT tag_val = -1; return; }
+   REPORT
+   if (indx > 0) { delete [] indx; indx = 0; }
+   ((CroutMatrix&)gm).get_aux(*this);
+   Eq(gm);
+}
+   
+
+
+
+
+void GeneralMatrix::operator<<(const double* r)
+{
+   REPORT
+   int i = storage; Real* s=store;
+   while(i--) *s++ = (Real)*r++;
+}
+
+
+void GeneralMatrix::operator<<(const float* r)
+{
+   REPORT
+   int i = storage; Real* s=store;
+   while(i--) *s++ = (Real)*r++;
+}
+
+
+void GeneralMatrix::operator<<(const int* r)
+{
+   REPORT
+   int i = storage; Real* s=store;
+   while(i--) *s++ = (Real)*r++;
+}
+
+
+void GenericMatrix::operator=(const GenericMatrix& bmx)
+{
+   if (&bmx != this) { REPORT if (gm) delete gm; gm = bmx.gm->Image();}
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator=(const BaseMatrix& bmx)
+{
+   if (gm)
+   {
+      int counter=bmx.search(gm);
+      if (counter==0) { REPORT delete gm; gm=0; }
+      else { REPORT gm->Release(counter); }
+   }
+   else { REPORT }
+   GeneralMatrix* gmx = ((BaseMatrix&)bmx).Evaluate();
+   if (gmx != gm) { REPORT if (gm) delete gm; gm = gmx->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+
+/*************************** += etc ***************************************/
+
+
+// GeneralMatrix operators
+
+void GeneralMatrix::operator+=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator+=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   AddedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,type());
+}
+
+void GeneralMatrix::operator-=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator-=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   SubtractedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,type());
+}
+
+void GeneralMatrix::operator*=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator*=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   MultipliedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,type());
+}
+
+void GeneralMatrix::operator|=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator|=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   ConcatenatedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,type());
+}
+
+void GeneralMatrix::operator&=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator&=");
+   // MatrixConversionCheck mcc;
+   Protect();                                   // so it cannot get deleted
+						// during Evaluate
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate();
+   StackedMatrix am(this,gm);
+   if (gm==this) Release(2); else Release();
+   Eq2(am,type());
+}
+
+void GeneralMatrix::operator+=(Real r)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator+=(Real)");
+   // MatrixConversionCheck mcc;
+   ShiftedMatrix am(this,r);
+   Release(); Eq2(am,type());
+}
+
+void GeneralMatrix::operator*=(Real r)
+{
+   REPORT
+   Tracer tr("GeneralMatrix::operator*=(Real)");
+   // MatrixConversionCheck mcc;
+   ScaledMatrix am(this,r);
+   Release(); Eq2(am,type());
+}
+
+
+// Generic matrix operators
+
+void GenericMatrix::operator+=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator+=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   AddedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator-=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator-=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   SubtractedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator*=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator*=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   MultipliedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator|=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator|=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   ConcatenatedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator&=(const BaseMatrix& X)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator&=");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   gm->Protect();            // so it cannot get deleted during Evaluate
+   GeneralMatrix* gmx = ((BaseMatrix&)X).Evaluate();
+   StackedMatrix am(gm,gmx);
+   if (gmx==gm) gm->Release(2); else gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator+=(Real r)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator+= (Real)");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   ShiftedMatrix am(gm,r);
+   gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+void GenericMatrix::operator*=(Real r)
+{
+   REPORT
+   Tracer tr("GenericMatrix::operator*= (Real)");
+   if (!gm) Throw(ProgramException("GenericMatrix is null"));
+   ScaledMatrix am(gm,r);
+   gm->Release();
+   GeneralMatrix* gmy = am.Evaluate();
+   if (gmy != gm) { REPORT delete gm; gm = gmy->Image(); }
+   else { REPORT }
+   gm->Protect();
+}
+
+
+/************************* element access *********************************/
+
+Real& Matrix::element(int m, int n)
+{
+   REPORT
+   if (m<0 || m>= nrows_val || n<0 || n>= ncols_val)
+      Throw(IndexException(m,n,*this,true));
+   return store[m*ncols_val+n];
+}
+
+Real Matrix::element(int m, int n) const
+{
+   REPORT
+   if (m<0 || m>= nrows_val || n<0 || n>= ncols_val)
+      Throw(IndexException(m,n,*this,true));
+   return store[m*ncols_val+n];
+}
+
+Real& SymmetricMatrix::element(int m, int n)
+{
+   REPORT
+   if (m<0 || n<0 || m >= nrows_val || n>=ncols_val)
+      Throw(IndexException(m,n,*this,true));
+   if (m>=n) return store[tristore(m)+n];
+   else return store[tristore(n)+m];
+}
+
+Real SymmetricMatrix::element(int m, int n) const
+{
+   REPORT
+   if (m<0 || n<0 || m >= nrows_val || n>=ncols_val)
+      Throw(IndexException(m,n,*this,true));
+   if (m>=n) return store[tristore(m)+n];
+   else return store[tristore(n)+m];
+}
+
+Real& UpperTriangularMatrix::element(int m, int n)
+{
+   REPORT
+   if (m<0 || n<m || n>=ncols_val)
+      Throw(IndexException(m,n,*this,true));
+   return store[m*ncols_val+n-tristore(m)];
+}
+
+Real UpperTriangularMatrix::element(int m, int n) const
+{
+   REPORT
+   if (m<0 || n<m || n>=ncols_val)
+      Throw(IndexException(m,n,*this,true));
+   return store[m*ncols_val+n-tristore(m)];
+}
+
+Real& LowerTriangularMatrix::element(int m, int n)
+{
+   REPORT
+   if (n<0 || m<n || m>=nrows_val)
+      Throw(IndexException(m,n,*this,true));
+   return store[tristore(m)+n];
+}
+
+Real LowerTriangularMatrix::element(int m, int n) const
+{
+   REPORT
+   if (n<0 || m<n || m>=nrows_val)
+      Throw(IndexException(m,n,*this,true));
+   return store[tristore(m)+n];
+}
+
+Real& DiagonalMatrix::element(int m, int n)
+{
+   REPORT
+   if (n<0 || m!=n || m>=nrows_val || n>=ncols_val)
+      Throw(IndexException(m,n,*this,true));
+   return store[n];
+}
+
+Real DiagonalMatrix::element(int m, int n) const
+{
+   REPORT
+   if (n<0 || m!=n || m>=nrows_val || n>=ncols_val)
+      Throw(IndexException(m,n,*this,true));
+   return store[n];
+}
+
+Real& DiagonalMatrix::element(int m)
+{
+   REPORT
+   if (m<0 || m>=nrows_val) Throw(IndexException(m,*this,true));
+   return store[m];
+}
+
+Real DiagonalMatrix::element(int m) const
+{
+   REPORT
+   if (m<0 || m>=nrows_val) Throw(IndexException(m,*this,true));
+   return store[m];
+}
+
+Real& ColumnVector::element(int m)
+{
+   REPORT
+   if (m<0 || m>= nrows_val) Throw(IndexException(m,*this,true));
+   return store[m];
+}
+
+Real ColumnVector::element(int m) const
+{
+   REPORT
+   if (m<0 || m>= nrows_val) Throw(IndexException(m,*this,true));
+   return store[m];
+}
+
+Real& RowVector::element(int n)
+{
+   REPORT
+   if (n<0 || n>= ncols_val)  Throw(IndexException(n,*this,true));
+   return store[n];
+}
+
+Real RowVector::element(int n) const
+{
+   REPORT
+   if (n<0 || n>= ncols_val)  Throw(IndexException(n,*this,true));
+   return store[n];
+}
+
+Real& BandMatrix::element(int m, int n)
+{
+   REPORT
+   int w = upper_val+lower_val+1; int i = lower_val+n-m;
+   if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real BandMatrix::element(int m, int n) const
+{
+   REPORT
+   int w = upper_val+lower_val+1; int i = lower_val+n-m;
+   if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real& UpperBandMatrix::element(int m, int n)
+{
+   REPORT
+   int w = upper_val+1; int i = n-m;
+   if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real UpperBandMatrix::element(int m, int n) const
+{
+   REPORT
+   int w = upper_val+1; int i = n-m;
+   if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real& LowerBandMatrix::element(int m, int n)
+{
+   REPORT
+   int w = lower_val+1; int i = lower_val+n-m;
+   if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real LowerBandMatrix::element(int m, int n) const
+{
+   REPORT
+   int w = lower_val+1; int i = lower_val+n-m;
+   if (m<0 || m>= nrows_val || n<0 || n>= ncols_val || i<0 || i>=w)
+      Throw(IndexException(m,n,*this,true));
+   return store[w*m+i];
+}
+
+Real& SymmetricBandMatrix::element(int m, int n)
+{
+   REPORT
+   int w = lower_val+1;
+   if (m>=n)
+   {
+      REPORT
+      int i = lower_val+n-m;
+      if ( m>=nrows_val || n<0 || i<0 )
+         Throw(IndexException(m,n,*this,true));
+      return store[w*m+i];
+   }
+   else
+   {
+      REPORT
+      int i = lower_val+m-n;
+      if ( n>=nrows_val || m<0 || i<0 )
+         Throw(IndexException(m,n,*this,true));
+      return store[w*n+i];
+   }
+}
+
+Real SymmetricBandMatrix::element(int m, int n) const
+{
+   REPORT
+   int w = lower_val+1;
+   if (m>=n)
+   {
+      REPORT
+      int i = lower_val+n-m;
+      if ( m>=nrows_val || n<0 || i<0 )
+         Throw(IndexException(m,n,*this,true));
+      return store[w*m+i];
+   }
+   else
+   {
+      REPORT
+      int i = lower_val+m-n;
+      if ( n>=nrows_val || m<0 || i<0 )
+         Throw(IndexException(m,n,*this,true));
+      return store[w*n+i];
+   }
+}
+
+#ifdef use_namespace
+}
+#endif
+
+
+///}
Index: trunk/BNC/newmat/newmat7.cpp
===================================================================
--- trunk/BNC/newmat/newmat7.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmat7.cpp	(revision 2013)
@@ -0,0 +1,1032 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmat7.cpp
+/// Invert, solve, binary operations.
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,7); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+//***************************** solve routines ******************************/
+
+GeneralMatrix* GeneralMatrix::MakeSolver()
+{
+   REPORT
+   GeneralMatrix* gm = new CroutMatrix(*this);
+   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
+}
+
+GeneralMatrix* Matrix::MakeSolver()
+{
+   REPORT
+   GeneralMatrix* gm = new CroutMatrix(*this);
+   MatrixErrorNoSpace(gm); gm->ReleaseAndDelete(); return gm;
+}
+
+void CroutMatrix::Solver(MatrixColX& mcout, const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip; Real* el = mcin.data-i; Real* el1 = el;
+   while (i--) *el++ = 0.0;
+   el += mcin.storage; i = nrows_val - mcin.skip - mcin.storage;
+   while (i--) *el++ = 0.0;
+   lubksb(el1, mcout.skip);
+}
+
+
+// Do we need check for entirely zero output?
+
+void UpperTriangularMatrix::Solver(MatrixColX& mcout,
+   const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
+   while (i-- > 0) *elx++ = 0.0;
+   int nr = mcin.skip+mcin.storage;
+   elx = mcin.data+mcin.storage; Real* el = elx;
+   int j = mcout.skip+mcout.storage-nr;
+   int nc = ncols_val-nr; i = nr-mcout.skip;
+   while (j-- > 0) *elx++ = 0.0;
+   Real* Ael = store + (nr*(2*ncols_val-nr+1))/2; j = 0;
+   while (i-- > 0)
+   {
+      elx = el; Real sum = 0.0; int jx = j++; Ael -= nc;
+      while (jx--) sum += *(--Ael) * *(--elx);
+      elx--; *elx = (*elx - sum) / *(--Ael);
+   }
+}
+
+void LowerTriangularMatrix::Solver(MatrixColX& mcout,
+   const MatrixColX& mcin)
+{
+   REPORT
+   int i = mcin.skip-mcout.skip; Real* elx = mcin.data-i;
+   while (i-- > 0) *elx++ = 0.0;
+   int nc = mcin.skip; i = nc+mcin.storage; elx = mcin.data+mcin.storage;
+   int nr = mcout.skip+mcout.storage; int j = nr-i; i = nr-nc;
+   while (j-- > 0) *elx++ = 0.0;
+   Real* el = mcin.data; Real* Ael = store + (nc*(nc+1))/2; j = 0;
+   while (i-- > 0)
+   {
+      elx = el; Real sum = 0.0; int jx = j++; Ael += nc;
+      while (jx--) sum += *Ael++ * *elx++;
+      *elx = (*elx - sum) / *Ael++;
+   }
+}
+
+//******************* carry out binary operations *************************/
+
+static GeneralMatrix*
+   GeneralMult(GeneralMatrix*,GeneralMatrix*,MultipliedMatrix*,MatrixType);
+static GeneralMatrix*
+   GeneralSolv(GeneralMatrix*,GeneralMatrix*,BaseMatrix*,MatrixType);
+static GeneralMatrix*
+   GeneralSolvI(GeneralMatrix*,BaseMatrix*,MatrixType);
+static GeneralMatrix*
+   GeneralKP(GeneralMatrix*,GeneralMatrix*,KPMatrix*,MatrixType);
+
+GeneralMatrix* MultipliedMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   gm2 = ((BaseMatrix*&)bm2)->Evaluate();
+   gm2 = gm2->Evaluate(gm2->type().MultRHS());     // no symmetric on RHS
+   gm1 = ((BaseMatrix*&)bm1)->Evaluate();
+   return GeneralMult(gm1, gm2, this, mt);
+}
+
+GeneralMatrix* SolvedMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   gm1 = ((BaseMatrix*&)bm1)->Evaluate();
+   gm2 = ((BaseMatrix*&)bm2)->Evaluate();
+   return GeneralSolv(gm1,gm2,this,mt);
+}
+
+GeneralMatrix* KPMatrix::Evaluate(MatrixType mt)
+{
+   REPORT
+   gm1 = ((BaseMatrix*&)bm1)->Evaluate();
+   gm2 = ((BaseMatrix*&)bm2)->Evaluate();
+   return GeneralKP(gm1,gm2,this,mt);
+}
+
+// routines for adding or subtracting matrices of identical storage structure
+
+static void Add(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   Real* s1=gm1->Store(); Real* s2=gm2->Store();
+   Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   {
+       *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
+       *s++ = *s1++ + *s2++; *s++ = *s1++ + *s2++;
+   }
+   i=gm->Storage() & 3; while (i--) *s++ = *s1++ + *s2++;
+}
+
+static void AddTo(GeneralMatrix* gm, const GeneralMatrix* gm2)
+{
+   REPORT
+   const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   { *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; *s++ += *s2++; }
+   i=gm->Storage() & 3; while (i--) *s++ += *s2++;
+}
+
+void GeneralMatrix::PlusEqual(const GeneralMatrix& gm)
+{
+   REPORT
+   if (nrows_val != gm.nrows_val || ncols_val != gm.ncols_val)
+      Throw(IncompatibleDimensionsException(*this, gm));
+   AddTo(this, &gm);
+}
+
+static void Subtract(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   Real* s1=gm1->Store(); Real* s2=gm2->Store();
+   Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   {
+       *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
+       *s++ = *s1++ - *s2++; *s++ = *s1++ - *s2++;
+   }
+   i=gm->Storage() & 3; while (i--) *s++ = *s1++ - *s2++;
+}
+
+static void SubtractFrom(GeneralMatrix* gm, const GeneralMatrix* gm2)
+{
+   REPORT
+   const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   { *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; *s++ -= *s2++; }
+   i=gm->Storage() & 3; while (i--) *s++ -= *s2++;
+}
+
+void GeneralMatrix::MinusEqual(const GeneralMatrix& gm)
+{
+   REPORT
+   if (nrows_val != gm.nrows_val || ncols_val != gm.ncols_val)
+      Throw(IncompatibleDimensionsException(*this, gm));
+   SubtractFrom(this, &gm);
+}
+
+static void ReverseSubtract(GeneralMatrix* gm, const GeneralMatrix* gm2)
+{
+   REPORT
+   const Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   {
+      *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
+      *s = *s2++ - *s; s++; *s = *s2++ - *s; s++;
+   }
+   i=gm->Storage() & 3; while (i--) { *s = *s2++ - *s; s++; }
+}
+
+static void SP(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   Real* s1=gm1->Store(); Real* s2=gm2->Store();
+   Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   {
+       *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
+       *s++ = *s1++ * *s2++; *s++ = *s1++ * *s2++;
+   }
+   i=gm->Storage() & 3; while (i--) *s++ = *s1++ * *s2++;
+}
+
+static void SP(GeneralMatrix* gm, GeneralMatrix* gm2)
+{
+   REPORT
+   Real* s2=gm2->Store(); Real* s=gm->Store(); int i=gm->Storage() >> 2;
+   while (i--)
+   { *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; *s++ *= *s2++; }
+   i=gm->Storage() & 3; while (i--) *s++ *= *s2++;
+}
+
+// routines for adding or subtracting matrices of different storage structure
+
+static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+   MatrixRow mr(gm, StoreOnExit+DirectPart);
+   while (nr--) { mr.Add(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
+}
+
+static void AddDS(GeneralMatrix* gm, GeneralMatrix* gm2)
+// Add into first argument
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
+   MatrixRow mr2(gm2, LoadOnEntry);
+   while (nr--) { mr.Add(mr2); mr.Next(); mr2.Next(); }
+}
+
+static void SubtractDS
+   (GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+   MatrixRow mr(gm, StoreOnExit+DirectPart);
+   while (nr--) { mr.Sub(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
+}
+
+static void SubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
+   MatrixRow mr2(gm2, LoadOnEntry);
+   while (nr--) { mr.Sub(mr2); mr.Next(); mr2.Next(); }
+}
+
+static void ReverseSubtractDS(GeneralMatrix* gm, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart);
+   MatrixRow mr2(gm2, LoadOnEntry);
+   while (nr--) { mr.RevSub(mr2); mr2.Next(); mr.Next(); }
+}
+
+static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+   MatrixRow mr(gm, StoreOnExit+DirectPart);
+   while (nr--) { mr.Multiply(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
+}
+
+static void SPDS(GeneralMatrix* gm, GeneralMatrix* gm2)
+// SP into first argument
+{
+   REPORT
+   int nr = gm->Nrows();
+   MatrixRow mr(gm, StoreOnExit+LoadOnEntry+DirectPart);
+   MatrixRow mr2(gm2, LoadOnEntry);
+   while (nr--) { mr.Multiply(mr2); mr.Next(); mr2.Next(); }
+}
+
+static GeneralMatrix* GeneralMult1(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   MultipliedMatrix* mm, MatrixType mtx)
+{
+   REPORT
+   Tracer tr("GeneralMult1");
+   int nr=gm1->Nrows(); int nc=gm2->Ncols();
+   if (gm1->Ncols() !=gm2->Nrows())
+      Throw(IncompatibleDimensionsException(*gm1, *gm2));
+   GeneralMatrix* gmx = mtx.New(nr,nc,mm);
+
+   MatrixCol mcx(gmx, StoreOnExit+DirectPart);
+   MatrixCol mc2(gm2, LoadOnEntry);
+   while (nc--)
+   {
+      MatrixRow mr1(gm1, LoadOnEntry, mcx.Skip());
+      Real* el = mcx.Data();                         // pointer to an element
+      int n = mcx.Storage();
+      while (n--) { *(el++) = DotProd(mr1,mc2); mr1.Next(); }
+      mc2.Next(); mcx.Next();
+   }
+   gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+static GeneralMatrix* GeneralMult2(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   MultipliedMatrix* mm, MatrixType mtx)
+{
+   // version that accesses by row only - not good for thin matrices
+   // or column vectors in right hand term.
+   REPORT
+   Tracer tr("GeneralMult2");
+   int nr=gm1->Nrows(); int nc=gm2->Ncols();
+   if (gm1->Ncols() !=gm2->Nrows())
+      Throw(IncompatibleDimensionsException(*gm1, *gm2));
+   GeneralMatrix* gmx = mtx.New(nr,nc,mm);
+
+   MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart);
+   MatrixRow mr1(gm1, LoadOnEntry);
+   while (nr--)
+   {
+      MatrixRow mr2(gm2, LoadOnEntry, mr1.Skip());
+      Real* el = mr1.Data();                         // pointer to an element
+      int n = mr1.Storage();
+      mrx.Zero();
+      while (n--) { mrx.AddScaled(mr2, *el++); mr2.Next(); }
+      mr1.Next(); mrx.Next();
+   }
+   gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+static GeneralMatrix* mmMult(GeneralMatrix* gm1, GeneralMatrix* gm2)
+{
+   // matrix multiplication for type Matrix only
+   REPORT
+   Tracer tr("MatrixMult");
+
+   int nr=gm1->Nrows(); int ncr=gm1->Ncols(); int nc=gm2->Ncols();
+   if (ncr != gm2->Nrows()) Throw(IncompatibleDimensionsException(*gm1,*gm2));
+
+   Matrix* gm = new Matrix(nr,nc); MatrixErrorNoSpace(gm);
+
+   Real* s1=gm1->Store(); Real* s2=gm2->Store(); Real* s=gm->Store();
+
+   if (ncr)
+   {
+      while (nr--)
+      {
+         Real* s2x = s2; int j = ncr;
+         Real* sx = s; Real f = *s1++; int k = nc;
+         while (k--) *sx++ = f * *s2x++;
+         while (--j)
+            { sx = s; f = *s1++; k = nc; while (k--) *sx++ += f * *s2x++; }
+         s = sx;
+      }
+   }
+   else *gm = 0.0;
+
+   gm->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gm;
+}
+
+static GeneralMatrix* GeneralMult(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   MultipliedMatrix* mm, MatrixType mtx)
+{
+   if ( Rectangular(gm1->type(), gm2->type(), mtx))
+      { REPORT return mmMult(gm1, gm2); }
+   Compare(gm1->type() * gm2->type(),mtx);
+   int nr = gm2->Nrows(); int nc = gm2->Ncols();
+   if (nc <= 5 && nr > nc) { REPORT return GeneralMult1(gm1, gm2, mm, mtx); }
+   REPORT return GeneralMult2(gm1, gm2, mm, mtx);
+}
+
+static GeneralMatrix* GeneralKP(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   KPMatrix* kp, MatrixType mtx)
+{
+   REPORT
+   Tracer tr("GeneralKP");
+   int nr1 = gm1->Nrows(); int nc1 = gm1->Ncols();
+   int nr2 = gm2->Nrows(); int nc2 = gm2->Ncols();
+   Compare((gm1->type()).KP(gm2->type()),mtx);
+   GeneralMatrix* gmx = mtx.New(nr1*nr2, nc1*nc2, kp);
+   MatrixRow mrx(gmx, LoadOnEntry+StoreOnExit+DirectPart);
+   MatrixRow mr1(gm1, LoadOnEntry);
+   for (int i = 1; i <= nr1; ++i)
+   {
+      MatrixRow mr2(gm2, LoadOnEntry);
+      for (int j = 1; j <= nr2; ++j)
+         { mrx.KP(mr1,mr2); mr2.Next(); mrx.Next(); }
+      mr1.Next();
+   }
+   gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+static GeneralMatrix* GeneralSolv(GeneralMatrix* gm1, GeneralMatrix* gm2,
+   BaseMatrix* sm, MatrixType mtx)
+{
+   REPORT
+   Tracer tr("GeneralSolv");
+   Compare(gm1->type().i() * gm2->type(),mtx);
+   int nr = gm1->Nrows();
+   if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1));
+   int nc = gm2->Ncols();
+   if (gm1->Ncols() != gm2->Nrows())
+      Throw(IncompatibleDimensionsException(*gm1, *gm2));
+   GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx);
+   Real* r = new Real [nr]; MatrixErrorNoSpace(r);
+   MONITOR_REAL_NEW("Make   (GenSolv)",nr,r)
+   GeneralMatrix* gms = gm1->MakeSolver();
+   Try
+   {
+
+      MatrixColX mcx(gmx, r, StoreOnExit+DirectPart);   // copy to and from r
+         // this must be inside Try so mcx is destroyed before gmx
+      MatrixColX mc2(gm2, r, LoadOnEntry);
+      while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); }
+   }
+   CatchAll
+   {
+      if (gms) gms->tDelete();
+      delete gmx;                   // <--------------------
+      gm2->tDelete();
+      MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
+                          // AT&T version 2.1 gives an internal error
+      delete [] r;
+      ReThrow;
+   }
+   gms->tDelete(); gmx->ReleaseAndDelete(); gm2->tDelete();
+   MONITOR_REAL_DELETE("Delete (GenSolv)",nr,r)
+                          // AT&T version 2.1 gives an internal error
+   delete [] r;
+   return gmx;
+}
+
+// version for inverses - gm2 is identity
+static GeneralMatrix* GeneralSolvI(GeneralMatrix* gm1, BaseMatrix* sm,
+   MatrixType mtx)
+{
+   REPORT
+   Tracer tr("GeneralSolvI");
+   Compare(gm1->type().i(),mtx);
+   int nr = gm1->Nrows();
+   if (nr != gm1->Ncols()) Throw(NotSquareException(*gm1));
+   int nc = nr;
+   // DiagonalMatrix I(nr); I = 1;
+   IdentityMatrix I(nr);
+   GeneralMatrix* gmx = mtx.New(nr,nc,sm); MatrixErrorNoSpace(gmx);
+   Real* r = new Real [nr]; MatrixErrorNoSpace(r);
+   MONITOR_REAL_NEW("Make   (GenSolvI)",nr,r)
+   GeneralMatrix* gms = gm1->MakeSolver();
+   Try
+   {
+
+      MatrixColX mcx(gmx, r, StoreOnExit+DirectPart);   // copy to and from r
+         // this must be inside Try so mcx is destroyed before gmx
+      MatrixColX mc2(&I, r, LoadOnEntry);
+      while (nc--) { gms->Solver(mcx, mc2); mcx.Next(); mc2.Next(); }
+   }
+   CatchAll
+   {
+      if (gms) gms->tDelete();
+      delete gmx;
+      MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
+                          // AT&T version 2.1 gives an internal error
+      delete [] r;
+      ReThrow;
+   }
+   gms->tDelete(); gmx->ReleaseAndDelete();
+   MONITOR_REAL_DELETE("Delete (GenSolvI)",nr,r)
+                          // AT&T version 2.1 gives an internal error
+   delete [] r;
+   return gmx;
+}
+
+GeneralMatrix* InvertedMatrix::Evaluate(MatrixType mtx)
+{
+   // Matrix Inversion - use solve routines
+   Tracer tr("InvertedMatrix::Evaluate");
+   REPORT
+   gm=((BaseMatrix*&)bm)->Evaluate();
+   return GeneralSolvI(gm,this,mtx);
+}
+
+//*************************** New versions ************************
+
+GeneralMatrix* AddedMatrix::Evaluate(MatrixType mtd)
+{
+   REPORT
+   Tracer tr("AddedMatrix::Evaluate");
+   gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
+   int nr=gm1->Nrows(); int nc=gm1->Ncols();
+   if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
+   {
+      Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
+      CatchAll
+      {
+         gm1->tDelete(); gm2->tDelete();
+         ReThrow;
+      }
+   }
+   MatrixType mt1 = gm1->type(), mt2 = gm2->type(); MatrixType mts = mt1 + mt2;
+   if (!mtd) { REPORT mtd = mts; }
+   else if (!(mtd.DataLossOK || mtd >= mts))
+   {
+      REPORT
+      gm1->tDelete(); gm2->tDelete();
+      Throw(ProgramException("Illegal Conversion", mts, mtd));
+   }
+   GeneralMatrix* gmx;
+   bool c1 = (mtd == mt1), c2 = (mtd == mt2);
+   if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
+   {
+      if (gm1->reuse()) { REPORT AddTo(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (gm2->reuse()) { REPORT AddTo(gm2,gm1); gmx = gm2; }
+      else
+      {
+         REPORT
+         // what if new throws an exception
+         Try { gmx = mt1.New(nr,nc,this); }
+         CatchAll
+         {
+            ReThrow;
+         }
+         gmx->ReleaseAndDelete(); Add(gmx,gm1,gm2);
+      }
+   }
+   else
+   {
+      if (c1 && c2)
+      {
+         short SAO = gm1->SimpleAddOK(gm2);
+         if (SAO & 1) { REPORT c1 = false; }
+         if (SAO & 2) { REPORT c2 = false; }
+      }
+      if (c1 && gm1->reuse() )               // must have type test first
+         { REPORT AddDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (c2 && gm2->reuse() )
+         { REPORT AddDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; }
+      else
+      {
+         REPORT
+         Try { gmx = mtd.New(nr,nc,this); }
+         CatchAll
+         {
+            if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+            ReThrow;
+         }
+         AddDS(gmx,gm1,gm2);
+         if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+         gmx->ReleaseAndDelete();
+      }
+   }
+   return gmx;
+}
+
+GeneralMatrix* SubtractedMatrix::Evaluate(MatrixType mtd)
+{
+   REPORT
+   Tracer tr("SubtractedMatrix::Evaluate");
+   gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
+   int nr=gm1->Nrows(); int nc=gm1->Ncols();
+   if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
+   {
+      Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
+      CatchAll
+      {
+         gm1->tDelete(); gm2->tDelete();
+         ReThrow;
+      }
+   }
+   MatrixType mt1 = gm1->type(), mt2 = gm2->type(); MatrixType mts = mt1 + mt2;
+   if (!mtd) { REPORT mtd = mts; }
+   else if (!(mtd.DataLossOK || mtd >= mts))
+   {
+      gm1->tDelete(); gm2->tDelete();
+      Throw(ProgramException("Illegal Conversion", mts, mtd));
+   }
+   GeneralMatrix* gmx;
+   bool c1 = (mtd == mt1), c2 = (mtd == mt2);
+   if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
+   {
+      if (gm1->reuse())
+         { REPORT SubtractFrom(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (gm2->reuse()) { REPORT ReverseSubtract(gm2,gm1); gmx = gm2; }
+      else
+      {
+         REPORT
+         Try { gmx = mt1.New(nr,nc,this); }
+         CatchAll
+         {
+            ReThrow;
+         }
+         gmx->ReleaseAndDelete(); Subtract(gmx,gm1,gm2);
+      }
+   }
+   else
+   {
+      if (c1 && c2)
+      {
+         short SAO = gm1->SimpleAddOK(gm2);
+         if (SAO & 1) { REPORT c1 = false; }
+         if (SAO & 2) { REPORT c2 = false; }
+      }
+      if (c1 && gm1->reuse() )               // must have type test first
+         { REPORT SubtractDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (c2 && gm2->reuse() )
+      {
+         REPORT ReverseSubtractDS(gm2,gm1);
+         if (!c1) gm1->tDelete(); gmx = gm2;
+      }
+      else
+      {
+         REPORT
+         // what if New throws and exception
+         Try { gmx = mtd.New(nr,nc,this); }
+         CatchAll
+         {
+            if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+            ReThrow;
+         }
+         SubtractDS(gmx,gm1,gm2);
+         if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+         gmx->ReleaseAndDelete();
+      }
+   }
+   return gmx;
+}
+
+GeneralMatrix* SPMatrix::Evaluate(MatrixType mtd)
+{
+   REPORT
+   Tracer tr("SPMatrix::Evaluate");
+   gm1=((BaseMatrix*&)bm1)->Evaluate(); gm2=((BaseMatrix*&)bm2)->Evaluate();
+   int nr=gm1->Nrows(); int nc=gm1->Ncols();
+   if (nr!=gm2->Nrows() || nc!=gm2->Ncols())
+   {
+      Try { Throw(IncompatibleDimensionsException(*gm1, *gm2)); }
+      CatchAll
+      {
+         gm1->tDelete(); gm2->tDelete();
+         ReThrow;
+      }
+   }
+   MatrixType mt1 = gm1->type(), mt2 = gm2->type();
+   MatrixType mts = mt1.SP(mt2);
+   if (!mtd) { REPORT mtd = mts; }
+   else if (!(mtd.DataLossOK || mtd >= mts))
+   {
+      gm1->tDelete(); gm2->tDelete();
+      Throw(ProgramException("Illegal Conversion", mts, mtd));
+   }
+   GeneralMatrix* gmx;
+   bool c1 = (mtd == mt1), c2 = (mtd == mt2);
+   if ( c1 && c2 && (gm1->SimpleAddOK(gm2) == 0) )
+   {
+      if (gm1->reuse()) { REPORT SP(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (gm2->reuse()) { REPORT SP(gm2,gm1); gmx = gm2; }
+      else
+      {
+         REPORT
+         Try { gmx = mt1.New(nr,nc,this); }
+         CatchAll
+         {
+            ReThrow;
+         }
+         gmx->ReleaseAndDelete(); SP(gmx,gm1,gm2);
+      }
+   }
+   else
+   {
+      if (c1 && c2)
+      {
+         short SAO = gm1->SimpleAddOK(gm2);
+         if (SAO & 1) { REPORT c2 = false; }    // c1 and c2 swapped
+         if (SAO & 2) { REPORT c1 = false; }
+      }
+      if (c1 && gm1->reuse() )               // must have type test first
+         { REPORT SPDS(gm1,gm2); gm2->tDelete(); gmx = gm1; }
+      else if (c2 && gm2->reuse() )
+         { REPORT SPDS(gm2,gm1); if (!c1) gm1->tDelete(); gmx = gm2; }
+      else
+      {
+         REPORT
+         // what if New throws and exception
+         Try { gmx = mtd.New(nr,nc,this); }
+         CatchAll
+         {
+            if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+            ReThrow;
+         }
+         SPDS(gmx,gm1,gm2);
+         if (!c1) gm1->tDelete(); if (!c2) gm2->tDelete();
+         gmx->ReleaseAndDelete();
+      }
+   }
+   return gmx;
+}
+
+
+
+//*************************** norm functions ****************************/
+
+Real BaseMatrix::norm1() const
+{
+   // maximum of sum of absolute values of a column
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   int nc = gm->Ncols(); Real value = 0.0;
+   MatrixCol mc(gm, LoadOnEntry);
+   while (nc--)
+      { Real v = mc.SumAbsoluteValue(); if (value < v) value = v; mc.Next(); }
+   gm->tDelete(); return value;
+}
+
+Real BaseMatrix::norm_infinity() const
+{
+   // maximum of sum of absolute values of a row
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   int nr = gm->Nrows(); Real value = 0.0;
+   MatrixRow mr(gm, LoadOnEntry);
+   while (nr--)
+      { Real v = mr.SumAbsoluteValue(); if (value < v) value = v; mr.Next(); }
+   gm->tDelete(); return value;
+}
+
+//********************** Concatenation and stacking *************************/
+
+GeneralMatrix* ConcatenatedMatrix::Evaluate(MatrixType mtx)
+{
+   REPORT
+   Tracer tr("Concatenate");
+      gm2 = ((BaseMatrix*&)bm2)->Evaluate();
+      gm1 = ((BaseMatrix*&)bm1)->Evaluate();
+      Compare(gm1->type() | gm2->type(),mtx);
+      int nr=gm1->Nrows(); int nc = gm1->Ncols() + gm2->Ncols();
+      if (nr != gm2->Nrows())
+         Throw(IncompatibleDimensionsException(*gm1, *gm2));
+      GeneralMatrix* gmx = mtx.New(nr,nc,this);
+      MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+      MatrixRow mr(gmx, StoreOnExit+DirectPart);
+      while (nr--) { mr.ConCat(mr1,mr2); mr1.Next(); mr2.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+GeneralMatrix* StackedMatrix::Evaluate(MatrixType mtx)
+{
+   REPORT
+   Tracer tr("Stack");
+      gm2 = ((BaseMatrix*&)bm2)->Evaluate();
+      gm1 = ((BaseMatrix*&)bm1)->Evaluate();
+      Compare(gm1->type() & gm2->type(),mtx);
+      int nc=gm1->Ncols();
+      int nr1 = gm1->Nrows(); int nr2 = gm2->Nrows();
+      if (nc != gm2->Ncols())
+         Throw(IncompatibleDimensionsException(*gm1, *gm2));
+      GeneralMatrix* gmx = mtx.New(nr1+nr2,nc,this);
+      MatrixRow mr1(gm1, LoadOnEntry); MatrixRow mr2(gm2, LoadOnEntry);
+      MatrixRow mr(gmx, StoreOnExit+DirectPart);
+      while (nr1--) { mr.Copy(mr1); mr1.Next(); mr.Next(); }
+      while (nr2--) { mr.Copy(mr2); mr2.Next(); mr.Next(); }
+      gmx->ReleaseAndDelete(); gm1->tDelete(); gm2->tDelete(); return gmx;
+}
+
+// ************************* equality of matrices ******************** //
+
+static bool RealEqual(Real* s1, Real* s2, int n)
+{
+   int i = n >> 2;
+   while (i--)
+   {
+      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
+      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
+   }
+   i = n & 3; while (i--) if (*s1++ != *s2++) return false;
+   return true;
+}
+
+static bool intEqual(int* s1, int* s2, int n)
+{
+   int i = n >> 2;
+   while (i--)
+   {
+      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
+      if (*s1++ != *s2++) return false; if (*s1++ != *s2++) return false;
+   }
+   i = n & 3; while (i--) if (*s1++ != *s2++) return false;
+   return true;
+}
+
+
+bool operator==(const BaseMatrix& A, const BaseMatrix& B)
+{
+   Tracer tr("BaseMatrix ==");
+   REPORT
+   GeneralMatrix* gmA = ((BaseMatrix&)A).Evaluate();
+   GeneralMatrix* gmB = ((BaseMatrix&)B).Evaluate();
+
+   if (gmA == gmB)                            // same matrix
+      { REPORT gmA->tDelete(); return true; }
+
+   if ( gmA->Nrows() != gmB->Nrows() || gmA->Ncols() != gmB->Ncols() )
+                                              // different dimensions
+      { REPORT gmA->tDelete(); gmB->tDelete(); return false; }
+
+   // check for CroutMatrix or BandLUMatrix
+   MatrixType AType = gmA->type(); MatrixType BType = gmB->type();
+   if (AType.CannotConvert() || BType.CannotConvert() )
+   {
+      REPORT
+      bool bx = gmA->IsEqual(*gmB);
+      gmA->tDelete(); gmB->tDelete();
+      return bx;
+   }
+
+   // is matrix storage the same
+   // will need to modify if further matrix structures are introduced
+   if (AType == BType && gmA->bandwidth() == gmB->bandwidth())
+   {                                          // compare store
+      REPORT
+      bool bx = RealEqual(gmA->Store(),gmB->Store(),gmA->Storage());
+      gmA->tDelete(); gmB->tDelete();
+      return bx;
+   }
+
+   // matrix storage different - just subtract
+   REPORT  return is_zero(*gmA-*gmB);
+}
+
+bool operator==(const GeneralMatrix& A, const GeneralMatrix& B)
+{
+   Tracer tr("GeneralMatrix ==");
+   // May or may not call tDeletes
+   REPORT
+
+   if (&A == &B)                              // same matrix
+      { REPORT return true; }
+
+   if ( A.Nrows() != B.Nrows() || A.Ncols() != B.Ncols() )
+      { REPORT return false; }                // different dimensions
+
+   // check for CroutMatrix or BandLUMatrix
+   MatrixType AType = A.Type(); MatrixType BType = B.Type();
+   if (AType.CannotConvert() || BType.CannotConvert() )
+      { REPORT  return A.IsEqual(B); }
+
+   // is matrix storage the same
+   // will need to modify if further matrix structures are introduced
+   if (AType == BType && A.bandwidth() == B.bandwidth())
+      { REPORT return RealEqual(A.Store(),B.Store(),A.Storage()); }
+
+   // matrix storage different - just subtract
+   REPORT  return is_zero(A-B);
+}
+
+bool GeneralMatrix::is_zero() const
+{
+   REPORT
+   Real* s=store; int i = storage >> 2;
+   while (i--)
+   {
+      if (*s++) return false; if (*s++) return false;
+      if (*s++) return false; if (*s++) return false;
+   }
+   i = storage & 3; while (i--) if (*s++) return false;
+   return true;
+}
+
+bool is_zero(const BaseMatrix& A)
+{
+   Tracer tr("BaseMatrix::is_zero");
+   REPORT
+   GeneralMatrix* gm1 = 0; bool bx;
+   Try { gm1=((BaseMatrix&)A).Evaluate(); bx = gm1->is_zero(); }
+   CatchAll { if (gm1) gm1->tDelete(); ReThrow; }
+   gm1->tDelete();
+   return bx;
+}
+
+// IsEqual functions - insist matrices are of same type
+// as well as equal values to be equal
+
+bool GeneralMatrix::IsEqual(const GeneralMatrix& A) const
+{
+   Tracer tr("GeneralMatrix IsEqual");
+   if (A.type() != type())                       // not same types
+      { REPORT return false; }
+   if (&A == this)                               // same matrix
+      { REPORT  return true; }
+   if (A.nrows_val != nrows_val || A.ncols_val != ncols_val)
+                                                 // different dimensions
+   { REPORT return false; }
+   // is matrix storage the same - compare store
+   REPORT
+   return RealEqual(A.store,store,storage);
+}
+
+bool CroutMatrix::IsEqual(const GeneralMatrix& A) const
+{
+   Tracer tr("CroutMatrix IsEqual");
+   if (A.type() != type())                       // not same types
+      { REPORT return false; }
+   if (&A == this)                               // same matrix
+      { REPORT  return true; }
+   if (A.nrows_val != nrows_val || A.ncols_val != ncols_val)
+                                                 // different dimensions
+   { REPORT return false; }
+   // is matrix storage the same - compare store
+   REPORT
+   return RealEqual(A.store,store,storage)
+      && intEqual(((CroutMatrix&)A).indx, indx, nrows_val);
+}
+
+
+bool BandLUMatrix::IsEqual(const GeneralMatrix& A) const
+{
+   Tracer tr("BandLUMatrix IsEqual");
+   if (A.type() != type())                       // not same types
+      { REPORT  return false; }
+   if (&A == this)                               // same matrix
+      { REPORT  return true; }
+   if ( A.Nrows() != nrows_val || A.Ncols() != ncols_val
+      || ((BandLUMatrix&)A).m1 != m1 || ((BandLUMatrix&)A).m2 != m2 )
+                                                 // different dimensions
+   { REPORT  return false; }
+
+   // matrix storage the same - compare store
+   REPORT
+   return RealEqual(A.Store(),store,storage)
+      && RealEqual(((BandLUMatrix&)A).store2,store2,storage2)
+      && intEqual(((BandLUMatrix&)A).indx, indx, nrows_val);
+}
+
+
+// ************************* cross products ******************** //
+
+inline void crossproduct_body(Real* a, Real* b, Real* c)
+{
+   c[0] = a[1] * b[2] - a[2] * b[1];
+   c[1] = a[2] * b[0] - a[0] * b[2];
+   c[2] = a[0] * b[1] - a[1] * b[0];
+}
+
+Matrix crossproduct(const Matrix& A, const Matrix& B)
+{
+   REPORT
+   int ac = A.Ncols(); int ar = A.Nrows();
+   int bc = B.Ncols(); int br = B.Nrows();
+   Real* a = A.Store(); Real* b = B.Store();
+   if (ac == 3)
+   {
+      if (bc != 3 || ar != 1 || br != 1)
+         { Tracer et("crossproduct"); IncompatibleDimensionsException(A, B); }
+      REPORT
+      RowVector C(3);  Real* c = C.Store(); crossproduct_body(a, b, c);
+      return (Matrix&)C;
+   }
+   else
+   {
+      if (ac != 1 || bc != 1 || ar != 3 || br != 3)
+         { Tracer et("crossproduct"); IncompatibleDimensionsException(A, B); }
+      REPORT
+      ColumnVector C(3);  Real* c = C.Store(); crossproduct_body(a, b, c);
+      return (Matrix&)C;
+   }
+}
+
+ReturnMatrix crossproduct_rows(const Matrix& A, const Matrix& B)
+{
+   REPORT
+   int n = A.Nrows();
+   if (A.Ncols() != 3 || B.Ncols() != 3 || n != B.Nrows())
+   {
+      Tracer et("crossproduct_rows"); IncompatibleDimensionsException(A, B);
+   }
+   Matrix C(n, 3);
+   Real* a = A.Store(); Real* b = B.Store(); Real* c = C.Store();
+   if (n--)
+   {
+      for (;;)
+      {
+         crossproduct_body(a, b, c);
+         if (!(n--)) break;
+         a += 3; b += 3; c += 3;
+      }
+   }
+
+   return C.ForReturn();
+}
+
+ReturnMatrix crossproduct_columns(const Matrix& A, const Matrix& B)
+{
+   REPORT
+   int n = A.Ncols();
+   if (A.Nrows() != 3 || B.Nrows() != 3 || n != B.Ncols())
+   {
+      Tracer et("crossproduct_columns");
+      IncompatibleDimensionsException(A, B);
+   }
+   Matrix C(3, n);
+   Real* a = A.Store(); Real* b = B.Store(); Real* c = C.Store();
+   Real* an = a+n; Real* an2 = an+n;
+   Real* bn = b+n; Real* bn2 = bn+n;
+   Real* cn = c+n; Real* cn2 = cn+n;
+
+   int i = n; 
+   while (i--)
+   {
+      *c++   = *an    * *bn2   - *an2   * *bn;
+      *cn++  = *an2++ * *b     - *a     * *bn2++;
+      *cn2++ = *a++   * *bn++  - *an++  * *b++;
+   }
+
+   return C.ForReturn();
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
+
Index: trunk/BNC/newmat/newmat8.cpp
===================================================================
--- trunk/BNC/newmat/newmat8.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmat8.cpp	(revision 2013)
@@ -0,0 +1,832 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmat8.cpp
+/// LU transform, scalar functions of matrices.
+
+// Copyright (C) 1991,2,3,4,8: R B Davies
+
+#define WANT_MATH
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+#include "precisio.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,8); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/************************** LU transformation ****************************/
+
+void CroutMatrix::ludcmp()
+// LU decomposition from Golub & Van Loan, algorithm 3.4.1, (the "outer
+// product" version).
+// This replaces the code derived from Numerical Recipes in C in previous
+// versions of newmat and being row oriented runs much faster with large
+// matrices.
+{
+   REPORT
+   Tracer tr( "Crout(ludcmp)" ); sing = false;
+   Real* akk = store;                    // runs down diagonal
+
+   Real big = fabs(*akk); int mu = 0; Real* ai = akk; int k;
+
+   for (k = 1; k < nrows_val; k++)
+   {
+      ai += nrows_val; const Real trybig = fabs(*ai);
+      if (big < trybig) { big = trybig; mu = k; }
+   }
+
+
+   if (nrows_val) for (k = 0;;)
+   {
+      /*
+      int mu1;
+      {
+         Real big = fabs(*akk); mu1 = k; Real* ai = akk; int i;
+
+         for (i = k+1; i < nrows_val; i++)
+         {
+            ai += nrows_val; const Real trybig = fabs(*ai);
+            if (big < trybig) { big = trybig; mu1 = i; }
+         }
+      }
+      if (mu1 != mu) cout << k << " " << mu << " " << mu1 << endl;
+      */
+
+      indx[k] = mu;
+
+      if (mu != k)                       //row swap
+      {
+         Real* a1 = store + nrows_val * k;
+         Real* a2 = store + nrows_val * mu; d = !d;
+         int j = nrows_val;
+         while (j--) { const Real temp = *a1; *a1++ = *a2; *a2++ = temp; }
+      }
+
+      Real diag = *akk; big = 0; mu = k + 1;
+      if (diag != 0)
+      {
+         ai = akk; int i = nrows_val - k - 1;
+         while (i--)
+         {
+            ai += nrows_val; Real* al = ai;
+            Real mult = *al / diag; *al = mult;
+            int l = nrows_val - k - 1; Real* aj = akk;
+            // work out the next pivot as part of this loop
+            // this saves a column operation
+            if (l-- != 0)
+            {
+               *(++al) -= (mult * *(++aj));
+               const Real trybig = fabs(*al);
+               if (big < trybig) { big = trybig; mu = nrows_val - i - 1; }
+               while (l--) *(++al) -= (mult * *(++aj));
+            }
+         }
+      }
+      else sing = true;
+      if (++k == nrows_val) break;          // so next line won't overflow
+      akk += nrows_val + 1;
+   }
+}
+
+void CroutMatrix::lubksb(Real* B, int mini)
+{
+   REPORT
+   // this has been adapted from Numerical Recipes in C. The code has been
+   // substantially streamlined, so I do not think much of the original
+   // copyright remains. However there is not much opportunity for
+   // variation in the code, so it is still similar to the NR code.
+   // I follow the NR code in skipping over initial zeros in the B vector.
+
+   Tracer tr("Crout(lubksb)");
+   if (sing) Throw(SingularException(*this));
+   int i, j, ii = nrows_val;       // ii initialised : B might be all zeros
+
+
+   // scan for first non-zero in B
+   for (i = 0; i < nrows_val; i++)
+   {
+      int ip = indx[i]; Real temp = B[ip]; B[ip] = B[i]; B[i] = temp;
+      if (temp != 0.0) { ii = i; break; }
+   }
+
+   Real* bi; Real* ai;
+   i = ii + 1;
+
+   if (i < nrows_val)
+   {
+      bi = B + ii; ai = store + ii + i * nrows_val;
+      for (;;)
+      {
+         int ip = indx[i]; Real sum = B[ip]; B[ip] = B[i];
+         Real* aij = ai; Real* bj = bi; j = i - ii;
+         while (j--) sum -= *aij++ * *bj++;
+         B[i] = sum;
+         if (++i == nrows_val) break;
+         ai += nrows_val;
+      }
+   }
+
+   ai = store + nrows_val * nrows_val;
+
+   for (i = nrows_val - 1; i >= mini; i--)
+   {
+      Real* bj = B+i; ai -= nrows_val; Real* ajx = ai+i;
+      Real sum = *bj; Real diag = *ajx;
+      j = nrows_val - i; while(--j) sum -= *(++ajx) * *(++bj);
+      B[i] = sum / diag;
+   }
+}
+
+/****************************** scalar functions ****************************/
+
+inline Real square(Real x) { return x*x; }
+
+Real GeneralMatrix::sum_square() const
+{
+   REPORT
+   Real sum = 0.0; int i = storage; Real* s = store;
+   while (i--) sum += square(*s++);
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real GeneralMatrix::sum_absolute_value() const
+{
+   REPORT
+   Real sum = 0.0; int i = storage; Real* s = store;
+   while (i--) sum += fabs(*s++);
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real GeneralMatrix::sum() const
+{
+   REPORT
+   Real sm = 0.0; int i = storage; Real* s = store;
+   while (i--) sm += *s++;
+   ((GeneralMatrix&)*this).tDelete(); return sm;
+}
+
+// maxima and minima
+
+// There are three sets of routines
+// maximum_absolute_value, minimum_absolute_value, maximum, minimum
+// ... these find just the maxima and minima
+// maximum_absolute_value1, minimum_absolute_value1, maximum1, minimum1
+// ... these find the maxima and minima and their locations in a
+//     one dimensional object
+// maximum_absolute_value2, minimum_absolute_value2, maximum2, minimum2
+// ... these find the maxima and minima and their locations in a
+//     two dimensional object
+
+// If the matrix has no values throw an exception
+
+// If we do not want the location find the maximum or minimum on the
+// array stored by GeneralMatrix
+// This won't work for BandMatrices. We call ClearCorner for
+// maximum_absolute_value but for the others use the absolute_minimum_value2
+// version and discard the location.
+
+// For one dimensional objects, when we want the location of the
+// maximum or minimum, work with the array stored by GeneralMatrix
+
+// For two dimensional objects where we want the location of the maximum or
+// minimum proceed as follows:
+
+// For rectangular matrices use the array stored by GeneralMatrix and
+// deduce the location from the location in the GeneralMatrix
+
+// For other two dimensional matrices use the Matrix Row routine to find the
+// maximum or minimum for each row.
+
+static void NullMatrixError(const GeneralMatrix* gm)
+{
+   ((GeneralMatrix&)*gm).tDelete();
+   Throw(ProgramException("Maximum or minimum of null matrix"));
+}
+
+Real GeneralMatrix::maximum_absolute_value() const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real maxval = 0.0; int l = storage; Real* s = store;
+   while (l--) { Real a = fabs(*s++); if (maxval < a) maxval = a; }
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::maximum_absolute_value1(int& i) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real maxval = 0.0; int l = storage; Real* s = store; int li = storage;
+   while (l--)
+      { Real a = fabs(*s++); if (maxval <= a) { maxval = a; li = l; }  }
+   i = storage - li;
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::minimum_absolute_value() const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real minval = fabs(*s++);
+   while (l--) { Real a = fabs(*s++); if (minval > a) minval = a; }
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::minimum_absolute_value1(int& i) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real minval = fabs(*s++); int li = l;
+   while (l--)
+      { Real a = fabs(*s++); if (minval >= a) { minval = a; li = l; }  }
+   i = storage - li;
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::maximum() const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real maxval = *s++;
+   while (l--) { Real a = *s++; if (maxval < a) maxval = a; }
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::maximum1(int& i) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real maxval = *s++; int li = l;
+   while (l--) { Real a = *s++; if (maxval <= a) { maxval = a; li = l; } }
+   i = storage - li;
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::minimum() const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real minval = *s++;
+   while (l--) { Real a = *s++; if (minval > a) minval = a; }
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::minimum1(int& i) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   int l = storage - 1; Real* s = store; Real minval = *s++; int li = l;
+   while (l--) { Real a = *s++; if (minval >= a) { minval = a; li = l; } }
+   i = storage - li;
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::maximum_absolute_value2(int& i, int& j) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real maxval = 0.0; int nr = Nrows();
+   MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
+   for (int r = 1; r <= nr; r++)
+   {
+      int c; maxval = mr.MaximumAbsoluteValue1(maxval, c);
+      if (c > 0) { i = r; j = c; }
+      mr.Next();
+   }
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::minimum_absolute_value2(int& i, int& j) const
+{
+   REPORT
+   if (storage == 0)  NullMatrixError(this);
+   Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows();
+   MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
+   for (int r = 1; r <= nr; r++)
+   {
+      int c; minval = mr.MinimumAbsoluteValue1(minval, c);
+      if (c > 0) { i = r; j = c; }
+      mr.Next();
+   }
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real GeneralMatrix::maximum2(int& i, int& j) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real maxval = -FloatingPointPrecision::Maximum(); int nr = Nrows();
+   MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
+   for (int r = 1; r <= nr; r++)
+   {
+      int c; maxval = mr.Maximum1(maxval, c);
+      if (c > 0) { i = r; j = c; }
+      mr.Next();
+   }
+   ((GeneralMatrix&)*this).tDelete(); return maxval;
+}
+
+Real GeneralMatrix::minimum2(int& i, int& j) const
+{
+   REPORT
+   if (storage == 0) NullMatrixError(this);
+   Real minval = FloatingPointPrecision::Maximum(); int nr = Nrows();
+   MatrixRow mr((GeneralMatrix*)this, LoadOnEntry+DirectPart);
+   for (int r = 1; r <= nr; r++)
+   {
+      int c; minval = mr.Minimum1(minval, c);
+      if (c > 0) { i = r; j = c; }
+      mr.Next();
+   }
+   ((GeneralMatrix&)*this).tDelete(); return minval;
+}
+
+Real Matrix::maximum_absolute_value2(int& i, int& j) const
+{
+   REPORT
+   int k; Real m = GeneralMatrix::maximum_absolute_value1(k); k--;
+   i = k / Ncols(); j = k - i * Ncols(); i++; j++;
+   return m;
+}
+
+Real Matrix::minimum_absolute_value2(int& i, int& j) const
+{
+   REPORT
+   int k; Real m = GeneralMatrix::minimum_absolute_value1(k); k--;
+   i = k / Ncols(); j = k - i * Ncols(); i++; j++;
+   return m;
+}
+
+Real Matrix::maximum2(int& i, int& j) const
+{
+   REPORT
+   int k; Real m = GeneralMatrix::maximum1(k); k--;
+   i = k / Ncols(); j = k - i * Ncols(); i++; j++;
+   return m;
+}
+
+Real Matrix::minimum2(int& i, int& j) const
+{
+   REPORT
+   int k; Real m = GeneralMatrix::minimum1(k); k--;
+   i = k / Ncols(); j = k - i * Ncols(); i++; j++;
+   return m;
+}
+
+Real SymmetricMatrix::sum_square() const
+{
+   REPORT
+   Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows_val;
+   for (int i = 0; i<nr; i++)
+   {
+      int j = i;
+      while (j--) sum2 += square(*s++);
+      sum1 += square(*s++);
+   }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real SymmetricMatrix::sum_absolute_value() const
+{
+   REPORT
+   Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows_val;
+   for (int i = 0; i<nr; i++)
+   {
+      int j = i;
+      while (j--) sum2 += fabs(*s++);
+      sum1 += fabs(*s++);
+   }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real IdentityMatrix::sum_absolute_value() const
+   { REPORT  return fabs(trace()); }    // no need to do tDelete?
+
+Real SymmetricMatrix::sum() const
+{
+   REPORT
+   Real sum1 = 0.0; Real sum2 = 0.0; Real* s = store; int nr = nrows_val;
+   for (int i = 0; i<nr; i++)
+   {
+      int j = i;
+      while (j--) sum2 += *s++;
+      sum1 += *s++;
+   }
+   ((GeneralMatrix&)*this).tDelete(); return sum1 + 2.0 * sum2;
+}
+
+Real IdentityMatrix::sum_square() const
+{
+   Real sum = *store * *store * nrows_val;
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+
+Real BaseMatrix::sum_square() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->sum_square(); return s;
+}
+
+Real BaseMatrix::norm_Frobenius() const
+   { REPORT  return sqrt(sum_square()); }
+
+Real BaseMatrix::sum_absolute_value() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->sum_absolute_value(); return s;
+}
+
+Real BaseMatrix::sum() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->sum(); return s;
+}
+
+Real BaseMatrix::maximum_absolute_value() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->maximum_absolute_value(); return s;
+}
+
+Real BaseMatrix::maximum_absolute_value1(int& i) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->maximum_absolute_value1(i); return s;
+}
+
+Real BaseMatrix::maximum_absolute_value2(int& i, int& j) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->maximum_absolute_value2(i, j); return s;
+}
+
+Real BaseMatrix::minimum_absolute_value() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->minimum_absolute_value(); return s;
+}
+
+Real BaseMatrix::minimum_absolute_value1(int& i) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->minimum_absolute_value1(i); return s;
+}
+
+Real BaseMatrix::minimum_absolute_value2(int& i, int& j) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->minimum_absolute_value2(i, j); return s;
+}
+
+Real BaseMatrix::maximum() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->maximum(); return s;
+}
+
+Real BaseMatrix::maximum1(int& i) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->maximum1(i); return s;
+}
+
+Real BaseMatrix::maximum2(int& i, int& j) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->maximum2(i, j); return s;
+}
+
+Real BaseMatrix::minimum() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->minimum(); return s;
+}
+
+Real BaseMatrix::minimum1(int& i) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->minimum1(i); return s;
+}
+
+Real BaseMatrix::minimum2(int& i, int& j) const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   Real s = gm->minimum2(i, j); return s;
+}
+
+Real dotproduct(const Matrix& A, const Matrix& B)
+{
+   REPORT
+   int n = A.storage;
+   if (n != B.storage)
+   {
+      Tracer tr("dotproduct");
+      Throw(IncompatibleDimensionsException(A,B));
+   }
+   Real sum = 0.0; Real* a = A.store; Real* b = B.store;
+   while (n--) sum += *a++ * *b++;
+   return sum;
+}
+
+Real Matrix::trace() const
+{
+   REPORT
+   Tracer tr("trace");
+   int i = nrows_val; int d = i+1;
+   if (i != ncols_val) Throw(NotSquareException(*this));
+   Real sum = 0.0; Real* s = store;
+//   while (i--) { sum += *s; s += d; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += d; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real DiagonalMatrix::trace() const
+{
+   REPORT
+   int i = nrows_val; Real sum = 0.0; Real* s = store;
+   while (i--) sum += *s++;
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real SymmetricMatrix::trace() const
+{
+   REPORT
+   int i = nrows_val; Real sum = 0.0; Real* s = store; int j = 2;
+   // while (i--) { sum += *s; s += j++; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real LowerTriangularMatrix::trace() const
+{
+   REPORT
+   int i = nrows_val; Real sum = 0.0; Real* s = store; int j = 2;
+   // while (i--) { sum += *s; s += j++; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += j++; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real UpperTriangularMatrix::trace() const
+{
+   REPORT
+   int i = nrows_val; Real sum = 0.0; Real* s = store;
+   while (i) { sum += *s; s += i--; }             // won t cause a problem
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real BandMatrix::trace() const
+{
+   REPORT
+   int i = nrows_val; int w = lower_val+upper_val+1;
+   Real sum = 0.0; Real* s = store+lower_val;
+   // while (i--) { sum += *s; s += w; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real SymmetricBandMatrix::trace() const
+{
+   REPORT
+   int i = nrows_val; int w = lower_val+1;
+   Real sum = 0.0; Real* s = store+lower_val;
+   // while (i--) { sum += *s; s += w; }
+   if (i) for (;;) { sum += *s; if (!(--i)) break; s += w; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+Real IdentityMatrix::trace() const
+{
+   Real sum = *store * nrows_val;
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+
+Real BaseMatrix::trace() const
+{
+   REPORT
+   MatrixType Diag = MatrixType::Dg; Diag.SetDataLossOK();
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate(Diag);
+   Real sum = gm->trace(); return sum;
+}
+
+void LogAndSign::operator*=(Real x)
+{
+   if (x > 0.0) { log_val += log(x); }
+   else if (x < 0.0) { log_val += log(-x); sign_val = -sign_val; }
+   else sign_val = 0;
+}
+
+void LogAndSign::pow_eq(int k)
+{
+   if (sign_val)
+   {
+      log_val *= k;
+      if ( (k & 1) == 0 ) sign_val = 1;
+   }
+}
+
+Real LogAndSign::value() const
+{
+   Tracer et("LogAndSign::value");
+   if (log_val >= FloatingPointPrecision::LnMaximum())
+      Throw(OverflowException("Overflow in exponential"));
+   return sign_val * exp(log_val);
+}
+
+LogAndSign::LogAndSign(Real f)
+{
+   if (f == 0.0) { log_val = 0.0; sign_val = 0; return; }
+   else if (f < 0.0) { sign_val = -1; f = -f; }
+   else sign_val = 1;
+   log_val = log(f);
+}
+
+LogAndSign DiagonalMatrix::log_determinant() const
+{
+   REPORT
+   int i = nrows_val; LogAndSign sum; Real* s = store;
+   while (i--) sum *= *s++;
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign LowerTriangularMatrix::log_determinant() const
+{
+   REPORT
+   int i = nrows_val; LogAndSign sum; Real* s = store; int j = 2;
+   // while (i--) { sum *= *s; s += j++; }
+   if (i) for(;;) { sum *= *s; if (!(--i)) break; s += j++; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign UpperTriangularMatrix::log_determinant() const
+{
+   REPORT
+   int i = nrows_val; LogAndSign sum; Real* s = store;
+   while (i) { sum *= *s; s += i--; }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign IdentityMatrix::log_determinant() const
+{
+   REPORT
+   int i = nrows_val; LogAndSign sum;
+   if (i > 0) { sum = *store; sum.PowEq(i); }
+   ((GeneralMatrix&)*this).tDelete(); return sum;
+}
+
+LogAndSign BaseMatrix::log_determinant() const
+{
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   LogAndSign sum = gm->log_determinant(); return sum;
+}
+
+LogAndSign GeneralMatrix::log_determinant() const
+{
+   REPORT
+   Tracer tr("log_determinant");
+   if (nrows_val != ncols_val) Throw(NotSquareException(*this));
+   CroutMatrix C(*this); return C.log_determinant();
+}
+
+LogAndSign CroutMatrix::log_determinant() const
+{
+   REPORT
+   if (sing) return 0.0;
+   int i = nrows_val; int dd = i+1; LogAndSign sum; Real* s = store;
+   if (i) for(;;)
+   {
+      sum *= *s;
+      if (!(--i)) break;
+      s += dd;
+   }
+   if (!d) sum.ChangeSign(); return sum;
+
+}
+
+Real BaseMatrix::determinant() const
+{
+   REPORT
+   Tracer tr("determinant");
+   REPORT GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   LogAndSign ld = gm->log_determinant();
+   return ld.Value();
+}
+
+LinearEquationSolver::LinearEquationSolver(const BaseMatrix& bm)
+{
+   gm = ( ((BaseMatrix&)bm).Evaluate() )->MakeSolver();
+   if (gm==&bm) { REPORT  gm = gm->Image(); }
+   // want a copy if  *gm is actually bm
+   else { REPORT  gm->Protect(); }
+}
+
+ReturnMatrix BaseMatrix::sum_square_rows() const
+{
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   int nr = gm->nrows();
+   ColumnVector ssq(nr);
+   if (gm->size() == 0) { REPORT ssq = 0.0; }
+   else
+   {
+      MatrixRow mr(gm, LoadOnEntry);
+      for (int i = 1; i <= nr; ++i)
+      {
+         Real sum = 0.0;
+         int s = mr.Storage();
+         Real* in = mr.Data();
+         while (s--) sum += square(*in++);
+         ssq(i) = sum;   
+         mr.Next();
+      }
+   }
+   gm->tDelete();
+   ssq.release(); return ssq.for_return();
+}
+
+ReturnMatrix BaseMatrix::sum_square_columns() const
+{
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   int nr = gm->nrows(); int nc = gm->ncols();
+   RowVector ssq(nc); ssq = 0.0;
+   if (gm->size() != 0)
+   {
+      MatrixRow mr(gm, LoadOnEntry);
+      for (int i = 1; i <= nr; ++i)
+      {
+         int s = mr.Storage();
+         Real* in = mr.Data(); Real* out = ssq.data() + mr.Skip();
+         while (s--) *out++ += square(*in++);
+         mr.Next();
+      }
+   }
+   gm->tDelete();
+   ssq.release(); return ssq.for_return();
+}
+
+ReturnMatrix BaseMatrix::sum_rows() const
+{
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   int nr = gm->nrows();
+   ColumnVector sum_vec(nr);
+   if (gm->size() == 0) { REPORT sum_vec = 0.0; }
+   else
+   {
+      MatrixRow mr(gm, LoadOnEntry);
+      for (int i = 1; i <= nr; ++i)
+      {
+         Real sum = 0.0;
+         int s = mr.Storage();
+         Real* in = mr.Data();
+         while (s--) sum += *in++;
+         sum_vec(i) = sum;   
+         mr.Next();
+      }
+   }
+   gm->tDelete();
+   sum_vec.release(); return sum_vec.for_return();
+}
+
+ReturnMatrix BaseMatrix::sum_columns() const
+{
+   REPORT
+   GeneralMatrix* gm = ((BaseMatrix&)*this).Evaluate();
+   int nr = gm->nrows(); int nc = gm->ncols();
+   RowVector sum_vec(nc); sum_vec = 0.0;
+   if (gm->size() != 0)
+   {
+      MatrixRow mr(gm, LoadOnEntry);
+      for (int i = 1; i <= nr; ++i)
+      {
+         int s = mr.Storage();
+         Real* in = mr.Data(); Real* out = sum_vec.data() + mr.Skip();
+         while (s--) *out++ += *in++;
+         mr.Next();
+      }
+   }
+   gm->tDelete();
+   sum_vec.release(); return sum_vec.for_return();
+}
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+///}
Index: trunk/BNC/newmat/newmat9.cpp
===================================================================
--- trunk/BNC/newmat/newmat9.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmat9.cpp	(revision 2013)
@@ -0,0 +1,81 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmat9.cpp
+/// Output.
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+
+#define WANT_FSTREAM
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatio.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,9); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+// for G++ 3.01
+#ifndef ios_format_flags
+#define ios_format_flags long
+#endif
+
+ostream& operator<<(ostream& s, const BaseMatrix& X)
+{
+   GeneralMatrix* gm = ((BaseMatrix&)X).Evaluate(); operator<<(s, *gm);
+   gm->tDelete(); return s;
+}
+
+
+ostream& operator<<(ostream& s, const GeneralMatrix& X)
+{
+   MatrixRow mr((GeneralMatrix*)&X, LoadOnEntry);
+   int w = s.width();  int nr = X.Nrows();  ios_format_flags f = s.flags();
+   s.setf(ios::fixed, ios::floatfield);
+   for (int i=1; i<=nr; i++)
+   {
+      int skip = mr.skip;  int storage = mr.storage;
+      Real* store = mr.data;  skip *= w+1;
+      while (skip--) s << " ";
+      while (storage--) { s.width(w); s << *store++ << " "; }
+//      while (storage--) s << setw(w) << *store++ << " ";
+      mr.Next();  s << "\n";
+   }
+   s << flush;  s.flags(f); return s;
+}
+
+// include this stuff if you are using an old version of G++
+// with an incomplete io library
+
+/*
+
+ostream& operator<<(ostream& os, Omanip_precision i)
+   { os.precision(i.x); return os; }
+
+Omanip_precision setprecision(int i) { return Omanip_precision(i); }
+
+ostream& operator<<(ostream& os, Omanip_width i)
+   { os.width(i.x); return os; }
+
+Omanip_width setw(int i) { return Omanip_width(i); }
+
+*/
+
+#ifdef use_namespace
+}
+#endif
+
+
+///@}
Index: trunk/BNC/newmat/newmatap.h
===================================================================
--- trunk/BNC/newmat/newmatap.h	(revision 2013)
+++ trunk/BNC/newmat/newmatap.h	(revision 2013)
@@ -0,0 +1,250 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmatap.h
+/// Definition file for advanced matrix functions.
+
+// Copyright (C) 1991,2,3,4,8: R B Davies
+
+#ifndef NEWMATAP_LIB
+#define NEWMATAP_LIB 0
+
+#include "newmat.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+// ************************** applications *****************************/
+
+
+void QRZT(Matrix&, LowerTriangularMatrix&);
+
+void QRZT(const Matrix&, Matrix&, Matrix&);
+
+void QRZ(Matrix&, UpperTriangularMatrix&);
+
+void QRZ(const Matrix&, Matrix&, Matrix&);
+
+inline void HHDecompose(Matrix& X, LowerTriangularMatrix& L)
+{ QRZT(X,L); }
+
+inline void HHDecompose(const Matrix& X, Matrix& Y, Matrix& M)
+{ QRZT(X, Y, M); }
+
+void updateQRZT(Matrix& X, LowerTriangularMatrix& L);
+
+void updateQRZ(Matrix& X, UpperTriangularMatrix& U);
+
+inline void UpdateQRZT(Matrix& X, LowerTriangularMatrix& L)
+   { updateQRZT(X, L); }
+
+inline void UpdateQRZ(Matrix& X, UpperTriangularMatrix& U)
+   { updateQRZ(X, U); }
+
+// Matrix A's first n columns are orthonormal
+// so A.Columns(1,n).t() * A.Columns(1,n) is the identity matrix.
+// Fill out the remaining columns of A to make them orthonormal
+// so A.t() * A is the identity matrix 
+void extend_orthonormal(Matrix& A, int n);
+
+
+ReturnMatrix Cholesky(const SymmetricMatrix&);
+
+ReturnMatrix Cholesky(const SymmetricBandMatrix&);
+
+
+// produces the Cholesky decomposition of A + x.t() * x where A = chol.t() * chol
+// and x is a RowVector
+void update_Cholesky(UpperTriangularMatrix& chol, RowVector x);
+inline void UpdateCholesky(UpperTriangularMatrix& chol, const RowVector& x)
+   { update_Cholesky(chol, x); }
+
+// produces the Cholesky decomposition of A - x.t() * x where A = chol.t() * chol
+// and x is a RowVector
+void downdate_Cholesky(UpperTriangularMatrix &chol, RowVector x);
+inline void DowndateCholesky(UpperTriangularMatrix &chol, const RowVector& x)
+   { downdate_Cholesky(chol, x); }
+
+// a RIGHT circular shift of the rows and columns from
+// 1,...,k-1,k,k+1,...l,l+1,...,p to
+// 1,...,k-1,l,k,k+1,...l-1,l+1,...p
+void right_circular_update_Cholesky(UpperTriangularMatrix &chol, int k, int l);
+inline void RightCircularUpdateCholesky(UpperTriangularMatrix &chol,
+  int k, int l) { right_circular_update_Cholesky(chol, k, l); }
+
+// a LEFT circular shift of the rows and columns from
+// 1,...,k-1,k,k+1,...l,l+1,...,p to
+// 1,...,k-1,k+1,...l,k,l+1,...,p to
+void left_circular_update_Cholesky(UpperTriangularMatrix &chol, int k, int l); 
+inline void LeftCircularUpdateCholesky(UpperTriangularMatrix &chol,
+   int k, int l) { left_circular_update_Cholesky(chol, k, l); } 
+
+
+void SVD(const Matrix&, DiagonalMatrix&, Matrix&, Matrix&,
+    bool=true, bool=true);
+
+void SVD(const Matrix&, DiagonalMatrix&);
+
+inline void SVD(const Matrix& A, DiagonalMatrix& D, Matrix& U,
+   bool withU = true) { SVD(A, D, U, U, withU, false); }
+
+void SortSV(DiagonalMatrix& D, Matrix& U, bool ascending = false);
+
+void SortSV(DiagonalMatrix& D, Matrix& U, Matrix& V, bool ascending = false);
+
+void Jacobi(const SymmetricMatrix&, DiagonalMatrix&);
+
+void Jacobi(const SymmetricMatrix&, DiagonalMatrix&, SymmetricMatrix&);
+
+void Jacobi(const SymmetricMatrix&, DiagonalMatrix&, Matrix&);
+
+void Jacobi(const SymmetricMatrix&, DiagonalMatrix&, SymmetricMatrix&,
+   Matrix&, bool=true);
+
+void eigenvalues(const SymmetricMatrix&, DiagonalMatrix&);
+
+void eigenvalues(const SymmetricMatrix&, DiagonalMatrix&, SymmetricMatrix&);
+
+void eigenvalues(const SymmetricMatrix&, DiagonalMatrix&, Matrix&);
+
+inline void EigenValues(const SymmetricMatrix& A, DiagonalMatrix& D)
+   { eigenvalues(A, D); }
+
+inline void EigenValues(const SymmetricMatrix& A, DiagonalMatrix& D,
+   SymmetricMatrix& S) { eigenvalues(A, D, S); }
+
+inline void EigenValues(const SymmetricMatrix& A, DiagonalMatrix& D, Matrix& V)
+   { eigenvalues(A, D, V); }
+
+class SymmetricEigenAnalysis
+// not implemented yet
+{
+public:
+   SymmetricEigenAnalysis(const SymmetricMatrix&);
+private:
+   DiagonalMatrix diag;
+   DiagonalMatrix offdiag;
+   SymmetricMatrix backtransform;
+   FREE_CHECK(SymmetricEigenAnalysis)
+};
+
+void sort_ascending(GeneralMatrix&);
+
+void sort_descending(GeneralMatrix&);
+
+inline void SortAscending(GeneralMatrix& gm) { sort_ascending(gm); }
+
+inline void SortDescending(GeneralMatrix& gm) { sort_descending(gm); }
+
+/// Decide which fft method to use and carry out new fft function
+class FFT_Controller
+{
+public:
+   static bool OnlyOldFFT;
+   static bool ar_1d_ft (int PTS, Real* X, Real *Y);
+   static bool CanFactor(int PTS);
+};
+
+void FFT(const ColumnVector&, const ColumnVector&,
+   ColumnVector&, ColumnVector&);
+
+void FFTI(const ColumnVector&, const ColumnVector&,
+   ColumnVector&, ColumnVector&);
+
+void RealFFT(const ColumnVector&, ColumnVector&, ColumnVector&);
+
+void RealFFTI(const ColumnVector&, const ColumnVector&, ColumnVector&);
+
+void DCT_II(const ColumnVector&, ColumnVector&);
+
+void DCT_II_inverse(const ColumnVector&, ColumnVector&);
+
+void DST_II(const ColumnVector&, ColumnVector&);
+
+void DST_II_inverse(const ColumnVector&, ColumnVector&);
+
+void DCT(const ColumnVector&, ColumnVector&);
+
+void DCT_inverse(const ColumnVector&, ColumnVector&);
+
+void DST(const ColumnVector&, ColumnVector&);
+
+void DST_inverse(const ColumnVector&, ColumnVector&);
+
+void FFT2(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y);
+
+void FFT2I(const Matrix& U, const Matrix& V, Matrix& X, Matrix& Y);
+
+
+// This class is used by the new FFT program
+
+// Suppose an integer is expressed as a sequence of digits with each
+// digit having a different radix.
+// This class supposes we are counting with this multi-radix number
+// but also keeps track of the number with the digits (and radices)
+// reversed.
+// The integer starts at zero
+// operator++() increases it by 1
+// Counter gives the number of increments
+// Reverse() gives the value with the digits in reverse order
+// Swap is true if reverse is less than counter
+// Finish is true when we have done a complete cycle and are back at zero
+
+class MultiRadixCounter
+{
+   const SimpleIntArray& Radix;
+                              // radix of each digit
+                              // n-1 highest order, 0 lowest order
+   SimpleIntArray& Value;     // value of each digit
+   const int n;               // number of digits
+   int reverse;               // value when order of digits is reversed
+   int product;               // product of radices
+   int counter;               // counter
+   bool finish;               // true when we have gone over whole range
+public:
+   MultiRadixCounter(int nx, const SimpleIntArray& rx,
+      SimpleIntArray& vx);
+   void operator++();         // increment the multi-radix counter
+   bool Swap() const { return reverse < counter; }
+   bool Finish() const { return finish; }
+   int Reverse() const { return reverse; }
+   int Counter() const { return counter; }
+};
+
+// multiplication by Helmert matrix
+ReturnMatrix Helmert(int n, bool full=false);
+ReturnMatrix Helmert(const ColumnVector& X, bool full=false);
+ReturnMatrix Helmert(int n, int j, bool full=false);
+ReturnMatrix Helmert_transpose(const ColumnVector& Y, bool full=false);
+Real Helmert_transpose(const ColumnVector& Y, int j, bool full=false);
+ReturnMatrix Helmert(const Matrix& X, bool full=false);
+ReturnMatrix Helmert_transpose(const Matrix& Y, bool full=false);
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+#endif
+
+// body file: cholesky.cpp
+// body file: evalue.cpp
+// body file: fft.cpp
+// body file: hholder.cpp
+// body file: jacobi.cpp
+// body file: newfft.cpp
+// body file: sort.cpp
+// body file: svd.cpp
+// body file: nm_misc.cpp
+
+
+
+///@}
+
+
Index: trunk/BNC/newmat/newmatex.cpp
===================================================================
--- trunk/BNC/newmat/newmatex.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmatex.cpp	(revision 2013)
@@ -0,0 +1,325 @@
+/// \file newmatex.cpp
+/// \brief Exceptions thrown by matrix library.
+
+// Copyright (C) 1992,3,4,7: R B Davies
+
+#define WANT_STREAM                  // include.h will get stream fns
+
+#include "include.h"                 // include standard files
+#include "newmat.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+unsigned long OverflowException::Select;
+unsigned long SingularException::Select;
+unsigned long NPDException::Select;
+unsigned long ConvergenceException::Select;
+unsigned long ProgramException::Select;
+unsigned long IndexException::Select;
+unsigned long VectorException::Select;
+unsigned long NotSquareException::Select;
+unsigned long SubMatrixDimensionException::Select;
+unsigned long IncompatibleDimensionsException::Select;
+unsigned long NotDefinedException::Select;
+unsigned long CannotBuildException::Select;
+unsigned long InternalException::Select;
+
+
+
+static void MatrixDetails(const GeneralMatrix& A)
+// write matrix details to Exception buffer
+{
+   MatrixBandWidth bw = A.bandwidth();
+   int ubw = bw.upper_val; int lbw = bw.lower_val;
+   BaseException::AddMessage("MatrixType = ");
+   BaseException::AddMessage(A.Type().Value());
+   BaseException::AddMessage("  # Rows = "); BaseException::AddInt(A.Nrows());
+   BaseException::AddMessage("; # Cols = "); BaseException::AddInt(A.Ncols());
+   if (lbw >=0)
+   {
+      BaseException::AddMessage("; lower BW = ");
+      BaseException::AddInt(lbw);
+   }
+   if (ubw >=0)
+   {
+      BaseException::AddMessage("; upper BW = ");
+      BaseException::AddInt(ubw);
+   }
+   BaseException::AddMessage("\n");
+}
+
+NPDException::NPDException(const GeneralMatrix& A)
+   : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: matrix not positive definite\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+SingularException::SingularException(const GeneralMatrix& A)
+   : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: matrix is singular\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+ConvergenceException::ConvergenceException(const GeneralMatrix& A)
+   : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: process fails to converge\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+ConvergenceException::ConvergenceException(const char* c) : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   if (c) Tracer::AddTrace();
+}
+
+OverflowException::OverflowException(const char* c) : Runtime_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   if (c) Tracer::AddTrace();
+}
+
+ProgramException::ProgramException(const char* c) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   if (c) Tracer::AddTrace();
+}
+
+ProgramException::ProgramException(const char* c, const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   MatrixDetails(A);
+   if (c) Tracer::AddTrace();
+}
+
+ProgramException::ProgramException(const char* c, const GeneralMatrix& A,
+   const GeneralMatrix& B) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\n\n");
+   MatrixDetails(A); MatrixDetails(B);
+   if (c) Tracer::AddTrace();
+}
+
+ProgramException::ProgramException(const char* c, MatrixType a, MatrixType b)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(c); AddMessage("\nMatrixTypes = ");
+   AddMessage(a.Value()); AddMessage("; ");
+   AddMessage(b.Value()); AddMessage("\n\n");
+   if (c) Tracer::AddTrace();
+}
+
+VectorException::VectorException() : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: cannot convert matrix to vector\n\n");
+   Tracer::AddTrace();
+}
+
+VectorException::VectorException(const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: cannot convert matrix to vector\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+NotSquareException::NotSquareException(const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: matrix is not square\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+NotSquareException::NotSquareException()
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: matrix is not square\n\n");
+   Tracer::AddTrace();
+}
+
+SubMatrixDimensionException::SubMatrixDimensionException()
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: incompatible submatrix dimension\n\n");
+   Tracer::AddTrace();
+}
+
+IncompatibleDimensionsException::IncompatibleDimensionsException()
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: incompatible dimensions\n\n");
+   Tracer::AddTrace();
+}
+
+IncompatibleDimensionsException::IncompatibleDimensionsException
+   (const GeneralMatrix& A, const GeneralMatrix& B)
+      : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: incompatible dimensions\n\n");
+   MatrixDetails(A); MatrixDetails(B);
+   Tracer::AddTrace();
+}
+
+IncompatibleDimensionsException::IncompatibleDimensionsException
+   (const GeneralMatrix& A)
+      : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: incompatible dimensions\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+NotDefinedException::NotDefinedException(const char* op, const char* matrix)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: ");
+   AddMessage(op);
+   AddMessage(" not defined for ");
+   AddMessage(matrix);
+   AddMessage("\n\n");
+   Tracer::AddTrace();
+}
+
+CannotBuildException::CannotBuildException(const char* matrix)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: cannot build matrix type ");
+   AddMessage(matrix); AddMessage("\n\n");
+   Tracer::AddTrace();
+}
+
+IndexException::IndexException(int i, const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: index error: requested index = ");
+   AddInt(i); AddMessage("\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+IndexException::IndexException(int i, int j, const GeneralMatrix& A)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: index error: requested indices = ");
+   AddInt(i); AddMessage(", "); AddInt(j);
+   AddMessage("\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+
+IndexException::IndexException(int i, const GeneralMatrix& A, bool)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("detected by Newmat: element error: requested index (wrt 0) = ");
+   AddInt(i);
+   AddMessage("\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+IndexException::IndexException(int i, int j, const GeneralMatrix& A, bool)
+   : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage(
+      "detected by Newmat: element error: requested indices (wrt 0) = ");
+   AddInt(i); AddMessage(", "); AddInt(j);
+   AddMessage("\n\n");
+   MatrixDetails(A);
+   Tracer::AddTrace();
+}
+
+InternalException::InternalException(const char* c) : Logic_error()
+{
+   Select = BaseException::Select;
+   AddMessage("internal error detected by Newmat: please inform author\n");
+   AddMessage(c); AddMessage("\n\n");
+   Tracer::AddTrace();
+}
+
+
+
+
+/************************* ExeCounter functions *****************************/
+
+#ifdef DO_REPORT
+
+int ExeCounter::nreports;                      // will be set to zero
+
+ExeCounter::ExeCounter(int xl, int xf) : line(xl), fileid(xf), nexe(0) {}
+
+ExeCounter::~ExeCounter()
+{
+   nreports++;
+   cout << "REPORT  " << setw(6) << nreports << "  "
+      << setw(6) << fileid << "  " << setw(6) << line
+      << "  " << setw(6) << nexe << "\n";
+}
+
+#endif
+
+/**************************** error handler *******************************/
+
+void MatrixErrorNoSpace(const void* v) { if (!v) Throw(Bad_alloc()); }
+// throw exception if v is null
+
+
+
+
+/************************* miscellanous errors ***************************/
+
+
+void CroutMatrix::GetRow(MatrixRowCol&)
+   { Throw(NotDefinedException("GetRow","Crout")); }
+void CroutMatrix::GetCol(MatrixRowCol&)
+   { Throw(NotDefinedException("GetCol","Crout")); }
+void BandLUMatrix::GetRow(MatrixRowCol&)
+   { Throw(NotDefinedException("GetRow","BandLUMatrix")); }
+void BandLUMatrix::GetCol(MatrixRowCol&)
+   { Throw(NotDefinedException("GetCol","BandLUMatrix")); }
+void BaseMatrix::IEQND() const
+   { Throw(NotDefinedException("inequalities", "matrices")); }
+
+
+#ifdef use_namespace
+}
+#endif
+
Index: trunk/BNC/newmat/newmatio.h
===================================================================
--- trunk/BNC/newmat/newmatio.h	(revision 2013)
+++ trunk/BNC/newmat/newmatio.h	(revision 2013)
@@ -0,0 +1,65 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmatio.h
+/// Definition file for matrix package output.
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#ifndef NEWMATIO_LIB
+#define NEWMATIO_LIB 0
+
+#ifndef WANT_STREAM
+#define WANT_STREAM
+#endif
+
+#include "newmat.h"
+
+#ifdef USE_STD_NAMESPACE
+using namespace std;
+#endif
+
+// **************************** input/output *****************************/
+
+ostream& operator<<(ostream&, const BaseMatrix&);
+
+ostream& operator<<(ostream&, const GeneralMatrix&);
+
+
+/*  Use in some old versions of G++ without complete iomanipulators
+
+class Omanip_precision
+{
+   int x;
+public:
+   Omanip_precision(int i) : x(i) {}
+   friend ostream& operator<<(ostream& os, Omanip_precision i);
+};
+
+
+Omanip_precision setprecision(int i);
+
+class Omanip_width
+{
+   int x;
+public:
+   Omanip_width(int i) : x(i) {}
+   friend ostream& operator<<(ostream& os, Omanip_width i);
+};
+
+Omanip_width setw(int i);
+
+*/
+
+#ifdef use_namespace
+}
+#endif
+
+
+
+#endif
+
+// body file: newmat9.cpp
+
+
+///@}
Index: trunk/BNC/newmat/newmatrc.h
===================================================================
--- trunk/BNC/newmat/newmatrc.h	(revision 2013)
+++ trunk/BNC/newmat/newmatrc.h	(revision 2013)
@@ -0,0 +1,186 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmatrc.h
+/// Header file for row/column classes
+
+// Copyright (C) 1991,2,3,4,7: R B Davies
+
+#ifndef NEWMATRC_LIB
+#define NEWMATRC_LIB 0
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#include "controlw.h"
+
+
+/************** classes MatrixRowCol, MatrixRow, MatrixCol *****************/
+
+// Used for accessing the rows and columns of matrices
+// All matrix classes must provide routines for calculating matrix rows and
+// columns. Assume rows can be found very efficiently.
+
+enum LSF { LoadOnEntry=1,StoreOnExit=2,DirectPart=4,StoreHere=8,HaveStore=16 };
+
+
+/// Option for accessing row or column.
+/// \internal
+class LoadAndStoreFlag : public ControlWord
+{
+public:
+   LoadAndStoreFlag() {}
+   LoadAndStoreFlag(int i) : ControlWord(i) {}
+   LoadAndStoreFlag(LSF lsf) : ControlWord(lsf) {}
+   LoadAndStoreFlag(const ControlWord& cwx) : ControlWord(cwx) {}
+};
+
+
+/// Access a row or column of a matrix.
+/// \internal
+class MatrixRowCol
+{
+public:                                        // these are public to avoid
+                                               // numerous friend statements
+   int length;                                 // row or column length
+   int skip;                                   // initial number of zeros
+   int storage;                                // number of stored elements
+   int rowcol;                                 // row or column number
+   GeneralMatrix* gm;                          // pointer to parent matrix
+   Real* data;                                 // pointer to local storage
+   LoadAndStoreFlag cw;                        // Load? Store? Is a Copy?
+   void IncrMat() { rowcol++; data += storage; }   // used by NextRow
+   void IncrDiag() { rowcol++; skip++; data++; }
+   void IncrId() { rowcol++; skip++; }
+   void IncrUT() { rowcol++; data += storage; storage--; skip++; }
+   void IncrLT() { rowcol++; data += storage; storage++; }
+
+public:
+   void Zero();                                // set elements to zero
+   void Add(const MatrixRowCol&);              // add a row/col
+   void AddScaled(const MatrixRowCol&, Real);  // add a multiple of a row/col
+   void Add(const MatrixRowCol&, const MatrixRowCol&);
+                                               // add two rows/cols
+   void Add(const MatrixRowCol&, Real);        // add a row/col
+   void NegAdd(const MatrixRowCol&, Real);     // Real - a row/col
+   void Sub(const MatrixRowCol&);              // subtract a row/col
+   void Sub(const MatrixRowCol&, const MatrixRowCol&);
+					       // sub a row/col from another
+   void RevSub(const MatrixRowCol&);           // subtract from a row/col
+   void ConCat(const MatrixRowCol&, const MatrixRowCol&);
+                                               // concatenate two row/cols
+   void Multiply(const MatrixRowCol&);         // multiply a row/col
+   void Multiply(const MatrixRowCol&, const MatrixRowCol&);
+                                               // multiply two row/cols
+   void KP(const MatrixRowCol&, const MatrixRowCol&);
+                                               // Kronecker Product two row/cols
+   void Copy(const MatrixRowCol&);             // copy a row/col
+   void CopyCheck(const MatrixRowCol&);        // ... check for data loss
+   void Check(const MatrixRowCol&);            // just check for data loss
+   void Check();                               // check full row/col present
+   void Copy(const double*&);                  // copy from an array
+   void Copy(const float*&);                   // copy from an array
+   void Copy(const int*&);                     // copy from an array
+   void Copy(Real);                            // copy from constant
+   void Add(Real);                             // add a constant
+   void Multiply(Real);                        // multiply by constant
+   Real SumAbsoluteValue();                    // sum of absolute values
+   Real MaximumAbsoluteValue1(Real r, int& i); // maximum of absolute values
+   Real MinimumAbsoluteValue1(Real r, int& i); // minimum of absolute values
+   Real Maximum1(Real r, int& i);              // maximum
+   Real Minimum1(Real r, int& i);              // minimum
+   Real Sum();                                 // sum of values
+   void Inject(const MatrixRowCol&);           // copy stored els of a row/col
+   void Negate(const MatrixRowCol&);           // change sign of a row/col
+   void Multiply(const MatrixRowCol&, Real);   // scale a row/col
+   friend Real DotProd(const MatrixRowCol&, const MatrixRowCol&);
+                                               // sum of pairwise product
+   Real* Data() { return data; }
+   int Skip() { return skip; }                 // number of elements skipped
+   int Storage() { return storage; }           // number of elements stored
+   int Length() { return length; }             // length of row or column
+   void Skip(int i) { skip=i; }
+   void Storage(int i) { storage=i; }
+   void Length(int i) { length=i; }
+   void SubRowCol(MatrixRowCol&, int, int) const;
+					       // get part of a row or column
+   MatrixRowCol() {}                           // to stop warning messages
+   ~MatrixRowCol();
+   FREE_CHECK(MatrixRowCol)
+};
+
+/// Access a row of a matrix.
+/// \internal
+class MatrixRow : public MatrixRowCol
+{
+public:
+   // bodies for these are inline at the end of this .h file
+   MatrixRow(GeneralMatrix*, LoadAndStoreFlag, int=0);
+                                               // extract a row
+   ~MatrixRow();
+   void Next();                                // get next row
+   FREE_CHECK(MatrixRow)
+};
+
+/// Access a column of a matrix.
+/// \internal
+class MatrixCol : public MatrixRowCol
+{
+public:
+   // bodies for these are inline at the end of this .h file
+   MatrixCol(GeneralMatrix*, LoadAndStoreFlag, int=0);
+                                               // extract a col
+   MatrixCol(GeneralMatrix*, Real*, LoadAndStoreFlag, int=0);
+                                               // store/retrieve a col
+   ~MatrixCol();
+   void Next();                                // get next column
+   FREE_CHECK(MatrixCol)
+};
+
+/// Alternative to MatrixCol where the complete column is stored externally.
+/// \internal
+class MatrixColX : public MatrixRowCol
+{
+public:
+   // bodies for these are inline at the end of this .h file
+   MatrixColX(GeneralMatrix*, Real*, LoadAndStoreFlag, int=0);
+                                               // store/retrieve a col
+   ~MatrixColX();
+   void Next();                                // get next row
+   Real* store;                                // pointer to local storage
+                                               //    less skip
+   FREE_CHECK(MatrixColX)
+};
+
+/**************************** inline bodies ****************************/
+
+inline MatrixRow::MatrixRow(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int row)
+{ gm=gmx; cw=cwx; rowcol=row; gm->GetRow(*this); }
+
+inline void MatrixRow::Next() { gm->NextRow(*this); }
+
+inline MatrixCol::MatrixCol(GeneralMatrix* gmx, LoadAndStoreFlag cwx, int col)
+{ gm=gmx; cw=cwx; rowcol=col; gm->GetCol(*this); }
+
+inline MatrixCol::MatrixCol(GeneralMatrix* gmx, Real* r,
+   LoadAndStoreFlag cwx, int col)
+{ gm=gmx; data=r; cw=cwx+StoreHere; rowcol=col; gm->GetCol(*this); }
+
+inline MatrixColX::MatrixColX(GeneralMatrix* gmx, Real* r,
+   LoadAndStoreFlag cwx, int col)
+{ gm=gmx; store=data=r; cw=cwx+StoreHere; rowcol=col; gm->GetCol(*this); }
+
+
+inline void MatrixCol::Next() { gm->NextCol(*this); }
+
+inline void MatrixColX::Next() { gm->NextCol(*this); }
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
+
+
+///@}
Index: trunk/BNC/newmat/newmatrm.cpp
===================================================================
--- trunk/BNC/newmat/newmatrm.cpp	(revision 2013)
+++ trunk/BNC/newmat/newmatrm.cpp	(revision 2013)
@@ -0,0 +1,221 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmatrm.cpp
+/// Rectangular matrix operations
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+
+#include "newmat.h"
+#include "newmatrm.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,12); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+// operations on rectangular matrices
+
+
+void RectMatrixRow::Reset (const Matrix& M, int row, int skip, int length)
+{
+   REPORT
+   RectMatrixRowCol::Reset
+      ( M.Store()+row*M.Ncols()+skip, length, 1, M.Ncols() );
+}
+
+void RectMatrixRow::Reset (const Matrix& M, int row)
+{
+   REPORT
+   RectMatrixRowCol::Reset( M.Store()+row*M.Ncols(), M.Ncols(), 1, M.Ncols() );
+}
+
+void RectMatrixCol::Reset (const Matrix& M, int skip, int col, int length)
+{
+   REPORT
+   RectMatrixRowCol::Reset
+      ( M.Store()+col+skip*M.Ncols(), length, M.Ncols(), 1 );
+}
+
+void RectMatrixCol::Reset (const Matrix& M, int col)
+{
+   REPORT
+   RectMatrixRowCol::Reset( M.Store()+col, M.Nrows(), M.Ncols(), 1 );
+}
+
+
+Real RectMatrixRowCol::SumSquare() const
+{
+   REPORT
+   long_Real sum = 0.0; int i = n; Real* s = store; int d = spacing;
+   // while (i--) { sum += (long_Real)*s * *s; s += d; }
+   if (i) for(;;)
+      { sum += (long_Real)*s * *s; if (!(--i)) break; s += d; }
+   return (Real)sum;
+}
+
+Real RectMatrixRowCol::operator*(const RectMatrixRowCol& rmrc) const
+{
+   REPORT
+   long_Real sum = 0.0; int i = n;
+   Real* s = store; int d = spacing;
+   Real* s1 = rmrc.store; int d1 = rmrc.spacing;
+   if (i!=rmrc.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in *"));
+   }
+   // while (i--) { sum += (long_Real)*s * *s1; s += d; s1 += d1; }
+   if (i) for(;;)
+      { sum += (long_Real)*s * *s1; if (!(--i)) break; s += d; s1 += d1; }
+   return (Real)sum;
+}
+
+void RectMatrixRowCol::AddScaled(const RectMatrixRowCol& rmrc, Real r)
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   Real* s1 = rmrc.store; int d1 = rmrc.spacing;
+   if (i!=rmrc.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in AddScaled"));
+   }
+   // while (i--) { *s += *s1 * r; s += d; s1 += d1; }
+   if (i) for (;;)
+      { *s += *s1 * r; if (!(--i)) break; s += d; s1 += d1; }
+}
+
+void RectMatrixRowCol::Divide(const RectMatrixRowCol& rmrc, Real r)
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   Real* s1 = rmrc.store; int d1 = rmrc.spacing;
+   if (i!=rmrc.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in Divide"));
+   }
+   // while (i--) { *s = *s1 / r; s += d; s1 += d1; }
+   if (i) for (;;) { *s = *s1 / r; if (!(--i)) break; s += d; s1 += d1; }
+}
+
+void RectMatrixRowCol::Divide(Real r)
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   // while (i--) { *s /= r; s += d; }
+   if (i) for (;;) { *s /= r; if (!(--i)) break; s += d; }
+}
+
+void RectMatrixRowCol::Negate()
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   // while (i--) { *s = - *s; s += d; }
+   if (i) for (;;) { *s = - *s; if (!(--i)) break; s += d; }
+}
+
+void RectMatrixRowCol::Zero()
+{
+   REPORT
+   int i = n; Real* s = store; int d = spacing;
+   // while (i--) { *s = 0.0; s += d; }
+   if (i) for (;;) { *s = 0.0; if (!(--i)) break; s += d; }
+}
+
+void ComplexScale(RectMatrixCol& U, RectMatrixCol& V, Real x, Real y)
+{
+   REPORT
+   int n = U.n;
+   if (n != V.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in ComplexScale"));
+   }
+   Real* u = U.store; Real* v = V.store; 
+   int su = U.spacing; int sv = V.spacing;
+   //while (n--)
+   //{
+   //   Real z = *u * x - *v * y;  *v =  *u * y + *v * x;  *u = z;
+   //   u += su;  v += sv;
+   //}
+   if (n) for (;;)
+   {
+      Real z = *u * x - *v * y;  *v =  *u * y + *v * x;  *u = z;
+      if (!(--n)) break;
+      u += su;  v += sv;
+   }
+}
+
+void Rotate(RectMatrixCol& U, RectMatrixCol& V, Real tau, Real s)
+{
+   REPORT
+   //  (U, V) = (U, V) * (c, s)  where  tau = s/(1+c), c^2 + s^2 = 1
+   int n = U.n;
+   if (n != V.n)
+   {
+      Tracer tr("newmatrm");
+      Throw(InternalException("Dimensions differ in Rotate"));
+   }
+   Real* u = U.store; Real* v = V.store;
+   int su = U.spacing; int sv = V.spacing;
+   //while (n--)
+   //{
+   //   Real zu = *u; Real zv = *v;
+   //   *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau);
+   //   u += su;  v += sv;
+   //}
+   if (n) for(;;)
+   {
+      Real zu = *u; Real zv = *v;
+      *u -= s * (zv + zu * tau); *v += s * (zu - zv * tau);
+      if (!(--n)) break;
+      u += su;  v += sv;
+   }
+}
+
+
+// misc procedures for numerical things
+
+Real pythag(Real f, Real g, Real& c, Real& s)
+// return z=sqrt(f*f+g*g), c=f/z, s=g/z
+// set c=1,s=0 if z==0
+// avoid floating point overflow or divide by zero
+{
+   if (f==0 && g==0) { c=1.0; s=0.0; return 0.0; }
+   Real af = f>=0 ? f : -f;
+   Real ag = g>=0 ? g : -g;
+   if (ag<af)
+   {
+      REPORT
+      Real h = g/f; Real sq = sqrt(1.0+h*h);
+      if (f<0) sq = -sq;           // make return value non-negative
+      c = 1.0/sq; s = h/sq; return sq*f;
+   }
+   else
+   {
+      REPORT
+      Real h = f/g; Real sq = sqrt(1.0+h*h);
+      if (g<0) sq = -sq;
+      s = 1.0/sq; c = h/sq; return sq*g;
+   }
+}
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+///@}
Index: trunk/BNC/newmat/newmatrm.h
===================================================================
--- trunk/BNC/newmat/newmatrm.h	(revision 2013)
+++ trunk/BNC/newmat/newmatrm.h	(revision 2013)
@@ -0,0 +1,156 @@
+/// \ingroup newmat
+///@{
+
+/// \file newmatrm.h
+/// Rectangular matrix operations.
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#ifndef NEWMATRM_LIB
+#define NEWMATRM_LIB 0
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+class RectMatrixCol;
+
+/// Access rows and columns of a rectangular matrix.
+/// \internal
+class RectMatrixRowCol
+{
+protected:
+#ifdef use_namespace              // to make namespace work
+public:
+#endif
+   Real* store;                   // pointer to storage
+   int n;                         // number of elements
+   int spacing;                   // space between elements
+   int shift;                     // space between cols or rows
+   RectMatrixRowCol(Real* st, int nx, int sp, int sh)
+      : store(st), n(nx), spacing(sp), shift(sh) {}
+   void Reset(Real* st, int nx, int sp, int sh)
+      { store=st; n=nx; spacing=sp; shift=sh; }
+public:
+   Real operator*(const RectMatrixRowCol&) const;         // dot product
+   void AddScaled(const RectMatrixRowCol&, Real);         // add scaled
+   void Divide(const RectMatrixRowCol&, Real);            // scaling
+   void Divide(Real);                                     // scaling
+   void Negate();                                         // change sign
+   void Zero();                                           // zero row col
+   Real& operator[](int i) { return *(store+i*spacing); } // element
+   Real SumSquare() const;                                // sum of squares
+   Real& First() { return *store; }                       // get first element
+   void DownDiag() { store += (shift+spacing); n--; }
+   void UpDiag() { store -= (shift+spacing); n++; }
+   friend void ComplexScale(RectMatrixCol&, RectMatrixCol&, Real, Real);
+   friend void Rotate(RectMatrixCol&, RectMatrixCol&, Real, Real);
+   FREE_CHECK(RectMatrixRowCol)
+};
+
+/// Access rows of a rectangular matrix.
+/// \internal
+class RectMatrixRow : public RectMatrixRowCol
+{
+public:
+   RectMatrixRow(const Matrix&, int, int, int);
+   RectMatrixRow(const Matrix&, int);
+   void Reset(const Matrix&, int, int, int);
+   void Reset(const Matrix&, int);
+   Real& operator[](int i) { return *(store+i); }
+   void Down() { store += shift; }
+   void Right() { store++; n--; }
+   void Up() { store -= shift; }
+   void Left() { store--; n++; }
+   FREE_CHECK(RectMatrixRow)
+};
+
+/// Access columns of a rectangular matrix.
+/// \internal
+class RectMatrixCol : public RectMatrixRowCol
+{
+public:
+   RectMatrixCol(const Matrix&, int, int, int);
+   RectMatrixCol(const Matrix&, int);
+   void Reset(const Matrix&, int, int, int);
+   void Reset(const Matrix&, int);
+   void Down() { store += spacing; n--; }
+   void Right() { store++; }
+   void Up() { store -= spacing; n++; }
+   void Left() { store--; }
+   friend void ComplexScale(RectMatrixCol&, RectMatrixCol&, Real, Real);
+   friend void Rotate(RectMatrixCol&, RectMatrixCol&, Real, Real);
+   FREE_CHECK(RectMatrixCol)
+};
+
+/// Access diagonal of a rectangular matrix.
+/// \internal
+class RectMatrixDiag : public RectMatrixRowCol
+{
+public:
+   RectMatrixDiag(const DiagonalMatrix& D)
+      : RectMatrixRowCol(D.Store(), D.Nrows(), 1, 1) {}
+   Real& operator[](int i) { return *(store+i); }
+   void DownDiag() { store++; n--; }
+   void UpDiag() { store--; n++; }
+   FREE_CHECK(RectMatrixDiag)
+};
+
+
+
+
+inline RectMatrixRow::RectMatrixRow
+   (const Matrix& M, int row, int skip, int length)
+   : RectMatrixRowCol( M.Store()+row*M.Ncols()+skip, length, 1, M.Ncols() ) {}
+
+inline RectMatrixRow::RectMatrixRow (const Matrix& M, int row)
+   : RectMatrixRowCol( M.Store()+row*M.Ncols(), M.Ncols(), 1, M.Ncols() ) {}
+
+inline RectMatrixCol::RectMatrixCol
+   (const Matrix& M, int skip, int col, int length)
+   : RectMatrixRowCol( M.Store()+col+skip*M.Ncols(), length, M.Ncols(), 1 ) {}
+
+inline RectMatrixCol::RectMatrixCol (const Matrix& M, int col)
+   : RectMatrixRowCol( M.Store()+col, M.Nrows(), M.Ncols(), 1 ) {}
+
+inline Real square(Real x) { return x*x; }
+inline Real sign(Real x, Real y)
+   { return (y>=0) ? x : -x; }                    // assume x >=0
+
+
+// Misc numerical things
+
+Real pythag(Real f, Real g, Real& c, Real& s);
+
+inline void GivensRotation(Real cGivens, Real sGivens, Real& x, Real& y)
+{
+   // allow for possibility &x = &y
+   Real tmp0 = cGivens * x + sGivens * y;
+   Real tmp1 = -sGivens * x + cGivens * y;
+   x = tmp0; y = tmp1;
+}
+   
+inline void GivensRotationR(Real cGivens, Real sGivens, Real& x, Real& y)
+{
+   // also change sign of y
+   // allow for possibility &x = &y
+   Real tmp0 = cGivens * x + sGivens * y;
+   Real tmp1 = sGivens * x - cGivens * y;
+   x = tmp0; y = tmp1;
+}   
+
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+#endif
+
+// body file: newmatrm.cpp
+
+
+///@}
Index: trunk/BNC/newmat/nm_misc.cpp
===================================================================
--- trunk/BNC/newmat/nm_misc.cpp	(revision 2013)
+++ trunk/BNC/newmat/nm_misc.cpp	(revision 2013)
@@ -0,0 +1,147 @@
+/// \ingroup newmat
+///@{
+
+/// \file nm_misc.cpp
+/// Miscellaneous programs.
+
+#define WANT_MATH
+
+#include "include.h"
+
+#include "newmatap.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,21); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+ReturnMatrix Helmert(int n, bool full)
+{
+   REPORT
+   Tracer et("Helmert ");
+   if (n <= 0) Throw(ProgramException("Dimension <= 0 "));
+   Matrix H;
+   
+   if (full) H.resize(n,n); else H.resize(n-1,n);
+   H = 0.0;
+   for (int i = 1; i < n; ++i)
+   {
+      Real f = 1.0 / sqrt((Real)i * (i+1));
+      H.submatrix(i,i,1,i) = -f; H(i,i+1) = f * i;
+   }
+   if (full) { H.row(n) = 1.0 / sqrt((Real)n); }
+   H.release(); return H.for_return();
+} 
+
+
+
+// Multiply X by n-1 x n matrix to give n-1 contrasts
+// Return a ColumnVector
+ReturnMatrix Helmert(const ColumnVector& X, bool full)
+{
+   REPORT
+   Tracer et("Helmert * CV");
+   int n = X.nrows();
+   if (n == 0) Throw(ProgramException("X Vector of length 0", X));
+   Real sum = 0.0; ColumnVector Y;
+   if (full) Y.resize(n); else Y.resize(n-1);
+   for (int i = 1; i < n; ++i)
+      { sum += X(i); Y(i) = (i * X(i+1) - sum) / sqrt((Real)i * (i+1)); }
+   if (full) { sum += X(n); Y(n) = sum / sqrt((Real)n); }
+   Y.release(); return Y.for_return();
+} 
+
+// same as above for X a ColumnVector, length n, element j = 1; otherwise 0
+ReturnMatrix Helmert(int n, int j, bool full)
+{
+   REPORT
+   Tracer et("Helmert:single element ");
+   if (n <= 0) Throw(ProgramException("X Vector of length <= 0"));
+   if (j > n || j <= 0)
+      Throw(ProgramException("Out of range element number "));
+   ColumnVector Y; if (full) Y.resize(n); else Y.resize(n-1);
+   Y = 0.0;
+   if (j > 1) Y(j-1) = sqrt((Real)(j-1) / (Real)j);
+   for (int i = j; i < n; ++i) Y(i) = - 1.0 / sqrt((Real)i * (i+1));
+   if (full) Y(n) = 1.0 / sqrt((Real)n);
+   Y.release(); return Y.for_return();
+} 
+
+ReturnMatrix Helmert_transpose(const ColumnVector& Y, bool full)
+{
+   REPORT
+   Tracer et("Helmert_transpose * CV ");
+   int n = Y.nrows(); Real sum;
+   if (full) sum = Y(n) / sqrt((Real)n); else { sum = 0.0; ++n; }
+   ColumnVector X(n);
+   for (int i = n-1; i > 0; --i)
+   {
+      Real Yi = Y(i) / sqrt((Real)i * (i+1));
+      X(i+1) = i * Yi + sum; sum -= Yi;
+   }
+   X(1) = sum;
+   X.release(); return X.for_return();
+}
+
+// same as above but want only j-th element
+Real Helmert_transpose(const ColumnVector& Y, int j, bool full)
+{
+   REPORT
+   Tracer et("Helmert_transpose:single element ");
+   int n = Y.nrows(); Real sum;
+   if (full) sum = Y(n) / sqrt((Real)n); else { sum = 0.0; ++n; }
+   if (j > n || j <= 0) Throw(IndexException(j, Y));
+   for (int i = n-1; i > 0; --i)
+   {
+      Real Yi = Y(i) / sqrt((Real)i * (i+1));
+      if (i+1 == j) return i * Yi + sum;
+      sum -= Yi;
+   }
+   return sum;
+}
+
+ReturnMatrix Helmert(const Matrix& X, bool full)
+{
+   REPORT
+   Tracer et("Helmert * Matrix");
+   int m = X.nrows(); int n = X.ncols();
+   if (m == 0) Throw(ProgramException("Matrix has 0 rows ", X));
+   Matrix Y;
+   if (full) Y.resize(m,n); else Y.resize(m-1, n);
+   for (int j = 1; j <= n; ++j)
+   {
+      ColumnVector CV = X.Column(j);
+      Y.Column(j) = Helmert(CV, full);
+   }
+   Y.release(); return Y.for_return();
+}
+
+ReturnMatrix Helmert_transpose(const Matrix& Y, bool full)
+{
+   REPORT
+   Tracer et("Helmert_transpose * Matrix ");
+   int m = Y.nrows(); int n = Y.ncols(); if (!full) ++m;
+   Matrix X(m, n);
+   for (int j = 1; j <= n; ++j)
+   {
+      ColumnVector CV = Y.Column(j);
+      X.Column(j) = Helmert_transpose(CV, full);
+   }
+   X.release(); return X.for_return();
+}
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+
+///@}
Index: trunk/BNC/newmat/precisio.h
===================================================================
--- trunk/BNC/newmat/precisio.h	(revision 2013)
+++ trunk/BNC/newmat/precisio.h	(revision 2013)
@@ -0,0 +1,264 @@
+/// \ingroup newmat
+///@{
+
+/// \file precisio.h
+/// Floating point precision constants.
+
+#ifndef PRECISION_LIB
+#define PRECISION_LIB 0
+
+#define WANT_MATH
+#include "include.h"              // in case being used as stand alone
+
+#ifdef _STANDARD_                 // standard library available
+#include <limits>
+#endif
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef _STANDARD_                 // standard library available
+
+#ifdef OPT_COMPATIBLE
+#include <cfloat>                 // for FLT_MAX
+#endif
+
+/// Floating point precision.
+class FloatingPointPrecision
+{
+public:
+   static int Dig()              // number of decimal digits or precision
+      { return std::numeric_limits<Real>::digits10 ; }
+
+   static Real Epsilon()         // smallest number such that 1+Eps!=Eps
+      { return std::numeric_limits<Real>::epsilon(); }
+
+   static int Mantissa()         // bits in mantisa
+      { return std::numeric_limits<Real>::digits; }
+
+   static Real Maximum()         // maximum value
+      { return std::numeric_limits<Real>::max(); }
+
+   static int MaximumDecimalExponent()  // maximum decimal exponent
+      { return std::numeric_limits<Real>::max_exponent10; }
+
+   static int MaximumExponent()  // maximum binary exponent
+      { return std::numeric_limits<Real>::max_exponent; }
+
+   static Real LnMaximum()       // natural log of maximum
+      { return (Real)log(Maximum()); }
+
+   static Real Minimum()         // minimum positive value
+      { return std::numeric_limits<Real>::min(); } 
+
+   static int MinimumDecimalExponent() // minimum decimal exponent
+      { return std::numeric_limits<Real>::min_exponent10; }
+
+   static int MinimumExponent()  // minimum binary exponent
+      { return std::numeric_limits<Real>::min_exponent; }
+
+   static Real LnMinimum()       // natural log of minimum
+      { return (Real)log(Minimum()); }
+
+   static int Radix()            // exponent radix
+      { return std::numeric_limits<Real>::radix; }
+
+   static int Rounds()           // addition rounding (1 = does round)
+   {
+	  return std::numeric_limits<Real>::round_style ==
+		 std::round_to_nearest ? 1 : 0;
+   }
+
+};
+
+
+#else                              // _STANDARD_ not defined
+
+#ifndef SystemV                    // if there is float.h
+
+#ifdef USING_FLOAT
+
+/// Floating point precision (type float).
+class FloatingPointPrecision
+{
+public:
+   static int Dig()
+      { return FLT_DIG; }        // number of decimal digits or precision
+
+   static Real Epsilon()
+      { return FLT_EPSILON; }    // smallest number such that 1+Eps!=Eps
+
+   static int Mantissa()
+      { return FLT_MANT_DIG; }   // bits in mantisa
+
+   static Real Maximum()
+      { return FLT_MAX; }        // maximum value
+
+   static int MaximumDecimalExponent()
+      { return FLT_MAX_10_EXP; } // maximum decimal exponent
+
+   static int MaximumExponent()
+      { return FLT_MAX_EXP; }    // maximum binary exponent
+
+   static Real LnMaximum()
+      { return (Real)log(Maximum()); } // natural log of maximum
+
+   static Real Minimum()
+      { return FLT_MIN; }        // minimum positive value
+
+   static int MinimumDecimalExponent()
+      { return FLT_MIN_10_EXP; } // minimum decimal exponent
+
+   static int MinimumExponent()
+      { return FLT_MIN_EXP; }    // minimum binary exponent
+
+   static Real LnMinimum()
+      { return (Real)log(Minimum()); } // natural log of minimum
+
+   static int Radix()
+      { return FLT_RADIX; }      // exponent radix
+
+   static int Rounds()
+      { return FLT_ROUNDS; }     // addition rounding (1 = does round)
+
+};
+
+#endif                           // USING_FLOAT
+
+
+#ifdef USING_DOUBLE
+
+/// Floating point precision (type double).
+class FloatingPointPrecision
+{
+public:
+
+   static int Dig()
+      { return DBL_DIG; }        // number of decimal digits or precision
+
+   static Real Epsilon()
+      { return DBL_EPSILON; }    // smallest number such that 1+Eps!=Eps
+
+   static int Mantissa()
+      { return DBL_MANT_DIG; }   // bits in mantisa
+
+   static Real Maximum()
+      { return DBL_MAX; }        // maximum value
+
+   static int MaximumDecimalExponent()
+      { return DBL_MAX_10_EXP; } // maximum decimal exponent
+
+   static int MaximumExponent()
+      { return DBL_MAX_EXP; }    // maximum binary exponent
+
+   static Real LnMaximum()
+      { return (Real)log(Maximum()); } // natural log of maximum
+
+   static Real Minimum()
+   {
+//#ifdef __BCPLUSPLUS__
+//       return 2.225074e-308;     // minimum positive value
+//#else
+       return DBL_MIN;
+//#endif
+   }
+
+   static int MinimumDecimalExponent()
+      { return DBL_MIN_10_EXP; } // minimum decimal exponent
+
+   static int MinimumExponent()
+      { return DBL_MIN_EXP; }    // minimum binary exponent
+
+   static Real LnMinimum()
+      { return (Real)log(Minimum()); } // natural log of minimum
+
+
+   static int Radix()
+      { return FLT_RADIX; }      // exponent radix
+
+   static int Rounds()
+      { return FLT_ROUNDS; }     // addition rounding (1 = does round)
+
+};
+
+#endif                             // USING_DOUBLE
+
+#else                              // if there is no float.h
+
+#ifdef OPT_COMPATIBLE
+#define FLT_MAX MAXFLOAT
+#endif
+
+
+#ifdef USING_FLOAT
+
+/// Floating point precision (type float).
+class FloatingPointPrecision
+{
+public:
+
+   static Real Epsilon()
+      { return pow(2.0,(int)(1-FSIGNIF)); }
+                                   // smallest number such that 1+Eps!=Eps
+
+   static Real Maximum()
+      { return MAXFLOAT; }            // maximum value
+
+   static Real LnMaximum()
+      { return (Real)log(Maximum()); }  // natural log of maximum
+
+   static Real Minimum()
+      { return MINFLOAT; }             // minimum positive value
+
+   static Real LnMinimum()
+      { return (Real)log(Minimum()); }  // natural log of minimum
+
+};
+
+#endif                                  // USING_FLOAT
+
+
+#ifdef USING_DOUBLE
+
+/// Floating point precision (type double).
+class FloatingPointPrecision
+{
+public:
+
+   static Real Epsilon()
+      { return pow(2.0,(int)(1-DSIGNIF)); }
+                                      // smallest number such that 1+Eps!=Eps
+
+   static Real Maximum()
+      { return MAXDOUBLE; }           // maximum value
+
+   static Real LnMaximum()
+      { return LN_MAXDOUBLE; }        // natural log of maximum
+
+   static Real Minimum()
+      { return MINDOUBLE; }
+
+   static Real LnMinimum()
+      { return LN_MINDOUBLE; }        // natural log of minimum
+};
+
+#endif                                // USING_DOUBLE
+
+#endif                                // SystemV
+
+#endif                                // _STANDARD_
+
+
+
+
+#ifdef use_namespace
+}
+#endif                                // use_namespace
+
+
+
+#endif                                // PRECISION_LIB
+
+
+///@}
Index: trunk/BNC/newmat/sort.cpp
===================================================================
--- trunk/BNC/newmat/sort.cpp	(revision 2013)
+++ trunk/BNC/newmat/sort.cpp	(revision 2013)
@@ -0,0 +1,277 @@
+/// \ingroup newmat
+///@{
+
+/// \file sort.cpp
+/// Sorting functions.
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#define WANT_MATH
+
+#include "include.h"
+
+#include "newmatap.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,13); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+/******************************** Quick sort ********************************/
+
+// Quicksort.
+// Essentially the method described in Sedgewick s algorithms in C++
+// My version is still partially recursive, unlike Segewick s, but the
+// smallest segment of each split is used in the recursion, so it should
+// not overlead the stack.
+
+// If the process does not seems to be converging an exception is thrown.
+
+
+#define DoSimpleSort 17            // when to switch to insert sort
+#define MaxDepth 50                // maximum recursion depth
+
+static void MyQuickSortDescending(Real* first, Real* last, int depth);
+static void InsertionSortDescending(Real* first, const int length,
+   int guard);
+static Real SortThreeDescending(Real* a, Real* b, Real* c);
+
+static void MyQuickSortAscending(Real* first, Real* last, int depth);
+static void InsertionSortAscending(Real* first, const int length,
+   int guard);
+
+
+void sort_descending(GeneralMatrix& GM)
+{
+   REPORT
+   Tracer et("sort_descending");
+
+   Real* data = GM.Store(); int max = GM.Storage();
+
+   if (max > DoSimpleSort) MyQuickSortDescending(data, data + max - 1, 0);
+   InsertionSortDescending(data, max, DoSimpleSort);
+
+}
+
+static Real SortThreeDescending(Real* a, Real* b, Real* c)
+{
+   // sort *a, *b, *c; return *b; optimise for already sorted
+   if (*a >= *b)
+   {
+      if (*b >= *c) { REPORT return *b; }
+      else if (*a >= *c) { REPORT Real x = *c; *c = *b; *b = x; return x; }
+      else { REPORT Real x = *a; *a = *c; *c = *b; *b = x; return x; }
+   }
+   else if (*c >= *b) { REPORT Real x = *c; *c = *a; *a = x; return *b; }
+   else if (*a >= *c) { REPORT Real x = *a; *a = *b; *b = x; return x; }
+   else { REPORT Real x = *c; *c = *a; *a = *b; *b = x; return x; }
+}
+
+static void InsertionSortDescending(Real* first, const int length,
+   int guard)
+// guard gives the length of the sequence to scan to find first
+// element (eg = length)
+{
+   REPORT
+   if (length <= 1) return;
+
+   // scan for first element
+   Real* f = first; Real v = *f; Real* h = f;
+   if (guard > length) { REPORT guard = length; }
+   int i = guard - 1;
+   while (i--) if (v < *(++f)) { v = *f; h = f; }
+   *h = *first; *first = v;
+
+   // do the sort
+   i = length - 1; f = first;
+   while (i--)
+   {
+      Real* g = f++; h = f; v = *h;
+      while (*g < v) *h-- = *g--;
+      *h = v;
+   }
+}
+
+static void MyQuickSortDescending(Real* first, Real* last, int depth)
+{
+   REPORT
+   for (;;)
+   {
+      const int length = last - first + 1;
+      if (length < DoSimpleSort) { REPORT return; }
+      if (depth++ > MaxDepth)
+         Throw(ConvergenceException("QuickSortDescending fails: "));
+      Real* centre = first + length/2;
+      const Real test = SortThreeDescending(first, centre, last);
+      Real* f = first; Real* l = last;
+      for (;;)
+      {
+         while (*(++f) > test) {}
+         while (*(--l) < test) {}
+         if (l <= f) break;
+         const Real temp = *f; *f = *l; *l = temp;
+      }
+      if (f > centre)
+         { REPORT MyQuickSortDescending(l+1, last, depth); last = f-1; }
+      else { REPORT MyQuickSortDescending(first, f-1, depth); first = l+1; }
+   }
+}
+
+void sort_ascending(GeneralMatrix& GM)
+{
+   REPORT
+   Tracer et("sort_ascending");
+
+   Real* data = GM.Store(); int max = GM.Storage();
+
+   if (max > DoSimpleSort) MyQuickSortAscending(data, data + max - 1, 0);
+   InsertionSortAscending(data, max, DoSimpleSort);
+
+}
+
+static void InsertionSortAscending(Real* first, const int length,
+   int guard)
+// guard gives the length of the sequence to scan to find first
+// element (eg guard = length)
+{
+   REPORT
+   if (length <= 1) return;
+
+   // scan for first element
+   Real* f = first; Real v = *f; Real* h = f;
+   if (guard > length) { REPORT guard = length; }
+   int i = guard - 1;
+   while (i--) if (v > *(++f)) { v = *f; h = f; }
+   *h = *first; *first = v;
+
+   // do the sort
+   i = length - 1; f = first;
+   while (i--)
+   {
+      Real* g = f++; h = f; v = *h;
+      while (*g > v) *h-- = *g--;
+      *h = v;
+   }
+}
+static void MyQuickSortAscending(Real* first, Real* last, int depth)
+{
+   REPORT
+   for (;;)
+   {
+      const int length = last - first + 1;
+      if (length < DoSimpleSort) { REPORT return; }
+      if (depth++ > MaxDepth)
+         Throw(ConvergenceException("QuickSortAscending fails: "));
+      Real* centre = first + length/2;
+      const Real test = SortThreeDescending(last, centre, first);
+      Real* f = first; Real* l = last;
+      for (;;)
+      {
+         while (*(++f) < test) {}
+         while (*(--l) > test) {}
+         if (l <= f) break;
+         const Real temp = *f; *f = *l; *l = temp;
+      }
+      if (f > centre)
+         { REPORT MyQuickSortAscending(l+1, last, depth); last = f-1; }
+      else { REPORT MyQuickSortAscending(first, f-1, depth); first = l+1; }
+   }
+}
+
+//********* sort diagonal matrix & rearrange matrix columns ****************
+
+// used by SVD
+
+// these are for sorting singular values - should be updated with faster
+// sorts that handle exchange of columns better
+// however time is probably not significant compared with SVD time
+
+void SortSV(DiagonalMatrix& D, Matrix& U, bool ascending)
+{
+   REPORT
+   Tracer trace("SortSV_DU");
+   int m = U.Nrows(); int n = U.Ncols();
+   if (n != D.Nrows()) Throw(IncompatibleDimensionsException(D,U));
+   Real* u = U.Store();
+   for (int i=0; i<n; i++)
+   {
+      int k = i; Real p = D.element(i);
+      if (ascending)
+      {
+         for (int j=i+1; j<n; j++)
+            { if (D.element(j) < p) { k = j; p = D.element(j); } }
+      }
+      else
+      {
+         for (int j=i+1; j<n; j++)
+         { if (D.element(j) > p) { k = j; p = D.element(j); } }
+      }
+      if (k != i)
+      {
+         D.element(k) = D.element(i); D.element(i) = p; int j = m;
+         Real* uji = u + i; Real* ujk = u + k;
+         if (j) for(;;)
+         {
+            p = *uji; *uji = *ujk; *ujk = p;
+            if (!(--j)) break;
+            uji += n; ujk += n;
+         }
+      }
+   }
+}
+
+void SortSV(DiagonalMatrix& D, Matrix& U, Matrix& V, bool ascending)
+{
+   REPORT
+   Tracer trace("SortSV_DUV");
+   int mu = U.Nrows(); int mv = V.Nrows(); int n = D.Nrows();
+   if (n != U.Ncols()) Throw(IncompatibleDimensionsException(D,U));
+   if (n != V.Ncols()) Throw(IncompatibleDimensionsException(D,V));
+   Real* u = U.Store(); Real* v = V.Store();
+   for (int i=0; i<n; i++)
+   {
+      int k = i; Real p = D.element(i);
+      if (ascending)
+      {
+         for (int j=i+1; j<n; j++)
+            { if (D.element(j) < p) { k = j; p = D.element(j); } }
+      }
+      else
+      {
+         for (int j=i+1; j<n; j++)
+         { if (D.element(j) > p) { k = j; p = D.element(j); } }
+      }
+      if (k != i)
+      {
+         D.element(k) = D.element(i); D.element(i) = p;
+         Real* uji = u + i; Real* ujk = u + k;
+         Real* vji = v + i; Real* vjk = v + k;
+         int j = mu;
+         if (j) for(;;)
+         {
+            p = *uji; *uji = *ujk; *ujk = p; if (!(--j)) break;
+            uji += n; ujk += n;
+         }
+         j = mv;
+         if (j) for(;;)
+         {
+            p = *vji; *vji = *vjk; *vjk = p; if (!(--j)) break;
+            vji += n; vjk += n;
+         }
+      }
+   }
+}
+
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
Index: trunk/BNC/newmat/submat.cpp
===================================================================
--- trunk/BNC/newmat/submat.cpp	(revision 2013)
+++ trunk/BNC/newmat/submat.cpp	(revision 2013)
@@ -0,0 +1,363 @@
+/// \ingroup newmat
+///@{
+
+/// \file submat.cpp
+/// Submatrix manipulation.
+
+// Copyright (C) 1991,2,3,4: R B Davies
+
+#include "include.h"
+
+#include "newmat.h"
+#include "newmatrc.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,11); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+/****************************** submatrices *********************************/
+
+GetSubMatrix BaseMatrix::submatrix(int first_row, int last_row, int first_col,
+   int last_col) const
+{
+   REPORT
+   Tracer tr("submatrix");
+   int a = first_row - 1; int b = last_row - first_row + 1;
+   int c = first_col - 1; int d = last_col - first_col + 1;
+   if (a<0 || b<0 || c<0 || d<0) Throw(SubMatrixDimensionException());
+                             // allow zero rows or columns
+   return GetSubMatrix(this, a, b, c, d, false);
+}
+
+GetSubMatrix BaseMatrix::sym_submatrix(int first_row, int last_row) const
+{
+   REPORT
+   Tracer tr("sym_submatrix");
+   int a = first_row - 1; int b = last_row - first_row + 1;
+   if (a<0 || b<0) Throw(SubMatrixDimensionException());
+                             // allow zero rows or columns
+   return GetSubMatrix( this, a, b, a, b, true);
+}
+
+GetSubMatrix BaseMatrix::row(int first_row) const
+{
+   REPORT
+   Tracer tr("SubMatrix(row)");
+   int a = first_row - 1;
+   if (a<0) Throw(SubMatrixDimensionException());
+   return GetSubMatrix(this, a, 1, 0, -1, false);
+}
+
+GetSubMatrix BaseMatrix::rows(int first_row, int last_row) const
+{
+   REPORT
+   Tracer tr("SubMatrix(rows)");
+   int a = first_row - 1; int b = last_row - first_row + 1;
+   if (a<0 || b<0) Throw(SubMatrixDimensionException());
+                             // allow zero rows or columns
+   return GetSubMatrix(this, a, b, 0, -1, false);
+}
+
+GetSubMatrix BaseMatrix::column(int first_col) const
+{
+   REPORT
+   Tracer tr("SubMatrix(column)");
+   int c = first_col - 1;
+   if (c<0) Throw(SubMatrixDimensionException());
+   return GetSubMatrix(this, 0, -1, c, 1, false);
+}
+
+GetSubMatrix BaseMatrix::columns(int first_col, int last_col) const
+{
+   REPORT
+   Tracer tr("SubMatrix(columns)");
+   int c = first_col - 1; int d = last_col - first_col + 1;
+   if (c<0 || d<0) Throw(SubMatrixDimensionException());
+                             // allow zero rows or columns
+   return GetSubMatrix(this, 0, -1, c, d, false);
+}
+
+void GetSubMatrix::SetUpLHS()
+{
+   REPORT
+   Tracer tr("SubMatrix(LHS)");
+   const BaseMatrix* bm1 = bm;
+   GeneralMatrix* gm1 = ((BaseMatrix*&)bm)->Evaluate();
+   if ((BaseMatrix*)gm1!=bm1)
+      Throw(ProgramException("Invalid LHS"));
+   if (row_number < 0) row_number = gm1->Nrows();
+   if (col_number < 0) col_number = gm1->Ncols();
+   if (row_skip+row_number > gm1->Nrows()
+      || col_skip+col_number > gm1->Ncols())
+         Throw(SubMatrixDimensionException());
+}
+
+void GetSubMatrix::operator<<(const BaseMatrix& bmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(<<)"); GeneralMatrix* gmx = 0;
+   Try
+   {
+      SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
+      if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
+         Throw(IncompatibleDimensionsException());
+      MatrixRow mrx(gmx, LoadOnEntry);
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Copy(mrx); mr.Next(); mrx.Next();
+      }
+      gmx->tDelete();
+   }
+
+   CatchAll
+   {
+      if (gmx) gmx->tDelete();
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator=(const BaseMatrix& bmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(=)"); GeneralMatrix* gmx = 0;
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
+      if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
+         Throw(IncompatibleDimensionsException());
+      LoadAndStoreFlag lasf =
+         (  row_skip == col_skip
+            && gm->type().is_symmetric()
+            && gmx->type().is_symmetric() )
+        ? LoadOnEntry+DirectPart
+        : LoadOnEntry;
+      MatrixRow mrx(gmx, lasf);
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.CopyCheck(mrx); mr.Next(); mrx.Next();
+      }
+      gmx->tDelete();
+   }
+
+   CatchAll
+   {
+      if (gmx) gmx->tDelete();
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator<<(const double* r)
+{
+   REPORT
+   Tracer tr("SubMatrix(<<double*)");
+   SetUpLHS();
+   if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
+      Throw(SubMatrixDimensionException());
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                  // do need LoadOnEntry
+   MatrixRowCol sub; int i = row_number;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      sub.Copy(r); mr.Next();
+   }
+}
+
+void GetSubMatrix::operator<<(const float* r)
+{
+   REPORT
+   Tracer tr("SubMatrix(<<float*)");
+   SetUpLHS();
+   if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
+      Throw(SubMatrixDimensionException());
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                  // do need LoadOnEntry
+   MatrixRowCol sub; int i = row_number;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      sub.Copy(r); mr.Next();
+   }
+}
+
+void GetSubMatrix::operator<<(const int* r)
+{
+   REPORT
+   Tracer tr("SubMatrix(<<int*)");
+   SetUpLHS();
+   if (row_skip+row_number > gm->Nrows() || col_skip+col_number > gm->Ncols())
+      Throw(SubMatrixDimensionException());
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                  // do need LoadOnEntry
+   MatrixRowCol sub; int i = row_number;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      sub.Copy(r); mr.Next();
+   }
+}
+
+void GetSubMatrix::operator=(Real r)
+{
+   REPORT
+   Tracer tr("SubMatrix(=Real)");
+   SetUpLHS();
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                  // do need LoadOnEntry
+   MatrixRowCol sub; int i = row_number;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      sub.Copy(r); mr.Next();
+   }
+}
+
+void GetSubMatrix::inject(const GeneralMatrix& gmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(inject)");
+   SetUpLHS();
+   if (row_number != gmx.Nrows() || col_number != gmx.Ncols())
+      Throw(IncompatibleDimensionsException());
+   MatrixRow mrx((GeneralMatrix*)(&gmx), LoadOnEntry);
+   MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                  // do need LoadOnEntry
+   MatrixRowCol sub; int i = row_number;
+   while (i--)
+   {
+      mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+      sub.Inject(mrx); mr.Next(); mrx.Next();
+   }
+}
+
+void GetSubMatrix::operator+=(const BaseMatrix& bmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(+=)"); GeneralMatrix* gmx = 0;
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
+      if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
+         Throw(IncompatibleDimensionsException());
+      MatrixRow mrx(gmx, LoadOnEntry);
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Check(mrx);                            // check for loss of info
+         sub.Add(mrx); mr.Next(); mrx.Next();
+      }
+      gmx->tDelete();
+   }
+
+   CatchAll
+   {
+      if (gmx) gmx->tDelete();
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator-=(const BaseMatrix& bmx)
+{
+   REPORT
+   Tracer tr("SubMatrix(-=)"); GeneralMatrix* gmx = 0;
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS(); gmx = ((BaseMatrix&)bmx).Evaluate();
+      if (row_number != gmx->Nrows() || col_number != gmx->Ncols())
+         Throw(IncompatibleDimensionsException());
+      MatrixRow mrx(gmx, LoadOnEntry);
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Check(mrx);                            // check for loss of info
+         sub.Sub(mrx); mr.Next(); mrx.Next();
+      }
+      gmx->tDelete();
+   }
+
+   CatchAll
+   {
+      if (gmx) gmx->tDelete();
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator+=(Real r)
+{
+   REPORT
+   Tracer tr("SubMatrix(+= or -= Real)");
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS();
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Check();                               // check for loss of info
+         sub.Add(r); mr.Next();
+      }
+   }
+
+   CatchAll
+   {
+      ReThrow;
+   }
+}
+
+void GetSubMatrix::operator*=(Real r)
+{
+   REPORT
+   Tracer tr("SubMatrix(*= or /= Real)");
+   // MatrixConversionCheck mcc;         // Check for loss of info
+   Try
+   {
+      SetUpLHS();
+      MatrixRow mr(gm, LoadOnEntry+StoreOnExit+DirectPart, row_skip);
+                                     // do need LoadOnEntry
+      MatrixRowCol sub; int i = row_number;
+      while (i--)
+      {
+         mr.SubRowCol(sub, col_skip, col_number);   // put values in sub
+         sub.Multiply(r); mr.Next();
+      }
+   }
+
+   CatchAll
+   {
+      ReThrow;
+   }
+}
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
+
Index: trunk/BNC/newmat/svd.cpp
===================================================================
--- trunk/BNC/newmat/svd.cpp	(revision 2013)
+++ trunk/BNC/newmat/svd.cpp	(revision 2013)
@@ -0,0 +1,209 @@
+/// \ingroup newmat
+///@{
+
+/// \file svd.cpp
+/// Singular value decomposition.
+
+// Copyright (C) 1991,2,3,4,5: R B Davies
+// Updated 17 July, 1995
+
+#define WANT_MATH
+
+#include "include.h"
+#include "newmatap.h"
+#include "newmatrm.h"
+#include "precisio.h"
+
+#ifdef use_namespace
+namespace NEWMAT {
+#endif
+
+#ifdef DO_REPORT
+#define REPORT { static ExeCounter ExeCount(__LINE__,15); ++ExeCount; }
+#else
+#define REPORT {}
+#endif
+
+
+
+
+void SVD(const Matrix& A, DiagonalMatrix& Q, Matrix& U, Matrix& V,
+   bool withU, bool withV)
+// from Wilkinson and Reinsch: "Handbook of Automatic Computation"
+{
+   REPORT
+   Tracer trace("SVD");
+   Real eps = FloatingPointPrecision::Epsilon();
+   Real tol = FloatingPointPrecision::Minimum()/eps;
+
+   int m = A.Nrows(); int n = A.Ncols();
+   if (m<n)
+      Throw(ProgramException("Want no. Rows >= no. Cols", A));
+   if (withV && &U == &V)
+      Throw(ProgramException("Need different matrices for U and V", U, V));
+   U = A; Real g = 0.0; Real f,h; Real x = 0.0; int i;
+   RowVector E(n); RectMatrixRow EI(E,0); Q.ReSize(n);
+   RectMatrixCol UCI(U,0); RectMatrixRow URI(U,0,1,n-1);
+
+   if (n) for (i=0;;)
+   {
+      EI.First() = g; Real ei = g; EI.Right(); Real s = UCI.SumSquare();
+      if (s<tol) { REPORT Q.element(i) = 0.0; }
+      else
+      {
+         REPORT
+         f = UCI.First(); g = -sign(sqrt(s), f); h = f*g-s; UCI.First() = f-g;
+         Q.element(i) = g; RectMatrixCol UCJ = UCI; int j=n-i;
+         while (--j) { UCJ.Right(); UCJ.AddScaled(UCI, (UCI*UCJ)/h); }
+      }
+
+      s = URI.SumSquare();
+      if (s<tol) { REPORT g = 0.0; }
+      else
+      {
+         REPORT
+         f = URI.First(); g = -sign(sqrt(s), f); URI.First() = f-g;
+         EI.Divide(URI,f*g-s); RectMatrixRow URJ = URI; int j=m-i;
+         while (--j) { URJ.Down(); URJ.AddScaled(EI, URI*URJ); }
+      }
+
+      Real y = fabs(Q.element(i)) + fabs(ei); if (x<y) { REPORT x = y; }
+      if (++i == n) { REPORT break; }
+      UCI.DownDiag(); URI.DownDiag();
+   }
+
+   if (withV)
+   {
+      REPORT
+      V.ReSize(n,n); V = 0.0; RectMatrixCol VCI(V,n-1,n-1,1);
+      if (n) { VCI.First() = 1.0; g=E.element(n-1); if (n!=1) URI.UpDiag(); }
+      for (i=n-2; i>=0; i--)
+      {
+         VCI.Left();
+         if (g!=0.0)
+         {
+            VCI.Divide(URI, URI.First()*g); int j = n-i;
+            RectMatrixCol VCJ = VCI;
+            while (--j) { VCJ.Right(); VCJ.AddScaled( VCI, (URI*VCJ) ); }
+         }
+         VCI.Zero(); VCI.Up(); VCI.First() = 1.0; g=E.element(i);
+         if (i==0) break;
+         URI.UpDiag();
+      }
+   }
+
+   if (withU)
+   {
+      REPORT
+      for (i=n-1; i>=0; i--)
+      {
+         g = Q.element(i); URI.Reset(U,i,i+1,n-i-1); URI.Zero();
+         if (g!=0.0)
+         {
+            h=UCI.First()*g; int j=n-i; RectMatrixCol UCJ = UCI;
+            while (--j)
+            {
+               UCJ.Right(); UCI.Down(); UCJ.Down(); Real s = UCI*UCJ;
+               UCI.Up(); UCJ.Up(); UCJ.AddScaled(UCI,s/h);
+            }
+            UCI.Divide(g);
+         }
+         else UCI.Zero();
+         UCI.First() += 1.0;
+         if (i==0) break;
+         UCI.UpDiag();
+      }
+   }
+
+   eps *= x;
+   for (int k=n-1; k>=0; k--)
+   {
+      Real z = -FloatingPointPrecision::Maximum(); // to keep Gnu happy
+      Real y; int limit = 50; int l = 0;
+      while (limit--)
+      {
+         Real c, s; int i; int l1=k; bool tfc=false;
+         for (l=k; l>=0; l--)
+         {
+//          if (fabs(E.element(l))<=eps) goto test_f_convergence;
+            if (fabs(E.element(l))<=eps) { REPORT tfc=true; break; }
+            if (fabs(Q.element(l-1))<=eps) { REPORT l1=l; break; }
+            REPORT
+         }
+         if (!tfc)
+         {
+            REPORT
+            l=l1; l1=l-1; s = -1.0; c = 0.0;
+            for (i=l; i<=k; i++)
+            {
+               f = - s * E.element(i); E.element(i) *= c;
+//             if (fabs(f)<=eps) goto test_f_convergence;
+               if (fabs(f)<=eps) { REPORT break; }
+               g = Q.element(i); h = pythag(g,f,c,s); Q.element(i) = h;
+               if (withU)
+               {
+                  REPORT
+                  RectMatrixCol UCI(U,i); RectMatrixCol UCJ(U,l1);
+                  ComplexScale(UCJ, UCI, c, s);
+               }
+            }
+         }
+//       test_f_convergence: z = Q.element(k); if (l==k) goto convergence;
+         z = Q.element(k);  if (l==k) { REPORT break; }
+
+         x = Q.element(l); y = Q.element(k-1);
+         g = E.element(k-1); h = E.element(k);
+         f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2*h*y);
+         if (f>1)         { REPORT g = f * sqrt(1 + square(1/f)); }
+         else if (f<-1)   { REPORT g = -f * sqrt(1 + square(1/f)); }
+         else             { REPORT g = sqrt(f*f + 1); }
+            { REPORT f = ((x-z)*(x+z) + h*(y / ((f<0.0) ? f-g : f+g)-h)) / x; }
+
+         c = 1.0; s = 1.0;
+         for (i=l+1; i<=k; i++)
+         {
+            g = E.element(i); y = Q.element(i); h = s*g; g *= c;
+            z = pythag(f,h,c,s); E.element(i-1) = z;
+            f = x*c + g*s; g = -x*s + g*c; h = y*s; y *= c;
+            if (withV)
+            {
+               REPORT
+               RectMatrixCol VCI(V,i); RectMatrixCol VCJ(V,i-1);
+               ComplexScale(VCI, VCJ, c, s);
+            }
+            z = pythag(f,h,c,s); Q.element(i-1) = z;
+            f = c*g + s*y; x = -s*g + c*y;
+            if (withU)
+            {
+               REPORT
+               RectMatrixCol UCI(U,i); RectMatrixCol UCJ(U,i-1);
+               ComplexScale(UCI, UCJ, c, s);
+            }
+         }
+         E.element(l) = 0.0; E.element(k) = f; Q.element(k) = x;
+      }
+      if (l!=k) { Throw(ConvergenceException(A)); }
+// convergence:
+      if (z < 0.0)
+      {
+         REPORT
+         Q.element(k) = -z;
+         if (withV) { RectMatrixCol VCI(V,k); VCI.Negate(); }
+      }
+   }
+   if (withU & withV) SortSV(Q, U, V);
+   else if (withU) SortSV(Q, U);
+   else if (withV) SortSV(Q, V);
+   else sort_descending(Q);
+}
+
+void SVD(const Matrix& A, DiagonalMatrix& D)
+{ REPORT Matrix U; SVD(A, D, U, U, false, false); }
+
+
+
+#ifdef use_namespace
+}
+#endif
+
+///@}
Index: trunk/BNS/RTCM/rtcm3torinex.c
===================================================================
--- trunk/BNS/RTCM/rtcm3torinex.c	(revision 2012)
+++ trunk/BNS/RTCM/rtcm3torinex.c	(revision 2013)
@@ -1,5 +1,5 @@
 /*
   Converter for RTCM3 data to RINEX.
-  $Id: rtcm3torinex.c,v 1.25 2009/05/07 09:27:19 mervart Exp $
+  $Id: rtcm3torinex.c,v 1.27 2009/11/04 16:40:16 zdenek Exp $
   Copyright (C) 2005-2008 by Dirk Stöcker <stoecker@alberding.eu>
 
@@ -55,5 +55,5 @@
 
 /* CVS revision and version */
-static char revisionstr[] = "$Revision: 1.25 $";
+static char revisionstr[] = "$Revision: 1.27 $";
 
 #ifndef COMPILEDATE
@@ -675,4 +675,7 @@
           GETBITS(code, 1)
           GETBITS(freq, 5)
+
+          gnss->channels[num] = freq - 7;
+
           if(code)
           {
@@ -1689,5 +1692,5 @@
 
 #ifndef NO_RTCM3_MAIN
-static char datestr[]     = "$Date: 2009/05/07 09:27:19 $";
+static char datestr[]     = "$Date: 2009/11/04 16:40:16 $";
 
 /* The string, which is send as agent in HTTP request */
Index: trunk/BNS/RTCM/rtcm3torinex.h
===================================================================
--- trunk/BNS/RTCM/rtcm3torinex.h	(revision 2012)
+++ trunk/BNS/RTCM/rtcm3torinex.h	(revision 2013)
@@ -4,5 +4,5 @@
 /*
   Converter for RTCM3 data to RINEX.
-  $Id: rtcm3torinex.h,v 1.17 2009/05/07 09:27:19 mervart Exp $
+  $Id: rtcm3torinex.h,v 1.18 2009/11/04 16:19:40 zdenek Exp $
   Copyright (C) 2005-2006 by Dirk Stöcker <stoecker@alberding.eu>
 
@@ -108,4 +108,5 @@
   int    dataflags[24];      /* GPSDF_xxx */
   int    satellites[24];     /* SV - IDs */
+  int    channels[24];       /* Glonass channels - valid of Glonass SV only */
   int    snrL1[24];          /* Important: all the 5 SV-specific fields must */
   int    snrL2[24];          /* have the same SV-order */
