inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/sqm
Go to the documentation of this file.
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved.
00002 // See the file inlib.license for terms.
00003 
00004 #ifndef inlib_sqm
00005 #define inlib_sqm
00006 
00007 // sqm is for square matrix
00008 
00009 #include "array"
00010 
00011 namespace inlib {
00012 
00013 template <class T>
00014 class sqm : public array<T> {
00015 public:
00016   sqm(unsigned a_order):array<T>(2,a_order){
00017     // a_order is the matrix dimension, which must not be confused
00018     // with the array dimension which is 2).
00019   }
00020   virtual ~sqm() {}
00021 public: 
00022   sqm(const sqm& a_from):array<T>(a_from){}
00023   sqm& operator=(const sqm& a_from) {
00024     array<T>::operator=(a_from);
00025     return *this;
00026   }
00027 public:
00028   bool set_order(unsigned int a_order) {
00029     std::vector<unsigned int> orders(2);
00030     for(unsigned int index=0;index<2;index++) orders[index] = a_order;
00031     return array<T>::configure(orders);
00032   }
00033 
00034   unsigned int order() const { return array<T>::m_orders[0];}
00035 
00036   T value(unsigned int aR,unsigned int aC) const { 
00037     //WARNING : range of aR, aC not protected.
00038     unsigned int ord = order();
00039     return array<T>::m_vector[aR + aC * ord];
00040   }
00041 
00042   bool value(unsigned int aR,unsigned int aC,T& a_value) const { 
00043     unsigned int ord = order();
00044     if((aR>=ord)||(aC>=ord)) {
00045       a_value = array<T>::zero();
00046       return false;
00047     }
00048     a_value = array<T>::m_vector[aR + aC * ord];
00049     return true;
00050   }
00051 
00052   bool set_value(unsigned int aR,unsigned int aC,const T& a_value) { 
00053     unsigned int ord = order();
00054     if((aR>=ord)||(aC>=ord)) return false;
00055     array<T>::m_vector[aR + aC * ord] = a_value;
00056     return true;
00057   }
00058 
00059   void set_value_no_check(unsigned int aR,
00060                               unsigned int aC,
00061                               const T& a_value){ 
00062     array<T>::m_vector[aR + aC * order()] = a_value;
00063   }
00064 
00065   T trace() const {
00066     unsigned int ord = order();
00067     T value = array<T>::zero();
00068     for(unsigned int c=0;c<ord;c++) value += array<T>::m_vector[c+c*ord];
00069     return value;
00070   }
00071 
00072   bool mx_mul(const sqm<T>& a_matrix,sqm<T>& a_result) const {
00073     // a_result = this * a_matrix
00074     unsigned int ord = order();
00075     if(a_matrix.order()!=ord) return false;
00076     if(a_result.order()!=ord) return false;
00077     const T* p = &(array<T>::m_vector[0]);            //WARNING : dangerous.
00078     const T* a_p = &(a_matrix.array<T>::m_vector[0]); //WARNING : dangerous.
00079     T* r_p = &(a_result.array<T>::m_vector[0]);       //WARNING : dangerous.
00080     for(unsigned int r=0;r<ord;r++) {
00081       for(unsigned int c=0;c<ord;c++) {
00082         T value = array<T>::zero();
00083         for(unsigned int i=0;i<ord;i++) {
00084           //value += 
00085           //  array<T>::m_vector[r+i*ord] * 
00086           //  a_matrix.array<T>::m_vector[i+c*ord];
00087           value += (*(p+r+i*ord)) * (*(a_p+i+c*ord)); //optimize.
00088         }
00089         //a_result.array<T>::m_vector[r+c*ord] = value;
00090         *(r_p+r+c*ord) = value;
00091       }
00092     }
00093     return true;
00094   }
00095 
00096   bool mx_mul(const sqm<T>& a_matrix) {
00097     sqm<T> res(order());
00098     bool status = this->mx_mul(a_matrix,res);
00099     *this = res;
00100     return status;
00101   }
00102 
00103   bool mx_left_mul(const sqm<T>& a_matrix,sqm<T>& a_result) const {
00104     // a_result = a_matrix * this
00105     unsigned int ord = order();
00106     if(a_matrix.order()!=ord) return false;
00107     if(a_result.order()!=ord) return false;
00108     const T* p = &(array<T>::m_vector[0]);            //WARNING : dangerous.
00109     const T* a_p = &(a_matrix.array<T>::m_vector[0]); //WARNING : dangerous.
00110     T* r_p = &(a_result.array<T>::m_vector[0]);       //WARNING : dangerous.
00111     for(unsigned int r=0;r<ord;r++) {
00112       for(unsigned int c=0;c<ord;c++) {
00113         T value = array<T>::zero();
00114         for(unsigned int i=0;i<ord;i++) {
00115           //value += 
00116           //  a_matrix.array<T>::m_vector[r+i*ord] * 
00117           //  array<T>::m_vector[i+c*ord];
00118           value += (*(a_p+r+i*ord)) * (*(p+i+c*ord)); //optimize.
00119         }
00120         //a_result.array<T>::m_vector[r+c*ord] = value;
00121         *(r_p+r+c*ord) = value;
00122       }
00123     }
00124     return true;
00125   }
00126 
00127   bool mx_left_mul(const sqm<T>& a_matrix) {
00128     sqm<T> res(order());
00129     bool status = this->mx_left_mul(a_matrix,res);
00130     *this = res;
00131     return status;
00132   }
00133 
00134   virtual T determinant() const {
00135     unsigned int ord = order();
00136     if(ord==0) return array<T>::zero();
00137     else if(ord==1) return value(0,0);
00138     else if(ord==2) return (value(0,0) * value(1,1) - 
00139                             value(1,0) * value(0,1)); //Optimize
00140 
00141     unsigned int rord = ord-1;
00142     std::vector<unsigned int> cs(rord);
00143     std::vector<unsigned int> rs(rord);
00144 
00145     T det = array<T>::zero();
00146    {for(unsigned int i=0;i<rord;i++) {cs[i] = i+1;}}
00147     unsigned int c = 0;
00148     //if(c>=1) cs[c-1] = c-1;
00149 
00150    {for(unsigned int i=0;i<rord;i++) {rs[i] = i+1;}}
00151     bool sg = true; //c=0+r=0
00152     for(unsigned int r=0;r<ord;r++) {
00153       if(r>=1) rs[r-1] = r-1;
00154       T subdet = sub_determinant(rs,cs);
00155       if(sg) 
00156         det += value(r,c) * subdet;
00157       else
00158         det -= value(r,c) * subdet;
00159       sg = sg?false:true;
00160     }
00161 
00162     return det;
00163   }
00164   T sub_determinant(const std::vector<unsigned int>& aRs,
00165                           const std::vector<unsigned int>& aCs) const {
00166     //WARNING : to optimize, we do not check the content of aRs, aCs.
00167     unsigned int ord = aRs.size();
00168     if(ord==0) return array<T>::zero();
00169     else if(ord==1) return value(aRs[0],aCs[0]);
00170     else if(ord==2) {
00171       //return (value(aRs[0],aCs[0]) * value(aRs[1],aCs[1]) -
00172       //        value(aRs[1],aCs[0]) * value(aRs[0],aCs[1])); 
00173       //Optimize the upper :
00174 
00175       unsigned int r_0 = aRs[0];
00176       unsigned int r_1 = aRs[1];
00177       unsigned int c_0 = aCs[0];
00178       unsigned int c_1 = aCs[1];
00179 
00180       unsigned int ord = order();
00181       const T* p = &(array<T>::m_vector[0]); //WARNING : dangerous.
00182 
00183       return ( (*(p+r_0+c_0*ord)) * (*(p+r_1+c_1*ord)) -
00184                (*(p+r_1+c_0*ord)) * (*(p+r_0+c_1*ord)) );
00185     }
00186 
00187     unsigned int rord = ord-1;
00188     std::vector<unsigned int> cs(rord);
00189     std::vector<unsigned int> rs(rord);
00190 
00191     T det = array<T>::zero();
00192    {for(unsigned int i=0;i<rord;i++) {cs[i] = aCs[i+1];}}
00193     unsigned int c = 0;
00194     //if(c>=1) cs[c-1] = c-1;
00195 
00196    {for(unsigned int i=0;i<rord;i++) {rs[i] = aRs[i+1];}}
00197     bool sg = true; //c=0+r=0
00198     for(unsigned int r=0;r<ord;r++) {
00199       if(r>=1) rs[r-1] = aRs[r-1];
00200       T subdet = sub_determinant(rs,cs);
00201       if(sg)
00202         det += value(aRs[r],aCs[c]) * subdet;
00203       else
00204         det -= value(aRs[r],aCs[c]) * subdet;
00205       sg = sg?false:true;
00206     }
00207 
00208     return det;
00209   }
00210 
00211   bool invert(sqm<T>& a_result) const {
00212     //Generic invertion method.
00213     unsigned int ord = order();
00214     if(ord==0) return true;
00215 
00216     a_result.set_order(ord);
00217     if(ord==1) {
00218       T v;
00219       if(!value(0,0,v)) return false;
00220       if(v==array<T>::zero()) return false;
00221       if(!a_result.set_value(0,0,1./v)) return false;
00222       return true;
00223     }
00224   
00225     unsigned int rord = ord-1;
00226     std::vector<unsigned int> cs(rord);
00227     std::vector<unsigned int> rs(rord);
00228   
00229     // Get det with r = 0;
00230     T det = array<T>::zero();
00231    {
00232    {for(unsigned int i=0;i<rord;i++) {rs[i] = i+1;}}
00233     unsigned int r = 0;
00234     //if(r>=1) rs[r-1] = r-1;
00235   
00236    {for(unsigned int i=0;i<rord;i++) {cs[i] = i+1;}}
00237     bool sg = true; //r=0+c=0
00238     for(unsigned int c=0;c<ord;c++) {
00239       if(c>=1) cs[c-1] = c-1;
00240       T subdet = sub_determinant(rs,cs);
00241       T sgn = sg ? array<T>::one() : array<T>::minus_one();
00242       det += value(r,c) * subdet * sgn;
00243       T value = subdet * sgn;
00244       a_result.set_value_no_check(c,r,value);
00245       sg = sg?false:true;
00246     }}
00247   
00248     if(det==array<T>::zero()) return false;
00249   
00250    {for(unsigned int c=0;c<ord;c++) {
00251       a_result.set_value(c,0,a_result.value(c,0)/det);
00252     }}
00253   
00254    {for(unsigned int i=0;i<rord;i++) {rs[i] = i+1;}}
00255     bool sgr = false; //r=1+c=0
00256     for(unsigned int r=1;r<ord;r++) {
00257       if(r>=1) rs[r-1] = r-1;
00258      {for(unsigned int i=0;i<rord;i++) {cs[i] = i+1;}}
00259       bool sg = sgr;
00260       for(unsigned int c=0;c<ord;c++) {
00261         if(c>=1) cs[c-1] = c-1;
00262         T subdet = sub_determinant(rs,cs);
00263         T sgn = sg ? array<T>::one() : array<T>::minus_one();
00264         T value = (subdet * sgn)/det;
00265         a_result.set_value_no_check(c,r,value);
00266         sg = sg?false:true;
00267       }
00268       sgr = sgr?false:true;
00269     }
00270   
00271     return true;
00272   }
00273 
00274   void transpose() {
00275     unsigned int ord = order();
00276     for(unsigned int r=0;r<ord;r++) {
00277       for(unsigned int c=(r+1);c<ord;c++) {
00278         T vrc = value(r,c);
00279         T vcr = value(c,r);
00280         set_value_no_check(r,c,vcr);
00281         set_value_no_check(c,r,vrc);
00282       }
00283     }
00284   }
00285 
00286   bool is_symmetric() const {
00287     unsigned int ord = order();
00288     for(unsigned int r=0;r<ord;r++) {
00289       for(unsigned int c=(r+1);c<ord;c++) {
00290         if(value(r,c)!=value(c,r)) return false;
00291       }
00292     }
00293     return true;
00294   }
00295   bool is_antisymmetric() const {
00296     unsigned int ord = order();
00297    {for(unsigned int r=0;r<ord;r++) {
00298       if(value(r,r)!=array<T>::zero()) return false;
00299     }}
00300     for(unsigned int r=0;r<ord;r++) {
00301       for(unsigned int c=(r+1);c<ord;c++) {
00302         if(value(r,c)!=-value(c,r)) return false;
00303       }
00304     }
00305     return true;
00306   }
00307 
00308   void set_identity() {
00309     unsigned int ord = order();
00310     array<T>::reset();
00311     for(unsigned int c=0;c<ord;c++) set_value_no_check(c,c,array<T>::one());
00312   }
00313 
00314   void set_diag(const T& a_value) {
00315     unsigned int ord = order();
00316     for(unsigned int c=0;c<ord;c++) set_value_no_check(c,c,a_value);
00317   }
00318 
00319   //Factories :
00320   sqm symmetric_part() const {
00321     sqm res(*this);
00322     res.transpose();
00323     res.add(*this);
00324     res.divide(array<T>::two());
00325     return res;
00326   }
00327 
00328   sqm antisymmetric_part() const {
00329     sqm res(*this);
00330     res.transpose();
00331     res.multiply(array<T>::minus_one());
00332     res.add(*this);
00333     res.divide(array<T>::two());
00334     return res;
00335   }
00336 
00337   sqm& operator*=(const sqm<T>& a_from) {
00338     sqm<T> res(order());
00339     /*bool status =*/ this->mx_mul(a_from,res); //FIXME : throw
00340     *this = res;
00341     return *this;
00342   }
00343   sqm& operator+=(const sqm<T>& a_from) {
00344     /*bool status =*/ array<T>::add(a_from); //FIXME : throw
00345     return *this;
00346   }
00347   sqm& operator-=(const sqm<T>& a_from) {
00348     /*bool status =*/ array<T>::subtract(a_from); //FIXME : throw
00349     return *this;
00350   }
00351 };
00352 
00353 template <class T>
00354 inline sqm<T> operator-(const sqm<T>& a1,const sqm<T>& a2) {
00355   sqm<T> res(a1);
00356   res.subtract(a2);
00357   return res;
00358 }
00359 template <class T>
00360 inline sqm<T> operator+(const sqm<T>& a1,const sqm<T>& a2) {
00361   sqm<T> res(a1);
00362   res.add(a2);
00363   return res;
00364 }
00365 template <class T>
00366 inline sqm<T> operator*(const sqm<T>& a1,const sqm<T>& a2) {
00367   sqm<T> res(a1.order());
00368   a1.mx_mul(a2,res);
00369   return res;
00370 }
00371 
00372 template <class T>
00373 inline sqm<T> commutator(const sqm<T>& a1,const sqm<T>& a2) {
00374   return a1*a2-a2*a1;
00375 }
00376 
00377 template <class T>
00378 inline sqm<T> anticommutator(const sqm<T>& a1,const sqm<T>& a2) {
00379   return a1*a2+a2*a1;
00380 }
00381 
00382 template <class T>
00383 inline sqm<T> exp(const sqm<T>& a_matrix,unsigned int aNumber = 100) {
00384   // result = I + M + M**2/2! + M**3/3! + ....
00385   sqm<T> result(a_matrix.order());
00386   result.set_identity();
00387   sqm<T> m(a_matrix.order());     
00388   m.set_identity();
00389   for(unsigned int i=1;i<aNumber;i++) {
00390     m = m * a_matrix; 
00391     m.multiply(1./double(i)); 
00392     result.add(m);
00393   }
00394   return result;
00395 }
00396 
00397 template <class T>
00398 inline sqm<T> log(const sqm<T>& a_matrix,unsigned int aNumber = 100) {
00399   // result = (M-I) - (M-I)**2/2 + (M-I)**3/3 +...
00400   // Warning : cannot converge...
00401   unsigned int order = a_matrix.order();
00402   sqm<T> result(order);
00403   sqm<T> I(order);     
00404   I.set_identity();
00405   sqm<T> x(a_matrix);     
00406   x.subtract(I);
00407   sqm<T> m(I);
00408   sqm<T> tmp(order);
00409   double fact = -1;
00410   for(unsigned int i=0;i<aNumber;i++) {
00411     m = m * x; 
00412     fact *= -1;
00413     tmp = m;
00414     tmp.multiply(fact/double(i+1)); 
00415     result.add(tmp);
00416   }
00417   return result;
00418 }
00419 
00420 #ifdef __CINT__
00421 // pb with the T in double(*a_func)(T).
00422 #else
00423 template <class T>
00424 inline sqm<double> abs(const sqm<T>& a_matrix,double(*a_func)(T)) {
00425   const std::vector<T>& avec = a_matrix.vector();
00426   sqm<double> result(a_matrix.order());
00427   std::vector<double>& rvec = result.vector();
00428   unsigned int number = avec.size();
00429   for(unsigned int index=0;index<number;index++) 
00430     rvec[index] = a_func(avec[index]);
00431   return result;
00432 }
00433 
00434 template <class T>
00435 inline bool is_log_convergent(const sqm<T>& a_matrix,double(*a_func)(T)) {
00436   unsigned int order = a_matrix.order();
00437   sqm<T> I(order);     
00438   I.set_identity();
00439   sqm<T> s(a_matrix);
00440   s.subtract(I);
00441   sqm<double> a = abs(s,a_func);
00442   double radius = 1./order;
00443 
00444   std::vector<double>& vec = a.vector();
00445   typedef typename std::vector<T>::iterator vec_it_t;
00446   for(vec_it_t it = vec.begin();it!=vec.end();++it) {
00447     if((*it)>=radius) {
00448       //::printf("debug : not convergent at : %d : %g rad %g\n",
00449         //index,a.value(index),radius);
00450       return false;
00451     }
00452   }
00453 
00454   return true;
00455 }
00456 #endif
00457 
00458 template <class T>
00459 inline bool determinant(const sqm<T>& a_matrix,T& a_deter) {
00460   // Brut force determinant by using the kroneckers.
00461   a_deter = a_matrix.zero();
00462 
00463   unsigned int order = a_matrix.order(); 
00464 
00465   typedef typename std::vector<unsigned int> uints_t;
00466   typedef typename std::vector<T>::const_iterator const_vec_it_t;
00467 
00468   kronecker<T> k_c(order);
00469   const std::vector<T>& vec_c = k_c.vector();
00470   const_vec_it_t it_c;
00471   uints_t is_c(order);
00472 
00473   //kronecker<T> k_r(order);
00474   //const std::vector<T>& vec_r = k_r.vector();
00475   //const_vec_it_t it_r;
00476   //uints_t is_r(order);
00477 
00478   unsigned int index_c = 0;
00479   for(it_c = vec_c.begin();it_c!=vec_c.end();++it_c,index_c++) {
00480     if(*it_c==0.) continue;
00481     if(!k_c.indices(index_c,is_c)) return false;
00482     //unsigned int index_r = 0;
00483     //for(it_r = vec_r.begin();it_r!=vec_r.end();++it_r,index_r++) {
00484     //  if(*it_r==0.) continue;
00485     //  if(!k_r.indices(index_r,is_r)) return false;
00486       T v = array<T>::one();
00487       for(unsigned iorder=0;iorder<order;iorder++) {
00488         //v *= a_matrix.value(is_c[iorder],is_r[iorder]); 
00489         v *= a_matrix.value(is_c[iorder],iorder); 
00490       }
00491       a_deter += v;
00492     //}
00493   }
00494 
00495   //{T fact = array<T>::one();
00496   //for(unsigned index=1;index<=order;index++) fact *= index;
00497   //a_deter /= fact;}
00498 
00499   return true;
00500 }
00501 
00505 
00507 //
00508 //  En_k with k in [0,n(n-1)/2[
00509 //
00510 //  En_0 :        En_1 :         En_2 :            En_3
00511 //   0  1  0...     0  0 -1...     0  0  0  0...     0  0  0  1... 
00512 //  -1  0  0...     0  0  0...     0  0  1  0...     0  0  0  0...
00513 //   0  0  0...     1  0  0...     0 -1  0  0...     0  0  0  0...
00514 //   0  0  0...     0  0  0...     0  0  0  0...    -1  0  0  0...
00515 //   ..........     ..........     .............     .............
00516 //
00517 //  with r<c r,c in [0,n[ :
00518 //    k(r,c) = c*(c-1)/2 + r
00519 //  Reverse, given k :
00520 //    c is the first such that : c*(c-1)/2 <= k <= c*(c+1)/2 -1
00521 //  then :
00522 //    r = k - c*(c-1)/2
00523 //
00524 
00525 // T must accept -1,0,1
00526 template <class T>
00527 class E : public sqm<T> {
00528 public:
00529   static bool group_constants(unsigned int a_order,inlib::array<T>& a_constants) {
00530     unsigned int number = a_order * (a_order-1)/2;
00531   
00532     std::vector<unsigned int> orders(3,number);
00533     a_constants.configure(orders);
00534   
00535     std::vector< sqm<T> > Es;
00536     for(unsigned int index=0;index<number;index++)
00537       Es.push_back(E(a_order,index));
00538 
00539     sqm<T> zero(a_order);
00540   
00541     for(unsigned int j=0;j<number;j++) {
00542       for(unsigned int k=j+1;k<number;k++) {
00543         sqm<T> cm = commutator(Es[j],Es[k]);
00544   
00545         // Find the result in the Es themselves :
00546         bool found = false;
00547         for(unsigned int l=0;l<number;l++) {
00548           if(cm.equal(zero)) {
00549             found = true; 
00550             break;
00551           } else if(cm.equal(Es[l])) {
00552             std::vector<unsigned int> is(3);
00553             is[0] = j;
00554             is[1] = k;
00555             is[2] = l;
00556             a_constants.set_value(is,1);
00557             is[0] = k;
00558             is[1] = j;
00559             is[2] = l;
00560             a_constants.set_value(is,-1);
00561   
00562             found = true; 
00563             break;
00564           } else {
00565             sqm<T> tmp(cm);
00566             tmp.multiply(-1.);
00567             if(tmp.equal(Es[l])) {
00568               std::vector<unsigned int> is(3);
00569               is[0] = j;
00570               is[1] = k;
00571               is[2] = l;
00572               a_constants.set_value(is,-1);
00573               is[0] = k;
00574               is[1] = j;
00575               is[2] = l;
00576               a_constants.set_value(is,1);
00577   
00578               found = true; 
00579               break;
00580             }
00581           }
00582         }
00583         if(!found) {
00584           a_constants.clear();
00585           return false;
00586         }
00587       }
00588     }
00589     return true;
00590   }
00591   static bool metric(unsigned int a_order,sqm<T>& a_metric) {
00592     // For order n : -2*I(n*(n-1)/2) for all orders.
00593     unsigned int number = a_order * (a_order-1)/2;
00594   
00595     std::vector< sqm<T> > Es;
00596     for(unsigned int index=0;index<number;index++)
00597       Es.push_back(E<T>(a_order,index));
00598   
00599     a_metric.set_order(number);
00600   
00601     for(unsigned int j=0;j<number;j++) {
00602       for(unsigned int k=0;k<number;k++) {
00603         sqm<T> mx = Es[j]*Es[k];
00604         if(!a_metric.set_value(j,k,mx.trace())) return false;
00605       }
00606     }
00607   
00608     return true;
00609   }
00610   static bool cartan_metric(unsigned int a_order,sqm<T>& a_metric) {
00611     // For order n : -(2*n-4))*I(n*(n-1)/2)
00612     unsigned int number = a_order * (a_order-1)/2;
00613   
00614     array<T> csts;
00615     if(!E<T>::group_constants(a_order,csts)) {
00616       a_metric.clear();
00617       return false;
00618     }
00619   
00620     // Fill the adjoint representation :
00621     //      r        r
00622     //  (Xk)  = cst
00623     //      c      kc
00624     std::vector< sqm<T> > xs;
00625     for(unsigned int index=0;index<number;index++) {
00626       sqm<T> x(number);
00627       for(unsigned int j=0;j<number;j++) {
00628         for(unsigned int k=0;k<number;k++) {
00629           std::vector<unsigned int> is(3);
00630           is[0] = index;
00631           is[1] = k;
00632           is[2] = j;
00633           T value;
00634           if(!csts.value(is,value)) return false;
00635           if(!x.set_value(j,k,value)) return false;
00636         }
00637       }
00638       xs.push_back(x);
00639     }
00640   
00641     a_metric.set_order(number);
00642   
00643     for(unsigned int j=0;j<number;j++) {
00644       for(unsigned int k=0;k<number;k++) {
00645         sqm<T> mx = xs[j]*xs[k];
00646         if(!a_metric.set_value(j,k,mx.trace())) return false;
00647       }
00648     }
00649   
00650     return true;
00651   }
00652   
00653   static bool casimir(unsigned int a_order,sqm<T>& a_casimir) {
00654     //  For order n : (n-1)/2 * I(n)
00655     unsigned int number = a_order * (a_order-1)/2;
00656   
00657     sqm<T> metric(number);
00658     if(!E<T>::metric(a_order,metric)) {
00659       a_casimir.clear();
00660       return false;
00661     }
00662   
00663     sqm<T> metric_inv(number);
00664     if(!metric.invert(metric_inv)) return false;
00665   
00666     a_casimir.set_order(a_order);
00667   
00668     std::vector< sqm<T> > Es;
00669     for(unsigned int index=0;index<number;index++)
00670       Es.push_back(E<T>(a_order,index));
00671   
00672     for(unsigned int j=0;j<number;j++) {
00673       for(unsigned int k=0;k<number;k++) {
00674         sqm<T> mx = Es[j]*Es[k];
00675         mx.multiply(metric_inv.value(j,k));
00676         a_casimir.add(mx);
00677       }
00678     }
00679   
00680     return true;
00681   }
00682 public:
00683   E(unsigned int a_order,unsigned int a_index): sqm<double>(a_order){
00684     if(!initialize(a_order,a_index)) return; //FIXME : throw
00685   }
00686   virtual ~E(){}
00687 public:
00688   E(const E& a_from): sqm<T>(a_from){}
00689   E& operator=(const E& a_from) {
00690     inlib::sqm<T>::operator=(a_from);
00691     return *this;
00692   }
00693 private:
00694   bool initialize(unsigned int a_order,unsigned int a_index) {
00695     unsigned int number = a_order * (a_order-1)/2;
00696     if(a_index>number) return false;
00697 
00698     // Find column from index :
00699     bool found = false;
00700     unsigned int c = 0;
00701     unsigned int mn = 0;
00702     unsigned int mx = 0;
00703     for(c=1;c<a_order;c++) {
00704       mn = c*(c-1)/2;
00705       mx = c*(c+1)/2-1;
00706       if((mn<=a_index)&&(a_index<=mx)) {
00707         found = true;
00708         break;
00709       }
00710     }
00711     if(!found) return false;
00712     // ok, then compute row :
00713     unsigned int r = a_index - mn;
00714     //printf("debug : %d : r %d c %d : mn %d mx %d\n",a_index,r,c,mn,mx);
00715     // then set value :
00716     T value = power(-1,r+c+1);
00717     // If one, then rot 3D vec csts are no more epsilon(i,j,k).
00718     //T value = 1;
00719     set_value_no_check(r,c,value);
00720     set_value_no_check(c,r,-value);
00721   
00722     unsigned int icheck = c*(c-1)/2+r;
00723     if(a_index!=icheck) return false;
00724     return true;
00725   }
00726   static T power(const T& a_A,unsigned int a_B){
00727     T v = 1;
00728     for(unsigned int i=0;i<a_B;i++) v *= a_A; 
00729     return v;
00730   }
00731 };
00732 
00734 // Poincare group in "a_order" dimension with delta metric (identity).
00735 //
00736 // From the operator representation :
00737 //   OpRep_k = 1/2 * J_mu_nu * En_k_mu_nu   with k in [0,n*(n-1)/2[
00738 //   OpRep_alpha = D_alpha                  with alpha in [0,n[
00739 // With :
00740 //   J_mu_nu =   delta_mu_alpha * coord_alpha * D_nu 
00741 //             - delta_nu_alpha * coord_alpha * D_mu
00742 // Not null group constants are :
00743 //   c(j,k,l) = e_n(j,k,l)
00744 //   c(j,alpha,beta) = En_j_beta_alpha
00746 // T must accept -1,0,1
00747 template <class T>
00748 class poincare_cartan_metric : public sqm<T> {
00749 public:
00750   poincare_cartan_metric(unsigned int a_order)
00751   :sqm<T>(a_order*(a_order+1)/2){
00752     unsigned int number = a_order*(a_order+1)/2;
00753 
00754     // Fill the adjoint representation :
00755     //      c        c
00756     //  (Xa)  = cst
00757     //      b      ab
00758     // a,b,c in [0,n*(n+1)/2[
00759   
00760     std::vector< sqm<T> > xs;
00761   
00762    {array<T> csts;
00763     if(!E<T>::group_constants(a_order,csts)) return;
00764     unsigned int n = a_order*(a_order-1)/2;
00765     for(unsigned int index=0;index<n;index++) {
00766       sqm<T> x(number);
00767   
00768      {for(unsigned int j=0;j<n;j++) {
00769         for(unsigned int k=0;k<n;k++) {
00770           std::vector<unsigned int> is(3);
00771           is[0] = index;
00772           is[1] = k;
00773           is[2] = j;
00774           T value;
00775           if(!csts.value(is,value)) return;
00776           if(!x.set_value(j,k,value)) return;
00777         }
00778       }}
00779   
00780      {E<T> E(a_order,index);
00781       for(unsigned int j=0;j<a_order;j++) {
00782         for(unsigned int k=0;k<a_order;k++) {
00783   
00784           T value = E.value(j,k);
00785   
00786           if(!x.set_value(n+j,n+k,value)) return;
00787         }
00788       }}
00789   
00790       xs.push_back(x);
00791     }}
00792   
00793    {for(unsigned int index=0;index<a_order;index++) {
00794       sqm<T> x(number);
00795       xs.push_back(x);
00796     }}
00797   
00798     // Set cartan killing metric :
00799    {for(unsigned int j=0;j<number;j++) {
00800       for(unsigned int k=0;k<number;k++) {
00801         inlib::sqm<T> mx = xs[j]*xs[k];
00802         if(!set_value(j,k,mx.trace())) return;
00803       }
00804     }}
00805   
00806   }
00807 };
00808 
00809 }
00810 
00811 #include <ostream>
00812 
00813 namespace inlib {
00814 
00815 //NOTE : print is a Python keyword.
00816 template <class T>
00817 inline void dump(const sqm<T>& a_matrix,std::ostream& a_out,const std::string& aCMT) {
00818   if(aCMT.size()) a_out << aCMT << std::endl;
00819   unsigned int ord = a_matrix.order();
00820   for(unsigned int r=0;r<ord;r++) {
00821     for(unsigned int c=0;c<ord;c++) {
00822       a_out << " " << a_matrix.value(r,c);
00823     }
00824     a_out << std::endl;
00825   }
00826 }
00827 
00828 template <class T>
00829 inline bool check_invert(const sqm<T>& a_matrix,std::ostream& a_out) {
00830   unsigned int ord = a_matrix.order();
00831   sqm<T> I(ord);
00832   I.set_identity();
00833   sqm<T> inv(ord);
00834   if(!a_matrix.invert(inv)) return false;
00835   //sqm<T> tmp(ord);
00836   //a_matrix.mx_mul(inv,tmp);
00837   sqm<T> tmp = a_matrix * inv;
00838   if(!tmp.equal(I)) {
00839     dump(a_matrix,a_out,"problem with inv of :");
00840     dump(inv,a_out,"found :");
00841     return false;
00842   }
00843   return true;
00844 }
00845 
00846 }
00847 
00848 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines