CASToR  3.0
Tomographic Reconstruction (PET/SPECT/CT)
oMatrix.cc
Go to the documentation of this file.
1 /*
2 This file is part of CASToR.
3 
4  CASToR is free software: you can redistribute it and/or modify it under the
5  terms of the GNU General Public License as published by the Free Software
6  Foundation, either version 3 of the License, or (at your option) any later
7  version.
8 
9  CASToR is distributed in the hope that it will be useful, but WITHOUT ANY
10  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
12  details.
13 
14  You should have received a copy of the GNU General Public License along with
15  CASToR (in file GNU_GPL.TXT). If not, see <http://www.gnu.org/licenses/>.
16 
17 Copyright 2017-2019 all CASToR contributors listed below:
18 
19  --> Didier BENOIT, Claude COMTAT, Marina FILIPOVIC, Thibaut MERLIN, Mael MILLARDET, Simon STUTE, Valentin VIELZEUF
20 
21 This is CASToR version 3.0.
22 */
23 
30 #include "oMatrix.hh"
31 
32 // =====================================================================
33 // ---------------------------------------------------------------------
34 // ---------------------------------------------------------------------
35 // =====================================================================
36 /*
37  \brief oMatrix constructor.
38  Initialize the member variables to their default values.
39 */
41 {
42  m_lin = 0;
43  m_col = 0;
44 
45  m2p_Mat = NULL;
46 }
47 
48 
49 
50 // =====================================================================
51 // ---------------------------------------------------------------------
52 // ---------------------------------------------------------------------
53 // =====================================================================
54 /*
55  \param nl : a number of lines
56  \param nc : a number of colons
57  \brief oMatrix constructor.
58  Instanciate a Matrix structure with the number of lines and colons provided in parameters
59 */
60 oMatrix::oMatrix(uint16_t nl, uint16_t nc)
61 {
62  m_lin = nl;
63  m_col = nc;
64  m2p_Mat = new HPFLTNB *[nl];
65 
66  for(uint16_t l=0 ; l<nl ; l++)
67  m2p_Mat[l] = new HPFLTNB[nc];
68 }
69 
70 
71 
72 // =====================================================================
73 // ---------------------------------------------------------------------
74 // ---------------------------------------------------------------------
75 // =====================================================================
76 /*
77  \brief oMatrix destructor.
78  Free memory of the oMatrix object.
79 */
81 {
82  for(uint16_t l=0 ; l<m_lin ; l++)
83  if(m2p_Mat[l]) delete[] m2p_Mat[l];
84 
85  if(m2p_Mat) delete[] m2p_Mat;
86 }
87 
88 
89 
90 // =====================================================================
91 // ---------------------------------------------------------------------
92 // ---------------------------------------------------------------------
93 // =====================================================================
94 /*
95  \fn Allocate
96  \param nl : a number of lines
97  \param nc : a number of colons
98  \brief Instanciate a Matrix structure with the number of lines and colons provided in parameters
99 */
100 void oMatrix::Allocate(uint16_t nl, uint16_t nc)
101 {
102  // No verbosity in oMatrix structure. Show this only if CASTOR_DEBUG is enabled (for bug tracking)
103  #ifdef CASTOR_DEBUG
104  Cout("oMatrix::Allocate() ...");
105  #endif
106 
107  // Free memory in case the matrix had already been allocated
108  if(m2p_Mat != NULL)
109  {
110  for(uint16_t l=0 ; l<m_lin ; l++)
111  if(m2p_Mat[l]) delete[] m2p_Mat[l];
112 
113  delete[] m2p_Mat;
114  }
115 
116  m_lin = nl;
117  m_col = nc;
118  m2p_Mat = new HPFLTNB *[nl];
119 
120  for(uint16_t l=0 ; l<nl ; l++)
121  m2p_Mat[l] = new HPFLTNB[nc];
122 }
123 
124 
125 
126 // =====================================================================
127 // ---------------------------------------------------------------------
128 // ---------------------------------------------------------------------
129 // =====================================================================
130 /*
131  \fn SetMatriceElt
132  \param l : a line index
133  \param c : a colon index
134  \param a_val : a value to initialize the matrix element with
135  \brief set the matrix element corresponding to the argument indices with the provided value.
136  \return 0 if success, positive value otherwise
137 */
138 int oMatrix::SetMatriceElt(uint16_t l, uint16_t c, HPFLTNB a_val)
139 {
140  if(l>=m_lin || c>=m_col)
141  {
142  Cerr("***** oMatrix::SetMatriceElt()-> Nb of (lin,col) ("<<l+1<<","<<c+1<<") in parameters ");
143  Cerr("> to the number of (lin,col) of this matrix ("<<m_lin<<","<<m_col<<") !" << endl);
144  return 1;
145  }
146 
147  m2p_Mat[l][c] = a_val;
148 
149  return 0;
150 }
151 
152 
153 
154 // =====================================================================
155 // ---------------------------------------------------------------------
156 // ---------------------------------------------------------------------
157 // =====================================================================
165 HPFLTNB oMatrix::GetMatriceElt(uint16_t l,uint16_t c)
166 {
167  return m2p_Mat[l][c];
168 }
169 
170 
171 
172 // =====================================================================
173 // ---------------------------------------------------------------------
174 // ---------------------------------------------------------------------
175 // =====================================================================
176 /*
177  \fn Multiplication
178  \param ap_Mtx : input matrix to multiply to the matrix from which the function is called
179  \param ap_MtxResult : output matrix containing the result of the multiplication
180  \brief Multiply the member matrix with the matrix provided in 1st parameter
181  Return the result in the matric provided in 2nd parameter
182  \return 0 if success, positive value otherwise
183 */
184 int oMatrix::Multiplication(oMatrix *ap_Mtx, oMatrix *ap_MtxResult)
185 {
186  HPFLTNB sum=0;
187 
188  if ( m_col != ap_Mtx->m_lin )
189  {
190  Cerr("***** oMatrix::Multiplication()-> Not matching number of colons and lines of the two matrices !");
191  return 1;
192  }
193  else if (ap_MtxResult == NULL)
194  {
195  Cerr("***** oMatrix::Multiplication()-> The resulting matrix has not been allocated !");
196  return 1;
197  }
198  else
199  {
200  for ( uint16_t tl = 0; tl < m_lin; tl++ )
201  for ( uint16_t c = 0; c < ap_Mtx->m_col; c++ )
202  {
203  for ( uint16_t l = 0; l < ap_Mtx->m_lin; l++ )
204  {
205  sum += GetMatriceElt(tl,l) * ap_Mtx->GetMatriceElt(l,c);
206  }
207  ap_MtxResult->SetMatriceElt(tl,c,sum);
208  sum = 0;
209  }
210  }
211 
212  return 0;
213 }
214 
215 
216 
217 
218 // =====================================================================
219 // ---------------------------------------------------------------------
220 // ---------------------------------------------------------------------
221 // =====================================================================
222 /*
223  \fn int oMatrix::Transpose()
224  \param ap_MtxResult : output matrix containing the result of the transposition
225  \brief Transpose the elements of the matrix
226  \return 0 if success, positive value otherwise
227 */
229 {
230  if ( this->m_col != ap_Mtx->m_lin
231  || this->m_lin != ap_Mtx->m_col )
232  {
233  Cerr("***** oMatrix::Transpose()-> Not matching number of colons <-> lines between the input and transpose matrices !");
234  return 1;
235  }
236  if (ap_Mtx == NULL)
237  {
238  Cerr("***** oMatrix::Transpose()-> The resulting matrix has not been allocated !");
239  return 1;
240  }
241 
242  uint16_t lsize = m_lin>m_col ? m_lin : m_col;
243 
244  for ( uint16_t l = 0; l < lsize; l++ )
245  for ( uint16_t c = l; c < lsize; c++ )
246  {
247  HPFLTNB tmp = 0.;
248 
249  if( l < m_lin
250  && c < m_col )
251  tmp = m2p_Mat[l][c];
252 
253  if(l < ap_Mtx->m_lin
254  && c < ap_Mtx->m_col
255  && l < m_col
256  && c < m_lin )
257  ap_Mtx->SetMatriceElt( l , c , m2p_Mat[c][l] );
258 
259  if(l < ap_Mtx->m_col
260  && c < ap_Mtx->m_lin
261  && l < m_lin
262  && c < m_col )
263  ap_Mtx->SetMatriceElt( c , l , tmp );
264  }
265 
266  return 0;
267 }
268 
269 
270 
271 
272 // =====================================================================
273 // ---------------------------------------------------------------------
274 // ---------------------------------------------------------------------
275 // =====================================================================
276 /*
277  \fn int oMatrix::Inverse()
278  \param ap_MtxResult : output matrix containing the inverse matrix
279  \brief Inverse the matrix on which the function is called
280  An error is returned if the matrix is not square,
281  or if there is a nil component on the diagonal
282  The resulting matrix object must be different than the input matrix
283  \return 0 if success, positive value otherwise
284 */
286 {
287  // Check matching nb colons/lines
288  if ( (this->m_col != this->m_lin)
289  || (ap_Mtx->m_col != ap_Mtx->m_lin) )
290  {
291  Cerr("***** oMatrix::Inverse()-> Not matching number of colons <-> lines between the input and transpose matrices !");
292  return 1;
293  }
294  // Check if resulting matrix has been allocated
295  if (ap_Mtx == NULL)
296  {
297  Cerr("***** oMatrix::Inverse()-> The resulting matrix has not been allocated !");
298  return 1;
299  }
300  // Check if resulting matrix is the same as this matrix
301  // Throw error as the resulting matrix will overwrite the components of the input matrix in the process
302  if (this == ap_Mtx)
303  {
304  Cerr("***** oMatrix::Inverse()-> The resulting matrix has not been allocated !");
305  return 1;
306  }
307 
308  for ( uint16_t l = 0; l < m_lin; l++ )
309  for ( uint16_t c = 0; c < m_col; c++ )
310  {
311  if (m2p_Mat[l][c] == 0)
312  {
313  //Cerr("***** oMatrix::Inverse()-> One element on the diagonal is nil !");
314  return 1;
315  }
316  }
317 
318  oMatrix* p_tMtx = new oMatrix(m_lin, m_col);
319 
320 
321  // Init
322  for( uint16_t l=0 ; l<m_lin ; l++ )
323  for ( uint16_t c = 0; c < m_col; c++ )
324  {
325  p_tMtx->SetMatriceElt( l, c, 0. );
326  ap_Mtx->SetMatriceElt( l, c, m2p_Mat[l][c] );
327  }
328 
329  HPFLTNB** pMtx = ap_Mtx->GetMtx();
330 
331  for( uint16_t l=0 ; l<m_lin ; l++ )
332  {
333  for ( uint16_t c = 0; c < m_col; c++ )
334  {
335  p_tMtx->SetMatriceElt(l, l, 1./pMtx[l][l]);
336 
337  if(c != l)
338  p_tMtx->SetMatriceElt(l, c, -pMtx[l][c] / pMtx[l][l]);
339 
340  for( uint16_t r=0 ; r<m_lin ; r++ )
341  {
342  if(r!=l)
343  p_tMtx->SetMatriceElt(r, l, pMtx[r][l]/pMtx[l][l]);
344  if(c!=l && r!=l)
345  p_tMtx->SetMatriceElt(r, c, pMtx[r][c] - pMtx[l][c]*pMtx[r][l]/pMtx[l][l]);
346  }
347 
348  }
349 
350  for(int ll=0 ; ll<m_lin ; ll++)
351  for(int cc=0 ; cc<m_col ; cc++)
352  pMtx[ll][cc] = p_tMtx->GetMatriceElt(ll,cc) ;
353 
354  }
355 
356  delete p_tMtx;
357 
358  return 0;
359 }
360 
361 
362 // =====================================================================
363 // ---------------------------------------------------------------------
364 // ---------------------------------------------------------------------
365 // =====================================================================
366 /*
367  \fn int oMatrix::SetXRotMtx()
368  \param ang : angle in degree
369  \brief Set a (3,3) X-axis rotation matrix using the provided angle
370  \return 0 if sucess, positive value otherwise
371 */
373 {
374  if(m_lin !=3 || m_col != 3)
375  {
376  Cerr("***** oMatrix::SetXRotMtx()-> The matrix must be (3,3) in order to use this function !");
377  return 1;
378  }
379 
380  SetMatriceElt(0,0, 1 );
381  SetMatriceElt(0,1, 0 );
382  SetMatriceElt(0,2, 0 );
383  SetMatriceElt(1,0, 0 );
384  SetMatriceElt(1,1, cos(ang));
385  SetMatriceElt(1,2, -sin(ang));
386  SetMatriceElt(2,0, 0 );
387  SetMatriceElt(2,1, sin(ang));
388  SetMatriceElt(2,2, cos(ang)) ;
389 
390  return 0;
391 }
392 
393 
394 
395 
396 // =====================================================================
397 // ---------------------------------------------------------------------
398 // ---------------------------------------------------------------------
399 // =====================================================================
400 /*
401  \fn int oMatrix::SetYRotMtx()
402  \param ang : angle in degree
403  \brief Set a (3,3) Y-axis rotation matrix using the provided angle
404  \return 0 if sucess, positive value otherwise
405 */
407 {
408  if(m_lin !=3 || m_col != 3)
409  {
410  Cerr("***** oMatrix::SetYRotMtx()-> The matrix must be (3,3) in order to use this function !");
411  return 1;
412  }
413 
414  SetMatriceElt(0,0, cos(ang));
415  SetMatriceElt(0,1, 0 );
416  SetMatriceElt(0,2, sin(ang));
417  SetMatriceElt(1,0, 0 );
418  SetMatriceElt(1,1, 1 );
419  SetMatriceElt(1,2, 0 );
420  SetMatriceElt(2,0, -sin(ang));
421  SetMatriceElt(2,1, 0 );
422  SetMatriceElt(2,2, cos(ang));
423 
424  return 0;
425 }
426 
427 
428 
429 
430 // =====================================================================
431 // ---------------------------------------------------------------------
432 // ---------------------------------------------------------------------
433 // =====================================================================
434 /*
435  \fn int oMatrix::SetZRotMtx()
436  \param ang : angle in degree
437  \brief Set a (3,3) Z-axis rotation matrix using the provided angle
438  \return 0 if sucess, positive value otherwise
439 */
441 {
442  if(m_lin !=3 || m_col != 3)
443  {
444  Cerr("***** oMatrix::SetZRotMtx()-> The matrix must be (3,3) in order to use this function !");
445  return 1;
446  }
447 
448  SetMatriceElt(0,0, cos(ang) );
449  SetMatriceElt(0,1, -sin(ang) );
450  SetMatriceElt(0,2, 0);
451  SetMatriceElt(1,0, sin(ang));
452  SetMatriceElt(1,1, cos(ang) );
453  SetMatriceElt(1,2, 0);
454  SetMatriceElt(2,0, 0);
455  SetMatriceElt(2,1, 0);
456  SetMatriceElt(2,2, 1);
457 
458  return 0;
459 }
460 
461 
462 
463 
464 // =====================================================================
465 // ---------------------------------------------------------------------
466 // ---------------------------------------------------------------------
467 // =====================================================================
468 /*
469  \fn int oMatrix::Describe()
470  \brief Display the element of the matrix
471 */
473 {
474  for ( uint16_t l = 0; l < m_lin; l++ )
475  {
476  for ( uint16_t c = 0; c < m_col; c++ )
477  cout << m2p_Mat[l][c] << " ; ";
478 
479  cout << endl;
480  }
481 }
int Inverse(oMatrix *ap_MtxResult)
Inverse the matrix on which the function is called An error is returned if the matrix is not square...
Definition: oMatrix.cc:285
#define HPFLTNB
Definition: gVariables.hh:83
~oMatrix()
oMatrix destructor. Free memory of the oMatrix object.
Definition: oMatrix.cc:80
oMatrix()
oMatrix constructor. Initialize the member variables to their default values.
Definition: oMatrix.cc:40
#define Cerr(MESSAGE)
uint16_t m_lin
Definition: oMatrix.hh:156
HPFLTNB ** GetMtx()
Definition: oMatrix.hh:95
Declaration of class oMatrix.
HPFLTNB GetMatriceElt(uint16_t l, uint16_t c)
Definition: oMatrix.cc:165
void Describe()
Display the element of the matrix.
Definition: oMatrix.cc:472
uint16_t m_col
Definition: oMatrix.hh:157
HPFLTNB ** m2p_Mat
Definition: oMatrix.hh:159
Structure designed for basic matrices operations.
Definition: oMatrix.hh:41
int SetXRotMtx(HPFLTNB ang)
Set a (3,3) X-axis rotation matrix using the provided angle.
Definition: oMatrix.cc:372
#define Cout(MESSAGE)
int Multiplication(oMatrix *ap_Mtx, oMatrix *ap_MtxResult)
Multiply the member matrix with the matrix provided in 1st parameter Return the result in the matric ...
Definition: oMatrix.cc:184
int SetMatriceElt(uint16_t l, uint16_t c, HPFLTNB a_val)
Set the matrix element corresponding to the argument indices with the provided value.
Definition: oMatrix.cc:138
int SetZRotMtx(HPFLTNB ang)
Set a (3,3) Z-axis rotation matrix using the provided angle.
Definition: oMatrix.cc:440
int SetYRotMtx(HPFLTNB ang)
Set a (3,3) Y-axis rotation matrix using the provided angle.
Definition: oMatrix.cc:406
int Transpose(oMatrix *a_MtxResult)
Transpose the elements of the matrix.
Definition: oMatrix.cc:228
void Allocate(uint16_t nl, uint16_t nc)
Instanciate a Matrix structure with the number of lines and colons provided in parameters.
Definition: oMatrix.cc:100