GestureRecognitionToolkit  Version: 0.2.0
The Gesture Recognition Toolkit (GRT) is a cross-platform, open-source, c++ machine learning library for real-time gesture recognition.
Matrix.h
Go to the documentation of this file.
1 
8 /*
9  GRT MIT License
10  Copyright (c) <2012> <Nicholas Gillian, Media Lab, MIT>
11 
12  Permission is hereby granted, free of charge, to any person obtaining a copy of this software
13  and associated documentation files (the "Software"), to deal in the Software without restriction,
14  including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
16  subject to the following conditions:
17 
18  The above copyright notice and this permission notice shall be included in all copies or substantial
19  portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22  LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
24  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26  */
27 
28 #ifndef GRT_MATRIX_HEADER
29 #define GRT_MATRIX_HEADER
30 
31 #include "../Util/GRTTypedefs.h"
32 #include "Vector.h"
33 #include <exception>
34 #include "../Util/GRTException.h"
35 #include "../Util/ErrorLog.h"
36 
37 GRT_BEGIN_NAMESPACE
38 
39 template <class T> class Matrix{
40 public:
44  Matrix():errorLog("[ERROR Matrix]"){
45  rows = 0;
46  cols = 0;
47  size = 0;
48  capacity = 0;
49  dataPtr = NULL;
50  rowPtr = NULL;
51  }
52 
59  Matrix(const unsigned int rows,const unsigned int cols):errorLog("[ERROR Matrix]"){
60  dataPtr = NULL;
61  rowPtr = NULL;
62  resize(rows,cols);
63  }
64 
70  Matrix(const Matrix &rhs):errorLog("[ERROR Matrix]"){
71  this->dataPtr = NULL;
72  this->rowPtr = NULL;
73  this->rows = 0;
74  this->cols = 0;
75  this->size = 0;
76  this->capacity = 0;
77  this->copy( rhs );
78  }
79 
87  Matrix( const Vector< Vector< T > > &data ):errorLog("[ERROR Matrix]"){
88  this->dataPtr = NULL;
89  this->rowPtr = NULL;
90  this->rows = 0;
91  this->cols = 0;
92  this->size = 0;
93  this->capacity = 0;
94 
95  unsigned int tempRows = data.getSize();
96  unsigned int tempCols = 0;
97 
98  //If there is no data then return
99  if( tempRows == 0 ) return;
100 
101  //Check to make sure all the columns are the same size
102  for(unsigned int i=0; i<tempRows; i++){
103  if( i == 0 ) tempCols = data[i].getSize();
104  else{
105  if( data[i].getSize() != tempCols ){
106  return;
107  }
108  }
109  }
110 
111  if( tempCols == 0 ) return;
112 
113  //Resize the matrix and copy the data
114  if( resize(tempRows,tempCols) ){
115  for(unsigned int i=0; i<tempRows; i++){
116  for(unsigned int j=0; j<tempCols; j++){
117  dataPtr[(i*cols)+j] = data[i][j];
118  }
119  }
120  }
121 
122  }
123 
127  virtual ~Matrix(){
128  clear();
129  }
130 
137  Matrix& operator=(const Matrix &rhs){
138  if(this!=&rhs){
139  this->clear();
140  this->copy( rhs );
141  }
142  return *this;
143  }
144 
151  inline T* operator[](const unsigned int r){
152  return rowPtr[r];
153  }
154 
161  inline const T* operator[](const unsigned int r) const{
162  return rowPtr[r];
163  }
164 
171  Vector< T > getRowVector(const unsigned int r) const{
172  Vector< T > rowVector(cols);
173  for(unsigned int c=0; c<cols; c++)
174  rowVector[c] = dataPtr[r*cols+c];
175  return rowVector;
176  }
177 
184  Vector<T> getColVector(const unsigned int c) const{
185  Vector<T> columnVector(rows);
186  for(unsigned int r=0; r<rows; r++)
187  columnVector[r] = dataPtr[r*cols+c];
188  return columnVector;
189  }
190 
200  Vector<T> getConcatenatedVector(const bool concatByRow = true) const{
201 
202  if( rows == 0 || cols == 0 ) return Vector<T>();
203 
204  Vector<T> vectorData(rows*cols);
205 
206  unsigned int i,j =0;
207 
208  if( concatByRow ){
209  for( i=0; i<rows; i++){
210  for(j=0; j<cols; j++){
211  vectorData[ (i*cols)+j ] = dataPtr[i*cols+j];
212  }
213  }
214  }else{
215  for(j=0; j<cols; j++){
216  for(i=0; i<rows; i++){
217  vectorData[ (i*cols)+j ] = dataPtr[i*cols+j];
218  }
219  }
220  }
221 
222  return vectorData;
223  }
224 
232  virtual bool resize(const unsigned int r,const unsigned int c){
233 
234  if( r + c == 0 ){
235  errorLog << "resize(...) - Failed to resize matrix, rows and cols == zero!" << std::endl;
236  return false;
237  }
238 
239  //If the rows and cols are unchanged then do not resize the data
240  if( r == rows && c == cols ){
241  return true;
242  }
243 
244  //Clear any previous memory
245  clear();
246 
247  if( r > 0 && c > 0 ){
248  try{
249  rows = r;
250  cols = c;
251  size = r * c;
252  capacity = r;
253 
254  dataPtr = new T[size];
255  rowPtr = new T*[rows];
256 
257  if( dataPtr == NULL ){
258  rows = 0;
259  cols = 0;
260  size = 0;
261  capacity = 0;
262  errorLog << "resize(const unsigned r,const unsigned int c) - Failed to allocate memory! r: " << r << " c: " << c << std::endl;
263  throw GRT::Exception("Matrix::resize(const unsigned int r,const unsigned int c) - Failed to allocate memory!");
264  return false;
265  }
266 
267  if( rowPtr == NULL ){
268  rows = 0;
269  cols = 0;
270  size = 0;
271  capacity = 0;
272  errorLog << "resize(const unsigned r,const unsigned int c) - Failed to allocate memory! r: " << r << " c: " << c << std::endl;
273  throw Exception("Matrix::resize(const unsigned int r,const unsigned int c) - Failed to allocate memory!");
274  return false;
275  }
276 
277  //Setup the row pointers
278  unsigned int i=0;
279  T *p = &(dataPtr[0]);
280  for(i=0; i<rows; i++){
281  rowPtr[i] = p;
282  p += cols;
283  }
284 
285  return true;
286 
287  }catch( std::exception& e ){
288  errorLog << "resize: Failed to allocate memory. Error: " << e.what() << " rows: " << r << " cols: " << c << std::endl;
289  clear();
290  return false;
291  }catch( ... ){
292  errorLog << "resize: Failed to allocate memory." << std::endl;
293  clear();
294  return false;
295  }
296  }
297  return false;
298  }
299 
306  virtual bool copy( const Matrix<T> &rhs ){
307 
308  if( this != &rhs ){
309 
310  if( this->size != rhs.size ){
311  if( !this->resize( rhs.rows, rhs.cols ) ){
312  throw Exception("Matrix::copy( const Matrix<T> &rhs ) - Failed to allocate resize matrix!");
313  return false;
314  }
315  }
316 
317  //Copy the data
318  unsigned int i = 0;
319  for(i=0; i<size; i++){
320  this->dataPtr[i] = rhs.dataPtr[i];
321  }
322  }
323 
324  return true;
325  }
326 
336  bool setAllValues(const T &value){
337  return setAll( value );
338  }
339 
346  bool setAll(const T &value){
347  if(dataPtr!=NULL){
348  unsigned int i =0;
349  for(i=0; i<size; i++)
350  dataPtr[i] = value;
351  return true;
352  }
353  return false;
354  }
355 
364  bool setRowVector(const Vector<T> &row,const unsigned int rowIndex){
365  if( dataPtr == NULL ) return false;
366  if( row.size() != cols ) return false;
367  if( rowIndex >= rows ) return false;
368 
369  unsigned int j = 0;
370  for(j=0; j<cols; j++)
371  dataPtr[ rowIndex * cols + j ] = row[ j ];
372  return true;
373  }
374 
383  bool setColVector(const Vector<T> &column,const unsigned int colIndex){
384  if( dataPtr == NULL ) return false;
385  if( column.size() != rows ) return false;
386  if( colIndex >= cols ) return false;
387 
388  for(unsigned int i=0; i<rows; i++)
389  dataPtr[ i * cols + colIndex ] = column[ i ];
390  return true;
391  }
392 
401  bool push_back(const Vector<T> &sample){
402 
403  unsigned int i,j = 0;
404 
405  //If there is no data, but we know how many cols are in a sample then we simply create a new buffer of size 1 and add the sample
406  if(dataPtr==NULL){
407  cols = (unsigned int)sample.size();
408  if( !resize(1,cols) ){
409  clear();
410  return false;
411  }
412  for(j=0; j<cols; j++)
413  dataPtr[ j ] = sample[j];
414  return true;
415  }
416 
417  //If there is data and the sample size does not match the number of columns then return false
418  if(sample.size() != cols ){
419  return false;
420  }
421 
422  //Check to see if we have reached the capacity, if not then simply add the new data as there are unused rows
423  if( rows < capacity ){
424  //Add the new sample at the end
425  for(j=0; j<cols; j++)
426  dataPtr[rows * cols + j] = sample[j];
427 
428  }else{ //Otherwise we copy the existing data from the data ptr into a new buffer of size (rows+1) and add the sample at the end
429 
430  const unsigned int tmpRows = rows + 1;
431  T* tmpDataPtr = new T[tmpRows*cols];
432  T** tmpRowPtr = new T*[tmpRows];
433 
434  if( tmpDataPtr == NULL || tmpRowPtr == NULL ){//If NULL then we have run out of memory
435  return false;
436  }
437 
438  //Setup the row pointers
439  T *p = &(tmpDataPtr[0]);
440  for(i=0; i<tmpRows; i++){
441  tmpRowPtr[i] = p;
442  p += cols;
443  }
444 
445  //Copy the original data into the tmp buffer
446  for(i=0; i<rows*cols; i++)
447  tmpDataPtr[i] = dataPtr[i];
448 
449  //Add the new sample at the end of the tmp buffer
450  for(j=0; j<cols; j++)
451  tmpDataPtr[rows*cols+j] = sample[j];
452 
453  //Delete the original data and copy the pointer
454  delete[] dataPtr;
455  delete[] rowPtr;
456  dataPtr = tmpDataPtr;
457  rowPtr = tmpRowPtr;
458 
459  //Increment the capacity so it matches the number of rows
460  capacity++;
461  }
462 
463  //Increment the number of rows
464  rows++;
465 
466  //Update the size
467  size = rows * cols;
468 
469  //Finally return true to signal that the data was added correctly
470  return true;
471  }
472 
480  bool reserve( const unsigned int capacity ){
481 
482  //If the number of columns has not been set, then we can not do anything
483  if( cols == 0 ) return false;
484 
485  //Reserve the data and copy and existing data
486  unsigned int i=0;
487  T* tmpDataPtr = new T[ capacity * cols ];
488  T** tmpRowPtr = new T*[ capacity ];
489  if( tmpDataPtr == NULL || tmpRowPtr == NULL ){//If NULL then we have run out of memory
490  return false;
491  }
492 
493  //Setup the row pointers
494  T *p = &(tmpDataPtr[0]);
495  for(i=0; i<capacity; i++){
496  tmpRowPtr[i] = p;
497  p += cols;
498  }
499 
500  //Copy the existing data into the new memory
501  for(i=0; i<size; i++)
502  tmpDataPtr[i] = dataPtr[i];
503 
504  //Delete the original data and copy the pointer
505  delete[] dataPtr;
506  delete[] rowPtr;
507  dataPtr = tmpDataPtr;
508  rowPtr = tmpRowPtr;
509 
510  //Store the new capacity
511  this->capacity = capacity;
512 
513  //Store the size
514  size = rows * cols;
515 
516  return true;
517  }
518 
522  void clear(){
523  if( dataPtr != NULL ){
524  delete[] dataPtr;
525  dataPtr = NULL;
526  }
527  if( rowPtr != NULL ){
528  delete[] rowPtr;
529  rowPtr = NULL;
530  }
531  rows = 0;
532  cols = 0;
533  size = 0;
534  capacity = 0;
535  }
536 
542  inline unsigned int getNumRows() const{ return rows; }
543 
549  inline unsigned int getNumCols() const{ return cols; }
550 
557  inline unsigned int getCapacity() const{ return capacity; }
558 
564  inline unsigned int getSize() const{ return size; }
565 
571  T** getDataPointer() const{
572  if( rowPtr == NULL ){
573  throw Exception("Matrix::getDataPointer() - Matrix has not been initialized!");
574  }
575  return &(rowPtr[0]);
576  }
577 
583  T* getData() const {
584  return dataPtr;
585  }
586 
587 protected:
588  unsigned int rows;
589  unsigned int cols;
590  unsigned int size;
591  unsigned int capacity;
592  T *dataPtr;
593  T **rowPtr;
594  ErrorLog errorLog;
595 };
596 
597 GRT_END_NAMESPACE
598 
599 #endif //Header guard
void clear()
Definition: Matrix.h:522
unsigned int getSize() const
Definition: Matrix.h:564
The Vector class is a basic class for storing any type of data. The default Vector is an interface fo...
T * operator[](const unsigned int r)
Definition: Matrix.h:151
bool setRowVector(const Vector< T > &row, const unsigned int rowIndex)
Definition: Matrix.h:364
bool setAll(const T &value)
Definition: Matrix.h:346
Matrix(const Matrix &rhs)
Definition: Matrix.h:70
T * getData() const
Definition: Matrix.h:583
unsigned int getCapacity() const
Definition: Matrix.h:557
T ** rowPtr
A pointer to each row in the data.
Definition: Matrix.h:593
Matrix()
Definition: Matrix.h:44
bool setAllValues(const T &value)
Definition: Matrix.h:336
bool reserve(const unsigned int capacity)
Definition: Matrix.h:480
virtual ~Matrix()
Definition: Matrix.h:127
Matrix & operator=(const Matrix &rhs)
Definition: Matrix.h:137
bool setColVector(const Vector< T > &column, const unsigned int colIndex)
Definition: Matrix.h:383
Vector< T > getRowVector(const unsigned int r) const
Definition: Matrix.h:171
unsigned int rows
The number of rows in the Matrix.
Definition: Matrix.h:588
Vector< T > getConcatenatedVector(const bool concatByRow=true) const
Definition: Matrix.h:200
unsigned int getNumRows() const
Definition: Matrix.h:542
unsigned int getNumCols() const
Definition: Matrix.h:549
Matrix(const Vector< Vector< T > > &data)
Definition: Matrix.h:87
T ** getDataPointer() const
Definition: Matrix.h:571
virtual bool copy(const Matrix< T > &rhs)
Definition: Matrix.h:306
unsigned int size
Stores rows * cols.
Definition: Matrix.h:590
Definition: Matrix.h:39
Vector< T > getColVector(const unsigned int c) const
Definition: Matrix.h:184
const T * operator[](const unsigned int r) const
Definition: Matrix.h:161
T * dataPtr
A pointer to the raw data.
Definition: Matrix.h:592
unsigned int cols
The number of columns in the Matrix.
Definition: Matrix.h:589
Matrix(const unsigned int rows, const unsigned int cols)
Definition: Matrix.h:59
virtual bool resize(const unsigned int r, const unsigned int c)
Definition: Matrix.h:232
Definition: Vector.h:41
bool push_back(const Vector< T > &sample)
Definition: Matrix.h:401
unsigned int capacity
The capacity of the Matrix, this will be the number of rows, not the actual memory size...
Definition: Matrix.h:591