feisty meow concerns codebase  2.140
matrix.h
Go to the documentation of this file.
1 #ifndef MATRIX_CLASS
2 #define MATRIX_CLASS
3 
4 /*****************************************************************************\
5 * *
6 * Name : matrix *
7 * Author : Chris Koeritz *
8 * *
9 *******************************************************************************
10 * Copyright (c) 1993-$now By Author. This program is free software; you can *
11 * redistribute it and/or modify it under the terms of the GNU General Public *
12 * License as published by the Free Software Foundation; either version 2 of *
13 * the License or (at your option) any later version. This is online at: *
14 * http://www.fsf.org/copyleft/gpl.html *
15 * Please send any updates to: fred@gruntose.com *
16 \*****************************************************************************/
17 
18 #include <basis/array.h>
19 #include <basis/astring.h>
20 #include <basis/functions.h>
21 #include <basis/guards.h>
22 
23 namespace structures {
24 
26 
30 template <class contents>
31 class matrix : protected basis::array<contents>
32 {
33 public:
34  matrix(int rows = 0, int cols = 0, contents *data = NULL_POINTER);
36  matrix(const matrix &to_copy);
37 
38  ~matrix() {}
39 
40  int rows() const { return _rows; }
41  int columns() const { return _cols; }
42 
43  matrix &operator = (const matrix &to_copy);
44 
45  contents &get(int row, int column);
46  const contents &get(int row, int column) const;
48 
49  bool put(int row, int column, const contents &to_put);
51 
52  contents *operator[] (int row);
54 
59  const contents *operator[] (int row) const;
61 
62  matrix submatrix(int row, int column, int rows, int columns) const;
64 
66  void submatrix(matrix &sub, int row, int column, int rows, int cols) const;
68 
69  matrix transpose() const;
71  void transpose(matrix &resultant) const;
73 
78 
79  bool insert_row(int before_row);
81 
83  bool insert_column(int before_column);
85 
86  void reset(int rows = 0, int columns = 0);
88 
89  void redimension(int new_rows, int new_columns);
91 
94  bool zap_row(int row_to_zap);
95  bool zap_column(int column_to_zap);
97 
100 private:
101  int _rows;
102  int _cols;
103 
104  int compute_index(int row, int column) const;
106 };
107 
109 
111 class int_matrix : public matrix<int>
112 {
113 public:
114  int_matrix(int rows = 0, int cols = 0, int *data = NULL_POINTER)
115  : matrix<int>(rows, cols, data) {}
116  int_matrix(const matrix<int> &to_copy) : matrix<int>(to_copy) {}
117 };
118 
120 class string_matrix : public matrix<basis::astring>
121 {
122 public:
123  string_matrix(int rows = 0, int cols = 0, basis::astring *data = NULL_POINTER)
124  : matrix<basis::astring>(rows, cols, data) {}
125  string_matrix(const matrix<basis::astring> &to_copy) : matrix<basis::astring>(to_copy) {}
126 };
127 
129 class double_matrix : public matrix<double>
130 {
131 public:
132  double_matrix(int rows = 0, int cols = 0, double *data = NULL_POINTER)
133  : matrix<double>(rows, cols, data) {}
134  double_matrix(const matrix<double> &to_copy) : matrix<double>(to_copy) {}
135 };
136 
138 
139 // implementation for longer methods...
140 
141 //hmmm: the operations for zapping use extra memory. they could easily
142 // be done as in-place copies.
143 
144 #undef static_class_name
145 #define static_class_name() "matrix"
146  // used in bounds_halt macro.
147 
148 template <class contents>
149 matrix<contents>::matrix(int r, int c, contents *dat)
150 : basis::array<contents>(r*c, dat), _rows(r), _cols(c) {}
151 
152 template <class contents>
154 : basis::array<contents>(0), _rows(0), _cols(0)
155 { *this = to_copy; }
156 
157 template <class contents>
159 {
160  if (&to_copy == this) return *this;
162  _rows = to_copy._rows;
163  _cols = to_copy._cols;
164  return *this;
165 }
166 
167 template <class contents>
169 { return &basis::array<contents>::operator [] (compute_index(r, 0)); }
170 
171 template <class contents>
172 const contents *matrix<contents>::operator[] (int r) const
173 { return &basis::array<contents>::operator [] (compute_index(r, 0)); }
174 
175 template <class contents>
176 const contents &matrix<contents>::get(int r, int c) const
177 { return basis::array<contents>::get(compute_index(r, c)); }
178 
179 template <class contents>
180 contents &matrix<contents>::get(int row, int column)
181 { return basis::array<contents>::operator [] (compute_index(row, column)); }
182 
183 template <class contents>
184 int matrix<contents>::compute_index(int row, int column) const
185 { return column + row * _cols; }
186 
187 template <class contents>
188 void matrix<contents>::reset(int rows_in, int columns_in)
189 {
190  if ( (_rows == rows_in) && (_cols == columns_in) ) {
191  // reuse space, but reset the objects to their initial state.
192  for (int i = 0; i < basis::array<contents>::length(); i++)
193  basis::array<contents>::operator [](i) = contents();
194  return;
195  }
196 
197  _rows = 0;
198  _cols = 0;
200 
201  this->insert(0, rows_in * columns_in);
202  _rows = rows_in;
203  _cols = columns_in;
204 }
205 
206 template <class contents>
207 void matrix<contents>::redimension(int new_rows, int new_columns)
208 {
209  if ( (_rows == new_rows) && (_cols == new_columns) ) return;
210  matrix<contents> new_this(new_rows, new_columns);
211  for (int r = 0; r < basis::minimum(new_rows, rows()); r++)
212  for (int c = 0; c < basis::minimum(new_columns, columns()); c++)
213  new_this[r][c] = (*this)[r][c];
214  *this = new_this;
215 }
216 
217 template <class contents>
218 bool matrix<contents>::put(int row, int column, const contents &to_put)
219 {
220  if ( (row >= rows()) || (column >= columns()) )
221  return false;
222  (operator [](row))[column] = to_put;
223  return true;
224 }
225 
226 template <class contents>
227 matrix<contents> matrix<contents>::submatrix(int row, int column, int rows_in,
228  int columns_in) const
229 {
230  matrix<contents> to_return;
231  submatrix(to_return, row, column, rows_in, columns_in);
232  return to_return;
233 }
234 
235 template <class contents>
236 void matrix<contents>::submatrix(matrix<contents> &sub, int row, int column,
237  int rows_in, int columns_in) const
238 {
239  sub.reset();
240  if ( (row >= rows()) || (row + rows_in >= rows()) ) return;
241  if ( (column >= columns()) || (column + columns_in >= columns()) ) return;
242  sub.reset(rows_in, columns_in);
243  for (int r = row; r < row + rows_in; r++)
244  for (int c = column; c < column + columns_in; c++)
245  sub[r - row][c - column] = (*this)[r][c];
246 }
247 
248 template <class contents>
250 {
251  matrix<contents> to_return;
252  transpose(to_return);
253  return to_return;
254 }
255 
256 template <class contents>
258 {
259  resultant.reset(columns(), rows());
260  for (int i = 0; i < rows(); i++)
261  for (int j = 0; j < columns(); j++)
262  resultant[j][i] = (*this)[i][j];
263 }
264 
265 template <class contents>
267 {
268  basis::array<contents> to_return;
269  if (row >= rows()) return to_return;
270  to_return.reset(columns());
271  for (int i = 0; i < columns(); i++)
272  to_return[i] = get(row, i);
273  return to_return;
274 }
275 
276 template <class contents>
278 {
279  basis::array<contents> to_return;
280  if (column >= columns()) return to_return;
281  to_return.reset(rows());
282  for (int i = 0; i < rows(); i++)
283  to_return[i] = get(i, column);
284  return to_return;
285 }
286 
287 template <class contents>
288 bool matrix<contents>::zap_row(int row_to_zap)
289 {
290  FUNCDEF("zap_row");
291  bounds_halt(row_to_zap, 0, rows() - 1, false);
292  const int start = compute_index(row_to_zap, 0);
293  // this is only safe because the indices are stored in row-major order (which
294  // i hope means the right thing). in any case, the order is like so:
295  // 1 2 3 4
296  // 5 6 7 8
297  // thus we can whack a whole row contiguously.
298  basis::array<contents>::zap(start, start + columns() - 1);
299  _rows--;
300  return true;
301 }
302 
303 template <class contents>
304 bool matrix<contents>::zap_column(int column_to_zap)
305 {
306  FUNCDEF("zap_column");
307  bounds_halt(column_to_zap, 0, columns() - 1, false);
308  // this starts at the end, which keeps the indexes meaningful. otherwise
309  // the destruction interferes with finding the elements.
310  for (int r = rows(); r >= 0; r--) {
311  const int loc = compute_index(r, column_to_zap);
312  basis::array<contents>::zap(loc, loc);
313  }
314  _cols--;
315  return true;
316 }
317 
318 template <class contents>
320 {
321  FUNCDEF("insert_row");
322  bounds_halt(position, 0, rows(), false);
323  // see comment in zap_row for reasoning about the below.
324  basis::array<contents>::insert(compute_index(position, 0), columns());
325  _rows++;
326  // clear out those spaces.
327  for (int c = 0; c < columns(); c++)
328  put(position, c, contents());
329  return true;
330 }
331 
332 template <class contents>
334 {
335  FUNCDEF("insert_column");
336  bounds_halt(position, 0, columns(), false);
337  // similarly to zap_column, we must iterate in reverse.
338  for (int r = rows(); r >= 0; r--)
339  basis::array<contents>::insert(compute_index(r, position), 1);
340  _cols++;
341  // clear out those spaces.
342  for (int r = 0; r < rows(); r++)
343  put(r, position, contents());
344  return true;
345 }
346 
347 #undef static_class_name
348 
349 } //namespace.
350 
351 #endif
352 
Represents a sequential, ordered, contiguous collection of objects.
Definition: array.h:54
outcome insert(int index, int new_indices)
Adds "new_indices" new positions for objects into the array at "index".
Definition: array.h:803
void reset(int number=0, const contents *initial_contents=NULL_POINTER)
Resizes this array and sets the contents from an array of contents.
Definition: array.h:349
const contents & get(int index) const
Accesses individual objects stored in "this" at the "index" position.
Definition: array.h:372
const contents & operator[](int index) const
Synonym for get that provides the expected array indexing syntax.
Definition: array.h:137
outcome zap(int start, int end)
Deletes from "this" the objects inclusively between "start" and "end".
Definition: array.h:769
array & operator=(const array< contents > &copy_from)
Copies the array in "copy_from" into this.
Definition: array.h:353
Provides a dynamically resizable ASCII character string.
Definition: astring.h:35
A matrix of double floating point numbers.
Definition: matrix.h:130
double_matrix(int rows=0, int cols=0, double *data=NULL_POINTER)
Definition: matrix.h:132
double_matrix(const matrix< double > &to_copy)
Definition: matrix.h:134
A matrix of integers.
Definition: matrix.h:112
int_matrix(const matrix< int > &to_copy)
Definition: matrix.h:116
int_matrix(int rows=0, int cols=0, int *data=NULL_POINTER)
Definition: matrix.h:114
Represents a two-dimensional array of objects.
Definition: matrix.h:32
bool zap_column(int column_to_zap)
removes a row or column from the matrix.
Definition: matrix.h:304
contents & get(int row, int column)
Definition: matrix.h:180
matrix(int rows=0, int cols=0, contents *data=NULL_POINTER)
the "data" array must have at least "rows" * "cols" contents in it.
Definition: matrix.h:149
void submatrix(matrix &sub, int row, int column, int rows, int cols) const
like submatrix() above, but stores into the "sub" parameter.
Definition: matrix.h:236
void transpose(matrix &resultant) const
stores the transpose of this matrix in "resultant".
Definition: matrix.h:257
bool insert_row(int before_row)
inserts a row before the "before_" parameter.
Definition: matrix.h:319
matrix submatrix(int row, int column, int rows, int columns) const
returns a submatrix of this one starting at "row" and "column".
Definition: matrix.h:227
bool insert_column(int before_column)
inserts a column before the "before_" parameter.
Definition: matrix.h:333
bool put(int row, int column, const contents &to_put)
stores "to_put" into the matrix at "row" and "column".
Definition: matrix.h:218
int columns() const
Definition: matrix.h:41
void reset(int rows=0, int columns=0)
empties the matrix and changes its size.
Definition: matrix.h:188
matrix & operator=(const matrix &to_copy)
Definition: matrix.h:158
int rows() const
Definition: matrix.h:40
basis::array< contents > get_row(int row)
return the vector at the "row", or an empty array if "row" is invalid.
Definition: matrix.h:266
bool zap_row(int row_to_zap)
Definition: matrix.h:288
contents * operator[](int row)
dangerous: indexes by "row" into the underlying contents.
Definition: matrix.h:168
matrix transpose() const
provides the transposed form of this matrix.
Definition: matrix.h:249
basis::array< contents > get_column(int column)
return the vector at the "column", or an empty array if it's invalid.
Definition: matrix.h:277
const contents & get(int row, int column) const
retrieves the contents from the specified "row" and "column".
Definition: matrix.h:176
void redimension(int new_rows, int new_columns)
changes the size to contain "new_rows" by "new_columns" elements.
Definition: matrix.h:207
matrix(const matrix &to_copy)
Definition: matrix.h:153
A matrix of strings.
Definition: matrix.h:121
string_matrix(int rows=0, int cols=0, basis::astring *data=NULL_POINTER)
Definition: matrix.h:123
string_matrix(const matrix< basis::astring > &to_copy)
Definition: matrix.h:125
#define NULL_POINTER
The value representing a pointer to nothing.
Definition: definitions.h:32
#define FUNCDEF(func_in)
FUNCDEF sets the name of a function (and plugs it into the callstack).
Definition: enhance_cpp.h:57
#define bounds_halt(value, low, high, to_return)
Verifies that "value" is between "low" and "high", inclusive.
Definition: guards.h:60
The guards collection helps in testing preconditions and reporting errors.
Definition: array.h:30
type minimum(type a, type b)
maximum returns the greater of two values.
Definition: functions.h:29
A dynamic container class that holds any kind of object via pointers.
Definition: amorph.h:55