Jpp
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
JMatrixND.hh
Go to the documentation of this file.
1 #ifndef __JMATH__JMATRIXND__
2 #define __JMATH__JMATRIXND__
3 
4 #include <cstring>
5 #include <limits>
6 #include <cmath>
7 #include <algorithm>
8 
9 #include "JIO/JSerialisable.hh"
10 #include "JLang/JException.hh"
11 #include "JLang/JEquals.hh"
12 #include "JLang/JSingleton.hh"
13 #include "JMath/JMath.hh"
14 #include "JMath/JVectorND.hh"
15 #include "Jeep/JPrint.hh"
16 
17 
18 namespace JMATH {}
19 namespace JPP { using namespace JMATH; }
20 
21 namespace JMATH {
22 
23  using JIO::JReader;
24  using JIO::JWriter;
25  using JLANG::JEquals;
26  using JLANG::JSingleton;
27  using JLANG::JException;
30 
31 
32  /**
33  * Basic NxN matrix.
34  */
35  struct JMatrixND_t :
36  public JSingleton<JMatrixND_t>
37  {
38  /**
39  * Default constructor.
40  */
42  __p(NULL),
43  __n(0),
44  __m(0)
45  {}
46 
47 
48  /**
49  * Destructor.
50  */
52  {
53  clear();
54  }
55 
56 
57  /**
58  * Clear memory.
59  */
60  void clear()
61  {
62  if (__p != NULL) {
63  delete [] __p;
64  }
65 
66  __p = NULL;
67  __n = 0;
68  __m = 0;
69  }
70 
71 
72  /**
73  * Resize matrix.
74  *
75  * Note that this method does not maintain data in the matrix.
76  *
77  * \param size dimension
78  */
79  void resize(const size_t size)
80  {
81  if (size != this->__n) {
82 
83  if (size > this->__m) {
84 
85  if (__p != NULL) {
86  delete[] __p;
87  }
88 
89  __m = size;
90  __p = new double[__m*__m];
91 
92  if (__p == NULL) {
93  THROW(JNewException, "JMatrixND::resize(" << size << "): Memory allocation failure.");
94  }
95  }
96 
97  __n = size;
98  }
99  }
100 
101 
102  /**
103  * Set matrix.
104  *
105  * \param A matrix
106  */
107  void set(const JMatrixND_t& A)
108  {
109  this->resize(A.size());
110 
111  memcpy(this->data(), A.data(), A.size() * A.size() * sizeof(double));
112  }
113 
114 
115  /**
116  * Swap matrices
117  *
118  * \param A matrix
119  */
121  {
122  using std::swap;
123 
124  swap(this->__p, A.__p);
125  swap(this->__n, A.__n);
126  swap(this->__m, A.__m);
127  }
128 
129 
130  /**
131  * Transpose.
132  *
133  * \return this matrix
134  */
136  {
137  using std::swap;
138 
139  for (size_t row = 0; row != this->size(); ++row) {
140  for (size_t col = 0; col != row; ++col) {
141  swap((*this)(row,col), (*this)(col,row));
142  }
143  }
144 
145  return *this;
146  }
147 
148 
149  /**
150  * Get dimension of matrix.
151  *
152  * \return dimension
153  */
154  size_t size() const
155  {
156  return __n;
157  }
158 
159 
160  /**
161  * Get capacity of dimension.
162  *
163  * \return capacity
164  */
165  size_t capacity() const
166  {
167  return __m;
168  }
169 
170 
171  /**
172  * Check emptyness.
173  *
174  * \return true if empty; else false
175  */
176  bool empty() const
177  {
178  return __n == 0;
179  }
180 
181 
182  /**
183  * Get pointer to data.
184  *
185  * \return pointer to data.
186  */
187  const double* data() const
188  {
189  return __p;
190  }
191 
192 
193  /**
194  * Get pointer to data.
195  *
196  * \return pointer to data.
197  */
198  double* data()
199  {
200  return __p;
201  }
202 
203 
204  /**
205  * Get row data.
206  *
207  * \param row row number
208  * \return pointer to row data
209  */
210  const double* operator[](size_t row) const
211  {
212  return __p + row*__n;
213  }
214 
215 
216  /**
217  * Get row data.
218  *
219  * \param row row number
220  * \return pointer to row data
221  */
222  double* operator[](size_t row)
223  {
224  return __p + row*__n;
225  }
226 
227 
228  /**
229  * Get matrix element.
230  *
231  * \param row row number
232  * \param col column number
233  * \return matrix element at (row,col)
234  */
235  double operator()(const size_t row, const size_t col) const
236  {
237  return *(__p + row*__n + col);
238  }
239 
240 
241  /**
242  * Get matrix element.
243  *
244  * \param row row number
245  * \param col column number
246  * \return matrix element at (row,col)
247  */
248  double& operator()(const size_t row, const size_t col)
249  {
250  return *(__p + row*__n + col);
251  }
252 
253 
254  /**
255  * Get matrix element.
256  *
257  * \param row row number
258  * \param col column number
259  * \return matrix element at (row,col)
260  */
261  double at(size_t row, size_t col) const
262  {
263  if (row >= this->size() ||
264  col >= this->size()) {
265  THROW(JIndexOutOfRange, "JMatrixND::at(" << row << "," << col << "): index out of range.");
266  }
267 
268  return (*this)(row, col);
269  }
270 
271 
272  /**
273  * Get matrix element.
274  *
275  * \param row row number
276  * \param col column number
277  * \return matrix element at (row,col)
278  */
279  double& at(size_t row, size_t col)
280  {
281  if (row >= this->size() ||
282  col >= this->size()) {
283  THROW(JIndexOutOfRange, "JMatrixND::at(" << row << "," << col << "): index out of range.");
284  }
285 
286  return (*this)(row, col);
287  }
288 
289 
290  protected:
291  double* __p; //!< pointer to data
292  size_t __n; //!< dimension of matrix
293  size_t __m; //!< capacity of matrix
294  };
295 
296 
297  /**
298  * NxN matrix.
299  */
300  struct JMatrixND :
301  public JMatrixND_t,
302  public JMath <JMatrixND>,
303  public JEquals<JMatrixND>
304  {
305  using JMath<JMatrixND>::mul;
306 
307  /**
308  * Default constructor.
309  */
311  {}
312 
313 
314  /**
315  * Constructor.
316  *
317  * The matrix is set to zero.
318  *
319  * \param size dimension
320  */
321  JMatrixND(const size_t size)
322  {
323  resize(size);
324  reset();
325  }
326 
327 
328  /**
329  * Copy constructor.
330  *
331  * \param A matrix
332  */
334  {
335  set(A);
336  }
337 
338 
339  /**
340  * Assignment operator.
341  *
342  * \param A matrix
343  */
345  {
346  this->set(A);
347 
348  return *this;
349  }
350 
351 
352  /**
353  * Resize matrix.
354  *
355  * Note that this method does not maintain data in the matrix.
356  *
357  * \param size dimension
358  */
359  void resize(const size_t size)
360  {
361  static_cast<JMatrixND_t&>(*this).resize(size);
362 
363  getInstance().resize(size);
364  }
365 
366 
367  /**
368  * Set matrix to the null matrix.
369  *
370  * \return this matrix
371  */
373  {
375 
376  double* p = A.data();
377 
378  for (size_t i = this->size(); i != 0; --i, ++p) {
379  *p = 0.0;
380  }
381 
382  p = this->data();
383 
384  for (size_t i = this->size(); i != 0; --i, p += this->size()) {
385  memcpy(p, A.data(), this->size() * sizeof(double));
386  }
387 
388  return *this;
389  }
390 
391 
392  /**
393  * Set to identity matrix
394  *
395  * \return this matrix
396  */
398  {
399  reset();
400 
401  for (size_t i = 0; i != this->size(); ++i) {
402  (*this)(i,i) = 1.0;
403  }
404 
405  return *this;
406  }
407 
408 
409  /**
410  * Negate matrix.
411  *
412  * \return this matrix
413  */
415  {
416  double* p = this->data();
417 
418  for (size_t i = this->size()*this->size(); i != 0; --i, ++p) {
419  *p = -*p;
420  }
421 
422  return *this;
423  }
424 
425 
426  /**
427  * Matrix addition.
428  *
429  * \param A matrix
430  * \return this matrix
431  */
433  {
434  if (this->size() == A.size()) {
435 
436  double* p = this->data();
437  const double* q = A.data();
438 
439  for (size_t i = this->size()*this->size(); i != 0; --i, ++p, ++q) {
440  *p += *q;
441  }
442 
443  } else {
444  THROW(JException, "JMatrixND::add() inconsistent matrix dimensions " << this->size() << ' ' << A.size());
445  }
446  }
447 
448 
449  /**
450  * Matrix subtraction.
451  *
452  * \param A matrix
453  * \return this matrix
454  */
456  {
457  if (this->size() == A.size()) {
458 
459  double* p = this->data();
460  const double* q = A.data();
461 
462  for (size_t i = this->size()*this->size(); i != 0; --i, ++p, ++q) {
463  *p -= *q;
464  }
465 
466  } else {
467  THROW(JException, "JMatrixND::sub() inconsistent matrix dimensions " << this->size() << ' ' << A.size());
468  }
469 
470  return *this;
471  }
472 
473 
474  /**
475  * Scale matrix.
476  *
477  * \param factor factor
478  * \return this matrix
479  */
480  JMatrixND& mul(const double factor)
481  {
482  double* p = this->data();
483 
484  for (size_t i = this->size()*this->size(); i != 0; --i, ++p) {
485  *p *= factor;
486  }
487 
488  return *this;
489  }
490 
491 
492  /**
493  * Scale matrix.
494  *
495  * \param factor factor
496  * \return this matrix
497  */
498  JMatrixND& div(const double factor)
499  {
500  double* p = this->data();
501 
502  for (size_t i = this->size()*this->size(); i != 0; --i, ++p) {
503  *p /= factor;
504  }
505 
506  return *this;
507  }
508 
509 
510  /**
511  * Matrix multiplication.
512  *
513  * \param A matrix
514  * \param B matrix
515  * \return this matrix
516  */
518  const JMatrixND& B)
519  {
520  if (A.size() == B.size()) {
521 
522  this->resize(A.size());
523 
524  if (!this->empty()) {
525 
527 
528  C.set(B);
529  C.transpose();
530 
531  size_t i, row;
532 
533  for (row = 0; row + 4 <= this->size(); row += 4) { // process rows by four
534 
535  double* p0 = (*this)[row + 0];
536  double* p1 = (*this)[row + 1];
537  double* p2 = (*this)[row + 2];
538  double* p3 = (*this)[row + 3];
539 
540  for (size_t col = 0; col != this->size(); ++col, ++p0, ++p1, ++p2, ++p3) {
541 
542  double w0 = 0.0;
543  double w1 = 0.0;
544  double w2 = 0.0;
545  double w3 = 0.0;
546 
547  const double* a0 = A[row + 0];
548  const double* a1 = A[row + 1];
549  const double* a2 = A[row + 2];
550  const double* a3 = A[row + 3];
551 
552  const double* c0 = C[col];
553 
554  for (i = 0; i + 4 <= this->size(); i += 4, a0 += 4, a1 += 4, a2 += 4, a3 += 4, c0 += 4) {
555  w0 += a0[0] * c0[0] + a0[1] * c0[1] + a0[2] * c0[2] + a0[3] * c0[3];
556  w1 += a1[0] * c0[0] + a1[1] * c0[1] + a1[2] * c0[2] + a1[3] * c0[3];
557  w2 += a2[0] * c0[0] + a2[1] * c0[1] + a2[2] * c0[2] + a2[3] * c0[3];
558  w3 += a3[0] * c0[0] + a3[1] * c0[1] + a3[2] * c0[2] + a3[3] * c0[3];
559  }
560 
561  for ( ; i != this->size(); ++i, ++a0, ++a1, ++a2, ++a3, ++c0) {
562  w0 += (*a0) * (*c0);
563  w1 += (*a1) * (*c0);
564  w2 += (*a2) * (*c0);
565  w3 += (*a3) * (*c0);
566  }
567 
568  *p0 = w0;
569  *p1 = w1;
570  *p2 = w2;
571  *p3 = w3;
572  }
573  }
574 
575  for ( ; row != this->size(); ++row) { // remaining rows
576 
577  double* p0 = (*this)[row + 0];
578 
579  for (size_t col = 0; col != this->size(); ++col, ++p0) {
580 
581  double w0 = 0.0;
582 
583  const double* a0 = A[row + 0];
584  const double* c0 = C[col];
585 
586  for (i = 0; i + 4 <= this->size(); i += 4, a0 += 4, c0 += 4) {
587  w0 += a0[0] * c0[0] + a0[1] * c0[1] + a0[2] * c0[2] + a0[3] * c0[3];
588  }
589 
590  for ( ; i != this->size(); ++i, ++a0, ++c0) {
591  w0 += (*a0) * (*c0);
592  }
593 
594  *p0 = w0;
595  }
596  }
597  }
598 
599  } else {
600  THROW(JException, "JMatrixND::mul() inconsistent matrix dimensions " << A.size() << ' ' << B.size());
601  }
602 
603  return *this;
604  }
605 
606 
607  /**
608  * Equality.
609  *
610  * \param A matrix
611  * \param eps numerical precision
612  * \return true if matrices identical; else false
613  */
614  bool equals(const JMatrixND& A,
615  const double eps = std::numeric_limits<double>::min()) const
616  {
617  if (this->size() == A.size()) {
618 
619  for (size_t row = 0; row != this->size(); ++row) {
620 
621  const double* p = (*this)[row];
622  const double* q = A [row];
623 
624  for (size_t i = this->size(); i != 0; --i, ++p, ++q) {
625  if (fabs(*p - *q) > eps) {
626  return false;
627  }
628  }
629  }
630 
631  return true;
632 
633  } else {
634  THROW(JException, "JMatrixND::equals() inconsistent matrix dimensions " << this->size() << ' ' << A.size());
635  }
636  }
637 
638 
639  /**
640  * Test identity.
641  *
642  * \param eps numerical precision
643  * \return true if identity matrix; else false
644  */
645  bool isIdentity(const double eps = std::numeric_limits<double>::min()) const
646  {
647  for (size_t i = 0; i != this->size(); ++i) {
648 
649  if (fabs(1.0 - (*this)(i,i)) > eps) {
650  return false;
651  };
652 
653  for (size_t j = 0; j != i; ++j) {
654  if (fabs((*this)(i,j)) > eps || fabs((*this)(j,i)) > eps) {
655  return false;
656  };
657  }
658  }
659 
660  return true;
661  }
662 
663 
664  /**
665  * Test symmetry.
666  *
667  * \param eps numerical precision
668  * \return true if symmetric matrix; else false
669  */
670  bool isSymmetric(const double eps = std::numeric_limits<double>::min()) const
671  {
672  for (size_t i = 0; i != this->size(); ++i) {
673  for (size_t j = 0; j != i; ++j) {
674  if (fabs((*this)(i,j) - (*this)(j,i)) > eps) {
675  return false;
676  };
677  }
678  }
679 
680  return true;
681  }
682 
683 
684  /**
685  * Get dot product.
686  *
687  * The dot product corresponds to \f[ v^{T} \times A \times v \f].
688  *
689  * \param v vector
690  * \return dot product
691  */
692  double getDot(const JVectorND& v) const
693  {
694  double dot = 0.0;
695 
696  for (size_t i = 0; i != v.size(); ++i) {
697 
698  const double* p = (*this)[i];
699 
700  double w = 0.0;
701 
702  for (JVectorND::const_iterator y = v.begin(); y != v.end(); ++y, ++p) {
703  w += (*p) * (*y);
704  }
705 
706  dot += v[i] * w;
707  }
708 
709  return dot;
710  }
711 
712 
713  /**
714  * Read matrix from input.
715  *
716  * \param in reader
717  * \param A matrix
718  * \return reader
719  */
720  friend inline JReader& operator>>(JReader& in, JMatrixND& A)
721  {
722  size_t size;
723 
724  in >> size;
725 
726  A.resize(size);
727 
728  size_t n = A.size() * A.size();
729 
730  for (double* p = A.data(); n != 0; --n, ++p) {
731  in >> *p;
732  }
733 
734  return in;
735  }
736 
737 
738  /**
739  * Write matrix to output.
740  *
741  * \param out writer
742  * \param A matrix
743  * \return writer
744  */
745  friend inline JWriter& operator<<(JWriter& out, const JMatrixND& A)
746  {
747  out << A.size();
748 
749  size_t n = A.size() * A.size();
750 
751  for (const double* p = A.data(); n != 0; --n, ++p) {
752  out << *p;
753  }
754 
755  return out;
756  }
757 
758 
759  /**
760  * Print ASCII formatted output.
761  *
762  * \param out output stream
763  * \param A matrix
764  * \return output stream
765  */
766  friend inline std::ostream& operator<<(std::ostream& out, const JMatrixND& A)
767  {
768  using namespace std;
769 
770  JFlags flags(out);
771 
772  for (size_t row = 0; row != A.size(); ++row) {
773 
774  for (size_t col = 0; col != A.size(); ++col) {
775  out << FIXED(10,3) << A(row,col) << ' ';
776  }
777 
778  out << endl;
779  }
780 
781  return out;
782  }
783 
784 
785  protected:
786  /*
787  * Swap rows.
788  *
789  * \param r1 row
790  * \param r2 row
791  */
792  void rswap(size_t r1, size_t r2)
793  {
794  JMatrixND_t& A = getInstance();
795 
796  memcpy(A.data(), (*this)[r1], this->size() * sizeof(double));
797  memcpy((*this)[r1], (*this)[r2], this->size() * sizeof(double));
798  memcpy((*this)[r2], A.data(), this->size() * sizeof(double));
799  }
800 
801 
802  /**
803  * Swap columns.
804  *
805  * \param c1 column
806  * \param c2 column
807  */
808  void cswap(size_t c1, size_t c2)
809  {
810  using std::swap;
811 
812  double* p1 = this->data() + c1;
813  double* p2 = this->data() + c2;
814 
815  for (size_t i = this->size(); i != 0; --i, p1 += this->size(), p2 += this->size()) {
816  swap(*p1, *p2);
817  }
818  }
819  };
820 }
821 
822 #endif
JMatrixND(const JMatrixND &A)
Copy constructor.
Definition: JMatrixND.hh:333
Exception for failure of memory allocation.
Definition: JException.hh:306
General exception.
Definition: JException.hh:23
data_type w[N+1][M+1]
Definition: JPolint.hh:708
Exceptions.
Simple singleton class.
Definition: JSingleton.hh:18
Interface for binary output.
Auxiliary base class for aritmetic operations of derived class types.
Definition: JMath.hh:26
TPaveText * p1
JMatrixND & sub(const JMatrixND &A)
Matrix subtraction.
Definition: JMatrixND.hh:455
double at(size_t row, size_t col) const
Get matrix element.
Definition: JMatrixND.hh:261
void clear()
Clear memory.
Definition: JMatrixND.hh:60
JMatrixND & mul(const double factor)
Scale matrix.
Definition: JMatrixND.hh:480
#define THROW(JException_t, A)
Marco for throwing exception with std::ostream compatible message.
Definition: JException.hh:670
esac print_variable DETECTOR INPUT_FILE OUTPUT_FILE CDF for TYPE in
Definition: JSirene.sh:45
JMatrixND & reset()
Set matrix to the null matrix.
Definition: JMatrixND.hh:372
Auxiliary data structure for floating point format specification.
Definition: JPrint.hh:481
void resize(const size_t size)
Resize matrix.
Definition: JMatrixND.hh:359
const double * operator[](size_t row) const
Get row data.
Definition: JMatrixND.hh:210
JMatrixND & operator=(const JMatrixND &A)
Assignment operator.
Definition: JMatrixND.hh:344
~JMatrixND_t()
Destructor.
Definition: JMatrixND.hh:51
double operator()(const size_t row, const size_t col) const
Get matrix element.
Definition: JMatrixND.hh:235
JMatrixND(const size_t size)
Constructor.
Definition: JMatrixND.hh:321
NxN matrix.
Definition: JMatrixND.hh:300
friend JWriter & operator<<(JWriter &out, const JMatrixND &A)
Write matrix to output.
Definition: JMatrixND.hh:745
void set(const JMatrixND_t &A)
Set matrix.
Definition: JMatrixND.hh:107
I/O formatting auxiliaries.
JMatrixND_t()
Default constructor.
Definition: JMatrixND.hh:41
bool isIdentity(const double eps=std::numeric_limits< double >::min()) const
Test identity.
Definition: JMatrixND.hh:645
Template definition of auxiliary base class for comparison of data structures.
Definition: JEquals.hh:24
double * data()
Get pointer to data.
Definition: JMatrixND.hh:198
JMatrixND & add(const JMatrixND &A)
Matrix addition.
Definition: JMatrixND.hh:432
Interface for binary input.
bool equals(const JMatrixND &A, const double eps=std::numeric_limits< double >::min()) const
Equality.
Definition: JMatrixND.hh:614
void rswap(size_t r1, size_t r2)
Definition: JMatrixND.hh:792
friend JReader & operator>>(JReader &in, JMatrixND &A)
Read matrix from input.
Definition: JMatrixND.hh:720
size_t size() const
Get dimension of matrix.
Definition: JMatrixND.hh:154
TCanvas * c1
Global variables to handle mouse events.
JMatrixND & negate()
Negate matrix.
Definition: JMatrixND.hh:414
double & at(size_t row, size_t col)
Get matrix element.
Definition: JMatrixND.hh:279
size_t __n
dimension of matrix
Definition: JMatrixND.hh:292
static data_type & getInstance()
Get unique instance of template class.
Definition: JSingleton.hh:27
alias put_queue eval echo n
Definition: qlib.csh:19
double * __p
pointer to data
Definition: JMatrixND.hh:291
bool isSymmetric(const double eps=std::numeric_limits< double >::min()) const
Test symmetry.
Definition: JMatrixND.hh:670
void resize(const size_t size)
Resize matrix.
Definition: JMatrixND.hh:79
JMatrixND_t & transpose()
Transpose.
Definition: JMatrixND.hh:135
Base class for data structures with artithmetic capabilities.
void cswap(size_t c1, size_t c2)
Swap columns.
Definition: JMatrixND.hh:808
size_t capacity() const
Get capacity of dimension.
Definition: JMatrixND.hh:165
JMatrixND()
Default constructor.
Definition: JMatrixND.hh:310
void swap(JMatrixND_t &A)
Swap matrices.
Definition: JMatrixND.hh:120
int j
Definition: JPolint.hh:634
Exception for accessing an index in a collection that is outside of its range.
Definition: JException.hh:90
data_type v[N+1][M+1]
Definition: JPolint.hh:707
static const double C
Speed of light in vacuum [m/ns].
Definition: JConstants.hh:22
double getDot(const JVectorND &v) const
Get dot product.
Definition: JMatrixND.hh:692
const double * data() const
Get pointer to data.
Definition: JMatrixND.hh:187
bool empty() const
Check emptyness.
Definition: JMatrixND.hh:176
double & operator()(const size_t row, const size_t col)
Get matrix element.
Definition: JMatrixND.hh:248
size_t __m
capacity of matrix
Definition: JMatrixND.hh:293
Basic NxN matrix.
Definition: JMatrixND.hh:35
Auxiliary class to temporarily modify format specifications.
Definition: JPrint.hh:617
source $JPP_DIR setenv csh $JPP_DIR eval JShellParser o a A
JMatrixND & setIdentity()
Set to identity matrix.
Definition: JMatrixND.hh:397
double * operator[](size_t row)
Get row data.
Definition: JMatrixND.hh:222
Nx1 matrix.
Definition: JVectorND.hh:14
JMatrixND & div(const double factor)
Scale matrix.
Definition: JMatrixND.hh:498
friend std::ostream & operator<<(std::ostream &out, const JMatrixND &A)
Print ASCII formatted output.
Definition: JMatrixND.hh:766
JMatrixND & mul(const JMatrixND &A, const JMatrixND &B)
Matrix multiplication.
Definition: JMatrixND.hh:517