This file is indexed.

/usr/include/root/Math/SMatrix.h is in libroot-math-smatrix-dev 5.34.30-0ubuntu8.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
// @(#)root/smatrix:$Id$
// Author: T. Glebe, L. Moneta, J. Palacios    2005

#ifndef ROOT_Math_SMatrix
#define ROOT_Math_SMatrix

/*********************************************************************************
//
// source:
//
// type:      source code
//
// created:   20. Mar 2001
//
// author:    Thorsten Glebe
//            HERA-B Collaboration
//            Max-Planck-Institut fuer Kernphysik
//            Saupfercheckweg 1
//            69117 Heidelberg
//            Germany
//            E-mail: T.Glebe@mpi-hd.mpg.de
//
// Description: A fixed size two dimensional Matrix class
//
// changes:
// 20 Mar 2001 (TG) creation
// 21 Mar 2001 (TG) added operators +=, -=, *=, /=
// 26 Mar 2001 (TG) place_in_row(), place_in_col() added
// 02 Apr 2001 (TG) non-const Array() added
// 03 Apr 2001 (TG) invert() added
// 07 Apr 2001 (TG) CTOR from SVertex (dyadic product) added
// 09 Apr 2001 (TG) CTOR from array added
// 11 Apr 2001 (TG) rows(), cols(), size() replaced by rows, cols, size
// 25 Mai 2001 (TG) row(), col() added
// 04 Sep 2001 (TG) moved inlined functions to .icc file
// 11 Jan 2002 (TG) added operator==(), operator!=()
// 14 Jan 2002 (TG) added more operator==(), operator!=(), operator>(), operator<()
//
***************************************************************************/
// for platform specific configurations

#ifndef ROOT_Math_MnConfig
#include "Math/MConfig.h"
#endif

#include <iosfwd>




//doxygen tag

/**
   @defgroup SMatrixGroup SMatrix 

   \ref SMatrix  for high performance vector and matrix computations.
   Classes representing Matrices and Vectors of arbitrary type and dimension and related functions.  
   For a detailed description and usage examples see: 
   <ul>
    <li>\ref SMatrix home page
    <li>\ref SVectorDoc
    <li>\ref SMatrixDoc
    <li>\ref MatVecFunctions
   </ul>
  
*/

/**
   @defgroup SMatrixSVector Matrix and Vector classes
   
   @ingroup SMatrixGroup

   Classes representing Matrices and Vectors of arbitrary type and dimension. 
   For a detailed description and usage examples see: 
   <ul>
    <li>\ref SVectorDoc
    <li>\ref SMatrixDoc
    <li>\ref MatVecFunctions
   </ul>
  
*/


#ifndef ROOT_Math_Expression
#include "Math/Expression.h"
#endif
#ifndef ROOT_Math_MatrixRepresentationsStatic 
#include "Math/MatrixRepresentationsStatic.h"
#endif


namespace ROOT {

namespace Math {


template <class T, unsigned int D> class SVector;

struct SMatrixIdentity { };
 
//__________________________________________________________________________
/** 
    SMatrix: a generic fixed size D1 x D2 Matrix class.
    The class is template on the scalar type, on the matrix sizes: 
    D1 = number of rows and D2 = number of columns 
    amd on the representation storage type. 
    By default the representation is MatRepStd<T,D1,D2> (standard D1xD2 of type T), 
    but it can be of type MatRepSym<T,D> for symmetric matrices DxD, where the storage is only
    D*(D+1)/2. 

    See \ref SMatrixDoc.

    Original author is Thorsten Glebe
    HERA-B Collaboration, MPI Heidelberg (Germany)
    
    @ingroup SMatrixSVector

    @authors T. Glebe, L. Moneta and J. Palacios
*/
//==============================================================================
// SMatrix: column-wise storage
//==============================================================================
template <class T, 
          unsigned int D1, 
          unsigned int D2 = D1, 
          class R=MatRepStd<T, D1, D2> >
class SMatrix {
public:
   /** @name --- Typedefs --- */
  
