7#include "ginac/parse_context.h"
16 alignas(2)
static ex SP_reader(
const exvector& ev) {
17 if(ev.size()<2)
return SP(ev[0]);
18 else return SP(ev[0], ev[1]);
21 alignas(2)
static ex LC_reader(
const exvector& ev) {
22 if(ev.size()==4)
return (-I)*
LC(ev[0], ev[1], ev[2], ev[3]);
26 alignas(2)
static ex SUNT_reader(
const exvector& ev) {
28 if(n==3)
return SUNT(ev[0], ev[1], ev[2]);
31 for(
int i=0; i<n-2; i++)
as.append(ev[i]);
32 return SUNT(
as,ev[n-2],ev[n-1]);
33 }
else throw Error(
"SUNT_reader: number of arguments less than 3.");
36 alignas(2)
static ex TTR_reader(
const exvector& ev) {
37 if(ev.size()==1)
return TTR(ev[0]);
39 for(
auto item : ev)
as.append(item);
43 alignas(2)
static ex DGamma_reader(
const exvector& ev) {
45 if(n==1)
return GAS(ev[0]);
48 for(
int i=1; i<n; i++) ret = ret *
GAS(ev[i],rl);
52 alignas(2)
static ex gi_reader(
const exvector& ev) {
54 if(n==0)
return GAS(1);
55 else if(n==1)
return GAS(1,
ex2int(ev[0]));
56 else throw Error(
"DGamma_reader: number of arguments more than 2.");
59 alignas(2)
static ex GMat_reader(
const exvector& ev) {
60 return GMat(ev[0],ev[1],ev[2]);
69 struct mapGamma :
public map_function {
71 ex operator()(
const ex &e) {
72 if(is_a<DGamma>(e))
return DGamma(ex_to<DGamma>(e), gline);
74 else return e.map(*
this);
76 mapGamma(
int _gline) : gline(_gline) { };
81 struct mapTR :
public map_function {
83 ex operator()(
const ex &e) {
87 trs = mapGamma(gline)(trs);
88 trs = DGamma(1, gline) * trs;
91 if(glmax>128)
throw Error(
"too large index with glmax>128.");
94 }
else if(is_a<add>(e)) {
97 unsigned glmax = gline;
100 res += (*this)(item);
101 if(glmax<gline)
glmax = gline;
105 }
else if(is_a<power>(e)) {
108 if(!ee.has(TR(
w)))
return e;
109 if(!nn.info(info_flags::posint))
return e;
111 int pn = ex_to<numeric>(nn).to_int();
112 for(
int i=0; i<
pn; i++) {
116 }
else return e.map(*
this);
123 string init_script = R
"EOF(
124CFunction pow,sqrt,gamma,HF,GMat,WF;
125Tensor TTR(cyclic), f(antisymmetric), T, f4, colTp;
126Symbols reX,I2R,NF,NA,d;
127AutoDeclare Symbols gCF, trcN;
129AutoDeclare Index colA;
131AutoDeclare Index colF;
137 id,once,TTR(?a) = T(?a,colF1,colF1);
140 id,once,T(colA1?,colA2?,?a,colF1?,colF2?) = T(colA1,colF1,colF3)*T(colA2,?a,colF3,colF2);
142 id,once,f4(colA1?,colA2?,colA3?,colA4?) = f(colA1,colA2,colA5) * f(colA5,colA3,colA4);
148 if ( count(f,1) || match(T(colA1?,colF1?,colF2?)*T(colA1?,colF3?,colF4?)) ) redefine colXi "0";
149 id,once,f(colA1?,colA2?,colA3?) = 1/I2R/i_*T(colA1,colF1,colF2)*T(colA2,colF2,colF3)*T(colA3,colF3,colF1)-1/I2R/i_*T(colA3,colF1,colF2)*T(colA2,colF2,colF3)*T(colA1,colF3,colF1);
150 sum colF1,colF2,colF3;
151 id T(colA1?,colF1?,colF2?)*T(colA1?,colF3?,colF4?) = colTp(colF1,colF2,colF3,colF4);
153 if ( count(colTp,1) ) redefine colXj "0";
155 id,once,colTp(colF1?,colF2?,colF3?,colF4?) = I2R*(d_(colF1,colF4)*d_(colF2,colF3)-d_(colF1,colF2)*d_(colF3,colF4)/NF);
160 id T(colA1?,?a,colF1?,colF2?)*T(colA2?,?b,colF2?,colF3?) = T(colA1,?a,colA2,?b,colF1,colF3);
162id T(?a,colF1?,colF1?) = TTR(?a);
164id TTR(colA1?,colA2?) = I2R*d_(colA1,colA2);
180 ex runform(
const ex &expr_in,
int verb) {
181 static map<pid_t, Form> form_map;
183 if((form_map.find(pid)==form_map.end())) {
185 ss << init_script << endl;
186 form_map[pid].Init(
"form");
187 form_map[pid].Execute(ss.str());
189 Form &fprc = form_map[pid];
191 ex expr = expr_in.subs(
SP_map);
196 ids <<
"id " << kv.first <<
"=" << kv.second <<
";" << endl;
197 all_expr += iWF(kv.first) * iWF(kv.second);
199 string idstr = sss.str();
201 lst vec_lst, VD_lst, CF_lst, CA_lst, sym_lst;
202 for(const_preorder_iterator i = all_expr.preorder_begin(); i != all_expr.preorder_end(); ++i) {
203 if(is_a<Vector>(*i)) vec_lst.append(*i);
204 else if(is_a<Index>(*i)) {
205 if(ex_to<Index>(*i).dim==
d) VD_lst.append(*i);
206 else if(ex_to<Index>(*i).dim==
NF) CF_lst.append(*i);
207 else if(ex_to<Index>(*i).dim==
NA) CA_lst.append(*i);
208 }
else if(is_a<symbol>(*i)) sym_lst.append(*i);
209 else if(is_a<GiNaC::function>(*i)) {
210 static vector<string> fun_vec = {
211 "iWF",
"WF",
"TR",
"sin",
"cos",
"HF",
"TTR",
"GMat"
213 auto func = ex_to<GiNaC::function>(*i).get_name();
215 for(
auto fi : fun_vec) {
216 if(fi==func) { ok =
true;
break; }
219 cout << (*i) << endl;
220 throw Error(
"runform: Functions not defined in FORM: "+func);
224 vec_lst.sort(); vec_lst.unique();
225 VD_lst.sort(); VD_lst.unique();
226 CF_lst.sort(); CF_lst.unique();
227 CA_lst.sort(); CA_lst.unique();
229 sym_lst.sort(); sym_lst.unique();
233 ff <<
".store" << endl;
235 if(sym_lst.nops()>0) {
237 for(
auto sx : sym_lst) {
238 auto s = ex_to<symbol>(sx);
239 ff <<
" " << s.get_name();
240 st[s.get_name()] = sx;
244 if(vec_lst.nops()>0) {
246 for(
auto vx : vec_lst) {
247 auto v = ex_to<Vector>(vx);
249 st[v.name.get_name()] = v;
250 for(
auto vvx : vec_lst) {
251 auto vv = ex_to<Vector>(vvx);
252 st[v.name.get_name()+
"__"+vv.name.get_name()] =
SP(v,vv);
257 if(VD_lst.nops()>0) {
259 else ff <<
"Dimension d;" << endl;
261 for(
auto ix : VD_lst) {
262 auto i = ex_to<Index>(ix);
264 st[i.name.get_name()] = i;
270 if(CF_lst.nops()>0) {
271 ff <<
"Dimension NF;" << endl;
273 for(
auto ix : CF_lst) {
274 auto i = ex_to<Index>(ix);
276 st[i.name.get_name()] = i;
282 if(CA_lst.nops()>0) {
283 ff <<
"Dimension NA;" << endl;
285 for(
auto ix : CA_lst) {
286 auto i = ex_to<Index>(ix);
288 st[i.name.get_name()] = i;
294 ff <<
".global" << endl;
298 bool islst = is_a<lst>(expr);
300 if(islst) expr_lst = ex_to<lst>(expr);
301 else expr_lst.append(expr);
302 auto total = expr_lst.nops();
309 map<ex,int,ex_is_less> e2i_map;
310 for(
auto it : expr_lst) {
311 ff <<
".store" << endl;
313 item = MapFunction([](
const ex & e, MapFunction &self)->ex{
314 if(!e.has(TR(
w)))
return e;
315 else if(e.match(TR(
w))) {
316 ex nd = e.op(0).normal().numer_denom();
317 return TR(nd.op(0))/nd.op(1);
318 }
else return e.map(self);
322 item = collect_common_factors(item);
324 auto ckey = item.op(0);
325 if(!is_a<numeric>(ckey)) {
327 if(e2i_map.find(ckey)==e2i_map.end()) {
331 }
else ckid = e2i_map[ckey];
332 string gCF =
"gCF" + to_string(ckid);
333 st[gCF] = item.op(0);
334 item = Symbol(gCF) * item.op(1);
336 item = ckey * item.op(1);
343 for(
int i=0; i<cv_lst.nops(); i++) {
344 auto it = cv_lst.op(i);
347 color_vec.push_back(vv);
348 item += cc * Symbol(
"[cl"+to_string(i)+
"]");
352 for(
int i=0; i<color_vec.size(); i++) {
353 coss <<
" [cl" << i <<
"]";
354 ff <<
"L [cl" << i <<
"]=" << color_vec[i] <<
";" << endl;
355 ff <<
".sort" << endl;
356 ff <<
"#call SUNTrace" << endl;
357 ff <<
".sort" << endl;
359 ff <<
"id NF^reX?=3^reX;" << endl;
360 ff <<
"id I2R=1/2;" << endl;
361 ff <<
"id NA^reX?=8^reX;" << endl;
362 ff <<
".sort" << endl;
370 find(item,TR(
w),trs);
378 ff <<
"L [o]=" << item <<
";" << endl;
379 ff <<
".sort" << endl;
380 ff <<
"#do i = 1,1" << endl;
381 ff <<
"id once HF(reX?)=reX;" << endl;
383 ff <<
"if(count(HF,1)>0) redefine i \"0\";" << endl;
384 ff <<
".sort" << endl;
385 ff <<
"#enddo" << endl;
386 ff <<
"contract 0;" << endl;
387 ff <<
".sort" << endl;
388 ff << idstr <<
".sort" << endl;
390 for(
int gl=1; gl<=tr.glmax; gl++) {
392 ff <<
".sort" << endl;
394 else ff <<
"Dimension d;" << endl;
395 ff <<
"Indices [g5_i1], [g5_i2], [g5_i3], [g5_i4];" << endl;
396 ff <<
"id g_(" << gl <<
",5_) = e_([g5_i1],[g5_i2],[g5_i3],[g5_i4])*g_(" << gl <<
",[g5_i1],[g5_i2],[g5_i3],[g5_i4])/24;" << endl;
397 ff <<
"sum [g5_i1],[g5_i2],[g5_i3],[g5_i4];" << endl;
398 ff <<
".sort" << endl;
401 else ff <<
"tracen " << gl <<
";" << endl;
402 ff <<
".sort" << endl;
403 ff << idstr <<
".sort" << endl;
410 tr2v[tr] = Symbol(
"[tr"+to_string(trn)+
"]");
411 auto tri = mapGamma(gid)(tr.op(0));
412 trvec.push_back(tri);
415 item = item.subs(tr2v);
416 for(
int i=0; i<trvec.size(); i++) {
417 ff <<
"L [tr" << i <<
"]=" << trvec[i] <<
";" << endl;
419 ff <<
".sort" << endl;
421 else ff <<
"Dimension d;" << endl;
422 ff <<
"Indices [g5_i1], [g5_i2], [g5_i3], [g5_i4];" << endl;
423 ff <<
"id g_(" << gid <<
",5_) = e_([g5_i1],[g5_i2],[g5_i3],[g5_i4])*g_(" << gid <<
",[g5_i1],[g5_i2],[g5_i3],[g5_i4])/24;" << endl;
424 ff <<
"sum [g5_i1],[g5_i2],[g5_i3],[g5_i4];" << endl;
427 else ff <<
"tracen " << gid <<
";" << endl;
428 ff <<
".sort" << endl;
429 ff << idstr <<
".sort" << endl;
431 ff <<
"L [o]=" << item <<
";" << endl;
432 ff <<
".sort" << endl;
433 ff <<
"#do i = 1,1" << endl;
434 ff <<
"id once HF(reX?)=reX;" << endl;
436 ff <<
"if(count(HF,1)>0) redefine i \"0\";" << endl;
437 ff <<
".sort" << endl;
438 ff <<
"#enddo" << endl;
439 ff << idstr <<
".sort" << endl;
446 tr2v[tr] = Symbol(
"trcN"+to_string(trn));
447 auto tri = mapGamma(gid)(tr.op(0));
448 trvec.push_back(tri);
451 item = item.subs(tr2v);
453 if(color_vec.size()>0) ff <<
"drop" << coss.str() <<
";" << endl;
454 ff <<
"L [o]=" << item <<
";" << endl;
455 ff <<
".sort" << endl;
456 ff <<
"#do i = 1,1" << endl;
457 ff <<
"id once HF(reX?)=reX;" << endl;
459 ff <<
"if(count(HF,1)>0) redefine i \"0\";" << endl;
460 ff <<
".sort" << endl;
461 ff <<
"#enddo" << endl;
464 for(
int i=0; i<trvec.size(); i++) {
465 ff <<
"L [tr" << i <<
"]=" << trvec[i] <<
";" << endl;
467 ff <<
".sort" << endl;
469 else ff <<
"Dimension d;" << endl;
470 ff <<
"Indices [g5_i1], [g5_i2], [g5_i3], [g5_i4];" << endl;
471 ff <<
"id g_(" << gid <<
",5_) = e_([g5_i1],[g5_i2],[g5_i3],[g5_i4])*g_(" << gid <<
",[g5_i1],[g5_i2],[g5_i3],[g5_i4])/24;" << endl;
472 ff <<
"sum [g5_i1],[g5_i2],[g5_i3],[g5_i4];" << endl;
475 else ff <<
"tracen " << gid <<
";" << endl;
476 ff <<
".sort" << endl;
477 ff << idstr <<
".sort" << endl;
478 ff <<
"drop [tr" << i <<
"];" << endl;
479 ff <<
"id trcN" << i <<
"=[tr" << i <<
"];" << endl;
480 ff <<
".sort" << endl;
481 ff << idstr <<
".sort" << endl;
485 throw Error(
"runform: unsupported form_trace_mode = " + to_string(
form_trace_mode));
488 ff <<
"contract 0;" << endl;
489 ff <<
".sort" << endl;
490 ff << idstr <<
".sort" << endl;
494 cout <<
PRE <<
"\\--Form Script @ " << c <<
" / " << total << flush;
496 cout <<
"--------------------------------------" << endl;
497 cout <<
"Form Script @ " << c <<
" / " << total << endl;
498 cout <<
"--------------------------------------" << endl;
499 cout << ss.str() << endl;
502 auto script = ss.str();
506 auto otmp = fprc.Execute(script);
508 cout <<
"--------------------------------------" << endl;
509 cout <<
"Form Output @ " << c <<
" / " << total << endl;
510 cout <<
"--------------------------------------" << endl;
511 cout << otmp << endl;
518 if(c<total) ostr +=
",";
520 }
catch(Error& err) {
525 if(verb==1) cout << endl;
533 for(
auto v : vec_lst) {
534 string pat(ex_to<Vector>(v).name.get_name());
535 string from = pat+
"(";
536 string to =
"d_("+pat+
",";
562 fp.FTable.insert({{
"SP", 2}, reader_func(SP_reader)});
563 fp.FTable.insert({{
"SP", 1}, reader_func(SP_reader)});
565 for(
int i=3; i<10; i++) fp.FTable.insert({{
"LC", i}, reader_func(LC_reader)});
566 fp.FTable.insert({{
"GMat", 3}, reader_func(GMat_reader)});
567 for(
int i=1; i<30; i++) fp.FTable.insert({{
"T", i}, reader_func(SUNT_reader)});
568 for(
int i=1; i<30; i++) fp.FTable.insert({{
"TTRX", i}, reader_func(TTR_reader)});
569 for(
int i=1; i<30; i++) fp.FTable.insert({{
"DG", i}, reader_func(DGamma_reader)});
570 fp.FTable.insert({{
"GI", 0}, reader_func(gi_reader)});
571 fp.FTable.insert({{
"GI", 1}, reader_func(gi_reader)});
572 ex ret = fp.Read(ostr);
573 if(!islst) ret = ret.op(0);
583 ex
form(
const ex & iexpr,
int verb) {
585 if(!is_a<lst>(expr)) {
586 static MapFunction mf([](
const ex & e, MapFunction & self)->ex{
587 if(!e.has(TR(w)))
return e;
588 else if(e.match(TR(w))) {
589 if(is_a<mul>(e.op(0))) {
591 for(auto const & ei : e.op(0)) {
592 if(DGamma::has(ei)) v *= ei;
597 }
else return e.map(self);
601 if(form_expand_mode==form_expand_none || is_a<lst>(expr))
return runform(expr, verb);
602 else if(form_expand_mode==form_expand_tr) {
603 auto cv_lst =
collect_lst(expr.subs(SP_map), TR(w));
605 for(
auto cv : cv_lst) to_lst.append(cv.op(0)*cv.op(1));
606 lst out_lst = ex_to<lst>(runform(to_lst, verb));
609 for(
int i=0; i<cv_lst.nops(); i++) ret += out_lst.op(i);
611 return ret.subs(SP_map);
612 }
else if(form_expand_mode==form_expand_ci) {
613 auto cv_lst =
collect_lst(expr.subs(SP_map), [](
const ex & e)->bool {
614 return e.has(TR(w)) || Index::hasc(e);
617 for(
auto cv : cv_lst) to_lst.append(cv.op(0)*cv.op(1));
618 lst out_lst = ex_to<lst>(runform(to_lst, verb));
621 for(
int i=0; i<cv_lst.nops(); i++) ret += out_lst.op(i);
623 return ret.subs(SP_map);
624 }
else if(form_expand_mode==form_expand_li) {
625 auto cv_lst =
collect_lst(expr.subs(SP_map), [](
const ex & e)->bool {
626 return e.has(TR(w)) || Index::hasv(e);
629 for(
auto cv : cv_lst) to_lst.append(cv.op(0)*cv.op(1));
630 lst out_lst = ex_to<lst>(runform(to_lst, verb));
633 for(
int i=0; i<cv_lst.nops(); i++) ret += out_lst.op(i);
635 return ret.subs(SP_map);
636 }
else if(form_expand_mode==form_expand_all) {
637 auto cv_lst =
collect_lst(expr.subs(SP_map), [](
const ex & e)->bool {
638 return e.has(TR(w)) || SUNT::has(e) || SUNF::has(e) || SUNF4::has(e) || Index::has(e) || DGamma::has(e);
641 for(
auto cv : cv_lst) to_lst.append(cv.op(1));
642 lst out_lst = ex_to<lst>(runform(to_lst, verb));
645 for(
int i=0; i<cv_lst.nops(); i++) ret += cv_lst.op(i).op(0) * out_lst.op(i);
647 return ret.subs(SP_map);
648 }
else throw Error(
"form: unsupported form_expand_mode = " + to_string(form_expand_mode));
658 if(expr.has(GMat(w1,w2,w3)))
throw Error(
"charge_conjugate: GMat found.");
660 if(!DGamma::has(expr) && !AsGamma::has(expr))
return expr;
661 if(is_a<DGamma>(expr)) {
662 DGamma g = ex_to<DGamma>(expr);
663 if(is_a<Vector>(g.pi) || is_a<Index>(g.pi))
return -expr;
664 else if(is_zero(g.pi-1) || is_zero(g.pi-5))
return expr;
665 }
else if(is_a<AsGamma>(expr)) {
666 AsGamma ag = ex_to<AsGamma>(expr);
669 for(
int i=ag.pis.size()-1; i>=0; --i) {
671 if(is_a<Vector>(pi) || is_a<Index>(pi)) sign *= -1;
672 else if(is_zero(pi-1) || is_zero(pi-5)) sign *= 1;
673 else throw Error(
"charge_conjugate: only p/i/1/5 supported.");
676 return sign * AsGamma::from(pis_lst);
679 if(is_a<add>(expr)) {
683 }
else if(is_a<mul>(expr)) {
687 }
else if(is_a<ncmul>(expr)) {
693 cout << expr << endl;
694 throw Error(
"charge_conjugate: unexpected region.");
704 if(expr.has(GMat(w1,w2,w3)))
throw Error(
"charge_conjugate: GMat found.");
705 if(AsGamma::has(expr))
throw Error(
"gamma_transpose: Not supported for AsGamma.");
707 if(!DGamma::has(expr))
return expr;
708 if(is_a<DGamma>(expr)) {
709 if(expr.is_equal(DGamma::C))
return (-1)*DGamma::C;
710 DGamma g = ex_to<DGamma>(expr);
715 if(is_a<add>(expr)) {
719 }
else if(is_a<mul>(expr)) {
723 }
else if(is_a<ncmul>(expr)) {
729 cout <<
"gamma_transpose input:" << expr << endl;
730 throw Error(
"gamma_transpose: unexpected region.");
static bool has(const ex &e)
static bool has(const ex &e)
static bool hasc(const ex &e)
static GiNaC::exmap Dimension
static bool has(const ex &e)
lst CoPat(const ex &e, std::function< bool(const ex &)> f)
ex GAS(const ex &expr, unsigned rl)
function similar to GAD/GSD in FeynClac
const int form_trace_each_all
ex gamma_transpose(const ex &expr)
make the transpose operaton M --> M^T
ex charge_conjugate(const ex &expr)
make the charge conjugate operaton, M -> C^{-1} . M^T . C w.r.t. a GMat object
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}, ... }
void string_replace_all(string &str, const string &from, const string &to)
const int form_trace_each_each
const int form_trace_auto
ex SP(const ex &a, bool use_map=true)
ex LC(ex pi1, ex pi2, ex pi3, ex pi4)
function similar to LCD in FeynCalc
ex form(const ex &iexpr, int verb)
evalulate expr in form program, see also the form_trace_mode and form_expand_mode
int ex2int(ex num)
ex to integer