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
250 static int GiNaC_Parallel_Level = 0; // for the internal usage only
260 exvector GiNaC_Parallel(int ntotal, std::function<ex(int)> f, const string & key) {
261 if(ntotal<1) return exvector();
262 int ec = 0;
263 int nactive = 0;
264 string exstr = "";
265 int fork_retried = 0;
266 int nproc = GiNaC_Parallel_Process;
267 if(GiNaC_Parallel_NP.find(key)!=GiNaC_Parallel_NP.end()) nproc = GiNaC_Parallel_NP[key];
268
269 bool rm = true;
270 if(GiNaC_Parallel_RM.find(key)!=GiNaC_Parallel_RM.end()) rm = GiNaC_Parallel_RM[key];
271 string pre = PRE;
272 if(GiNaC_Parallel_PRE.find(key)!=GiNaC_Parallel_PRE.end()) pre = GiNaC_Parallel_PRE[key];
273
274 int verb = Verbose;
275 if(GiNaC_Parallel_Verb.find(key)!=GiNaC_Parallel_Verb.end()) verb = GiNaC_Parallel_Verb[key];
276
277 // nproc=0, non-parallel
278 if(nproc==0) {
279 exvector ovec;
280 for(int i=0; i<ntotal; i++) ovec.push_back(f(i));
281 return exvector(std::move(ovec));
282 }
283
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();
287
288 int rc;
289 auto ppid = getpid();
290 ostringstream cmd;
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());
295
296 int nbatch = GiNaC_Parallel_Batch;
297 if(GiNaC_Parallel_NB.find(key)!=GiNaC_Parallel_NB.end()) nbatch = GiNaC_Parallel_NB[key];
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);
302
303 bool nst = (GiNaC_Parallel_Level>0);
304 pid_t npid=0, pgid;
305 if(getpgid(0)!=ppid) { // not group leader
306 if(nst) {
307 npid = fork();
308 if(npid < 0) throw Error("GiNaC_Parallel: Error (1) @ fork()");
309 if(npid!=0) goto wait_label;
310 } // else - for case in a shell script
311 if(setpgid(0,0)) {
312 if(setpgid(0,0)) throw Error("GiNaC_Parallel: setpgid(0,0) Failed.");
313 }
314 }
315
316 pgid = getpid(); // should be groud leader @ here
317 while(fork_retried<5) {
318 ec = 0;
319 exstr = "";
320 nactive = 0;
321 for(int bi=0; bi<btotal; bi++) {
322 restart: ;
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 ";
327 if(key != "") cout << Color_HighLight << key << RESET << " ";
328 cout << Color_HighLight << nbatch << "x" << RESET << "[" << (bi+1) << "/" << btotal << "] @ " << now(false) << exstr << flush;
329 }
330
331 if(fork_retried>0) { // skip when bi.*.gar exists
332 ostringstream garfn;
333 if(key == "") garfn << gp_host << ppid << "/" << bi << ".gar";
334 else garfn << gp_host << ppid << "/" << bi << "." << key << ".gar";
335 if(file_exists(garfn.str())) continue;
336 }
337
338 auto pid = fork();
339 if(pid < 0) {
340 if(getpid()!=pgid) exit(0); // make sure exit child process
341 ec++;
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--;
345 goto restart; // parent process goes next cycle
346 }
347 if(pid==0 && setpgid(0, pgid)!=0) {
348 if(setpgid(0, pgid)) throw Error("GiNaC_Parallel: setpgid(0, pgid) Failed.");
349 }
350 if(pid>0) {
351 nactive++;
352 if(nactive >= para_max_run) if(waitpid(-pgid,NULL,0)>0) nactive--;
353 continue; // parent process goes next cycle
354 }
355
356 // pid = 0, child process
357 In_GiNaC_Parallel = true;
358 GiNaC_Parallel_Level++;
359 try {
360 lst res_lst;
361 for(int ri=0; ri<nbatch; ri++) {
362 int i = bi*nbatch + ri;
363 if(i<ntotal) res_lst.append(f(i));
364 else break;
365 }
366 ostringstream garfn;
367 if(key == "") garfn << gp_host << ppid << "/" << bi << ".gar";
368 else garfn << gp_host << ppid << "/" << bi << "." << key << ".gar";
369 garWrite(garfn.str(), res_lst);
370 } catch(exception &p) { // NOT use Error
371 cout << ErrColor << "Failed in GiNaC_Parallel!" << RESET << endl;
372 cout << ErrColor << p.what() << RESET << endl;
373 }
374 exit(0);
375 }
376
377 if(getpid()!=pgid) exit(0); // make sure child exit
378 while (waitpid(-pgid,NULL,0) != -1) { }
379 if(!nst && verb > 1) cout << endl;
380 if(getpid()!=ppid) exit(0); // make the forked group leader exit
381
382 if(ec<2) break;
383 // check all *.gar and retry
384 bool all_gar_exists = true;
385 for(int bi=0; bi<btotal; bi++) {
386 ostringstream garfn;
387 if(key == "") garfn << gp_host << ppid << "/" << bi << ".gar";
388 else garfn << gp_host << ppid << "/" << bi << "." << key << ".gar";
389 if(!file_exists(garfn.str())) {
390 all_gar_exists = false;
391 break;
392 }
393 }
394 if(all_gar_exists) break;
395 para_max_run = para_max_run/2;
396 if(para_max_run<2) break;
397 fork_retried++;
398 }
399
400 wait_label:
401 if(npid!=0) waitpid(npid,NULL,0); // wait nest process to exit
402
403 //#define use_gar_write // use ReWR
404
405 exvector ovec;
406 if(true) {
407 #ifdef use_gar_write
408 exvector ovec_tmp;
409 #endif
410 for(int bi=0; bi<btotal; bi++) {
411 if(verb > 1 && !nst) {
412 if(key == "") {
413 cout << "\r \r" << pre;
414 cout << "\\--Reading *.gar [" << (bi+1) << "/" << btotal << "] @ " << now(false) << flush;
415 } else {
416 cout << "\r \r" << pre;
417 cout << "\\--Reading *." << Color_HighLight << key << RESET << ".gar [" << (bi+1) << "/" << btotal << "] @ " << now(false) << flush;
418 }
419 }
420
421 ostringstream garfn;
422 if(key == "") garfn << gp_host << ppid << "/" << bi << ".gar";
423 else garfn << gp_host << ppid << "/" << bi << "." << key << ".gar";
424 lst res_lst;
425 try {
426 if(file_exists(garfn.str())) {
427 res_lst = ex_to<lst>(garRead(garfn.str()));
428 remove(garfn.str().c_str());
429 goto done;
430 }
431 } catch(exception &p) { }
432 if(verb > 1 && !nst) cout << " - ReTry" << endl;
433 try {
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));
438 else break;
439 }
440 } catch(exception &p) {
441 cout << ErrColor << "Failed in GiNaC_Parallel!" << RESET << endl;
442 cout << ErrColor << p.what() << RESET << endl;
443 throw Error("GiNaC_Parallel_ReTRY: "+string(p.what()));
444 }
445 done: ;
446 #ifdef use_gar_write
447 if(GiNaC_Parallel_ReWR.find(key)==GiNaC_Parallel_ReWR.end() || GiNaC_Parallel_ReWR[key]) {
448 for(auto res : res_lst) ovec_tmp.push_back(res);
449 } else {
450 for(auto res : res_lst) ovec.push_back(res);
451 }
452 #else
453 for(auto res : res_lst) ovec.push_back(res);
454 #endif
455 }
456
457 #ifdef use_gar_write
458 if(!nst && verb>1) {
459 cout << endl;
460 if(key == "") {
461 cout << "\r \r" << pre;
462 cout << "\\--ReWR" << flush;
463 } else {
464 cout << "\r \r" << pre;
465 cout << "\\--ReWR " << Color_HighLight << key << RESET << flush;
466 }
467 }
468
469 if(GiNaC_Parallel_ReWR.find(key)==GiNaC_Parallel_ReWR.end() || GiNaC_Parallel_ReWR[key]) {
470 ostringstream garfn;
471 if(key == "") garfn << gp_host << ppid << "/ReWR.gar";
472 else garfn << gp_host << ppid << "/ReWR." << key << ".gar";
473 garWrite(garfn.str(), ovec_tmp);
474 ovec_tmp.clear();
475 garRead(garfn.str(), ovec);
476 }
477 #endif
478
479 if(!nst && verb>1) cout << endl;
480 }
481
482 if(rm) {
483 cmd.clear();
484 cmd.str("");
485 cmd << "rm -fr " << gp_host << ppid;
486 rc = system(cmd.str().c_str());
487 }
488 if(ovec.size() != ntotal) {
489 throw Error("GiNaC_Parallel: The output size is wrong!");
490 }
491
492 return exvector(std::move(ovec));
493 }
494
501 std::vector<std::string> split(const std::string& s, char delimiter) {
502 std::vector<std::string> tokens;
503 std::string token;
504 std::istringstream tokenStream(s);
505 while (std::getline(tokenStream, token, delimiter)) {
506 tokens.push_back(token);
507 }
508 return tokens;
509 }
510
516 ex lstHelper::sum(lst m) {
517 ex ret = 0;
518 for(int i=0; i<m.nops(); i++) ret += m.op(i);
519 return ret;
520 }
521
527 string now(bool use_date) {
528 time_t timep;
529 time (&timep);
530 char tmp[64];
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) );
533 return tmp;
534 }
535
541 lst gather_symbols(const ex & e) {
542 exset ss;
543 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) {
544 if(is_a<symbol>(*i)) ss.insert(*i);
545 }
546 lst sym_lst;
547 for(auto item : ss) sym_lst.append(item);
548 return sym_lst;
549 }
550
556 lst gather_symbols(const exvector & ve) {
557 exset ss;
558 for(auto e : ve) {
559 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) {
560 if(is_a<symbol>(*i)) ss.insert(*i);
561 }
562 }
563 lst sym_lst;
564 for(auto item : ss) sym_lst.append(item);
565 return sym_lst;
566 }
567
573 string RunOS(const string & cmd) {
574 char buf[128];
575 ostringstream oss;
576 FILE *fp = NULL;
577 if( (fp = popen(cmd.c_str(), "r")) != NULL) {
578 while(fgets(buf, 128, fp) != NULL) {
579 oss << buf;
580 }
581 pclose(fp);
582 fp = NULL;
583 }
584 return oss.str();
585 }
586
587
593 void garRead(const string &garfn, map<string, ex> &resMap) {
594 archive ar;
595 ifstream in(garfn);
596 in >> ar;
597 in.close();
598 for(int i=0; i<ar.num_expressions(); i++) {
599 string name;
600 ex res = ar.unarchive_ex(name, i);
601 resMap[name] = res;
602 }
603 }
604
611 ex garRead(const string &garfn, const char* key) { // use the const char *, not string
612 archive ar;
613 ifstream in(garfn);
614 in >> ar;
615 in.close();
616 auto res = ar.unarchive_ex(key);
617 return res;
618 }
619
625 ex garRead(const string &garfn) {
626 archive ar;
627 ifstream in(garfn);
628 in >> ar;
629 in.close();
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);
633 return res;
634 }
635
641 void garWrite(const string &garfn, const map<string, ex> &resMap) {
642 archive ar;
643 for(const auto & item : resMap) {
644 ar.archive_ex(item.second, item.first.c_str());
645 }
646 ofstream out(garfn);
647 out << ar;
648 out.close();
649 }
650
656 void garWrite(const string &garfn, const ex & res) {
657 archive ar;
658 ar.archive_ex(res, "res");
659 ar.archive_ex(19790923, "c");
660 ofstream out(garfn);
661 out << ar;
662 out.close();
663 }
664
665
672 ex str2ex(const string &expr, symtab stab) {
673 Parser par(stab);
674 ex ret = par.Read(expr);
675 return ret;
676 }
677
683 ex str2ex(const string &expr) {
684 Parser par;
685 ex ret = par.Read(expr);
686 return ret;
687 }
688
695 lst str2lst(const string &expr, symtab stab) {
696 Parser par(stab);
697 ex ret = par.Read(expr);
698 return ex_to<lst>(ret);
699 }
700
706 lst str2lst(const string &expr) {
707 Parser par;
708 ex ret = par.Read(expr);
709 return ex_to<lst>(ret);
710 }
711
717 string ex2str(const ex &expr) {
718 ostringstream oss;
719 oss << expr;
720 return oss.str();
721 }
722
728 string ex2str(const exvector &expr) {
729 ostringstream oss;
730 oss << expr;
731 return oss.str();
732 }
733
739 matrix lst2mat(const lst & ls) {
740 int nr = ls.nops();
741 int nc = ls.op(0).nops();
742 matrix mat(nr,nc);
743 for(int r=0; r<nr; r++) {
744 auto row = ls.op(r);
745 for(int c=0; c<nc; c++) mat(r,c) = row.op(c);
746 }
747 return mat;
748 }
749
755 string ex2str(const exmap &expr) {
756 ostringstream oss;
757 oss << expr;
758 return oss.str();
759 }
760
766 string ex2str(const exset &expr) {
767 ostringstream oss;
768 oss << expr;
769 return oss.str();
770 }
771
777 string file2str(string filename) {
778 ifstream ifs(filename);
779 string ostr((istreambuf_iterator<char>(ifs)), (istreambuf_iterator<char>()));
780 ifs.close();
781 return ostr;
782 }
783
789 void str2file(const string & ostr, string filename) {
790 std::ofstream ofs;
791 ofs.open(filename, ios::out);
792 ofs << ostr << flush;
793 ofs.close();
794 }
795
796 // not finished, just for memo
797 void str2file(char * buff, FILE* fh) {
798 string nstr;
799 int n = nstr.length();
800 char nbuff[n+1];
801 strcpy(nbuff, nstr.c_str());
802 FILE * f = fmemopen(nbuff, n, "r");
803 }
804
811 vector<string> file2strvec(string filename, bool skip_empty) {
812 ifstream fs(filename);
813 vector<string> ovec;
814 std::string line;
815 while (std::getline(fs, line)) {
816 if(!skip_empty || line.size()>0) ovec.push_back(line);
817 }
818 fs.close();
819 return ovec;
820 }
821
827 ex file2ex(string filename) {
828 return str2ex(file2str(filename));
829 }
830
837 ex file2ex(string filename, symtab st) {
838 return str2ex(file2str(filename), st);
839 }
840
847 void ex2file(const ex & expr, string filename) {
848 std::ofstream ofs;
849 ofs.open(filename, ios::out);
850 ofs << expr << endl;
851 ofs.close();
852 }
853
860 void ex2file(string filename, const ex & expr) {
861 ex2file(expr, filename);
862 }
863
869 ex q2ex(__float128 num) {
870 char buffer[128];
871 quadmath_snprintf(buffer, sizeof buffer, "%.36QG", num);
872 numeric ret(buffer);
873 return ret;
874 }
875
881 __float128 ex2q(ex num) {
882 ostringstream nss;
883 set_precision(40);
884 nss << num.evalf() << endl;
885 __float128 ret = strtoflt128(nss.str().c_str(), NULL);
887 return ret;
888 }
889
895 int ex2int(ex num) {
896 return ex_to<numeric>(num).to_int();
897 }
898
904 lst vec2lst(const exvector & ev) {
905 return GiNaC::lst(ev.begin(), ev.end());
906 }
907
913 exvector lst2vec(const lst & alst) {
914 exvector ret(alst.begin(), alst.end());
915 return exvector(std::move(ret));
916 }
917
923 lst add2lst(const ex & expr) {
924 if(!is_a<add>(expr)) return lst{expr};
925 lst ret;
926 for(auto item : expr) ret.append(item);
927 return ret;
928 }
929
935 lst mul2lst(const ex & expr) {
936 if(!is_a<mul>(expr)) return lst{expr};
937 lst ret;
938 for(auto item : expr) ret.append(item);
939 return ret;
940 }
941
948 lst xlst(int bi, int ei) {
949 lst ret;
950 for(int i=bi; i<=ei; i++) ret.append(x(i));
951 return ret;
952 }
953
959 lst xlst(int ei) {
960 return xlst(0, ei);
961 }
962
970 ex series_ex(ex const & expr_in, ex const &s0, int sn0) {
971 static symbol ss;
972 return series_ex(expr_in.subs(s0==ss),ss,sn0).subs(ss==s0);
973 }
974
982 ex series_ex(ex const & expr_in, symbol const &s0, int sn0) {
983 ex expr = expr_in;
984 if(!expr.has(s0)) return (sn0>=0 ? expr : 0);
985
986 exset sset;
987 expr.find(pow(s0, w), sset);
988 numeric sn_lcm = 1;
989 exmap repl1st, repl2nd;
990 for(auto pi : sset) {
991 auto sn = expand(pi.op(1));
992 if(!is_a<numeric>(sn)) {
993 ex ex1 = 0, ex2 = 0;
994 for(auto item : add2lst(sn)) {
995 if(!is_a<numeric>(item)) ex1 += item;
996 else ex2 += item;
997 }
998 sn = ex2;
999 static symbol sss;
1000 repl1st[pi] = sss * pow(s0, sn);
1001 repl2nd[sss] = pow(s0, ex1);
1002 }
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));
1007 }
1008 sn_lcm = lcm(sn_lcm, ex_to<numeric>(sn).denom());
1009 }
1010 if(expr.has(sqrt(s0))) sn_lcm = lcm(sn_lcm, numeric(2));
1011 expr = expr.subs(repl1st);
1012
1013 symbol s("s");
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));
1018
1019 auto cvs = collect_lst(expr,s);
1020 ex ret = 0;
1021 for(auto cv : cvs) {
1022 bool ok = false;
1023 int exN = 1;
1024 while(exN<10) {
1025 expr = cv.op(1) + pow(s,sn+exN+2)+pow(s,sn+exN+3);
1026 expr = expr.series(s,sn+exN);
1027 ex ot = 0;
1028 for(int i=0; i<expr.nops(); i++) {
1029 if(is_order_function(expr.op(i))) {
1030 ot = expr.op(i);
1031 break;
1032 }
1033 }
1034 if(!is_order_function(ot)) {
1035 cerr << "expr = " << expr << endl;
1036 throw Error("series_ex: Not an Order term with " + ex2str(ot));
1037 }
1038 if(ot.op(0).degree(s)>sn) {
1039 expr = series_to_poly(expr);
1040 expr = collect_ex(expr,s);
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);
1043 }
1044 ok = true;
1045 break;
1046 }
1047 exN++;
1048 }
1049 if(!ok) throw Error("series_ex seems not working!");
1050 }
1051 ret = ret.subs(s==pow(s0,ex(1)/sn_lcm)); // need this for log-terms
1052 ret = ret.subs(repl2nd);
1053 ret = collect_ex(ret,s0);
1054 return ret;
1055 }
1056
1065 ex diff_ex(ex const expr, ex const xp, unsigned nth, bool expand) {
1066 symbol s;
1067 ex res = expr.subs(xp==s);
1068 if(!expand) return res.diff(s,nth).subs(s==xp);
1069 auto cvs = collect_lst(res, s);
1070 res = 0;
1071 for(auto cv : cvs) {
1072 res += cv.op(0) * cv.op(1).diff(s,nth).subs(s==xp);
1073 }
1074 return res;
1075 }
1076
1077 typedef vector<pair<ex,ex>> epvec_t; // first-pat, second-coeff
1078 typedef pair<ex,epvec_t> co_epvec_t; // first - overall coeff
1079 co_epvec_t power_expand_2(const co_epvec_t & co_epv, int n) {
1080 if(n==1) return co_epv;
1081 else if(n==2) {
1082 ex co = pow(co_epv.first,2);
1083 exmap pcmap;
1084 if(true) {
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;
1091 }
1092 }
1093 epvec_t epv;
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));
1098 }
1099 return make_pair(co, epvec_t(std::move(epv)));
1100 }
1101 int n2 = n/2;
1102 auto co_epv2 = power_expand_2(co_epv, n2);
1103 co_epv2 = power_expand_2(co_epv2, 2);
1104 if((n % 2)==0) return co_epvec_t(std::move(co_epv2));
1105
1106 ex co = co_epv.first * co_epv2.first;
1107 exmap pcmap;
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;
1111 }
1112 for(auto ep2 : co_epv2.second) pcmap[ep2.first] += ep2.second * co_epv.first;
1113
1114 epvec_t epv;
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));
1119 }
1120 return make_pair(co, epvec_t(std::move(epv)));
1121 }
1122
1123 pair<ex,epvec_t> inner_expand_collect(ex const &expr_in, std::function<bool(const ex &)> has_func, int depth=0) {
1124 if(!has_func(expr_in)) {
1125 ex co;
1126 epvec_t epv;
1127 co = expr_in;
1128 return make_pair(co,epv);
1129 } if(is_a<add>(expr_in)) {
1130 ex co = 0;
1131 exmap pcmap;
1132 for(auto item : expr_in) {
1133 if(has_func(item)) {
1134 auto co_epv = inner_expand_collect(item, has_func, depth+1);
1135 co += co_epv.first;
1136 for(auto ep : co_epv.second) pcmap[ep.first] += ep.second;
1137 } else co += item;
1138 }
1139 epvec_t epv;
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));
1144 }
1145 return make_pair(co, epvec_t(std::move(epv)));
1146 } else if(is_a<mul>(expr_in)) {
1147 ex co = 1;
1148 epvec_t epv;
1149 for(auto item : expr_in) {
1150 if(!has_func(item)) {
1151 for(auto & ep : epv) ep.second *= item;
1152 co *= item;
1153 } else {
1154 exmap pcmap;
1155 auto co_epv = inner_expand_collect(item, has_func, depth+1);
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;
1159 }
1160 for(auto ep1 : epv) pcmap[ep1.first] += ep1.second * co_epv.first;
1161 co *= co_epv.first;
1162 epv.clear();
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));
1167 }
1168 }
1169 }
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();
1173 auto co_epv = inner_expand_collect(expr_in.op(0), has_func, depth+1);
1174 return power_expand_2(co_epv,n);
1175 } else {
1176 ex co = 0;
1177 epvec_t epv;
1178 epv.push_back(make_pair(expr_in, 1));
1179 return make_pair(co,epvec_t(std::move(epv)));
1180 }
1181 throw Error("inner_expand_collect unexpected region reached.");
1182 }
1183
1190 ex expand_ex(ex const &expr_in, std::function<bool(const ex &)> has_func) {
1191 auto co_epv = inner_expand_collect(expr_in, has_func, 0);
1192 ex ret = co_epv.first;
1193 for(auto ep : co_epv.second) ret += ep.second * ep.first;
1194 return ret;
1195 }
1196
1204 ex collect_ex(ex const &expr_in, std::function<bool(const ex &)> has_func, int opt) {
1205 auto cvs = collect_lst(expr_in, has_func, opt);
1206 exvector res_vec;
1207 res_vec.reserve(cvs.nops());
1208 for(auto cv : cvs) {
1209 auto cc = cv.op(0);
1210 auto vv = cv.op(1);
1211 if(cc.is_zero() || vv.is_zero()) continue;
1212 res_vec.push_back(cc * vv);
1213 }
1214 return add(res_vec);
1215 }
1216
1224 lst collect_lst(ex const &expr_in, std::function<bool(const ex &)> has_func, int opt) {
1225 auto co_epv = inner_expand_collect(expr_in, has_func);
1226 ex cf = co_epv.first;
1227 lst res_lst;
1228 if(!is_zero(cf)) co_epv.second.push_back(make_pair(1,cf));
1229 for(auto ep : co_epv.second) {
1230 ex vv = ep.first;
1231 ex cc = ep.second;
1232 if(opt==o_normal || opt==o_fermat || opt==o_fermatfD || opt==o_fermatN || opt==o_flint || opt==o_flintf || opt==o_flintfD) cc = exnormal(cc,opt);
1233 else if(opt==o_form) cc = exfactor(cc,opt);
1234 else if(opt==o_normal_fermat) cc = exnormal(normal(cc),o_fermat);
1235 else if(opt==o_normal_form) cc = form_factor(normal(cc),o_fermat);
1236 else if(opt==o_fermat_form) cc = form_factor(fermat_normal(cc),o_fermat);
1237 if(!is_zero(cc)) res_lst.append(lst{cc, vv});
1238 }
1239 return res_lst;
1240 }
1241
1247 ex EvalF(ex expr) {
1248 exset zs;
1249 //patterns needing evalf()
1250 expr.find(zeta(w), zs);
1251 expr.find(zeta(w,w), zs);
1252
1253 lst repl;
1254 for(auto zi : zs) repl.append(zi==NN(zi));
1255 return expr.subs(repl);
1256 }
1257
1258 ex EvalL(ex expr) {
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));
1262 }
1263 ex EvalQ(ex expr) {
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));
1267 }
1268 ex EvalMP(ex expr) {
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));
1272 }
1273
1280 ex NN(ex expr, int digits) {
1281 set_precision(digits);
1282 auto nexpr = evalf(expr);
1284 return nexpr;
1285 }
1286
1292 bool xPositive(ex const expr) {
1293 auto tmp = expand(expr);
1294 if(tmp.is_zero()) return false;
1295 bool ret = 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;
1300 }
1301 ret = true;
1302 } else {
1303 auto ntmp = NN(tmp.subs(x(w)==1).normal());
1304 ret = (is_a<numeric>(ntmp) && ntmp>0);
1305 }
1306 return ret;
1307 }
1308
1314 int xSign(ex const expr) {
1315 if(is_zero(expr)) return 0;
1316 if(xPositive(expr)) return 1;
1317 else if(xPositive(ex(0)-expr)) return -1;
1318 else return 0;
1319 }
1320
1326 void let_op_append(ex & ex_in, const ex item) {
1327 auto tmp = ex_to<lst>(ex_in);
1328 tmp.append(item);
1329 ex_in = tmp;
1330 }
1331
1337 void let_op_prepend(ex & ex_in, const ex item) {
1338 auto tmp = ex_to<lst>(ex_in);
1339 tmp.prepend(item);
1340 ex_in = tmp;
1341 }
1342
1347 void let_op_remove_last(ex & ex_in) {
1348 auto tmp = ex_to<lst>(ex_in);
1349 tmp.remove_last();
1350 ex_in = tmp;
1351 }
1352
1357 void let_op_remove_first(ex & ex_in) {
1358 auto tmp = ex_to<lst>(ex_in);
1359 tmp.remove_first();
1360 ex_in = tmp;
1361 }
1362
1369 void let_op_append(ex & ex_in, int index, ex const item) {
1370 auto tmp = ex_to<lst>(ex_in.op(index));
1371 tmp.append(item);
1372 ex_in[index] = tmp;
1373 }
1374
1381 void let_op_append(lst & ex_in, int index, ex const item) {
1382 auto tmp = ex_to<lst>(ex_in.op(index));
1383 tmp.append(item);
1384 ex_in[index] = tmp;
1385 }
1386
1394 void let_op_append(ex & ex_in, int index1, int index2, ex const item) {
1395 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1396 tmp.append(item);
1397 ex_in[index1][index2] = tmp;
1398 }
1399
1407 void let_op_append(lst & ex_in, int index1, int index2, ex const item) {
1408 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1409 tmp.append(item);
1410 ex_in[index1][index2] = tmp;
1411 }
1412
1419 void let_op_prepend(ex & ex_in, int index, ex const item) {
1420 auto tmp = ex_to<lst>(ex_in.op(index));
1421 tmp.prepend(item);
1422 ex_in[index] = tmp;
1423 }
1424
1431 void let_op_prepend(lst & ex_in, int index, ex const item) {
1432 auto tmp = ex_to<lst>(ex_in.op(index));
1433 tmp.prepend(item);
1434 ex_in[index] = tmp;
1435 }
1436
1444 void let_op_prepend(ex & ex_in, int index1, int index2, ex const item) {
1445 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1446 tmp.prepend(item);
1447 ex_in[index1][index2] = tmp;
1448 }
1449
1457 void let_op_prepend(lst & ex_in, int index1, int index2, ex const item) {
1458 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1459 tmp.prepend(item);
1460 ex_in[index1][index2] = tmp;
1461 }
1462
1468 void let_op_remove_last(ex & ex_in, int index) {
1469 auto tmp = ex_to<lst>(ex_in.op(index));
1470 tmp.remove_last();
1471 ex_in[index] = tmp;
1472 }
1473
1479 void let_op_remove_last(lst & ex_in, int index) {
1480 auto tmp = ex_to<lst>(ex_in.op(index));
1481 tmp.remove_last();
1482 ex_in[index] = tmp;
1483 }
1484
1491 void let_op_remove_last(ex & ex_in, int index1, int index2) {
1492 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1493 tmp.remove_last();
1494 ex_in[index1][index2] = tmp;
1495 }
1496
1503 void let_op_remove_last(lst & ex_in, int index1, int index2) {
1504 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1505 tmp.remove_last();
1506 ex_in[index1][index2] = tmp;
1507 }
1508
1514 void let_op_remove_first(ex & ex_in, int index) {
1515 auto tmp = ex_to<lst>(ex_in.op(index));
1516 tmp.remove_first();
1517 ex_in[index] = tmp;
1518 }
1519
1525 void let_op_remove_first(lst & ex_in, int index) {
1526 auto tmp = ex_to<lst>(ex_in.op(index));
1527 tmp.remove_first();
1528 ex_in[index] = tmp;
1529 }
1530
1537 void let_op_remove_first(ex & ex_in, int index1, int index2) {
1538 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1539 tmp.remove_first();
1540 ex_in[index1][index2] = tmp;
1541 }
1542
1549 void let_op_remove_first(lst & ex_in, int index1, int index2) {
1550 auto tmp = ex_to<lst>(ex_in.op(index1).op(index2));
1551 tmp.remove_first();
1552 ex_in[index1][index2] = tmp;
1553 }
1554
1562 void let_op(ex &ex_in, int index1, int index2, const ex item) {
1563 ex_in[index1][index2] = item;
1564 }
1565
1573 void let_op(lst &ex_in, int index1, int index2, const ex item) {
1574 ex_in[index1][index2] = item;
1575 }
1576
1585 void let_op(ex &ex_in, int index1, int index2, int index3, const ex item) {
1586 ex_in[index1][index2][index3] = item;
1587 }
1588
1597 void let_op(lst &ex_in, int index1, int index2, int index3, const ex item) {
1598 ex_in[index1][index2][index3] = item;
1599 }
1600
1608 ex get_op(const ex ex_in, int index1, int index2) {
1609 return ex_in.op(index1).op(index2);
1610 }
1611
1619 ex get_op(const lst ex_in, int index1, int index2) {
1620 return ex_in.op(index1).op(index2);
1621 }
1622
1631 ex get_op(const ex ex_in, int index1, int index2, int index3) {
1632 return ex_in.op(index1).op(index2).op(index3);
1633 }
1634
1643 ex get_op(const lst ex_in, int index1, int index2, int index3) {
1644 return ex_in.op(index1).op(index2).op(index3);
1645 }
1646
1647 //-----------------------------------------------------------
1648 // XIntegral Class
1649 //-----------------------------------------------------------
1650 //GINAC_IMPLEMENT_REGISTERED_CLASS_OPT(XIntegral, basic,print_func<print_dflt>(&XIntegral::print))
1651 GiNaC::registered_class_info & XIntegral::get_class_info_static() { return reg_info; }
1653 XIntegral * XIntegral::duplicate() const { XIntegral * bp = new XIntegral(*this); bp->setflag(GiNaC::status_flags::dynallocated); return bp; }
1654 void XIntegral::accept(GiNaC::visitor & v) const { if (visitor *p = dynamic_cast<visitor *>(&v)) p->visit(*this); else inherited::accept(v); }
1655 const GiNaC::registered_class_info &XIntegral::get_class_info() const { return get_class_info_static(); }
1656 GiNaC::registered_class_info &XIntegral::get_class_info() { return get_class_info_static(); }
1657 const char *XIntegral::class_name() const { return get_class_info_static().options.get_name(); }
1658 //GINAC_IMPLEMENT_REGISTERED_CLASS END
1659
1663
1664 int XIntegral::compare_same_type(const basic &other) const {
1665 if(!is_a<XIntegral>(other)) throw Error("XIntegral::compare_same_type");
1666 const XIntegral &o = static_cast<const XIntegral &>(other);
1667 auto c = Function.compare(o.Function);
1668 if(c!=0) return c;
1669 c = Exponent.compare(o.Exponent);
1670 if(c!=0) return c;
1671 c = Deltas.compare(o.Deltas);
1672 if(c!=0) return c;
1673 return 0;
1674 }
1675
1676 void XIntegral::print(const print_dflt &c, unsigned level) const {
1677 c.s << "[∬" << "(" << Function << ")^(" << Exponent << ")";
1678 if(Deltas.nops()>0) c.s << "*𝜹(" << Deltas << ")";
1679 c.s << "]";
1680 }
1681
1682 size_t XIntegral::nops() const { return 3; }
1683 ex XIntegral::op(size_t i) const {
1684 if(i==0) return Function;
1685 else if(i==1) return Exponent;
1686 else if(i==2) return Deltas;
1687 else throw Error("XIntegral::op, It is required that i<3.");
1688 }
1689 ex & XIntegral::let_op(size_t i) {
1690 ensure_if_modifiable();
1691 if(i==0) return Function;
1692 else if(i==1) return Exponent;
1693 else if(i==2) return Deltas;
1694 else throw Error("XIntegral::let_op, It is required that i<3.");
1695 }
1696
1697 void XIntegral::archive(archive_node & n) const {
1698 inherited::archive(n);
1699 n.add_ex("Function", Function);
1700 n.add_ex("Exponent", Exponent);
1701 n.add_ex("Deltas", Deltas);
1702 }
1703
1704 void XIntegral::read_archive(const archive_node& n) {
1705 inherited::read_archive(n);
1706 n.find_ex("Function", Function);
1707 n.find_ex("Exponent", Exponent);
1708 n.find_ex("Deltas", Deltas);
1709 }
1710
1712 Function = fed.op(0);
1713 Exponent = fed.op(1);
1714 if(fed.nops()>2) Deltas = fed.op(2);
1715 }
1716
1717 XIntegral::XIntegral(ex loops, ex ps, ex ns) {
1718 ex a = 0;
1719 ex pre = 1;
1720 ex rem = 0;
1721 lst delta;
1722 int xni = 0;
1723 lst funs, exps;
1724 for(int i=0; i<ps.nops(); i++) {
1725 if(is_zero(ns.op(i))) continue;
1726 auto cpi = Symbol::set_all(ps.op(i).expand());
1727 bool ltQ = false;
1728 for(auto li : loops) {
1729 if(cpi.has(li)) {
1730 ltQ = true;
1731 break;
1732 }
1733 }
1734
1735 ex sgn = 0;
1736 if(!ltQ) {
1737 pre *= pow(Symbol::set_all(ps.op(i).expand()), ex(0)-ns.op(i));
1738 ns[i] = 0;
1739 ps[i] = 1;
1740 continue;
1741 } else if(is_a<numeric>(ns.op(i)) && (ns.op(i)<0)) {
1742 throw Error("XIntegral, negative powers not supported yet.");
1743 }
1744
1745 // check loop^2
1746 for(auto li : loops) {
1747 if(!is_a<numeric>(cpi.coeff(li,2))) continue; // TODO: make sure positive
1748 numeric nm = ex_to<numeric>(cpi.coeff(li,2));
1749 if(nm.is_zero()) continue;
1750 sgn = nm>0 ? -1 : 1;
1751 break;
1752 }
1753 // check iEpsilon
1754 if(sgn.is_zero()) {
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;
1758 }
1759 // others
1760 if(sgn.is_zero()) {
1761 sgn = 1;
1762 if(is_a<numeric>(cpi) && ex_to<numeric>(cpi)>0) sgn = -1;
1763 else sgn = 1;
1764 }
1765
1766 cpi = (ps.op(i)*sgn).subs(iEpsilon==0);
1767 if(sgn==-1) pre *= exp(I * Pi * ns.op(i)); // sgn<0: +iep, sgn>0: -iep, so I*Pi here
1768 a += ns.op(i);
1769 auto xi = x(xni);
1770 rem += xi * cpi;
1771 delta.append(xi);
1772 if(!is_zero(ns.op(i)-1)) {
1773 funs.append(xi);
1774 exps.append(ns.op(i)-1);
1775 }
1776 pre /= tgamma(ns.op(i));
1777 xni++;
1778 }
1779 rem = Symbol::set_all(rem.expand());
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));
1782
1783 // Loop
1784 ex u=1;
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);
1789 u *= (-t2);
1790 if(t2==0) {
1791 Function = lst{0};
1792 Exponent = lst{1};
1793 return;
1794 }
1795 rem = (t0 - pow(t1,2)/(4*t2)).expand();
1796 }
1797 rem = Symbol::set_all(rem).normal();
1798 u = Symbol::set_all(u).normal();
1799 rem = (rem * u).normal();
1800
1801 funs.prepend(rem);
1802 exps.prepend(dl2-a);
1803 funs.prepend(u);
1804 exps.prepend(a-dl2-(4-2*ep)/2);
1805 auto num_den = numer_denom(pre);
1806 funs.append(num_den.op(0));
1807 exps.append(1);
1808 if(!is_zero(num_den.op(1))) {
1809 funs.append(num_den.op(1));
1810 exps.append(-1);
1811 }
1812
1813 Function = funs;
1814 Exponent = exps;
1815 Deltas = lst{delta};
1816 }
1817
1822 int CpuCores() {
1823 return omp_get_num_procs();
1824 }
1825
1826
1833 ex normal_fermat(const ex & expr, bool dfactor) {
1834 auto nd = fermat_numer_denom(expr, dfactor);
1835 return nd.op(0)/nd.op(1);
1836 }
1837
1843 ex collect_factors(const ex & expr) {
1844 try {
1845 return collect_common_factors(expr);
1846 } catch(...) { }
1847 return expr;
1848 }
1849
1856 ex exfactor(const ex & expr_in, int opt) {
1857 // replace Symbol
1858 auto syms = gather_symbols(expr_in);
1859 exmap subs1, subs2;
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);
1864 }
1865 ex expr = expr_in.subs(subs1);
1866
1867 if(opt==o_form) expr = factor_form(expr);
1868 else if(opt==o_flint || opt==o_flintf) expr = factor_flint(expr);
1869
1870 return expr.subs(subs2); // replace back
1871 }
1872
1879 ex exexpand(const ex & expr, int opt) {
1880 if(opt==1) return expand(expr);
1881 else return expand(expr);
1882 }
1883
1884 namespace {
1885 exvector ev_fermat_pern(const exvector & ev, int np) {
1886 if(ev.size()<np) return ev;
1887 int tn = ev.size();
1888 exvector evs;
1889 int ci = 0;
1890 while(ci<tn) {
1891 ex sum = 0;
1892 for(int i=0; i<np; i++) {
1893 sum += ev[ci];
1894 ci++;
1895 if(ci==tn) break;
1896 }
1897 ex tt = normal_fermat(sum);
1898 evs.push_back(tt);
1899 }
1900 return exvector(std::move(evs));
1901 }
1902
1903 ex normal_fermat_pern(const ex & e, int np) {
1904 if(!is_a<add>(e)) return normal_fermat(e);
1905 exvector evs(e.begin(), e.end());
1906 while(evs.size()>np) evs = ev_fermat_pern(evs,np);
1907 ex res = normal_fermat(add(evs));
1908 return res;
1909 }
1910 }
1911
1918 ex exnormal(const ex & expr, int opt) {
1919 if(opt<0) return normal_fermat_pern(expr,-opt);
1920 else if(opt==o_normal) return normal(expr);
1921 else if(opt==o_fermat) return normal_fermat(expr);
1922 else if(opt==o_flint || opt==o_flintf || opt==o_flintfD) return normal_flint(expr, opt);
1923 else if(opt==o_fermatfD) return normal_fermat(expr,true);
1924 else if(opt==o_fermatN) return numer_fermat(expr);
1925 return expr;
1926 }
1927
1934 ex exnd(const ex & expr, int opt) {
1935 if(opt==1) return numer_denom(factor_form(expr));
1936 else if(opt==2) return numer_denom_fermat(expr);
1937 else return numer_denom(expr);
1938 }
1939
1940 ex form_eval(const ex & expr) {
1941 static map<pid_t, Form> form_map;
1942 auto pid = getpid();
1943 if((form_map.find(pid)==form_map.end())) { // init section
1944 ostringstream ss;
1945 ss << "AutoDeclare Symbols fv;" << endl;
1946 form_map[pid].Init("form");
1947 form_map[pid].Execute(ss.str());
1948 }
1949 Form &fprc = form_map[pid];
1950
1951 auto expr_in = expr;
1952 exmap map_rat;
1953 expr_in = expr_in.to_polynomial(map_rat);
1954
1955 exset vs;
1956 for(const_preorder_iterator i = expr_in.preorder_begin(); i != expr_in.preorder_end(); ++i) {
1957 auto e = (*i);
1958 if(is_a<symbol>(e)) vs.insert(e);
1959 }
1960
1961 exmap s2v;
1962 symtab st;
1963 int cid = 0;
1964 for(auto ss : vs) {
1965 cid++;
1966 string cvv = "fv"+to_string(cid);
1967 s2v[ss] = Symbol(cvv);
1968 st[cvv] = ss.subs(map_rat);
1969 }
1970 ostringstream oss;
1971 expr_in = expr_in.subs(s2v);
1972 oss << "Local ff = " << expr_in << ";" << endl;
1973 oss << ".sort" << endl;
1974 try {
1975 auto ostr = fprc.Execute(oss.str(), "ff");
1976 Parser fp(st);
1977 ex ret = fp.Read(ostr);
1978 return ret;
1979 } catch(Error& err) {
1980 cout << oss.str() << endl;
1981 form_map.erase(pid);
1982 throw;
1983 }
1984 }
1985
1986 ex inner_factor_form(const ex & expr) {
1987 if(is_a<mul>(expr)) {
1988 ex res = 1;
1989 for(auto item : expr) res *= inner_factor_form(item);
1990 return res;
1991 }
1992 static map<pid_t, Form> form_map;
1993 auto pid = getpid();
1994 if((form_map.find(pid)==form_map.end())) { // init section
1995 ostringstream ss;
1996 ss << "AutoDeclare Symbols fv;" << endl;
1997 form_map[pid].Init("form");
1998 form_map[pid].Execute(ss.str());
1999 }
2000 Form &fprc = form_map[pid];
2001
2002 auto expr_in = expr;
2003 exmap map_rat;
2004 expr_in = expr_in.to_polynomial(map_rat);
2005
2006 exset vs;
2007 for(const_preorder_iterator i = expr_in.preorder_begin(); i != expr_in.preorder_end(); ++i) {
2008 auto e = (*i);
2009 if(is_a<symbol>(e)) vs.insert(e);
2010 }
2011
2012 exmap s2v;
2013 symtab st;
2014 int cid = 0;
2015 for(auto ss : vs) {
2016 cid++;
2017 string cvv = "fv"+to_string(cid);
2018 s2v[ss] = Symbol(cvv);
2019 st[cvv] = ss.subs(map_rat);
2020 }
2021 ostringstream oss;
2022 expr_in = expr_in.subs(s2v);
2023 oss << "Local ff = " << expr_in << ";" << endl;
2024 oss << "Factorize ff;" << endl;
2025 oss << ".sort" << endl;
2026 try {
2027 auto ostr = fprc.Execute(oss.str(), "ff");
2028 string_replace_all(ostr, "[", "(");
2029 string_replace_all(ostr, "]", ")");
2030 string_replace_all(ostr, "\\\n", "");
2031 string_replace_all(ostr, " ","");
2032 Parser fp(st);
2033 ex ret = fp.Read(ostr);
2034 ex res = 1;
2035 Symbol sfac("factor_");
2036 for(auto item : add2lst(ret)) res *= item.subs(sfac==1);
2037 return res;
2038 } catch(Error& err) {
2039 cout << oss.str() << endl;
2040 form_map.erase(pid);
2041 throw;
2042 }
2043 }
2044
2050 ex factor_form(const ex & expr, bool nd) {
2051 if(!nd) return inner_factor_form(expr);
2052 auto num_den = fermat_numer_denom(expr);
2053 if(is_zero(num_den.op(1)-1)) return inner_factor_form(num_den.op(0));
2054 return inner_factor_form(num_den.op(0))/inner_factor_form(num_den.op(1));
2055 }
2056
2057 //-----------------------------------------------------------
2058 // MMAFormat Output
2059 //-----------------------------------------------------------
2060 MMAFormat::MMAFormat(ostream &os, unsigned opt) : print_dflt(os, opt) {}
2061 MMAFormat::MMAFormat() : print_dflt(std::cout) {}
2062 GINAC_IMPLEMENT_PRINT_CONTEXT(MMAFormat, print_dflt)
2063
2064 const MMAFormat & MMAFormat::operator << (const basic & v) const {
2065 v.print(*this);
2066 return *this;
2067 }
2068 const MMAFormat & MMAFormat::operator << (const ex & v) const {
2069 v.print(*this);
2070 return *this;
2071 }
2072 const MMAFormat & MMAFormat::operator << (const lst & v) const {
2073 v.print(*this);
2074 return *this;
2075 }
2076 const MMAFormat & MMAFormat::operator<<(std::ostream& (*v)(std::ostream&)) const {
2077 s << v;
2078 return *this;
2079 }
2080
2081 const MMAFormat & MMAFormat::operator << (const matrix & mat) const {
2082 s << "{";
2083 int nr = mat.rows();
2084 int nc = mat.cols();
2085 for(int r=0; r<nr; r++) {
2086 s << "{";
2087 for(int c=0; c<nc; c++) {
2088 mat(r,c).print(*this);
2089 if(c+1!=nc) s << ",";
2090 }
2091 s << "}";
2092 if(r+1!=nr) s << ",";
2093 }
2094 s << "}";
2095 return *this;
2096 }
2097
2098 const MMAFormat & MMAFormat::operator << (const exvector & e) const {
2099 auto i = e.begin();
2100 auto vend = e.end();
2101 if (i==vend) { s << "{}"; return *this; }
2102 s << "{";
2103 while (true) {
2104 i->print(*this);
2105 ++i;
2106 if(i==vend) break;
2107 s << ",";
2108 }
2109 s << "}";
2110 return *this;
2111 }
2112
2113 const MMAFormat & MMAFormat::operator << (const exset & e) const {
2114 auto i = e.begin();
2115 auto send = e.end();
2116 if (i==send) { s << "{}"; return *this; }
2117 s << "{";
2118 while (true) {
2119 i->print(*this);
2120 ++i;
2121 if(i==send) break;
2122 s << ",";
2123 }
2124 s << "}";
2125 return *this;
2126 }
2127
2128 const MMAFormat & MMAFormat::operator << (const exmap & e) const {
2129 auto i = e.begin();
2130 auto mend = e.end();
2131 if (i==mend) { s << "{}"; return *this; }
2132 s << "{";
2133 while (true) {
2134 i->first.print(*this);
2135 s << "->";
2136 i->second.print(*this);
2137 ++i;
2138 if(i==mend) break;
2139 s << ",";
2140 }
2141 s << "}";
2142 return *this;
2143 }
2144
2145 void garWrite(const exvector &exv, string garfn) {
2146 archive ar;
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());
2150 }
2151 ofstream out(garfn);
2152 out << ar;
2153 out.close();
2154 }
2155
2156 void garRead(exvector &exv, string garfn) {
2157 archive ar;
2158 ifstream in(garfn);
2159 in >> ar;
2160 in.close();
2161
2162 map<string, ex> dict;
2163 for(int i=0; i<ar.num_expressions(); i++) {
2164 string name;
2165 ex res = ar.unarchive_ex(name, i);
2166 dict[name] = res;
2167 }
2168
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)];
2173 }
2174
2175 ex add_collect_normal(const exvector &exv, ex const &pats, int opt) {
2176 auto cvs_vec = GiNaC_Parallel(exv.size(), [&exv,pats](int idx)->ex {
2177 return collect_lst(exv[idx], pats);
2178 }, "ColEx");
2179 exmap res_map;
2180 for(auto cvs : cvs_vec) for(auto cv : cvs) res_map[cv.op(1)] += cv.op(0);
2181 exvector res_vec;
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);
2185 }, "NorEx");
2186 return add(res_vec);
2187 }
2188
2189 ex add_collect_normal(const exvector &exv, init_list const &pats, int opt) {
2190 auto cvs_vec = GiNaC_Parallel(exv.size(), [&exv,pats](int idx)->ex {
2191 return collect_lst(exv[idx], pats);
2192 }, "ColEx");
2193 exmap res_map;
2194 for(auto cvs : cvs_vec) for(auto cv : cvs) res_map[cv.op(1)] += cv.op(0);
2195 exvector res_vec;
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);
2199 }, "NorEx");
2200 return add(res_vec);
2201 }
2202
2203 ex add_collect_normal(const exvector &exv, lst const &pats, int opt) {
2204 auto cvs_vec = GiNaC_Parallel(exv.size(), [&exv,pats](int idx)->ex {
2205 return collect_lst(exv[idx], pats);
2206 }, "ColEx");
2207 exmap res_map;
2208 for(auto cvs : cvs_vec) for(auto cv : cvs) res_map[cv.op(1)] += cv.op(0);
2209 exvector res_vec;
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);
2213 }, "NorEx");
2214 return add(res_vec);
2215 }
2216
2217 ex add_collect_normal(const ex & e, ex const &pats, int opt) {
2218 if(!is_a<add>(e)) throw Error("add_collect_normal: input is NOT a add class.");
2219 exvector exv(e.begin(), e.end());
2220 return add_collect_normal(exv, pats, opt);
2221 }
2222
2223 ex add_collect_normal(const ex & e, lst const &pats, int opt) {
2224 if(!is_a<add>(e)) throw Error("add_collect_normal: input is NOT a add class.");
2225 exvector exv(e.begin(), e.end());
2226 return add_collect_normal(exv, pats, opt);
2227 }
2228
2229 ex add_collect_normal(const ex & e, init_list const &pats, int opt) {
2230 if(!is_a<add>(e)) throw Error("add_collect_normal: input is NOT a add class.");
2231 exvector exv(e.begin(), e.end());
2232 return add_collect_normal(exv, pats, opt);
2233 }
2234
2235 bool has_w(const ex & e) {
2236 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) if(is_a<wildcard>(*i)) return true;
2237 return false;
2238 }
2239
2240 void subs_w(exmap & repl) {
2241 auto r = repl;
2242 for(auto kv : r) if(is_a<mul>(kv.first) && !has_w(kv.first)) repl[w*kv.first]=w*kv.second;
2243 }
2244
2245 void subs_w(lst & repl) {
2246 auto r = repl;
2247 for(auto item : r) if(is_a<mul>(item) && !has_w(item)) repl.append(w*item.op(0)==w*item.op(1));
2248 repl.sort();
2249 repl.unique();
2250 }
2251
2252 void ReShare(const ex & e) {
2253 archive ar;
2254 ar.archive_ex(e, "e");
2255 }
2256
2257 void ReShare(const lst & es) {
2258 archive ar;
2259 for(auto const & e : es) ar.archive_ex(e, "e");
2260 }
2261
2262 void ReShare(const ex & e1, const ex & e2) {
2263 archive ar;
2264 ar.archive_ex(e1, "e");
2265 ar.archive_ex(e2, "e");
2266 }
2267
2268 void ReShare(const ex & e1, const ex & e2, const ex & e3) {
2269 archive ar;
2270 ar.archive_ex(e1, "e");
2271 ar.archive_ex(e2, "e");
2272 ar.archive_ex(e3, "e");
2273 }
2274
2275 void ReShare(const exvector & ev) {
2276 archive ar;
2277 for(auto & e : ev) ar.archive_ex(e, "e");
2278 }
2279
2280 void ReShare(const exvector & ev1, const exvector & ev2) {
2281 archive ar;
2282 for(auto & e : ev1) ar.archive_ex(e, "e");
2283 for(auto & e : ev2) ar.archive_ex(e, "e");
2284 }
2285
2286 ex nextprime(const ex & n) {
2287 auto v = cln::the<cln::cl_I>(ex_to<numeric>(n).to_cl_N());
2288 return numeric(cln::nextprobprime(v));
2289 }
2290 ex nextprime(int n) {
2291 auto v = cln::the<cln::cl_I>(numeric(n).to_cl_N());
2292 return numeric(cln::nextprobprime(v));
2293 }
2294
2295 ex Rationalize(const ex & e, int dn) {
2296
2297 static MapFunction R([](const ex & e, MapFunction & self)->ex{
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);
2306 });
2307
2308 if(dn>0) set_precision(dn);
2309 ex res = R(e);
2310 if(dn>0) reset_precision();
2311 return res;
2312 }
2313
2314 extern std::stack<cln::float_format_t> cln_prec_stack;
2315 extern std::stack<long> digits_stack;
2316 void set_precision(long prec, bool push) {
2317 if(push) {
2318 cln_prec_stack.push(cln::default_float_format);
2319 digits_stack.push(Digits);
2320 }
2321 Digits = prec;
2322 cln::default_float_format = cln::float_format(prec);
2323 }
2324
2326 if(cln_prec_stack.empty()) return;
2327 auto digits = digits_stack.top();
2328 auto prec = cln_prec_stack.top();
2329 Digits = digits;
2330 cln::default_float_format = prec;
2331 cln_prec_stack.pop();
2332 digits_stack.pop();
2333 }
2334
2336 return cln::default_float_format;
2337 }
2338
2339 void arg2map(int argc, char** argv, const char *optstring, std::map<char,std::string> & kv) {
2340 auto o_opterr = opterr;
2341 opterr = 0;
2342 while(true) {
2343 int opt = getopt(argc, argv, optstring);
2344 if(opt==-1) break;
2345 else if(opt!='?') {
2346 if(optarg) kv[opt] = optarg;
2347 else kv[opt] = "";
2348 }
2349 }
2350 argc -= optind;
2351 argv += optind;
2352 opterr = o_opterr;
2353 }
2354
2355 bool has_symbol(const ex & e) {
2356 for(const_preorder_iterator i = e.preorder_begin(); i != e.preorder_end(); ++i) if(is_a<symbol>(*i)) return true;
2357 return false;
2358 }
2359
2360 #include <unistd.h>
2361 string get_hostname() {
2362 char hostname[256];
2363 memset(hostname, 0, sizeof(hostname));
2364 if (gethostname(hostname, sizeof(hostname)) == 0) {
2365 return string(hostname);
2366 } else {
2367 throw Error("get_hostname error");
2368 }
2369 }
2370
2371 string get_env(const string & name) {
2372 const char* val = std::getenv(name.c_str());
2373 if(val==NULL) return string("");
2374 return string(val);
2375 }
2376
2377}
2378
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:242
string msg
Definition BASIC.h:244
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:863
string Execute(const string &script, const string &out_var="[o]")
Definition Process.cpp:271
class for Mathematica Format Output
Definition BASIC.h:886
const MMAFormat & operator<<(const T &v) const
Definition BASIC.h:891
MMAFormat(ostream &os, unsigned opt=0)
Definition BASIC.cpp:2060
class to wrap map_function of GiNaC
Definition BASIC.h:675
class to parse for string or file, helpful with Symbol class
Definition BASIC.h:688
ex Read(const string &instr, bool s2S=true)
class extended to GiNaC symbol class, represent a positive symbol
Definition BASIC.h:113
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:145
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:160
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:167
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:783
ex op(size_t i) const override
Definition BASIC.cpp:1683
int compare_same_type(const GiNaC::basic &other) const override
Definition BASIC.cpp:1664
void accept(GiNaC::visitor &v) const override
Definition BASIC.cpp:1654
XIntegral * duplicate() const override
Definition BASIC.cpp:1653
void archive(archive_node &n) const override
Definition BASIC.cpp:1697
ex & let_op(size_t i) override
Definition BASIC.cpp:1689
void print(const print_dflt &c, unsigned level=0) const
Definition BASIC.cpp:1676
void read_archive(const archive_node &n) override
Definition BASIC.cpp:1704
const char * class_name() const override
Definition BASIC.cpp:1657
static GiNaC::registered_class_info & get_class_info_static()
Definition BASIC.cpp:1651
const GiNaC::registered_class_info & get_class_info() const override
Definition BASIC.cpp:1655
size_t nops() const override
Definition BASIC.cpp:1682
class extended to GiNaC symbol class, pure imaginary symbol
Definition BASIC.h:183
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:230
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:516
static lst map(const lst &m, F f)
Definition BASIC.h:270
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:1190
const char * Color_HighLight
Definition BASIC.cpp:248
ex exfactor(const ex &expr_in, int opt)
factorize a expression
Definition BASIC.cpp:1856
ex collect_factors(const ex &expr)
a wrapper for collect_common_factors, catch errors
Definition BASIC.cpp:1843
void arg2map(int argc, char **argv, const char *optstring, std::map< char, std::string > &kv)
Definition BASIC.cpp:2339
__float128 ex2q(ex num)
ex of numeric to __float128
Definition BASIC.cpp:881
const iSymbol iEpsilon
void reset_precision()
Definition BASIC.cpp:2325
ex EvalF(ex expr)
the nuerical evaluation, Digits=100 will be used
Definition BASIC.cpp:1247
lst str2lst(const string &expr, symtab stab)
convert string to the lst, using Parser internally
Definition BASIC.cpp:695
ex exnd(const ex &expr, int opt)
num_den a expression
Definition BASIC.cpp:1934
ex form_factor(const ex &expr, bool nd=true)
Definition BASIC.h:472
lst gather_symbols(const ex &e)
get all symbols from input expression
Definition BASIC.cpp:541
void let_op_prepend(ex &ex_in, const ex item)
preppend item into expression
Definition BASIC.cpp:1337
ex EvalL(ex expr)
Definition BASIC.cpp:1258
lst xlst(int bi, int ei)
return a lst: x(bi), x(bi+1), ..., x(ei)
Definition BASIC.cpp:948
int GiNaC_Parallel_Process
Definition Init.cpp:146
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:1562
std::initializer_list< ex > init_list
Definition BASIC.h:47
ex q2ex(__float128 num)
__float128 to ex
Definition BASIC.cpp:869
bool xPositive(ex const expr)
check the expr is xPositive, i.e., each x-monomial item is postive
Definition BASIC.cpp:1292
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:1123
void ex2file(const ex &expr, string filename)
export expression file
Definition BASIC.cpp:847
ex normal_fermat(const ex &expr, bool dfactor)
return the normalizatied expression, using fermat_numer_denom
Definition BASIC.cpp:1833
ex NN(ex expr, int digits)
the nuerical evaluation
Definition BASIC.cpp:1280
const int o_flint
Definition Init.cpp:113
map< string, bool > GiNaC_Parallel_RM
Definition Init.cpp:151
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:1204
ex EvalQ(ex expr)
Definition BASIC.cpp:1263
void garRead(const string &garfn, map< string, ex > &resMap)
garRead from file, and output in a map
Definition BASIC.cpp:593
map< string, int > GiNaC_Parallel_NB
Definition Init.cpp:150
void subs_w(exmap &repl)
Definition BASIC.cpp:2240
const int o_fermat_form
Definition Init.cpp:118
void ReShare(const ex &e)
Definition BASIC.cpp:2252
bool file_exists(string fn)
Definition BASIC.h:289
bool has_w(const ex &e)
Definition BASIC.cpp:2235
ex factor_form(const ex &expr, bool nd)
factorize a expression using FORM
Definition BASIC.cpp:2050
ex series_ex(ex const &expr_in, ex const &s0, int sn0)
the series like Mathematica, include s^n
Definition BASIC.cpp:970
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:672
lst syms(const exvector &ev)
Definition FIRE.cpp:61
ex form_eval(const ex &expr)
Definition BASIC.cpp:1940
string now(bool use_date)
date/time string
Definition BASIC.cpp:527
vector< pair< ex, ex > > epvec_t
Definition BASIC.cpp:1077
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:573
lst add2lst(const ex &expr)
convert add to lst
Definition BASIC.cpp:923
ex w
Definition Init.cpp:93
ex fermat_normal(const ex &expr, bool dfactor=false)
Definition BASIC.h:465
const Symbol vs
int CpuCores()
return the cpu cores using OpenMP
Definition BASIC.cpp:1822
map< string, int > GiNaC_Parallel_NP
Definition Init.cpp:147
map< string, int > GiNaC_Parallel_Verb
Definition Init.cpp:148
map< string, bool > GiNaC_Parallel_ReWR
Definition Init.cpp:153
exvector lst2vec(const lst &alst)
convert lst to exvector
Definition BASIC.cpp:913
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:1608
vector< string > file2strvec(string filename, bool skip_empty)
read file content to string vector
Definition BASIC.cpp:811
ex file2ex(string filename)
read file content to ex
Definition BASIC.cpp:827
ex exnormal(const ex &expr, int opt)
normalize a expression
Definition BASIC.cpp:1918
const int o_flintf
Definition Init.cpp:114
const int o_flintfD
Definition Init.cpp:115
ex EvalMP(ex expr)
Definition BASIC.cpp:1268
const int o_normal_fermat
Definition Init.cpp:116
ex nextprime(const ex &n)
Definition BASIC.cpp:2286
ex normal_flint(const ex &expr, int opt=o_flint)
ex inner_factor_form(const ex &expr)
Definition BASIC.cpp:1986
bool In_GiNaC_Parallel
Definition Init.cpp:145
lst mul2lst(const ex &expr)
convert mul to lst
Definition BASIC.cpp:935
string file2str(string filename)
read file content to string
Definition BASIC.cpp:777
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:1224
ex diff_ex(ex const expr, ex const xp, unsigned nth, bool expand)
the differential like Mathematica
Definition BASIC.cpp:1065
int Verbose
Definition Init.cpp:142
ex Rationalize(const ex &e, int dn)
Definition BASIC.cpp:2295
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:1879
void garWrite(const string &garfn, const map< string, ex > &resMap)
garWrite to write the string-key map to the archive
Definition BASIC.cpp:641
void let_op_append(ex &ex_in, const ex item)
append item into expression
Definition BASIC.cpp:1326
lst vec2lst(const exvector &ev)
convert exvector to lst
Definition BASIC.cpp:904
string ex2str(const ex &expr)
convert ex to output string, the defalut printer format will be used
Definition BASIC.cpp:717
void let_op_remove_first(ex &ex_in)
remove first from expression
Definition BASIC.cpp:1357
matrix lst2mat(const lst &ls)
convert 2Dim lst to matrix
Definition BASIC.cpp:739
bool dir_exists(string dir)
Definition BASIC.h:297
void str2file(const string &ostr, string filename)
export string to a file
Definition BASIC.cpp:789
const int o_normal_form
Definition Init.cpp:117
co_epvec_t power_expand_2(const co_epvec_t &co_epv, int n)
Definition BASIC.cpp:1079
void set_precision(long prec, bool push)
Definition BASIC.cpp:2316
ex add_collect_normal(const exvector &exv, ex const &pats, int opt)
Definition BASIC.cpp:2175
map< string, string > GiNaC_Parallel_PRE
Definition Init.cpp:152
std::vector< std::string > split(const std::string &s, char delimiter)
split the string into serveral part, separated by the delimiter
Definition BASIC.cpp:501
int xSign(ex const expr)
the always sign for expr
Definition BASIC.cpp:1314
pair< ex, epvec_t > co_epvec_t
Definition BASIC.cpp:1078
exvector GiNaC_Parallel(int ntotal, std::function< ex(int)> f, const string &key)
GiNaC Parallel Evaluation using fork.
Definition BASIC.cpp:260
string get_hostname()
Definition BASIC.cpp:2361
void let_op_remove_last(ex &ex_in)
remove last from expression
Definition BASIC.cpp:1347
const int o_fermatN
Definition Init.cpp:111
bool has_symbol(const ex &e)
Definition BASIC.cpp:2355
std::stack< cln::float_format_t > cln_prec_stack
Definition Init.cpp:362
std::stack< long > digits_stack
Definition Init.cpp:363
string get_env(const string &name)
Definition BASIC.cpp:2371
long get_precision()
Definition BASIC.cpp:2335
ex numer_fermat(const ex &expr)
Definition Fermat.cpp:170
ex fermat_numer_denom(const ex &expr, bool dfactor=false)
Definition BASIC.h:461
string PRE
Definition Init.cpp:143
int ex2int(ex num)
ex to integer
Definition BASIC.cpp:895
ex subs(const ex &e, init_list sl)
Definition BASIC.h:51
int GiNaC_Parallel_Batch
Definition Init.cpp:149