| 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;
}
*/
}