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