2 #include <symengine/printers/strprinter.h>
3 #include <symengine/printers/unicode.h>
7 #define U8(x) reinterpret_cast<const char *>(u8##x)
12 struct PrinterBasicCmp {
14 bool operator()(
const RCP<const Basic> &x,
const RCP<const Basic> &y)
const
18 return x->__cmp__(*y) == -1;
22 void UnicodePrinter::bvisit(
const Basic &x)
25 s << U8(
"<") << typeName<Basic>(x) << U8(
" instance at ")
26 << (
const void *)
this << U8(
">");
27 StringBox box(s.
str());
31 void UnicodePrinter::bvisit(
const Symbol &x)
33 box_ = StringBox(x.get_name());
36 void UnicodePrinter::bvisit(
const Infty &x)
38 if (x.is_negative_infinity())
39 box_ = StringBox(U8(
"-\u221E"), 2);
40 else if (x.is_positive_infinity())
41 box_ = StringBox(U8(
"\u221E"), 1);
43 box_ = StringBox(U8(
"\U0001D467\u221E"), 2);
46 void UnicodePrinter::bvisit(
const NaN &x)
48 box_ = StringBox(U8(
"NaN"));
51 void UnicodePrinter::bvisit(
const Integer &x)
54 s << x.as_integer_class();
55 box_ = StringBox(s.
str());
58 void UnicodePrinter::bvisit(
const Rational &x)
61 num << (*x.get_num()).as_integer_class();
62 StringBox rat(num.
str());
64 denom << (*x.get_den()).as_integer_class();
65 StringBox denbox(denom.
str());
66 rat.add_below_unicode_line(denbox);
70 void UnicodePrinter::bvisit(
const Complex &x)
77 if (mp_sign(x.imaginary_) == 1) {
83 if (x.imaginary_ != mp_sign(x.imaginary_)) {
84 s << mp_abs(x.imaginary_);
85 s << U8(
"\u22C5") << get_imag_symbol();
88 s << get_imag_symbol();
91 if (x.imaginary_ != mp_sign(x.imaginary_)) {
93 s << U8(
"\u22C5") << get_imag_symbol();
96 if (mp_sign(x.imaginary_) == 1) {
97 s << get_imag_symbol();
99 s << U8(
"-") << get_imag_symbol();
107 StringBox box(str, width);
111 void UnicodePrinter::bvisit(
const RealDouble &x)
113 box_ = StringBox(print_double(x.i));
116 void UnicodePrinter::bvisit(
const ComplexDouble &x)
119 if (x.i.imag() < 0) {
120 str += U8(
" - ") + print_double(-x.i.imag());
122 str += U8(
" + ") + print_double(x.i.imag());
124 auto len = str.length();
125 str += U8(
"\u22C5") + get_imag_symbol();
126 box_ = StringBox(str, len + 2);
129 void UnicodePrinter::bvisit(
const Equality &x)
131 StringBox box = apply(x.get_arg1());
134 StringBox rhs = apply(x.get_arg2());
139 void UnicodePrinter::bvisit(
const Unequality &x)
141 StringBox box = apply(x.get_arg1());
142 StringBox
eq(U8(
" \u2260 "), 3);
144 StringBox rhs = apply(x.get_arg2());
149 void UnicodePrinter::bvisit(
const LessThan &x)
151 StringBox box = apply(x.get_arg1());
152 StringBox
eq(U8(
" \u2264 "), 3);
154 StringBox rhs = apply(x.get_arg2());
159 void UnicodePrinter::bvisit(
const StrictLessThan &x)
161 StringBox box = apply(x.get_arg1());
162 StringBox
eq(
" < ", 3);
164 StringBox rhs = apply(x.get_arg2());
169 void UnicodePrinter::bvisit(
const Interval &x)
171 StringBox box = apply(x.get_start());
172 StringBox comma = StringBox(
", ");
173 box.add_right(comma);
174 StringBox
end = StringBox(apply(x.get_end()));
176 if (x.get_left_open()) {
177 box.add_left_parens();
179 box.add_left_sqbracket();
181 if (x.get_right_open())
182 box.add_right_parens();
184 box.add_right_sqbracket();
188 void UnicodePrinter::bvisit(
const BooleanAtom &x)
191 box_ = StringBox(
"true");
193 box_ = StringBox(
"false");
197 void UnicodePrinter::bvisit(
const And &x)
199 auto container = x.get_container();
200 StringBox box = apply(*container.begin());
201 StringBox op(U8(
" \u2227 "), 3);
202 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
204 StringBox
next = apply(*it);
210 void UnicodePrinter::bvisit(
const Or &x)
212 auto container = x.get_container();
213 StringBox box = apply(*container.begin());
214 StringBox op(U8(
" \u2228 "), 3);
215 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
217 StringBox
next = apply(*it);
223 void UnicodePrinter::bvisit(
const Xor &x)
225 auto container = x.get_container();
226 StringBox box = apply(*container.begin());
227 StringBox op(U8(
" \u22BB "), 3);
228 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
230 StringBox
next = apply(*it);
236 void UnicodePrinter::bvisit(
const Not &x)
238 StringBox box(U8(
"\u00AC"), 1);
239 StringBox expr = apply(*x.get_arg());
240 expr.enclose_parens();
245 void UnicodePrinter::bvisit(
const Contains &x)
247 StringBox s = apply(x.get_expr());
248 StringBox op(U8(
" \u220A "), 3);
250 auto right = apply(x.get_set());
255 void UnicodePrinter::bvisit(
const Piecewise &x)
259 auto vec = x.get_vec();
260 auto it = vec.begin();
262 StringBox piece = apply((*it).first);
263 StringBox mid(
" if ");
264 piece.add_right(mid);
265 StringBox second = apply((*it).second);
266 piece.add_right(second);
267 box.add_below(piece);
269 if (it == vec.end()) {
273 box.add_left_curly();
277 void UnicodePrinter::bvisit(
const Complexes &x)
279 box_ = StringBox(U8(
"\u2102"), 1);
282 void UnicodePrinter::bvisit(
const Reals &x)
284 box_ = StringBox(U8(
"\u211D"), 1);
287 void UnicodePrinter::bvisit(
const Rationals &x)
289 box_ = StringBox(U8(
"\u211A"), 1);
292 void UnicodePrinter::bvisit(
const Integers &x)
294 box_ = StringBox(U8(
"\u2124"), 1);
297 void UnicodePrinter::bvisit(
const Naturals &x)
299 box_ = StringBox(U8(
"\u2115"), 1);
302 void UnicodePrinter::bvisit(
const Naturals0 &x)
304 box_ = StringBox(U8(
"\u2115\u2080"), 2);
307 void UnicodePrinter::bvisit(
const EmptySet &x)
309 box_ = StringBox(U8(
"\u2205"), 1);
312 void UnicodePrinter::bvisit(
const UniversalSet &x)
314 box_ = StringBox(U8(
"\U0001D54C"), 1);
317 void UnicodePrinter::bvisit(
const Union &x)
319 auto container = x.get_container();
320 StringBox box = apply(*container.begin());
321 StringBox op(U8(
" \u222A "), 3);
322 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
324 StringBox
next = apply(*it);
330 void UnicodePrinter::bvisit(
const Intersection &x)
332 auto container = x.get_container();
333 StringBox box = apply(*container.begin());
334 StringBox op(U8(
" \u2229 "), 3);
335 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
337 StringBox
next = apply(*it);
343 void UnicodePrinter::bvisit(
const Complement &x)
345 StringBox box = apply(*x.get_universe());
346 StringBox op(U8(
" \\ "));
348 StringBox rhs = apply(*x.get_container());
353 void UnicodePrinter::bvisit(
const ImageSet &x)
355 StringBox box = apply(*x.get_expr());
356 StringBox bar(
" | ");
358 StringBox
symbol = apply(*x.get_symbol());
360 StringBox in(U8(
" \u220A "), 3);
362 StringBox base = apply(*x.get_baseset());
364 box.enclose_curlies();
368 void UnicodePrinter::bvisit(
const FiniteSet &x)
371 StringBox comma(
", ");
373 for (
const auto &elem : x.get_container()) {
375 box.add_right(comma);
379 StringBox arg = apply(elem);
382 box.enclose_curlies();
386 void UnicodePrinter::bvisit(
const ConditionSet &x)
388 StringBox box = apply(*x.get_symbol());
389 StringBox bar(
" | ");
391 StringBox cond = apply(*x.get_condition());
393 box.enclose_curlies();
397 void UnicodePrinter::bvisit(
const Add &x)
402 x.get_dict().begin(), x.get_dict().end());
404 if (
neq(*(x.get_coef()), *zero)) {
405 box = apply(x.get_coef());
409 for (
const auto &p : dict) {
411 if (
eq(*(p.second), *one)) {
412 t = parenthesizeLT(p.first, PrecedenceEnum::Add);
413 }
else if (
eq(*(p.second), *minus_one)) {
415 t = parenthesizeLT(p.first, PrecedenceEnum::Mul);
417 if (down_cast<const Number &>(*p.second).is_negative()) {
421 t = parenthesizeLT(p.second, PrecedenceEnum::Mul);
422 auto op = print_mul();
424 auto rhs = parenthesizeLT(p.first, PrecedenceEnum::Mul);
447 void UnicodePrinter::_print_pow(
const RCP<const Basic> &a,
448 const RCP<const Basic> &b)
451 StringBox box = apply(a);
455 StringBox base = parenthesizeLE(a, PrecedenceEnum::Pow);
456 StringBox
exp = parenthesizeLE(b, PrecedenceEnum::Pow);
462 void UnicodePrinter::bvisit(
const Mul &x)
464 StringBox box1, box2;
467 StringBox mulbox = print_mul();
469 bool first_box1 =
true;
470 bool first_box2 =
true;
472 if (
eq(*(x.get_coef()), *minus_one)) {
473 box1 = StringBox(
"-");
474 }
else if (
neq(*(x.get_coef()), *one)) {
475 RCP<const Basic> numer, denom;
476 as_numer_denom(x.get_coef(), outArg(numer), outArg(denom));
477 if (
neq(*numer, *one)) {
479 box1 = parenthesizeLT(numer, PrecedenceEnum::Mul);
482 if (
neq(*denom, *one)) {
484 box2 = parenthesizeLT(denom, PrecedenceEnum::Mul);
489 for (
const auto &p : x.get_dict()) {
490 if ((is_a<Integer>(*p.second) or is_a<Rational>(*p.second))
491 and down_cast<const Number &>(*p.second).is_negative()) {
492 if (not first_box2) {
493 box2.add_right(mulbox);
497 if (
eq(*(p.second), *minus_one)) {
498 auto expr = parenthesizeLT(p.first, PrecedenceEnum::Mul);
499 box2.add_right(expr);
501 _print_pow(p.first,
neg(p.second));
502 box2.add_right(box_);
506 if (not first_box1) {
507 box1.add_right(mulbox);
511 if (
eq(*(p.second), *one)) {
512 auto expr = parenthesizeLT(p.first, PrecedenceEnum::Mul);
513 box1.add_right(expr);
515 _print_pow(p.first, p.second);
516 box1.add_right(box_);
523 auto onebox = StringBox(
"1");
524 box1.add_right(onebox);
525 box1.add_right(mulbox);
530 box2.enclose_parens();
532 box1.add_below_unicode_line(box2);
537 void UnicodePrinter::bvisit(
const Pow &x)
539 _print_pow(x.get_base(), x.get_exp());
542 void UnicodePrinter::bvisit(
const Constant &x)
547 box_ = StringBox(U8(
"\U0001D70B"), 1);
548 }
else if (
eq(x, *E)) {
549 box_ = StringBox(U8(
"\U0001D452"), 1);
550 }
else if (
eq(x, *EulerGamma)) {
551 box_ = StringBox(U8(
"\U0001D6FE"), 1);
552 }
else if (
eq(x, *Catalan)) {
553 box_ = StringBox(U8(
"\U0001D43A"), 1);
554 }
else if (
eq(x, *GoldenRatio)) {
555 box_ = StringBox(U8(
"\U0001D719"), 1);
559 StringBox UnicodePrinter::apply(
const vec_basic &d)
562 StringBox comma(
", ");
563 for (
auto p = d.begin(); p != d.end(); p++) {
564 if (p != d.begin()) {
565 box.add_right(comma);
567 StringBox arg = apply(*p);
573 void UnicodePrinter::bvisit(
const Abs &x)
575 StringBox box = apply(*x.get_arg());
580 void UnicodePrinter::bvisit(
const Floor &x)
582 StringBox box = apply(*x.get_arg());
587 void UnicodePrinter::bvisit(
const Ceiling &x)
589 StringBox box = apply(*x.get_arg());
590 box.enclose_ceiling();
597 names[SYMENGINE_LAMBERTW] =
"W";
598 names[SYMENGINE_ZETA] = U8(
"\U0001D701");
599 names[SYMENGINE_DIRICHLET_ETA] = U8(
"\U0001D702");
600 names[SYMENGINE_LOWERGAMMA] = U8(
"\U0001D6FE");
601 names[SYMENGINE_UPPERGAMMA] = U8(
"\u0393");
602 names[SYMENGINE_BETA] = U8(
"B");
603 names[SYMENGINE_LOGGAMMA] = U8(
"log \u0393");
604 names[SYMENGINE_GAMMA] = U8(
"\u0393");
605 names[SYMENGINE_PRIMEPI] = U8(
"\U0001D70B");
613 for (
auto &name : names) {
616 lengths[SYMENGINE_LAMBERTW] = 1;
617 lengths[SYMENGINE_ZETA] = 1;
618 lengths[SYMENGINE_DIRICHLET_ETA] = 1;
619 lengths[SYMENGINE_LOWERGAMMA] = 1;
620 lengths[SYMENGINE_UPPERGAMMA] = 1;
621 lengths[SYMENGINE_BETA] = 1;
622 lengths[SYMENGINE_LOGGAMMA] = 5;
623 lengths[SYMENGINE_GAMMA] = 1;
624 lengths[SYMENGINE_PRIMEPI] = 1;
628 void UnicodePrinter::bvisit(
const Function &x)
632 = init_unicode_printer_lengths(names_);
633 StringBox box(names_[x.get_type_code()], lengths_[x.get_type_code()]);
634 vec_basic vec = x.get_args();
635 StringBox args = apply(vec);
636 args.enclose_parens();
641 void UnicodePrinter::bvisit(
const FunctionSymbol &x)
643 StringBox box(x.get_name());
645 StringBox comma(
", ");
647 for (
auto arg : x.get_args()) {
651 args.add_right(comma);
653 StringBox argbox = apply(arg);
654 args.add_right(argbox);
656 args.enclose_parens();
661 void UnicodePrinter::bvisit(
const Tuple &x)
663 vec_basic vec = x.get_args();
664 StringBox args = apply(vec);
665 args.enclose_parens();
669 StringBox UnicodePrinter::parenthesizeLT(
const RCP<const Basic> &x,
670 PrecedenceEnum precedenceEnum)
673 if (prec.getPrecedence(x) < precedenceEnum) {
675 box.enclose_parens();
682 StringBox UnicodePrinter::parenthesizeLE(
const RCP<const Basic> &x,
683 PrecedenceEnum precedenceEnum)
686 if (prec.getPrecedence(x) <= precedenceEnum) {
688 box.enclose_parens();
695 StringBox UnicodePrinter::apply(
const RCP<const Basic> &b)
701 StringBox UnicodePrinter::apply(
const Basic &b)
707 StringBox UnicodePrinter::print_mul()
709 return StringBox(U8(
"\u22C5"), 1);
714 return U8(
"\U0001D456");
719 UnicodePrinter printer;
720 return printer.apply(x).get_string();
Main namespace for SymEngine package.
RCP< const Symbol > symbol(const std::string &name)
inline version to return Symbol
bool eq(const Basic &a, const Basic &b)
Checks equality for a and b
RCP< const Basic > exp(const RCP< const Basic > &x)
Returns the natural exponential function E**x = pow(E, x)
RCP< const Basic > mul(const RCP< const Basic > &a, const RCP< const Basic > &b)
Multiplication.
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.
bool operator()(const RCP< const Basic > &x, const RCP< const Basic > &y) const
true if x < y, false otherwise