Mass++ Common Libraries v2.7.5
 All Classes Namespaces Files Functions Variables Enumerations Macros
Matrix.cpp
Go to the documentation of this file.
1 
11 #include "stdafx.h"
12 #include "Matrix.h"
13 
14 #include <gtest/gtest.h>
15 
16 
17 using namespace kome::core;
18 
19 
20 #include <crtdbg.h>
21 #ifdef _DEBUG
22  #define new new( _NORMAL_BLOCK, __FILE__, __LINE__ )
23  #define malloc( s ) _malloc_dbg( s, _NORMAL_BLOCK, __FILE__, __LINE__ )
24 #endif // _DEBUG
25 
26 
27 
28 // constructor
29 Matrix::Matrix( const unsigned int row, const unsigned int col )
30  : m_row( row ), m_col( col ),
31  m_array( ( row == 0 || col == 0 ) ? NULL : new double[ row * col ] ) {
32  if( m_array != NULL ) {
33  fillzero( m_array, sizeof( double ) * m_row * m_col );
34  }
35 }
36 
37 // copy constructor
38 Matrix::Matrix( const Matrix& mat )
39  : m_row( mat.m_row ), m_col( mat.m_col ),
40  m_array( mat.m_array == NULL ? NULL : new double[ mat.m_row * mat.m_col ] ) {
41  if( m_array != NULL ) {
42  memcpy( m_array, mat.m_array, sizeof( double ) * mat.m_row * mat.m_col );
43  }
44 }
45 
46 // destructor
48  if( m_array != NULL ) {
49  delete[] m_array;
50  }
51 }
52 
53 // get row size
54 unsigned int Matrix::getRowSize() {
55  return m_row;
56 }
57 
58 // get col size
59 unsigned int Matrix::getColSize() {
60  return m_col;
61 }
62 
63 // calculate determinant
64 double Matrix::det() {
65  // check size
66  if( m_row != m_col ) {
67  throw FMT( "This is not a square matrix." );
68  }
69  if( m_row == 0 ) {
70  throw FMT( "Matrix size is illegal." );
71  }
72  if( m_row == 1 ) {
73  return m_array[ 0 ];
74  }
75 
76  // calculate
77  double d = 0.0;
78  for( unsigned int i = 0; i < m_col; i++ ) {
79  d += operator()( 0, i ) * cofactor( 0, i );
80  }
81 
82  return d;
83 }
84 
85 // calculate cofactor
86 double Matrix::cofactor( const unsigned int row, const unsigned int col ) {
87  // check size
88  if( m_row != m_col ) {
89  throw FMT( "This is not a square matrix." );
90  }
91  if( m_row <= 1 ) {
92  throw FMT( "Matrix size is illegal." );
93  }
94 
95  // check parameter
96  if( row >= m_row || col >= m_col ) {
97  throw FMT( "The specified element does not exist. [row=%d, col=%d]", row, col );
98  }
99 
100  // create matrix to calculate determinant
101  Matrix m( m_row - 1 , m_col - 1 );
102  for( unsigned int i = 0; i < m_row - 1; i++ ) {
103  int r = ( i < row ) ? i : i + 1;
104  for( unsigned int j = 0; j < m_col - 1; j++ ) {
105  int c = ( j < col ) ? j : j + 1;
106 
107  m( i, j ) = operator()( r, c );
108  }
109  }
110 
111  // calculate cofactor
112  double d = m.det();
113  if( ( row + col ) % 2 != 0 ) {
114  d = - d;
115  }
116 
117  return d;
118 }
119 
120 // get inverse matrix
122  // check size
123  if( m_row != m_col ) {
124  throw FMT( "This is not a square matrix." );
125  }
126  if( m_row == 0 ) {
127  throw FMT( "Matrix size is illegal." );
128  }
129 
130  // calculate determinant
131  double d = det();
132  if( d == 0.0 ) {
133  throw FMT( "There isn't an inverse matrix." );
134  }
135 
136  // create inverse matrix
137  Matrix m( m_row, m_col );
138  if( m_row == 1 ) {
139  m( 0, 0 ) = 1.0 / d;
140  }
141  else {
142  for( unsigned int i = 0; i < m_row; i++ ) {
143  for( unsigned int j = 0; j < m_col; j++ ) {
144  m( i, j ) = cofactor( j, i ) / d;
145  }
146  }
147  }
148 
149  return m;
150 }
151 
152 // multiply
154  // check size
155  if( m_col != v.getDimention() ) {
156  throw FMT( "The size is illegal. [col=%d, dim=%d]", m_row, v.getDimention() );
157  }
158 
159  // multiply
160  Vector tmp( m_row );
161  for( unsigned int i = 0; i < m_row; i++ ) {
162  double elm = 0.0;
163  for( unsigned int j = 0; j < m_col; j++ ) {
164  elm += (*this)( i, j ) * v( j );
165  }
166 
167  tmp( i ) = elm;
168  }
169 
170  return tmp;
171 }
172 
173 // copy
175  if( m.m_row != m_row || m.m_col != m_col ) {
176  throw FMT( "Matrix size is illegal." );
177  }
178 
179  if( m_array != NULL ) {
180  memcpy( m_array, m.m_array, sizeof( double ) * m_row * m_col );
181  }
182 
183  return *this;
184 }
185 
186 // get reference of value
187 double& Matrix::operator()( const unsigned int row, const unsigned int col ) {
188  // check parameter
189  if( row >= m_row || col >= m_col ) {
190  throw FMT( "The specified element does not exist. [row=%d, col=%d]", row, col );
191  }
192 
193  return m_array[ row + col * m_row ];
194 }
195 
196 // matrix addition
198  // check size
199  if( m.m_row != m_row || m.m_col != m_col ) {
200  throw FMT( "Matrix size is illegal." );
201  }
202 
203  // size
204  unsigned int size = m_row * m_col;
205 
206  // addition
207  for( unsigned int i = 0; i < size; i++ ) {
208  m_array[ i ] += m.m_array[ i ];
209  }
210 
211  return *this;
212 }
213 
214 // matrix subtraction
216  // check size
217  if( m.m_row != m_row || m.m_col != m_col ) {
218  throw FMT( "Matrix size is illegal." );
219  }
220 
221  // size
222  unsigned int size = m_row * m_col;
223 
224  // addition
225  for( unsigned int i = 0; i < size; i++ ) {
226  m_array[ i ] -= m.m_array[ i ];
227  }
228 
229  return *this;
230 }
231 
232 // scalar multiplication
233 Matrix& Matrix::operator*=( const double k ) {
234  // get the size of array
235  unsigned int size = m_row * m_col;
236 
237  // multiplication
238  for( unsigned int i = 0; i < size; i++ ) {
239  m_array[ i ] *= k;
240  }
241 
242  return *this;
243 }
244 
245 // scalar division
246 Matrix& Matrix::operator/=( const double k ) {
247  // get the size of array
248  unsigned int size = m_row * m_col;
249 
250  // dividion
251  for( unsigned int i = 0; i < size; i++ ) {
252  m_array[ i ] /= k;
253  }
254 
255  return *this;
256 }
257 
258 // matrix addition
260  Matrix tmp = *this;
261  tmp += m;
262 
263  return tmp;
264 }
265 
266 // matrix subtraction
268  Matrix tmp = *this;
269  tmp -= m;
270 
271  return tmp;
272 }
273 
274 // matrix multiplication
276  // check size
277  if( this->m_col != m.m_row ) {
278  throw FMT( "Matrix size is illegal." );
279  }
280 
281  // copy
282  Matrix tmp( this->m_row, m.m_col );
283 
284  // change size
285  unsigned int num = this->m_col;
286 
287  // multiplication
288  for( unsigned int i = 0; i < this->m_row; i++ ) {
289  for( unsigned int j = 0; j < m.m_col; j++ ) {
290  double val = 0.0;
291  for( unsigned int k = 0; k < num; k++ ) {
292  val += this->m_array[ i + k * this->m_row ] * m.m_array[ k + j * m.m_row ];
293  }
294  tmp( i, j ) = val;
295  }
296  }
297 
298  return tmp;
299 }
300 
301 // scalar multiplication
302 Matrix Matrix::operator*( const double k ) {
303  Matrix tmp = *this;
304  tmp *= k;
305 
306  return tmp;
307 }
308 
309 // scalar division
310 Matrix Matrix::operator/( const double k ) {
311  Matrix tmp = *this;
312  tmp /= k;
313 
314  return tmp;
315 }
316 
317 // Fixture class
318 class MatrixTest : public testing::Test {
319 protected:
320  // matrix A
321  Matrix m_A;
322 
323  // matrix B
324  Matrix m_B;
325 
326  // matrix C
327  Matrix m_C;
328 
329  // matrix D
330  Matrix m_D;
331 
332 public:
333  // constructor
334  MatrixTest() : m_A( 2, 2 ), m_B( 2, 2 ), m_C( 3, 2 ), m_D( 2, 3 ) {
335  }
336 
337  // setup the test fixture class (override method)
338  virtual void SetUp() {
339  // matrix A
340  m_A( 0, 0 ) = 1.0;
341  m_A( 0, 1 ) = 2.0;
342  m_A( 1, 0 ) = 3.0;
343  m_A( 1, 1 ) = 4.0;
344 
345  // matrix B
346  m_B( 0, 0 ) = 5.0;
347  m_B( 0, 1 ) = 6.0;
348  m_B( 1, 0 ) = 7.0;
349  m_B( 1, 1 ) = 8.0;
350 
351  // matrix C
352  m_C( 0, 0 ) = 1.0;
353  m_C( 0, 1 ) = 2.0;
354  m_C( 1, 0 ) = 2.0;
355  m_C( 1, 1 ) = 3.0;
356  m_C( 2, 0 ) = 3.0;
357  m_C( 2, 1 ) = 4.0;
358 
359  // matrix D
360  m_D( 0, 0 ) = 1.0;
361  m_D( 0, 1 ) = 2.0;
362  m_D( 0, 2 ) = 2.0;
363  m_D( 1, 0 ) = 3.0;
364  m_D( 1, 1 ) = 3.0;
365  m_D( 1, 2 ) = 4.0;
366  }
367 };
368 
369 // row size
370 TEST( Matrix, rowSize ) {
371  Matrix A( 3, 4 );
372 
373  ASSERT_EQ( A.getRowSize(), 3 );
374 }
375 
376 // column size
377 TEST( Matrix, colSize ) {
378  Matrix A( 4, 5 );
379 
380  ASSERT_EQ( A.getColSize(), 5 );
381 }
382 
383 // addition test
384 TEST_F( MatrixTest, addition ) {
385  // A + B
386  Matrix C = m_A + m_B;
387 
388  ASSERT_DOUBLE_EQ( 6.0, C( 0, 0 ) );
389  ASSERT_DOUBLE_EQ( 8.0, C( 0, 1 ) );
390  ASSERT_DOUBLE_EQ( 10.0, C( 1, 0 ) );
391  ASSERT_DOUBLE_EQ( 12.0, C( 1, 1 ) );
392 
393  // A + C
394  ASSERT_ANY_THROW( m_A + m_C );
395 
396 }
Matrix operator-(const Matrix &m)
matrix subtraction
Definition: Matrix.cpp:267
Matrix & operator-=(const Matrix &m)
matrix subtraction
Definition: Matrix.cpp:215
double cofactor(const unsigned int row, const unsigned int col)
calculates cofactor (This matrix must be a square matrix.)
Definition: Matrix.cpp:86
vector class
Definition: Vector.h:22
double & operator()(const unsigned int row, const unsigned int col)
gets reference of value of specified element
Definition: Matrix.cpp:187
unsigned int getRowSize()
gets row size of matrix
Definition: Matrix.cpp:54
Matrix operator=(const Matrix &m)
copy matrix
Definition: Matrix.cpp:174
Matrix operator+(const Matrix &m)
matrix addition
Definition: Matrix.cpp:259
double *const m_array
Definition: Matrix.h:54
Matrix & operator+=(const Matrix &m)
matrix addition
Definition: Matrix.cpp:197
virtual ~Matrix()
destructor
Definition: Matrix.cpp:47
unsigned int getColSize()
gets col size of matrix
Definition: Matrix.cpp:59
unsigned int getDimention()
gets the dimention size of vector
Definition: Vector.cpp:53
Vector multiply(Vector &v)
multiplies vector
Definition: Matrix.cpp:153
#define NULL
Definition: CoreMacros.h:18
interfaces of Matrix class
const unsigned int m_col
Definition: Matrix.h:52
const unsigned int m_row
Definition: Matrix.h:50
double det()
calculates determinant. (This matrix must be a square matrix.)
Definition: Matrix.cpp:64
Matrix operator*(const Matrix &m)
matrix multiplication
Definition: Matrix.cpp:275
Matrix invert()
gets inverse matrix (This matrix must be a square matrix.)
Definition: Matrix.cpp:121
Matrix & operator/=(const double k)
scalar division
Definition: Matrix.cpp:246
void fillzero(void *p, size_t n)
This function fills a block of memory zeros.
matrix class
Definition: Matrix.h:25
Matrix & operator*=(const double k)
scalar multiplication
Definition: Matrix.cpp:233
Matrix operator/(const double k)
scalar division
Definition: Matrix.cpp:310
Matrix(const unsigned int row, const unsigned int col)
constructor
Definition: Matrix.cpp:29