// @(#)root/matrix:$Id$
// Authors: Fons Rademakers, Eddy Offermann   Nov 2003

/*************************************************************************
 * Copyright (C) 1995-2000, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#ifndef ROOT_TMatrixTBase
#define ROOT_TMatrixTBase

//////////////////////////////////////////////////////////////////////////
//                                                                      //
// TMatrixTBase                                                         //
//                                                                      //
// Template of base class in the linear algebra package                 //
//                                                                      //
//  matrix properties are stored here, however the data storage is part //
//  of the derived classes                                              //
//                                                                      //
//////////////////////////////////////////////////////////////////////////

//======================================================================//
// Summary of the streamer version history                              //
//======================================================================//
//              3.10/02      4.00/a   4.00/b   4.00/c 4.00-08 5.05-1    //
// TMatrixFBase   -          2        2        2       4      5         //
// TMatrix        2          3        3        3       3      4         //
// TMatrixF       -          3        3        3       3      4         //
// TMatrixFSym    -          1        1        1       1      2         //
// TMatrixDSparse -          -        -        -       -      2         //
//                                                                      //
// TMatrixDBase   -          2        3        3       4      5         //
// TMatrixD       2          3        3        3       3      4         //
// TMatrixDSym    -          1        1        1       1      2         //
// TMatrixDSparse -          -        1        1       1      2         //
//                                                                      //
// TVector        2          3        3        3       3      4         //
// TVectorF       -          2        2        2       3      4         //
//                                                                      //
// TVectorD       2          2        2        2       3      4         //
//======================================================================//
//                                                                      //
// 4.00/a : (Jan 25 2004) introduced new classes/inheritance scheme,    //
//          TMatrix now inherits from TMatrixF                          //
//                                                                      //
//          TMatrixF::TMatrixFBase                                      //
//          TMatrixFSym::TMatrixFBase                                   //
//          TMatrixD::TMatrixDBase                                      //
//          TMatrixDSym::TMatrixDBase                                   //
//                                                                      //
// 4.00/b : (May 12 2004) introduced TMatrixDSparse and added new       //
//          element fNRowIndex to TMatrixFBase and TMatrixDBase         //
//          TMatrixDSparse::TMatrixDBase                                //
//                                                                      //
// 4.00/c : (May 27 2004) Used the TObject::fBits to store validity     //
//           state for vectors and matrices                             //
//                                                                      //
// 5.05-1 :  templates TMatrixTBase,TMatrixT,TMatrixTSym and            //
//           TMatrixTSparse were introduced, all versions were          //
//           increased by 1 .                                           //
//                                                                      //
//======================================================================//

#include <limits>

#ifndef ROOT_TNamed
#include "TNamed.h"
#endif
#ifndef ROOT_TMatrixFBasefwd
#include "TMatrixFBasefwd.h"
#endif
#ifndef ROOT_TMatrixDBasefwd
#include "TMatrixDBasefwd.h"
#endif
#ifndef ROOT_TVectorFfwd
#include "TVectorFfwd.h"
#endif
#ifndef ROOT_TVectorDfwd
#include "TVectorDfwd.h"
#endif
#ifndef ROOT_TError
#include "TError.h"
#endif

template<class Element> class TVectorT;
template<class Element> class TElementActionT;
template<class Element> class TElementPosActionT;

R__EXTERN Int_t gMatrixCheck;

template<class Element> class TMatrixTBase : public TObject {

private:
   Element *GetElements();  // This function is now obsolete (and is not implemented) you should use TMatrix::GetMatrixArray().

protected:
   Int_t    fNrows;               // number of rows
   Int_t    fNcols;               // number of columns
   Int_t    fRowLwb;              // lower bound of the row index
   Int_t    fColLwb;              // lower bound of the col index
   Int_t    fNelems;              // number of elements in matrix
   Int_t    fNrowIndex;           // length of row index array (= fNrows+1) wich is only used for sparse matrices

   Element  fTol;                 // sqrt(epsilon); epsilon is smallest number number so that  1+epsilon > 1
                                  //  fTol is used in matrix decomposition (like in inversion)

   Bool_t   fIsOwner;             //!default kTRUE, when Use array kFALSE

   static  void DoubleLexSort (Int_t n,Int_t *first,Int_t *second,Element *data);
   static  void IndexedLexSort(Int_t n,Int_t *first,Int_t swapFirst,
                               Int_t *second,Int_t swapSecond,Int_t *index);

   enum {kSizeMax = 25};          // size data container on stack, see New_m(),Delete_m()
   enum {kWorkMax = 100};         // size of work array's in several routines

   enum EMatrixStatusBits {
     kStatus = BIT(14) // set if matrix object is valid
   };

public:

   TMatrixTBase():
     fNrows(0), fNcols(0), fRowLwb(0), fColLwb(0), fNelems(0), fNrowIndex(0),
     fTol(0), fIsOwner(kTRUE) { }

   virtual ~TMatrixTBase() {}

           inline       Int_t     GetRowLwb     () const { return fRowLwb; }
           inline       Int_t     GetRowUpb     () const { return fNrows+fRowLwb-1; }
           inline       Int_t     GetNrows      () const { return fNrows; }
           inline       Int_t     GetColLwb     () const { return fColLwb; }
           inline       Int_t     GetColUpb     () const { return fNcols+fColLwb-1; }
           inline       Int_t     GetNcols      () const { return fNcols; }
           inline       Int_t     GetNoElements () const { return fNelems; }
           inline       Element   GetTol        () const { return fTol; }

   virtual        const Element  *GetMatrixArray  () const = 0;
   virtual              Element  *GetMatrixArray  ()       = 0;
   virtual        const Int_t    *GetRowIndexArray() const = 0;
   virtual              Int_t    *GetRowIndexArray()       = 0;
   virtual        const Int_t    *GetColIndexArray() const = 0;
   virtual              Int_t    *GetColIndexArray()       = 0;

   virtual              TMatrixTBase<Element> &SetRowIndexArray(Int_t *data) = 0;
   virtual              TMatrixTBase<Element> &SetColIndexArray(Int_t *data) = 0;
   virtual              TMatrixTBase<Element> &SetMatrixArray  (const Element *data,Option_t *option="");
           inline       Element                SetTol          (Element tol);

   virtual void   Clear      (Option_t *option="") = 0;

   inline  void   Invalidate ()       { SetBit(kStatus); }
   inline  void   MakeValid  ()       { ResetBit(kStatus); }
   inline  Bool_t IsValid    () const { return !TestBit(kStatus); }
   inline  Bool_t IsOwner    () const { return fIsOwner; }
   virtual Bool_t IsSymmetric() const;

   virtual TMatrixTBase<Element> &GetSub(Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb,
                                         TMatrixTBase<Element> &target,Option_t *option="S") const = 0;
   virtual TMatrixTBase<Element> &SetSub(Int_t row_lwb,Int_t col_lwb,const TMatrixTBase<Element> &source) = 0;

   virtual void                   GetMatrix2Array(Element *data,Option_t *option="") const;
   virtual TMatrixTBase<Element> &InsertRow      (Int_t row,Int_t col,const Element *v,Int_t n = -1);
   virtual void                   ExtractRow     (Int_t row,Int_t col,      Element *v,Int_t n = -1) const;

   virtual TMatrixTBase<Element> &Shift          (Int_t row_shift,Int_t col_shift);
   virtual TMatrixTBase<Element> &ResizeTo       (Int_t nrows,Int_t ncols,Int_t nr_nonzeros=-1) = 0;
   virtual TMatrixTBase<Element> &ResizeTo       (Int_t row_lwb,Int_t row_upb,Int_t col_lwb,Int_t col_upb,Int_t nr_nonzeros=-1) = 0;

   virtual Double_t Determinant() const                          { AbstractMethod("Determinant()"); return 0.; }
   virtual void     Determinant(Double_t &d1,Double_t &d2) const { AbstractMethod("Determinant()"); d1 = 0.; d2 = 0.; }

   virtual TMatrixTBase<Element> &Zero       ();
   virtual TMatrixTBase<Element> &Abs        ();
   virtual TMatrixTBase<Element> &Sqr        ();
   virtual TMatrixTBase<Element> &Sqrt       ();
   virtual TMatrixTBase<Element> &UnitMatrix ();

   virtual TMatrixTBase<Element> &NormByDiag (const TVectorT<Element> &v,Option_t *option="D");

   virtual Element RowNorm    () const;
   virtual Element ColNorm    () const;
   virtual Element E2Norm     () const;
   inline  Element NormInf    () const { return RowNorm(); }
   inline  Element Norm1      () const { return ColNorm(); }
   virtual Int_t   NonZeros   () const;
   virtual Element Sum        () const;
   virtual Element Min        () const;
   virtual Element Max        () const;

   void Draw (Option_t *option="");       // *MENU*
   void Print(Option_t *name  ="") const; // *MENU*

   virtual Element   operator()(Int_t rown,Int_t coln) const = 0;
   virtual Element  &operator()(Int_t rown,Int_t coln)       = 0;

   Bool_t operator==(Element val) const;
   Bool_t operator!=(Element val) const;
   Bool_t operator< (Element val) const;
   Bool_t operator<=(Element val) const;
   Bool_t operator> (Element val) const;
   Bool_t operator>=(Element val) const;

   virtual TMatrixTBase<Element> &Apply(const TElementActionT<Element>    &action);
   virtual TMatrixTBase<Element> &Apply(const TElementPosActionT<Element> &action);

   virtual TMatrixTBase<Element> &Randomize(Element alpha,Element beta,Double_t &seed);

   // make it public since it can be called by TMatrixTRow
   static Element & NaNValue();

   ClassDef(TMatrixTBase,5) // Matrix base class (template)
};

template<class Element> Element TMatrixTBase<Element>::SetTol(Element newTol)
{
   const Element  oldTol = fTol;
   if (newTol >= 0.0)
      fTol = newTol;
   return oldTol;
}

template<class Element> Bool_t  operator==   (const TMatrixTBase<Element>  &m1,const TMatrixTBase<Element>  &m2);
template<class Element> Element E2Norm       (const TMatrixTBase<Element>  &m1,const TMatrixTBase<Element>  &m2);
template<class Element1,class Element2>
                        Bool_t  AreCompatible(const TMatrixTBase<Element1> &m1,const TMatrixTBase<Element2> &m2,Int_t verbose=0);
template<class Element> void    Compare      (const TMatrixTBase<Element>  &m1,const TMatrixTBase<Element>  &m2);

// Service functions (useful in the verification code).
// They print some detail info if the validation condition fails

template<class Element> Bool_t VerifyMatrixValue   (const TMatrixTBase<Element> &m,Element val,
                                                    Int_t verbose,Element maxDevAllow);
template<class Element> Bool_t VerifyMatrixValue   (const TMatrixTBase<Element> &m,Element val,Int_t verbose)
                                                                           { return VerifyMatrixValue(m,val,verbose,Element(0.)); }
template<class Element> Bool_t VerifyMatrixValue   (const TMatrixTBase<Element> &m,Element val)
                                                                           { return VerifyMatrixValue(m,val,1,Element(0.)); }
template<class Element> Bool_t VerifyMatrixIdentity(const TMatrixTBase<Element> &m1,const TMatrixTBase<Element> &m2,
                                                    Int_t verbose,Element maxDevAllow);
template<class Element> Bool_t VerifyMatrixIdentity(const TMatrixTBase<Element> &m1,const TMatrixTBase<Element> &m2,Int_t verbose)
                                                                           { return VerifyMatrixIdentity(m1,m2,verbose,Element(0.)); }
template<class Element> Bool_t VerifyMatrixIdentity(const TMatrixTBase<Element> &m1,const TMatrixTBase<Element> &m2)
                                                                           { return VerifyMatrixIdentity(m1,m2,1,Element(0.)); }

#endif
 TMatrixTBase.h:1
 TMatrixTBase.h:2
 TMatrixTBase.h:3
 TMatrixTBase.h:4
 TMatrixTBase.h:5
 TMatrixTBase.h:6
 TMatrixTBase.h:7
 TMatrixTBase.h:8
 TMatrixTBase.h:9
 TMatrixTBase.h:10
 TMatrixTBase.h:11
 TMatrixTBase.h:12
 TMatrixTBase.h:13
 TMatrixTBase.h:14
 TMatrixTBase.h:15
 TMatrixTBase.h:16
 TMatrixTBase.h:17
 TMatrixTBase.h:18
 TMatrixTBase.h:19
 TMatrixTBase.h:20
 TMatrixTBase.h:21
 TMatrixTBase.h:22
 TMatrixTBase.h:23
 TMatrixTBase.h:24
 TMatrixTBase.h:25
 TMatrixTBase.h:26
 TMatrixTBase.h:27
 TMatrixTBase.h:28
 TMatrixTBase.h:29
 TMatrixTBase.h:30
 TMatrixTBase.h:31
 TMatrixTBase.h:32
 TMatrixTBase.h:33
 TMatrixTBase.h:34
 TMatrixTBase.h:35
 TMatrixTBase.h:36
 TMatrixTBase.h:37
 TMatrixTBase.h:38
 TMatrixTBase.h:39
 TMatrixTBase.h:40
 TMatrixTBase.h:41
 TMatrixTBase.h:42
 TMatrixTBase.h:43
 TMatrixTBase.h:44
 TMatrixTBase.h:45
 TMatrixTBase.h:46
 TMatrixTBase.h:47
 TMatrixTBase.h:48
 TMatrixTBase.h:49
 TMatrixTBase.h:50
 TMatrixTBase.h:51
 TMatrixTBase.h:52
 TMatrixTBase.h:53
 TMatrixTBase.h:54
 TMatrixTBase.h:55
 TMatrixTBase.h:56
 TMatrixTBase.h:57
 TMatrixTBase.h:58
 TMatrixTBase.h:59
 TMatrixTBase.h:60
 TMatrixTBase.h:61
 TMatrixTBase.h:62
 TMatrixTBase.h:63
 TMatrixTBase.h:64
 TMatrixTBase.h:65
 TMatrixTBase.h:66
 TMatrixTBase.h:67
 TMatrixTBase.h:68
 TMatrixTBase.h:69
 TMatrixTBase.h:70
 TMatrixTBase.h:71
 TMatrixTBase.h:72
 TMatrixTBase.h:73
 TMatrixTBase.h:74
 TMatrixTBase.h:75
 TMatrixTBase.h:76
 TMatrixTBase.h:77
 TMatrixTBase.h:78
 TMatrixTBase.h:79
 TMatrixTBase.h:80
 TMatrixTBase.h:81
 TMatrixTBase.h:82
 TMatrixTBase.h:83
 TMatrixTBase.h:84
 TMatrixTBase.h:85
 TMatrixTBase.h:86
 TMatrixTBase.h:87
 TMatrixTBase.h:88
 TMatrixTBase.h:89
 TMatrixTBase.h:90
 TMatrixTBase.h:91
 TMatrixTBase.h:92
 TMatrixTBase.h:93
 TMatrixTBase.h:94
 TMatrixTBase.h:95
 TMatrixTBase.h:96
 TMatrixTBase.h:97
 TMatrixTBase.h:98
 TMatrixTBase.h:99
 TMatrixTBase.h:100
 TMatrixTBase.h:101
 TMatrixTBase.h:102
 TMatrixTBase.h:103
 TMatrixTBase.h:104
 TMatrixTBase.h:105
 TMatrixTBase.h:106
 TMatrixTBase.h:107
 TMatrixTBase.h:108
 TMatrixTBase.h:109
 TMatrixTBase.h:110
 TMatrixTBase.h:111
 TMatrixTBase.h:112
 TMatrixTBase.h:113
 TMatrixTBase.h:114
 TMatrixTBase.h:115
 TMatrixTBase.h:116
 TMatrixTBase.h:117
 TMatrixTBase.h:118
 TMatrixTBase.h:119
 TMatrixTBase.h:120
 TMatrixTBase.h:121
 TMatrixTBase.h:122
 TMatrixTBase.h:123
 TMatrixTBase.h:124
 TMatrixTBase.h:125
 TMatrixTBase.h:126
 TMatrixTBase.h:127
 TMatrixTBase.h:128
 TMatrixTBase.h:129
 TMatrixTBase.h:130
 TMatrixTBase.h:131
 TMatrixTBase.h:132
 TMatrixTBase.h:133
 TMatrixTBase.h:134
 TMatrixTBase.h:135
 TMatrixTBase.h:136
 TMatrixTBase.h:137
 TMatrixTBase.h:138
 TMatrixTBase.h:139
 TMatrixTBase.h:140
 TMatrixTBase.h:141
 TMatrixTBase.h:142
 TMatrixTBase.h:143
 TMatrixTBase.h:144
 TMatrixTBase.h:145
 TMatrixTBase.h:146
 TMatrixTBase.h:147
 TMatrixTBase.h:148
 TMatrixTBase.h:149
 TMatrixTBase.h:150
 TMatrixTBase.h:151
 TMatrixTBase.h:152
 TMatrixTBase.h:153
 TMatrixTBase.h:154
 TMatrixTBase.h:155
 TMatrixTBase.h:156
 TMatrixTBase.h:157
 TMatrixTBase.h:158
 TMatrixTBase.h:159
 TMatrixTBase.h:160
 TMatrixTBase.h:161
 TMatrixTBase.h:162
 TMatrixTBase.h:163
 TMatrixTBase.h:164
 TMatrixTBase.h:165
 TMatrixTBase.h:166
 TMatrixTBase.h:167
 TMatrixTBase.h:168
 TMatrixTBase.h:169
 TMatrixTBase.h:170
 TMatrixTBase.h:171
 TMatrixTBase.h:172
 TMatrixTBase.h:173
 TMatrixTBase.h:174
 TMatrixTBase.h:175
 TMatrixTBase.h:176
 TMatrixTBase.h:177
 TMatrixTBase.h:178
 TMatrixTBase.h:179
 TMatrixTBase.h:180
 TMatrixTBase.h:181
 TMatrixTBase.h:182
 TMatrixTBase.h:183
 TMatrixTBase.h:184
 TMatrixTBase.h:185
 TMatrixTBase.h:186
 TMatrixTBase.h:187
 TMatrixTBase.h:188
 TMatrixTBase.h:189
 TMatrixTBase.h:190
 TMatrixTBase.h:191
 TMatrixTBase.h:192
 TMatrixTBase.h:193
 TMatrixTBase.h:194
 TMatrixTBase.h:195
 TMatrixTBase.h:196
 TMatrixTBase.h:197
 TMatrixTBase.h:198
 TMatrixTBase.h:199
 TMatrixTBase.h:200
 TMatrixTBase.h:201
 TMatrixTBase.h:202
 TMatrixTBase.h:203
 TMatrixTBase.h:204
 TMatrixTBase.h:205
 TMatrixTBase.h:206
 TMatrixTBase.h:207
 TMatrixTBase.h:208
 TMatrixTBase.h:209
 TMatrixTBase.h:210
 TMatrixTBase.h:211
 TMatrixTBase.h:212
 TMatrixTBase.h:213
 TMatrixTBase.h:214
 TMatrixTBase.h:215
 TMatrixTBase.h:216
 TMatrixTBase.h:217
 TMatrixTBase.h:218
 TMatrixTBase.h:219
 TMatrixTBase.h:220
 TMatrixTBase.h:221
 TMatrixTBase.h:222
 TMatrixTBase.h:223
 TMatrixTBase.h:224
 TMatrixTBase.h:225
 TMatrixTBase.h:226
 TMatrixTBase.h:227
 TMatrixTBase.h:228
 TMatrixTBase.h:229
 TMatrixTBase.h:230
 TMatrixTBase.h:231
 TMatrixTBase.h:232
 TMatrixTBase.h:233
 TMatrixTBase.h:234
 TMatrixTBase.h:235
 TMatrixTBase.h:236
 TMatrixTBase.h:237
 TMatrixTBase.h:238
 TMatrixTBase.h:239
 TMatrixTBase.h:240
 TMatrixTBase.h:241
 TMatrixTBase.h:242
 TMatrixTBase.h:243
 TMatrixTBase.h:244
 TMatrixTBase.h:245
 TMatrixTBase.h:246
 TMatrixTBase.h:247
 TMatrixTBase.h:248