Back to home page

EIC code displayed by LXR

 
 

    


Warning, /include/Geant4/tools/lina/MATCOM is written in an unsupported language. File is not indexed.

0001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
0002 // See the file tools.license for terms.
0003 
0004 #ifndef tools_MATCOM
0005 #define tools_MATCOM
0006 
0007 #include "../eqT"
0008 
0009 #include <cstddef> //size_t
0010 
0011 // common code to class mat and nmat.
0012 
0013 #define TOOLS_MATCOM \
0014 protected:\
0015   static T zero() {return T();}\
0016   static T one() {return T(1);}\
0017   static T minus_one() {return T(-1);}\
0018   static T two() {return T(2);}\
0019 public:\
0020   typedef T elem_t;\
0021   typedef unsigned int size_type;\
0022 public:\
0023   unsigned int rows() const {return dimension();}\
0024   unsigned int cols() const {return dimension();}\
0025 \
0026   void set_value(unsigned int aR,unsigned int aC,const T& a_value) { \
0027     m_vec[aR + aC * dimension()] = a_value;\
0028   }\
0029 \
0030   const T& value(unsigned int aR,unsigned int aC) const { \
0031     return m_vec[aR + aC * dimension()];\
0032   }\
0033 \
0034   T value(unsigned int aR,unsigned int aC) { \
0035     return m_vec[aR + aC * dimension()];\
0036   }\
0037 \
0038   void set_matrix(const TOOLS_MAT_CLASS& a_m){ /*optimization.*/\
0039     _copy(a_m.m_vec);\
0040   }\
0041 \
0042   void set_constant(const T& a_v){\
0043     for(unsigned int i=0;i<dim2();i++) m_vec[i] = a_v;\
0044   }\
0045   void set_zero(){\
0046     set_constant(zero());\
0047   }\
0048   void set_identity() {\
0049     set_zero();\
0050     for(unsigned int i=0;i<dimension();i++) m_vec[i+i*dimension()] = one();\
0051   }\
0052   void set_diagonal(const T& a_s) {\
0053     set_zero();\
0054     for(unsigned int i=0;i<dimension();i++) m_vec[i+i*dimension()] = a_s;\
0055   }\
0056   typedef T (*func)(const T&);\
0057   void apply_func(func a_func) {\
0058     T* pos = m_vec;\
0059     for(unsigned int i=0;i<dim2();i++,pos++) *pos = a_func(*pos);\
0060   }\
0061   template <class RANDOM>\
0062   void set_random(RANDOM& a_random) {\
0063     for(unsigned int i=0;i<dim2();i++) m_vec[i] = a_random.shoot();\
0064   }\
0065   template <class RANDOM>\
0066   void set_symmetric_random(RANDOM& a_random) {\
0067     unsigned int _D = dimension();\
0068    {for(unsigned int r=0;r<_D;r++) set_value(r,r,a_random.shoot());}\
0069     T rd;\
0070    {for(unsigned int r=0;r<_D;r++) {\
0071       for(unsigned int c=(r+1);c<_D;c++) {\
0072         rd = a_random.shoot();\
0073         set_value(r,c,rd);\
0074         set_value(c,r,rd);\
0075       }\
0076     }}\
0077   }\
0078   template <class RANDOM>\
0079   void set_antisymmetric_random(RANDOM& a_random) {\
0080     unsigned int _D = dimension();\
0081    {for(unsigned int r=0;r<_D;r++) set_value(r,r,zero());}\
0082     T rd;\
0083    {for(unsigned int r=0;r<_D;r++) {\
0084       for(unsigned int c=(r+1);c<_D;c++) {\
0085         rd = a_random.shoot();\
0086         set_value(r,c,rd);\
0087         set_value(c,r,minus_one()*rd);\
0088       }\
0089     }}\
0090   }\
0091 public:\
0092   template <class ARRAY>\
0093   bool mul_array(ARRAY& a_array,T a_tmp[]) const {\
0094     /* a_array = this *= a_array */\
0095     unsigned int _dim = dimension();\
0096     T* pos = a_tmp;\
0097     for(unsigned int r=0;r<_dim;r++,pos++) {\
0098       *pos = T();\
0099       for(unsigned int c=0;c<_dim;c++) *pos += m_vec[r+c*_dim]*a_array[c];\
0100     }\
0101    {for(unsigned int i=0;i<_dim;i++) a_array[i] = a_tmp[i];}\
0102     return true;\
0103   }\
0104   template <class VEC>\
0105   bool mul_vec(VEC& a_vec,T a_tmp[]) const {\
0106     /* a_vec = this *= a_vec */\
0107     unsigned int _dim = dimension();\
0108     if(a_vec.dimension()!=_dim) return false;\
0109     T* pos = a_tmp;\
0110     for(unsigned int r=0;r<_dim;r++,pos++) {\
0111       *pos = T();\
0112       for(unsigned int c=0;c<_dim;c++) *pos += m_vec[r+c*_dim]*a_vec[c];\
0113     }\
0114    {for(unsigned int i=0;i<_dim;i++) a_vec[i] = a_tmp[i];}\
0115     return true;\
0116   }\
0117   template <class VEC>\
0118   bool mul_vec(VEC& a_vec) const {\
0119     T* _tmp = new T[dimension()];\
0120     bool status = mul_vec(a_vec,_tmp);\
0121     delete [] _tmp;\
0122     return status;\
0123   }\
0124 \
0125   bool mul_array(T a_vec[],T a_tmp[]) const {\
0126     /* a_vec = this *= a_vec */\
0127     unsigned int _dim = dimension();\
0128     T* pos = a_tmp;\
0129     for(unsigned int r=0;r<_dim;r++,pos++) {\
0130       *pos = T();\
0131       for(unsigned int c=0;c<_dim;c++) *pos += m_vec[r+c*_dim]*a_vec[c];\
0132     }\
0133    {for(unsigned int i=0;i<_dim;i++) a_vec[i] = a_tmp[i];}\
0134     return true;\
0135   }\
0136   bool mul_array(T a_vec[]) const {\
0137     T* _tmp = new T[dimension()];\
0138     bool status = mul_array(a_vec,_tmp);\
0139     delete [] _tmp;\
0140     return status;\
0141   }\
0142 \
0143   void mul_mtx(const TOOLS_MAT_CLASS& a_m) {\
0144     _mul_mtx(a_m.m_vec);\
0145   }\
0146   void mul_mtx(const TOOLS_MAT_CLASS& a_m,T a_tmp[]) {\
0147     _mul_mtx(a_m.m_vec,a_tmp);\
0148   }\
0149   void left_mul_mtx(const TOOLS_MAT_CLASS& a_m) {    \
0150     /* this = a_m * this :*/\
0151     _left_mul_mtx(a_m.m_vec);\
0152   }\
0153   bool equal(const TOOLS_MAT_CLASS& a_m) const {\
0154     if(&a_m==this) return true;\
0155     for(unsigned int i=0;i<dim2();i++) {\
0156       if(m_vec[i]!=a_m.m_vec[i]) return false;\
0157     }\
0158     return true;\
0159   }\
0160 \
0161   bool equal(const TOOLS_MAT_CLASS& a_m,const T& a_prec) const {\
0162     if(&a_m==this) return true;\
0163     T* tp = (T*)m_vec;\
0164     T* mp = (T*)a_m.m_vec;\
0165     for(unsigned int i=0;i<dim2();i++,tp++,mp++) {\
0166       T diff = (*tp) - (*mp);\
0167       if(diff<zero()) diff *= minus_one();\
0168       if(diff>=a_prec) return false;\
0169     }\
0170     return true;\
0171   }\
0172 \
0173   template <class PREC>\
0174   bool equal_prec(const TOOLS_MAT_CLASS& a_m,const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0175     if(&a_m==this) return true;\
0176     T* tp = (T*)m_vec;\
0177     T* mp = (T*)a_m.m_vec;\
0178     for(unsigned int i=0;i<dim2();i++,tp++,mp++) {\
0179       T diff = (*tp) - (*mp);\
0180       if(a_fabs(diff)>=a_prec) return false;\
0181     }\
0182     return true;\
0183   }\
0184 \
0185   void mx_diff(const TOOLS_MAT_CLASS& a_m,T& a_mx_diff) const {\
0186     T* tp = (T*)m_vec;\
0187     T* mp = (T*)a_m.m_vec;\
0188     a_mx_diff = (*tp) - (*mp);\
0189     if(a_mx_diff<zero()) a_mx_diff *= minus_one();\
0190     for(unsigned int i=0;i<dim2();i++,tp++,mp++) {\
0191       T diff = (*tp) - (*mp);\
0192       if(diff<zero()) diff *= minus_one();\
0193       a_mx_diff = (diff>a_mx_diff?diff:a_mx_diff);\
0194     }\
0195   }\
0196 \
0197   bool to_rm_is_proportional(const TOOLS_MAT_CLASS& a_m,const T& a_prec,T& a_factor) const {\
0198     if(&a_m==this) {a_factor=one();return true;}\
0199     /* If true, then : a_m = a_factor * this.*/\
0200     a_factor = zero();\
0201     T* tp = (T*)m_vec;\
0202     T* mp = (T*)a_m.m_vec;\
0203     bool first = true;\
0204     for(unsigned int i=0;i<dim2();i++,tp++,mp++) {\
0205              if( ((*tp)==zero()) && ((*mp)==zero())) {\
0206         continue;\
0207       } else if( ((*tp)==zero()) && ((*mp)!=zero())) {\
0208         return false;\
0209       } else {\
0210         if(first) {\
0211           a_factor = (*mp)/(*tp);\
0212           first = false;\
0213         } else {\
0214           T diff = (*tp)*a_factor - (*mp);\
0215           if(diff<zero()) diff *= minus_one();\
0216           if(diff>=a_prec) return false;\
0217         }\
0218       }\
0219     }\
0220     return true;\
0221   }\
0222 \
0223 public:\
0224   bool is_proportional(const TOOLS_MAT_CLASS& a_right,T& a_factor) const {\
0225     /* If true, then : a_right = a_factor * this. a_factor could be zero.*/\
0226     if(this==&a_right) {a_factor=T(1);return true;}\
0227     a_factor = zero();\
0228     if(dimension()!=a_right.dimension()) return false;\
0229     T* lp = (T*)m_vec;\
0230     T* rp = (T*)a_right.m_vec;\
0231     bool first = true;\
0232     size_t _data_size = data_size();\
0233     for(size_t i=0;i<_data_size;i++,lp++,rp++) {\
0234       if(*lp==zero()) {\
0235         if(*rp==zero()) continue;\
0236         return false;\
0237       }\
0238       if(first) {\
0239         a_factor = (*rp)/(*lp);\
0240         first = false;\
0241         continue;\
0242       }\
0243       if((*lp)*a_factor!=(*rp)) return false;\
0244     }\
0245     return true;\
0246   }\
0247 \
0248   template <class PREC>\
0249   bool is_proportional_prec(const TOOLS_MAT_CLASS& a_right,const PREC& a_prec,PREC(*a_fabs)(const T&),T& a_factor) const {\
0250     /* If true, then : a_right = a_factor * this. a_factor could be zero.*/\
0251     if(this==&a_right) {a_factor=T(1);return true;}\
0252     a_factor = zero();\
0253     if(dimension()!=a_right.dimension()) return false;\
0254     T* lp = (T*)m_vec;\
0255     T* rp = (T*)a_right.m_vec;\
0256     bool first = true;\
0257     size_t _data_size = data_size();\
0258     for(size_t i=0;i<_data_size;i++,lp++,rp++) {\
0259       if(is_zero(*lp,a_prec,a_fabs)) {\
0260         if(is_zero(*rp,a_prec,a_fabs)) continue;\
0261         return false;\
0262       }\
0263       if(first) {\
0264         a_factor = (*rp)/(*lp);\
0265         first = false;\
0266         continue;\
0267       }\
0268       if(!numbers_are_equal((*lp)*a_factor,*rp,a_prec,a_fabs)) return false;\
0269     }\
0270     return true;\
0271   }\
0272 \
0273   bool is_diagonal() const {\
0274     unsigned int _D = dimension();\
0275     for(unsigned int r=0;r<_D;r++) {\
0276       for(unsigned int c=0;c<_D;c++) {\
0277         if(c!=r) {if(value(r,c)!=zero()) return false;}\
0278       }\
0279     }\
0280     return true;\
0281   }\
0282 \
0283   template <class PREC>\
0284   bool is_diagonal_prec(const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0285     unsigned int _D = dimension();\
0286     for(unsigned int r=0;r<_D;r++) {\
0287       for(unsigned int c=0;c<_D;c++) {\
0288         if(c!=r) {if(!is_zero(value(r,c),a_prec,a_fabs)) return false;}\
0289       }\
0290     }\
0291     return true;\
0292   }\
0293 \
0294   bool is_identity() const {\
0295     unsigned int _D = dimension();\
0296    {for(unsigned int r=0;r<_D;r++) {\
0297       if(value(r,r)!=one()) return false;\
0298     }}\
0299    {for(unsigned int r=0;r<_D;r++) {\
0300       for(unsigned int c=0;c<_D;c++) {\
0301         if(c!=r) {if(value(r,c)!=zero()) return false;}\
0302       }\
0303     }}\
0304     return true;\
0305   }\
0306 \
0307   template <class PREC>\
0308   bool is_identity_prec(const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0309     unsigned int _D = dimension();\
0310    {for(unsigned int r=0;r<_D;r++) {\
0311       if(!numbers_are_equal(value(r,r),one(),a_prec,a_fabs)) return false;\
0312     }}\
0313    {for(unsigned int r=0;r<_D;r++) {\
0314       for(unsigned int c=0;c<_D;c++) {\
0315         if(c!=r) {if(!is_zero(value(r,c),a_prec,a_fabs)) return false;}\
0316       }\
0317     }}\
0318     return true;\
0319   }\
0320 \
0321   const T* data() const {return m_vec;}\
0322   unsigned int size() const {return dim2();}\
0323   unsigned int data_size() const {return dim2();} /*for mathz*/\
0324 \
0325   T trace() const {\
0326     T _value = zero();\
0327     unsigned int _D = dimension();\
0328     for(unsigned int c=0;c<_D;c++) _value += m_vec[c+c*_D];\
0329     return _value;\
0330   }\
0331 \
0332   void transpose() {\
0333     unsigned int _D = dimension();\
0334     for(unsigned int r=0;r<_D;r++) {\
0335       for(unsigned int c=(r+1);c<_D;c++) {\
0336         T vrc = value(r,c);\
0337         T vcr = value(c,r);\
0338         set_value(r,c,vcr);\
0339         set_value(c,r,vrc);\
0340       }\
0341     }\
0342   }\
0343 \
0344   void multiply(const T& a_T) {\
0345     for(unsigned int i=0;i<dim2();i++) m_vec[i] *= a_T;\
0346   }\
0347 \
0348   bool is_symmetric() const {\
0349     unsigned int _D = dimension();\
0350     for(unsigned int r=0;r<_D;r++) {\
0351       for(unsigned int c=(r+1);c<_D;c++) {\
0352         if(value(r,c)!=value(c,r)) return false;\
0353       }\
0354     }\
0355     return true;\
0356   }\
0357 \
0358   template <class PREC>\
0359   bool is_symmetric_prec(const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0360     unsigned int _D = dimension();\
0361     for(unsigned int r=0;r<_D;r++) {\
0362       for(unsigned int c=(r+1);c<_D;c++) {\
0363         T diff = value(r,c)-value(c,r);\
0364         if(a_fabs(diff)>=a_prec) return false;\
0365       }\
0366     }\
0367     return true;\
0368   }\
0369 \
0370   bool is_antisymmetric() const {\
0371     unsigned int _D = dimension();\
0372    {for(unsigned int r=0;r<_D;r++) {\
0373       if(value(r,r)!=zero()) return false;\
0374     }}\
0375     for(unsigned int r=0;r<_D;r++) {\
0376       for(unsigned int c=(r+1);c<_D;c++) {\
0377         if(value(r,c)!=minus_one()*value(c,r)) return false;\
0378       }\
0379     }\
0380     return true;\
0381   }\
0382 \
0383   template <class PREC>\
0384   bool is_antisymmetric_prec(const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0385     unsigned int _D = dimension();\
0386    {for(unsigned int r=0;r<_D;r++) {\
0387       if(a_fabs(value(r,r))>=a_prec) return false;\
0388     }}\
0389     for(unsigned int r=0;r<_D;r++) {\
0390       for(unsigned int c=(r+1);c<_D;c++) {\
0391         T diff = value(r,c)-minus_one()*value(c,r);\
0392         if(a_fabs(diff)>=a_prec) return false;\
0393       }\
0394     }\
0395     return true;\
0396   }\
0397 \
0398   void symmetric_part(TOOLS_MAT_CLASS& a_res) const {\
0399     a_res = *this;\
0400     a_res.transpose();\
0401     a_res += *this;\
0402     a_res.multiply(one()/two());\
0403   }\
0404 \
0405   void antisymmetric_part(TOOLS_MAT_CLASS& a_res) const {\
0406     a_res = *this;\
0407     a_res.transpose();\
0408     a_res.multiply(minus_one());\
0409     a_res += *this;\
0410     a_res.multiply(one()/two());\
0411   }\
0412 \
0413   template <class PREC>\
0414   bool is_block_UL_DR(const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0415     /* Look if even dim matrix is of the form :  |X 0|\
0416                                                  |0 Y|*/\
0417     unsigned int _D = dimension();\
0418     unsigned int _D_2 = _D/2;\
0419     if(2*_D_2!=_D) return false;\
0420     for(unsigned int r=0;r<_D_2;r++) {\
0421       for(unsigned int c=_D_2;c<_D;c++) {\
0422         if(a_fabs(value(r,c))>=a_prec) return false;\
0423       }\
0424     }\
0425     for(unsigned int r=_D_2;r<_D;r++) {\
0426       for(unsigned int c=0;c<_D_2;c++) {\
0427         if(a_fabs(value(r,c))>=a_prec) return false;\
0428       }\
0429     }\
0430     return true;\
0431   }\
0432 \
0433   template <class PREC>\
0434   bool is_block_UR_DL(const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0435     /* Look if even dim matrix is of the form :  |0 X|\
0436                                                  |Y 0|*/\
0437     unsigned int _D = dimension();\
0438     unsigned int _D_2 = _D/2;\
0439     if(2*_D_2!=_D) return false;\
0440     for(unsigned int r=0;r<_D_2;r++) {\
0441       for(unsigned int c=0;c<_D_2;c++) {\
0442         if(a_fabs(value(r,c))>=a_prec) return false;\
0443       }\
0444     }\
0445     for(unsigned int r=_D_2;r<_D;r++) {\
0446       for(unsigned int c=_D_2;c<_D;c++) {\
0447         if(a_fabs(value(r,c))>=a_prec) return false;\
0448       }\
0449     }\
0450     return true;\
0451   }\
0452 \
0453   template <class PREC>\
0454   bool is_decomplex(const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0455     /* Look if even dim matrix is of the form :  | X Y|\
0456                                                  |-Y X|*/\
0457     unsigned int _D = dimension();\
0458     unsigned int _D_2 = _D/2;\
0459     if(2*_D_2!=_D) return false;\
0460     for(unsigned int r=0;r<_D_2;r++) {\
0461       for(unsigned int c=0;c<_D_2;c++) {\
0462         if(a_fabs(value(r,c)-value(r+_D_2,c+_D_2))>=a_prec) return false;\
0463       }\
0464     }\
0465     for(unsigned int r=0;r<_D_2;r++) {\
0466       for(unsigned int c=_D_2;c<_D;c++) {\
0467         if(a_fabs(value(r,c)+value(r+_D_2,c-_D_2))>=a_prec) return false;\
0468       }\
0469     }\
0470     return true;\
0471   }\
0472 \
0473   template <class PREC>\
0474   T determinant_prec(unsigned int a_tmp_rs[],unsigned int a_tmp_cs[],  /*[rord=dim-1]*/\
0475                      const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0476     unsigned int ord = dimension();\
0477     if(ord==0) {\
0478       return zero();\
0479     } else if(ord==1) {\
0480       return *m_vec;\
0481     } else if(ord==2) {\
0482       T v00 = *m_vec;\
0483       T v10 = *(m_vec+1);\
0484       T v01 = *(m_vec+2);\
0485       T v11 = *(m_vec+3);\
0486       return (v00 * v11 - v10 * v01);\
0487     } else if(ord==3) {\
0488       /*   00 01 02 \
0489            10 11 12 \
0490            20 21 22 \
0491       */\
0492       T v00 = *m_vec;\
0493       T v10 = *(m_vec+1);\
0494       T v20 = *(m_vec+2);\
0495       T v01 = *(m_vec+3);\
0496       T v11 = *(m_vec+4);\
0497       T v21 = *(m_vec+5);\
0498       T v02 = *(m_vec+6);\
0499       T v12 = *(m_vec+7);\
0500       T v22 = *(m_vec+8);\
0501       T cof_00 = v11 * v22 - v21 * v12;\
0502       T cof_10 = v01 * v22 - v21 * v02;\
0503       T cof_20 = v01 * v12 - v11 * v02;\
0504       return (v00*cof_00-v10*cof_10+v20*cof_20);\
0505     }\
0506 \
0507     unsigned int rord = ord-1;\
0508 \
0509     T v_rc;\
0510 \
0511     T det = zero();\
0512    {for(unsigned int i=0;i<rord;i++) {a_tmp_cs[i] = i+1;}}\
0513     unsigned int c = 0;\
0514 \
0515    {for(unsigned int i=0;i<rord;i++) {a_tmp_rs[i] = i+1;}}\
0516     bool sg = true; /*c=0+r=0*/\
0517     for(unsigned int r=0;r<ord;r++) {\
0518       if(r>=1) a_tmp_rs[r-1] = r-1;\
0519       v_rc = value(r,c);\
0520       if(!is_zero(v_rc,a_prec,a_fabs)) {\
0521         T subdet = sub_determinant_prec(rord,a_tmp_rs,a_tmp_cs,a_prec,a_fabs);\
0522         if(sg) \
0523           det += v_rc * subdet;\
0524         else\
0525           det -= v_rc * subdet;\
0526       }\
0527       sg = sg?false:true;\
0528     }\
0529 \
0530     return det;\
0531   }\
0532 \
0533   T determinant(unsigned int a_tmp_rs[],unsigned int a_tmp_cs[]) const { /*[rord=dim-1]*/ \
0534     return determinant_prec<double>(a_tmp_rs,a_tmp_cs,0,zero_fabs);\
0535   }\
0536 \
0537   T determinant() const {\
0538     unsigned int ord = dimension();\
0539     if(ord==0) {\
0540       return zero();\
0541     } else if(ord==1) {\
0542       return *m_vec;\
0543     } else if(ord==2) {\
0544       T v00 = *m_vec;\
0545       T v10 = *(m_vec+1);\
0546       T v01 = *(m_vec+2);\
0547       T v11 = *(m_vec+3);\
0548       return (v00 * v11 - v10 * v01);\
0549     } else if(ord==3) {\
0550       /*   00 01 02 \
0551            10 11 12 \
0552            20 21 22 \
0553       */\
0554       T v00 = *m_vec;\
0555       T v10 = *(m_vec+1);\
0556       T v20 = *(m_vec+2);\
0557       T v01 = *(m_vec+3);\
0558       T v11 = *(m_vec+4);\
0559       T v21 = *(m_vec+5);\
0560       T v02 = *(m_vec+6);\
0561       T v12 = *(m_vec+7);\
0562       T v22 = *(m_vec+8);\
0563       T cof_00 = v11 * v22 - v21 * v12;\
0564       T cof_10 = v01 * v22 - v21 * v02;\
0565       T cof_20 = v01 * v12 - v11 * v02;\
0566       return (v00*cof_00-v10*cof_10+v20*cof_20);\
0567     }\
0568     unsigned int rord = ord-1;\
0569     unsigned int* rs = new unsigned int[rord];\
0570     unsigned int* cs = new unsigned int[rord];\
0571     T det = determinant(rs,cs);\
0572     delete [] rs;\
0573     delete [] cs;\
0574     return det;\
0575   }\
0576 \
0577   template <class PREC>\
0578   bool invert_prec(TOOLS_MAT_CLASS& a_res,\
0579                    unsigned int a_tmp_rs[],unsigned int a_tmp_cs[],  /*[rord=dim-1]*/\
0580                    const PREC& a_prec,PREC(*a_fabs)(const T&) /*for det=?zero*/ \
0581                    ) const { \
0582     unsigned int ord = dimension();\
0583     if(ord==0) return true;\
0584 \
0585     if(ord==1) {\
0586       T det = value(0,0);\
0587       if(is_zero(det,a_prec,a_fabs)) return false;\
0588       a_res.set_value(0,0,one()/det);\
0589       return true;\
0590     } else if(ord==2) {\
0591       T v00 = *m_vec;\
0592       T v10 = *(m_vec+1);\
0593       T v01 = *(m_vec+2);\
0594       T v11 = *(m_vec+3);\
0595       T det = (v00 * v11 - v10 * v01);\
0596       if(is_zero(det,a_prec,a_fabs)) return false;\
0597       a_res.set_value(0,0,v11/det);\
0598       a_res.set_value(1,1,v00/det);\
0599       a_res.set_value(0,1,minus_one()*v01/det);\
0600       a_res.set_value(1,0,minus_one()*v10/det);\
0601       return true;\
0602     } else if(ord==3) {\
0603       /*   00 01 02 \
0604            10 11 12 \
0605            20 21 22 \
0606       */\
0607       T v00 = *m_vec;\
0608       T v10 = *(m_vec+1);\
0609       T v20 = *(m_vec+2);\
0610       T v01 = *(m_vec+3);\
0611       T v11 = *(m_vec+4);\
0612       T v21 = *(m_vec+5);\
0613       T v02 = *(m_vec+6);\
0614       T v12 = *(m_vec+7);\
0615       T v22 = *(m_vec+8);\
0616       T cof_00 = v11 * v22 - v21 * v12;\
0617       T cof_10 = v01 * v22 - v21 * v02;\
0618       T cof_20 = v01 * v12 - v11 * v02;\
0619       T det = (v00*cof_00-v10*cof_10+v20*cof_20);\
0620       if(is_zero(det,a_prec,a_fabs)) return false;\
0621       T cof_01 = v10 * v22 - v20 * v12;\
0622       T cof_11 = v00 * v22 - v20 * v02;\
0623       T cof_21 = v00 * v12 - v10 * v02;\
0624       T cof_02 = v10 * v21 - v20 * v11;\
0625       T cof_12 = v00 * v21 - v20 * v01;\
0626       T cof_22 = v00 * v11 - v10 * v01;\
0627       a_res.set_value(0,0,cof_00/det);\
0628       a_res.set_value(1,0,minus_one()*cof_01/det);\
0629       a_res.set_value(2,0,cof_02/det);\
0630       a_res.set_value(0,1,minus_one()*cof_10/det);\
0631       a_res.set_value(1,1,cof_11/det);\
0632       a_res.set_value(2,1,minus_one()*cof_12/det);\
0633       a_res.set_value(0,2,cof_20/det);\
0634       a_res.set_value(1,2,minus_one()*cof_21/det);\
0635       a_res.set_value(2,2,cof_22/det);\
0636       return true;\
0637     }\
0638   \
0639     /*Generic invertion method.*/\
0640   \
0641     unsigned int rord = ord-1;\
0642   \
0643     /* Get det with r = 0;*/\
0644     T det = zero();\
0645     T subdet;\
0646    {\
0647    {for(unsigned int i=0;i<rord;i++) {a_tmp_rs[i] = i+1;}}\
0648     unsigned int r = 0;\
0649    {for(unsigned int i=0;i<rord;i++) {a_tmp_cs[i] = i+1;}}\
0650     bool sg = true; /*r=0+c=0*/\
0651     for(unsigned int c=0;c<ord;c++) {\
0652       if(c>=1) a_tmp_cs[c-1] = c-1;\
0653       subdet = sub_determinant_prec(rord,a_tmp_rs,a_tmp_cs,a_prec,a_fabs);\
0654       if(sg) {\
0655         det += value(r,c) * subdet;\
0656         a_res.set_value(c,r,subdet);\
0657         sg = false;\
0658       } else {\
0659         det += value(r,c) * subdet * minus_one();\
0660         a_res.set_value(c,r,subdet * minus_one());\
0661         sg = true;\
0662       }\
0663     }}\
0664 \
0665    if(is_zero(det,a_prec,a_fabs)) return false;\
0666 \
0667    {for(unsigned int c=0;c<ord;c++) {\
0668       a_res.set_value(c,0,a_res.value(c,0)/det);\
0669     }}\
0670   \
0671    {for(unsigned int i=0;i<rord;i++) {a_tmp_rs[i] = i+1;}}\
0672     bool sgr = false; /*r=1+c=0*/\
0673     for(unsigned int r=1;r<ord;r++) {\
0674       if(r>=1) a_tmp_rs[r-1] = r-1;\
0675      {for(unsigned int i=0;i<rord;i++) {a_tmp_cs[i] = i+1;}}\
0676       bool sg = sgr;\
0677       for(unsigned int c=0;c<ord;c++) {\
0678         if(c>=1) a_tmp_cs[c-1] = c-1;\
0679         subdet = sub_determinant_prec(rord,a_tmp_rs,a_tmp_cs,a_prec,a_fabs);\
0680         if(sg) {\
0681           a_res.set_value(c,r,subdet/det);\
0682           sg = false;\
0683         } else {\
0684           a_res.set_value(c,r,(subdet * minus_one())/det);\
0685           sg = true;\
0686         }\
0687       }\
0688       sgr = sgr?false:true;\
0689     }\
0690 \
0691     return true;\
0692   }\
0693 \
0694   template <class PREC>\
0695   bool invert_prec(TOOLS_MAT_CLASS& a_res,const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0696     unsigned int ord = dimension();\
0697     if(ord==0) return true;\
0698 \
0699     if(ord==1) {\
0700       T det = value(0,0);\
0701       if(is_zero(det,a_prec,a_fabs)) return false;\
0702       a_res.set_value(0,0,one()/det);\
0703       return true;\
0704     } else if(ord==2) {\
0705       T v00 = *m_vec;\
0706       T v10 = *(m_vec+1);\
0707       T v01 = *(m_vec+2);\
0708       T v11 = *(m_vec+3);\
0709       T det = (v00 * v11 - v10 * v01);\
0710       if(is_zero(det,a_prec,a_fabs)) return false;\
0711       a_res.set_value(0,0,v11/det);\
0712       a_res.set_value(1,1,v00/det);\
0713       a_res.set_value(0,1,minus_one()*v01/det);\
0714       a_res.set_value(1,0,minus_one()*v10/det);\
0715       return true;\
0716     } else if(ord==3) {\
0717       /*   00 01 02 \
0718            10 11 12 \
0719            20 21 22 \
0720       */\
0721       T v00 = *m_vec;\
0722       T v10 = *(m_vec+1);\
0723       T v20 = *(m_vec+2);\
0724       T v01 = *(m_vec+3);\
0725       T v11 = *(m_vec+4);\
0726       T v21 = *(m_vec+5);\
0727       T v02 = *(m_vec+6);\
0728       T v12 = *(m_vec+7);\
0729       T v22 = *(m_vec+8);\
0730       T cof_00 = v11 * v22 - v21 * v12;\
0731       T cof_10 = v01 * v22 - v21 * v02;\
0732       T cof_20 = v01 * v12 - v11 * v02;\
0733       T det = (v00*cof_00-v10*cof_10+v20*cof_20);\
0734       if(is_zero(det,a_prec,a_fabs)) return false;\
0735       T cof_01 = v10 * v22 - v20 * v12;\
0736       T cof_11 = v00 * v22 - v20 * v02;\
0737       T cof_21 = v00 * v12 - v10 * v02;\
0738       T cof_02 = v10 * v21 - v20 * v11;\
0739       T cof_12 = v00 * v21 - v20 * v01;\
0740       T cof_22 = v00 * v11 - v10 * v01;\
0741       a_res.set_value(0,0,cof_00/det);\
0742       a_res.set_value(1,0,minus_one()*cof_01/det);\
0743       a_res.set_value(2,0,cof_02/det);\
0744       a_res.set_value(0,1,minus_one()*cof_10/det);\
0745       a_res.set_value(1,1,cof_11/det);\
0746       a_res.set_value(2,1,minus_one()*cof_12/det);\
0747       a_res.set_value(0,2,cof_20/det);\
0748       a_res.set_value(1,2,minus_one()*cof_21/det);\
0749       a_res.set_value(2,2,cof_22/det);\
0750       return true;\
0751     }\
0752 \
0753     unsigned int rord = ord-1;\
0754     unsigned int* cs = new unsigned int[rord];\
0755     unsigned int* rs = new unsigned int[rord];\
0756     bool status = invert_prec(a_res,rs,cs,a_prec,a_fabs);\
0757     delete [] cs;\
0758     delete [] rs;\
0759     return status;\
0760   }\
0761 \
0762   bool invert(TOOLS_MAT_CLASS& a_res,unsigned int a_tmp_rs[],unsigned int a_tmp_cs[]) const { /*[rord=dim-1]*/ \
0763     return invert_prec<double>(a_res,a_tmp_rs,a_tmp_cs,0,zero_fabs);\
0764   }\
0765 \
0766   bool invert(TOOLS_MAT_CLASS& a_res) const {\
0767     return invert_prec<double>(a_res,0,zero_fabs);\
0768   }\
0769 \
0770   void power(unsigned int a_n,TOOLS_MAT_CLASS& a_res) const {\
0771     a_res.set_identity();\
0772     T* _tmp = new T[dim2()];\
0773     for(unsigned int i=0;i<a_n;i++) {\
0774       a_res._mul_mtx(m_vec,_tmp);\
0775     }\
0776     delete [] _tmp;\
0777   }\
0778 \
0779   void exp(unsigned int a_le,TOOLS_MAT_CLASS& a_res,TOOLS_MAT_CLASS& a_tmp,T a_tmp_2[]) const { /*OPTIMIZATION*/\
0780     /* result = I + M + M**2/2! + M**3/3! + .... */\
0781     a_res.set_identity();\
0782     a_tmp.set_identity();\
0783     for(unsigned int i=1;i<=a_le;i++) {\
0784       a_tmp._mul_mtx(m_vec,a_tmp_2);\
0785       a_tmp.multiply(one()/T(i));\
0786       a_res += a_tmp;\
0787     }\
0788   }\
0789 \
0790   void exp(unsigned int a_le,TOOLS_MAT_CLASS& a_res) const {\
0791     /* result = I + M + M**2/2! + M**3/3! + .... */\
0792     TOOLS_MAT_CLASS tmp(*this);\
0793     tmp.set_identity();\
0794     T* tmp_2 = new T[dim2()];\
0795     exp(a_le,a_res,tmp,tmp_2);\
0796     delete [] tmp_2;\
0797   }\
0798 \
0799   void cosh(unsigned int a_le,TOOLS_MAT_CLASS& a_res) const {\
0800     /* result = I + M**2/2! + M**4/4! + .... */\
0801     a_res.set_identity();\
0802     TOOLS_MAT_CLASS M_2(*this);\
0803     M_2._mul_mtx(m_vec);\
0804     TOOLS_MAT_CLASS tmp(*this);\
0805     tmp.set_identity();\
0806     T* _tmp = new T[dim2()];\
0807     for(unsigned int i=1;i<=a_le;i+=2) {\
0808       tmp._mul_mtx(M_2.m_vec,_tmp);\
0809       tmp.multiply(one()/T(i+0)); \
0810       tmp.multiply(one()/T(i+1)); \
0811       a_res += tmp;\
0812     }\
0813     delete [] _tmp;\
0814   }\
0815 \
0816   void sinh(unsigned int a_le,TOOLS_MAT_CLASS& a_res) const {\
0817     /* result = M + M**3/3! + .... */\
0818     a_res._copy(m_vec);\
0819     TOOLS_MAT_CLASS M_2(*this);\
0820     M_2._mul_mtx(m_vec);\
0821     TOOLS_MAT_CLASS tmp(*this);\
0822     tmp._copy(m_vec);\
0823     T* _tmp = new T[dim2()];\
0824     for(unsigned int i=1;i<=a_le;i+=2) {\
0825       tmp._mul_mtx(M_2.m_vec,_tmp);\
0826       tmp.multiply(one()/T(i+1)); \
0827       tmp.multiply(one()/T(i+2)); \
0828       a_res += tmp;\
0829     }\
0830     delete [] _tmp;\
0831   }\
0832 \
0833   void log(unsigned int a_le,TOOLS_MAT_CLASS& a_res) const {\
0834     /* result = (M-I) - (M-I)**2/2 + (M-I)**3/3 +... */\
0835     /* WARNING : touchy, it may not converge ! */\
0836     a_res.set_zero();\
0837 \
0838     TOOLS_MAT_CLASS M_I;\
0839     M_I.set_identity();\
0840     M_I.multiply(minus_one());\
0841     M_I._add_mtx(m_vec);\
0842 \
0843     TOOLS_MAT_CLASS M_Ip(M_I);\
0844     T fact = minus_one();\
0845 \
0846     TOOLS_MAT_CLASS tmp;\
0847 \
0848     T* _tmp = new T[dim2()];\
0849     for(unsigned int i=0;i<=a_le;i++) {\
0850       fact *= minus_one();      \
0851       tmp = M_Ip;\
0852       tmp.multiply(fact/T(i+1)); \
0853       a_res += tmp;\
0854       M_Ip._mul_mtx(M_I.m_vec,_tmp);\
0855     }\
0856     delete [] _tmp;\
0857   }\
0858 \
0859   void omega(unsigned int a_le,TOOLS_MAT_CLASS& a_res,TOOLS_MAT_CLASS& a_tmp,T a_tmp_2[]) const { /*OPTIMIZATION*/\
0860     /* result = I + M/2! + M**2/3! + M**3/4! + .... */\
0861     a_res.set_identity();\
0862     a_tmp.set_identity();\
0863     for(unsigned int i=1;i<=a_le;i++) {\
0864       a_tmp._mul_mtx(m_vec,a_tmp_2);\
0865       a_tmp.multiply(one()/T(i+1));\
0866       a_res += a_tmp;\
0867     }\
0868   }\
0869 \
0870   void omega(unsigned int a_le,TOOLS_MAT_CLASS& a_res) const {\
0871     /* result = I + M/2! + M**2/3! + M**3/4! + .... */\
0872     TOOLS_MAT_CLASS tmp(*this);\
0873     tmp.set_identity();\
0874     T* tmp_2 = new T[dim2()];\
0875     omega(a_le,a_res,tmp,tmp_2);\
0876     delete [] tmp_2;\
0877   }\
0878 \
0879   template <class MAT>\
0880   bool copy(const MAT& a_from) {\
0881     /*for exa from a double matrix to a symbol matrix*/\
0882     unsigned int _D = dimension();\
0883     if(a_from.dimension()!=_D) return false;\
0884     for(unsigned int r=0;r<_D;r++) {\
0885       for(unsigned int c=0;c<_D;c++) {\
0886         set_value(r,c,a_from.value(r,c));\
0887       }\
0888     }\
0889     return true;\
0890   }\
0891 public: /*operators*/\
0892   T operator()(unsigned int a_r,unsigned int a_c) const {\
0893     /*WARNING : no check on a_r,a_c.*/\
0894     return m_vec[a_r + a_c * dimension()];\
0895   }\
0896 \
0897   T& operator[](size_t a_index) { /*for tools/sg/sf_vec*/\
0898     /*WARNING : no check on a_index.*/\
0899     return m_vec[a_index];\
0900   }\
0901   const T& operator[](size_t a_index) const {\
0902     /*WARNING : no check on a_index.*/\
0903     return m_vec[a_index];\
0904   }\
0905   bool operator==(const TOOLS_MAT_CLASS& a_array) const {\
0906     return equal(a_array);\
0907   }\
0908   bool operator!=(const TOOLS_MAT_CLASS& a_array) const {\
0909     return !operator==(a_array);\
0910   }\
0911   TOOLS_MAT_CLASS& operator*=(const TOOLS_MAT_CLASS& a_m) {\
0912     _mul_mtx(a_m.m_vec);\
0913     return *this;\
0914   }\
0915   TOOLS_MAT_CLASS& operator+=(const TOOLS_MAT_CLASS& a_m) {\
0916     _add_mtx(a_m.m_vec);\
0917     return *this;\
0918   }\
0919   TOOLS_MAT_CLASS& operator-=(const TOOLS_MAT_CLASS& a_m) {\
0920     _sub_mtx(a_m.m_vec);\
0921     return *this;\
0922   }\
0923   TOOLS_MAT_CLASS& operator*=(const T& a_fac) {\
0924     for(unsigned int i=0;i<dim2();i++) m_vec[i] *= a_fac;\
0925     return *this;\
0926   }\
0927 \
0928   TOOLS_MAT_CLASS operator*(const T& a_fac) {\
0929     TOOLS_MAT_CLASS res;\
0930     res.operator*=(a_fac);\
0931     return res;\
0932   }\
0933 protected:\
0934   void _copy(const T a_m[]) {\
0935     T* tp = (T*)m_vec;T* ap = (T*)a_m;\
0936     for(unsigned int i=0;i<dim2();i++,tp++,ap++) *tp = *ap;\
0937   }\
0938 \
0939   void _add_mtx(const T a_m[]) {  /* this = this + a_m, */\
0940     T* tp = (T*)m_vec;T* ap = (T*)a_m;\
0941     for(unsigned int i=0;i<dim2();i++,tp++,ap++) *tp += *ap;\
0942   }\
0943   void _sub_mtx(const T a_m[]) {  /* this = this - a_m, */\
0944     T* tp = (T*)m_vec;T* ap = (T*)a_m;\
0945     for(unsigned int i=0;i<dim2();i++,tp++,ap++) *tp -= *ap;\
0946   }\
0947 \
0948   void _mul_mtx(const T a_m[],T a_tmp[]) { /*OPTIMIZATION*/\
0949     /* this = this * a_m */\
0950     typedef T* Tp;\
0951     Tp tpos,ttpos,rpos,apos,mpos,aapos;\
0952     T _value;\
0953     unsigned int r,c,i;\
0954 \
0955     unsigned int _D = dimension();\
0956 \
0957     tpos = a_tmp;\
0958     for(r=0;r<_D;r++,tpos++) {\
0959       ttpos = tpos;\
0960       rpos = m_vec+r;\
0961       apos = (T*)a_m;\
0962       for(c=0;c<_D;c++,ttpos+=_D,apos+=_D) {\
0963         _value = zero();\
0964         mpos = rpos;\
0965         aapos = apos;\
0966         for(i=0;i<_D;i++,mpos+=_D,aapos++) _value += (*mpos) * (*aapos);\
0967         *ttpos = _value;\
0968       }\
0969     }\
0970     _copy(a_tmp);\
0971   }\
0972 \
0973   void _mul_mtx(const T a_m[]) {\
0974     T* _tmp = new T[dim2()];\
0975     _mul_mtx(a_m,_tmp);\
0976     delete [] _tmp;\
0977   }\
0978 \
0979   void _left_mul_mtx(const T a_m[]) {\
0980     /* this = a_m * this */\
0981     unsigned int _D = dimension();\
0982     T* _tmp = new T[dim2()];\
0983     for(unsigned int r=0;r<_D;r++) {\
0984       for(unsigned int c=0;c<_D;c++) {\
0985         T _value = zero();\
0986         for(unsigned int i=0;i<_D;i++) {\
0987           _value += (*(a_m+r+i*_D)) * (*(m_vec+i+c*_D)); /*optimize.*/\
0988         }\
0989         *(_tmp+r+c*_D) = _value;\
0990       }\
0991     }\
0992     _copy(_tmp);\
0993     delete [] _tmp;\
0994   }\
0995 \
0996   template <class PREC>\
0997   T sub_determinant_prec(unsigned int a_ord,unsigned int aRs[],unsigned int aCs[],\
0998                          const PREC& a_prec,PREC(*a_fabs)(const T&)) const {\
0999     /*WARNING : to optimize, we do not check the content of aRs, aCs.*/\
1000     unsigned int ord = a_ord;\
1001     if(ord==0) return zero();\
1002     else if(ord==1) return value(aRs[0],aCs[0]);\
1003     else if(ord==2) {\
1004       /*return (value(aRs[0],aCs[0]) * value(aRs[1],aCs[1]) -\
1005                value(aRs[1],aCs[0]) * value(aRs[0],aCs[1])); \
1006       Optimize the upper :*/\
1007 \
1008       unsigned int _ord = dimension();\
1009 \
1010       return ( (*(m_vec+aRs[0]+aCs[0]*_ord)) * (*(m_vec+aRs[1]+aCs[1]*_ord)) -\
1011                (*(m_vec+aRs[1]+aCs[0]*_ord)) * (*(m_vec+aRs[0]+aCs[1]*_ord)) );\
1012 \
1013     } else if(ord==3) {\
1014       /*   00 01 02 \
1015            10 11 12 \
1016            20 21 22 \
1017       */\
1018       unsigned int _ord = dimension();\
1019 \
1020       T v00 = *(m_vec+aRs[0]+aCs[0]*_ord);\
1021       T v10 = *(m_vec+aRs[1]+aCs[0]*_ord);\
1022       T v20 = *(m_vec+aRs[2]+aCs[0]*_ord);\
1023       T v01 = *(m_vec+aRs[0]+aCs[1]*_ord);\
1024       T v11 = *(m_vec+aRs[1]+aCs[1]*_ord);\
1025       T v21 = *(m_vec+aRs[2]+aCs[1]*_ord);\
1026       T v02 = *(m_vec+aRs[0]+aCs[2]*_ord);\
1027       T v12 = *(m_vec+aRs[1]+aCs[2]*_ord);\
1028       T v22 = *(m_vec+aRs[2]+aCs[2]*_ord);\
1029       T cof_00 = v11 * v22 - v21 * v12;\
1030       T cof_10 = v01 * v22 - v21 * v02;\
1031       T cof_20 = v01 * v12 - v11 * v02;\
1032       return (v00*cof_00-v10*cof_10+v20*cof_20);\
1033     }\
1034 \
1035     unsigned int rord = ord-1;\
1036     unsigned int* cs = new unsigned int[rord];\
1037     unsigned int* rs = new unsigned int[rord];\
1038 \
1039     T v_rc;\
1040 \
1041     T det = zero();\
1042    {for(unsigned int i=0;i<rord;i++) {cs[i] = aCs[i+1];}}\
1043     unsigned int c = 0;\
1044     /*if(c>=1) cs[c-1] = c-1;*/\
1045 \
1046    {for(unsigned int i=0;i<rord;i++) {rs[i] = aRs[i+1];}}\
1047     bool sg = true; /*c=0+r=0*/\
1048     for(unsigned int r=0;r<ord;r++) {\
1049       if(r>=1) rs[r-1] = aRs[r-1];\
1050       v_rc = value(aRs[r],aCs[c]);\
1051       if(!is_zero(v_rc,a_prec,a_fabs)) {\
1052         T subdet = sub_determinant_prec(rord,rs,cs,a_prec,a_fabs);\
1053         if(sg)\
1054           det += v_rc * subdet;\
1055         else\
1056           det -= v_rc * subdet;\
1057       }\
1058       sg = sg?false:true;\
1059     }\
1060 \
1061     delete [] cs;\
1062     delete [] rs;\
1063 \
1064     return det;\
1065   }\
1066 \
1067   static double zero_fabs(const T& a_number) {return a_number==zero()?0:1000000;}
1068 
1069 #endif