bjaspan@athena.mit.edu (Barr3y Jaspan) (04/30/91)
Here is a general n x m Matrix class for C++. It has been tested on a VAX running (mostly) BSD with g++, on an IBM RT running AOS4.3 with cfront, and on a DECstation 3100 with g++. Your mileage may vary. The shar file contains Matrix.C and Matrix.H. -- Barr3y Jaspan, bjaspan@mit.edu #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 1)." # Contents: Matrix.C Matrix.H # Wrapped by bjaspan@portnoy on Tue Apr 30 00:25:26 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'Matrix.C' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Matrix.C'\" else echo shar: Extracting \"'Matrix.C'\" \(6727 characters\) sed "s/^X//" >'Matrix.C' <<'END_OF_FILE' X/* X * C++ class for MxN matrices. X * X * $Id: Matrix.C,v 1.6 91/04/14 18:27:48 bjaspan Exp $ X */ X X X/* X * (1) An m x n matrix has m rows and n columns -- ie height x width. X * X * (2) nam == 1 --> nothing else is guaranteed (some code here might X * violate that.. sigh) X * X * (3) Two NAM's are equal. X */ X X#include <stdio.h> X#include <stdlib.h> X#include <stdarg.h> X#include "Matrix.H" X XMatrix *Matrix::M_NAM = Matrix::MakeNAM(); X X/* Constructors */ X Xvoid Matrix::Init(const int m, const int n) X{ X M_m = m; X M_n = n; X nam = 0; X d = new double[m*n]; X} X XMatrix::Matrix() X{ X nam = 1; X M_m = M_n = 0; X d = 0; X} X XMatrix::Matrix(int m, int n) X{ X Init(m, n); X} X XMatrix::Matrix(int m, int n, double first ...) X{ X int i; X va_list ap; X X Init(m, n); X X d[0] = first; X va_start(ap, first); X for (i=1; i < m*n; i += 1) X d[i] = va_arg(ap, double); X} X XMatrix::Matrix(int m, int n, int first ...) X{ X int i; X va_list ap; X X Init(m, n); X X d[0] = double(first); X va_start(ap, first); X for (i=1; i < m*n; i += 1) X d[i] = double(va_arg(ap, int)); X} X XMatrix::Matrix(int m, int n, int *array) X{ X int i; X X Init(m, n); X for (i=0; i < (m*n); i += 1) X d[i] = double(array[i]); X} X XMatrix::Matrix(int m, int n, double *array) X{ X int i; X X Init(m, n); X for (i=0; i < (m*n); i += 1) X d[i] = array[i]; X} X XMatrix::Matrix(const Matrix& m1) X{ X int i; X X Init(m1.M_m, m1.M_n); X for (i=0; i < (M_m*M_n); i += 1) X d[i] = m1.d[i]; X} X XMatrix::Matrix(const Matrix& m1, int r, int c, int m, int n) X{ X int i,j; X X if (r<1 || c<1 || m1.Rows() < r-1+m || m1.Cols() < c-1+n) X nam = 1; X else { X Init(m,n); X X for (i=1;i<=m;i++) X for (j=1;j<=n;j++) X (*this)(i,j) = m1(r+i-1,c+j-1); X } X} X XMatrix::~Matrix() X{ X delete [M_m*M_n] d; X} X X/* Overloaded operators */ X Xint operator==(const Matrix& m1, const Matrix& m2) X{ X int i; X X if (m1.nam != m2.nam) X return 0; X if (m1.nam == 1) X return 1; X if (! m1.SameSize(m2)) X return 0; X X for (i = 0; i < m1.M_m*m1.M_n; i++) X if (m1.d[i] != m2.d[i]) X return 0; X X return 1; X} X XMatrix operator+(const Matrix& m1, const Matrix& m2) X{ X if (m1.M_m != m2.M_m || m1.M_n != m2.M_n || X m1 == Matrix::NAM() || m2 == Matrix::NAM()) X return Matrix::NAM(); X X Matrix m(m1); X X for (int i=0; i < (m1.M_m*m1.M_n); i++) X m.d[i] += m2.d[i]; X X return m; X} X XMatrix operator-(const Matrix& m1, const Matrix& m2) X{ X if (m1.M_m != m2.M_m || m1.M_n != m2.M_n || X m1 == Matrix::NAM() || m2 == Matrix::NAM()) X return Matrix::NAM(); X X Matrix m(m1); X X for (int i=0; i < (m1.M_m*m1.M_n); i++) X m.d[i] -= m2.d[i]; X X return m; X} X XMatrix operator*(const Matrix& m1, const Matrix& m2) X{ X if (m1.M_n != m2.M_m || m1 == Matrix::NAM() || m2 == Matrix::NAM()) X return Matrix::NAM(); X X Matrix m(m1.M_m, m2.M_n); X double val = 0.0; X X for (int i=1; i <= m1.M_m; i += 1) X for (int j=1; j <= m2.M_n; j += 1) { X m(i, j) = 0.0; X for (int k=1; k <= m1.M_n; k += 1) X m(i, j) += m1(i, k) * m2(k, j); X } X X return m; X} X XMatrix& Matrix::operator+=(const Matrix& m) X{ X if (M_m != m.M_m || M_n != m.M_n || *this == Matrix::NAM() || X m == Matrix::NAM()) X nam = 1; X else X for (int i=0; i < (M_m*M_n); i++) X d[i] += m.d[i]; X X return *this; X} X XMatrix& Matrix::operator-=(const Matrix& m) X{ X if (M_m != m.M_m || M_n != m.M_n || *this == Matrix::NAM() || X m == Matrix::NAM()) X nam = 1; X else X for (int i=0; i < (M_m*M_n); i++) X d[i] -= m.d[i]; X X return *this; X} X XMatrix operator*(double k, const Matrix& m) X{ X Matrix n(m); X int i; X X for (i=0;i<n.M_m*n.M_n;i++) n.d[i]*=k; X return(n); X} X XMatrix& Matrix::operator=(const Matrix& m) X{ X nam = m.nam; X X if (nam) X ; X else if (M_m == m.M_m && M_n == m.M_n) X bcopy(m.d, d, M_m*M_n*sizeof(double)); X else if (M_m*M_n == m.M_m*m.M_n) { X bcopy(m.d, d, M_m*M_n*sizeof(double)); X M_m = m.M_m; X M_n = m.M_n; X } else { X delete [M_m*M_n] d; X X M_m = m.M_m; X M_n = m.M_n; X X d = new double[M_m*M_n]; X bcopy(m.d, d, M_m*M_n*sizeof(double)); X } X X return(*this); X} X XMatrix operator|(const Matrix& m1, const Matrix& m2) X // Concatenates two matrices horizontally. Requires that m1 and m2 X // have the same number of rows. X // [ A ] | [ B ] --> [ A | B ] X{ X if (m1.Rows() != m2.Rows() || m1 == Matrix::NAM() || m2 == Matrix::NAM()) X return Matrix::NAM(); X X Matrix m(m1.Rows(), m1.Cols() + m2.Cols()); X int r, c; X X for (r = 1; r <= m1.Rows(); r += 1) X for (c = 1; c <= m1.Cols(); c += 1) X m(r, c) = m1(r, c); X X for (r = 1; r <= m1.Rows(); r += 1) X for (c = 1; c <= m2.Cols(); c += 1) X m(r, c + m1.Cols()) = m2(r, c); X X return m; X} X XMatrix operator&(const Matrix& m1, const Matrix& m2) X // Concatenates two matrices vertically. Requires that m1 and m2 X // have the same number of columns. X // [ A ] X // [ A ] & [ B ] --> [ - ] X // [ B ] X{ X if (m1.Cols() != m2.Cols() || m1 == Matrix::NAM() || m2 == Matrix::NAM()) X return Matrix::NAM(); X X Matrix m(m1.Rows()+m2.Rows(), m1.Cols()); X int r, c; X X for (r = 1; r <= m1.Rows(); r += 1) X for (c = 1; c <= m1.Cols(); c += 1) X m(r, c) = m1(r, c); X for (r = 1; r <= m2.Rows(); r += 1) X for (c = 1; c <= m2.Cols(); c += 1) X m(r + m1.Rows(), c) = m2(r, c); X X#if 0 X // This doesn't work, and I don't know why. X bcopy(m1.d, m.d, m1.Rows()*m1.Cols()*sizeof(double)); X bcopy(m2.d, m.d + m1.Rows()*m1.Cols()*sizeof(double), X m2.Rows()*m2.Cols()*sizeof(double)); X#endif X X return m; X} X Xostream& operator<<(ostream& s, const Matrix& m) X{ X int i,j; X X if (m.nam) { X s << "NAM\n"; X return(s); X } X X for (i = 1; i <= m.M_m; i++) { X for (j = 1; j <= m.M_n; j++) X#ifdef __GNUG__ X s.form("%6.2f ", m(i, j)); X#else X s << form("%6.2f ", m(i, j)); X#endif X s << "\n"; X } X X return(s); X} X X/* Member functions */ X XMatrix Matrix::T() const X{ X Matrix t(M_n, M_m); X X for (int i = 1; i <= M_m; i++) X for (int j = 1; j <= M_n; j++) X t(j, i) = (*this)(i, j); X X return t; X} X Xvoid Matrix::Print() const X{ X cout << *this; X} X X/* Special matrix constructors */ XMatrix *Matrix::MakeNAM() X{ X Matrix *m = new Matrix(1,1); X m->nam = 1; X return m; X} X X/* Matrix mutators */ Xvoid Matrix::Identify() X{ X if (M_m != M_n) { X nam = 1; X return; X } X X for (int i = 1; i <= M_m; i++) X for (int j = 1; j <= M_n; j++) X (*this)(i, j) = 0.0; X X for (i = 1; i <= M_m; i++) X (*this)(i, i) = 1.0; X} END_OF_FILE if test 6727 -ne `wc -c <'Matrix.C'`; then echo shar: \"'Matrix.C'\" unpacked with wrong size! fi # end of 'Matrix.C' fi if test -f 'Matrix.H' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Matrix.H'\" else echo shar: Extracting \"'Matrix.H'\" \(2542 characters\) sed "s/^X//" >'Matrix.H' <<'END_OF_FILE' X#ifndef __MATRIX_H__ X#define __MATRIX_H__ X X/* $Id: Matrix.H,v 1.4 91/04/16 18:03:17 bjaspan Exp $ */ X X#include <assert.h> /* for abort() */ X#include <stream.h> X Xclass Matrix { Xpublic: X /* Constructors */ X Matrix(); X Matrix(int, int); X Matrix(int, int, int *); X Matrix(int, int, double *); X Matrix(int, int, int ...); X Matrix(int, int, double ...); X Matrix(const Matrix&); X Matrix(const Matrix&,int,int,int,int); X ~Matrix(); X X /* Member functions */ X Matrix T() const; X inline int Rows() const; X inline int Cols() const; X inline int SameSize(const Matrix&) const; X inline double& operator()(int, int) const; X inline double *Row(int) const; X void Print() const; X X /* Overloaded operators */ X friend Matrix operator+(const Matrix&, const Matrix&); X friend Matrix operator-(const Matrix&, const Matrix&); X friend Matrix operator*(const Matrix&, const Matrix&); X friend Matrix operator*(double, const Matrix&); X Matrix& operator+=(const Matrix&); X Matrix& operator-=(const Matrix&); X inline friend Matrix& operator*=(Matrix&, const Matrix&); X inline friend Matrix operator/(const Matrix&, double); X friend int operator==(const Matrix&, const Matrix&); X friend Matrix operator|(const Matrix&, const Matrix&); X friend Matrix operator&(const Matrix&, const Matrix&); X Matrix& operator=(const Matrix&); X friend ostream& operator<<(ostream&, const Matrix&); X X /* Special matrix creators */ X static inline const Matrix& NAM(); X X /* Matrix mutators */ X void Identify(); X Xprivate: X void Init(const int, const int); X X static Matrix *M_NAM; X static Matrix *MakeNAM(); X X int M_m, M_n, nam; X double *d; X}; X Xinline int Matrix::Rows() const X{ X return M_m; X} X Xinline int Matrix::Cols() const X{ X return M_n; X} X Xinline Matrix& operator*=(Matrix& m1, const Matrix& m) X{ X return(m1 = m1*m); X} X Xinline Matrix operator/(const Matrix& m, double k) X{ X return((1.0/k)*m); X} X Xinline double& Matrix::operator()(int m, int n) const X{ X /* My kingdom for exception handling ... */ X if (m > M_m || n > M_n || m < 1 || n < 1) X abort(); X X return d[M_n*(m-1) + n - 1]; X} X Xinline double *Matrix::Row(int r) const X{ X return(d+(r-1)*M_n); X} X Xinline const Matrix& Matrix::NAM() X{ X return *Matrix::M_NAM; X} X Xinline int Matrix::SameSize(const Matrix& m) const X{ X return (M_m == m.M_m && M_n == m.M_n); X} X X/* DO NOT ADD ANYTHING AFTER THIS #endif */ X#endif /* __MATRIX_H__ */ END_OF_FILE if test 2542 -ne `wc -c <'Matrix.H'`; then echo shar: \"'Matrix.H'\" unpacked with wrong size! fi # end of 'Matrix.H' fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have the archive. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0