HepLib
Loading...
Searching...
No Matches
BASIC.cpp
Go to the documentation of this file.
1
6#include "BASIC.h"
7#include "cln/cln.h"
8
9inline unsigned golden_ratio_hash(uintptr_t n) {
10 return n * UINT64_C(0x4f1bbcdd);
11}
12
13extern "C" {
14 #include <quadmath.h>
15}
16
17namespace HepLib {
18
23 Error::Error(string _msg) : msg(_msg) { }
24 const char * Error::what() const throw () {
25 return msg.c_str();
26 }
27
28 /*-----------------------------------------------------*/
29 // Symbol
30 /*-----------------------------------------------------*/
31
32 namespace {
33 const symbol & get_symbol(const string & s) {
34 static map<string, symbol> dict;
35 string key = s;
36 if (dict.find(key) == dict.end()) dict[key] = symbol(s,0);
37 return dict[key];
38 }
39
40 const Symbol & get_Symbol(const string & s) {
41 static map<string, Symbol> dict;
42 string key = s;
43 if (dict.find(key) == dict.end()) dict[key] = Symbol(s);
44 return dict[key];
45 }
46
47 const iSymbol & get_iSymbol(const string & s) {
48 static map<string, iSymbol> dict;
49 string key = s;
50 if (dict.find(key) == dict.end()) dict[key] = iSymbol(s);
51 return dict[key];
52 }
53 }
54
55 //DEFAULT_CTOR(Symbol)
56 IMPLEMENT_HAS(Symbol)
57 IMPLEMENT_ALL(Symbol)
58 //GINAC_IMPLEMENT_REGISTERED_CLASS(Symbol, symbol)
59 GiNaC::registered_class_info & Symbol::get_class_info_static() { return reg_info; }
61 Symbol * Symbol::duplicate() const { Symbol * bp = new Symbol(*this); bp->setflag(GiNaC::status_flags::dynallocated); return bp; }
62 void Symbol::accept(GiNaC::visitor & v) const { if (visitor *p = dynamic_cast<visitor *>(&v)) p->visit(*this); else inherited::accept(v); }
63 const GiNaC::registered_class_info &Symbol::get_class_info() const { return get_class_info_static(); }
64 GiNaC::registered_class_info &Symbol::get_class_info() { return get_class_info_static(); }
65 const char *Symbol::class_name() const { return get_class_info_static().options.get_name(); }
66 //GINAC_IMPLEMENT_REGISTERED_CLASS END
67
72 Symbol::Symbol(const string &s) : symbol(get_symbol(s)) { Table[s]=*this; }
73 Symbol::Symbol() : symbol(get_symbol("")) { Table[""]=*this; }
74
75 int Symbol::compare_same_type(const basic &other) const {
76 if(!is_a<Symbol>(other)) throw Error("Symbol::compare_same_type");;
77 const Symbol &o = static_cast<const Symbol &>(other);
78 int ret = get_name().compare(o.get_name());
79 if(ret==0) return 0;
80 else if(ret<0) return -1;
81 else return 1;
82 }
83
88 void Symbol::archive(archive_node & n) const {
89 inherited::archive(n);
90 }
91
96 void Symbol::read_archive(const archive_node& n) {
97 inherited::read_archive(n);
98 }
99
100 ex Symbol::eval() const { return *this; }
101 ex Symbol::evalf() const { return *this; }
102 ex Symbol::conjugate() const { return *this; }
103 ex Symbol::real_part() const { return *this; }
104 ex Symbol::imag_part() const { return 0; }
105 unsigned Symbol::calchash() const {
106 static std::hash<std::string> hs;
107 unsigned seed = hs(get_name()+typeid(*this).name());
108 hashvalue = golden_ratio_hash(seed);
109 setflag(status_flags::hash_calculated);
110 return hashvalue;
111 }
112
113 bool Symbol::is_equal_same_type(const basic & other) const {
114 if(!is_a<Symbol>(other)) throw Error("Symbol::is_equal_same_type");
115 const Symbol *o = static_cast<const Symbol *>(&other);
116 return get_name()==o->get_name(); // should be the same as symbol class
117 }
118
119 ex Symbol::derivative(const symbol & s) const {
120 if(!is_exactly_a<Symbol>(s)) return 0;
121 if(is_equal_same_type(s)) return 1;
122 else return 0;
123 }
124
125 ex Symbol::series(const relational & r, int order, unsigned options) const {
126 epvector seq;
127 const ex point = r.rhs();
128
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));
135 }
136
137 void Symbol::set_name(string n) { throw Error("Symbol can not reset the name!"); }
138
139 void Symbol::set(const ex & v) const { vmap[*this] = v; }
140 void Symbol::unset() const { vmap.erase(*this); }
141
142 void Symbol::set(const Symbol & s, const ex & v) { vmap[s] = v; }
143 void Symbol::set(const string & str, const ex & v) { vmap[Symbol(str)] = v; }
144 void Symbol::unset(const Symbol &s) { vmap.erase(s); }
145 void Symbol::unset(const string &str) { vmap.erase(Symbol(str)); }
146 void Symbol::unset_all() { vmap.clear(); }
147 ex Symbol::set_all(const ex & expr) {
148 ex v1 = expr;
149 while(true) {
150 ex v2 = v1.subs(vmap);
151 if(v2.is_equal(v1)) break;
152 v1 = v2;
153 }
154 return v1;
155 }
156
157 /*-----------------------------------------------------*/
158 // iSymbol
159 /*-----------------------------------------------------*/
160
161 //DEFAULT_CTOR(iSymbol)
163 //GINAC_IMPLEMENT_REGISTERED_CLASS(iSymbol, symbol)
164 GiNaC::registered_class_info & iSymbol::get_class_info_static() { return reg_info; }
166 iSymbol * iSymbol::duplicate() const { iSymbol * bp = new iSymbol(*this); bp->setflag(GiNaC::status_flags::dynallocated); return bp; }
167 void iSymbol::accept(GiNaC::visitor & v) const { if (visitor *p = dynamic_cast<visitor *>(&v)) p->visit(*this); else inherited::accept(v); }
168 const GiNaC::registered_class_info &iSymbol::get_class_info() const { return get_class_info_static(); }
169 GiNaC::registered_class_info &iSymbol::get_class_info() { return get_class_info_static(); }
170 const char *iSymbol::class_name() const { return get_class_info_static().options.get_name(); }
171 //GINAC_IMPLEMENT_REGISTERED_CLASS END
172
177 iSymbol::iSymbol(const string &s) : symbol(get_symbol(s)) { Table[s]=*this; }
178 iSymbol::iSymbol() : symbol(get_symbol("")) { Table[""]=*this; }
179 int iSymbol::compare_same_type(const basic &other) const {
180 if(!is_a<iSymbol>(other)) throw Error("iSymbol::compare_same_type");
181 const iSymbol &o = static_cast<const iSymbol &>(other);
182 int ret = get_name().compare(o.get_name());
183 if(ret==0) return 0;
184 else if(ret<0) return -1;
185 else return 1;
186 }
187
188 bool iSymbol::is_equal_same_type(const basic & other) const {
189 if(!is_a<iSymbol>(other)) throw Error("iSymbol::is_equal_same_type");
190 const iSymbol *o = static_cast<const iSymbol *>(&other);
191 return serial==o->serial; // should be the same as symbol class
192 }
193
194 ex iSymbol::derivative(const symbol & s) const {
195 if(!is_exactly_a<iSymbol>(s)) return 0;
196 if(is_equal_same_type(s)) return 1;
197 else return 0;
198 }
199
200 ex iSymbol::series(const relational & r, int order, unsigned options) const {
201 epvector seq;
202 const ex point = r.rhs();
203
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));
210 }
211
212 void iSymbol::set_name(string n) { throw Error("iSymbol can not reset the name!"); }
213
214 unsigned iSymbol::calchash() const {
215 hashvalue = get_symbol(get_name()).gethash();
216 setflag(status_flags::hash_calculated);
217 return hashvalue;
218 }
219
224 void iSymbol::archive(archive_node & n) const {
225 inherited::archive(n);
226 }
227
232 void iSymbol::read_archive(const archive_node& n) {
233 inherited::read_archive(n);
234 }
235
236 ex iSymbol::eval() const { return *this; }
237 ex iSymbol::evalf() const { return *this; }
238 ex iSymbol::conjugate() const { return (*this)*(-1); }
239 ex iSymbol::real_part() const { return ex(0); }
240 ex iSymbol::imag_part() const { return (-I)*(*this); }
241
242 /*-----------------------------------------------------*/
243 // Global varibales
244 /*-----------------------------------------------------*/
245
246 const char* ErrColor = RED;
247 const char* WarnColor = MAGENTA;
248 const char* Color_HighLight = WHITE;
249
259 exvector GiNaC_Parallel(int ntotal, std::function<ex(int)> f, const string & key) {
260 if(ntotal<1) return exvector();
261 int ec = 0;
262 int nactive = 0;
263 string exstr = "";
264 int fork_retried = 0;
265 int nproc = GiNaC_Parallel_Process;
266 if(GiNaC_Parallel_NP.find(key)!=GiNaC_Parallel_NP.end()) nproc = GiNaC_Parallel_NP[key];
267
268 bool rm = true;
269 if(GiNaC_Parallel_RM.find(key)!=GiNaC_Parallel_RM.end()) rm = GiNaC_Parallel_RM[key];
270 string pre = PRE;
271 if(GiNaC_Parallel_PRE.find(key)!=GiNaC_Parallel_PRE.end()) pre = GiNaC_Parallel_PRE[key];
272
273 int verb = Verbose;
274 if(GiNaC_Parallel_Verb.find(key)!=GiNaC_Parallel_Verb.end()) verb = GiNaC_Parallel_Verb[key];
275
276 // nproc=0, non-parallel
277 if(nproc==0) {
278 exvector ovec;
279 for(int i=0; i<ntotal; i++) ovec.push_back(f(i));
280 return exvector(std::move(ovec));
281 }
282
283 int para_max_run = nproc<0 ? omp_get_num_procs() : nproc;
284 if(para_max_run<0) para_max_run = 0;
285 if(para_max_run>omp_get_num_procs()) para_max_run = omp_get_num_procs();
286
287 int rc;
288 auto ppid = getpid();
289 ostringstream cmd;
290 string gp_host = get_env("GiNaC_Parallel_Host");
291 if(gp_host.length()>0) gp_host += "_";
292 cmd << "mkdir -p " << gp_host << ppid;
293 if(!dir_exists(gp_host+to_string(ppid))) rc = system(cmd.str().c_str());
294
295 int nbatch = GiNaC_Parallel_Batch;
296 if(GiNaC_Parallel_NB.find(key)!=GiNaC_Parallel_NB.end()) nbatch = GiNaC_Parallel_NB[key];
297 if(nbatch<=0) nbatch = ntotal/para_max_run/5;
298 else if(nbatch > ntotal/para_max_run) nbatch = ntotal/para_max_run;
299 if(nbatch<1) nbatch = 1;
300 int btotal = ntotal/nbatch + ((ntotal%nbatch)==0 ? 0 : 1);
301
302 bool nst = (GiNaC_Parallel_Level>0);
303 pid_t npid=0, pgid;
304 if(getpgid(0)!=ppid) { // not group leader
305 if(nst) {
306 npid = fork();
307 if(npid < 0) throw Error("GiNaC_Parallel: Error (1) @ fork()");
308 if(npid!=0) goto wait_label;
309 } // else - for case in a shell script
310 if(setpgid(0,0)) {
311 if(setpgid(0,0)) throw Error("GiNaC_Parallel: setpgid(0,0) Failed.");
312 }
313 }
314
315 pgid = getpid(); // should be groud leader @ here
316 while(fork_retried<5) {
317 ec = 0;
318 exstr = "";
319 nactive = 0;
320 for(int bi=0; bi<btotal; bi++) {
321 restart: ;
322 for(int i=0; i<btotal; i++) if(waitpid(-pgid,NULL,WNOHANG)>0) nactive--;
323 if(verb > 1 && !nst) {
324 cout << "\r \r" << pre;
325 cout << "\\--Evaluating ";
326 if(key != "") cout << Color_HighLight << key << RESET << " ";
327 cout << Color_HighLight << nbatch << "x" << RESET << "[" << (bi+1) << "/" << btotal << "] @ " << now(false) << exstr << flush;
328 }
329
330 if(fork_retried>0) { // skip when bi.*.gar exists
331 ostringstream garfn;
332 if(key == "") garfn << gp_host << ppid << "/" << bi << ".gar";
333 else garfn << gp_host << ppid << "/" << bi << "." << key << ".gar";
334 if(file_exists(garfn.str())) continue;
335 }
336
337 auto pid = fork();
338 if(pid < 0) {
339 if(getpid()!=pgid) exit(0); // make sure exit child process
340 ec++;
341 if(ec>3*btotal) throw Error("GiNaC_Parallel: Error (2) @ fork()");
342 exstr = " [fork(" + to_string(ec) + ")]";
343 if(waitpid(-pgid,NULL,0)>0) nactive--;
344 goto restart; // parent process goes next cycle
345 }
346 if(pid==0 && setpgid(0, pgid)!=0) {
347 if(setpgid(0, pgid)) throw Error("GiNaC_Parallel: setpgid(0, pgid) Failed.");
348 }
349 if(pid>0) {
350 nactive++;
351 if(nactive >= para_max_run) if(waitpid(-pgid,NULL,0)>0) nactive--;
352 continue; // parent process goes next cycle
353 }
354
355 // pid = 0, child process
356 In_GiNaC_Parallel = true;
358 try {
359 lst res_lst;
360 for(int ri=0; ri<nbatch; ri++) {
361 int i = bi*nbatch + ri;
362 if(i<ntotal) res_lst.append(f(i));
363 else break;
364 }
365 ostringstream garfn;
366 if(key == "") garfn << gp_host << ppid << "/" << bi << ".gar";
367 else garfn << gp_host << ppid << "/" << bi << "." << key << ".gar";
368 garWrite(garfn.str(), res_lst);
369 } catch(exception &p) { // NOT use Error
370 cout << ErrColor << "Failed in GiNaC_Parallel!" << RESET << endl;
371 cout << ErrColor << p.what() << RESET << endl;
372 }
373 exit(0);
374 }
375
376 if(getpid()!=pgid) exit(0); // make sure child exit
377 while (waitpid(-pgid,NULL,0) != -1) { }
378 if(!nst && verb > 1) cout << endl;
379 if(getpid()!=ppid) exit(0); // make the forked group leader exit
380
381 if(ec<2) break;
382 // check all *.gar and retry
383 bool all_gar_exists = true;
384 for(int bi=0; bi<btotal; bi++) {
385 ostringstream garfn;
386 if(key == "") garfn << gp_host << ppid << "/" << bi << ".gar";
387 else garfn << gp_host << ppid << "/" << bi << "." << key << ".gar";
388 if(!file_exists(garfn.str())) {
389 all_gar_exists = false;
390 break;
391 }
392 }
393 if(all_gar_exists) break;
394 para_max_run = para_max_run/2;
395 if(para_max_run<2) break;
396 fork_retried++;
397 }
398
399 wait_label:
400 if(npid!=0) waitpid(npid,NULL,0); // wait nest process to exit
401
402 //#define use_gar_write // use ReWR
403
404 exvector ovec;
405 if(true) {
406 #ifdef use_gar_write
407 exvector ovec_tmp;
408 #endif
409 for(int bi=0; bi<btotal; bi++) {
410 if(verb > 1 && !nst) {
411 if(key == "") {
412 cout << "\r \r" << pre;
413 cout << "\\--Reading *.gar [" << (bi+1) << "/" << btotal << "] @ " << now(false) << flush;
414 } else {
415 cout << "\r \r" << pre;
416 cout << "\\--Reading *." << Color_HighLight << key << RESET << ".gar [" << (bi+1) << "/" << btotal << "] @ " << now(false) << flush;
417 }
418 }
419
420 ostringstream garfn;
421 if(key == "") garfn << gp_host << ppid << "/" << bi << ".gar";
422 else garfn << gp_host << ppid << "/" << bi << "." << key << ".gar";
423 lst res_lst;
424 try {
425 if(file_exists(garfn.str())) {
426 res_lst = ex_to<lst>(garRead(garfn.str()));
427 remove(garfn.str().c_str());
428 goto done;
429 }
430 } catch(exception &p) { }
431 if(verb > 1 && !nst) cout << " - ReTry" << endl;
432 try {
433 res_lst.remove_all();
434 for(int ri=0; ri<nbatch; ri++) {
435 int i = bi*nbatch + ri;
436 if(i<ntotal) res_lst.append(f(i));
437 else break;
438 }
439 } catch(exception &p) {
440 cout << ErrColor << "Failed in GiNaC_Parallel!" << RESET << endl;
441 cout << ErrColor << p.what() << RESET << endl;
442 throw Error("GiNaC_Parallel_ReTRY: "+string(p.what()));
443 }
444 done: ;
445 #ifdef use_gar_write
446 if(GiNaC_Parallel_ReWR.find(key)==GiNaC_Parallel_ReWR.end() || GiNaC_Parallel_ReWR[key]) {
447 for(auto res : res_lst) ovec_tmp.push_back(res);
448 } else {
449 for(auto res : res_lst) ovec.push_back(res);
450 }
451 #else
452 for(auto res : res_lst) ovec.push_back(res);
453 #endif
454 }
455
456 #ifdef use_gar_write
457 if(!nst && verb>1) {
458 cout << endl;
459 if(key == "") {
460 cout << "\r \r" << pre;
461 cout << "\\--ReWR" << flush;
462 } else {
463 cout << "\r \r" << pre;
464 cout << "\\--ReWR " << Color_HighLight << key << RESET << flush;
465 }
466 }
467
468 if(GiNaC_Parallel_ReWR.find(key)==GiNaC_Parallel_ReWR.end() || GiNaC_Parallel_ReWR[key]) {
469 ostringstream garfn;
470 if(key == "") garfn << gp_host << ppid << "/ReWR.gar";
471 else garfn << gp_host << ppid << "/ReWR." << key << ".gar";
472 garWrite(garfn.str(), ovec_tmp);
473 ovec_tmp.clear();
474 garRead(garfn.str(), ovec);
475 }
476 #endif
477
478 if(!nst && verb>1) cout << endl;
479 }
480
481 if(rm) {
482 cmd.clear();
483 cmd.str("");
484 cmd << "rm -fr " << gp_host << ppid;
485 rc = system(cmd.str().c_str());
486 }
487 if(ovec.size() != ntotal) {
488 throw Error("GiNaC_Parallel: The output size is wrong!");
489 }
490
491 return exvector(std::move(ovec));
492 }
493
500 std::vector<std::string> split(const std::string& s, char delimiter) {
501 std::vector<std::string> tokens;
502 std::string token;
503 std::istringstream tokenStream(s);
504 while (std::getline(tokenStream, token, delimiter)) {
505 tokens.push_back(token);
506 }
507 return tokens;
508 }
509
515 ex lstHelper::sum(lst m) {
516 ex ret = 0;
517 for(int i=0; i<m.nops(); i++) ret += m.op(i);
518 return ret;
519 }
520
526 string now(bool use_date) {
527 time_t timep;
528 time (&timep);
529 char tmp[64];
530 if(use_date) strftime(tmp, sizeof(tmp), "%Y-%m-%d %H:%M:%S",localtime(&timep) );
531 else strftime(tmp, sizeof(tmp), "%H:%M:%S",localtime(&timep) );
532 return tmp;
533 }
534
540 lst gather_symbols(const ex & e) {
541 exset ss;
542 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) {
543 if(is_a<symbol>(*i)) ss.insert(*i);
544 }
545 lst sym_lst;
546 for(auto item : ss) sym_lst.append(item);
547 return sym_lst;
548 }
549
555 lst gather_symbols(const exvector & ve) {
556 exset ss;
557 for(auto e : ve) {
558 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) {
559 if(is_a<symbol>(*i)) ss.insert(*i);
560 }
561 }
562 lst sym_lst;
563 for(auto item : ss) sym_lst.append(item);
564 return sym_lst;
565 }
566
572 string RunOS(const string & cmd) {
573 char buf[128];
574 ostringstream oss;
575 FILE *fp = NULL;
576 if( (fp = popen(cmd.c_str(), "r")) != NULL) {
577 while(fgets(buf, 128, fp) != NULL) {
578 oss << buf;
579 }
580 pclose(fp);
581 fp = NULL;
582 }
583 return oss.str();
584 }
585
586
592 void garRead(const string &garfn, map<string, ex> &resMap) {
593 archive ar;
594 ifstream in(garfn);
595 in >> ar;
596 in.close();
597 for(int i=0; i<ar.num_expressions(); i++) {
598 string name;
599 ex res = ar.unarchive_ex(name, i);
600 resMap[name] = res;
601 }
602 }
603
610 ex garRead(const string &garfn, const char* key) { // use the const char *, not string
611 archive ar;
612 ifstream in(garfn);
613 in >> ar;
614 in.close();
615 auto res = ar.unarchive_ex(key);
616 return res;
617 }
618
624 ex garRead(const string &garfn) {
625 archive ar;
626 ifstream in(garfn);
627 in >> ar;
628 in.close();
629 auto c = ar.unarchive_ex("c");
630 auto res = ar.unarchive_ex("res");
631 if(c!=19790923) throw Error("garRead: check faild for file: " + garfn);
632 return res;
633 }
634
640 void garWrite(const string &garfn, const map<string, ex> &resMap) {
641 archive ar;
642 for(const auto & item : resMap) {
643 ar.archive_ex(item.second, item.first.c_str());
644 }
645 ofstream out(garfn);
646 out << ar;
647 out.close();
648 }
649
655 void garWrite(const string &garfn, const ex & res) {
656 archive ar;
657 ar.archive_ex(res, "res");
658 ar.archive_ex(19790923, "c");
659 ofstream out(garfn);
660 out << ar;
661 out.close();
662 }
663
664
671 ex str2ex(const string &expr, symtab stab) {
672 Parser par(stab);
673 ex ret = par.Read(expr);
674 return ret;
675 }
676
682 ex str2ex(const string &expr) {
683 Parser par;
684 ex ret = par.Read(expr);
685 return ret;
686 }
687
694 lst str2lst(const string &expr, symtab stab) {
695 Parser par(stab);
696 ex ret = par.Read(expr);
697 return ex_to<lst>(ret);
698 }
699
705 lst str2lst(const string &expr) {
706 Parser par;
707 ex ret = par.Read(expr);
708 return ex_to<lst>(ret);
709 }
710
716 string ex2str(const ex &expr) {
717 ostringstream oss;
718 oss << expr;
719 return oss.str();
720 }
721
727 string ex2str(const exvector &expr) {
728 ostringstream oss;
729 oss << expr;
730 return oss.str();
731 }
732
738 matrix lst2mat(const lst & ls) {
739 int nr = ls.nops();
740 int nc = ls.op(0).nops();
741 matrix mat(nr,nc);
742 for(int r=0; r<nr; r++) {
743 auto row = ls.op(r);
744 for(int c=0; c<nc; c++) mat(r,c) = row.op(c);
745 }
746 return mat;
747 }
748
754 string ex2str(const exmap &expr) {
755 ostringstream oss;
756 oss << expr;
757 return oss.str();
758 }
759
765 string ex2str(const exset &expr) {
766 ostringstream oss;
767 oss << expr;
768 return oss.str();
769 }
770
776 string file2str(string filename) {
777 ifstream ifs(filename);
778 string ostr((istreambuf_iterator<char>(ifs)), (istreambuf_iterator<char>()));
779 ifs.close();
780 return ostr;
781 }
782
788 void str2file(const string & ostr, string filename) {
789 std::ofstream ofs;
790 ofs.open(filename, ios::out);
791 ofs << ostr << flush;
792 ofs.close();
793 }
794
795 // not finished, just for memo
796 void str2file(char * buff, FILE* fh) {
797 string nstr;
798 int n = nstr.length();
799 char nbuff[n+1];
800 strcpy(nbuff, nstr.c_str());
801 FILE * f = fmemopen(nbuff, n, "r");
802 }
803
810 vector<string> file2strvec(string filename, bool skip_empty) {
811 ifstream fs(filename);
812 vector<string> ovec;
813 std::string line;
814 while (std::getline(fs, line)) {
815 if(!skip_empty || line.size()>0) ovec.push_back(line);
816 }
817 fs.close();
818 return ovec;
819 }
820
826 ex file2ex(string filename) {
827 return str2ex(file2str(filename));
828 }
829
836 ex file2ex(string filename, symtab st) {
837 return str2ex(file2str(filename), st);
838 }
839
846 void ex2file(const ex & expr, string filename) {
847 std::ofstream ofs;
848 ofs.open(filename, ios::out);
849 ofs << expr << endl;
850 ofs.close();
851 }
852
859 void ex2file(string filename, const ex & expr) {
860 ex2file(expr, filename);
861 }
862
868 ex q2ex(__float128 num) {
869 char buffer[128];
870 quadmath_snprintf(buffer, sizeof buffer, "%.36QG", num);
871 numeric ret(buffer);
872 return ret;
873 }
874
880 __float128 ex2q(ex num) {
881 ostringstream nss;
882 set_precision(40);
883 nss << num.evalf() << endl;
884 __float128 ret = strtoflt128(nss.str().c_str(), NULL);
886 return ret;
887 }
888
894 int ex2int(ex num) {
895 return ex_to<numeric>(num).to_int();
896 }
897
903 lst vec2lst(const exvector & ev) {
904 return GiNaC::lst(ev.begin(), ev.end());
905 }
906
912 exvector lst2vec(const lst & alst) {
913 exvector ret(alst.begin(), alst.end());
914 return exvector(std::move(ret));
915 }
916
922 lst add2lst(const ex & expr) {
923 if(!is_a<add>(expr)) return lst{expr};
924 lst ret;
925 for(auto item : expr) ret.append(item);
926 return ret;
927 }
928
934 lst mul2lst(const ex & expr) {
935 if(!is_a<mul>(expr)) return lst{expr};
936 lst ret;
937 for(auto item : expr) ret.append(item);
938 return ret;
939 }
940
947 lst xlst(int bi, int ei) {
948 lst ret;
949 for(int i=bi; i<=ei; i++) ret.append(x(i));
950 return ret;
951 }
952
958 lst xlst(int ei) {
959 return xlst(0, ei);
960 }
961
969 ex series_ex(ex const & expr_in, ex const &s0, int sn0) {
970 static symbol ss;
971 return series_ex(expr_in.subs(s0==ss),ss,sn0).subs(ss==s0);
972 }
973
981 ex series_ex(ex const & expr_in, symbol const &s0, int sn0) {
982 ex expr = expr_in;
983 if(!expr.has(s0)) return (sn0>=0 ? expr : 0);
984
985 exset sset;
986 expr.find(pow(s0, w), sset);
987 numeric sn_lcm = 1;
988 exmap repl1st, repl2nd;
989 for(auto pi : sset) {
990 auto sn = expand(pi.op(1));
991 if(!is_a<numeric>(sn)) {
992 ex ex1 = 0, ex2 = 0;
993 for(auto item : add2lst(sn)) {
994 if(!is_a<numeric>(item)) ex1 += item;
995 else ex2 += item;
996 }
997 sn = ex2;
998 static symbol sss;
999 repl1st[pi] = sss * pow(s0, sn);
1000 repl2nd[sss] = pow(s0, ex1);
1001 }
1002 if(!(is_a<numeric>(sn) && ex_to<numeric>(sn).is_rational())) {
1003 cerr << "s = " << s0 << endl;
1004 cerr << "expr_in = " << expr_in << endl;
1005 throw Error("series_ex: Not rational sn = " + ex2str(sn));
1006 }
1007 sn_lcm = lcm(sn_lcm, ex_to<numeric>(sn).denom());
1008 }
1009 if(expr.has(sqrt(s0))) sn_lcm = lcm(sn_lcm, numeric(2));
1010 expr = expr.subs(repl1st);
1011
1012 symbol s("s");
1013 if(!sn_lcm.is_integer()) throw Error("series_ex: Not integer with " + ex2str(sn_lcm));
1014 if(sn_lcm<0) sn_lcm = numeric(0)-sn_lcm;
1015 int sn = sn0 * sn_lcm.to_int();
1016 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));
1017
1018 auto cvs = collect_lst(expr,s);
1019 ex ret = 0;
1020 for(auto cv : cvs) {
1021 bool ok = false;
1022 int exN = 1;
1023 while(exN<10) {
1024 expr = cv.op(1) + pow(s,sn+exN+2)+pow(s,sn+exN+3);
1025 expr = expr.series(s,sn+exN);
1026 ex ot = 0;
1027 for(int i=0; i<expr.nops(); i++) {
1028 if(is_order_function(expr.op(i))) {
1029 ot = expr.op(i);
1030 break;
1031 }
1032 }
1033 if(!is_order_function(ot)) {
1034 cerr << "expr = " << expr << endl;
1035 throw Error("series_ex: Not an Order term with " + ex2str(ot));
1036 }
1037 if(ot.op(0).degree(s)>sn) {
1038 expr = series_to_poly(expr);
1039 expr = collect_ex(expr,s);
1040 for(int i=expr.ldegree(s); (i<=expr.degree(s) && i<=sn); i++) {
1041 ret += cv.op(0) * expr.coeff(s,i) * pow(s0,ex(i)/sn_lcm);
1042 }
1043 ok = true;
1044 break;
1045 }
1046 exN++;
1047 }
1048 if(!ok) throw Error("series_ex seems not working!");
1049 }
1050 ret = ret.subs(s==pow(s0,ex(1)/sn_lcm)); // need this for log-terms
1051 ret = ret.subs(repl2nd);
1052 ret = collect_ex(ret,s0);
1053 return ret;
1054 }
1055
1064 ex diff_ex(ex const expr, ex const xp, unsigned nth, bool expand) {
1065 symbol s;
1066 ex res = expr.subs(xp==s);
1067 if(!expand) return res.diff(s,nth).subs(s==xp);
1068 auto cvs = collect_lst(res, s);
1069 res = 0;
1070 for(auto cv : cvs) {
1071 res += cv.op(0) * cv.op(1).diff(s,nth).subs(s==xp);
1072 }
1073 return res;
1074 }
1075
1076 typedef vector<pair<ex,ex>> epvec_t; // first-pat, second-coeff
1077 typedef pair<ex,epvec_t> co_epvec_t; // first - overall coeff
1078 co_epvec_t power_expand_2(const co_epvec_t & co_epv, int n) {
1079 if(n==1) return co_epv;
1080 else if(n==2) {
1081 ex co = pow(co_epv.first,2);
1082 exmap pcmap;
1083 if(true) {
1084 auto epv = co_epv.second;
1085 if(epv.size()>10000) cout << "Warning: power_expand_2: epv.size > 10000" << endl;
1086 for(int i=0; i<epv.size(); i++) {
1087 pcmap[epv[i].first] += 2*co_epv.first*epv[i].second;
1088 pcmap[pow(epv[i].first,2)] += pow(epv[i].second,2);
1089 for(int j=i+1; j<epv.size(); j++) pcmap[epv[i].first*epv[j].first] += 2*epv[i].second*epv[j].second;
1090 }
1091 }
1092 epvec_t epv;
1093 epv.reserve(pcmap.size());
1094 for(auto kv : pcmap) {
1095 if(is_zero(kv.first) || is_zero(kv.second)) continue;
1096 epv.push_back(make_pair(kv.first, kv.second));
1097 }
1098 return make_pair(co, epvec_t(std::move(epv)));
1099 }
1100 int n2 = n/2;
1101 auto co_epv2 = power_expand_2(co_epv, n2);
1102 co_epv2 = power_expand_2(co_epv2, 2);
1103 if((n % 2)==0) return co_epvec_t(std::move(co_epv2));
1104
1105 ex co = co_epv.first * co_epv2.first;
1106 exmap pcmap;
1107 for(auto ep1 : co_epv.second) {
1108 pcmap[ep1.first] += ep1.second * co_epv2.first;
1109 for(auto ep2 : co_epv2.second) pcmap[ep2.first * ep1.first] += ep1.second * ep2.second;
1110 }
1111 for(auto ep2 : co_epv2.second) pcmap[ep2.first] += ep2.second * co_epv.first;
1112
1113 epvec_t epv;
1114 epv.reserve(pcmap.size());
1115 for(auto kv : pcmap) {
1116 if(is_zero(kv.first) || is_zero(kv.second)) continue;
1117 epv.push_back(make_pair(kv.first, kv.second));
1118 }
1119 return make_pair(co, epvec_t(std::move(epv)));
1120 }
1121
1122 pair<ex,epvec_t> inner_expand_collect(ex const &expr_in, std::function<bool(const ex &)> has_func, int depth=0) {
1123 if(!has_func(expr_in)) {
1124 ex co;
1125 epvec_t epv;
1126 co = expr_in;
1127 return make_pair(co,epv);
1128 } if(is_a<add>(expr_in)) {
1129 ex co = 0;
1130 exmap pcmap;
1131 for(auto item : expr_in) {
1132 if(has_func(item)) {
1133 auto co_epv = inner_expand_collect(item, has_func, depth+1);
1134 co += co_epv.first;
1135 for(auto ep : co_epv.second) pcmap[ep.first] += ep.second;
1136 } else co += item;
1137 }
1138 epvec_t epv;
1139 epv.reserve(pcmap.size());
1140 for(auto kv : pcmap) {
1141 if(is_zero(kv.first) || is_zero(kv.second)) continue;
1142 epv.push_back(make_pair(kv.first, kv.second));
1143 }
1144 return make_pair(co, epvec_t(std::move(epv)));
1145 } else if(is_a<mul>(expr_in)) {
1146 ex co = 1;
1147 epvec_t epv;
1148 for(auto item : expr_in) {
1149 if(!has_func(item)) {
1150 for(auto & ep : epv) ep.second *= item;
1151 co *= item;
1152 } else {
1153 exmap pcmap;
1154 auto co_epv = inner_expand_collect(item, has_func, depth+1);
1155 for(auto ep2 : co_epv.second) {
1156 pcmap[ep2.first] += ep2.second * co;
1157 for(auto ep1 : epv) pcmap[ep1.first * ep2.first] += ep1.second * ep2.second;
1158 }
1159 for(auto ep1 : epv) pcmap[ep1.first] += ep1.second * co_epv.first;
1160 co *= co_epv.first;
1161 epv.clear();
1162 epv.reserve(pcmap.size());
1163 for(auto kv : pcmap) {
1164 if(is_zero(kv.first) || is_zero(kv.second)) continue;
1165 epv.push_back(make_pair(kv.first, kv.second));
1166 }
1167 }
1168 }
1169 return make_pair(co,epvec_t(std::move(epv)));
1170 } else if(is_a<power>(expr_in) && expr_in.op(1).info(info_flags::nonnegint)) {
1171 int n = ex_to<numeric>(expr_in.op(1)).to_int();
1172 auto co_epv = inner_expand_collect(expr_in.op(0), has_func, depth+1);
1173 return power_expand_2(co_epv,n);
1174 } else {
1175 ex co = 0;
1176 epvec_t epv;
1177 epv.push_back(make_pair(expr_in, 1));
1178 return make_pair(co,epvec_t(std::move(epv)));
1179 }
1180 throw Error("inner_expand_collect unexpected region reached.");
1181 }
1182
1189 ex expand_ex(ex const &expr_in, std::function<bool(const ex &)> has_func) {
1190 auto co_epv = inner_expand_collect(expr_in, has_func, 0);
1191 ex ret = co_epv.first;
1192 for(auto ep : co_epv.second) ret += ep.second * ep.first;
1193 return ret;
1194 }
1195
1203 ex collect_ex(ex const &expr_in, std::function<bool(const ex &)> has_func, int opt) {
1204 auto cvs = collect_lst(expr_in, has_func, opt);
1205 exvector res_vec;
1206 res_vec.reserve(cvs.nops());
1207 for(auto cv : cvs) {
1208 auto cc = cv.op(0);
1209 auto vv = cv.op(1);
1210 if(cc.is_zero() || vv.is_zero()) continue;
1211 res_vec.push_back(cc * vv);
1212 }
1213 return add(res_vec);
1214 }
1215
1223 lst collect_lst(ex const &expr_in, std::function<bool(const ex &)> has_func, int opt) {
1224 auto co_epv = inner_expand_collect(expr_in, has_func);
1225 ex cf = co_epv.first;
1226 lst res_lst;
1227 if(!is_zero(cf)) co_epv.second.push_back(make_pair(1,cf));
1228 for(auto ep : co_epv.second) {
1229 ex vv = ep.first;
1230 ex cc = ep.second;
1231 if(opt==o_normal || opt==o_fermat || opt==o_fermatfD || opt==o_fermatN || opt==o_flint || opt==o_flint_ccf || opt==o_flintf || opt==o_flintf_ccf || opt==o_flintfD || opt==o_flintfD_ccf) cc = exnormal(cc,opt);
1232 else if(opt==o_form) cc = exfactor(cc,opt);
1233 else if(opt==o_normal_fermat) cc = exnormal(normal(cc),o_fermat);
1234 else if(opt==o_normal_form) cc = form_factor(normal(cc),o_fermat);
1235 else if(opt==o_fermat_form) cc = form_factor(fermat_normal(cc),o_fermat);
1236 if(!is_zero(cc)) res_lst.append(lst{cc, vv});
1237 }
1238 return res_lst;
1239 }
1240
1246 ex EvalF(ex expr) {
1247 exset zs;
1248 //patterns needing evalf()
1249 expr.find(zeta(w), zs);
1250 expr.find(zeta(w,w), zs);
1251
1252 lst repl;
1253 for(auto zi : zs) repl.append(zi==NN(zi));
1254 return expr.subs(repl);
1255 }
1256
1257 ex EvalL(ex expr) {
1258 static symbol sPi("dPi"), sEuler("dEuler"), siEpsilon("diEpsilon");
1259 lst repl = lst{Pi==sPi, Euler==sEuler,iEpsilon==siEpsilon};
1260 return EvalF(expr.subs(repl));
1261 }
1262 ex EvalQ(ex expr) {
1263 static symbol sPi("qPi"), sEuler("qEuler"), siEpsilon("qiEpsilon");
1264 lst repl = lst{Pi==sPi, Euler==sEuler,iEpsilon==siEpsilon};
1265 return EvalF(expr.subs(repl));
1266 }
1267 ex EvalMP(ex expr) {
1268 static symbol sPi("mpPi"), sEuler("mpEuler"), siEpsilon("mpiEpsilon");
1269 lst repl = lst{Pi==sPi, Euler==sEuler,iEpsilon==siEpsilon};
1270 return EvalF(expr.subs(repl));
1271 }
1272
1279 ex NN(ex expr, int digits) {
1280 set_precision(digits);
1281 auto nexpr = evalf(expr);
1283 return nexpr;
1284 }
1285
1291 bool xPositive(ex const expr) {
1292 auto tmp = expand(expr);
1293 if(tmp.is_zero()) return false;
1294 bool ret = false;
1295 if(is_a<add>(tmp)) {
1296 for(auto item : tmp) {
1297 auto nit = NN(item.subs(x(w)==1).normal());
1298 if(!is_a<numeric>(nit) || nit<0) return false;
1299 }
1300 ret = true;
1301 } else {
1302 auto ntmp = NN(tmp.subs(x(w)==1).normal());
1303 ret = (is_a<numeric>(ntmp) && ntmp>0);
1304 }
1305 return ret;
1306 }
1307
1313 int xSign(ex const expr) {
1314 if(is_zero(expr)) return 0;
1315 if(xPositive(expr)) return 1;
1316 else if(xPositive(ex(0)-expr)) return -1;
1317 else return 0;
1318 }
1319
1325 void let_op_append(ex & ex_in, const ex item) {
1326 auto tmp = ex_to<lst>(ex_in);
1327 tmp.append(item);
1328 ex_in = tmp;
1329 }
1330
1336 void let_op_prepend(ex & ex_in, const ex item) {
1337 auto tmp = ex_to<lst>(ex_in);
1338 tmp.prepend(item);
1339 ex_in = tmp;
1340 }
1341
1346 void let_op_remove_last(ex & ex_in) {
1347 auto tmp = ex_to<lst>(ex_in);
1348 tmp.remove_last();
1349 ex_in = tmp;
1350 }
1351
1356 void let_op_remove_first(ex & ex_in) {
1357 auto tmp = ex_to<lst>(ex_in);
1358 tmp.remove_first();
1359 ex_in = tmp;
1360 }
1361
1368 void let_op_append(ex & ex_in, int index, ex const item) {
1369 auto tmp = ex_to<lst>(ex_in.op(index));
1370 tmp.append(item);
1371 ex_in[index] = tmp;
1372 }
1373
1380 void let_op_append(lst & ex_in, int index, ex const item) {
1381 auto tmp = ex_to<lst>(ex_in.op(index));
1382 tmp.append(item);
1383 ex_in[index] = tmp;
1384 }
1385
1393 void let_op_append(ex & ex_in, int index1, int index2, ex const item) {
1394 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1395 tmp.append(item);
1396 ex_in[index1][index2] = tmp;
1397 }
1398
1406 void let_op_append(lst & ex_in, int index1, int index2, ex const item) {
1407 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1408 tmp.append(item);
1409 ex_in[index1][index2] = tmp;
1410 }
1411
1418 void let_op_prepend(ex & ex_in, int index, ex const item) {
1419 auto tmp = ex_to<lst>(ex_in.op(index));
1420 tmp.prepend(item);
1421 ex_in[index] = tmp;
1422 }
1423
1430 void let_op_prepend(lst & ex_in, int index, ex const item) {
1431 auto tmp = ex_to<lst>(ex_in.op(index));
1432 tmp.prepend(item);
1433 ex_in[index] = tmp;
1434 }
1435
1443 void let_op_prepend(ex & ex_in, int index1, int index2, ex const item) {
1444 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1445 tmp.prepend(item);
1446 ex_in[index1][index2] = tmp;
1447 }
1448
1456 void let_op_prepend(lst & ex_in, int index1, int index2, ex const item) {
1457 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1458 tmp.prepend(item);
1459 ex_in[index1][index2] = tmp;
1460 }
1461
1467 void let_op_remove_last(ex & ex_in, int index) {
1468 auto tmp = ex_to<lst>(ex_in.op(index));
1469 tmp.remove_last();
1470 ex_in[index] = tmp;
1471 }
1472
1478 void let_op_remove_last(lst & ex_in, int index) {
1479 auto tmp = ex_to<lst>(ex_in.op(index));
1480 tmp.remove_last();
1481 ex_in[index] = tmp;
1482 }
1483
1490 void let_op_remove_last(ex & ex_in, int index1, int index2) {
1491 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1492 tmp.remove_last();
1493 ex_in[index1][index2] = tmp;
1494 }
1495
1502 void let_op_remove_last(lst & ex_in, int index1, int index2) {
1503 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1504 tmp.remove_last();
1505 ex_in[index1][index2] = tmp;
1506 }
1507
1513 void let_op_remove_first(ex & ex_in, int index) {
1514 auto tmp = ex_to<lst>(ex_in.op(index));
1515 tmp.remove_first();
1516 ex_in[index] = tmp;
1517 }
1518
1524 void let_op_remove_first(lst & ex_in, int index) {
1525 auto tmp = ex_to<lst>(ex_in.op(index));
1526 tmp.remove_first();
1527 ex_in[index] = tmp;
1528 }
1529
1536 void let_op_remove_first(ex & ex_in, int index1, int index2) {
1537 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1538 tmp.remove_first();
1539 ex_in[index1][index2] = tmp;
1540 }
1541
1548 void let_op_remove_first(lst & ex_in, int index1, int index2) {
1549 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1550 tmp.remove_first();
1551 ex_in[index1][index2] = tmp;
1552 }
1553
1561 void let_op(ex &ex_in, int index1, int index2, const ex item) {
1562 ex_in[index1][index2] = item;
1563 }
1564
1572 void let_op(lst &ex_in, int index1, int index2, const ex item) {
1573 ex_in[index1][index2] = item;
1574 }
1575
1584 void let_op(ex &ex_in, int index1, int index2, int index3, const ex item) {
1585 ex_in[index1][index2][index3] = item;
1586 }
1587
1596 void let_op(lst &ex_in, int index1, int index2, int index3, const ex item) {
1597 ex_in[index1][index2][index3] = item;
1598 }
1599
1607 ex get_op(const ex ex_in, int index1, int index2) {
1608 return ex_in.op(index1).op(index2);
1609 }
1610
1618 ex get_op(const lst ex_in, int index1, int index2) {
1619 return ex_in.op(index1).op(index2);
1620 }
1621
1630 ex get_op(const ex ex_in, int index1, int index2, int index3) {
1631 return ex_in.op(index1).op(index2).op(index3);
1632 }
1633
1642 ex get_op(const lst ex_in, int index1, int index2, int index3) {
1643 return ex_in.op(index1).op(index2).op(index3);
1644 }
1645
1646 //-----------------------------------------------------------
1647 // XIntegral Class
1648 //-----------------------------------------------------------
1649 //GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(XIntegral, basic,print_func<print_dflt>(&XIntegral::print))
1650 GiNaC::registered_class_info & XIntegral::get_class_info_static() { return reg_info; }
1652 XIntegral * XIntegral::duplicate() const { XIntegral * bp = new XIntegral(*this); bp->setflag(GiNaC::status_flags::dynallocated); return bp; }
1653 void XIntegral::accept(GiNaC::visitor & v) const { if (visitor *p = dynamic_cast<visitor *>(&v)) p->visit(*this); else inherited::accept(v); }
1654 const GiNaC::registered_class_info &XIntegral::get_class_info() const { return get_class_info_static(); }
1655 GiNaC::registered_class_info &XIntegral::get_class_info() { return get_class_info_static(); }
1656 const char *XIntegral::class_name() const { return get_class_info_static().options.get_name(); }
1657 //GINAC_IMPLEMENT_REGISTERED_CLASS END
1658
1662
1663 int XIntegral::compare_same_type(const basic &other) const {
1664 if(!is_a<XIntegral>(other)) throw Error("XIntegral::compare_same_type");
1665 const XIntegral &o = static_cast<const XIntegral &>(other);
1666 auto c = Function.compare(o.Function);
1667 if(c!=0) return c;
1668 c = Exponent.compare(o.Exponent);
1669 if(c!=0) return c;
1670 c = Deltas.compare(o.Deltas);
1671 if(c!=0) return c;
1672 return 0;
1673 }
1674
1675 void XIntegral::print(const print_dflt &c, unsigned level) const {
1676 c.s << "[∬" << "(" << Function << ")^(" << Exponent << ")";
1677 if(Deltas.nops()>0) c.s << "*𝜹(" << Deltas << ")";
1678 c.s << "]";
1679 }
1680
1681 size_t XIntegral::nops() const { return 3; }
1682 ex XIntegral::op(size_t i) const {
1683 if(i==0) return Function;
1684 else if(i==1) return Exponent;
1685 else if(i==2) return Deltas;
1686 else throw Error("XIntegral::op, It is required that i<3.");
1687 }
1688 ex & XIntegral::let_op(size_t i) {
1689 ensure_if_modifiable();
1690 if(i==0) return Function;
1691 else if(i==1) return Exponent;
1692 else if(i==2) return Deltas;
1693 else throw Error("XIntegral::let_op, It is required that i<3.");
1694 }
1695
1696 void XIntegral::archive(archive_node & n) const {
1697 inherited::archive(n);
1698 n.add_ex("Function", Function);
1699 n.add_ex("Exponent", Exponent);
1700 n.add_ex("Deltas", Deltas);
1701 }
1702
1703 void XIntegral::read_archive(const archive_node& n) {
1704 inherited::read_archive(n);
1705 n.find_ex("Function", Function);
1706 n.find_ex("Exponent", Exponent);
1707 n.find_ex("Deltas", Deltas);
1708 }
1709
1711 Function = fed.op(0);
1712 Exponent = fed.op(1);
1713 if(fed.nops()>2) Deltas = fed.op(2);
1714 }
1715
1716 XIntegral::XIntegral(ex loops, ex ps, ex ns) {
1717 ex a = 0;
1718 ex pre = 1;
1719 ex rem = 0;
1720 lst delta;
1721 int xni = 0;
1722 lst funs, exps;
1723 for(int i=0; i<ps.nops(); i++) {
1724 if(is_zero(ns.op(i))) continue;
1725 auto cpi = Symbol::set_all(ps.op(i).expand());
1726 bool ltQ = false;
1727 for(auto li : loops) {
1728 if(cpi.has(li)) {
1729 ltQ = true;
1730 break;
1731 }
1732 }
1733
1734 ex sgn = 0;
1735 if(!ltQ) {
1736 pre *= pow(Symbol::set_all(ps.op(i).expand()), ex(0)-ns.op(i));
1737 ns[i] = 0;
1738 ps[i] = 1;
1739 continue;
1740 } else if(is_a<numeric>(ns.op(i)) && (ns.op(i)<0)) {
1741 throw Error("XIntegral, negative powers not supported yet.");
1742 }
1743
1744 // check loop^2
1745 for(auto li : loops) {
1746 if(!is_a<numeric>(cpi.coeff(li,2))) continue; // TODO: make sure positive
1747 numeric nm = ex_to<numeric>(cpi.coeff(li,2));
1748 if(nm.is_zero()) continue;
1749 sgn = nm>0 ? -1 : 1;
1750 break;
1751 }
1752 // check iEpsilon
1753 if(sgn.is_zero()) {
1754 if(!is_a<numeric>(cpi.coeff(iEpsilon))) continue;
1755 numeric nm = ex_to<numeric>(cpi.coeff(iEpsilon));
1756 if(!nm.is_zero()) sgn = nm>0 ? -1 : 1;
1757 }
1758 // others
1759 if(sgn.is_zero()) {
1760 sgn = 1;
1761 if(is_a<numeric>(cpi) && ex_to<numeric>(cpi)>0) sgn = -1;
1762 else sgn = 1;
1763 }
1764
1765 cpi = (ps.op(i)*sgn).subs(iEpsilon==0);
1766 if(sgn==-1) pre *= exp(I * Pi * ns.op(i)); // sgn<0: +iep, sgn>0: -iep, so I*Pi here
1767 a += ns.op(i);
1768 auto xi = x(xni);
1769 rem += xi * cpi;
1770 delta.append(xi);
1771 if(!is_zero(ns.op(i)-1)) {
1772 funs.append(xi);
1773 exps.append(ns.op(i)-1);
1774 }
1775 pre /= tgamma(ns.op(i));
1776 xni++;
1777 }
1778 rem = Symbol::set_all(rem.expand());
1779 ex dl2 = loops.nops()*(4-2*ep)/2;
1780 pre *= tgamma(a-dl2) * pow(I,loops.nops()) * pow(Pi,dl2) * pow(2*Pi,loops.nops()*(2*ep-4));
1781
1782 // Loop
1783 ex u=1;
1784 for(int i=0; i<loops.nops(); i++) {
1785 ex t2 = rem.coeff(loops.op(i),2);
1786 ex t1 = rem.coeff(loops.op(i),1);
1787 ex t0 = rem.coeff(loops.op(i),0);
1788 u *= (-t2);
1789 if(t2==0) {
1790 Function = lst{0};
1791 Exponent = lst{1};
1792 return;
1793 }
1794 rem = (t0 - pow(t1,2)/(4*t2)).expand();
1795 }
1796 rem = Symbol::set_all(rem).normal();
1797 u = Symbol::set_all(u).normal();
1798 rem = (rem * u).normal();
1799
1800 funs.prepend(rem);
1801 exps.prepend(dl2-a);
1802 funs.prepend(u);
1803 exps.prepend(a-dl2-(4-2*ep)/2);
1804 auto num_den = numer_denom(pre);
1805 funs.append(num_den.op(0));
1806 exps.append(1);
1807 if(!is_zero(num_den.op(1))) {
1808 funs.append(num_den.op(1));
1809 exps.append(-1);
1810 }
1811
1812 Function = funs;
1813 Exponent = exps;
1814 Deltas = lst{delta};
1815 }
1816
1821 int CpuCores() {
1822 return omp_get_num_procs();
1823 }
1824
1825
1832 ex normal_fermat(const ex & expr, bool dfactor) {
1833 auto nd = fermat_numer_denom(expr, dfactor);
1834 return nd.op(0)/nd.op(1);
1835 }
1836
1842 ex collect_factors(const ex & expr) {
1843 try {
1844 return collect_common_factors(expr);
1845 } catch(...) { }
1846 return expr;
1847 }
1848
1855 ex exfactor(const ex & expr_in, int opt) {
1856 // replace Symbol
1857 auto syms = gather_symbols(expr_in);
1858 exmap subs1, subs2;
1859 for(int i=0; i<syms.nops(); i++) {
1860 Symbol si("xfaci"+to_string(i));
1861 subs1[syms.op(i)] = si;
1862 subs2[si] = syms.op(i);
1863 }
1864 ex expr = expr_in.subs(subs1);
1865
1866 if(opt==o_form) expr = factor_form(expr);
1867 else if(opt==o_flint || opt==o_flintf || opt==o_flint_ccf || opt==o_flintf_ccf) {
1868 expr = factor_flint(expr);
1869 if(opt==o_flint_ccf || opt==o_flintf_ccf) expr = collect_common_factors(expr);
1870 }
1871
1872 return expr.subs(subs2); // replace back
1873 }
1874
1881 ex exexpand(const ex & expr, int opt) {
1882 if(opt==1) return expand(expr);
1883 else return expand(expr);
1884 }
1885
1886 namespace {
1887 exvector ev_fermat_pern(const exvector & ev, int np) {
1888 if(ev.size()<np) return ev;
1889 int tn = ev.size();
1890 exvector evs;
1891 int ci = 0;
1892 while(ci<tn) {
1893 ex sum = 0;
1894 for(int i=0; i<np; i++) {
1895 sum += ev[ci];
1896 ci++;
1897 if(ci==tn) break;
1898 }
1899 ex tt = normal_fermat(sum);
1900 evs.push_back(tt);
1901 }
1902 return exvector(std::move(evs));
1903 }
1904
1905 ex normal_fermat_pern(const ex & e, int np) {
1906 if(!is_a<add>(e)) return normal_fermat(e);
1907 exvector evs(e.begin(), e.end());
1908 while(evs.size()>np) evs = ev_fermat_pern(evs,np);
1909 ex res = normal_fermat(add(evs));
1910 return res;
1911 }
1912 }
1913
1920 ex exnormal(const ex & expr, int opt) {
1921 if(opt<0) return normal_fermat_pern(expr,-opt);
1922 else if(opt==o_normal) return normal(expr);
1923 else if(opt==o_fermat) return normal_fermat(expr);
1924 else if(opt==o_flint || opt==o_flint_ccf || opt==o_flintf || opt==o_flintf_ccf || opt==o_flintfD || opt==o_flintfD_ccf) return normal_flint(expr, opt);
1925 else if(opt==o_fermatfD) return normal_fermat(expr,true);
1926 else if(opt==o_fermatN) return numer_fermat(expr);
1927 return expr;
1928 }
1929
1936 ex exnd(const ex & expr, int opt) {
1937 if(opt==1) return numer_denom(factor_form(expr));
1938 else if(opt==2) return numer_denom_fermat(expr);
1939 else return numer_denom(expr);
1940 }
1941
1942 ex form_eval(const ex & expr) {
1943 static map<pid_t, Form> form_map;
1944 auto pid = getpid();
1945 if((form_map.find(pid)==form_map.end())) { // init section
1946 ostringstream ss;
1947 ss << "AutoDeclare Symbols fv;" << endl;
1948 form_map[pid].Init("form");
1949 form_map[pid].Execute(ss.str());
1950 }
1951 Form &fprc = form_map[pid];
1952
1953 auto expr_in = expr;
1954 exmap map_rat;
1955 expr_in = expr_in.to_polynomial(map_rat);
1956
1957 exset vs;
1958 for(const_preorder_iterator i = expr_in.preorder_begin(); i != expr_in.preorder_end(); ++i) {
1959 auto e = (*i);
1960 if(is_a<symbol>(e)) vs.insert(e);
1961 }
1962
1963 exmap s2v;
1964 symtab st;
1965 int cid = 0;
1966 for(auto ss : vs) {
1967 cid++;
1968 string cvv = "fv"+to_string(cid);
1969 s2v[ss] = Symbol(cvv);
1970 st[cvv] = ss.subs(map_rat);
1971 }
1972 ostringstream oss;
1973 expr_in = expr_in.subs(s2v);
1974 oss << "Local ff = " << expr_in << ";" << endl;
1975 oss << ".sort" << endl;
1976 try {
1977 auto ostr = fprc.Execute(oss.str(), "ff");
1978 Parser fp(st);
1979 ex ret = fp.Read(ostr);
1980 return ret;
1981 } catch(Error& err) {
1982 cout << oss.str() << endl;
1983 form_map.erase(pid);
1984 throw;
1985 }
1986 }
1987
1988 ex inner_factor_form(const ex & expr) {
1989 if(is_a<mul>(expr)) {
1990 ex res = 1;
1991 for(auto item : expr) res *= inner_factor_form(item);
1992 return res;
1993 }
1994 static map<pid_t, Form> form_map;
1995 auto pid = getpid();
1996 if((form_map.find(pid)==form_map.end())) { // init section
1997 ostringstream ss;
1998 ss << "AutoDeclare Symbols fv;" << endl;
1999 form_map[pid].Init("form");
2000 form_map[pid].Execute(ss.str());
2001 }
2002 Form &fprc = form_map[pid];
2003
2004 auto expr_in = expr;
2005 exmap map_rat;
2006 expr_in = expr_in.to_polynomial(map_rat);
2007
2008 exset vs;
2009 for(const_preorder_iterator i = expr_in.preorder_begin(); i != expr_in.preorder_end(); ++i) {
2010 auto e = (*i);
2011 if(is_a<symbol>(e)) vs.insert(e);
2012 }
2013
2014 exmap s2v;
2015 symtab st;
2016 int cid = 0;
2017 for(auto ss : vs) {
2018 cid++;
2019 string cvv = "fv"+to_string(cid);
2020 s2v[ss] = Symbol(cvv);
2021 st[cvv] = ss.subs(map_rat);
2022 }
2023 ostringstream oss;
2024 expr_in = expr_in.subs(s2v);
2025 oss << "Local ff = " << expr_in << ";" << endl;
2026 oss << "Factorize ff;" << endl;
2027 oss << ".sort" << endl;
2028 try {
2029 auto ostr = fprc.Execute(oss.str(), "ff");
2030 string_replace_all(ostr, "[", "(");
2031 string_replace_all(ostr, "]", ")");
2032 string_replace_all(ostr, "\\\n", "");
2033 string_replace_all(ostr, " ","");
2034 Parser fp(st);
2035 ex ret = fp.Read(ostr);
2036 ex res = 1;
2037 Symbol sfac("factor_");
2038 for(auto item : add2lst(ret)) res *= item.subs(sfac==1);
2039 return res;
2040 } catch(Error& err) {
2041 cout << oss.str() << endl;
2042 form_map.erase(pid);
2043 throw;
2044 }
2045 }
2046
2052 ex factor_form(const ex & expr, bool nd) {
2053 if(!nd) return inner_factor_form(expr);
2054 auto num_den = fermat_numer_denom(expr);
2055 if(is_zero(num_den.op(1)-1)) return inner_factor_form(num_den.op(0));
2056 return inner_factor_form(num_den.op(0))/inner_factor_form(num_den.op(1));
2057 }
2058
2059 //-----------------------------------------------------------
2060 // MMAFormat Output
2061 //-----------------------------------------------------------
2062 MMAFormat::MMAFormat(ostream &os, unsigned opt) : print_dflt(os, opt) {}
2063 MMAFormat::MMAFormat() : print_dflt(std::cout) {}
2064 GINAC_IMPLEMENT_PRINT_CONTEXT(MMAFormat, print_dflt)
2065
2066 const MMAFormat & MMAFormat::operator << (const basic & v) const {
2067 v.print(*this);
2068 return *this;
2069 }
2070 const MMAFormat & MMAFormat::operator << (const ex & v) const {
2071 v.print(*this);
2072 return *this;
2073 }
2074 const MMAFormat & MMAFormat::operator << (const lst & v) const {
2075 v.print(*this);
2076 return *this;
2077 }
2078 const MMAFormat & MMAFormat::operator<<(std::ostream& (*v)(std::ostream&)) const {
2079 s << v;
2080 return *this;
2081 }
2082
2083 const MMAFormat & MMAFormat::operator << (const matrix & mat) const {
2084 s << "{";
2085 int nr = mat.rows();
2086 int nc = mat.cols();
2087 for(int r=0; r<nr; r++) {
2088 s << "{";
2089 for(int c=0; c<nc; c++) {
2090 mat(r,c).print(*this);
2091 if(c+1!=nc) s << ",";
2092 }
2093 s << "}";
2094 if(r+1!=nr) s << ",";
2095 }
2096 s << "}";
2097 return *this;
2098 }
2099
2100 const MMAFormat & MMAFormat::operator << (const exvector & e) const {
2101 auto i = e.begin();
2102 auto vend = e.end();
2103 if (i==vend) { s << "{}"; return *this; }
2104 s << "{";
2105 while (true) {
2106 i->print(*this);
2107 ++i;
2108 if(i==vend) break;
2109 s << ",";
2110 }
2111 s << "}";
2112 return *this;
2113 }
2114
2115 const MMAFormat & MMAFormat::operator << (const exset & e) const {
2116 auto i = e.begin();
2117 auto send = e.end();
2118 if (i==send) { s << "{}"; return *this; }
2119 s << "{";
2120 while (true) {
2121 i->print(*this);
2122 ++i;
2123 if(i==send) break;
2124 s << ",";
2125 }
2126 s << "}";
2127 return *this;
2128 }
2129
2130 const MMAFormat & MMAFormat::operator << (const exmap & e) const {
2131 auto i = e.begin();
2132 auto mend = e.end();
2133 if (i==mend) { s << "{}"; return *this; }
2134 s << "{";
2135 while (true) {
2136 i->first.print(*this);
2137 s << "->";
2138 i->second.print(*this);
2139 ++i;
2140 if(i==mend) break;
2141 s << ",";
2142 }
2143 s << "}";
2144 return *this;
2145 }
2146
2147 void garWrite(const exvector &exv, string garfn) {
2148 archive ar;
2149 ar.archive_ex(exv.size(), "size");
2150 for(int i=0; i<exv.size(); i++) {
2151 ar.archive_ex(exv[i], to_string(i).c_str());
2152 }
2153 ofstream out(garfn);
2154 out << ar;
2155 out.close();
2156 }
2157
2158 void garRead(exvector &exv, string garfn) {
2159 archive ar;
2160 ifstream in(garfn);
2161 in >> ar;
2162 in.close();
2163
2164 map<string, ex> dict;
2165 for(int i=0; i<ar.num_expressions(); i++) {
2166 string name;
2167 ex res = ar.unarchive_ex(name, i);
2168 dict[name] = res;
2169 }
2170
2171 auto size = ex_to<numeric>(dict["size"]).to_int();
2172 if(exv.size()>0 && size != exv.size()) throw Error("garRead: exvector size>0 & not match!");
2173 if(exv.size()<1) exv.resize(size);
2174 for(int i=0; i<size; i++) exv[i] = dict[to_string(i)];
2175 }
2176
2177 ex add_collect_normal(const exvector &exv, ex const &pats, int opt) {
2178 auto cvs_vec = GiNaC_Parallel(exv.size(), [&exv,pats](int idx)->ex {
2179 return collect_lst(exv[idx], pats);
2180 }, "ColEx");
2181 exmap res_map;
2182 for(auto cvs : cvs_vec) for(auto cv : cvs) res_map[cv.op(1)] += cv.op(0);
2183 exvector res_vec;
2184 for(auto kv : res_map) res_vec.push_back(lst{kv.second, kv.first});
2185 res_vec = GiNaC_Parallel(res_vec.size(), [&res_vec,opt](int idx)->ex {
2186 return exnormal(res_vec[idx].op(0), opt) * res_vec[idx].op(1);
2187 }, "NorEx");
2188 return add(res_vec);
2189 }
2190
2191 ex add_collect_normal(const exvector &exv, init_list const &pats, int opt) {
2192 auto cvs_vec = GiNaC_Parallel(exv.size(), [&exv,pats](int idx)->ex {
2193 return collect_lst(exv[idx], pats);
2194 }, "ColEx");
2195 exmap res_map;
2196 for(auto cvs : cvs_vec) for(auto cv : cvs) res_map[cv.op(1)] += cv.op(0);
2197 exvector res_vec;
2198 for(auto kv : res_map) res_vec.push_back(lst{kv.second, kv.first});
2199 res_vec = GiNaC_Parallel(res_vec.size(), [&res_vec,opt](int idx)->ex {
2200 return exnormal(res_vec[idx].op(0),opt) * res_vec[idx].op(1);
2201 }, "NorEx");
2202 return add(res_vec);
2203 }
2204
2205 ex add_collect_normal(const exvector &exv, lst const &pats, int opt) {
2206 auto cvs_vec = GiNaC_Parallel(exv.size(), [&exv,pats](int idx)->ex {
2207 return collect_lst(exv[idx], pats);
2208 }, "ColEx");
2209 exmap res_map;
2210 for(auto cvs : cvs_vec) for(auto cv : cvs) res_map[cv.op(1)] += cv.op(0);
2211 exvector res_vec;
2212 for(auto kv : res_map) res_vec.push_back(lst{kv.second, kv.first});
2213 res_vec = GiNaC_Parallel(res_vec.size(), [&res_vec,opt](int idx)->ex {
2214 return exnormal(res_vec[idx].op(0),opt) * res_vec[idx].op(1);
2215 }, "NorEx");
2216 return add(res_vec);
2217 }
2218
2219 ex add_collect_normal(const ex & e, ex const &pats, int opt) {
2220 if(!is_a<add>(e)) throw Error("add_collect_normal: input is NOT a add class.");
2221 exvector exv(e.begin(), e.end());
2222 return add_collect_normal(exv, pats, opt);
2223 }
2224
2225 ex add_collect_normal(const ex & e, lst const &pats, int opt) {
2226 if(!is_a<add>(e)) throw Error("add_collect_normal: input is NOT a add class.");
2227 exvector exv(e.begin(), e.end());
2228 return add_collect_normal(exv, pats, opt);
2229 }
2230
2231 ex add_collect_normal(const ex & e, init_list const &pats, int opt) {
2232 if(!is_a<add>(e)) throw Error("add_collect_normal: input is NOT a add class.");
2233 exvector exv(e.begin(), e.end());
2234 return add_collect_normal(exv, pats, opt);
2235 }
2236
2237 bool has_w(const ex & e) {
2238 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) if(is_a<wildcard>(*i)) return true;
2239 return false;
2240 }
2241
2242 void subs_w(exmap & repl) {
2243 auto r = repl;
2244 for(auto kv : r) if(is_a<mul>(kv.first) && !has_w(kv.first)) repl[w*kv.first]=w*kv.second;
2245 }
2246
2247 void subs_w(lst & repl) {
2248 auto r = repl;
2249 for(auto item : r) if(is_a<mul>(item) && !has_w(item)) repl.append(w*item.op(0)==w*item.op(1));
2250 repl.sort();
2251 repl.unique();
2252 }
2253
2254 void ReShare(const ex & e) {
2255 archive ar;
2256 ar.archive_ex(e, "e");
2257 }
2258
2259 void ReShare(const lst & es) {
2260 archive ar;
2261 for(auto const & e : es) ar.archive_ex(e, "e");
2262 }
2263
2264 void ReShare(const ex & e1, const ex & e2) {
2265 archive ar;
2266 ar.archive_ex(e1, "e");
2267 ar.archive_ex(e2, "e");
2268 }
2269
2270 void ReShare(const ex & e1, const ex & e2, const ex & e3) {
2271 archive ar;
2272 ar.archive_ex(e1, "e");
2273 ar.archive_ex(e2, "e");
2274 ar.archive_ex(e3, "e");
2275 }
2276
2277 void ReShare(const exvector & ev) {
2278 archive ar;
2279 for(auto & e : ev) ar.archive_ex(e, "e");
2280 }
2281
2282 void ReShare(const exvector & ev1, const exvector & ev2) {
2283 archive ar;
2284 for(auto & e : ev1) ar.archive_ex(e, "e");
2285 for(auto & e : ev2) ar.archive_ex(e, "e");
2286 }
2287
2288 ex nextprime(const ex & n) {
2289 auto v = cln::the<cln::cl_I>(ex_to<numeric>(n).to_cl_N());
2290 return numeric(cln::nextprobprime(v));
2291 }
2292 ex nextprime(int n) {
2293 auto v = cln::the<cln::cl_I>(numeric(n).to_cl_N());
2294 return numeric(cln::nextprobprime(v));
2295 }
2296
2297 ex Rationalize(const ex & e, int dn) {
2298
2299 static MapFunction R([](const ex & e, MapFunction & self)->ex{
2300 if(is_a<numeric>(e)) {
2301 auto ne = ex_to<numeric>(e);
2302 if(ne.is_crational()) return e;
2303 auto zz = ne.to_cl_N();
2304 auto re = cln::rationalize(cln::realpart(zz));
2305 auto im = cln::rationalize(cln::imagpart(zz));
2306 return numeric(cln::complex(re,im));
2307 } else return e.map(self);
2308 });
2309
2310 if(dn>0) set_precision(dn);
2311 ex res = R(e);
2312 if(dn>0) reset_precision();
2313 return res;
2314 }
2315
2316 extern std::stack<cln::float_format_t> cln_prec_stack;
2317 extern std::stack<long> digits_stack;
2318 void set_precision(long prec, bool push) {
2319 if(push) {
2320 cln_prec_stack.push(cln::default_float_format);
2321 digits_stack.push(Digits);
2322 }
2323 Digits = prec;
2324 cln::default_float_format = cln::float_format(prec);
2325 }
2326
2328 if(cln_prec_stack.empty()) return;
2329 auto digits = digits_stack.top();
2330 auto prec = cln_prec_stack.top();
2331 Digits = digits;
2332 cln::default_float_format = prec;
2333 cln_prec_stack.pop();
2334 digits_stack.pop();
2335 }
2336
2338 return cln::default_float_format;
2339 }
2340
2341 void arg2map(int argc, char** argv, const char *optstring, std::map<char,std::string> & kv) {
2342 auto o_opterr = opterr;
2343 opterr = 0;
2344 while(true) {
2345 int opt = getopt(argc, argv, optstring);
2346 if(opt==-1) break;
2347 else if(opt!='?') {
2348 if(optarg) kv[opt] = optarg;
2349 else kv[opt] = "";
2350 }
2351 }
2352 argc -= optind;
2353 argv += optind;
2354 opterr = o_opterr;
2355 }
2356
2357 bool has_symbol(const ex & e) {
2358 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) if(is_a<symbol>(*i)) return true;
2359 return false;
2360 }
2361
2362 #include <unistd.h>
2363 string get_hostname() {
2364 char hostname[256];
2365 memset(hostname, 0, sizeof(hostname));
2366 if (gethostname(hostname, sizeof(hostname)) == 0) {
2367 return string(hostname);
2368 } else {
2369 throw Error("get_hostname error");
2370 }
2371 }
2372
2373 string get_env(const string & name) {
2374 const char* val = std::getenv(name.c_str());
2375 if(val==NULL) return string("");
2376 return string(val);
2377 }
2378
2379 ex chop(const ex & expr, const ex & err) {
2380 return MapFunction([err](const ex & e, MapFunction &self)->ex{
2381 if(is_a<numeric>(e)) {
2382 numeric ne = ex_to<numeric>(e);
2383 auto ner = real(ne);
2384 auto nei = imag(ne);
2385 if(abs(ner)<err) ner = 0;
2386 if(abs(nei)<err) nei = 0;
2387 return ner+I*nei;
2388 } else return e.map(self);
2389 })(expr);
2390 }
2391
2392}
2393
int * a
unsigned golden_ratio_hash(uintptr_t n)
Definition BASIC.cpp:9
Basic header file.
#define IMPLEMENT_HAS(classname)
Definition BASIC.h:24
#define MAGENTA
Definition BASIC.h:85
#define WHITE
Definition BASIC.h:87
#define RED
Definition BASIC.h:81
#define DEFAULT_CTOR(classname)
Definition BASIC.h:21
#define RESET
Definition BASIC.h:79
#define IMPLEMENT_ALL(classname)
Definition BASIC.h:30
class used to wrap error message
Definition BASIC.h:245
string msg
Definition BASIC.h:247
const char * what() const
Definition BASIC.cpp:24
Error(string _msg)
Error constructor,.
Definition BASIC.cpp:23
interface to communicate with Form program
Definition BASIC.h:867
string Execute(const string &script, const string &out_var="[o]")
Definition Process.cpp:271
class for Mathematica Format Output
Definition BASIC.h:890
const MMAFormat & operator<<(const T &v) const
Definition BASIC.h:895
MMAFormat(ostream &os, unsigned opt=0)
Definition BASIC.cpp:2062
class to wrap map_function of GiNaC
Definition BASIC.h:679
class to parse for string or file, helpful with Symbol class
Definition BASIC.h:692
ex Read(const string &instr, bool s2S=true)
class extended to GiNaC symbol class, represent a positive symbol
Definition BASIC.h:116
void unset() const
Definition BASIC.cpp:140
static void unset_all()
Definition BASIC.cpp:146
ex series(const relational &s, int order, unsigned options=0) const override
Definition BASIC.cpp:125
void archive(archive_node &n) const override
Symbol archive.
Definition BASIC.cpp:88
ex imag_part() const override
Definition BASIC.cpp:104
Symbol * duplicate() const override
Definition BASIC.cpp:61
bool is_equal_same_type(const basic &other) const override
Definition BASIC.cpp:113
ex conjugate() const override
Definition BASIC.cpp:102
static ex set_all(const ex &expr)
Definition BASIC.cpp:147
const char * class_name() const override
Definition BASIC.cpp:65
ex subs(const exmap &m, unsigned options=0) const override
Definition BASIC.h:148
void read_archive(const archive_node &n) override
Symbol read_archive.
Definition BASIC.cpp:96
static GiNaC::registered_class_info & get_class_info_static()
Definition BASIC.cpp:59
ex derivative(const symbol &s) const override
Definition BASIC.cpp:119
unsigned calchash() const override
Definition BASIC.cpp:105
ex evalf() const override
Definition BASIC.cpp:101
void set(const ex &v) const
Definition BASIC.cpp:139
static std::map< std::string, ex > Table
Definition BASIC.h:163
ex eval() const override
Definition BASIC.cpp:100
void set_name(string n)
Definition BASIC.cpp:137
void accept(GiNaC::visitor &v) const override
Definition BASIC.cpp:62
static exmap vmap
Definition BASIC.h:170
ex real_part() const override
Definition BASIC.cpp:103
int compare_same_type(const GiNaC::basic &other) const override
Definition BASIC.cpp:75
const GiNaC::registered_class_info & get_class_info() const override
Definition BASIC.cpp:63
XIntegral Class, preface to SecDec.
Definition BASIC.h:787
ex op(size_t i) const override
Definition BASIC.cpp:1682
int compare_same_type(const GiNaC::basic &other) const override
Definition BASIC.cpp:1663
void accept(GiNaC::visitor &v) const override
Definition BASIC.cpp:1653
XIntegral * duplicate() const override
Definition BASIC.cpp:1652
void archive(archive_node &n) const override
Definition BASIC.cpp:1696
ex & let_op(size_t i) override
Definition BASIC.cpp:1688
void print(const print_dflt &c, unsigned level=0) const
Definition BASIC.cpp:1675
void read_archive(const archive_node &n) override
Definition BASIC.cpp:1703
const char * class_name() const override
Definition BASIC.cpp:1656
static GiNaC::registered_class_info & get_class_info_static()
Definition BASIC.cpp:1650
const GiNaC::registered_class_info & get_class_info() const override
Definition BASIC.cpp:1654
size_t nops() const override
Definition BASIC.cpp:1681
class extended to GiNaC symbol class, pure imaginary symbol
Definition BASIC.h:186
bool is_equal_same_type(const basic &other) const override
Definition BASIC.cpp:188
ex eval() const override
Definition BASIC.cpp:236
ex evalf() const override
Definition BASIC.cpp:237
static std::map< std::string, ex > Table
Definition BASIC.h:233
void archive(archive_node &n) const override
Symbol archive.
Definition BASIC.cpp:224
void set_name(string n)
Definition BASIC.cpp:212
iSymbol * duplicate() const override
Definition BASIC.cpp:166
ex real_part() const override
Definition BASIC.cpp:239
ex derivative(const symbol &s) const override
Definition BASIC.cpp:194
static GiNaC::registered_class_info & get_class_info_static()
Definition BASIC.cpp:164
ex conjugate() const override
Definition BASIC.cpp:238
const char * class_name() const override
Definition BASIC.cpp:170
ex series(const relational &s, int order, unsigned options=0) const override
Definition BASIC.cpp:200
void accept(GiNaC::visitor &v) const override
Definition BASIC.cpp:167
ex imag_part() const override
Definition BASIC.cpp:240
const GiNaC::registered_class_info & get_class_info() const override
Definition BASIC.cpp:168
int compare_same_type(const GiNaC::basic &other) const override
Definition BASIC.cpp:179
void read_archive(const archive_node &n) override
Symbol read_archive.
Definition BASIC.cpp:232
unsigned calchash() const override
Definition BASIC.cpp:214
static ex sum(lst m)
sum all elements in the list
Definition BASIC.cpp:515
static lst map(const lst &m, F f)
Definition BASIC.h:273
HepLib namespace.
Definition BASIC.cpp:17
ex expand_ex(ex const &expr_in, std::function< bool(const ex &)> has_func)
the expand like Mathematica
Definition BASIC.cpp:1189
const char * Color_HighLight
Definition BASIC.cpp:248
ex exfactor(const ex &expr_in, int opt)
factorize a expression
Definition BASIC.cpp:1855
ex collect_factors(const ex &expr)
a wrapper for collect_common_factors, catch errors
Definition BASIC.cpp:1842
const int o_flint_ccf
Definition Init.cpp:114
void arg2map(int argc, char **argv, const char *optstring, std::map< char, std::string > &kv)
Definition BASIC.cpp:2341
__float128 ex2q(ex num)
ex of numeric to __float128
Definition BASIC.cpp:880
const iSymbol iEpsilon
void reset_precision()
Definition BASIC.cpp:2327
ex EvalF(ex expr)
the nuerical evaluation, Digits=100 will be used
Definition BASIC.cpp:1246
lst str2lst(const string &expr, symtab stab)
convert string to the lst, using Parser internally
Definition BASIC.cpp:694
ex exnd(const ex &expr, int opt)
num_den a expression
Definition BASIC.cpp:1936
ex form_factor(const ex &expr, bool nd=true)
Definition BASIC.h:476
const int o_flintf_ccf
Definition Init.cpp:116
lst gather_symbols(const ex &e)
get all symbols from input expression
Definition BASIC.cpp:540
void let_op_prepend(ex &ex_in, const ex item)
preppend item into expression
Definition BASIC.cpp:1336
ex EvalL(ex expr)
Definition BASIC.cpp:1257
lst xlst(int bi, int ei)
return a lst: x(bi), x(bi+1), ..., x(ei)
Definition BASIC.cpp:947
int GiNaC_Parallel_Process
Definition Init.cpp:150
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:1561
std::initializer_list< ex > init_list
Definition BASIC.h:47
ex q2ex(__float128 num)
__float128 to ex
Definition BASIC.cpp:868
bool xPositive(ex const expr)
check the expr is xPositive, i.e., each x-monomial item is postive
Definition BASIC.cpp:1291
const int o_form
Definition Init.cpp:112
const int o_fermat
Definition Init.cpp:109
pair< ex, epvec_t > inner_expand_collect(ex const &expr_in, std::function< bool(const ex &)> has_func, int depth=0)
Definition BASIC.cpp:1122
void ex2file(const ex &expr, string filename)
export expression file
Definition BASIC.cpp:846
ex normal_fermat(const ex &expr, bool dfactor)
return the normalizatied expression, using fermat_numer_denom
Definition BASIC.cpp:1832
ex NN(ex expr, int digits)
the nuerical evaluation
Definition BASIC.cpp:1279
const int o_flint
Definition Init.cpp:113
map< string, bool > GiNaC_Parallel_RM
Definition Init.cpp:155
ex factor_flint(const ex &e, bool nd=true)
const char * ErrColor
Definition BASIC.cpp:246
const Symbol ep
const int o_fermatfD
Definition Init.cpp:110
ex collect_ex(ex const &expr_in, std::function< bool(const ex &)> has_func, int opt)
the collect function like Mathematica
Definition BASIC.cpp:1203
ex EvalQ(ex expr)
Definition BASIC.cpp:1262
void garRead(const string &garfn, map< string, ex > &resMap)
garRead from file, and output in a map
Definition BASIC.cpp:592
map< string, int > GiNaC_Parallel_NB
Definition Init.cpp:154
void subs_w(exmap &repl)
Definition BASIC.cpp:2242
const int o_fermat_form
Definition Init.cpp:121
void ReShare(const ex &e)
Definition BASIC.cpp:2254
bool file_exists(string fn)
Definition BASIC.h:292
bool has_w(const ex &e)
Definition BASIC.cpp:2237
ex factor_form(const ex &expr, bool nd)
factorize a expression using FORM
Definition BASIC.cpp:2052
int GiNaC_Parallel_Level
Definition Init.cpp:149
ex series_ex(ex const &expr_in, ex const &s0, int sn0)
the series like Mathematica, include s^n
Definition BASIC.cpp:969
const char * WarnColor
Definition BASIC.cpp:247
ex str2ex(const string &expr, symtab stab)
convert string to ex expression, using Parser internally
Definition BASIC.cpp:671
lst syms(const exvector &ev)
Definition FIRE.cpp:61
ex form_eval(const ex &expr)
Definition BASIC.cpp:1942
string now(bool use_date)
date/time string
Definition BASIC.cpp:526
vector< pair< ex, ex > > epvec_t
Definition BASIC.cpp:1076
ex numer_denom_fermat(const ex &expr, bool dfactor=false)
return the numerator and denominator after normalization
Definition Fermat.cpp:23
string RunOS(const string &cmd)
run symtem command and return the output as string
Definition BASIC.cpp:572
lst add2lst(const ex &expr)
convert add to lst
Definition BASIC.cpp:922
ex w
Definition Init.cpp:93
ex fermat_normal(const ex &expr, bool dfactor=false)
Definition BASIC.h:469
const Symbol vs
int CpuCores()
return the cpu cores using OpenMP
Definition BASIC.cpp:1821
map< string, int > GiNaC_Parallel_NP
Definition Init.cpp:151
map< string, int > GiNaC_Parallel_Verb
Definition Init.cpp:152
map< string, bool > GiNaC_Parallel_ReWR
Definition Init.cpp:157
exvector lst2vec(const lst &alst)
convert lst to exvector
Definition BASIC.cpp:912
const int o_normal
Definition Init.cpp:108
ex get_op(const ex ex_in, int index1, int index2)
return index1-th.index2-th of expression
Definition BASIC.cpp:1607
vector< string > file2strvec(string filename, bool skip_empty)
read file content to string vector
Definition BASIC.cpp:810
ex file2ex(string filename)
read file content to ex
Definition BASIC.cpp:826
ex exnormal(const ex &expr, int opt)
normalize a expression
Definition BASIC.cpp:1920
const int o_flintf
Definition Init.cpp:115
const int o_flintfD_ccf
Definition Init.cpp:118
const int o_flintfD
Definition Init.cpp:117
ex EvalMP(ex expr)
Definition BASIC.cpp:1267
const int o_normal_fermat
Definition Init.cpp:119
ex nextprime(const ex &n)
Definition BASIC.cpp:2288
ex normal_flint(const ex &expr, int opt=o_flint)
ex inner_factor_form(const ex &expr)
Definition BASIC.cpp:1988
bool In_GiNaC_Parallel
Definition Init.cpp:148
lst mul2lst(const ex &expr)
convert mul to lst
Definition BASIC.cpp:934
string file2str(string filename)
read file content to string
Definition BASIC.cpp:776
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:1223
ex diff_ex(ex const expr, ex const xp, unsigned nth, bool expand)
the differential like Mathematica
Definition BASIC.cpp:1064
int Verbose
Definition Init.cpp:145
ex Rationalize(const ex &e, int dn)
Definition BASIC.cpp:2297
void string_replace_all(string &str, const string &from, const string &to)
ex exexpand(const ex &expr, int opt)
factorize a expression
Definition BASIC.cpp:1881
void garWrite(const string &garfn, const map< string, ex > &resMap)
garWrite to write the string-key map to the archive
Definition BASIC.cpp:640
void let_op_append(ex &ex_in, const ex item)
append item into expression
Definition BASIC.cpp:1325
lst vec2lst(const exvector &ev)
convert exvector to lst
Definition BASIC.cpp:903
string ex2str(const ex &expr)
convert ex to output string, the defalut printer format will be used
Definition BASIC.cpp:716
void let_op_remove_first(ex &ex_in)
remove first from expression
Definition BASIC.cpp:1356
matrix lst2mat(const lst &ls)
convert 2Dim lst to matrix
Definition BASIC.cpp:738
bool dir_exists(string dir)
Definition BASIC.h:300
void str2file(const string &ostr, string filename)
export string to a file
Definition BASIC.cpp:788
const int o_normal_form
Definition Init.cpp:120
co_epvec_t power_expand_2(const co_epvec_t &co_epv, int n)
Definition BASIC.cpp:1078
void set_precision(long prec, bool push)
Definition BASIC.cpp:2318
ex add_collect_normal(const exvector &exv, ex const &pats, int opt)
Definition BASIC.cpp:2177
ex chop(const ex &expr, const ex &err)
Definition BASIC.cpp:2379
map< string, string > GiNaC_Parallel_PRE
Definition Init.cpp:156
std::vector< std::string > split(const std::string &s, char delimiter)
split the string into serveral part, separated by the delimiter
Definition BASIC.cpp:500
int xSign(ex const expr)
the always sign for expr
Definition BASIC.cpp:1313
pair< ex, epvec_t > co_epvec_t
Definition BASIC.cpp:1077
exvector GiNaC_Parallel(int ntotal, std::function< ex(int)> f, const string &key)
GiNaC Parallel Evaluation using fork.
Definition BASIC.cpp:259
string get_hostname()
Definition BASIC.cpp:2363
void let_op_remove_last(ex &ex_in)
remove last from expression
Definition BASIC.cpp:1346
const int o_fermatN
Definition Init.cpp:111
bool has_symbol(const ex &e)
Definition BASIC.cpp:2357
std::stack< cln::float_format_t > cln_prec_stack
Definition Init.cpp:366
std::stack< long > digits_stack
Definition Init.cpp:367
string get_env(const string &name)
Definition BASIC.cpp:2373
long get_precision()
Definition BASIC.cpp:2337
ex numer_fermat(const ex &expr)
Definition Fermat.cpp:170
ex fermat_numer_denom(const ex &expr, bool dfactor=false)
Definition BASIC.h:465
string PRE
Definition Init.cpp:146
int ex2int(ex num)
ex to integer
Definition BASIC.cpp:894
ex subs(const ex &e, init_list sl)
Definition BASIC.h:51
int GiNaC_Parallel_Batch
Definition Init.cpp:153