00001 #ifndef __MATRIX_H__
00002 #define __MATRIX_H__
00003
00004 #pragma once
00005
00006 #include <iostream>
00007 #include <cstdlib>
00008 #include <cstring>
00009
00010 template<class Type> class Matrix;
00011
00017 template<class Type>
00018 Matrix<Type> operator* (const Matrix<Type>& left,const Matrix<Type>& right)
00019 {
00020 if (left.n_col != right.n_lin){
00021 std::cerr << "Warning! Ingnoring \"*\" between matrices of sizes (" << left.n_lin << "," << left.n_col << ") and (" << right.n_lin << "," << right.n_col << ").\n";
00022 return Matrix<Type>();
00023 } else {
00024 Matrix<Type> result(left.n_lin, right.n_col, Matrix<Type>::Zero);
00025 for (int i = 0; i < left.n_lin; i++){
00026 for (int j = 0; j < right.n_col; j++){
00027 for (int k = 0; k < left.n_col; k++){
00028 result[i][j] += left[i][k] * right[k][j];
00029 }
00030 }
00031 }
00032 return result;
00033 }
00034 }
00035
00042 template<class Type>
00043 Matrix<Type> operator+ (const Matrix<Type>& left, const Matrix<Type>& right)
00044 {
00045 if (left.n_lin != right.n_lin || left.n_col != right.n_col){
00046 std::cerr << "Warning! Ingnoring \"+\" between matrices of sizes (" << left.n_lin << "," << left.n_col << ") and (" << right.n_lin << "," << right.n_col << ").\n";
00047 return Matrix<Type>();
00048 } else {
00049 Matrix<Type> result(left.n_lin, right.n_col, Matrix<Type>::Zero);
00050 for (int i = 0; i < left.n_lin; i++){
00051 for (int j = 0; j < right.n_col; j++){
00052 result[i][j] = left[i][j] + right[i][j];
00053 }
00054 }
00055 return result;
00056 }
00057 }
00058
00064 template<class Type>
00065 Matrix<Type> operator- (const Matrix<Type>& left, const Matrix<Type>& right)
00066 {
00067 if (left.n_lin != right.n_lin || left.n_col != right.n_col){
00068 std::cerr << "Warning! Ingnoring \"+\" between matrices of sizes (" << left.n_lin << "," << left.n_col << ") and (" << right.n_lin << "," << right.n_col << ").\n";
00069 return Matrix<Type>();
00070 } else {
00071 Matrix<Type> result(left.n_lin, right.n_col, Matrix<Type>::Zero);
00072 for (int i = 0; i < left.n_lin; i++){
00073 for (int j = 0; j < right.n_col; j++){
00074 result[i][j] = left[i][j] - right[i][j];
00075 }
00076 }
00077 return result;
00078 }
00079 }
00080
00086 template<class Type>
00087 std::istream& operator>> (std::istream& in, Matrix<Type> &right)
00088 {
00089 for (int i = 0; i < right.n_lin; i++){
00090 for (int j = 0; j < right.n_col; j++){
00091 in >> right[i][j];
00092 }
00093 }
00094 return in;
00095 }
00096
00102 template<class Type>
00103 std::ostream& operator<< (std::ostream& out, Matrix<Type> right)
00104 {
00105 for (int i = 0; i < right.n_lin; i++){
00106 for (int j = 0; j < right.n_col; j++){
00107 out << (j == 0 ? "" : " ") << right[i][j];
00108 }
00109 out << std::endl;
00110 }
00111 return out;
00112 }
00113
00114 template <class Type>
00115 class Matrix{
00116 private:
00117 int n_lin, n_col;
00118 Type* m;
00119
00120 void deallocate()
00121 {
00122 if (n_lin | n_col){
00123 delete[] m;
00124 n_lin = n_col = 0;
00125 }
00126 }
00127
00128 void allocate(int init)
00129 {
00130 m = new Type[n_lin*n_col];
00131 if (init == Zero){
00132
00133 memset(m, 0x00, sizeof(Type)*n_col*n_lin);
00134 } else if (init == Unit && n_lin == n_col){
00135
00136 memset(m, 0x00, sizeof(Type)*n_col*n_lin);
00137 for (int i = 0; i < n_lin; i++){
00138 m[i*n_col+i] = 1;
00139 }
00140 }
00141 }
00142
00143 void allocate(const Matrix<Type>& right)
00144 {
00145 m = new Type[n_lin*n_col];
00146 memcpy(m, right.m, sizeof(Type)*n_col*n_lin);
00147 }
00148
00149 public:
00155 Matrix(int n_lin, int n_col, int init = None):
00156 n_lin(n_lin),
00157 n_col(n_col)
00158 {
00159 if (n_lin > 0 && n_col > 0){
00160 allocate(init);
00161 } else {
00162 n_lin = 0;
00163 n_col = 0;
00164 m = NULL;
00165 }
00166 }
00167
00171 Matrix(const Matrix<Type>& right):
00172 n_lin(right.n_lin),
00173 n_col(right.n_col)
00174 {
00175 allocate(right);
00176 }
00177
00180 Matrix():
00181 n_lin(0),
00182 n_col(0),
00183 m(NULL)
00184 {
00185 }
00186
00189 inline int get_n_lin() const {
00190 return n_lin;
00191 }
00192
00195 inline int get_n_col() const {
00196 return n_col;
00197 }
00198
00199 ~Matrix()
00200 {
00201 deallocate();
00202 }
00203
00206 static const int Zero = 0;
00209 static const int Unit = 1;
00212 static const int None = 2;
00213
00221 Matrix<Type> submatrix(int start_lin, int start_col, int n_lines, int n_columns) const
00222 {
00223 if (start_lin + n_lines > n_lin || start_col + n_columns > n_col){
00224 std::cerr << "Error! Request for sumatrix of size (" << n_lines << "," << n_columns << ") exceeds size of original matrix!\n";
00225 return Matrix<Type>();
00226 } else {
00227 Matrix<Type> result(n_lines, n_columns);
00228 for (int i = 0; i < n_lines; i++){
00229 for (int j = 0; j < n_columns; j++){
00230 result[i][j] = m[(start_lin+i)*n_col+start_col+j];
00231 }
00232 }
00233 return result;
00234 }
00235 }
00236
00243 Matrix<Type>& copy(int start_lin, int start_col, const Matrix<Type>& source)
00244 {
00245 if (start_lin + source.n_lin > n_lin || start_col + source.n_col > n_col){
00246 std::cerr << "Error! Copy-ing matrix of size (" << source.n_lin << "," << source.n_col << ") will exceed size of original matrix!\n";
00247 } else {
00248 for (int i = 0; i < source.n_lin; i++){
00249 for (int j = 0; j < source.n_col; j++){
00250 m[(i+start_lin)*n_col+j+start_col] = source[i][j];
00251 }
00252 }
00253 }
00254 return (*this);
00255 }
00256
00259 inline Type* operator[](int line) const
00260 {
00261 return m+line*n_col;
00262 }
00263
00268 Matrix<Type>& operator= (const Matrix<Type>& right)
00269 {
00270 if (this != &right){
00271 if (n_lin > 0 && n_col > 0){
00272 deallocate();
00273 }
00274 n_lin = right.n_lin;
00275 n_col = right.n_col;
00276 allocate(right);
00277 }
00278 return (*this);
00279 }
00280
00285 Matrix<Type>& operator+= (const Matrix<Type>& right)
00286 {
00287 if (this == &right){
00288 std::cerr << "Error! Ignoring increment with self! Try m=m+m instead of m+=m!\n";
00289 } else if (n_lin != right.n_lin || n_col != right.n_col){
00290 std::cerr << "Warning! Ingnoring \"+=\" between matrices of sizes (" << n_lin << "," << n_col << ") and (" << right.n_lin << "," << right.n_col << ").\n";
00291 } else {
00292 for (int i = 0; i < n_lin; i++){
00293 for (int j = 0; j < n_col; j++){
00294 m[i*n_col+j] += right[i][j];
00295 }
00296 }
00297 }
00298 return (*this);
00299 }
00300
00305 Matrix<Type>& operator-= (const Matrix<Type>& right)
00306 {
00307 if (this == &right){
00308 std::cerr << "Error! Ignoring decrement by self! Try m=m-m instead of m-=m!\n";
00309 } else if (n_lin != right.n_lin || n_col != right.n_col){
00310 std::cerr << "Warning! Ingnoring \"-=\" between matrices of sizes (" << n_lin << "," << n_col << ") and (" << right.n_lin << "," << right.n_col << ").\n";
00311 } else {
00312 for (int i = 0; i < n_lin; i++){
00313 for (int j = 0; j < n_col; j++){
00314 m[i*n_col+j] -= right[i][j];
00315 }
00316 }
00317 }
00318 return (*this);
00319 }
00320
00321 friend std::istream& operator>> <>(std::istream&, Matrix<Type>& right);
00322 friend std::ostream& operator<< <>(std::ostream&, const Matrix<Type> right);
00323 friend Matrix<Type> operator* <>(const Matrix<Type>& left, const Matrix<Type>& right);
00324 friend Matrix<Type> operator+ <>(const Matrix<Type>& left, const Matrix<Type>& right);
00325 friend Matrix<Type> operator- <>(const Matrix<Type>& left, const Matrix<Type>& right);
00326 };
00327
00328 #endif
00329