matrix.cpp

Go to the documentation of this file.
00001 #ifndef MATRIX_IMPLEMENTATION
00002 #define MATRIX_IMPLEMENTATION
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : matrix                                                            *
00007 *  Author : Chris Koeritz                                                     *
00008 *                                                                             *
00009 *******************************************************************************
00010 * Copyright (c) 1993-$now By Author.  This program is free software; you can  *
00011 * redistribute it and/or modify it under the terms of the GNU General Public  *
00012 * License as published by the Free Software Foundation; either version 2 of   *
00013 * the License or (at your option) any later version.  This is online at:      *
00014 *     http://www.fsf.org/copyleft/gpl.html                                    *
00015 * Please send any updates to: fred@gruntose.com                               *
00016 \*****************************************************************************/
00017 
00018 #include "matrix.h"
00019 
00020 #include <basis/array.cpp>
00021 #include <basis/function.h>
00022 #include <basis/guards.h>
00023 
00024 //hmmm: the operations for zapping use extra memory.  they could easily
00025 //      be done as in-place copies.
00026 
00027 #undef static_class_name
00028 #define static_class_name() "matrix"
00029   // used in bounds_halt macro.
00030 
00031 template <class contents>
00032 matrix<contents>::matrix(int r, int c, contents *dat)
00033 : array<contents>(r*c, dat), _rows(r), _cols(c) {}
00034 
00035 template <class contents>
00036 matrix<contents>::matrix(const matrix<contents> &to_copy)
00037 : array<contents>(0), _rows(0), _cols(0)
00038 { *this = to_copy; }
00039 
00040 template <class contents>
00041 matrix<contents> &matrix<contents>::operator = (const matrix &to_copy)
00042 {
00043   if (&to_copy == this) return *this;
00044   array<contents>::operator = (to_copy);
00045   _rows = to_copy._rows;
00046   _cols = to_copy._cols;
00047   return *this;
00048 }
00049 
00050 template <class contents>
00051 contents *matrix<contents>::operator[] (int r)
00052 { return &array<contents>::operator [] (compute_index(r, 0)); }
00053 
00054 template <class contents>
00055 const contents *matrix<contents>::operator[] (int r) const
00056 { return &array<contents>::operator [] (compute_index(r, 0)); }
00057 
00058 template <class contents>
00059 const contents &matrix<contents>::get(int r, int c) const
00060 { return array<contents>::get(compute_index(r, c)); }
00061 
00062 template <class contents>
00063 contents &matrix<contents>::get(int row, int column)
00064 { return array<contents>::operator [] (compute_index(row, column)); }
00065 
00066 template <class contents>
00067 int matrix<contents>::compute_index(int row, int column) const
00068 { return column + row * _cols; }
00069 
00070 template <class contents>
00071 void matrix<contents>::reset(int rows_in, int columns_in)
00072 {
00073   if ( (_rows == rows_in) && (_cols == columns_in) ) {
00074     // reuse space, but reset the objects to their initial state.
00075     for (int i = 0; i < array<contents>::length(); i++)
00076       array<contents>::operator [](i) = contents();
00077     return;
00078   }
00079 
00080   _rows = 0;
00081   _cols = 0;
00082   array<contents>::reset(0);
00083 
00084   this->insert(0, rows_in * columns_in);
00085   _rows = rows_in;
00086   _cols = columns_in;
00087 }
00088 
00089 template <class contents>
00090 void matrix<contents>::redimension(int new_rows, int new_columns)
00091 {
00092   if ( (_rows == new_rows) && (_cols == new_columns) ) return;
00093   matrix<contents> new_this(new_rows, new_columns);
00094   for (int r = 0; r < minimum(new_rows, rows()); r++)
00095     for (int c = 0; c < minimum(new_columns, columns()); c++)
00096       new_this[r][c] = (*this)[r][c];
00097   *this = new_this;
00098 }
00099 
00100 template <class contents>
00101 bool matrix<contents>::put(int row, int column, const contents &to_put)
00102 {
00103   if ( (row >= rows()) || (column >= columns()) )
00104     return false;
00105   (operator [](row))[column] = to_put;
00106   return true;
00107 }
00108 
00109 template <class contents>
00110 matrix<contents> matrix<contents>::submatrix(int row, int column, int rows_in,
00111     int columns_in) const
00112 {
00113   matrix<contents> to_return;
00114   submatrix(to_return, row, column, rows_in, columns_in);
00115   return to_return;
00116 }
00117 
00118 template <class contents>
00119 void matrix<contents>::submatrix(matrix<contents> &sub, int row, int column,
00120     int rows_in, int columns_in) const
00121 {
00122   sub.reset();
00123   if ( (row >= rows()) || (row + rows_in >= rows()) ) return;
00124   if ( (column >= columns()) || (column + columns_in >= columns()) ) return;
00125   sub.reset(rows_in, columns_in);
00126   for (int r = row; r < row + rows_in; r++)
00127     for (int c = column; c < column + columns_in; c++)
00128       sub[r - row][c - column] = (*this)[r][c];
00129 }
00130 
00131 template <class contents>
00132 matrix<contents> matrix<contents>::transpose() const
00133 {
00134   matrix<contents> to_return;
00135   transpose(to_return);
00136   return to_return;
00137 }
00138 
00139 template <class contents>
00140 void matrix<contents>::transpose(matrix<contents> &resultant) const
00141 {
00142   resultant.reset(columns(), rows());
00143   for (int i = 0; i < rows(); i++)
00144     for (int j = 0; j < columns(); j++)
00145       resultant[j][i] = (*this)[i][j];
00146 }
00147 
00148 template <class contents>
00149 array<contents> matrix<contents>::get_row(int row)
00150 {
00151   array<contents> to_return;
00152   if (row >= rows()) return to_return;
00153   to_return.reset(columns());
00154   for (int i = 0; i < columns(); i++)
00155     to_return[i] = get(row, i);
00156   return to_return;
00157 }
00158 
00159 template <class contents>
00160 array<contents> matrix<contents>::get_column(int column)
00161 {
00162   array<contents> to_return;
00163   if (column >= columns()) return to_return;
00164   to_return.reset(rows());
00165   for (int i = 0; i < rows(); i++)
00166     to_return[i] = get(i, column);
00167   return to_return;
00168 }
00169 
00170 template <class contents>
00171 bool matrix<contents>::zap_row(int row_to_zap)
00172 {
00173   FUNCDEF("zap_row");
00174   bounds_halt(row_to_zap, 0, rows() - 1, false);
00175   const int start = compute_index(row_to_zap, 0);
00176   // this is only safe because the indices are stored in row-major order (which
00177   // i hope means the right thing).  in any case, the order is like so:
00178   //   1 2 3 4
00179   //   5 6 7 8
00180   // thus we can whack a whole row contiguously.
00181   array<contents>::zap(start, start + columns() - 1);
00182   _rows--;
00183   return true;
00184 }
00185 
00186 template <class contents>
00187 bool matrix<contents>::zap_column(int column_to_zap)
00188 {
00189   FUNCDEF("zap_column");
00190   bounds_halt(column_to_zap, 0, columns() - 1, false);
00191   // this starts at the end, which keeps the indexes meaningful.  otherwise
00192   // the destruction interferes with finding the elements.
00193   for (int r = rows(); r >= 0; r--) {
00194     const int loc = compute_index(r, column_to_zap);
00195     array<contents>::zap(loc, loc);
00196   }
00197   _cols--;
00198   return true;
00199 }
00200 
00201 template <class contents>
00202 bool matrix<contents>::insert_row(int position)
00203 {
00204   FUNCDEF("insert_row");
00205   bounds_halt(position, 0, rows(), false);
00206   // see comment in zap_row for reasoning about the below.
00207   array<contents>::insert(compute_index(position, 0), columns());
00208   _rows++;
00209   // clear out those spaces.
00210   for (int c = 0; c < columns(); c++)
00211     put(position, c, contents());
00212   return true;
00213 }
00214 
00215 template <class contents>
00216 bool matrix<contents>::insert_column(int position)
00217 {
00218   FUNCDEF("insert_column");
00219   bounds_halt(position, 0, columns(), false);
00220   // similarly to zap_column, we must iterate in reverse.
00221   for (int r = rows(); r >= 0; r--)
00222     array<contents>::insert(compute_index(r, position), 1);
00223   _cols++;
00224   // clear out those spaces.
00225   for (int r = 0; r < rows(); r++) 
00226     put(r, position, contents());
00227   return true;
00228 }
00229 
00230 #undef static_class_name
00231 
00232 #endif
00233 

Generated on Fri Nov 28 04:29:12 2008 for HOOPLE Libraries by  doxygen 1.5.1