2 #include <symengine/printers/strprinter.h>
10 bool operator()(
const RCP<const Basic> &x,
const RCP<const Basic> &y)
const
14 return x->__cmp__(*y) == -1;
21 "| __|_ _ _____| __|___ ___|_|___ ___ \n"
22 "|__ | | | | __| | . | | | -_|\n"
23 "|_____|_ |_|_|_|_____|_|_|_ |_|_|_|___|\n"
28 void Precedence::bvisit(
const Add &x)
30 precedence = PrecedenceEnum::Add;
33 void Precedence::bvisit(
const Mul &x)
35 precedence = PrecedenceEnum::Mul;
38 void Precedence::bvisit(
const Relational &x)
40 precedence = PrecedenceEnum::Relational;
43 void Precedence::bvisit(
const Pow &x)
45 precedence = PrecedenceEnum::Pow;
48 void Precedence::bvisit(
const GaloisField &x)
54 void Precedence::bvisit(
const Rational &x)
56 precedence = PrecedenceEnum::Add;
59 void Precedence::bvisit(
const Complex &x)
62 if (x.imaginary_ == 1) {
63 precedence = PrecedenceEnum::Atom;
65 precedence = PrecedenceEnum::Mul;
68 precedence = PrecedenceEnum::Add;
72 void Precedence::bvisit(
const Integer &x)
74 if (x.is_negative()) {
75 precedence = PrecedenceEnum::Mul;
77 precedence = PrecedenceEnum::Atom;
81 void Precedence::bvisit(
const RealDouble &x)
83 if (x.is_negative()) {
84 precedence = PrecedenceEnum::Mul;
86 precedence = PrecedenceEnum::Atom;
90 #ifdef HAVE_SYMENGINE_PIRANHA
91 void Precedence::bvisit(
const URatPSeriesPiranha &x)
93 precedence = PrecedenceEnum::Add;
96 void Precedence::bvisit(
const UPSeriesPiranha &x)
98 precedence = PrecedenceEnum::Add;
101 void Precedence::bvisit(
const ComplexDouble &x)
103 precedence = PrecedenceEnum::Add;
105 #ifdef HAVE_SYMENGINE_MPFR
106 void Precedence::bvisit(
const RealMPFR &x)
108 if (x.is_negative()) {
109 precedence = PrecedenceEnum::Mul;
111 precedence = PrecedenceEnum::Atom;
115 #ifdef HAVE_SYMENGINE_MPC
116 void Precedence::bvisit(
const ComplexMPC &x)
118 precedence = PrecedenceEnum::Add;
122 void Precedence::bvisit(
const Basic &x)
124 precedence = PrecedenceEnum::Atom;
127 PrecedenceEnum Precedence::getPrecedence(
const RCP<const Basic> &x)
133 void StrPrinter::bvisit(
const Basic &x)
136 s <<
"<" << typeName<Basic>(x) <<
" instance at " << (
const void *)
this
141 void StrPrinter::bvisit(
const Symbol &x)
146 void StrPrinter::bvisit(
const Infty &x)
149 if (x.is_negative_infinity())
151 else if (x.is_positive_infinity())
158 void StrPrinter::bvisit(
const NaN &x)
163 void StrPrinter::bvisit(
const Integer &x)
166 s << x.as_integer_class();
170 void StrPrinter::bvisit(
const Rational &x)
173 s << x.as_rational_class();
177 void StrPrinter::bvisit(
const Complex &x)
183 if (mp_sign(x.imaginary_) == 1) {
189 if (x.imaginary_ != mp_sign(x.imaginary_)) {
190 s << mp_abs(x.imaginary_);
191 s << print_mul() << get_imag_symbol();
196 if (x.imaginary_ != mp_sign(x.imaginary_)) {
198 s << print_mul() << get_imag_symbol();
200 if (mp_sign(x.imaginary_) == 1) {
201 s << get_imag_symbol();
203 s <<
"-" << get_imag_symbol();
216 if (str_.find(
".") == std::string::npos
217 and str_.find(
"e") == std::string::npos) {
227 void StrPrinter::bvisit(
const RealDouble &x)
229 str_ = print_double(x.i);
232 void StrPrinter::bvisit(
const ComplexDouble &x)
234 str_ = print_double(x.i.real());
235 if (x.i.imag() < 0) {
236 str_ +=
" - " + print_double(-x.i.imag()) + print_mul()
239 str_ +=
" + " + print_double(x.i.imag()) + print_mul()
244 void StrPrinter::bvisit(
const Equality &x)
247 s << apply(x.get_arg1()) <<
" == " << apply(x.get_arg2());
251 void StrPrinter::bvisit(
const Unequality &x)
254 s << apply(x.get_arg1()) <<
" != " << apply(x.get_arg2());
258 void StrPrinter::bvisit(
const LessThan &x)
261 s << apply(x.get_arg1()) <<
" <= " << apply(x.get_arg2());
265 void StrPrinter::bvisit(
const StrictLessThan &x)
268 s << apply(x.get_arg1()) <<
" < " << apply(x.get_arg2());
272 void StrPrinter::bvisit(
const Interval &x)
275 if (x.get_left_open())
279 s << *x.get_start() <<
", " << *x.get_end();
280 if (x.get_right_open())
287 void StrPrinter::bvisit(
const BooleanAtom &x)
296 void StrPrinter::bvisit(
const And &x)
299 auto container = x.get_container();
301 s << apply(*container.begin());
302 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
303 s <<
", " << apply(*it);
309 void StrPrinter::bvisit(
const Or &x)
312 auto container = x.get_container();
314 s << apply(*container.begin());
315 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
316 s <<
", " << apply(*it);
322 void StrPrinter::bvisit(
const Xor &x)
325 auto container = x.get_container();
327 s << apply(*container.begin());
328 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
329 s <<
", " << apply(*it);
335 void StrPrinter::bvisit(
const Not &x)
338 s <<
"Not(" << *x.get_arg() <<
")";
342 void StrPrinter::bvisit(
const Contains &x)
345 s <<
"Contains(" << apply(x.get_expr()) <<
", " << apply(x.get_set())
350 void StrPrinter::bvisit(
const Piecewise &x)
353 auto vec = x.get_vec();
354 auto it = vec.begin();
358 s << apply((*it).first);
360 s << apply((*it).second);
363 if (it != vec.end()) {
373 void StrPrinter::bvisit(
const Complexes &x)
378 void StrPrinter::bvisit(
const Reals &x)
383 void StrPrinter::bvisit(
const Rationals &x)
388 void StrPrinter::bvisit(
const Integers &x)
393 void StrPrinter::bvisit(
const Naturals &x)
398 void StrPrinter::bvisit(
const Naturals0 &x)
403 void StrPrinter::bvisit(
const EmptySet &x)
408 void StrPrinter::bvisit(
const Union &x)
411 s << apply(*x.get_container().begin());
412 for (
auto it = ++(x.get_container().begin()); it != x.get_container().end();
414 s <<
" U " << apply(*it);
419 void StrPrinter::bvisit(
const Intersection &x)
422 vec_basic vec = x.get_args();
424 s << parenthesize(apply(vec));
428 void StrPrinter::bvisit(
const Complement &x)
431 s << apply(*x.get_universe());
432 s <<
" \\ " << apply(*x.get_container());
436 void StrPrinter::bvisit(
const ImageSet &x)
439 s <<
"{" << apply(*x.get_expr()) <<
" | ";
440 s << apply(*x.get_symbol());
441 s <<
" in " << apply(*x.get_baseset()) <<
"}";
445 void StrPrinter::bvisit(
const UniversalSet &x)
447 str_ =
"UniversalSet";
450 void StrPrinter::bvisit(
const FiniteSet &x)
453 s << x.get_container();
457 void StrPrinter::bvisit(
const ConditionSet &x)
460 s <<
"{" << apply(*x.get_symbol());
461 s <<
" | " << apply(x.get_condition()) <<
"}";
465 #ifdef HAVE_SYMENGINE_MPFR
466 void StrPrinter::bvisit(
const RealMPFR &x)
472 / 3.3219280948873626)
475 = mpfr_get_str(
nullptr, &ex, 10, digits, x.i.get_mpfr_t(), MPFR_RNDN);
478 if (str_.at(0) ==
'-') {
480 str_ = str_.substr(1, str_.length() - 1);
483 s << str_.at(0) <<
'.' << str_.substr(1, str_.length() - 1) <<
'e'
486 s << str_.substr(0, (
unsigned long)ex) <<
".";
487 s << str_.substr((
unsigned long)ex, str_.length() - ex);
488 }
else if (ex > -5) {
490 for (
int i = 0; i < -ex; ++i) {
495 s << str_.at(0) <<
'.' << str_.substr(1, str_.length() - 1) <<
'e'
502 #ifdef HAVE_SYMENGINE_MPC
503 void StrPrinter::bvisit(
const ComplexMPC &x)
505 RCP<const Number> imag = x.imaginary_part();
506 if (imag->is_negative()) {
508 str = str.substr(1, str.length() - 1);
509 str_ = this->apply(x.real_part()) +
" - " + str + print_mul()
512 str_ = this->apply(x.real_part()) +
" + " + this->apply(imag)
513 + print_mul() + get_imag_symbol();
517 void StrPrinter::bvisit(
const Add &x)
522 x.get_dict().begin(), x.get_dict().end());
524 if (
neq(*(x.get_coef()), *zero)) {
525 o << this->apply(x.get_coef());
528 for (
const auto &p : dict) {
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);
535 t = parenthesizeLT(p.second, PrecedenceEnum::Mul) + print_mul()
536 + parenthesizeLT(p.first, PrecedenceEnum::Mul);
541 o <<
" - " << t.
substr(1);
554 const RCP<const Basic> &b)
557 o <<
"exp(" << apply(b) <<
")";
559 o <<
"sqrt(" << apply(a) <<
")";
561 o << parenthesizeLE(a, PrecedenceEnum::Pow);
563 o << parenthesizeLE(b, PrecedenceEnum::Pow);
567 void StrPrinter::bvisit(
const Mul &x)
573 if (
eq(*(x.get_coef()), *minus_one)) {
575 }
else if (
neq(*(x.get_coef()), *one)) {
576 if (not split_mul_coef()) {
577 o << parenthesizeLT(x.get_coef(), PrecedenceEnum::Mul)
581 RCP<const Basic> numer, denom;
582 as_numer_denom(x.get_coef(), outArg(numer), outArg(denom));
583 if (
neq(*numer, *one)) {
585 o << parenthesizeLT(numer, PrecedenceEnum::Mul) << print_mul();
587 if (
neq(*denom, *one)) {
589 o2 << parenthesizeLT(denom, PrecedenceEnum::Mul) << print_mul();
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);
601 _print_pow(o2, p.first,
neg(p.second));
606 if (
eq(*(p.second), *one)) {
607 o << parenthesizeLT(p.first, PrecedenceEnum::Mul);
609 _print_pow(o, p.first, p.second);
617 o <<
"1" << print_mul();
627 str_ = print_div(s, s2,
true);
629 str_ = print_div(s, s2,
false);
640 return num +
"/" + parenthesize(den);
642 return num +
"/" + den;
646 bool StrPrinter::split_mul_coef()
651 void StrPrinter::bvisit(
const Pow &x)
654 _print_pow(o, x.get_base(), x.get_exp());
658 template <
typename T>
659 char _print_sign(
const T &i)
668 void StrPrinter::bvisit(
const GaloisField &x)
675 auto dict = x.get_dict();
676 if (x.get_dict().size() == 0)
679 for (
auto it = dict.size(); it-- != 0;) {
687 s <<
" " << _print_sign(dict[it]) <<
" "
694 if (mp_abs(dict[it]) == 1) {
700 s << detail::poly_print(x.get_var());
702 s <<
" " << _print_sign(dict[it]) <<
" "
703 << detail::poly_print(x.get_var());
711 s << dict[it] <<
"*" << detail::poly_print(x.get_var());
713 s <<
" " << _print_sign(dict[it]) <<
" " << mp_abs(dict[it])
714 <<
"*" << detail::poly_print(x.get_var());
731 template <
typename P>
739 for (
auto it = x.obegin(); it != x.oend(); ++it) {
742 if (it->first == 0) {
746 s <<
" " << _print_sign(m) <<
" " << mp_abs(m);
752 if (mp_abs(m) == 1) {
758 s << detail::poly_print(x.get_var());
760 s <<
" " << _print_sign(m) <<
" "
761 << detail::poly_print(x.get_var());
769 s << m <<
"*" << detail::poly_print(x.get_var());
771 s <<
" " << _print_sign(m) <<
" " << mp_abs(m) <<
"*"
772 << detail::poly_print(x.get_var());
776 if (it->first != 1) {
777 s <<
"**" << it->first;
787 void StrPrinter::bvisit(
const UIntPoly &x)
789 str_ = upoly_print<UIntPoly>(x);
792 void StrPrinter::bvisit(
const URatPoly &x)
794 str_ = upoly_print<URatPoly>(x);
797 #ifdef HAVE_SYMENGINE_FLINT
798 void StrPrinter::bvisit(
const UIntPolyFlint &x)
800 str_ = upoly_print<UIntPolyFlint>(x);
802 void StrPrinter::bvisit(
const URatPolyFlint &x)
804 str_ = upoly_print<URatPolyFlint>(x);
808 #ifdef HAVE_SYMENGINE_PIRANHA
809 void StrPrinter::bvisit(
const UIntPolyPiranha &x)
811 str_ = upoly_print<UIntPolyPiranha>(x);
813 void StrPrinter::bvisit(
const URatPolyPiranha &x)
815 str_ = upoly_print<URatPolyPiranha>(x);
821 void StrPrinter::bvisit(
const UExprPoly &x)
824 if (x.get_dict().size() == 0)
827 s << x.get_poly().__str__(detail::poly_print(x.get_var()));
831 void StrPrinter::bvisit(
const UnivariateSeries &x)
834 o << x.get_poly().__str__(x.get_var()) <<
" + O(" << x.get_var() <<
"**"
835 << x.get_degree() <<
")";
839 #ifdef HAVE_SYMENGINE_PIRANHA
840 void StrPrinter::bvisit(
const URatPSeriesPiranha &x)
843 o << x.get_poly() <<
" + O(" << x.get_var() <<
"**" << x.get_degree()
847 void StrPrinter::bvisit(
const UPSeriesPiranha &x)
850 o << x.get_poly() <<
" + O(" << x.get_var() <<
"**" << x.get_degree()
856 void StrPrinter::bvisit(
const Constant &x)
864 for (
auto p = d.begin(); p != d.end(); p++) {
865 if (p != d.begin()) {
868 o << this->apply(*p);
873 void StrPrinter::bvisit(
const Function &x)
877 o << names_[x.get_type_code()];
878 vec_basic vec = x.get_args();
879 o << parenthesize(apply(vec));
883 void StrPrinter::bvisit(
const FunctionSymbol &x)
887 vec_basic vec = x.get_args();
888 o << parenthesize(apply(vec));
892 void StrPrinter::bvisit(
const Derivative &x)
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);
904 void StrPrinter::bvisit(
const Subs &x)
907 for (
auto p = x.get_dict().begin(); p != x.get_dict().end(); p++) {
908 if (p != x.get_dict().begin()) {
912 vars << apply(p->first);
913 point << apply(p->second);
915 o <<
"Subs(" << apply(x.get_arg()) <<
", (" << vars.
str() <<
"), ("
916 << point.
str() <<
"))";
920 void StrPrinter::bvisit(
const NumberWrapper &x)
925 void StrPrinter::bvisit(
const MIntPoly &x)
933 for (vec_uint exps : v) {
934 integer_class c = x.get_poly().dict_.find(exps)->second;
936 s <<
" " << _print_sign(c) <<
" ";
943 bool first_var =
true;
944 for (
auto it : x.get_vars()) {
949 expr << it->__str__();
951 expr <<
"**" << exps[i];
956 if (mp_abs(c) != 1) {
958 if (!expr.
str().empty()) {
961 }
else if (expr.
str().empty()) {
973 void StrPrinter::bvisit(
const MExprPoly &x)
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) {
992 bool first_var =
true;
993 for (
auto it : x.get_vars()) {
998 expr << it->__str__();
999 if (exps[i] > 1 or exps[i] < 0)
1000 expr <<
"**" << exps[i];
1005 if (c != 1 && c != -1) {
1007 if (!expr.
str().empty()) {
1010 }
else if (expr.
str().empty()) {
1017 if (s.
str().empty())
1022 void StrPrinter::bvisit(
const Tuple &x)
1025 vec_basic vec = x.get_args();
1026 o << parenthesize(apply(vec));
1030 void StrPrinter::bvisit(
const IdentityMatrix &x)
1035 void StrPrinter::bvisit(
const ZeroMatrix &x)
1040 std::string StrPrinter::parenthesizeLT(
const RCP<const Basic> &x,
1041 PrecedenceEnum precedenceEnum)
1044 if (prec.getPrecedence(x) < precedenceEnum) {
1045 return parenthesize(apply(x));
1051 std::string StrPrinter::parenthesizeLE(
const RCP<const Basic> &x,
1052 PrecedenceEnum precedenceEnum)
1055 if (prec.getPrecedence(x) <= precedenceEnum) {
1056 return parenthesize(apply(x));
1064 return "(" + x +
")";
1067 std::string StrPrinter::apply(
const RCP<const Basic> &b)
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";
1133 names[SYMENGINE_UNEVALUATED_EXPR] =
"";
1143 const RCP<const Basic> &a,
1144 const RCP<const Basic> &b)
1147 o <<
"exp(" << apply(b) <<
")";
1149 o <<
"sqrt(" << apply(a) <<
")";
1151 o << parenthesizeLE(a, PrecedenceEnum::Pow);
1153 o << parenthesizeLE(b, PrecedenceEnum::Pow);
1157 void JuliaStrPrinter::bvisit(
const Constant &x)
1162 str_ = x.get_name();
1163 std::transform(str_.begin(), str_.end(), str_.begin(), ::tolower);
1167 void JuliaStrPrinter::bvisit(
const NaN &x)
1172 void JuliaStrPrinter::bvisit(
const Infty &x)
1175 if (x.is_negative_infinity())
1177 else if (x.is_positive_infinity())
1196 StrPrinter strPrinter;
1197 return strPrinter.apply(x);
1207 JuliaStrPrinter strPrinter;
1208 return strPrinter.apply(x);
Main namespace for SymEngine package.
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
bool neq(const Basic &a, const Basic &b)
Checks inequality for a and b
RCP< const Number > rational(long n, long d)
convenience creator from two longs
RCP< const Basic > neg(const RCP< const Basic > &a)
Negation.
Less operator (<) using cmp:
bool operator()(const RCP< const Basic > &x, const RCP< const Basic > &y) const
true if x < y, false otherwise