   /** contained scalar type */ 
   typedef T  value_type;

   /** storage representation type */
   typedef R  rep_type;

   /** STL iterator interface. */
   typedef T*  iterator;

   /** STL const_iterator interface. */
   typedef const T*  const_iterator;



   /** @name --- Constructors and Assignment --- */

   /**
      Default constructor:
   */
   SMatrix();
   /// 
   /** 
       construct from an identity matrix 
   */
   SMatrix( SMatrixIdentity ); 
   /** 
       copy constructor (from a matrix of the same representation 
   */ 
   SMatrix(const SMatrix<T,D1,D2,R>& rhs);
   /**
      construct from a matrix with different representation.
      Works only from symmetric to general and not viceversa. 
   */ 
   template <class R2>
   SMatrix(const SMatrix<T,D1,D2,R2>& rhs);

   /**
      Construct from an expression. 
      In case of symmetric matrices does not work if expression is of type general 
      matrices. In case one needs to force the assignment from general to symmetric, one can use the 
      ROOT::Math::AssignSym::Evaluate function. 
   */ 
   template <class A, class R2>
   SMatrix(const Expr<A,T,D1,D2,R2>& rhs);


   /**
      Constructor with STL iterator interface. The data will be copied into the matrix
      \param begin start iterator position
      \param end end iterator position
      \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators 
      \param lower if true the lower triangular part is filled 
     
      Size of the matrix must match size of the iterators, if triang is false, otherwise the size of the 
      triangular block. In the case of symmetric matrices triang is considered always to be true 
      (what-ever the user specifies) and the size of the iterators must be equal to the size of the 
      triangular block, which is the number of independent elements of a symmetric matrix:  N*(N+1)/2 
     
   */
   template<class InputIterator>
   SMatrix(InputIterator begin, InputIterator end, bool triang = false, bool lower = true);

   /**
      Constructor with STL iterator interface. The data will be copied into the matrix
      \param begin  start iterator position
      \param size   iterator size 
      \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators 
      \param lower if true the lower triangular part is filled 
    
      Size of the iterators must not be larger than the size of the matrix representation. 
      In the case of symmetric matrices the size is N*(N+1)/2.
    
   */
   template<class InputIterator>
   SMatrix(InputIterator begin, unsigned int size, bool triang = false, bool lower = true);

   /**
      constructor of a symmetrix a matrix from a SVector containing the lower (upper)
      triangular part. 
   */
#ifndef UNSUPPORTED_TEMPLATE_EXPRESSION
   SMatrix(const SVector<T, D1*(D2+1)/2> & v, bool lower = true );
#else
   template<unsigned int N>
   SMatrix(const SVector<T,N> & v, bool lower = true );
#endif


   /** 
       Construct from a scalar value (only for size 1 matrices)
   */
   explicit SMatrix(const T& rhs);

   /** 
       Assign from another compatible matrix. 
       Possible Symmetirc to general but NOT vice-versa
   */
   template <class M>
   SMatrix<T,D1,D2,R>& operator=(const M& rhs);
  
   /** 
       Assign from a matrix expression
   */
   template <class A, class R2>
   SMatrix<T,D1,D2,R>& operator=(const Expr<A,T,D1,D2,R2>& rhs);

   /**
      Assign from an identity matrix
   */
   SMatrix<T,D1,D2,R> & operator=(SMatrixIdentity ); 

   /** 
       Assign from a scalar value (only for size 1 matrices)
   */
   SMatrix<T,D1,D2,R>& operator=(const T& rhs);

   /** @name --- Matrix dimension --- */

   /**
      Enumeration defining the matrix dimension, 
      number of rows, columns and size = rows*columns)
   */
   enum {
      /// return no. of matrix rows
      kRows = D1,
      /// return no. of matrix columns
      kCols = D2,
      /// return no of elements: rows*columns
      kSize = D1*D2
   };

