Loading...
Searching...
No Matches
strprinter.cpp
1#include <limits>
2#include <symengine/printers/strprinter.h>
3
4namespace SymEngine
5{
6
10 bool operator()(const RCP<const Basic> &x, const RCP<const Basic> &y) const
11 {
12 if (x->__eq__(*y))
13 return false;
14 return x->__cmp__(*y) == -1;
15 }
16};
17
18std::string ascii_art()
19{
20 std::string a = " _____ _____ _ \n"
21 "| __|_ _ _____| __|___ ___|_|___ ___ \n"
22 "|__ | | | | __| | . | | | -_|\n"
23 "|_____|_ |_|_|_|_____|_|_|_ |_|_|_|___|\n"
24 " |___| |___| \n";
25 return a;
26}
27
28void Precedence::bvisit(const Add &x)
29{
30 precedence = PrecedenceEnum::Add;
31}
32
33void Precedence::bvisit(const Mul &x)
34{
35 precedence = PrecedenceEnum::Mul;
36}
37
38void Precedence::bvisit(const Relational &x)
39{
40 precedence = PrecedenceEnum::Relational;
41}
42
43void Precedence::bvisit(const Pow &x)
44{
45 precedence = PrecedenceEnum::Pow;
46}
47
48void Precedence::bvisit(const GaloisField &x)
49{
50 // iterators need to be implemented
51 // bvisit_upoly(x);
52}
53
54void Precedence::bvisit(const Rational &x)
55{
56 precedence = PrecedenceEnum::Add;
57}
58
59void Precedence::bvisit(const Complex &x)
60{
61 if (x.is_re_zero()) {
62 if (x.imaginary_ == 1) {
63 precedence = PrecedenceEnum::Atom;
64 } else {
65 precedence = PrecedenceEnum::Mul;
66 }
67 } else {
68 precedence = PrecedenceEnum::Add;
69 }
70}
71
72void Precedence::bvisit(const Integer &x)
73{
74 if (x.is_negative()) {
75 precedence = PrecedenceEnum::Mul;
76 } else {
77 precedence = PrecedenceEnum::Atom;
78 }
79}
80
81void Precedence::bvisit(const RealDouble &x)
82{
83 if (x.is_negative()) {
84 precedence = PrecedenceEnum::Mul;
85 } else {
86 precedence = PrecedenceEnum::Atom;
87 }
88}
89
90#ifdef HAVE_SYMENGINE_PIRANHA
91void Precedence::bvisit(const URatPSeriesPiranha &x)
92{
93 precedence = PrecedenceEnum::Add;
94}
95
96void Precedence::bvisit(const UPSeriesPiranha &x)
97{
98 precedence = PrecedenceEnum::Add;
99}
100#endif
101void Precedence::bvisit(const ComplexDouble &x)
102{
103 precedence = PrecedenceEnum::Add;
104}
105#ifdef HAVE_SYMENGINE_MPFR
106void Precedence::bvisit(const RealMPFR &x)
107{
108 if (x.is_negative()) {
109 precedence = PrecedenceEnum::Mul;
110 } else {
111 precedence = PrecedenceEnum::Atom;
112 }
113}
114#endif
115#ifdef HAVE_SYMENGINE_MPC
116void Precedence::bvisit(const ComplexMPC &x)
117{
118 precedence = PrecedenceEnum::Add;
119}
120#endif
121
122void Precedence::bvisit(const Basic &x)
123{
124 precedence = PrecedenceEnum::Atom;
125}
126
127PrecedenceEnum Precedence::getPrecedence(const RCP<const Basic> &x)
128{
129 (*x).accept(*this);
130 return precedence;
131}
132
133void StrPrinter::bvisit(const Basic &x)
134{
136 s << "<" << typeName<Basic>(x) << " instance at " << (const void *)this
137 << ">";
138 str_ = s.str();
139}
140
141void StrPrinter::bvisit(const Symbol &x)
142{
143 str_ = x.get_name();
144}
145
146void StrPrinter::bvisit(const Infty &x)
147{
149 if (x.is_negative_infinity())
150 s << "-oo";
151 else if (x.is_positive_infinity())
152 s << "oo";
153 else
154 s << "zoo";
155 str_ = s.str();
156}
157
158void StrPrinter::bvisit(const NaN &x)
159{
161 s << "nan";
162 str_ = s.str();
163}
164
165void StrPrinter::bvisit(const Integer &x)
166{
168 s << x.as_integer_class();
169 str_ = s.str();
170}
171
172void StrPrinter::bvisit(const Rational &x)
173{
175 s << x.as_rational_class();
176 str_ = s.str();
177}
178
179void StrPrinter::bvisit(const Complex &x)
180{
182 if (x.real_ != 0) {
183 s << x.real_;
184 // Since Complex is in canonical form, imaginary_ is not 0.
185 if (mp_sign(x.imaginary_) == 1) {
186 s << " + ";
187 } else {
188 s << " - ";
189 }
190 // If imaginary_ is not 1 or -1, print the absolute value
191 if (x.imaginary_ != mp_sign(x.imaginary_)) {
192 s << mp_abs(x.imaginary_);
193 s << print_mul() << get_imag_symbol();
194 } else {
195 s << "I";
196 }
197 } else {
198 if (x.imaginary_ != mp_sign(x.imaginary_)) {
199 s << x.imaginary_;
200 s << print_mul() << get_imag_symbol();
201 } else {
202 if (mp_sign(x.imaginary_) == 1) {
203 s << get_imag_symbol();
204 } else {
205 s << "-" << get_imag_symbol();
206 }
207 }
208 }
209 str_ = s.str();
210}
211
212std::string print_double(double d)
213{
216 s << d;
217 auto str_ = s.str();
218 if (str_.find(".") == std::string::npos
219 and str_.find("e") == std::string::npos) {
220 if (std::numeric_limits<double>::digits10 - str_.size() > 0) {
221 str_ += ".0";
222 } else {
223 str_ += ".";
224 }
225 }
226 return str_;
227}
228
229void StrPrinter::bvisit(const RealDouble &x)
230{
231 str_ = print_double(x.i);
232}
233
234void StrPrinter::bvisit(const ComplexDouble &x)
235{
236 str_ = print_double(x.i.real());
237 if (x.i.imag() < 0) {
238 str_ += " - " + print_double(-x.i.imag()) + print_mul()
239 + get_imag_symbol();
240 } else {
241 str_ += " + " + print_double(x.i.imag()) + print_mul()
242 + get_imag_symbol();
243 }
244}
245
246void StrPrinter::bvisit(const Equality &x)
247{
249 s << apply(x.get_arg1()) << " == " << apply(x.get_arg2());
250 str_ = s.str();
251}
252
253void StrPrinter::bvisit(const Unequality &x)
254{
256 s << apply(x.get_arg1()) << " != " << apply(x.get_arg2());
257 str_ = s.str();
258}
259
260void StrPrinter::bvisit(const LessThan &x)
261{
263 s << apply(x.get_arg1()) << " <= " << apply(x.get_arg2());
264 str_ = s.str();
265}
266
267void StrPrinter::bvisit(const StrictLessThan &x)
268{
270 s << apply(x.get_arg1()) << " < " << apply(x.get_arg2());
271 str_ = s.str();
272}
273
274void StrPrinter::bvisit(const Interval &x)
275{
277 if (x.get_left_open())
278 s << "(";
279 else
280 s << "[";
281 s << *x.get_start() << ", " << *x.get_end();
282 if (x.get_right_open())
283 s << ")";
284 else
285 s << "]";
286 str_ = s.str();
287}
288
289void StrPrinter::bvisit(const BooleanAtom &x)
290{
291 if (x.get_val()) {
292 str_ = "True";
293 } else {
294 str_ = "False";
295 }
296}
297
298void StrPrinter::bvisit(const And &x)
299{
301 auto container = x.get_container();
302 s << "And(";
303 s << apply(*container.begin());
304 for (auto it = ++(container.begin()); it != container.end(); ++it) {
305 s << ", " << apply(*it);
306 }
307 s << ")";
308 str_ = s.str();
309}
310
311void StrPrinter::bvisit(const Or &x)
312{
314 auto container = x.get_container();
315 s << "Or(";
316 s << apply(*container.begin());
317 for (auto it = ++(container.begin()); it != container.end(); ++it) {
318 s << ", " << apply(*it);
319 }
320 s << ")";
321 str_ = s.str();
322}
323
324void StrPrinter::bvisit(const Xor &x)
325{
327 auto container = x.get_container();
328 s << "Xor(";
329 s << apply(*container.begin());
330 for (auto it = ++(container.begin()); it != container.end(); ++it) {
331 s << ", " << apply(*it);
332 }
333 s << ")";
334 str_ = s.str();
335}
336
337void StrPrinter::bvisit(const Not &x)
338{
340 s << "Not(" << *x.get_arg() << ")";
341 str_ = s.str();
342}
343
344void StrPrinter::bvisit(const Contains &x)
345{
347 s << "Contains(" << apply(x.get_expr()) << ", " << apply(x.get_set())
348 << ")";
349 str_ = s.str();
350}
351
352void StrPrinter::bvisit(const Piecewise &x)
353{
355 auto vec = x.get_vec();
356 auto it = vec.begin();
357 s << "Piecewise(";
358 while (true) {
359 s << "(";
360 s << apply((*it).first);
361 s << ", ";
362 s << apply((*it).second);
363 s << ")";
364 ++it;
365 if (it != vec.end()) {
366 s << ", ";
367 } else {
368 break;
369 }
370 }
371 s << ")";
372 str_ = s.str();
373}
374
375void StrPrinter::bvisit(const Complexes &x)
376{
377 str_ = "Complexes";
378}
379
380void StrPrinter::bvisit(const Reals &x)
381{
382 str_ = "Reals";
383}
384
385void StrPrinter::bvisit(const Rationals &x)
386{
387 str_ = "Rationals";
388}
389
390void StrPrinter::bvisit(const Integers &x)
391{
392 str_ = "Integers";
393}
394
395void StrPrinter::bvisit(const Naturals &x)
396{
397 str_ = "Naturals";
398}
399
400void StrPrinter::bvisit(const Naturals0 &x)
401{
402 str_ = "Naturals0";
403}
404
405void StrPrinter::bvisit(const EmptySet &x)
406{
407 str_ = "EmptySet";
408}
409
410void StrPrinter::bvisit(const Union &x)
411{
413 s << apply(*x.get_container().begin());
414 for (auto it = ++(x.get_container().begin()); it != x.get_container().end();
415 ++it) {
416 s << " U " << apply(*it);
417 }
418 str_ = s.str();
419}
420
421void StrPrinter::bvisit(const Complement &x)
422{
424 s << apply(*x.get_universe());
425 s << " \\ " << apply(*x.get_container());
426 str_ = s.str();
427}
428
429void StrPrinter::bvisit(const ImageSet &x)
430{
432 s << "{" << apply(*x.get_expr()) << " | ";
433 s << apply(*x.get_symbol());
434 s << " in " << apply(*x.get_baseset()) << "}";
435 str_ = s.str();
436}
437
438void StrPrinter::bvisit(const UniversalSet &x)
439{
440 str_ = "UniversalSet";
441}
442
443void StrPrinter::bvisit(const FiniteSet &x)
444{
446 s << x.get_container();
447 str_ = s.str();
448}
449
450void StrPrinter::bvisit(const ConditionSet &x)
451{
453 s << "{" << apply(*x.get_symbol());
454 s << " | " << apply(x.get_condition()) << "}";
455 str_ = s.str();
456}
457
458#ifdef HAVE_SYMENGINE_MPFR
459void StrPrinter::bvisit(const RealMPFR &x)
460{
461 mpfr_exp_t ex;
462 // mpmath.libmp.libmpf.prec_to_dps
463 long digits
464 = std::max(long(1), std::lround(static_cast<double>(x.i.get_prec())
465 / 3.3219280948873626)
466 - 1);
467 char *c
468 = mpfr_get_str(nullptr, &ex, 10, digits, x.i.get_mpfr_t(), MPFR_RNDN);
470 str_ = std::string(c);
471 if (str_.at(0) == '-') {
472 s << '-';
473 str_ = str_.substr(1, str_.length() - 1);
474 }
475 if (ex > 6) {
476 s << str_.at(0) << '.' << str_.substr(1, str_.length() - 1) << 'e'
477 << (ex - 1);
478 } else if (ex > 0) {
479 s << str_.substr(0, (unsigned long)ex) << ".";
480 s << str_.substr((unsigned long)ex, str_.length() - ex);
481 } else if (ex > -5) {
482 s << "0.";
483 for (int i = 0; i < -ex; ++i) {
484 s << '0';
485 }
486 s << str_;
487 } else {
488 s << str_.at(0) << '.' << str_.substr(1, str_.length() - 1) << 'e'
489 << (ex - 1);
490 }
491 mpfr_free_str(c);
492 str_ = s.str();
493}
494#endif
495#ifdef HAVE_SYMENGINE_MPC
496void StrPrinter::bvisit(const ComplexMPC &x)
497{
498 RCP<const Number> imag = x.imaginary_part();
499 if (imag->is_negative()) {
500 std::string str = this->apply(imag);
501 str = str.substr(1, str.length() - 1);
502 str_ = this->apply(x.real_part()) + " - " + str + print_mul()
503 + get_imag_symbol();
504 } else {
505 str_ = this->apply(x.real_part()) + " + " + this->apply(imag)
506 + print_mul() + get_imag_symbol();
507 }
508}
509#endif
510void StrPrinter::bvisit(const Add &x)
511{
513 bool first = true;
514 std::map<RCP<const Basic>, RCP<const Number>, PrinterBasicCmp> dict(
515 x.get_dict().begin(), x.get_dict().end());
516
517 if (neq(*(x.get_coef()), *zero)) {
518 o << this->apply(x.get_coef());
519 first = false;
520 }
521 for (const auto &p : dict) {
522 std::string t;
523 if (eq(*(p.second), *one)) {
524 t = parenthesizeLT(p.first, PrecedenceEnum::Add);
525 } else if (eq(*(p.second), *minus_one)) {
526 t = "-" + parenthesizeLT(p.first, PrecedenceEnum::Mul);
527 } else {
528 t = parenthesizeLT(p.second, PrecedenceEnum::Mul) + print_mul()
529 + parenthesizeLT(p.first, PrecedenceEnum::Mul);
530 }
531
532 if (not first) {
533 if (t[0] == '-') {
534 o << " - " << t.substr(1);
535 } else {
536 o << " + " << t;
537 }
538 } else {
539 o << t;
540 first = false;
541 }
542 }
543 str_ = o.str();
544}
545
546void StrPrinter::_print_pow(std::ostringstream &o, const RCP<const Basic> &a,
547 const RCP<const Basic> &b)
548{
549 if (eq(*a, *E)) {
550 o << "exp(" << apply(b) << ")";
551 } else if (eq(*b, *rational(1, 2))) {
552 o << "sqrt(" << apply(a) << ")";
553 } else {
554 o << parenthesizeLE(a, PrecedenceEnum::Pow);
555 o << "**";
556 o << parenthesizeLE(b, PrecedenceEnum::Pow);
557 }
558}
559
560void StrPrinter::bvisit(const Mul &x)
561{
562 std::ostringstream o, o2;
563 bool num = false;
564 unsigned den = 0;
565
566 if (eq(*(x.get_coef()), *minus_one)) {
567 o << "-";
568 } else if (neq(*(x.get_coef()), *one)) {
569 if (not split_mul_coef()) {
570 o << parenthesizeLT(x.get_coef(), PrecedenceEnum::Mul)
571 << print_mul();
572 num = true;
573 } else {
574 RCP<const Basic> numer, denom;
575 as_numer_denom(x.get_coef(), outArg(numer), outArg(denom));
576 if (neq(*numer, *one)) {
577 num = true;
578 o << parenthesizeLT(numer, PrecedenceEnum::Mul) << print_mul();
579 }
580 if (neq(*denom, *one)) {
581 den++;
582 o2 << parenthesizeLT(denom, PrecedenceEnum::Mul) << print_mul();
583 }
584 }
585 }
586
587 for (const auto &p : x.get_dict()) {
588 if ((is_a<Integer>(*p.second) or is_a<Rational>(*p.second))
589 and down_cast<const Number &>(*p.second).is_negative()
590 and neq(*(p.first), *E)) {
591 if (eq(*(p.second), *minus_one)) {
592 o2 << parenthesizeLT(p.first, PrecedenceEnum::Mul);
593 } else {
594 _print_pow(o2, p.first, neg(p.second));
595 }
596 o2 << print_mul();
597 den++;
598 } else {
599 if (eq(*(p.second), *one)) {
600 o << parenthesizeLT(p.first, PrecedenceEnum::Mul);
601 } else {
602 _print_pow(o, p.first, p.second);
603 }
604 o << print_mul();
605 num = true;
606 }
607 }
608
609 if (not num) {
610 o << "1" << print_mul();
611 }
612
613 std::string s = o.str();
614 s = s.substr(0, s.size() - 1);
615
616 if (den != 0) {
617 std::string s2 = o2.str();
618 s2 = s2.substr(0, s2.size() - 1);
619 if (den > 1) {
620 str_ = print_div(s, s2, true);
621 } else {
622 str_ = print_div(s, s2, false);
623 }
624 } else {
625 str_ = s;
626 }
627}
628
629std::string StrPrinter::print_div(const std::string &num,
630 const std::string &den, bool paren)
631{
632 if (paren) {
633 return num + "/" + parenthesize(den);
634 } else {
635 return num + "/" + den;
636 }
637}
638
639bool StrPrinter::split_mul_coef()
640{
641 return false;
642}
643
644void StrPrinter::bvisit(const Pow &x)
645{
647 _print_pow(o, x.get_base(), x.get_exp());
648 str_ = o.str();
649}
650
651template <typename T>
652char _print_sign(const T &i)
653{
654 if (i < 0) {
655 return '-';
656 } else {
657 return '+';
658 }
659}
660
661void StrPrinter::bvisit(const GaloisField &x)
662{
664 // bool variable needed to take care of cases like -5, -x, -3*x etc.
665 bool first = true;
666 // we iterate over the map in reverse order so that highest degree gets
667 // printed first
668 auto dict = x.get_dict();
669 if (x.get_dict().size() == 0)
670 s << "0";
671 else {
672 for (auto it = dict.size(); it-- != 0;) {
673 if (dict[it] == 0)
674 continue;
675 // if exponent is 0, then print only coefficient
676 if (it == 0) {
677 if (first) {
678 s << dict[it];
679 } else {
680 s << " " << _print_sign(dict[it]) << " "
681 << mp_abs(dict[it]);
682 }
683 first = false;
684 break;
685 }
686 // if the coefficient of a term is +1 or -1
687 if (mp_abs(dict[it]) == 1) {
688 // in cases of -x, print -x
689 // in cases of x**2 - x, print - x
690 if (first) {
691 if (dict[it] == -1)
692 s << "-";
693 s << detail::poly_print(x.get_var());
694 } else {
695 s << " " << _print_sign(dict[it]) << " "
696 << detail::poly_print(x.get_var());
697 }
698 }
699 // same logic is followed as above
700 else {
701 // in cases of -2*x, print -2*x
702 // in cases of x**2 - 2*x, print - 2*x
703 if (first) {
704 s << dict[it] << "*" << detail::poly_print(x.get_var());
705 } else {
706 s << " " << _print_sign(dict[it]) << " " << mp_abs(dict[it])
707 << "*" << detail::poly_print(x.get_var());
708 }
709 }
710 // if exponent is not 1, print the exponent;
711 if (it != 1) {
712 s << "**" << it;
713 }
714 // corner cases of only first term handled successfully, switch the
715 // bool
716 first = false;
717 }
718 }
719 str_ = s.str();
720}
721
722// Printing of Integer and Rational Polynomials, tests taken
723// from SymPy and printing ensures that there is compatibility
724template <typename P>
725std::string upoly_print(const P &x)
726{
728 // bool variable needed to take care of cases like -5, -x, -3*x etc.
729 bool first = true;
730 // we iterate over the map in reverse order so that highest degree gets
731 // printed first
732 for (auto it = x.obegin(); it != x.oend(); ++it) {
733 auto m = it->second;
734 // if exponent is 0, then print only coefficient
735 if (it->first == 0) {
736 if (first) {
737 s << m;
738 } else {
739 s << " " << _print_sign(m) << " " << mp_abs(m);
740 }
741 first = false;
742 continue;
743 }
744 // if the coefficient of a term is +1 or -1
745 if (mp_abs(m) == 1) {
746 // in cases of -x, print -x
747 // in cases of x**2 - x, print - x
748 if (first) {
749 if (m == -1)
750 s << "-";
751 s << detail::poly_print(x.get_var());
752 } else {
753 s << " " << _print_sign(m) << " "
754 << detail::poly_print(x.get_var());
755 }
756 }
757 // same logic is followed as above
758 else {
759 // in cases of -2*x, print -2*x
760 // in cases of x**2 - 2*x, print - 2*x
761 if (first) {
762 s << m << "*" << detail::poly_print(x.get_var());
763 } else {
764 s << " " << _print_sign(m) << " " << mp_abs(m) << "*"
765 << detail::poly_print(x.get_var());
766 }
767 }
768 // if exponent is not 1, print the exponent;
769 if (it->first != 1) {
770 s << "**" << it->first;
771 }
772 // corner cases of only first term handled successfully, switch the bool
773 first = false;
774 }
775 if (x.size() == 0)
776 s << "0";
777 return s.str();
778}
779
780void StrPrinter::bvisit(const UIntPoly &x)
781{
782 str_ = upoly_print<UIntPoly>(x);
783}
784
785void StrPrinter::bvisit(const URatPoly &x)
786{
787 str_ = upoly_print<URatPoly>(x);
788}
789
790#ifdef HAVE_SYMENGINE_FLINT
791void StrPrinter::bvisit(const UIntPolyFlint &x)
792{
793 str_ = upoly_print<UIntPolyFlint>(x);
794}
795void StrPrinter::bvisit(const URatPolyFlint &x)
796{
797 str_ = upoly_print<URatPolyFlint>(x);
798}
799#endif
800
801#ifdef HAVE_SYMENGINE_PIRANHA
802void StrPrinter::bvisit(const UIntPolyPiranha &x)
803{
804 str_ = upoly_print<UIntPolyPiranha>(x);
805}
806void StrPrinter::bvisit(const URatPolyPiranha &x)
807{
808 str_ = upoly_print<URatPolyPiranha>(x);
809}
810#endif
811
812// UExprPoly printing, tests taken from SymPy and printing ensures
813// that there is compatibility
814void StrPrinter::bvisit(const UExprPoly &x)
815{
817 if (x.get_dict().size() == 0)
818 s << "0";
819 else
820 s << x.get_poly().__str__(detail::poly_print(x.get_var()));
821 str_ = s.str();
822}
823
824void StrPrinter::bvisit(const UnivariateSeries &x)
825{
827 o << x.get_poly().__str__(x.get_var()) << " + O(" << x.get_var() << "**"
828 << x.get_degree() << ")";
829 str_ = o.str();
830}
831
832#ifdef HAVE_SYMENGINE_PIRANHA
833void StrPrinter::bvisit(const URatPSeriesPiranha &x)
834{
836 o << x.get_poly() << " + O(" << x.get_var() << "**" << x.get_degree()
837 << ")";
838 str_ = o.str();
839}
840void StrPrinter::bvisit(const UPSeriesPiranha &x)
841{
843 o << x.get_poly() << " + O(" << x.get_var() << "**" << x.get_degree()
844 << ")";
845 str_ = o.str();
846}
847#endif
848
849void StrPrinter::bvisit(const Constant &x)
850{
851 str_ = x.get_name();
852}
853
854std::string StrPrinter::apply(const vec_basic &d)
855{
857 for (auto p = d.begin(); p != d.end(); p++) {
858 if (p != d.begin()) {
859 o << ", ";
860 }
861 o << this->apply(*p);
862 }
863 return o.str();
864}
865
866void StrPrinter::bvisit(const Function &x)
867{
868 static const std::vector<std::string> names_ = init_str_printer_names();
870 o << names_[x.get_type_code()];
871 vec_basic vec = x.get_args();
872 o << parenthesize(apply(vec));
873 str_ = o.str();
874}
875
876void StrPrinter::bvisit(const FunctionSymbol &x)
877{
879 o << x.get_name();
880 vec_basic vec = x.get_args();
881 o << parenthesize(apply(vec));
882 str_ = o.str();
883}
884
885void StrPrinter::bvisit(const Derivative &x)
886{
888 o << "Derivative(" << this->apply(x.get_arg());
889 auto m1 = x.get_symbols();
890 for (const auto &elem : m1) {
891 o << ", " << this->apply(elem);
892 }
893 o << ")";
894 str_ = o.str();
895}
896
897void StrPrinter::bvisit(const Subs &x)
898{
899 std::ostringstream o, vars, point;
900 for (auto p = x.get_dict().begin(); p != x.get_dict().end(); p++) {
901 if (p != x.get_dict().begin()) {
902 vars << ", ";
903 point << ", ";
904 }
905 vars << apply(p->first);
906 point << apply(p->second);
907 }
908 o << "Subs(" << apply(x.get_arg()) << ", (" << vars.str() << "), ("
909 << point.str() << "))";
910 str_ = o.str();
911}
912
913void StrPrinter::bvisit(const NumberWrapper &x)
914{
915 str_ = x.__str__();
916}
917
918void StrPrinter::bvisit(const MIntPoly &x)
919{
921 bool first = true; // is this the first term being printed out?
922 // To change the ordering in which the terms will print out, change
923 // vec_uint_compare in dict.h
924 std::vector<vec_uint> v = sorted_keys(x.get_poly().dict_);
925
926 for (vec_uint exps : v) {
927 integer_class c = x.get_poly().dict_.find(exps)->second;
928 if (!first) {
929 s << " " << _print_sign(c) << " ";
930 } else if (c < 0) {
931 s << "-";
932 }
933
934 unsigned int i = 0;
936 bool first_var = true;
937 for (auto it : x.get_vars()) {
938 if (exps[i] != 0) {
939 if (!first_var) {
940 expr << "*";
941 }
942 expr << it->__str__();
943 if (exps[i] > 1)
944 expr << "**" << exps[i];
945 first_var = false;
946 }
947 i++;
948 }
949 if (mp_abs(c) != 1) {
950 s << mp_abs(c);
951 if (!expr.str().empty()) {
952 s << "*";
953 }
954 } else if (expr.str().empty()) {
955 s << "1";
956 }
957 s << expr.str();
958 first = false;
959 }
960
961 if (s.str().empty())
962 s << "0";
963 str_ = s.str();
964}
965
966void StrPrinter::bvisit(const MExprPoly &x)
967{
969 bool first = true; // is this the first term being printed out?
970 // To change the ordering in which the terms will print out, change
971 // vec_uint_compare in dict.h
972 std::vector<vec_int> v = sorted_keys(x.get_poly().dict_);
973
974 for (vec_int exps : v) {
975 Expression c = x.get_poly().dict_.find(exps)->second;
976 std::string t = parenthesizeLT(c.get_basic(), PrecedenceEnum::Mul);
977 if ('-' == t[0] && !first) {
978 s << " - ";
979 t = t.substr(1);
980 } else if (!first) {
981 s << " + ";
982 }
983 unsigned int i = 0;
985 bool first_var = true;
986 for (auto it : x.get_vars()) {
987 if (exps[i] != 0) {
988 if (!first_var) {
989 expr << "*";
990 }
991 expr << it->__str__();
992 if (exps[i] > 1 or exps[i] < 0)
993 expr << "**" << exps[i];
994 first_var = false;
995 }
996 i++;
997 }
998 if (c != 1 && c != -1) {
999 s << t;
1000 if (!expr.str().empty()) {
1001 s << "*";
1002 }
1003 } else if (expr.str().empty()) {
1004 s << "1";
1005 }
1006 s << expr.str();
1007 first = false;
1008 }
1009
1010 if (s.str().empty())
1011 s << "0";
1012 str_ = s.str();
1013}
1014
1015void StrPrinter::bvisit(const Tuple &x)
1016{
1018 vec_basic vec = x.get_args();
1019 o << parenthesize(apply(vec));
1020 str_ = o.str();
1021}
1022
1023std::string StrPrinter::parenthesizeLT(const RCP<const Basic> &x,
1024 PrecedenceEnum precedenceEnum)
1025{
1026 Precedence prec;
1027 if (prec.getPrecedence(x) < precedenceEnum) {
1028 return parenthesize(apply(x));
1029 } else {
1030 return apply(x);
1031 }
1032}
1033
1034std::string StrPrinter::parenthesizeLE(const RCP<const Basic> &x,
1035 PrecedenceEnum precedenceEnum)
1036{
1037 Precedence prec;
1038 if (prec.getPrecedence(x) <= precedenceEnum) {
1039 return parenthesize(apply(x));
1040 } else {
1041 return apply(x);
1042 }
1043}
1044
1045std::string StrPrinter::parenthesize(const std::string &x)
1046{
1047 return "(" + x + ")";
1048}
1049
1050std::string StrPrinter::apply(const RCP<const Basic> &b)
1051{
1052 b->accept(*this);
1053 return str_;
1054}
1055
1056std::string StrPrinter::apply(const Basic &b)
1057{
1058 b.accept(*this);
1059 return str_;
1060}
1061
1062std::vector<std::string> init_str_printer_names()
1063{
1065 names.assign(TypeID_Count, "");
1066 names[SYMENGINE_SIN] = "sin";
1067 names[SYMENGINE_COS] = "cos";
1068 names[SYMENGINE_TAN] = "tan";
1069 names[SYMENGINE_COT] = "cot";
1070 names[SYMENGINE_CSC] = "csc";
1071 names[SYMENGINE_SEC] = "sec";
1072 names[SYMENGINE_ASIN] = "asin";
1073 names[SYMENGINE_ACOS] = "acos";
1074 names[SYMENGINE_ASEC] = "asec";
1075 names[SYMENGINE_ACSC] = "acsc";
1076 names[SYMENGINE_ATAN] = "atan";
1077 names[SYMENGINE_ACOT] = "acot";
1078 names[SYMENGINE_ATAN2] = "atan2";
1079 names[SYMENGINE_SINH] = "sinh";
1080 names[SYMENGINE_CSCH] = "csch";
1081 names[SYMENGINE_COSH] = "cosh";
1082 names[SYMENGINE_SECH] = "sech";
1083 names[SYMENGINE_TANH] = "tanh";
1084 names[SYMENGINE_COTH] = "coth";
1085 names[SYMENGINE_ASINH] = "asinh";
1086 names[SYMENGINE_ACSCH] = "acsch";
1087 names[SYMENGINE_ACOSH] = "acosh";
1088 names[SYMENGINE_ATANH] = "atanh";
1089 names[SYMENGINE_ACOTH] = "acoth";
1090 names[SYMENGINE_ASECH] = "asech";
1091 names[SYMENGINE_LOG] = "log";
1092 names[SYMENGINE_LAMBERTW] = "lambertw";
1093 names[SYMENGINE_ZETA] = "zeta";
1094 names[SYMENGINE_DIRICHLET_ETA] = "dirichlet_eta";
1095 names[SYMENGINE_KRONECKERDELTA] = "kroneckerdelta";
1096 names[SYMENGINE_LEVICIVITA] = "levicivita";
1097 names[SYMENGINE_FLOOR] = "floor";
1098 names[SYMENGINE_CEILING] = "ceiling";
1099 names[SYMENGINE_TRUNCATE] = "truncate";
1100 names[SYMENGINE_ERF] = "erf";
1101 names[SYMENGINE_ERFC] = "erfc";
1102 names[SYMENGINE_LOWERGAMMA] = "lowergamma";
1103 names[SYMENGINE_UPPERGAMMA] = "uppergamma";
1104 names[SYMENGINE_BETA] = "beta";
1105 names[SYMENGINE_LOGGAMMA] = "loggamma";
1106 names[SYMENGINE_LOG] = "log";
1107 names[SYMENGINE_POLYGAMMA] = "polygamma";
1108 names[SYMENGINE_GAMMA] = "gamma";
1109 names[SYMENGINE_ABS] = "abs";
1110 names[SYMENGINE_MAX] = "max";
1111 names[SYMENGINE_MIN] = "min";
1112 names[SYMENGINE_SIGN] = "sign";
1113 names[SYMENGINE_CONJUGATE] = "conjugate";
1114 names[SYMENGINE_PRIMEPI] = "primepi";
1115 names[SYMENGINE_PRIMORIAL] = "primorial";
1116 names[SYMENGINE_UNEVALUATED_EXPR] = "";
1117 return names;
1118}
1119
1120std::string StrPrinter::print_mul()
1121{
1122 return "*";
1123}
1124
1125void JuliaStrPrinter::_print_pow(std::ostringstream &o,
1126 const RCP<const Basic> &a,
1127 const RCP<const Basic> &b)
1128{
1129 if (eq(*a, *E)) {
1130 o << "exp(" << apply(b) << ")";
1131 } else if (eq(*b, *rational(1, 2))) {
1132 o << "sqrt(" << apply(a) << ")";
1133 } else {
1134 o << parenthesizeLE(a, PrecedenceEnum::Pow);
1135 o << "^";
1136 o << parenthesizeLE(b, PrecedenceEnum::Pow);
1137 }
1138}
1139
1140void JuliaStrPrinter::bvisit(const Constant &x)
1141{
1142 if (eq(x, *E)) {
1143 str_ = "exp(1)";
1144 } else {
1145 str_ = x.get_name();
1146 std::transform(str_.begin(), str_.end(), str_.begin(), ::tolower);
1147 }
1148}
1149
1150void JuliaStrPrinter::bvisit(const NaN &x)
1151{
1153 s << "NaN";
1154 str_ = s.str();
1155}
1156
1157void JuliaStrPrinter::bvisit(const Infty &x)
1158{
1160 if (x.is_negative_infinity())
1161 s << "-Inf";
1162 else if (x.is_positive_infinity())
1163 s << "Inf";
1164 else
1165 s << "zoo";
1166 str_ = s.str();
1167}
1168
1169std::string JuliaStrPrinter::get_imag_symbol()
1170{
1171 return "im";
1172}
1173
1174std::string StrPrinter::get_imag_symbol()
1175{
1176 return "I";
1177}
1178
1179std::string str(const Basic &x)
1180{
1181 StrPrinter strPrinter;
1182 return strPrinter.apply(x);
1183}
1184
1185std::string str(const DenseMatrix &x)
1186{
1187 return x.__str__();
1188}
1189
1190std::string julia_str(const Basic &x)
1191{
1192 JuliaStrPrinter strPrinter;
1193 return strPrinter.apply(x);
1194}
1195} // namespace SymEngine
T assign(T... args)
T max(T... args)
Main namespace for SymEngine package.
Definition: add.cpp:19
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
Definition: basic-inl.h:21
RCP< const Number > rational(long n, long d)
convenience creator from two longs
Definition: rational.h:328
@ TypeID_Count
Definition: basic.h:52
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
Definition: basic-inl.h:29
RCP< const Basic > neg(const RCP< const Basic > &a)
Negation.
Definition: mul.cpp:443
T precision(T... args)
T lround(T... args)
T size(T... args)
T str(T... args)
Less operator (<) using cmp:
Definition: strprinter.cpp:8
bool operator()(const RCP< const Basic > &x, const RCP< const Basic > &y) const
true if x < y, false otherwise
Definition: strprinter.cpp:10
T substr(T... args)
T transform(T... args)