inlib
1.2.0
|
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