   /** @name --- Access functions --- */

   /** access the parse tree with the index starting from zero and 
       following the C convention for the order in accessing 
       the matrix elements. 
       Same convention for general and symmetric matrices.
   */  
   T apply(unsigned int i) const;

   /// return read-only pointer to internal array
   const T* Array() const;
   /// return pointer to internal array
   T* Array();

   /** @name --- STL-like interface --- 
       The iterators access the matrix element in the order how they are 
       stored in memory. The C (row-major) convention is used, and in the 
       case of symmetric matrices the iterator spans only the lower diagonal 
       block. For example for a symmetric 3x3 matrices the order of the 6 
       elements \f${a_0,...a_5}\f$ is: 
       \f[
       M = \left( \begin{array}{ccc} 
       a_0 & a_1 & a_3  \\ 
       a_1 & a_2  & a_4  \\
       a_3 & a_4 & a_5   \end{array} \right)
       \f]
   */

   /** STL iterator interface. */
   iterator begin();

   /** STL iterator interface. */
   iterator end();

   /** STL const_iterator interface. */
   const_iterator begin() const;

   /** STL const_iterator interface. */
   const_iterator end() const;

   /**
      Set matrix elements with STL iterator interface. The data will be copied into the matrix
      \param begin start iterator position
      \param end end iterator position
      \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators 
      \param lower if true the lower triangular part is filled 
     
      Size of the matrix must match size of the iterators, if triang is false, otherwise the size of the 
      triangular block. In the case of symmetric matrices triang is considered always to be true 
      (what-ever the user specifies) and the size of the iterators must be equal to the size of the 
      triangular block, which is the number of independent elements of a symmetric matrix:  N*(N+1)/2 
     
   */
   template<class InputIterator>
   void SetElements(InputIterator begin, InputIterator end, bool triang = false, bool lower = true);

   /**
      Constructor with STL iterator interface. The data will be copied into the matrix
      \param begin  start iterator position
      \param size   iterator size 
      \param triang if true only the triangular lower/upper part of the matrix is filled from the iterators 
      \param lower if true the lower triangular part is filled 
    
      Size of the iterators must not be larger than the size of the matrix representation. 
      In the case of symmetric matrices the size is N*(N+1)/2.
    
   */
   template<class InputIterator>
   void SetElements(InputIterator begin, unsigned int size, bool triang = false, bool lower = true);


   /** @name --- Operators --- */
   /// element wise comparison
   bool operator==(const T& rhs) const;
   /// element wise comparison
   bool operator!=(const T& rhs) const;
   /// element wise comparison
   template <class R2>
   bool operator==(const SMatrix<T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   bool operator!=(const SMatrix<T,D1,D2,R>& rhs) const;
   /// element wise comparison
   template <class A, class R2>
   bool operator==(const Expr<A,T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   template <class A, class R2>
   bool operator!=(const Expr<A,T,D1,D2,R2>& rhs) const;

   /// element wise comparison
   bool operator>(const T& rhs) const;
   /// element wise comparison
   bool operator<(const T& rhs) const;
   /// element wise comparison
   template <class R2>
   bool operator>(const SMatrix<T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   template <class R2>
   bool operator<(const SMatrix<T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   template <class A, class R2>
   bool operator>(const Expr<A,T,D1,D2,R2>& rhs) const;
   /// element wise comparison
   template <class A, class R2>
   bool operator<(const Expr<A,T,D1,D2,R2>& rhs) const;

   /**
      read only access to matrix element, with indices starting from 0
   */ 
   const T& operator()(unsigned int i, unsigned int j) const;
    /**
      read/write access to matrix element with indices starting from 0
   */ 
   T& operator()(unsigned int i, unsigned int j);

   /**
      read only access to matrix element, with indices starting from 0.
      Function will check index values and it will assert if they are wrong 
   */ 
   const T& At(unsigned int i, unsigned int j) const;
   /**
      read/write access to matrix element with indices starting from 0.
      Function will check index values and it will assert if they are wrong 
   */ 
   T& At(unsigned int i, unsigned int j);


  // helper class for implementing the m[i][j] operator

   class SMatrixRow {
   public: 
      SMatrixRow ( SMatrix<T,D1,D2,R> & rhs, unsigned int i ) : 
         fMat(&rhs), fRow(i) 
      {}
      T & operator[](int j) { return (*fMat)(fRow,j); }
   private:    
      SMatrix<T,D1,D2,R> *  fMat;
      unsigned int fRow;
   };

   class SMatrixRow_const {
   public: 
      SMatrixRow_const ( const SMatrix<T,D1,D2,R> & rhs, unsigned int i ) : 
         fMat(&rhs), fRow(i) 
      {}
      
      const T & operator[](int j) const { return (*fMat)(fRow, j); }

   private: 
      const SMatrix<T,D1,D2,R> *  fMat;
      unsigned int fRow;
   };
 
  /**
      read only access to matrix element, with indices starting from 0 : m[i][j] 
   */ 
   SMatrixRow_const  operator[](unsigned int i) const { return SMatrixRow_const(*this, i); }
   /**
      read/write access to matrix element with indices starting from 0 : m[i][j] 
   */ 
   SMatrixRow operator[](unsigned int i) { return SMatrixRow(*this, i); }


   /**
      addition with a scalar
   */ 
   SMatrix<T,D1,D2,R>&operator+=(const T& rhs);

   /**
      addition with another matrix of any compatible representation
   */ 
   template <class R2>   
   SMatrix<T,D1,D2,R>&operator+=(const SMatrix<T,D1,D2,R2>& rhs);

   /**  
      addition with a compatible matrix expression  
   */
   template <class A, class R2>
   SMatrix<T,D1,D2,R>& operator+=(const Expr<A,T,D1,D2,R2>& rhs);

   /**
      subtraction with a scalar
   */ 
   SMatrix<T,D1,D2,R>& operator-=(const T& rhs);

   /**
      subtraction with another matrix of any compatible representation
   */ 
   template <class R2>   
   SMatrix<T,D1,D2,R>&operator-=(const SMatrix<T,D1,D2,R2>& rhs);

   /**  
      subtraction with a compatible matrix expression  
   */
   template <class A, class R2>
   SMatrix<T,D1,D2,R>& operator-=(const Expr<A,T,D1,D2,R2>& rhs);

   /**
      multiplication with a scalar
    */
   SMatrix<T,D1,D2,R>& operator*=(const T& rhs);

#ifndef __CINT__


   /**  
      multiplication with another compatible matrix (it is a real matrix multiplication) 
      Note that this operation does not avid to create a temporary to store intermidiate result
   */
   template <class R2>
   SMatrix<T,D1,D2,R>& operator*=(const SMatrix<T,D1,D2,R2>& rhs);

   /**  
      multiplication with a compatible matrix expression (it is a real matrix multiplication) 
   */
   template <class A, class R2>
   SMatrix<T,D1,D2,R>& operator*=(const Expr<A,T,D1,D2,R2>& rhs);

#endif
  
   /**
      division with a scalar
   */
   SMatrix<T,D1,D2,R>& operator/=(const T& rhs);
 


   /** @name --- Linear Algebra Functions --- */

   /**
      Invert a square Matrix ( this method changes the current matrix).
      Return true if inversion is successfull.
      The method used for general square matrices is the LU factorization taken from Dinv routine 
      from the CERNLIB (written in C++ from CLHEP authors)
      In case of symmetric matrices Bunch-Kaufman diagonal pivoting method is used
      (The implementation is the one written by the CLHEP authors)
   */
   bool Invert();

   /**
      Invert a square Matrix and  returns a new matrix. In case the inversion fails
      the current matrix is returned. 
      \param ifail . ifail will be set to 0 when inversion is successfull.  
      See ROOT::Math::SMatrix::Invert for the inversion algorithm
   */
   SMatrix<T,D1,D2,R> Inverse(int & ifail ) const;

   /**
      Fast Invertion of a square Matrix ( this method changes the current matrix).
      Return true if inversion is successfull.
      The method used is based on direct inversion using the Cramer rule for 
      matrices upto 5x5. Afterwards the same default algorithm of Invert() is used. 
      Note that this method is faster but can suffer from much larger numerical accuracy 
      when the condition of the matrix is large
   */
   bool InvertFast();

   /**
      Invert a square Matrix and  returns a new matrix. In case the inversion fails
      the current matrix is returned. 
      \param ifail . ifail will be set to 0 when inversion is successfull.  
      See ROOT::Math::SMatrix::InvertFast for the inversion algorithm
   */
   SMatrix<T,D1,D2,R> InverseFast(int & ifail ) const;

   /**
      Invertion of a symmetric positive defined Matrix using Choleski decomposition. 
      ( this method changes the current matrix).
      Return true if inversion is successfull.
      The method used is based on Choleski decomposition
      A compile error is given if the matrix is not of type symmetric and a run-time failure if the 
      matrix is not positive defined. 
      For solving  a linear system, it is possible to use also the function 
      ROOT::Math::SolveChol(matrix, vector) which will be faster than performing the inversion
   */
   bool InvertChol();

   /**
      Invert of a symmetric positive defined Matrix using Choleski decomposition.
      A compile error is given if the matrix is not of type symmetric and a run-time failure if the 
      matrix is not positive defined. 
      In case the inversion fails the current matrix is returned. 
      \param ifail . ifail will be set to 0 when inversion is successfull.  
      See ROOT::Math::SMatrix::InvertChol for the inversion algorithm
   */
   SMatrix<T,D1,D2,R> InverseChol(int & ifail ) const;

   /**
      determinant of square Matrix via Dfact. 
      Return true when the calculation is successfull.
      \param det will contain the calculated determinant value
      \b Note: this will destroy the contents of the Matrix!
   */
   bool Det(T& det);

   /**
      determinant of square Matrix via Dfact. 
      Return true when the calculation is successfull.
      \param det will contain the calculated determinant value
      \b Note: this will preserve the content of the Matrix!
   */
   bool Det2(T& det) const;


   /** @name --- Matrix Slice Functions --- */

   /// place a vector in a Matrix row
   template <unsigned int D>
   SMatrix<T,D1,D2,R>& Place_in_row(const SVector<T,D>& rhs,
                                    unsigned int row,
                                    unsigned int col);
   /// place a vector expression in a Matrix row 
   template <class A, unsigned int D>
   SMatrix<T,D1,D2,R>& Place_in_row(const VecExpr<A,T,D>& rhs,
                                    unsigned int row,
                                    unsigned int col);
   /// place a vector in a Matrix column
   template <unsigned int D>
   SMatrix<T,D1,D2,R>& Place_in_col(const SVector<T,D>& rhs,
                                    unsigned int row,
                                    unsigned int col);
   /// place a vector expression in a Matrix column
   template <class A, unsigned int D>
   SMatrix<T,D1,D2,R>& Place_in_col(const VecExpr<A,T,D>& rhs,
                                    unsigned int row,
                                    unsigned int col);
   /// place a matrix in this matrix
   template <unsigned int D3, unsigned int D4, class R2>
   SMatrix<T,D1,D2,R>& Place_at(const SMatrix<T,D3,D4,R2>& rhs,
                                unsigned int row,
                                unsigned int col);
   /// place a matrix expression in this matrix
   template <class A, unsigned int D3, unsigned int D4, class R2>
   SMatrix<T,D1,D2,R>& Place_at(const Expr<A,T,D3,D4,R2>& rhs,
                                unsigned int row,
                                unsigned int col);

   /**
      return a full Matrix row as a vector (copy the content in a new vector)
   */
   SVector<T,D2> Row(unsigned int therow) const;

   /**
      return a full Matrix column as a vector (copy the content in a new vector)
   */
   SVector<T,D1> Col(unsigned int thecol) const;

   /**
      return a slice of therow as a vector starting at the colum value col0 until col0+N, 
      where N is the size of the vector (SubVector::kSize )
      Condition  col0+N <= D2 
   */
   template <class SubVector>
   SubVector SubRow(unsigned int therow, unsigned int col0 = 0 ) const;

   /**
      return a slice of the column as a vector starting at the row value row0 until row0+Dsub.
      where N is the size of the vector (SubVector::kSize )
      Condition  row0+N <= D1
   */
   template <class SubVector>
   SubVector SubCol(unsigned int thecol, unsigned int row0 = 0) const;

   /**
      return a submatrix with the upper left corner at the values (row0, col0) and with sizes N1, N2
      where N1 and N2 are the dimension of the sub-matrix (SubMatrix::kRows and SubMatrix::kCols )
      Condition  row0+N1 <= D1 && col0+N2 <=D2
   */
   template <class SubMatrix >
   SubMatrix Sub(unsigned int row0, unsigned int col0) const;

   /**
      return diagonal elements of a matrix as a Vector.
      It works only for squared matrices D1 == D2, otherwise it will produce a compile error
   */
   SVector<T,D1> Diagonal() const;

   /**
      Set the diagonal elements from a Vector
      Require that vector implements ::kSize since a check (statically) is done on 
      diagonal size == vector size
   */
   template <class Vector> 
   void SetDiagonal(const Vector & v);

   /**
      return the trace of a matrix
      Sum of the diagonal elements
   */
   T Trace() const; 


   /**
      return the upper Triangular block of the matrices (including the diagonal) as
      a vector of sizes N = D1 * (D1 + 1)/2.
      It works only for square matrices with D1==D2, otherwise it will produce a compile error
   */
#ifndef UNSUPPORTED_TEMPLATE_EXPRESSION
   SVector<T, D1 * (D2 +1)/2> UpperBlock() const;
#else
   template<class SubVector>
   SubVector UpperBlock() const;
#endif

   /**
      return the lower Triangular block of the matrices (including the diagonal) as
      a vector of sizes N = D1 * (D1 + 1)/2.
      It works only for square matrices with D1==D2, otherwise it will produce a compile error
   */
#ifndef UNSUPPORTED_TEMPLATE_EXPRESSION
   SVector<T, D1 * (D2 +1)/2> LowerBlock() const;
#else
   template<class SubVector>
   SubVector LowerBlock() const;
#endif


   /** @name --- Other Functions --- */

   /** 
       Function to check if a matrix is sharing same memory location of the passed pointer
       This function is used by the expression templates to avoid the alias problem during  
       expression evaluation. When  the matrix is in use, for example in operations 
       like A = B * A, a temporary object storing the intermediate result is automatically 
       created when evaluating the expression. 
      
   */
   bool IsInUse(const T* p) const; 

   // submatrices

   /// Print: used by operator<<()
   std::ostream& Print(std::ostream& os) const;



   
public:

   /** @name --- Data Member --- */
   
   /**
      Matrix Storage Object containing matrix data 
   */
   R fRep;
  
}; // end of class SMatrix




//==============================================================================
// operator<<
//==============================================================================
template <class T, unsigned int D1, unsigned int D2, class R>
inline std::ostream& operator<<(std::ostream& os, const ROOT::Math::SMatrix<T,D1,D2,R>& rhs) {
  return rhs.Print(os);
}


  }  // namespace Math

}  // namespace ROOT






#ifndef __CINT__

#ifndef ROOT_Math_SMatrix_icc
#include "Math/SMatrix.icc"
#endif

#ifndef ROOT_Math_MatrixFunctions
#include "Math/MatrixFunctions.h"
#endif

#endif //__CINT__

#endif  /* ROOT_Math_SMatrix  */