10 return n * UINT64_C(0x4f1bbcdd);
33 const symbol & get_symbol(
const string & s) {
34 static map<string, symbol> dict;
36 if (dict.find(key) == dict.end()) dict[key] = symbol(s,0);
40 const Symbol & get_Symbol(
const string & s) {
41 static map<string, Symbol> dict;
43 if (dict.find(key) == dict.end()) dict[key] = Symbol(s);
47 const iSymbol & get_iSymbol(
const string & s) {
48 static map<string, iSymbol> dict;
50 if (dict.find(key) == dict.end()) dict[key] = iSymbol(s);
59 GiNaC::registered_class_info &
Symbol::get_class_info_static() {
return reg_info; }
76 if(!is_a<Symbol>(other))
throw Error(
"Symbol::compare_same_type");;
78 int ret = get_name().compare(o.get_name());
80 else if(ret<0)
return -1;
89 inherited::archive(n);
97 inherited::read_archive(n);
106 static std::hash<std::string> hs;
107 unsigned seed = hs(get_name()+
typeid(*this).name());
109 setflag(status_flags::hash_calculated);
114 if(!is_a<Symbol>(other))
throw Error(
"Symbol::is_equal_same_type");
116 return get_name()==o->get_name();
120 if(!is_exactly_a<Symbol>(s))
return 0;
127 const ex point = r.rhs();
129 if (is_exactly_a<Symbol>(r.lhs()) && this->is_equal_same_type(ex_to<Symbol>(r.lhs()))) {
130 if (order>0 && !point.is_zero()) seq.emplace_back(expair(point, 0));
131 if (order>1) seq.emplace_back(expair(1, 1));
132 else seq.emplace_back(expair(Order(1), numeric(order)));
133 }
else seq.emplace_back(expair(*
this, 0));
134 return pseries(r, std::move(seq));
150 ex v2 = v1.subs(
vmap);
151 if(v2.is_equal(v1))
break;
164 GiNaC::registered_class_info &
iSymbol::get_class_info_static() {
return reg_info; }
180 if(!is_a<iSymbol>(other))
throw Error(
"iSymbol::compare_same_type");
182 int ret = get_name().compare(o.get_name());
184 else if(ret<0)
return -1;
189 if(!is_a<iSymbol>(other))
throw Error(
"iSymbol::is_equal_same_type");
191 return serial==o->serial;
195 if(!is_exactly_a<iSymbol>(s))
return 0;
202 const ex point = r.rhs();
204 if (is_exactly_a<iSymbol>(r.lhs()) && this->is_equal_same_type(ex_to<iSymbol>(r.lhs()))) {
205 if (order>0 && !point.is_zero()) seq.emplace_back(expair(point, 0));
206 if (order>1) seq.emplace_back(expair(1, 1));
207 else seq.emplace_back(expair(Order(1), numeric(order)));
208 }
else seq.emplace_back(expair(*
this, 0));
209 return pseries(r, std::move(seq));
215 hashvalue = get_symbol(get_name()).gethash();
216 setflag(status_flags::hash_calculated);
225 inherited::archive(n);
233 inherited::read_archive(n);
250 static int GiNaC_Parallel_Level = 0;
260 exvector
GiNaC_Parallel(
int ntotal, std::function<ex(
int)> f,
const string & key) {
261 if(ntotal<1)
return exvector();
265 int fork_retried = 0;
280 for(
int i=0; i<ntotal; i++) ovec.push_back(f(i));
281 return exvector(std::move(ovec));
284 int para_max_run = nproc<0 ? omp_get_num_procs() : nproc;
285 if(para_max_run<0) para_max_run = 0;
286 if(para_max_run>omp_get_num_procs()) para_max_run = omp_get_num_procs();
289 auto ppid = getpid();
291 string gp_host =
get_env(
"GiNaC_Parallel_Host");
292 if(gp_host.length()>0) gp_host +=
"_";
293 cmd <<
"mkdir -p " << gp_host << ppid;
294 if(!
dir_exists(gp_host+to_string(ppid))) rc = system(cmd.str().c_str());
298 if(nbatch<=0) nbatch = ntotal/para_max_run/5;
299 else if(nbatch > ntotal/para_max_run) nbatch = ntotal/para_max_run;
300 if(nbatch<1) nbatch = 1;
301 int btotal = ntotal/nbatch + ((ntotal%nbatch)==0 ? 0 : 1);
303 bool nst = (GiNaC_Parallel_Level>0);
305 if(getpgid(0)!=ppid) {
308 if(npid < 0)
throw Error(
"GiNaC_Parallel: Error (1) @ fork()");
309 if(npid!=0)
goto wait_label;
312 if(setpgid(0,0))
throw Error(
"GiNaC_Parallel: setpgid(0,0) Failed.");
317 while(fork_retried<5) {
321 for(
int bi=0; bi<btotal; bi++) {
323 for(
int i=0; i<btotal; i++)
if(waitpid(-pgid,NULL,WNOHANG)>0) nactive--;
324 if(verb > 1 && !nst) {
325 cout <<
"\r \r" << pre;
326 cout <<
"\\--Evaluating ";
328 cout <<
Color_HighLight << nbatch <<
"x" <<
RESET <<
"[" << (bi+1) <<
"/" << btotal <<
"] @ " <<
now(
false) << exstr << flush;
333 if(key ==
"") garfn << gp_host << ppid <<
"/" << bi <<
".gar";
334 else garfn << gp_host << ppid <<
"/" << bi <<
"." << key <<
".gar";
340 if(getpid()!=pgid) exit(0);
342 if(ec>3*btotal)
throw Error(
"GiNaC_Parallel: Error (2) @ fork()");
343 exstr =
" [fork(" + to_string(ec) +
")]";
344 if(waitpid(-pgid,NULL,0)>0) nactive--;
347 if(pid==0 && setpgid(0, pgid)!=0) {
348 if(setpgid(0, pgid))
throw Error(
"GiNaC_Parallel: setpgid(0, pgid) Failed.");
352 if(nactive >= para_max_run)
if(waitpid(-pgid,NULL,0)>0) nactive--;
358 GiNaC_Parallel_Level++;
361 for(
int ri=0; ri<nbatch; ri++) {
362 int i = bi*nbatch + ri;
363 if(i<ntotal) res_lst.append(f(i));
367 if(key ==
"") garfn << gp_host << ppid <<
"/" << bi <<
".gar";
368 else garfn << gp_host << ppid <<
"/" << bi <<
"." << key <<
".gar";
370 }
catch(exception &p) {
371 cout <<
ErrColor <<
"Failed in GiNaC_Parallel!" <<
RESET << endl;
377 if(getpid()!=pgid) exit(0);
378 while (waitpid(-pgid,NULL,0) != -1) { }
379 if(!nst && verb > 1) cout << endl;
380 if(getpid()!=ppid) exit(0);
384 bool all_gar_exists =
true;
385 for(
int bi=0; bi<btotal; bi++) {
387 if(key ==
"") garfn << gp_host << ppid <<
"/" << bi <<
".gar";
388 else garfn << gp_host << ppid <<
"/" << bi <<
"." << key <<
".gar";
390 all_gar_exists =
false;
394 if(all_gar_exists)
break;
395 para_max_run = para_max_run/2;
396 if(para_max_run<2)
break;
401 if(npid!=0) waitpid(npid,NULL,0);
410 for(
int bi=0; bi<btotal; bi++) {
411 if(verb > 1 && !nst) {
413 cout <<
"\r \r" << pre;
414 cout <<
"\\--Reading *.gar [" << (bi+1) <<
"/" << btotal <<
"] @ " <<
now(
false) << flush;
416 cout <<
"\r \r" << pre;
417 cout <<
"\\--Reading *." <<
Color_HighLight << key <<
RESET <<
".gar [" << (bi+1) <<
"/" << btotal <<
"] @ " <<
now(
false) << flush;
422 if(key ==
"") garfn << gp_host << ppid <<
"/" << bi <<
".gar";
423 else garfn << gp_host << ppid <<
"/" << bi <<
"." << key <<
".gar";
427 res_lst = ex_to<lst>(
garRead(garfn.str()));
428 remove(garfn.str().c_str());
431 }
catch(exception &p) { }
432 if(verb > 1 && !nst) cout <<
" - ReTry" << endl;
434 res_lst.remove_all();
435 for(
int ri=0; ri<nbatch; ri++) {
436 int i = bi*nbatch + ri;
437 if(i<ntotal) res_lst.append(f(i));
440 }
catch(exception &p) {
441 cout <<
ErrColor <<
"Failed in GiNaC_Parallel!" <<
RESET << endl;
443 throw Error(
"GiNaC_Parallel_ReTRY: "+
string(p.what()));
448 for(
auto res : res_lst) ovec_tmp.push_back(res);
450 for(
auto res : res_lst) ovec.push_back(res);
453 for(
auto res : res_lst) ovec.push_back(res);
461 cout <<
"\r \r" << pre;
462 cout <<
"\\--ReWR" << flush;
464 cout <<
"\r \r" << pre;
471 if(key ==
"") garfn << gp_host << ppid <<
"/ReWR.gar";
472 else garfn << gp_host << ppid <<
"/ReWR." << key <<
".gar";
479 if(!nst && verb>1) cout << endl;
485 cmd <<
"rm -fr " << gp_host << ppid;
486 rc = system(cmd.str().c_str());
488 if(ovec.size() != ntotal) {
489 throw Error(
"GiNaC_Parallel: The output size is wrong!");
492 return exvector(std::move(ovec));
501 std::vector<std::string>
split(
const std::string& s,
char delimiter) {
502 std::vector<std::string> tokens;
504 std::istringstream tokenStream(s);
505 while (std::getline(tokenStream, token, delimiter)) {
506 tokens.push_back(token);
518 for(
int i=0;
i<
m.nops();
i++)
ret +=
m.op(
i);
527 string now(
bool use_date) {
531 if(use_date) strftime(tmp,
sizeof(tmp),
"%Y-%m-%d %H:%M:%S",localtime(&timep) );
532 else strftime(tmp,
sizeof(tmp),
"%H:%M:%S",localtime(&timep) );
543 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) {
544 if(is_a<symbol>(*i)) ss.insert(*i);
547 for(
auto item : ss) sym_lst.append(item);
559 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) {
560 if(is_a<symbol>(*i)) ss.insert(*i);
564 for(
auto item : ss) sym_lst.append(item);
577 if( (fp = popen(cmd.c_str(),
"r")) != NULL) {
578 while(fgets(buf, 128, fp) != NULL) {
593 void garRead(
const string &garfn, map<string, ex> &resMap) {
598 for(
int i=0; i<ar.num_expressions(); i++) {
600 ex res = ar.unarchive_ex(name, i);
611 ex
garRead(
const string &garfn,
const char* key) {
616 auto res = ar.unarchive_ex(key);
630 auto c = ar.unarchive_ex(
"c");
631 auto res = ar.unarchive_ex(
"res");
632 if(c!=19790923)
throw Error(
"garRead: check faild for file: " + garfn);
641 void garWrite(
const string &garfn,
const map<string, ex> &resMap) {
643 for(
const auto & item : resMap) {
644 ar.archive_ex(item.second, item.first.c_str());
656 void garWrite(
const string &garfn,
const ex & res) {
658 ar.archive_ex(res,
"res");
659 ar.archive_ex(19790923,
"c");
672 ex
str2ex(
const string &expr, symtab stab) {
674 ex ret = par.
Read(expr);
685 ex ret = par.
Read(expr);
695 lst
str2lst(
const string &expr, symtab stab) {
697 ex ret = par.
Read(expr);
698 return ex_to<lst>(ret);
708 ex ret = par.
Read(expr);
709 return ex_to<lst>(ret);
741 int nc = ls.op(0).nops();
743 for(
int r=0; r<nr; r++) {
745 for(
int c=0; c<nc; c++) mat(r,c) = row.op(c);
778 ifstream ifs(filename);
779 string ostr((istreambuf_iterator<char>(ifs)), (istreambuf_iterator<char>()));
789 void str2file(
const string & ostr,
string filename) {
791 ofs.open(filename, ios::out);
792 ofs << ostr << flush;
799 int n = nstr.length();
801 strcpy(nbuff, nstr.c_str());
802 FILE * f = fmemopen(nbuff, n,
"r");
812 ifstream fs(filename);
815 while (std::getline(fs, line)) {
816 if(!skip_empty || line.size()>0) ovec.push_back(line);
847 void ex2file(
const ex & expr,
string filename) {
849 ofs.open(filename, ios::out);
860 void ex2file(
string filename,
const ex & expr) {
871 quadmath_snprintf(buffer,
sizeof buffer,
"%.36QG", num);
884 nss << num.evalf() << endl;
885 __float128 ret = strtoflt128(nss.str().c_str(), NULL);
896 return ex_to<numeric>(num).to_int();
905 return GiNaC::lst(ev.begin(), ev.end());
914 exvector ret(alst.begin(), alst.end());
915 return exvector(std::move(ret));
924 if(!is_a<add>(expr))
return lst{expr};
926 for(
auto item : expr) ret.append(item);
936 if(!is_a<mul>(expr))
return lst{expr};
938 for(
auto item : expr) ret.append(item);
950 for(
int i=bi; i<=ei; i++) ret.append(x(i));
970 ex
series_ex(ex
const & expr_in, ex
const &s0,
int sn0) {
972 return series_ex(expr_in.subs(s0==ss),ss,sn0).subs(ss==s0);
982 ex
series_ex(ex
const & expr_in, symbol
const &s0,
int sn0) {
984 if(!expr.has(s0))
return (sn0>=0 ? expr : 0);
987 expr.find(pow(s0,
w), sset);
989 exmap repl1st, repl2nd;
990 for(
auto pi : sset) {
991 auto sn = expand(pi.op(1));
992 if(!is_a<numeric>(sn)) {
995 if(!is_a<numeric>(item)) ex1 += item;
1000 repl1st[pi] = sss * pow(s0, sn);
1001 repl2nd[sss] = pow(s0, ex1);
1003 if(!(is_a<numeric>(sn) && ex_to<numeric>(sn).is_rational())) {
1004 cerr <<
"s = " << s0 << endl;
1005 cerr <<
"expr_in = " << expr_in << endl;
1006 throw Error(
"series_ex: Not rational sn = " +
ex2str(sn));
1008 sn_lcm = lcm(sn_lcm, ex_to<numeric>(sn).denom());
1010 if(expr.has(sqrt(s0))) sn_lcm = lcm(sn_lcm, numeric(2));
1011 expr = expr.subs(repl1st);
1014 if(!sn_lcm.is_integer())
throw Error(
"series_ex: Not integer with " +
ex2str(sn_lcm));
1015 if(sn_lcm<0) sn_lcm = numeric(0)-sn_lcm;
1016 int sn = sn0 * sn_lcm.to_int();
1017 expr = expr.subs(pow(s0,
w)==pow(s,
w*sn_lcm)).subs(sqrt(s0)==pow(s,sn_lcm/2)).subs(s0==pow(s,sn_lcm));
1021 for(
auto cv : cvs) {
1025 expr = cv.op(1) + pow(s,sn+exN+2)+pow(s,sn+exN+3);
1026 expr = expr.series(s,sn+exN);
1028 for(
int i=0; i<expr.nops(); i++) {
1029 if(is_order_function(expr.op(i))) {
1034 if(!is_order_function(ot)) {
1035 cerr <<
"expr = " << expr << endl;
1036 throw Error(
"series_ex: Not an Order term with " +
ex2str(ot));
1038 if(ot.op(0).degree(s)>sn) {
1039 expr = series_to_poly(expr);
1041 for(
int i=expr.ldegree(s); (i<=expr.degree(s) && i<=sn); i++) {
1042 ret += cv.op(0) * expr.coeff(s,i) * pow(s0,ex(i)/sn_lcm);
1049 if(!ok)
throw Error(
"series_ex seems not working!");
1051 ret = ret.subs(s==pow(s0,ex(1)/sn_lcm));
1052 ret = ret.subs(repl2nd);
1065 ex
diff_ex(ex
const expr, ex
const xp,
unsigned nth,
bool expand) {
1067 ex res = expr.subs(xp==s);
1068 if(!expand)
return res.diff(s,nth).subs(s==xp);
1071 for(
auto cv : cvs) {
1072 res += cv.op(0) * cv.op(1).diff(s,nth).subs(s==xp);
1080 if(n==1)
return co_epv;
1082 ex co = pow(co_epv.first,2);
1085 auto epv = co_epv.second;
1086 if(epv.size()>10000) cout <<
"Warning: power_expand_2: epv.size > 10000" << endl;
1087 for(
int i=0; i<epv.size(); i++) {
1088 pcmap[epv[i].first] += 2*co_epv.first*epv[i].second;
1089 pcmap[pow(epv[i].first,2)] += pow(epv[i].second,2);
1090 for(
int j=i+1; j<epv.size(); j++) pcmap[epv[i].first*epv[j].first] += 2*epv[i].second*epv[j].second;
1094 epv.reserve(pcmap.size());
1095 for(
auto kv : pcmap) {
1096 if(is_zero(kv.first) || is_zero(kv.second))
continue;
1097 epv.push_back(make_pair(kv.first, kv.second));
1099 return make_pair(co,
epvec_t(std::move(epv)));
1104 if((n % 2)==0)
return co_epvec_t(std::move(co_epv2));
1106 ex co = co_epv.first * co_epv2.first;
1108 for(
auto ep1 : co_epv.second) {
1109 pcmap[ep1.first] += ep1.second * co_epv2.first;
1110 for(
auto ep2 : co_epv2.second) pcmap[ep2.first * ep1.first] += ep1.second * ep2.second;
1112 for(
auto ep2 : co_epv2.second) pcmap[ep2.first] += ep2.second * co_epv.first;
1115 epv.reserve(pcmap.size());
1116 for(
auto kv : pcmap) {
1117 if(is_zero(kv.first) || is_zero(kv.second))
continue;
1118 epv.push_back(make_pair(kv.first, kv.second));
1120 return make_pair(co,
epvec_t(std::move(epv)));
1124 if(!has_func(expr_in)) {
1128 return make_pair(co,epv);
1129 }
if(is_a<add>(expr_in)) {
1132 for(
auto item : expr_in) {
1133 if(has_func(item)) {
1136 for(
auto ep : co_epv.second) pcmap[
ep.first] +=
ep.second;
1140 epv.reserve(pcmap.size());
1141 for(
auto kv : pcmap) {
1142 if(is_zero(kv.first) || is_zero(kv.second))
continue;
1143 epv.push_back(make_pair(kv.first, kv.second));
1145 return make_pair(co,
epvec_t(std::move(epv)));
1146 }
else if(is_a<mul>(expr_in)) {
1149 for(
auto item : expr_in) {
1150 if(!has_func(item)) {
1151 for(
auto &
ep : epv)
ep.second *= item;
1156 for(
auto ep2 : co_epv.second) {
1157 pcmap[ep2.first] += ep2.second * co;
1158 for(
auto ep1 : epv) pcmap[ep1.first * ep2.first] += ep1.second * ep2.second;
1160 for(
auto ep1 : epv) pcmap[ep1.first] += ep1.second * co_epv.first;
1163 epv.reserve(pcmap.size());
1164 for(
auto kv : pcmap) {
1165 if(is_zero(kv.first) || is_zero(kv.second))
continue;
1166 epv.push_back(make_pair(kv.first, kv.second));
1170 return make_pair(co,
epvec_t(std::move(epv)));
1171 }
else if(is_a<power>(expr_in) && expr_in.op(1).info(info_flags::nonnegint)) {
1172 int n = ex_to<numeric>(expr_in.op(1)).to_int();
1178 epv.push_back(make_pair(expr_in, 1));
1179 return make_pair(co,
epvec_t(std::move(epv)));
1181 throw Error(
"inner_expand_collect unexpected region reached.");
1190 ex
expand_ex(ex
const &expr_in, std::function<
bool(
const ex &)> has_func) {
1192 ex ret = co_epv.first;
1193 for(
auto ep : co_epv.second) ret +=
ep.second *
ep.first;
1204 ex
collect_ex(ex
const &expr_in, std::function<
bool(
const ex &)> has_func,
int opt) {
1207 res_vec.reserve(cvs.nops());
1208 for(
auto cv : cvs) {
1211 if(cc.is_zero() || vv.is_zero())
continue;
1212 res_vec.push_back(cc * vv);
1214 return add(res_vec);
1224 lst
collect_lst(ex
const &expr_in, std::function<
bool(
const ex &)> has_func,
int opt) {
1226 ex cf = co_epv.first;
1228 if(!is_zero(cf)) co_epv.second.push_back(make_pair(1,cf));
1229 for(
auto ep : co_epv.second) {
1237 if(!is_zero(cc)) res_lst.append(lst{cc, vv});
1250 expr.find(zeta(
w), zs);
1251 expr.find(zeta(
w,
w), zs);
1254 for(
auto zi : zs) repl.append(zi==
NN(zi));
1255 return expr.subs(repl);
1259 static symbol sPi(
"dPi"), sEuler(
"dEuler"), siEpsilon(
"diEpsilon");
1260 lst repl = lst{Pi==sPi, Euler==sEuler,
iEpsilon==siEpsilon};
1261 return EvalF(expr.subs(repl));
1264 static symbol sPi(
"qPi"), sEuler(
"qEuler"), siEpsilon(
"qiEpsilon");
1265 lst repl = lst{Pi==sPi, Euler==sEuler,
iEpsilon==siEpsilon};
1266 return EvalF(expr.subs(repl));
1269 static symbol sPi(
"mpPi"), sEuler(
"mpEuler"), siEpsilon(
"mpiEpsilon");
1270 lst repl = lst{Pi==sPi, Euler==sEuler,
iEpsilon==siEpsilon};
1271 return EvalF(expr.subs(repl));
1280 ex
NN(ex expr,
int digits) {
1282 auto nexpr = evalf(expr);
1293 auto tmp = expand(expr);
1294 if(tmp.is_zero())
return false;
1296 if(is_a<add>(tmp)) {
1297 for(
auto item : tmp) {
1298 auto nit =
NN(item.subs(x(
w)==1).normal());
1299 if(!is_a<numeric>(nit) || nit<0)
return false;
1303 auto ntmp =
NN(tmp.subs(x(
w)==1).normal());
1304 ret = (is_a<numeric>(ntmp) && ntmp>0);
1315 if(is_zero(expr))
return 0;
1317 else if(
xPositive(ex(0)-expr))
return -1;
1327 auto tmp = ex_to<lst>(ex_in);
1338 auto tmp = ex_to<lst>(ex_in);
1348 auto tmp = ex_to<lst>(ex_in);
1358 auto tmp = ex_to<lst>(ex_in);
1370 auto tmp = ex_to<lst>(ex_in.op(index));
1382 auto tmp = ex_to<lst>(ex_in.op(index));
1395 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1397 ex_in[index1][index2] = tmp;
1408 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1410 ex_in[index1][index2] = tmp;
1420 auto tmp = ex_to<lst>(ex_in.op(index));
1432 auto tmp = ex_to<lst>(ex_in.op(index));
1445 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1447 ex_in[index1][index2] = tmp;
1458 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1460 ex_in[index1][index2] = tmp;
1469 auto tmp = ex_to<lst>(ex_in.op(index));
1480 auto tmp = ex_to<lst>(ex_in.op(index));
1492 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1494 ex_in[index1][index2] = tmp;
1504 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1506 ex_in[index1][index2] = tmp;
1515 auto tmp = ex_to<lst>(ex_in.op(index));
1526 auto tmp = ex_to<lst>(ex_in.op(index));
1538 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1540 ex_in[index1][index2] = tmp;
1550 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1552 ex_in[index1][index2] = tmp;
1562 void let_op(ex &ex_in,
int index1,
int index2,
const ex item) {
1563 ex_in[index1][index2] = item;
1573 void let_op(lst &ex_in,
int index1,
int index2,
const ex item) {
1574 ex_in[index1][index2] = item;
1585 void let_op(ex &ex_in,
int index1,
int index2,
int index3,
const ex item) {
1586 ex_in[index1][index2][index3] = item;
1597 void let_op(lst &ex_in,
int index1,
int index2,
int index3,
const ex item) {
1598 ex_in[index1][index2][index3] = item;
1608 ex
get_op(
const ex ex_in,
int index1,
int index2) {
1609 return ex_in.op(index1).op(index2);
1619 ex
get_op(
const lst ex_in,
int index1,
int index2) {
1620 return ex_in.op(index1).op(index2);
1631 ex
get_op(
const ex ex_in,
int index1,
int index2,
int index3) {
1632 return ex_in.op(index1).op(index2).op(index3);
1643 ex
get_op(
const lst ex_in,
int index1,
int index2,
int index3) {
1644 return ex_in.op(index1).op(index2).op(index3);
1665 if(!is_a<XIntegral>(other))
throw Error(
"XIntegral::compare_same_type");
1686 else if(i==2)
return Deltas;
1687 else throw Error(
"XIntegral::op, It is required that i<3.");
1690 ensure_if_modifiable();
1693 else if(i==2)
return Deltas;
1694 else throw Error(
"XIntegral::let_op, It is required that i<3.");
1698 inherited::archive(n);
1701 n.add_ex(
"Deltas",
Deltas);
1705 inherited::read_archive(n);
1708 n.find_ex(
"Deltas",
Deltas);
1714 if(fed.nops()>2)
Deltas = fed.op(2);
1724 for(
int i=0; i<ps.nops(); i++) {
1725 if(is_zero(ns.op(i)))
continue;
1728 for(
auto li : loops) {
1741 }
else if(is_a<numeric>(ns.op(i)) && (ns.op(i)<0)) {
1742 throw Error(
"XIntegral, negative powers not supported yet.");
1746 for(
auto li : loops) {
1747 if(!is_a<numeric>(cpi.coeff(li,2)))
continue;
1748 numeric nm = ex_to<numeric>(cpi.coeff(li,2));
1749 if(nm.is_zero())
continue;
1750 sgn = nm>0 ? -1 : 1;
1755 if(!is_a<numeric>(cpi.coeff(
iEpsilon)))
continue;
1756 numeric nm = ex_to<numeric>(cpi.coeff(
iEpsilon));
1757 if(!nm.is_zero()) sgn = nm>0 ? -1 : 1;
1762 if(is_a<numeric>(cpi) && ex_to<numeric>(cpi)>0) sgn = -1;
1767 if(sgn==-1) pre *= exp(I * Pi * ns.op(i));
1772 if(!is_zero(ns.op(i)-1)) {
1774 exps.append(ns.op(i)-1);
1776 pre /= tgamma(ns.op(i));
1780 ex dl2 = loops.nops()*(4-2*
ep)/2;
1781 pre *= tgamma(
a-dl2) * pow(I,loops.nops()) * pow(Pi,dl2) * pow(2*Pi,loops.nops()*(2*
ep-4));
1785 for(
int i=0; i<loops.nops(); i++) {
1786 ex t2 = rem.coeff(loops.op(i),2);
1787 ex t1 = rem.coeff(loops.op(i),1);
1788 ex t0 = rem.coeff(loops.op(i),0);
1795 rem = (t0 - pow(t1,2)/(4*t2)).expand();
1799 rem = (rem * u).normal();
1802 exps.prepend(dl2-
a);
1804 exps.prepend(
a-dl2-(4-2*
ep)/2);
1805 auto num_den = numer_denom(pre);
1806 funs.append(num_den.op(0));
1808 if(!is_zero(num_den.op(1))) {
1809 funs.append(num_den.op(1));
1823 return omp_get_num_procs();
1835 return nd.op(0)/nd.op(1);
1845 return collect_common_factors(expr);
1860 for(
int i=0; i<
syms.nops(); i++) {
1861 Symbol si(
"xfaci"+to_string(i));
1862 subs1[
syms.op(i)] = si;
1863 subs2[si] =
syms.op(i);
1865 ex expr = expr_in.
subs(subs1);
1870 return expr.subs(subs2);
1880 if(opt==1)
return expand(expr);
1881 else return expand(expr);
1885 exvector ev_fermat_pern(
const exvector & ev,
int np) {
1886 if(ev.size()<np)
return ev;
1892 for(
int i=0; i<np; i++) {
1900 return exvector(std::move(evs));
1903 ex normal_fermat_pern(
const ex & e,
int np) {
1905 exvector evs(e.begin(), e.end());
1906 while(evs.size()>np) evs = ev_fermat_pern(evs,np);
1919 if(opt<0)
return normal_fermat_pern(expr,-opt);
1920 else if(opt==
o_normal)
return normal(expr);
1934 ex
exnd(
const ex & expr,
int opt) {
1937 else return numer_denom(expr);
1941 static map<pid_t, Form> form_map;
1942 auto pid = getpid();
1943 if((form_map.find(pid)==form_map.end())) {
1945 ss <<
"AutoDeclare Symbols fv;" << endl;
1946 form_map[pid].Init(
"form");
1947 form_map[pid].Execute(ss.str());
1949 Form &fprc = form_map[pid];
1951 auto expr_in = expr;
1953 expr_in = expr_in.to_polynomial(map_rat);
1956 for(const_preorder_iterator i = expr_in.preorder_begin(); i != expr_in.preorder_end(); ++i) {
1958 if(is_a<symbol>(e))
vs.insert(e);
1966 string cvv =
"fv"+to_string(cid);
1968 st[cvv] = ss.subs(map_rat);
1971 expr_in = expr_in.subs(s2v);
1972 oss <<
"Local ff = " << expr_in <<
";" << endl;
1973 oss <<
".sort" << endl;
1975 auto ostr = fprc.
Execute(oss.str(),
"ff");
1977 ex ret = fp.
Read(ostr);
1979 }
catch(
Error& err) {
1980 cout << oss.str() << endl;
1981 form_map.erase(pid);
1987 if(is_a<mul>(expr)) {
1992 static map<pid_t, Form> form_map;
1993 auto pid = getpid();
1994 if((form_map.find(pid)==form_map.end())) {
1996 ss <<
"AutoDeclare Symbols fv;" << endl;
1997 form_map[pid].Init(
"form");
1998 form_map[pid].Execute(ss.str());
2000 Form &fprc = form_map[pid];
2002 auto expr_in = expr;
2004 expr_in = expr_in.to_polynomial(map_rat);
2007 for(const_preorder_iterator i = expr_in.preorder_begin(); i != expr_in.preorder_end(); ++i) {
2009 if(is_a<symbol>(e))
vs.insert(e);
2017 string cvv =
"fv"+to_string(cid);
2019 st[cvv] = ss.subs(map_rat);
2022 expr_in = expr_in.subs(s2v);
2023 oss <<
"Local ff = " << expr_in <<
";" << endl;
2024 oss <<
"Factorize ff;" << endl;
2025 oss <<
".sort" << endl;
2027 auto ostr = fprc.
Execute(oss.str(),
"ff");
2033 ex ret = fp.
Read(ostr);
2036 for(
auto item :
add2lst(ret)) res *= item.subs(sfac==1);
2038 }
catch(
Error& err) {
2039 cout << oss.str() << endl;
2040 form_map.erase(pid);
2062 GINAC_IMPLEMENT_PRINT_CONTEXT(MMAFormat, print_dflt)
2083 int nr = mat.rows();
2084 int nc = mat.cols();
2085 for(
int r=0; r<nr; r++) {
2087 for(
int c=0; c<nc; c++) {
2088 mat(r,c).print(*
this);
2089 if(c+1!=nc) s <<
",";
2092 if(r+1!=nr) s <<
",";
2100 auto vend = e.end();
2101 if (i==vend) { s <<
"{}";
return *
this; }
2115 auto send = e.end();
2116 if (i==send) { s <<
"{}";
return *
this; }
2130 auto mend = e.end();
2131 if (i==mend) { s <<
"{}";
return *
this; }
2134 i->first.print(*
this);
2136 i->second.print(*
this);
2147 ar.archive_ex(exv.size(),
"size");
2148 for(
int i=0; i<exv.size(); i++) {
2149 ar.archive_ex(exv[i], to_string(i).c_str());
2151 ofstream out(garfn);
2162 map<string, ex> dict;
2163 for(
int i=0; i<ar.num_expressions(); i++) {
2165 ex res = ar.unarchive_ex(name, i);
2169 auto size = ex_to<numeric>(dict[
"size"]).to_int();
2170 if(exv.size()>0 && size != exv.size())
throw Error(
"garRead: exvector size>0 & not match!");
2171 if(exv.size()<1) exv.resize(size);
2172 for(
int i=0; i<size; i++) exv[i] = dict[to_string(i)];
2176 auto cvs_vec =
GiNaC_Parallel(exv.size(), [&exv,pats](
int idx)->ex {
2177 return collect_lst(exv[idx], pats);
2180 for(
auto cvs : cvs_vec)
for(
auto cv : cvs) res_map[cv.op(1)] += cv.op(0);
2182 for(
auto kv : res_map) res_vec.push_back(lst{kv.second, kv.first});
2183 res_vec =
GiNaC_Parallel(res_vec.size(), [&res_vec,opt](
int idx)->ex {
2184 return exnormal(res_vec[idx].op(0), opt) * res_vec[idx].op(1);
2186 return add(res_vec);
2190 auto cvs_vec =
GiNaC_Parallel(exv.size(), [&exv,pats](
int idx)->ex {
2191 return collect_lst(exv[idx], pats);
2194 for(
auto cvs : cvs_vec)
for(
auto cv : cvs) res_map[cv.op(1)] += cv.op(0);
2196 for(
auto kv : res_map) res_vec.push_back(lst{kv.second, kv.first});
2197 res_vec = GiNaC_Parallel(res_vec.size(), [&res_vec,opt](
int idx)->ex {
2198 return exnormal(res_vec[idx].op(0),opt) * res_vec[idx].op(1);
2200 return add(res_vec);
2204 auto cvs_vec =
GiNaC_Parallel(exv.size(), [&exv,pats](
int idx)->ex {
2205 return collect_lst(exv[idx], pats);
2208 for(
auto cvs : cvs_vec)
for(
auto cv : cvs) res_map[cv.op(1)] += cv.op(0);
2210 for(
auto kv : res_map) res_vec.push_back(lst{kv.second, kv.first});
2211 res_vec = GiNaC_Parallel(res_vec.size(), [&res_vec,opt](
int idx)->ex {
2212 return exnormal(res_vec[idx].op(0),opt) * res_vec[idx].op(1);
2214 return add(res_vec);
2218 if(!is_a<add>(e))
throw Error(
"add_collect_normal: input is NOT a add class.");
2219 exvector exv(e.begin(), e.end());
2224 if(!is_a<add>(e))
throw Error(
"add_collect_normal: input is NOT a add class.");
2225 exvector exv(e.begin(), e.end());
2230 if(!is_a<add>(e))
throw Error(
"add_collect_normal: input is NOT a add class.");
2231 exvector exv(e.begin(), e.end());
2236 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i)
if(is_a<wildcard>(*i))
return true;
2242 for(
auto kv : r)
if(is_a<mul>(kv.first) && !
has_w(kv.first)) repl[
w*kv.first]=
w*kv.second;
2247 for(
auto item : r)
if(is_a<mul>(item) && !
has_w(item)) repl.append(
w*item.op(0)==
w*item.op(1));
2254 ar.archive_ex(e,
"e");
2259 for(
auto const & e : es) ar.archive_ex(e,
"e");
2264 ar.archive_ex(e1,
"e");
2265 ar.archive_ex(e2,
"e");
2268 void ReShare(
const ex & e1,
const ex & e2,
const ex & e3) {
2270 ar.archive_ex(e1,
"e");
2271 ar.archive_ex(e2,
"e");
2272 ar.archive_ex(e3,
"e");
2277 for(
auto & e : ev) ar.archive_ex(e,
"e");
2280 void ReShare(
const exvector & ev1,
const exvector & ev2) {
2282 for(
auto & e : ev1) ar.archive_ex(e,
"e");
2283 for(
auto & e : ev2) ar.archive_ex(e,
"e");
2287 auto v = cln::the<cln::cl_I>(ex_to<numeric>(n).to_cl_N());
2288 return numeric(cln::nextprobprime(v));
2291 auto v = cln::the<cln::cl_I>(numeric(n).to_cl_N());
2292 return numeric(cln::nextprobprime(v));
2298 if(is_a<numeric>(e)) {
2299 auto ne = ex_to<numeric>(e);
2300 if(ne.is_crational())
return e;
2301 auto zz = ne.to_cl_N();
2302 auto re = cln::rationalize(cln::realpart(zz));
2303 auto im = cln::rationalize(cln::imagpart(zz));
2304 return numeric(cln::complex(re,im));
2305 }
else return e.map(self);
2314 extern std::stack<cln::float_format_t> cln_prec_stack;
2315 extern std::stack<long> digits_stack;
2322 cln::default_float_format = cln::float_format(prec);
2330 cln::default_float_format = prec;
2336 return cln::default_float_format;
2339 void arg2map(
int argc,
char** argv,
const char *optstring, std::map<char,std::string> & kv) {
2340 auto o_opterr = opterr;
2343 int opt = getopt(argc, argv, optstring);
2346 if(optarg) kv[opt] = optarg;
2356 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i)
if(is_a<symbol>(*i))
return true;
2363 memset(hostname, 0,
sizeof(hostname));
2364 if (gethostname(hostname,
sizeof(hostname)) == 0) {
2365 return string(hostname);
2367 throw Error(
"get_hostname error");
2372 const char* val = std::getenv(name.c_str());
2373 if(val==NULL)
return string(
"");
unsigned golden_ratio_hash(uintptr_t n)
#define IMPLEMENT_HAS(classname)
#define DEFAULT_CTOR(classname)
#define IMPLEMENT_ALL(classname)
class used to wrap error message
const char * what() const
Error(string _msg)
Error constructor,.
class to wrap map_function of GiNaC
class to parse for string or file, helpful with Symbol class
ex Read(const string &instr, bool s2S=true)
class extended to GiNaC symbol class, represent a positive symbol
ex series(const relational &s, int order, unsigned options=0) const override
void archive(archive_node &n) const override
Symbol archive.
ex imag_part() const override
Symbol * duplicate() const override
bool is_equal_same_type(const basic &other) const override
ex conjugate() const override
static ex set_all(const ex &expr)
const char * class_name() const override
ex subs(const exmap &m, unsigned options=0) const override
void read_archive(const archive_node &n) override
Symbol read_archive.
static GiNaC::registered_class_info & get_class_info_static()
ex derivative(const symbol &s) const override
unsigned calchash() const override
ex evalf() const override
void set(const ex &v) const
static std::map< std::string, ex > Table
void accept(GiNaC::visitor &v) const override
ex real_part() const override
int compare_same_type(const GiNaC::basic &other) const override
const GiNaC::registered_class_info & get_class_info() const override
XIntegral Class, preface to SecDec.
ex op(size_t i) const override
int compare_same_type(const GiNaC::basic &other) const override
void accept(GiNaC::visitor &v) const override
XIntegral * duplicate() const override
void archive(archive_node &n) const override
ex & let_op(size_t i) override
void print(const print_dflt &c, unsigned level=0) const
void read_archive(const archive_node &n) override
const char * class_name() const override
static GiNaC::registered_class_info & get_class_info_static()
const GiNaC::registered_class_info & get_class_info() const override
size_t nops() const override
class extended to GiNaC symbol class, pure imaginary symbol
bool is_equal_same_type(const basic &other) const override
ex evalf() const override
static std::map< std::string, ex > Table
void archive(archive_node &n) const override
Symbol archive.
iSymbol * duplicate() const override
ex real_part() const override
ex derivative(const symbol &s) const override
static GiNaC::registered_class_info & get_class_info_static()
ex conjugate() const override
const char * class_name() const override
ex series(const relational &s, int order, unsigned options=0) const override
void accept(GiNaC::visitor &v) const override
ex imag_part() const override
const GiNaC::registered_class_info & get_class_info() const override
int compare_same_type(const GiNaC::basic &other) const override
void read_archive(const archive_node &n) override
Symbol read_archive.
unsigned calchash() const override
static ex sum(lst m)
sum all elements in the list
static lst map(const lst &m, F f)
ex expand_ex(ex const &expr_in, std::function< bool(const ex &)> has_func)
the expand like Mathematica
const char * Color_HighLight
ex exfactor(const ex &expr_in, int opt)
factorize a expression
ex collect_factors(const ex &expr)
a wrapper for collect_common_factors, catch errors
void arg2map(int argc, char **argv, const char *optstring, std::map< char, std::string > &kv)
__float128 ex2q(ex num)
ex of numeric to __float128
ex EvalF(ex expr)
the nuerical evaluation, Digits=100 will be used
lst str2lst(const string &expr, symtab stab)
convert string to the lst, using Parser internally
ex exnd(const ex &expr, int opt)
num_den a expression
ex form_factor(const ex &expr, bool nd=true)
lst gather_symbols(const ex &e)
get all symbols from input expression
void let_op_prepend(ex &ex_in, const ex item)
preppend item into expression
lst xlst(int bi, int ei)
return a lst: x(bi), x(bi+1), ..., x(ei)
int GiNaC_Parallel_Process
void let_op(ex &ex_in, int index1, int index2, const ex item)
update index1-th.index2-th of expression with item
std::initializer_list< ex > init_list
ex q2ex(__float128 num)
__float128 to ex
bool xPositive(ex const expr)
check the expr is xPositive, i.e., each x-monomial item is postive
pair< ex, epvec_t > inner_expand_collect(ex const &expr_in, std::function< bool(const ex &)> has_func, int depth=0)
void ex2file(const ex &expr, string filename)
export expression file
ex normal_fermat(const ex &expr, bool dfactor)
return the normalizatied expression, using fermat_numer_denom
ex NN(ex expr, int digits)
the nuerical evaluation
map< string, bool > GiNaC_Parallel_RM
ex factor_flint(const ex &e, bool nd=true)
ex collect_ex(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica
void garRead(const string &garfn, map< string, ex > &resMap)
garRead from file, and output in a map
map< string, int > GiNaC_Parallel_NB
void ReShare(const ex &e)
bool file_exists(string fn)
ex factor_form(const ex &expr, bool nd)
factorize a expression using FORM
ex series_ex(ex const &expr_in, ex const &s0, int sn0)
the series like Mathematica, include s^n
ex str2ex(const string &expr, symtab stab)
convert string to ex expression, using Parser internally
lst syms(const exvector &ev)
ex form_eval(const ex &expr)
string now(bool use_date)
date/time string
vector< pair< ex, ex > > epvec_t
ex numer_denom_fermat(const ex &expr, bool dfactor=false)
return the numerator and denominator after normalization
string RunOS(const string &cmd)
run symtem command and return the output as string
lst add2lst(const ex &expr)
convert add to lst
ex fermat_normal(const ex &expr, bool dfactor=false)
int CpuCores()
return the cpu cores using OpenMP
map< string, int > GiNaC_Parallel_NP
map< string, int > GiNaC_Parallel_Verb
map< string, bool > GiNaC_Parallel_ReWR
exvector lst2vec(const lst &alst)
convert lst to exvector
ex get_op(const ex ex_in, int index1, int index2)
return index1-th.index2-th of expression
vector< string > file2strvec(string filename, bool skip_empty)
read file content to string vector
ex file2ex(string filename)
read file content to ex
ex exnormal(const ex &expr, int opt)
normalize a expression
const int o_normal_fermat
ex nextprime(const ex &n)
ex normal_flint(const ex &expr, int opt=o_flint)
ex inner_factor_form(const ex &expr)
lst mul2lst(const ex &expr)
convert mul to lst
string file2str(string filename)
read file content to string
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}, ... }
ex diff_ex(ex const expr, ex const xp, unsigned nth, bool expand)
the differential like Mathematica
ex Rationalize(const ex &e, int dn)
void string_replace_all(string &str, const string &from, const string &to)
ex exexpand(const ex &expr, int opt)
factorize a expression
void garWrite(const string &garfn, const map< string, ex > &resMap)
garWrite to write the string-key map to the archive
void let_op_append(ex &ex_in, const ex item)
append item into expression
lst vec2lst(const exvector &ev)
convert exvector to lst
string ex2str(const ex &expr)
convert ex to output string, the defalut printer format will be used
void let_op_remove_first(ex &ex_in)
remove first from expression
matrix lst2mat(const lst &ls)
convert 2Dim lst to matrix
bool dir_exists(string dir)
void str2file(const string &ostr, string filename)
export string to a file
co_epvec_t power_expand_2(const co_epvec_t &co_epv, int n)
void set_precision(long prec, bool push)
ex add_collect_normal(const exvector &exv, ex const &pats, int opt)
map< string, string > GiNaC_Parallel_PRE
std::vector< std::string > split(const std::string &s, char delimiter)
split the string into serveral part, separated by the delimiter
int xSign(ex const expr)
the always sign for expr
pair< ex, epvec_t > co_epvec_t
exvector GiNaC_Parallel(int ntotal, std::function< ex(int)> f, const string &key)
GiNaC Parallel Evaluation using fork.
void let_op_remove_last(ex &ex_in)
remove last from expression
bool has_symbol(const ex &e)
std::stack< cln::float_format_t > cln_prec_stack
std::stack< long > digits_stack
string get_env(const string &name)
ex numer_fermat(const ex &expr)
ex fermat_numer_denom(const ex &expr, bool dfactor=false)
int ex2int(ex num)
ex to integer
ex subs(const ex &e, init_list sl)