1 #include <symengine/printers/latex.h>
2 #include <symengine/printers.h>
16 if (get_den(r) == 1) {
19 s <<
"\\frac{" << get_num(r) <<
"}{" << get_den(r) <<
"}";
23 void LatexPrinter::bvisit(
const Symbol &x)
27 if (name.
find(
'\\') != std::string::npos
28 or name.
find(
'{') != std::string::npos) {
36 = {
"alpha",
"beta",
"gamma",
"Gamma",
"delta",
"Delta",
"epsilon",
37 "zeta",
"eta",
"theta",
"Theta",
"iota",
"kappa",
"lambda",
38 "Lambda",
"mu",
"nu",
"xi",
"omicron",
"pi",
"Pi",
39 "rho",
"sigma",
"Sigma",
"tau",
"upsilon",
"Upsilon",
"phi",
40 "Phi",
"chi",
"psi",
"Psi",
"omega",
"Omega"};
42 for (
auto &letter : greeks) {
47 if (name.
size() > letter.size() and name.
find(letter +
"_") == 0) {
56 void LatexPrinter::bvisit(
const Rational &x)
58 const auto &
rational = x.as_rational_class();
64 void LatexPrinter::bvisit(
const Complex &x)
68 print_rational_class(x.real_, s);
70 if (mp_sign(x.imaginary_) == 1) {
76 if (x.imaginary_ != mp_sign(x.imaginary_)) {
77 print_rational_class(mp_abs(x.imaginary_), s);
83 if (x.imaginary_ != mp_sign(x.imaginary_)) {
84 print_rational_class(x.imaginary_, s);
87 if (mp_sign(x.imaginary_) == 1) {
97 void LatexPrinter::bvisit(
const ComplexBase &x)
99 RCP<const Number> imag = x.imaginary_part();
100 if (imag->is_negative()) {
102 str = str.substr(1, str.length() - 1);
103 str_ = apply(x.real_part()) +
" - " + str +
"j";
105 str_ = apply(x.real_part()) +
" + " + apply(imag) +
"j";
108 void LatexPrinter::bvisit(
const ComplexDouble &x)
110 bvisit(
static_cast<const ComplexBase &
>(x));
113 #ifdef HAVE_SYMENGINE_MPC
114 void LatexPrinter::bvisit(
const ComplexMPC &x)
116 bvisit(
static_cast<const ComplexBase &
>(x));
120 void LatexPrinter::bvisit(
const Infty &x)
122 if (x.is_negative_infinity()) {
124 }
else if (x.is_positive_infinity()) {
127 str_ =
"\\tilde{\\infty}";
131 void LatexPrinter::bvisit(
const NaN &x)
133 str_ =
"\\mathrm{NaN}";
136 void LatexPrinter::bvisit(
const Constant &x)
140 }
else if (
eq(x, *E)) {
142 }
else if (
eq(x, *EulerGamma)) {
144 }
else if (
eq(x, *Catalan)) {
146 }
else if (
eq(x, *GoldenRatio)) {
149 throw NotImplementedError(
"Constant " + x.get_name()
150 +
" is not implemented.");
154 void LatexPrinter::bvisit(
const Derivative &x)
156 const auto &symbols = x.get_symbols();
158 if (symbols.size() == 1) {
159 if (free_symbols(*x.get_arg()).
size() == 1) {
160 s <<
"\\frac{d}{d " << apply(*symbols.begin());
162 s <<
"\\frac{\\partial}{\\partial " << apply(*symbols.begin());
165 s <<
"\\frac{\\partial^" << symbols.size() <<
"}{";
167 auto it = symbols.begin();
168 RCP<const Basic>
prev = *it;
170 for (; it != symbols.end(); ++it) {
171 if (
neq(*prev, **it)) {
173 s <<
"\\partial " << apply(*prev) <<
" ";
175 s <<
"\\partial " << apply(*prev) <<
"^" <<
count <<
" ";
184 s <<
"\\partial " << apply(*prev) <<
" ";
186 s <<
"\\partial " << apply(*prev) <<
"^" <<
count <<
" ";
189 s <<
"} " << apply(x.get_arg());
193 void LatexPrinter::bvisit(
const Subs &x)
196 o <<
"\\left. " << apply(x.get_arg()) <<
"\\right|_{\\substack{";
197 for (
auto p = x.get_dict().begin(); p != x.get_dict().end(); p++) {
198 if (p != x.get_dict().begin()) {
201 o << apply(p->first) <<
"=" << apply(p->second);
207 void LatexPrinter::bvisit(
const Equality &x)
210 s << apply(x.get_arg1()) <<
" = " << apply(x.get_arg2());
214 void LatexPrinter::bvisit(
const Unequality &x)
217 s << apply(x.get_arg1()) <<
" \\neq " << apply(x.get_arg2());
221 void LatexPrinter::bvisit(
const LessThan &x)
224 s << apply(x.get_arg1()) <<
" \\leq " << apply(x.get_arg2());
228 void LatexPrinter::bvisit(
const StrictLessThan &x)
231 s << apply(x.get_arg1()) <<
" < " << apply(x.get_arg2());
235 std::string latex(
const DenseMatrix &m,
const unsigned max_rows,
236 const unsigned max_cols)
238 const unsigned int nrows = m.nrows();
239 const unsigned int ncols = m.ncols();
240 unsigned int nrows_display = nrows;
241 if (nrows > max_rows)
242 nrows_display = max_rows - 1;
243 unsigned int ncols_display = ncols;
244 if (ncols > max_cols)
245 ncols_display = max_cols - 1;
248 s <<
"\\left[\\begin{matrix}" <<
std::endl;
251 if (ncols_display < ncols) {
252 end_of_line =
" & \\cdots" + end_of_line;
254 for (
unsigned int row_index = 0; row_index < nrows_display; row_index++) {
255 for (
unsigned int column_index = 0; column_index < ncols_display;
257 RCP<const Basic> v = m.get(row_index, column_index);
261 throw SymEngineException(
262 "cannot display uninitialized element");
266 if (column_index < ncols_display - 1)
271 if (nrows_display < nrows) {
272 for (
unsigned int column_index = 0; column_index < ncols_display;
275 if (column_index < ncols_display - 1)
280 s <<
"\\end{matrix}\\right]\n";
285 void LatexPrinter::bvisit(
const Interval &x)
288 if (x.get_left_open())
292 s << *x.get_start() <<
", " << *x.get_end();
293 if (x.get_right_open())
300 void LatexPrinter::bvisit(
const BooleanAtom &x)
303 str_ =
"\\mathrm{True}";
305 str_ =
"\\mathrm{False}";
309 void LatexPrinter::bvisit(
const And &x)
312 auto container = x.get_container();
313 if (is_a<Or>(**container.begin()) or is_a<Xor>(**container.begin())) {
314 s << parenthesize(apply(*container.begin()));
316 s << apply(*container.begin());
319 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
321 if (is_a<Or>(**it) or is_a<Xor>(**it)) {
322 s << parenthesize(apply(*it));
330 void LatexPrinter::bvisit(
const Or &x)
333 auto container = x.get_container();
334 if (is_a<And>(**container.begin()) or is_a<Xor>(**container.begin())) {
335 s << parenthesize(apply(*container.begin()));
337 s << apply(*container.begin());
340 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
342 if (is_a<And>(**it) or is_a<Xor>(**it)) {
343 s << parenthesize(apply(*it));
351 void LatexPrinter::bvisit(
const Xor &x)
354 auto container = x.get_container();
355 if (is_a<Or>(**container.begin()) or is_a<And>(**container.begin())) {
356 s << parenthesize(apply(*container.begin()));
358 s << apply(*container.begin());
361 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
363 if (is_a<Or>(**it) or is_a<And>(**it)) {
364 s << parenthesize(apply(*it));
372 void LatexPrinter::print_with_args(
const Basic &x,
const std::string &join,
375 vec_basic v = x.get_args();
376 s << apply(*v.begin());
378 for (
auto it = ++(v.begin()); it != v.end(); ++it) {
379 s <<
" " << join <<
" " << apply(*it);
383 void LatexPrinter::bvisit(
const Not &x)
385 str_ =
"\\neg " + apply(*x.get_arg());
388 void LatexPrinter::bvisit(
const Union &x)
391 print_with_args(x,
"\\cup", s);
395 void LatexPrinter::bvisit(
const Intersection &x)
398 print_with_args(x,
"\\cap", s);
402 void LatexPrinter::bvisit(
const Complement &x)
405 s << apply(x.get_universe()) <<
" \\setminus " << apply(x.get_container());
409 void LatexPrinter::bvisit(
const ImageSet &x)
412 s <<
"\\left\\{" << apply(*x.get_expr()) <<
"\\; |\\; ";
413 s << apply(*x.get_symbol());
414 s <<
" \\in " << apply(*x.get_baseset()) <<
"\\right\\}";
418 void LatexPrinter::bvisit(
const ConditionSet &x)
421 s <<
"\\left\\{" << apply(*x.get_symbol()) <<
"\\; |\\; ";
422 s << apply(x.get_condition()) <<
"\\right\\}";
426 void LatexPrinter::bvisit(
const EmptySet &x)
431 void LatexPrinter::bvisit(
const Complexes &x)
433 str_ =
"\\mathbb{C}";
436 void LatexPrinter::bvisit(
const Reals &x)
438 str_ =
"\\mathbb{R}";
441 void LatexPrinter::bvisit(
const Rationals &x)
443 str_ =
"\\mathbb{Q}";
446 void LatexPrinter::bvisit(
const Integers &x)
448 str_ =
"\\mathbb{Z}";
451 void LatexPrinter::bvisit(
const Naturals &x)
453 str_ =
"\\mathbb{N}";
456 void LatexPrinter::bvisit(
const Naturals0 &x)
458 str_ =
"\\mathbb{N}_0";
461 void LatexPrinter::bvisit(
const FiniteSet &x)
465 print_with_args(x,
",", s);
470 void LatexPrinter::bvisit(
const Contains &x)
473 s << apply(x.get_expr()) <<
" \\in " << apply(x.get_set());
482 bool LatexPrinter::split_mul_coef()
491 for (
unsigned i = 0; i < names.
size(); i++) {
492 if (names[i] !=
"") {
493 names[i] =
"\\operatorname{" + names[i] +
"}";
496 names[SYMENGINE_SIN] =
"\\sin";
497 names[SYMENGINE_COS] =
"\\cos";
498 names[SYMENGINE_TAN] =
"\\tan";
499 names[SYMENGINE_COT] =
"\\cot";
500 names[SYMENGINE_CSC] =
"\\csc";
501 names[SYMENGINE_SEC] =
"\\sec";
502 names[SYMENGINE_ATAN2] =
"\\operatorname{atan_2}";
503 names[SYMENGINE_SINH] =
"\\sinh";
504 names[SYMENGINE_COSH] =
"\\cosh";
505 names[SYMENGINE_TANH] =
"\\tanh";
506 names[SYMENGINE_COTH] =
"\\coth";
507 names[SYMENGINE_LOG] =
"\\log";
508 names[SYMENGINE_ZETA] =
"\\zeta";
509 names[SYMENGINE_LAMBERTW] =
"\\operatorname{W}";
510 names[SYMENGINE_DIRICHLET_ETA] =
"\\eta";
511 names[SYMENGINE_KRONECKERDELTA] =
"\\delta_";
512 names[SYMENGINE_LEVICIVITA] =
"\\varepsilon_";
513 names[SYMENGINE_LOWERGAMMA] =
"\\gamma";
514 names[SYMENGINE_UPPERGAMMA] =
"\\Gamma";
515 names[SYMENGINE_BETA] =
"\\operatorname{B}";
516 names[SYMENGINE_LOG] =
"\\log";
517 names[SYMENGINE_GAMMA] =
"\\Gamma";
518 names[SYMENGINE_TRUNCATE] =
"\\operatorname{truncate}";
519 names[SYMENGINE_PRIMEPI] =
"\\pi";
523 void LatexPrinter::bvisit(
const Function &x)
527 o << names_[x.get_type_code()] <<
"{";
528 vec_basic vec = x.get_args();
529 o << parenthesize(apply(vec)) <<
"}";
533 void LatexPrinter::bvisit(
const Floor &x)
536 o <<
"\\lfloor{" << apply(x.get_arg()) <<
"}\\rfloor";
540 void LatexPrinter::bvisit(
const Ceiling &x)
543 o <<
"\\lceil{" << apply(x.get_arg()) <<
"}\\rceil";
547 void LatexPrinter::bvisit(
const Abs &x)
550 o <<
"\\left|" << apply(x.get_arg()) <<
"}\\right|";
556 return "\\left(" + expr +
"\\right)";
560 const RCP<const Basic> &b)
563 o <<
"e^{" << apply(b) <<
"}";
565 o <<
"\\sqrt{" << apply(a) <<
"}";
566 }
else if (is_a<Rational>(*b)
567 and
eq(*
static_cast<const Rational &
>(*b).get_num(), *one)) {
568 o <<
"\\sqrt[" << apply(
static_cast<const Rational &
>(*b).get_den())
569 <<
"]{" << apply(a) <<
"}";
571 o << parenthesizeLE(a, PrecedenceEnum::Pow);
573 auto b_str = apply(b);
574 if (b_str.size() > 1) {
575 o <<
"^{" << b_str <<
"}";
585 return "\\frac{" + num +
"}{" + den +
"}";
588 void LatexPrinter::bvisit(
const Piecewise &x)
591 s <<
"\\begin{cases} ";
592 const auto &vec = x.get_vec();
593 auto it = vec.begin();
594 auto it_last = --vec.end();
595 while (it != vec.end()) {
596 s << apply(it->first);
598 if (
eq(*it->second, *boolTrue)) {
599 s <<
" & \\text{otherwise} \\end{cases}";
601 s <<
" & \\text{for}\\: ";
602 s << apply(it->second);
603 s <<
" \\end{cases}";
606 s <<
" & \\text{for}\\: ";
607 s << apply(it->second);
615 void LatexPrinter::bvisit(
const Tuple &x)
618 vec_basic vec = x.get_args();
619 o << parenthesize(apply(vec));
The base class for SymEngine.
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