HepLib
Basic.cpp
Go to the documentation of this file.
1 
6 #include "HEP.h"
7 #include "flint/ulong_extras.h"
8 
9 namespace HepLib {
10 
11  DEFAULT_CTOR(Index)
12  IMPLEMENT_HAS(Index)
13  IMPLEMENT_ALL(Index)
14 
15  DEFAULT_CTOR(Vector)
16  IMPLEMENT_HAS(Vector)
17  IMPLEMENT_ALL(Vector)
18 
19  DEFAULT_CTOR(SUNT)
20  IMPLEMENT_HAS(SUNT)
21  IMPLEMENT_ALL(SUNT)
22 
23  DEFAULT_CTOR(SUNF)
24  IMPLEMENT_HAS(SUNF)
25  IMPLEMENT_ALL(SUNF)
26 
27  DEFAULT_CTOR(SUNF4)
28  IMPLEMENT_HAS(SUNF4)
29  IMPLEMENT_ALL(SUNF4)
30 
31  //-----------------------------------------------------------
32  // FormFormat Output
33  //-----------------------------------------------------------
34  FormFormat::FormFormat(ostream &os, unsigned opt) : print_dflt(os, opt) {}
35  FormFormat::FormFormat() : print_dflt(std::cout) {}
36  GINAC_IMPLEMENT_PRINT_CONTEXT(FormFormat, print_dflt)
37 
38  const FormFormat & FormFormat::operator << (const basic & v) const {
39  v.print(*this);
40  return *this;
41  }
42  const FormFormat & FormFormat::operator << (const ex & v) const {
43  v.print(*this);
44  return *this;
45  }
46  const FormFormat & FormFormat::operator << (const lst & v) const {
47  v.print(*this);
48  return *this;
49  }
50  const FormFormat & FormFormat::operator<<(std::ostream& (*v)(std::ostream&)) const {
51  s << v;
52  return *this;
53  }
54 
55  void FormFormat::power_print(const power & p, const FormFormat & c, unsigned level) {
56  if(p.op(1)==2 && !DGamma::has(p)) {
57  c << "((" << p.op(0) << ")*(" << p.op(0) << "))";
58  } else {
59  c << "((" << p.op(0) << ")^(" << p.op(1) << "))";
60  }
61  }
62 
63  //-----------------------------------------------------------
64  // FCFormat Output
65  //-----------------------------------------------------------
66  FCFormat::FCFormat(ostream &os, unsigned opt) : print_dflt(os, opt) {}
67  FCFormat::FCFormat() : print_dflt(std::cout) {}
68  GINAC_IMPLEMENT_PRINT_CONTEXT(FCFormat, print_dflt)
69 
70  const FCFormat & FCFormat::operator << (const basic & v) const {
71  v.print(*this);
72  return *this;
73  }
74  const FCFormat & FCFormat::operator << (const ex & v) const {
75  v.print(*this);
76  return *this;
77  }
78  const FCFormat & FCFormat::operator << (const lst & v) const {
79  v.print(*this);
80  return *this;
81  }
82  const FCFormat & FCFormat::operator<<(std::ostream& (*v)(std::ostream&)) const {
83  s << v;
84  return *this;
85  }
86 
87  const FCFormat & FCFormat::operator << (const matrix & mat) const {
88  s << "{";
89  int nr = mat.rows();
90  int nc = mat.cols();
91  for(int r=0; r<nr; r++) {
92  s << "{";
93  for(int c=0; c<nc; c++) {
94  mat(r,c).print(*this);
95  if(c+1!=nc) s << ",";
96  }
97  s << "}";
98  if(r+1!=nr) s << ",";
99  }
100  s << "}";
101  return *this;
102  }
103 
104  const FCFormat & FCFormat::operator << (const exvector & e) const {
105  auto i = e.begin();
106  auto vend = e.end();
107  if (i==vend) { s << "{}"; return *this; }
108  s << "{";
109  while (true) {
110  i->print(*this);
111  ++i;
112  if(i==vend) break;
113  s << ",";
114  }
115  s << "}";
116  return *this;
117  }
118 
119  const FCFormat & FCFormat::operator << (const exset & e) const {
120  auto i = e.begin();
121  auto send = e.end();
122  if (i==send) { s << "{}"; return *this; }
123  s << "{";
124  while (true) {
125  i->print(*this);
126  ++i;
127  if(i==send) break;
128  s << ",";
129  }
130  s << "}";
131  return *this;
132  }
133 
134  const FCFormat & FCFormat::operator << (const exmap & e) const {
135  auto i = e.begin();
136  auto mend = e.end();
137  if (i==mend) { s << "{}"; return *this; }
138  s << "{";
139  while (true) {
140  i->first.print(*this);
141  s << "->";
142  i->second.print(*this);
143  ++i;
144  if(i==mend) break;
145  s << ",";
146  }
147  s << "}";
148  return *this;
149  }
150 
151  namespace {
152  class ncmul_hack : public ncmul { // due to printseq is protected
153  public:
154  ncmul_hack(ncmul _nm) : ncmul(_nm){ }
155  void print(const FCFormat & c, unsigned level) {
156  printseq(c, '(', '.', ')', precedence(), level);
157  }
158  };
159  ex mat_conj(const ex & e1, const ex & e2, const ex & e3) {
160  return Matrix(e1.conjugate(), e3, e2);
161  }
162  }
163  void FCFormat::ncmul_print(const ncmul & nm, const FCFormat & c, unsigned level) {
164  ncmul_hack(nm).print(c, level);
165  }
166 
167  //-----------------------------------------------------------
168  // Index Class
169  //-----------------------------------------------------------
170  //GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(Index, basic,print_func<print_context>(&Index::print))
171  GiNaC::registered_class_info & Index::get_class_info_static() { return reg_info; }
173  Index * Index::duplicate() const { Index * bp = new Index(*this); bp->setflag(GiNaC::status_flags::dynallocated); return bp; }
174  void Index::accept(GiNaC::visitor & v) const { if (visitor *p = dynamic_cast<visitor *>(&v)) p->visit(*this); else inherited::accept(v); }
175  const GiNaC::registered_class_info &Index::get_class_info() const { return get_class_info_static(); }
176  GiNaC::registered_class_info &Index::get_class_info() { return get_class_info_static(); }
177  const char *Index::class_name() const { return get_class_info_static().options.get_name(); }
178  //GINAC_IMPLEMENT_REGISTERED_CLASS END
179 
180  Index::Index(const string &s, const Type t) : name(s), type(t) { }
181  int Index::compare_same_type(const basic &other) const {
182  if(!is_a<Index>(other)) throw Error("Index::compare_same_type");
183  const Index &o = static_cast<const Index &>(other);
184  auto ret = name.get_name().compare(o.name.get_name());
185  if(ret==0) return 0;
186  else if(ret<0) return -1;
187  else return 1;
188  }
189 
190  bool Index::is_equal_same_type(const basic & other) const {
191  if(!is_a<Index>(other)) throw Error("Index::is_equal_same_type");
192  const Index &o = static_cast<const Index &>(other);
193  return (name.get_name() == o.name.get_name());
194  }
195 
196  void Index::print(const print_context &c, unsigned level) const {
197  c.s << name;
198  }
199 
201  return Pair(*this, i);
202  }
203 
205  return Pair(p, *this);
206  }
207 
208  void Index::archive(archive_node & n) const {
209  inherited::archive(n);
210  n.add_string("name", name.get_name());
211  n.add_unsigned("type", type);
212  }
213 
214  void Index::read_archive(const archive_node& n) {
215  inherited::read_archive(n);
216  string nstr;
217  unsigned t;
218  n.find_string("name", nstr);
219  name = Symbol(nstr);
220  n.find_unsigned("type", t);
221  type = (Type)t;
222  }
223 
224  ex Index::derivative(const symbol & s) const {
225  return 0;
226  }
227 
228  bool Index::hasc(const ex & e) {
229  for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i)
230  if(is_a<Index>(*i) && ex_to<Index>(*i).type!=Index::Type::VD) return true;
231  return false;
232  }
233 
234  bool Index::hasv(const ex & e) {
235  for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i)
236  if(is_a<Index>(*i) && ex_to<Index>(*i).type==Index::Type::VD) return true;
237  return false;
238  }
239 
240  //-----------------------------------------------------------
241  // Vector Class
242  //-----------------------------------------------------------
243  //GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(Vector, basic,print_func<print_context>(&Vector::print))
244  GiNaC::registered_class_info & Vector::get_class_info_static() { return reg_info; }
246  Vector * Vector::duplicate() const { Vector * bp = new Vector(*this); bp->setflag(GiNaC::status_flags::dynallocated); return bp; }
247  void Vector::accept(GiNaC::visitor & v) const { if (visitor *p = dynamic_cast<visitor *>(&v)) p->visit(*this); else inherited::accept(v); }
248  const GiNaC::registered_class_info &Vector::get_class_info() const { return get_class_info_static(); }
249  GiNaC::registered_class_info &Vector::get_class_info() { return get_class_info_static(); }
250  const char *Vector::class_name() const { return get_class_info_static().options.get_name(); }
251  //GINAC_IMPLEMENT_REGISTERED_CLASS END
252 
253  Vector::Vector(const string &s) : name(s) { }
254  int Vector::compare_same_type(const basic &other) const {
255  if(!is_a<Vector>(other)) throw Error("Vector::compare_same_type");
256  const Vector &o = static_cast<const Vector &>(other);
257  auto ret = name.get_name().compare(o.name.get_name());
258  if(ret==0) return 0;
259  else if(ret<0) return -1;
260  else return 1;
261  }
262 
263  bool Vector::is_equal_same_type(const basic & other) const {
264  if(!is_a<Vector>(other)) throw Error("Vector::is_equal_same_type");
265  const Vector &o = static_cast<const Vector &>(other);
266  return (name.get_name() == o.name.get_name());
267  }
268 
269  void Vector::print(const print_context &c, unsigned level) const {
270  c.s << name;
271  }
272 
274  return Pair(*this, p);
275  }
276 
278  return Pair(*this, i);
279  }
280 
281  void Vector::archive(archive_node & n) const {
282  inherited::archive(n);
283  n.add_string("name", name.get_name());
284  }
285 
286  void Vector::read_archive(const archive_node& n) {
287  inherited::read_archive(n);
288  string nstr;
289  unsigned t;
290  n.find_string("name", nstr);
291  name = Symbol(nstr);
292  }
293 
294  ex Vector::derivative(const symbol & s) const {
295  return 0;
296  }
297 
298  //GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(SUNT, basic,print_func<print_dflt>(&SUNT::print).print_func<FormFormat>(&SUNT::form_print).print_func<FCFormat>(&SUNT::fc_print))
299  GiNaC::registered_class_info & SUNT::get_class_info_static() { return reg_info; }
301  SUNT * SUNT::duplicate() const { SUNT * bp = new SUNT(*this); bp->setflag(GiNaC::status_flags::dynallocated); return bp; }
302  void SUNT::accept(GiNaC::visitor & v) const { if (visitor *p = dynamic_cast<visitor *>(&v)) p->visit(*this); else inherited::accept(v); }
303  const GiNaC::registered_class_info &SUNT::get_class_info() const { return get_class_info_static(); }
304  GiNaC::registered_class_info &SUNT::get_class_info() { return get_class_info_static(); }
305  const char *SUNT::class_name() const { return get_class_info_static().options.get_name(); }
306  //GINAC_IMPLEMENT_REGISTERED_CLASS END
307 
308  SUNT::SUNT(ex a, ex i, ex j) : aij{a,i,j} { }
309  int SUNT::compare_same_type(const basic &other) const {
310  if(!is_a<SUNT>(other)) throw Error("SUNT::compare_same_type");
311  const SUNT &o = static_cast<const SUNT &>(other);
312  for(int i=0; i<3; i++) {
313  auto c = aij[i].compare(o.aij[i]);
314  if(c!=0) return c;
315  }
316  return 0;
317  }
318 
319  bool SUNT::is_equal_same_type(const basic & other) const {
320  if(!is_a<SUNT>(other)) throw Error("SUNT::is_equal_same_type");
321  const SUNT &o = static_cast<const SUNT &>(other);
322  for(int i=0; i<3; i++) {
323  if(!aij[i].is_equal(o.aij[i])) return false;
324  }
325  return true;
326  }
327 
328  void SUNT::form_print(const FormFormat &c, unsigned level) const {
329  if(is_a<lst>(aij[0])) {
330  bool first = true;
331  for(auto item : aij[0]) {
332  if(first) { first=false; c << "T(" << item; }
333  else c << "," << item;
334  }
335  } else c << "T(" << aij[0];
336  c << "," << aij[1] << "," << aij[2] << ")";
337  }
338 
339  void SUNT::fc_print(const FCFormat &c, unsigned level) const {
340  c << "SUNTF[" << aij[0] << "," << aij[1] << "," << aij[2] << "]";
341  }
342 
343  void SUNT::print(const print_dflt &c, unsigned level) const {
344  c.s << "T(" << aij[0] << "," << aij[1] << "," << aij[2] << ")";
345  }
346 
347  size_t SUNT::nops() const { return 3; }
348  ex SUNT::op(size_t i) const {
349  return aij[i];
350  }
351  ex & SUNT::let_op(size_t i) {
352  ensure_if_modifiable();
353  return aij[i];
354  }
355 
356  void SUNT::archive(archive_node & n) const {
357  inherited::archive(n);
358  n.add_ex("a", aij[0]);
359  n.add_ex("i", aij[1]);
360  n.add_ex("j", aij[2]);
361  }
362 
363  void SUNT::read_archive(const archive_node& n) {
364  inherited::read_archive(n);
365  ex o;
366  n.find_ex("a", o);
367  aij[0] = ex_to<Index>(o);
368  n.find_ex("i", o);
369  aij[1] = ex_to<Index>(o);
370  n.find_ex("j", o);
371  aij[2] = ex_to<Index>(o);
372  }
373 
374  ex SUNT::derivative(const symbol & s) const {
375  return 0;
376  }
377 
378  ex SUNT::conjugate() const {
379  if(!is_a<lst>(aij[0])) return SUNT(aij[0], aij[2], aij[1]);
380  lst argv = ex_to<lst>(aij[0]);
381  lst as;
382  for(auto it=argv.rbegin(); it!=argv.rend(); ++it) as.append(*it);
383  return SUNT(as, aij[2], aij[1]);
384  }
385 
386  //GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(SUNF, basic,print_func<print_dflt>(&SUNF::print).print_func<FormFormat>(&SUNF::form_print).print_func<FCFormat>(&SUNF::fc_print))
387  GiNaC::registered_class_info & SUNF::get_class_info_static() { return reg_info; }
389  SUNF * SUNF::duplicate() const { SUNF * bp = new SUNF(*this); bp->setflag(GiNaC::status_flags::dynallocated); return bp; }
390  void SUNF::accept(GiNaC::visitor & v) const { if (visitor *p = dynamic_cast<visitor *>(&v)) p->visit(*this); else inherited::accept(v); }
391  const GiNaC::registered_class_info &SUNF::get_class_info() const { return get_class_info_static(); }
392  GiNaC::registered_class_info &SUNF::get_class_info() { return get_class_info_static(); }
393  const char *SUNF::class_name() const { return get_class_info_static().options.get_name(); }
394  //GINAC_IMPLEMENT_REGISTERED_CLASS END
395 
396  SUNF::SUNF(ex i, ex j, ex k) : ijk{i,j,k} { }
397  int SUNF::compare_same_type(const basic &other) const {
398  if(!is_a<SUNF>(other)) throw Error("SUNF::compare_same_type");
399  const SUNF &o = static_cast<const SUNF &>(other);
400  for(int i=0; i<3; i++) {
401  auto c = ijk[i].compare(o.ijk[i]);
402  if(c!=0) return c;
403  }
404  return 0;
405  }
406 
407  bool SUNF::is_equal_same_type(const basic & other) const {
408  if(!is_a<SUNF>(other)) throw Error("SUNF::is_equal_same_type");
409  const SUNF &o = static_cast<const SUNF &>(other);
410  for(int i=0; i<3; i++) {
411  if(!ijk[i].is_equal(o.ijk[i])) return false;
412  }
413  return true;
414  }
415 
416  ex SUNF::eval() const {
417  if(flags & status_flags::evaluated) return *this;
418  if(ijk[0].is_equal(ijk[1]) || ijk[1].is_equal(ijk[2]) || ijk[0].is_equal(ijk[2])) return 0;
419  bool c01 = ex_less(ijk[0],ijk[1]);
420  bool c12 = ex_less(ijk[1],ijk[2]);
421  if(c01 && c12) return this->hold();
422  bool c02 = ex_less(ijk[0],ijk[2]);
423  if(!c01 && c02) return -SUNF(ijk[1],ijk[0],ijk[2]);
424  else if(c02 && !c12) return -SUNF(ijk[0],ijk[2],ijk[1]);
425  else if(!c02 && c01) return SUNF(ijk[2],ijk[0],ijk[1]);
426  else if(c12 && !c02) return SUNF(ijk[1],ijk[2],ijk[0]);
427  else if(!c12 && !c01) return -SUNF(ijk[2],ijk[1],ijk[0]);
428  else return this->hold();
429  }
430 
431  void SUNF::print(const print_dflt &c, unsigned) const {
432  c.s << "f(" << ijk[0] << "," << ijk[1] << "," << ijk[2] << ")";
433  }
434 
435  void SUNF::form_print(const FormFormat &c, unsigned) const {
436  c << "f(" << ijk[0] << "," << ijk[1] << "," << ijk[2] << ")";
437  }
438 
439  void SUNF::fc_print(const FCFormat &c, unsigned) const {
440  c << "SUNF[" << ijk[0] << "," << ijk[1] << "," << ijk[2] << "]";
441  }
442 
443  size_t SUNF::nops() const { return 3; }
444  ex SUNF::op(size_t i) const {
445  return ijk[i];
446  }
447  ex & SUNF::let_op(size_t i) {
448  ensure_if_modifiable();
449  return ijk[i];
450  }
451 
452  void SUNF::archive(archive_node & n) const {
453  inherited::archive(n);
454  n.add_ex("i", ijk[0]);
455  n.add_ex("j", ijk[1]);
456  n.add_ex("k", ijk[2]);
457  }
458 
459  void SUNF::read_archive(const archive_node& n) {
460  inherited::read_archive(n);
461  ex o;
462  n.find_ex("i", o);
463  ijk[0] = ex_to<Index>(o);
464  n.find_ex("j", o);
465  ijk[1] = ex_to<Index>(o);
466  n.find_ex("k", o);
467  ijk[2] = ex_to<Index>(o);
468  }
469 
475  ex SUNF::derivative(const symbol & s) const {
476  return 0;
477  }
478 
479  //GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(SUNF4, basic,print_func<print_dflt>(&SUNF4::print).print_func<FormFormat>(&SUNF4::form_print).print_func<FCFormat>(&SUNF4::fc_print))
480  GiNaC::registered_class_info & SUNF4::get_class_info_static() { return reg_info; }
482  SUNF4 * SUNF4::duplicate() const { SUNF4 * bp = new SUNF4(*this); bp->setflag(GiNaC::status_flags::dynallocated); return bp; }
483  void SUNF4::accept(GiNaC::visitor & v) const { if (visitor *p = dynamic_cast<visitor *>(&v)) p->visit(*this); else inherited::accept(v); }
484  const GiNaC::registered_class_info &SUNF4::get_class_info() const { return get_class_info_static(); }
485  GiNaC::registered_class_info &SUNF4::get_class_info() { return get_class_info_static(); }
486  const char *SUNF4::class_name() const { return get_class_info_static().options.get_name(); }
487  //GINAC_IMPLEMENT_REGISTERED_CLASS END
488 
489  SUNF4::SUNF4(ex i, ex j, ex k, ex l) : ijkl{i,j,k,l} { }
490  int SUNF4::compare_same_type(const basic &other) const {
491  if(!is_a<SUNF4>(other)) throw Error("SUNF4::compare_same_type");
492  const SUNF4 &o = static_cast<const SUNF4 &>(other);
493  for(int i=0; i<4; i++) {
494  auto c = ijkl[i].compare(o.ijkl[i]);
495  if(c!=0) return c;
496  }
497  return 0;
498  }
499 
500  bool SUNF4::is_equal_same_type(const basic & other) const {
501  if(!is_a<SUNF4>(other)) throw Error("SUNF4::is_equal_same_type");
502  const SUNF4 &o = static_cast<const SUNF4 &>(other);
503  for(int i=0; i<4; i++) {
504  if(!ijkl[i].is_equal(o.ijkl[i])) return false;
505  }
506  return true;
507  }
508 
513  ex SUNF4::eval() const {
514  if(flags & status_flags::evaluated) return *this;
515  if(ijkl[0].is_equal(ijkl[1]) || ijkl[2].is_equal(ijkl[3])) return 0;
516  bool c01 = ex_less(ijkl[0],ijkl[1]);
517  bool c23 = ex_less(ijkl[2],ijkl[3]);
518  if(c01 && c23) return this->hold(); // 01-23
519  else if(!c01 && c23) return -SUNF4(ijkl[1],ijkl[0],ijkl[2],ijkl[3]);
520  else if(!c01 && !c23) return SUNF4(ijkl[1],ijkl[0],ijkl[3],ijkl[2]);
521  else if(c01 && !c23) return -SUNF4(ijkl[0],ijkl[1],ijkl[3],ijkl[2]);
522  else return this->hold();
523  }
524 
530  void SUNF4::print(const print_dflt &c, unsigned o) const {
531  c.s << "f(" << ijkl[0] << "," << ijkl[1] << "," << ijkl[2] << "," << ijkl[3] << ")";
532  }
533 
534  void SUNF4::fc_print(const FCFormat &c, unsigned o) const {
535  c << "SUNF[" << ijkl[0] << "," << ijkl[1] << "," << ijkl[2] << "," << ijkl[3] << "]";
536  }
537 
543  void SUNF4::form_print(const FormFormat &c, unsigned o) const {
544  c << "f4(" << ijkl[0] << "," << ijkl[1] << "," << ijkl[2] << "," << ijkl[3] << ")";
545  }
546 
547  size_t SUNF4::nops() const { return 4; }
548  ex SUNF4::op(size_t i) const {
549  return ijkl[i];
550  }
551  ex & SUNF4::let_op(size_t i) {
552  ensure_if_modifiable();
553  return ijkl[i];
554  }
555 
560  void SUNF4::archive(archive_node & n) const {
561  inherited::archive(n);
562  n.add_ex("i", ijkl[0]);
563  n.add_ex("j", ijkl[1]);
564  n.add_ex("k", ijkl[2]);
565  n.add_ex("l", ijkl[3]);
566  }
567 
572  void SUNF4::read_archive(const archive_node& n) {
573  inherited::read_archive(n);
574  ex o;
575  n.find_ex("i", o);
576  ijkl[0] = ex_to<Index>(o);
577  n.find_ex("j", o);
578  ijkl[1] = ex_to<Index>(o);
579  n.find_ex("k", o);
580  ijkl[2] = ex_to<Index>(o);
581  n.find_ex("l", o);
582  ijkl[3] = ex_to<Index>(o);
583  }
584 
590  ex SUNF4::derivative(const symbol & s) const {
591  return 0;
592  }
593 
599  ex MatrixContract(const ex & expr_in) {
600  if(!expr_in.has(Matrix(w1,w2,w3))) return expr_in;
601 
602  auto expr = expr_in.subs(pow(Matrix(w1,w2,w3),2)==Matrix(w1,w2,w3)*Matrix(w1,w3,w2));
603  auto cv_lst = collect_lst(expr, Matrix(w1, w2, w3));
604  expr = 0;
605  for(auto cv : cv_lst) {
606  auto e = cv.op(1);
607  if(is_zero(e-1) || e.match(Matrix(w1, w2, w3))) {
608  expr += cv.op(0) * e;
609  continue;
610  } else if(!is_a<mul>(e)) throw Error("MatrixContract: collect error: " + ex2str(e));
611 
612  lst mats;
613  for(auto item : e) mats.append(item);
614 
615  std::map<ex,int,ex_is_less> to_map, from_map;
616  std::set<int> todo;
617  lst mats_idx;
618  for(int i=0; i<mats.nops(); i++) {
619  auto item = mats.op(i);
620  if(item.op(0).return_type()==return_types::commutative || item.op(0).is_equal(GAS(1)) || item.op(0).is_equal(color_ONE())) {
621  mats_idx.append(lst{item,i});
622  } else {
623  if(to_map[item.op(1)]!=0 || from_map[item.op(2)]!=0) throw Error("MatrixContract: index conflict for "+ex2str(item));
624  to_map[item.op(1)] = i+10; // avoid 0 in map
625  from_map[item.op(2)] = i+10; // avoid 0 in map
626  }
627  todo.insert(i);
628  }
629 
630  // update to_map/from_map w.r.t mats_idx
631  bool checked = false;
632  while(true) {
633  lst mats_idx2;
634  bool ok = true; // double check
635  for(int i=0; i<mats_idx.nops(); i++) {
636  auto item = mats_idx.op(i).op(0);
637  int ii = ex_to<numeric>(mats_idx.op(i).op(1)).to_int();
638  if(!checked &&
639  to_map[item.op(1)]==0 && from_map[item.op(2)]==0 &&
640  to_map[item.op(2)]==0 && from_map[item.op(1)]==0) {
641  mats_idx2.append(mats_idx.op(i));
642  continue;
643  }
644  ok = false;
645  checked = false;
646  if(to_map[item.op(1)]==0 && from_map[item.op(2)]==0) {
647  to_map[item.op(1)] = ii+10; // avoid 0 in map
648  from_map[item.op(2)] = ii+10; // avoid 0 in map
649  } else if(to_map[item.op(2)]==0 && from_map[item.op(1)]==0) {
650  to_map[item.op(2)] = ii+10; // avoid 0 in map
651  from_map[item.op(1)] = ii+10; // avoid 0 in map
652  // need to swap the 2nd and 3rd index
653  auto li = get_op(mats, ii, 1);
654  auto ri = get_op(mats, ii, 2);
655  let_op(mats, ii, 1, ri);
656  let_op(mats, ii, 2, li);
657  } else {
658  throw Error("MatrixContract: index conflict (2).");
659  }
660  }
661  if(mats_idx2.nops()<1) break;
662  mats_idx = mats_idx2;
663  if(ok) checked=true;
664  }
665 
666  ex retMat = 1;
667  while(todo.size()>0) {
668  int c = *(todo.begin());
669  todo.erase(c);
670  ex curMat = mats.op(c).op(0);
671  auto li=mats.op(c).op(1);
672  auto ri=mats.op(c).op(2);
673  while(true) {
674  if(is_zero(li-ri)) {
675  retMat *= TR(curMat);
676  break;
677  }
678  int ti = to_map[ri];
679  int fi = from_map[li];
680  if(ti==0 && fi==0) {
681  retMat *= Matrix(curMat, li, ri);
682  break;
683  }
684  if(ti!=0) {
685  auto mat = mats.op(ti-10).op(0);
686  if(is_zero(curMat-GAS(1))) curMat = mat;
687  else if(!is_zero(mat-GAS(1))) curMat = curMat * mat;
688  ri = mats.op(ti-10).op(2);
689  todo.erase(ti-10);
690  continue;
691  }
692  if(fi!=0) {
693  auto mat = mats.op(fi-10).op(0);
694  if(is_zero(curMat-GAS(1))) curMat = mat;
695  else if(!is_zero(mat-GAS(1))) curMat = mat * curMat;
696  li = mats.op(fi-10).op(1);
697  todo.erase(fi-10);
698  continue;
699  }
700  }
701  }
702  expr += cv.op(0) * retMat;
703  }
704 
705  return expr;
706  }
707 
708  namespace {
709  void Matrix_fc_print(const ex &arg1, const ex &arg2, const ex &arg3, const print_context &c0) {
710  auto c = static_cast<const FCFormat &>(c0);
711  c << "Matrix[" << arg1 << "," << arg2 << "," << arg3 << "]";
712  }
713  }
714 
715  REGISTER_FUNCTION(Matrix, do_not_evalf_params().print_func<FCFormat>(&Matrix_fc_print).conjugate_func(mat_conj).set_return_type(return_types::commutative))
716 
717  bool IsZero(const ex & e) {
718  try {
719  exset vs;
720  for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) {
721  if(is_a<symbol>(*i) || is_a<Pair>(*i)) vs.insert(*i);
722  }
723 
724  int n = 13;
725  for(int i=0; i<5; i++) {
726  exmap nsubs;
727  for(auto item : vs) {
728  nsubs[item] = ex(1)/n_nth_prime(n);
729  n++;
730  }
731  ex ret = e.subs(nsubs);
732  if(!normal(e).is_zero()) return false;
733  }
734 
735  auto ret = exnormal(e);
736  return ret.is_zero();
737  } catch(...) { }
738  return is_zero(exnormal(e));
739  }
740 
741  ex ToCF(const ex & e) {
742  ex res = e;
743  bool todo = true;
744  while(todo) {
745  todo = false;
746  auto cvs = collect_lst(res, lst{NF,TF});
747  res = 0;
748  for(auto cv : cvs) {
749  int degTF = cv.op(1).degree(TF);
750  int degNF = cv.op(1).ldegree(NF);
751  if(degTF>0 && degNF<0) {
752  todo = true;
753  int n = degTF;
754  if(degTF+degNF>0) n = -degNF;
755  res += cv.op(0) * cv.op(1) * pow(TF/NF,-n) * pow(TF*NF-CF,n);
756  } else if(degTF>0 && degNF>1) {
757  todo = true;
758  int n = degTF;
759  if(degTF>degNF/2) n = degNF/2;
760  res += cv.op(0) * cv.op(1) * pow(TF*NF*NF,-n) * pow(CF*NF+TF,n);
761  } else res += cv.op(0) * cv.op(1);
762  }
763  }
764  return res;
765  }
766 
767  ex ca_neg_pow_sub(const ex & expr) {
768  static MapFunction ca_map([](const ex & e, MapFunction & self)->ex {
769  if(!e.has(CA)) return e;
770  else if(e.match(pow(CA,w)) && e.op(1).info(info_flags::negint)) return pow(CA-2*CF,-e.op(1));
771  else return e.map(self);
772  });
773  return ca_map(expr);
774  }
775 
776  ex ToCACF(const ex & e) { // from FeynCalc
777  ex res = e.subs(lst{NA==(NF*NF-1),CF==(NF*NF-1)/(2*NF),TF==ex(1)/2});
778  res = exfactor(res);
779  // SUNN -> CA
780  res = res.subs(NF==CA);
781  // (-1+CA^2)->(-2 CA CF)
782  res = res.subs(lst{ w*(1-CA)*(1+CA)==-w*2*CA*CF, w*(-1+CA)*(1+CA)==w*2*CA*CF });
783  res = res.subs(lst{ w1*pow(1-CA,w2)*pow(1+CA,w2)==w1*pow(-2*CA*CF,w2), w1*pow(-1+CA,w2)*pow(1+CA,w2)==w1*pow(2*CA*CF,w2) });
784  // (((2 - CA^2) CF )/CA ) ->(CF (CA - 4 CF))
785  res = res.subs(lst{ w*(2-CA*CA)*CF/CA==w*CF*(CA-4*CF), w*(-2+CA*CA)*CF/CA==w*CF*(-CA+4*CF) });
786  // (1-CA^2) -> (-2 CA CF)
787  res = res.subs(lst{ w*(1-CA)*(1+CA)==-w*2*CA*CF, w*(-1+CA)*(1+CA)==w*2*CA*CF });
788  res = res.subs(lst{ w1*pow(1-CA,w2)*pow(1+CA,w2)==-w1*pow(2*CA*CF,w2), w1*pow(-1+CA,w2)*pow(1+CA,w2)==w1*pow(2*CA*CF,w2) });
789  // (1/CA)^n -> (CA - 2 CF)^n
790  //res = res.subs(lst{ w/CA==w*(CA-2*CF) });
791  res = ca_neg_pow_sub(res);
792  // ((1 - CA^2)*(CA - 2*CF)) -> (-2*CF)
793  res = res.subs(lst{ w*(1-CA)*(1+CA)*(CA-2*CF)==-2*w*CF, w*(-1+CA)*(1+CA)*(CA-2*CF)==2*w*CF });
794  // (CA (CA-2 CF)) -> 1
795  res = res.subs(lst{ w*CA*(CA-2*CF)==w, w*CA*(-CA+2*CF)==-w });
796  res = res.subs(lst{ w1*pow(CA,w2)*pow(CA-2*CF,w2)==w1, w1*pow(CA,w2)*pow(-CA+2*CF,w2)==w*pow(-1,w2) });
797  // (CA^2+c)(CA-2CF) -> CA+c(CA-2CF)
798  res = res.subs(lst{ w0*(CA*CA+w1)*(CA-2*CF)==w0*(CA+w1*(CA-2*CF)), w0*(CA*CA+w1)*(-CA+2*CF)==-w0*(CA+w1*(CA-2*CF)) });
799  res = res.subs(lst{ w0*(CA*CA+w1)*pow(CA-2*CF,w2)==w0*(CA+w1*(CA-2*CF))*pow(CA-2*CF,w2-1), w0*(CA*CA+w1)*pow(-CA+2*CF,w2)==-w0*(CA+w1*(CA-2*CF))*pow(-CA+2*CF,w2-1) });
800  return res;
801  }
802 
803  ex HomCACF(const ex & e) {
804  ex res = e.subs(lst{NA==(NF*NF-1),CA==NF,CF==(NF*NF-1)/(2*NF),TF==ex(1)/2});
805  res = exfactor(res);
806  if(!is_a<mul>(res)) res = lst{ res };
807  ex c=1, v=1;
808  for(auto item : res) {
809  if(item.has(NF)) c *= item;
810  else v *= item;
811  }
812  c = collect_ex(c, NF);
813  int deg = c.degree(NF);
814  int ldeg = -c.ldegree(NF);
815  if(ldeg>deg) deg = ldeg;
816  if(deg>0) {
817  lst vars;
818  ex eqn = c;
819  for(int i=0; i<=deg; i++) {
820  symbol xi;
821  eqn -= xi * pow(NF,i) * pow((NF*NF-1)/(2*NF), deg-i);
822  vars.append(xi);
823  }
824  eqn = collect_ex(eqn, NF);
825  int nH = eqn.degree(NF);
826  int nL = eqn.ldegree(NF);
827  lst eqns;
828  for(int i=nL; i<=nH; i++) {
829  ex cc = eqn.coeff(NF, i);
830  if(cc.is_zero()) continue;
831  eqns.append(cc==0);
832  }
833  auto sol = lsolve(eqns, vars);
834  if(sol.nops()!=deg+1) {
835  cout << "c=" << c << endl;
836  cout << "sol=" << sol << endl;
837  throw Error("HomCACF: no solution found!");
838  }
839  c = 0;
840  for(int i=0; i<=deg; i++) c += vars.op(i).subs(sol) * pow(CA,i) * pow(CF, deg-i);
841  }
842  return c * v;
843  }
844 
845  ex DoColor(const ex & expr, const ex & pref, int method) {
846  auto cvs = collect_lst(expr, [](const ex &e)->bool{ return Index::hasc(e); });
847  ex res = 0;
848  for(auto const & cv : cvs) {
849  auto cc = cv.op(0);
850  auto vv = cv.op(1);
851  if(method==0) vv = HomCACF(form(vv)/pref)*pref;
852  else vv = ToCACF(form(vv)/pref)*pref;
853  res += cc * vv;
854  }
855  return res;
856  }
857 }
858 
int * a
Definition: Functions.cpp:234
#define IMPLEMENT_HAS(classname)
Definition: BASIC.h:24
#define DEFAULT_CTOR(classname)
Definition: BASIC.h:21
#define IMPLEMENT_ALL(classname)
Definition: BASIC.h:30
HEP header file.
static bool has(const ex &e)
class used to wrap error message
Definition: BASIC.h:242
class for FCFormat Output
Definition: HEP.h:71
static void ncmul_print(const ncmul &p, const FCFormat &c, unsigned level=0)
Definition: Basic.cpp:163
const FCFormat & operator<<(const T &v) const
Definition: HEP.h:77
FCFormat(ostream &os, unsigned opt=0)
Definition: Basic.cpp:66
class for FormFormat Output
Definition: HEP.h:44
static void power_print(const power &p, const FormFormat &c, unsigned level=0)
Definition: Basic.cpp:55
const FormFormat & operator<<(const T &v) const
Definition: HEP.h:50
FormFormat(ostream &os, unsigned opt=0)
Definition: Basic.cpp:34
virtual ~visitor()
Definition: Basic.cpp:172
class for index object
Definition: HEP.h:104
int compare_same_type(const GiNaC::basic &other) const override
Definition: Basic.cpp:181
const char * class_name() const override
Definition: Basic.cpp:177
static bool hasv(const ex &e)
Definition: Basic.cpp:234
void archive(archive_node &n) const override
Definition: Basic.cpp:208
bool is_equal_same_type(const basic &other) const override
Definition: Basic.cpp:190
static GiNaC::registered_class_info & get_class_info_static()
Definition: Basic.cpp:171
Symbol name
Definition: HEP.h:133
Type type
Definition: HEP.h:134
void print(const print_context &c, unsigned level=0) const
Definition: Basic.cpp:196
void read_archive(const archive_node &n) override
Definition: Basic.cpp:214
static bool hasc(const ex &e)
Definition: Basic.cpp:228
ex derivative(const symbol &s) const override
Definition: Basic.cpp:224
const GiNaC::registered_class_info & get_class_info() const override
Definition: Basic.cpp:175
Pair operator()(const Index &i)
Definition: Basic.cpp:200
void accept(GiNaC::visitor &v) const override
Definition: Basic.cpp:174
Index * duplicate() const override
Definition: Basic.cpp:173
class to wrap map_function of GiNaC
Definition: BASIC.h:632
class for Pair object
Definition: HEP.h:322
virtual ~visitor()
Definition: Basic.cpp:481
class for SUNF4 object
Definition: HEP.h:278
void archive(archive_node &n) const override
save to archvie
Definition: Basic.cpp:560
static GiNaC::registered_class_info & get_class_info_static()
Definition: Basic.cpp:480
void form_print(const FormFormat &c, unsigned level=0) const
print the Form Format
Definition: Basic.cpp:543
void accept(GiNaC::visitor &v) const override
Definition: Basic.cpp:483
const GiNaC::registered_class_info & get_class_info() const override
Definition: Basic.cpp:484
size_t nops() const override
Definition: Basic.cpp:547
void fc_print(const FCFormat &c, unsigned level=0) const
Definition: Basic.cpp:534
void print(const print_dflt &c, unsigned level=0) const
normal priint
Definition: Basic.cpp:530
ex op(size_t i) const override
Definition: Basic.cpp:548
ex & let_op(size_t i) override
Definition: Basic.cpp:551
SUNF4 * duplicate() const override
Definition: Basic.cpp:482
ex ijkl[4]
Definition: HEP.h:303
ex eval() const override
automatical evaluation of SUNF4
Definition: Basic.cpp:513
ex derivative(const symbol &s) const override
set derivative of SUNF4 to 0
Definition: Basic.cpp:590
bool is_equal_same_type(const basic &other) const override
Definition: Basic.cpp:500
const char * class_name() const override
Definition: Basic.cpp:486
void read_archive(const archive_node &n) override
read from archive
Definition: Basic.cpp:572
int compare_same_type(const GiNaC::basic &other) const override
Definition: Basic.cpp:490
virtual ~visitor()
Definition: Basic.cpp:388
class for SUNF object
Definition: HEP.h:233
void archive(archive_node &n) const override
Definition: Basic.cpp:452
void print(const print_dflt &c, unsigned level=0) const
Definition: Basic.cpp:431
const char * class_name() const override
Definition: Basic.cpp:393
int compare_same_type(const GiNaC::basic &other) const override
Definition: Basic.cpp:397
ex derivative(const symbol &s) const override
set derivative of SUNF to 0
Definition: Basic.cpp:475
bool is_equal_same_type(const basic &other) const override
Definition: Basic.cpp:407
void form_print(const FormFormat &c, unsigned level=0) const
Definition: Basic.cpp:435
static GiNaC::registered_class_info & get_class_info_static()
Definition: Basic.cpp:387
ex & let_op(size_t i) override
Definition: Basic.cpp:447
SUNF * duplicate() const override
Definition: Basic.cpp:389
ex eval() const override
Definition: Basic.cpp:416
const GiNaC::registered_class_info & get_class_info() const override
Definition: Basic.cpp:391
void read_archive(const archive_node &n) override
Definition: Basic.cpp:459
size_t nops() const override
Definition: Basic.cpp:443
void accept(GiNaC::visitor &v) const override
Definition: Basic.cpp:390
void fc_print(const FCFormat &c, unsigned level=0) const
Definition: Basic.cpp:439
ex op(size_t i) const override
Definition: Basic.cpp:444
ex ijk[3]
Definition: HEP.h:258
virtual ~visitor()
Definition: Basic.cpp:300
class for SUNT object
Definition: HEP.h:189
static GiNaC::registered_class_info & get_class_info_static()
Definition: Basic.cpp:299
bool is_equal_same_type(const basic &other) const override
Definition: Basic.cpp:319
ex & let_op(size_t i) override
Definition: Basic.cpp:351
void archive(archive_node &n) const override
Definition: Basic.cpp:356
size_t nops() const override
Definition: Basic.cpp:347
void form_print(const FormFormat &c, unsigned level=0) const
Definition: Basic.cpp:328
ex op(size_t i) const override
Definition: Basic.cpp:348
const GiNaC::registered_class_info & get_class_info() const override
Definition: Basic.cpp:303
void fc_print(const FCFormat &c, unsigned level=0) const
Definition: Basic.cpp:339
void print(const print_dflt &c, unsigned level=0) const
Definition: Basic.cpp:343
int compare_same_type(const GiNaC::basic &other) const override
Definition: Basic.cpp:309
void read_archive(const archive_node &n) override
Definition: Basic.cpp:363
SUNT * duplicate() const override
Definition: Basic.cpp:301
const char * class_name() const override
Definition: Basic.cpp:305
void accept(GiNaC::visitor &v) const override
Definition: Basic.cpp:302
ex derivative(const symbol &s) const override
Definition: Basic.cpp:374
ex aij[3]
Definition: HEP.h:214
ex conjugate() const override
Definition: Basic.cpp:378
class extended to GiNaC symbol class, represent a positive symbol
Definition: BASIC.h:113
class for vector object
Definition: HEP.h:149
Vector * duplicate() const override
Definition: Basic.cpp:246
bool is_equal_same_type(const basic &other) const override
Definition: Basic.cpp:263
Pair operator()(const Vector &p)
Definition: Basic.cpp:273
const char * class_name() const override
Definition: Basic.cpp:250
ex derivative(const symbol &s) const override
Definition: Basic.cpp:294
void print(const print_context &c, unsigned level=0) const
Definition: Basic.cpp:269
static GiNaC::registered_class_info & get_class_info_static()
Definition: Basic.cpp:244
int compare_same_type(const GiNaC::basic &other) const override
Definition: Basic.cpp:254
void read_archive(const archive_node &n) override
Definition: Basic.cpp:286
void accept(GiNaC::visitor &v) const override
Definition: Basic.cpp:247
void archive(archive_node &n) const override
Definition: Basic.cpp:281
const GiNaC::registered_class_info & get_class_info() const override
Definition: Basic.cpp:248
Symbol name
Definition: HEP.h:176
do_not_evalf_params().expl_derivative_func(zd1D).derivative_func(zp1D)) REGISTER_FUNCTION(FTX
HepLib namespace.
Definition: BASIC.cpp:17
const Symbol NA
bool ex_less(const ex &a, const ex &b)
Definition: Sort.cpp:10
ex DoColor(const ex &expr, const ex &pref, int method)
Definition: Basic.cpp:845
void let_op(ex &ex_in, int index1, int index2, const ex item)
update index1-th.index2-th of expression with item
Definition: BASIC.cpp:1560
ex HomCACF(const ex &e)
Definition: Basic.cpp:803
ex MatrixContract(const ex &expr_in)
make contract on matrix, i.e., Matrix(a,i1,i2)*Matrix(b,i2,i3) -> Matrix(a*b,i1,i3)
Definition: Basic.cpp:599
ex w0
Definition: BASIC.h:499
const Symbol NF
ex collect_ex(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica
Definition: BASIC.cpp:1202
ex GAS(const ex &expr, unsigned rl)
function similar to GAD/GSD in FeynClac
Definition: DGamma.cpp:246
REGISTER_FUNCTION(Matrix, do_not_evalf_params().print_func< FCFormat >(&Matrix_fc_print).conjugate_func(mat_conj).set_return_type(return_types::commutative)) bool IsZero(const ex &e)
Definition: Basic.cpp:715
ex w
Definition: Init.cpp:90
const Symbol vs
ex get_op(const ex ex_in, int index1, int index2)
return index1-th.index2-th of expression
Definition: BASIC.cpp:1606
ex ToCACF(const ex &e)
Definition: Basic.cpp:776
const Symbol CA
const Symbol TF
ex exnormal(const ex &expr, int opt)
normalize a expression
Definition: BASIC.cpp:1906
const Symbol CF
const Symbol as
lst collect_lst(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica, reture the lst { {c1,v1}, {c2,v2}, ... }
Definition: BASIC.cpp:1222
ex ToCF(const ex &e)
Definition: Basic.cpp:741
string ex2str(const ex &expr)
convert ex to output string, the defalut printer format will be used
Definition: BASIC.cpp:715
ex exfactor(const ex &expr, int opt)
factorize a expression
Definition: BASIC.cpp:1854
bool IsZero(const ex &e)
const Symbol nL
const Symbol nH
ex w1
Definition: BASIC.h:499
ex w3
Definition: BASIC.h:499
ex w2
Definition: BASIC.h:499
ex form(const ex &iexpr, int verb)
evalulate expr in form program, see also the form_trace_mode and form_expand_mode
Definition: Form.cpp:563
ex ca_neg_pow_sub(const ex &expr)
Definition: Basic.cpp:767