GestureRecognitionToolkit  Version: 1.0 Revision: 04-03-15
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 
9 /*
10  GRT MIT License
11  Copyright (c) <2012> <Nicholas Gillian, Media Lab, MIT>
12 
13  Permission is hereby granted, free of charge, to any person obtaining a copy of this software
14  and associated documentation files (the "Software"), to deal in the Software without restriction,
15  including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
17  subject to the following conditions:
18 
19  The above copyright notice and this permission notice shall be included in all copies or substantial
20  portions of the Software.
21 
22  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
23  LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
24  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
25  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27  */
28 
29 #ifndef GRT_MATRIX_HEADER
30 #define GRT_MATRIX_HEADER
31 
32 #include <iostream>
33 #include <iterator> // std::front_inserter
34 #include <algorithm> // std::copy
35 #include <vector>
36 #include "GRTException.h"
37 #include "ErrorLog.h"
38 
39 namespace GRT{
40 
41 template <class T> class Matrix{
42 public:
46  Matrix():errorLog("[ERROR Matrix]"){
47  rows = 0;
48  cols = 0;
49  size = 0;
50  capacity = 0;
51  dataPtr = NULL;
52  rowPtr = NULL;
53  }
54 
61  Matrix(const unsigned int rows,const unsigned int cols):errorLog("[ERROR Matrix]"){
62  dataPtr = NULL;
63  rowPtr = NULL;
64  resize(rows,cols);
65  }
66 
72  Matrix(const Matrix &rhs):errorLog("[ERROR Matrix]"){
73  this->dataPtr = NULL;
74  this->rowPtr = NULL;
75  this->rows = 0;
76  this->cols = 0;
77  this->size = 0;
78  this->capacity = 0;
79  this->copy( rhs );
80  }
81 
89  Matrix(const std::vector< std::vector< T > > &data):errorLog("[ERROR Matrix]"){
90  this->dataPtr = NULL;
91  this->rowPtr = NULL;
92  this->rows = 0;
93  this->cols = 0;
94  this->size = 0;
95  this->capacity = 0;
96 
97  unsigned int tempRows = (unsigned int)data.size();
98  unsigned int tempCols = 0;
99 
100  //If there is no data then return
101  if( tempRows == 0 ) return;
102 
103  //Check to make sure all the columns are the same size
104  for(unsigned int i=0; i<tempRows; i++){
105  if( i == 0 ) tempCols = data[i].size();
106  else{
107  if( data[i].size() != tempCols ){
108  return;
109  }
110  }
111  }
112 
113  if( tempCols == 0 ) return;
114 
115  //Resize the matrix and copy the data
116  if( resize(tempRows,tempCols) ){
117  for(unsigned int i=0; i<tempRows; i++){
118  for(unsigned int j=0; j<tempCols; j++){
119  dataPtr[i][j] = data[i][j];
120  }
121  }
122  }
123 
124  }
125 
129  virtual ~Matrix(){
130  clear();
131  }
132 
139  Matrix& operator=(const Matrix &rhs){
140  if(this!=&rhs){
141  this->clear();
142  this->copy( rhs );
143  }
144  return *this;
145  }
146 
153  inline T* operator[](const unsigned int r){
154  return rowPtr[r];
155  }
156 
163  inline const T* operator[](const unsigned int r) const{
164  return rowPtr[r];
165  }
166 
173  std::vector<T> getRowVector(const unsigned int r) const{
174  std::vector<T> rowVector(cols);
175  for(unsigned int c=0; c<cols; c++)
176  rowVector[c] = dataPtr[r*cols+c];
177  return rowVector;
178  }
179 
186  std::vector<T> getColVector(const unsigned int c) const{
187  std::vector<T> columnVector(rows);
188  for(unsigned int r=0; r<rows; r++)
189  columnVector[r] = dataPtr[r*cols+c];
190  return columnVector;
191  }
192 
202  std::vector<T> getConcatenatedVector(const bool concatByRow = true) const{
203 
204  if( rows == 0 || cols == 0 ) return std::vector<T>();
205 
206  std::vector<T> vectorData(rows*cols);
207 
208  unsigned int i,j =0;
209 
210  if( concatByRow ){
211  for( i=0; i<rows; i++){
212  for(j=0; j<cols; j++){
213  vectorData[ (i*cols)+j ] = dataPtr[i*cols+j];
214  }
215  }
216  }else{
217  for(j=0; j<cols; j++){
218  for(i=0; i<rows; i++){
219  vectorData[ (i*cols)+j ] = dataPtr[i*cols+j];
220  }
221  }
222  }
223 
224  return vectorData;
225  }
226 
234  virtual bool resize(const unsigned int r,const unsigned int c){
235 
236  if( r + c == 0 ){
237  errorLog << "resize(...) - Failed to resize matrix, rows and cols == zero!" << std::endl;
238  return false;
239  }
240 
241  //If the rows and cols are unchanged then do not resize the data
242  if( r == rows && c == cols ){
243  return true;
244  }
245 
246  //Clear any previous memory
247  clear();
248 
249  if( r > 0 && c > 0 ){
250  try{
251  rows = r;
252  cols = c;
253  size = r * c;
254  capacity = r;
255 
256  dataPtr = new T[size];
257  rowPtr = new T*[rows];
258 
259  if( dataPtr == NULL ){
260  rows = 0;
261  cols = 0;
262  size = 0;
263  capacity = 0;
264  errorLog << "resize(const unsigned r,const unsigned int c) - Failed to allocate memory! r: " << r << " c: " << c << std::endl;
265  throw Exception("Matrix::resize(const unsigned int r,const unsigned int c) - Failed to allocate memory!");
266  return false;
267  }
268 
269  if( rowPtr == NULL ){
270  rows = 0;
271  cols = 0;
272  size = 0;
273  capacity = 0;
274  errorLog << "resize(const unsigned r,const unsigned int c) - Failed to allocate memory! r: " << r << " c: " << c << std::endl;
275  throw Exception("Matrix::resize(const unsigned int r,const unsigned int c) - Failed to allocate memory!");
276  return false;
277  }
278 
279  //Setup the row pointers
280  unsigned int i=0;
281  T *p = &(dataPtr[0]);
282  for(i=0; i<rows; i++){
283  rowPtr[i] = p;
284  p += cols;
285  }
286 
287  return true;
288 
289  }catch( std::exception& e ){
290  errorLog << "resize: Failed to allocate memory. Error: " << e.what() << " rows: " << r << " cols: " << c << std::endl;
291  clear();
292  return false;
293  }catch( ... ){
294  errorLog << "resize: Failed to allocate memory." << std::endl;
295  clear();
296  return false;
297  }
298  }
299  return false;
300  }
301 
308  virtual bool copy( const Matrix<T> &rhs ){
309 
310  if( this != &rhs ){
311 
312  if( this->size != rhs.size ){
313  if( !this->resize( rhs.rows, rhs.cols ) ){
314  throw Exception("Matrix::copy( const Matrix<T> &rhs ) - Failed to allocate resize matrix!");
315  return false;
316  }
317  }
318 
319  //Copy the data
320  unsigned int i = 0;
321  for(i=0; i<size; i++){
322  this->dataPtr[i] = rhs.dataPtr[i];
323  }
324  }
325 
326  return true;
327  }
328 
335  bool setAllValues(const T &value){
336  if(dataPtr!=NULL){
337  unsigned int i =0;
338  for(i=0; i<size; i++)
339  dataPtr[i] = value;
340  return true;
341  }
342  return false;
343  }
344 
353  bool setRowVector(const std::vector<T> &row,const unsigned int rowIndex){
354  if( dataPtr == NULL ) return false;
355  if( row.size() != cols ) return false;
356  if( rowIndex >= rows ) return false;
357 
358  unsigned int j = 0;
359  for(j=0; j<cols; j++)
360  dataPtr[ rowIndex * cols + j ] = row[ j ];
361  return true;
362  }
363 
372  bool setColVector(const std::vector<T> &column,const unsigned int colIndex){
373  if( dataPtr == NULL ) return false;
374  if( column.size() != rows ) return false;
375  if( colIndex >= cols ) return false;
376 
377  for(unsigned int i=0; i<rows; i++)
378  dataPtr[ i * cols + colIndex ] = column[ i ];
379  return true;
380  }
381 
390  bool push_back(const std::vector<T> &sample){
391 
392  unsigned int i,j = 0;
393 
394  //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
395  if(dataPtr==NULL){
396  cols = (unsigned int)sample.size();
397  if( !resize(1,cols) ){
398  clear();
399  return false;
400  }
401  for(j=0; j<cols; j++)
402  dataPtr[ j ] = sample[j];
403  return true;
404  }
405 
406  //If there is data and the sample size does not match the number of columns then return false
407  if(sample.size() != cols ){
408  return false;
409  }
410 
411  //Check to see if we have reached the capacity, if not then simply add the new data as there are unused rows
412  if( rows < capacity ){
413  //Add the new sample at the end
414  for(j=0; j<cols; j++)
415  dataPtr[rows * cols + j] = sample[j];
416 
417  }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
418 
419  const unsigned int tmpRows = rows + 1;
420  T* tmpDataPtr = new T[tmpRows*cols];
421  T** tmpRowPtr = new T*[tmpRows];
422 
423  if( tmpDataPtr == NULL || tmpRowPtr == NULL ){//If NULL then we have run out of memory
424  return false;
425  }
426 
427  //Setup the row pointers
428  T *p = &(tmpDataPtr[0]);
429  for(i=0; i<tmpRows; i++){
430  tmpRowPtr[i] = p;
431  p += cols;
432  }
433 
434  //Copy the original data into the tmp buffer
435  for(i=0; i<rows*cols; i++)
436  tmpDataPtr[i] = dataPtr[i];
437 
438  //Add the new sample at the end of the tmp buffer
439  for(j=0; j<cols; j++)
440  tmpDataPtr[rows*cols+j] = sample[j];
441 
442  //Delete the original data and copy the pointer
443  delete[] dataPtr;
444  delete[] rowPtr;
445  dataPtr = tmpDataPtr;
446  rowPtr = tmpRowPtr;
447 
448  //Increment the capacity so it matches the number of rows
449  capacity++;
450  }
451 
452  //Increment the number of rows
453  rows++;
454 
455  //Update the size
456  size = rows * cols;
457 
458  //Finally return true to signal that the data was added correctly
459  return true;
460  }
461 
469  bool reserve(const unsigned int capacity){
470 
471  //If the number of columns has not been set, then we can not do anything
472  if( cols == 0 ) return false;
473 
474  //Reserve the data and copy and existing data
475  unsigned int i=0;
476  T* tmpDataPtr = new T[ capacity * cols ];
477  T** tmpRowPtr = new T*[ capacity ];
478  if( tmpDataPtr == NULL || tmpRowPtr == NULL ){//If NULL then we have run out of memory
479  return false;
480  }
481 
482  //Setup the row pointers
483  T *p = &(tmpDataPtr[0]);
484  for(i=0; i<capacity; i++){
485  tmpRowPtr[i] = p;
486  p += cols;
487  }
488 
489  //Copy the existing data into the new memory
490  for(i=0; i<size; i++)
491  tmpDataPtr[i] = dataPtr[i];
492 
493  //Delete the original data and copy the pointer
494  delete[] dataPtr;
495  delete[] rowPtr;
496  dataPtr = tmpDataPtr;
497  rowPtr = tmpRowPtr;
498 
499  //Store the new capacity
500  this->capacity = capacity;
501 
502  //Store the size
503  size = rows * cols;
504 
505  return true;
506  }
507 
511  void clear(){
512  if( dataPtr != NULL ){
513  delete[] dataPtr;
514  dataPtr = NULL;
515  }
516  if( rowPtr != NULL ){
517  delete[] rowPtr;
518  rowPtr = NULL;
519  }
520  rows = 0;
521  cols = 0;
522  size = 0;
523  capacity = 0;
524  }
525 
531  inline unsigned int getNumRows() const{ return rows; }
532 
538  inline unsigned int getNumCols() const{ return cols; }
539 
546  inline unsigned int getCapacity() const{ return capacity; }
547 
553  inline unsigned int getSize() const{ return size; }
554 
560  T** getDataPointer() const{
561  if( rowPtr == NULL ){
562  throw Exception("Matrix::getDataPointer() - Matrix has not been initialized!");
563  }
564  return &(rowPtr[0]);
565  }
566 
567 protected:
568 
569  unsigned int rows;
570  unsigned int cols;
571  unsigned int size;
572  unsigned int capacity;
573  T *dataPtr;
574  T **rowPtr;
575  ErrorLog errorLog;
576 
577 };
578 
579 }//End of namespace GRT
580 
581 #endif //GRT_MATRIX_HEADER
bool setColVector(const std::vector< T > &column, const unsigned int colIndex)
Definition: Matrix.h:372
T * operator[](const unsigned int r)
Definition: Matrix.h:153
bool setRowVector(const std::vector< T > &row, const unsigned int rowIndex)
Definition: Matrix.h:353
Matrix()
Definition: Matrix.h:46
bool setAllValues(const T &value)
Definition: Matrix.h:335
Definition: AdaBoost.cpp:25
bool push_back(const std::vector< T > &sample)
Definition: Matrix.h:390
Matrix & operator=(const Matrix &rhs)
Definition: Matrix.h:139
unsigned int getNumCols() const
Definition: Matrix.h:538
T * dataPtr
A pointer to the raw data.
Definition: Matrix.h:573
T ** getDataPointer() const
Definition: Matrix.h:560
const T * operator[](const unsigned int r) const
Definition: Matrix.h:163
Matrix(const unsigned int rows, const unsigned int cols)
Definition: Matrix.h:61
unsigned int capacity
The capacity of the Matrix, this will be the number of rows, not the actual memory size...
Definition: Matrix.h:572
virtual bool copy(const Matrix< T > &rhs)
Definition: Matrix.h:308
virtual ~Matrix()
Definition: Matrix.h:129
void clear()
Definition: Matrix.h:511
unsigned int size
Stores rows * cols.
Definition: Matrix.h:571
T ** rowPtr
A pointer to each row in the data.
Definition: Matrix.h:574
std::vector< T > getConcatenatedVector(const bool concatByRow=true) const
Definition: Matrix.h:202
unsigned int getNumRows() const
Definition: Matrix.h:531
bool reserve(const unsigned int capacity)
Definition: Matrix.h:469
std::vector< T > getColVector(const unsigned int c) const
Definition: Matrix.h:186
Matrix(const std::vector< std::vector< T > > &data)
Definition: Matrix.h:89
Matrix(const Matrix &rhs)
Definition: Matrix.h:72
unsigned int rows
The number of rows in the Matrix.
Definition: Matrix.h:569
std::vector< T > getRowVector(const unsigned int r) const
Definition: Matrix.h:173
unsigned int cols
The number of columns in the Matrix.
Definition: Matrix.h:570
virtual bool resize(const unsigned int r, const unsigned int c)
Definition: Matrix.h:234
unsigned int getCapacity() const
Definition: Matrix.h:546
unsigned int getSize() const
Definition: Matrix.h:553