matrix.h.html mathcode2html   
 Source file:   matrix.h
 Converted:   Wed Mar 19 2014 at 13:56:25
 This documentation file will not reflect any later changes in the source file.

$$\phantom{******** If you see this on the webpage then the browser could not locate *********}$$
$$\phantom{******** jsMath/easy/load.js or the variable root is set wrong in this file *********}$$
$$\newcommand{\vector}[1]{\left[\begin{array}{c} #1 \end{array}\right]}$$ $$\newenvironment{matrix}{\left[\begin{array}{cccccccccc}} {\end{array}\right]}$$ $$\newcommand{\A}{{\cal A}}$$ $$\newcommand{\W}{{\cal W}}$$

/* Copyright 1998-2013 Research Foundation State University of New York   */

/* This file is part of QUB Express.                                      */

/* QUB Express is free software; you can redistribute it and/or modify    */
/* it under the terms of the GNU General Public License as published by   */
/* the Free Software Foundation, either version 3 of the License, or      */
/* (at your option) any later version.                                    */

/* QUB Express is distributed in the hope that it will be useful,         */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of         */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
/* GNU General Public License for more details.                           */

/* You should have received a copy of the GNU General Public License,     */
/* named LICENSE.txt, in the QUB Express program directory.  If not, see  */
/* <http://www.gnu.org/licenses/>.                                        */

#include <iostream>
#include <assert.h>

namespace fq
{
	
/**
 * int size() const: if no const, then when calling b.size() from assgnmt
 * operator, because the argument b is const ref, the compiler will 
 * complain.
 *
 * One senario: CString::SetCString(const CString&) - the arg must be 
 * either const ref or CString, and cannot be CString&. Consider
 *   LPCSTR lp;
 *   obj.SetCString(lp);
 * Suppose there is a type conversion function. To compile, the compiler 
 * needs to create a temp variable and the code becomes:
 *   LPCSTR;
 *   CString temp(lp); 
 *   obj.SetCString(temp);
 * With CString&, the compiler must allow the function to change the 
 * contents of lp. But such change cannot propagate back through temp.
 * See Periodic journal of MSDN under key word: const reference.
 *
 * operator []: the return type should be just a ref, not const ref; 
 * otherwise, if a is a matrix, then a[i]=v would not be allowed -
 * in fact compiler generates a warning message:
 * 'passing `const vector<double>' as `this' argument of `const class 
 * vector<double> & vector<double>::operator =<double>(const class 
 * vector<double> &)' discards const.
 *
 * subscript[i]: sometimes, i may be some type other than int, Microsoft
 * compiler will complain. So we need to add overloaded subscript function
 * for each type.
 *
 * 4/18/00: xmatrix.cpp doesn't behave properly after adding the type
 * conversion function T* in vector. The bugs disappers after 
 * rearrange the const-ness, but the reason is unknown.
 */

#ifndef _MATRIX_
#define _MATRIX_

#ifndef __cplusplus
  #define true 1
  #define false 0
#endif

// -------------------------------------------------------------------------
// vector class


template<class T> class vector {
	public:
		int n;             
		T* v; 
		int nbuf;      
		
		// empty Constructor
		vector() : n(0), v(0), nbuf(0) { 
			}            
		
		// copy Constructor
		vector(const vector<T>& b){
			n=nbuf=0, v=0; // v=0 is new 9/20/01 Chris 
			*this = b;                     // call assgn operator
			}
		
		vector(int m, T c) {
			n=nbuf=m;
			v=0;
			if (m > 0)
				v = new T[m];
			*this = c;                     // call assgn operator
			}

		vector(int m) { 
			n=nbuf=m;
			v=0; // v=0 is new 9/20/01 Chris
			if( m>0 ) 
				v = new T[m];
			for( int i=0; i<m; i++) 
				v[i]=(T)0;
			}
		
		// destructor
		~vector() {
			if (v != 0) 
				delete[] v;
			n=nbuf=0;
			}
		
		T& operator [] (int i) { 
			return v[i]; 
			} 
		T& operator [] (long i) { 
			return v[i]; 
			} 
		T& operator [] (unsigned long i) { 
			return v[i]; 
			} 
		
		// assgmt operators
		const vector<T>& operator =(const vector<T>& b){  // default assgnmt
			if (this == &b)
				return *this;
			
			if (n == b.size()) {
				for (int i=0; i<n; i++) 
					v[i] = b[i];
				return *this;
				}
			
			if (nbuf > 0) 
				delete[] v;
			n = nbuf = b.size();
			v = 0;
			if (n > 0) 
				v = new T[n];
			for (int i=0; i<n; i++)
				v[i] = b[i];          // recall that b[i] == *(b + i) == *(vector + scalar [add scalar to all elements]) == *vector = value of first element of vector after adding i.  Unfortunately the vector+T call itself calls vector=vector and the stack overflows.  Pretty sure this happens only with vector<int> (and maybe vector<long> if we had any) 
			return *this;
			}
		
		// set all members to a specified value 
		const vector<T>& operator =(const T c) {
			for (int i=0; i<n; i++)
				v[i] = c;
			return *this;
			}
		
		// cast (type conversion)
		operator T* () const { 
			return (T*)v; 
			}
		
		// resize while preserving
		void resize(int m){ // const vector<T>& resize(int m)                
			if ( m == n )
				return;
			
			vector<T> b(m);
			for (int i=0; i< (m<n ? m:n); i++)
				b[i] = v[i];
			*this = b;
			}
		
		// clear    
		void clear() {
			if (v!=0)
				delete[] v;   
			n=nbuf=0;
			}

		// append an element
		void push_back (const T c){ // const vector<T>& push_back (const T c)             
			if (n == nbuf){
				//----- If no room in preallocated space, grow buffer.
				T* b = new T[nbuf+nbuf+100];		//T* b = new T[nbuf+10000];		// Changed 11/2004 {JB}  generally these are growing from 0 to 1
				for ( int i=0; i<n; i++)
					b[i] = v[i];
				
				if (nbuf>0) 
					delete[] v;
				v = b;
				nbuf=nbuf+nbuf+100;		//nbuf += 10000;
				}
			v[n] = c;
			n++;
			}
		
		// empty, size
		int size() const { 
			return n; 
			} 
	};

template<class T> vector<T> operator -(const vector<T>& u, const vector<T>& v){
   return u+(-v);
	}

template<class T> std::ostream& operator<<(std::ostream& ost, vector<T>& v)
{
	int n;
	if ( (n = v.size()) )
		ost << v[0];
	for (int i=1; i<n; ++i)
		ost << '\t' << v[i];
	return ost;
}

// ------------------------------------------------------------------
// matrix class
//
// Chris 9/20/01 fix:
// if you repeatedly 'T **m = (T**)theMatrix;'
// then operator T** would repeatedly new[] without delete[]
// * added delete[] where appropriate.
template<class T> class matrix {
	public:
		int nr;             // number of rows
		int nc;             // number of columns
		vector<T>* a;       // array of vectors
    
		T** ptr;            
		// used for type conversion from matrix to T**.
		// ptr[i] refers to &a[i][0], i.e. the elements 
		// of the vector a[i] instead of the vector itself.
		// this can be eliminated by changing a to T**.
		
		// empty Constructor 
		matrix() : nr(0), nc(0), a(0), ptr(0) { 
			}     
		
		matrix(const matrix<T>& b) {          // copy
			nr=nc=0; 
			ptr=0;
			a = 0; // new 9/20/01 Chris
			*this = b;   // call assgn operator
			}
		
		matrix(int _m, int _n, T c){
			nr=_m, nc=_n, a=0, ptr=0;
			if (_m > 0){
				a = new vector<T>[_m];
				for (int i=0; i<_m; i++) 
					a[i].resize(_n);
				}
			*this = c;   // call assgn operator
			}
		
		matrix(int _m, int _n) { 
			nr=_m, nc=_n, a=0, ptr=0;
			if (_m > 0){
				a = new vector<T>[_m];
				for (int i=0; i<_m; i++) {
					a[i].resize(_n);
					for (int j=0; j<_n; j++)
						a[i][j] = (T)0;
					}
				}
			}
		
		// destructor
		~matrix() {
			if (a != 0) 
				delete[] a;
			if (ptr!=0) 
				delete[] ptr;
			}
		
		// assgmt operators
		const matrix<T>& operator = (const matrix<T>& b) { // default assgnmt
			if (this == &b)
				return *this;
			
			if (nr == b.m() && nc == b.n()){
				for (int i=0; i<nr; i++)
					for (int j=0; j<nc; j++)
						a[i][j] = b[i][j];
				return *this;
				}
			
			if (nr > 0) 
				delete[] a;   // invoke vector destructor???
			nr = b.m();
			nc = b.n();
			a = 0;
			if (nr > 0) 
				a = new vector<T>[nr];
			for (int i=0; i<nr; i++){
				a[i].resize(nc);
				for (int j=0; j<nc; j++)
					a[i][j] = b[i][j];
				}
			return *this;
			}
		
		const matrix<T>& operator = (const T c) {
			for (int i=0; i<nr; i++)
				for (int j=0; j<nc; j++)
					a[i][j] = c;
				return *this;
			}
		
		// other operators
		vector<T>& operator [] (int i) const {	// subscripting
			return a[i]; 
			} 
		
		// cast (type conversion)
		operator T** () { 
			if ( ptr ) 
				delete [] ptr; // new Chris 9/20/01
			ptr = new T*[nr];
			for (int i=0; i<nr; i++) 
				ptr[i] = a[i];
			return ptr; 
			}
		
		void operator *= (const matrix<T>& b){ // matrix<T>& operator *= (const matrix<T>& b)
			assert(nc == b.nr);
			int mm = nr, pp = nc, nn = b.nc;
			int i, j, k;
			matrix<T> c(mm, nn);
			for (i=0; i<mm; ++i)
				for (j=0; j<nn; ++j)
					for (k=0; k<pp; ++k)
						c[i][j] += a[i][k]*b[k][j];
					*this = c;
			}
		
		// functions
		void resize(int _m, int _n){ // matrix<T>& resize(int m, int n)                // resize, no copy ???
			if ( (_m == nr) && (_n == nc) )
				return;
			
			matrix<T> b(_m,_n);
			*this = b;
			}
		
		void clear(){                                  // clear
			if (a!=0)
				delete[] a;   // invoke vector destructor ???
			nr=nc=0;
			}
		
		void push_back(const vector<T>& v){ // vector<T>& push_back(vector<T>& v)             // append a new row
			assert (nc==0 || nc==v.size());
			nc = v.size();          
			matrix<T> b(nr+1,nc);
			int i,j;
			for (i=0; i<nr; i++)
				for (j=0; j<nc; j++)
					b[i][j] = a[i][j];
				for (j=0; j<nc; j++)
					b[nr][j] = v[j];
				*this = b;   // invoke vector destructor ???
			}
		
		int m() const { 
			return nr; 
			}                   // retrieve dimensions
		int n() const { 
			return nc; 
			}
	};

template<class T> matrix<T> operator *(const matrix<T>& a, const T b) {
	matrix<T> c = a;
	c *= b;
	return c;
	}

template<class T> matrix<T> operator *(const T a, const matrix<T>& b) {
	return b*a;
	}

template<class T> matrix<T> operator *(const matrix<T>& a, const matrix<T>& b) {
	matrix<T> c = a;
	c *= b;
	return c;
	}


// vector * matrix
template<class T> vector<T> operator *(const vector<T>& v, const matrix<T>& a) {
	int m = a.m();
	int n = a.n();
	assert(v.size()==m);
	vector<T> u(n);
	for (int j=0; j<n; j++){
		u[j] = 0.0;
		for (int i=0; i<m; i++)
			u[j] += v[i]*a[i][j];
		}
	return u;
	}

template<class T> vector<T> operator *(const matrix<T>& a, const vector<T>& v){
	int m = a.m();
	int n = a.n();
	assert(v.size()==n);
	vector<T> u(m);
	for (int i=0; i<m; i++) {
		u[i] = 0.0;
		for (int j=0; j<n; j++)
			u[i] += a[i][j]*v[j];
		}
	return u;
	}

template<class T> std::ostream& operator<<(std::ostream& ost, matrix<T>& a)
{
	int m = a.m();
	for (int i=0; i<m; ++i)
	  ost << a[i] << std::endl;
	return ost;
}

// -----------------------------------------------------
// Tensor class
//
template<class T> class tensor {
	public:
		int nr;             // number of rows
		int nc;             // number of columns
		int nd;             // number of depth
		matrix<T>* a;       
		
		// constructors
		tensor() : nr(0), nc(0), nd(0), a(0) { 
			}          // default empty
		
		tensor(const tensor<T>& b){  // default copy
			nr=nc=nd=0; 
			*this = b;   // call assgn operator
			}
		
		tensor(int _d, int _m, int _n, const T& c=(T)0){
			nd = _d; 
			nr = _m;
			nc = _n;
			a = 0;
			if (nd>0) {
				a = new matrix<T>[nd];
				for (int i=0; i<nd; i++) 
					a[i].resize(nr,nc);
				}
			*this = c;   // call assgn operator
			}
		
		~tensor()  { 
			if (a != 0) 
				delete[] a;      // invoke matrix destructor???
			}
		
		// assgmt operators
		const tensor<T>& operator = (const tensor<T>& b){     // default assgnmt
			if (this == &b)
				return *this;
			
			if (nd > 0) 
				delete[] a;   // invoke matrix destructor???
			nr = b.m();
			nc = b.n();
			nd = b.d();
			if (nd > 0) 
				a = new matrix<T>[nd];
			for (int i=0; i<nd; i++)
				a[i] = b[i];
			return *this;
			}
		
		const tensor<T>& operator =(const T c) {
			for (int _d=0; _d<nd; _d++)
				for (int i=0; i<nr; i++)
					for (int j=0; j<nc; j++)
						a[_d][i][j] = c;
					return *this;
			}
		
		// other operators
		matrix<T>& operator [] (int i) const {       // subscripting
			return a[i]; 
			}
		
		// template<class T> inline T*** tensor<T>::operator T*** () const { return a; }
		
		// functions
		void resize(int _d, int _m, int _n){ // tensor<T>& resize(int d, int m, int n)      // resize
			tensor<T> b(_d,_m,_n);
			*this = b;
			//return *this; 
			}
		
		void clear(){                                // clear
			if (a != 0)
				delete[] a;   // invoke matrix destructor
			nd=nr=nc=0;
			a = 0;
			}
		
		int m() const { 
			return nr; 
			}                // retrieve dimensions
		int n() const { 
			return nc; 
			}
		int d() const { 
			return nd; 
			}
	};

#endif // _MATRIX_


/* todo - unused ? 
// unary plus    
   
   vector<T> operator +() const { return *this; }      
    
// unary minus    
   
   vector<T> operator - () const               
   {
      vector<T> b(n);
      for (int i=0; i<n; i++)
         b[i] = -v[i];
      return b;
   }
   
// equality

   bool operator == (const vector<T>& b)
   {
      if (n != b.size())
         return false;

      for (int i=0; i<n; i++) 
         if (! (v[i] == b[i]))
            return false;

      return true;
   }


// add and assign    
   
   void operator += (const T c)           
   {
      for (int i=0; i<n; i++)
         v[i] += c;
      //return *this;
   }

   void operator += (const vector<T>& b) //const vector<T>& operator += (const vector<T>& b)
   {
      for (int i=0; i<n; i++)
         v[i] += b[i];
      //return *this;
   }
    
// subtract and assign    
   
   void operator -= (const T c) // const vector<T>& operator -= (const T c)           
   {
      for (int i=0; i<n; i++)
         v[i] -= c;
      //return *this;
   }

   void operator -= (const vector<T>& b) // const vector<T>& operator -= (const vector<T>& b)
   {
      for (int i=0; i<n; i++)
         v[i] -= b[i];
      //return *this;
   }
    
// multiply and assign    
   
   void operator *= (const T c) // const vector<T>& operator *= (const T c)             
   {
      for (int i=0; i<n; i++)
         v[i] *= c;
      // return *this;
   }
*/
//   bool empty() const { return n==0; } 
// multiplication
/*
template<class T> vector<T> operator *(const vector<T>& v, const T c) 
{
   vector<T> u = v;
   u *= c;
   return u;
}

template<class T> vector<T> operator *(const T c, const vector<T>& v) 
{
   return v*c;
}
*/
// dot product
/* todo - unused ? 
template<class T> T operator *(const vector<T>& u, const vector<T>& v) 
{
   assert(u.size() == v.size());       
   T sum = 0.0;
   for (int i=0; i<v.size(); i++)
      sum += u[i]*v[i];
   return sum;
}

// division

template<class T> vector<T> operator / (const vector<T>& v, const T c) 
{
   vector<T> u(v);
   for (int i=0; i<u.size(); i++)
      u[i] /= c;
   return u;
}

// absolute values

template<class T> vector<T> abs(const vector<T>& v)   // complex ???
{
   vector<T> u(v);
   for (int i=0; i<u.size(); i++)
      u[i] = fabs(u[i]);
   return u;
}

// maximal element

template<class T> T fqv_max(const vector<T>& v) 
{
   T vm = v[0];
   for (int i=0; i<v.size(); i++)
      vm = (vm>v[i]) ? vm : v[i];
   return vm;
}

// summation

template<class T> T sum(const vector<T>& v)
{
   T sm = 0.0;
   for (int i=0; i<v.size(); i++)
      sm += v[i];
   return sm;
}

template<class T>
std::ostream& operator<< (std::ostream& out, const vector<T>& vec)
{
	out << '[';
	for ( int i=0; i<vec.size(); ++i )
		out << (i ? ", " : "") << vec[i];
	out << ']';
	return out;
}
*/
// addition
/* wtf does anyone use this?
template<class T> vector<T> operator +(const vector<T>& v, const T c)
{
   vector<T> u = v;
   u += c;
   return u;
}

template<class T> vector<T> operator +(const T c, const vector<T>& v)  
{
   return v+c;
}
*/
/* todo - unused ? 
template<class T> vector<T> operator +(const vector<T>& u, const vector<T>& v)  
{
   assert(u.size() == v.size());
   vector<T> z = u;
   z += v;
   return z;
}
*/
// subtraction
/*
template<class T> vector<T> operator -(const vector<T>& v, const T c)  
{
   return v+(-c);
}

template<class T> vector<T> operator - (const T c, const vector<T>& v)  
{
   return -(v-c);
}
*/

/* TODO - unused ??? 
// append a vector
   void push_back (const vector<T>& u) // const vector<T>& push_back (const vector<T>& u)             
   {
      vector<T> b(n+u.size());
      int i;

      for (i=0; i<n; i++)
         b[i] = v[i];
      for (i=0; i<u.size(); i++)
         b[n+i] = u[i];
      *this = b;
      //return *this;
   }

// extract a sub-vector
   vector<T> slice (int k, int m)             
   {
      assert (k>=0 && k+m<=n);
      vector<T> b(m);
      for (int i=0; i<m; i++)
         b[i] = v[k+i];
      return b;
   }
*/

/* todo - unused 
    matrix<T> operator + () const { return *this; }      // unary plus
    
    matrix<T> operator - () const               // unary minus
    {
       matrix<T> b(nr,nc);
       for (int i=0; i<nr; i++)
          for (int j=0; j<nc; j++)
             b[i][j] = -a[i][j];
       return b;
    }
    
    void operator += (const T c) // matrix<T>& operator += (const T c) // add and assign
    {
       for (int i=0; i<nr; i++)
          for (int j=0; j<nc; j++)
             a[i][j] += c;
       //return *this;
    }

    void operator += (const matrix<T>& b) // matrix<T>& operator += (const matrix<T>& b)
    {
       for (int i=0; i<nr; i++)
          for (int j=0; j<nc; j++)
             a[i][j] += b[i][j];
       // return *this;
    }
    
    void operator -= (const T c) // matrix<T>& operator -= (const T c)           // subtract and assign
    {
       for (int i=0; i<nr; i++)
          for (int j=0; j<nc; j++)
             a[i][j] -= c;
       // return *this;
    }

    void operator -= (const matrix<T>& b) // matrix<T>& operator -= (const matrix<T>& b)
    {
       for (int i=0; i<nr; i++)
          for (int j=0; j<nc; j++)
             a[i][j] -= b[i][j];
       // return *this;
    }
    
    void operator *= (const T c) // matrix<T>& operator *= (const T c)              // multiply and assign
    {
       for (int i=0; i<nr; i++)
          for (int j=0; j<nc; j++)
             a[i][j] *= c;
       // return *this;
    }
*/
/* todo - unused ? 
    matrix<T> t() const                            // transpose
    {
       matrix<T> b(nc,nr);
       for (int i=0; i<nc; i++)
          for (int j=0; j<nr; j++)
             b[i][j] = a[j][i];
       return b;
    }

    matrix<T> sub(int k, int m, int l, int n)      // submatrix
    {
       assert(k+m<=nr && l+n<=nc);
       matrix<T> b(m,n);
       for (int i=0; i<m; i++)
          for (int j=0; j<n; j++)
             b[i][j] = a[k+i][l+j];
       return b;
    }

    vector<T> diag()                        // diagonal vector
    {
       assert (nr==nc);
       vector<T> d(nr);
       for (int i=0; i<nr; i++)
          d[i] = a[i][i];
       return d;
    }
*/
/* todo - unused ?
    int size() const { assert(nr==nc); return nr; }
*/
/* todo - unused ? 
// operators as global functions
template<class T> matrix<T> operator +(const matrix<T>& a, const T b) 
{
   matrix<T> c = a;
   for (int i=0; i<c.m(); i++)
      for (int j=0; j<c.n(); j++)
         c[i][j] += b;
   return c;
}

template<class T> matrix<T> operator +(const T a, const matrix<T>& b) 
{
   return b+a;
}

template<class T> matrix<T> operator +(const matrix<T>& a, const matrix<T>& b) 
{
   assert(a.m()==b.m() && a.n()==b.n());
    matrix<T> c = a;
    for (int i=0; i<c.m(); i++)
      for (int j=0; j<c.n(); j++)
         c[i][j] += b[i][j];
   return c;
}

template<class T> matrix<T> operator -(const matrix<T>& a, const T b) 
{
   return a+(-b);
}

template<class T> matrix<T> operator -(const T a, const matrix<T>& b) {
   return -(b-a);
}

template<class T> matrix<T> operator -(const matrix<T>& a, const matrix<T>& b) {
   return a+(-b);
}
*/

/* todo - unused ?
// col vector * row vector
template<class T> matrix<T> mul(const vector<T>& u, const vector<T>& v) 
{
   int m = u.size();
   int n = v.size();
   matrix<T> a(m,n);
   for (int i=0; i<m; i++)
      for (int j=0; j<n; j++)
         a[i][j] = u[i]*v[j];
   return a;
}

template<class T> vector<T> diag(const matrix<T>& a)
{
   assert(a.m()==a.n());
   vector<T> v(a.n());
   for (int i=0; i<a.n(); i++)
      v[i] = a[i][i];
   return v;
}

template<class T> matrix<T> diag(const vector<T>& v)
{
   int n = v.size();
   matrix<T> a(n,n);
   for (int i=0; i<n; i++)
      a[i][i] = v[i];
   return a;
}

template<class T> matrix<T> diag(int n, const T c)
{
    matrix<T> a(n,n);
    for (int i=0; i<n; i++)
       a[i][i] = c;
    return a;
}

template<class T>
std::ostream& operator<< (std::ostream& out, const matrix<T>& mat)
{
	out << '[';
	for ( int i=0; i<mat.nr; ++i )
		out << (i ? "\n " : "") << mat[i];
	out << ']';
	return out;
}
*/

}