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"};
43 for (
auto &letter : greeks) {
48 if (name.
size() > letter.size() and name.
find(letter +
"_") == 0) {
54 if (name.
find(
"_") != std::string::npos) {
58 for (
size_t i = 0; i <
prev.size(); i++) {
59 const char &c =
prev[i];
60 if (c ==
'_' and
prev.size() > i + 2) {
72 void LatexPrinter::bvisit(
const Rational &x)
74 const auto &
rational = x.as_rational_class();
80 void LatexPrinter::bvisit(
const Complex &x)
84 print_rational_class(x.real_, s);
86 if (mp_sign(x.imaginary_) == 1) {
92 if (x.imaginary_ != mp_sign(x.imaginary_)) {
93 print_rational_class(mp_abs(x.imaginary_), s);
99 if (x.imaginary_ != mp_sign(x.imaginary_)) {
100 print_rational_class(x.imaginary_, s);
103 if (mp_sign(x.imaginary_) == 1) {
113 void LatexPrinter::bvisit(
const ComplexBase &x)
115 RCP<const Number> imag = x.imaginary_part();
116 if (imag->is_negative()) {
118 str = str.substr(1, str.length() - 1);
119 str_ = apply(x.real_part()) +
" - " + str +
"j";
121 str_ = apply(x.real_part()) +
" + " + apply(imag) +
"j";
124 void LatexPrinter::bvisit(
const ComplexDouble &x)
126 bvisit(
static_cast<const ComplexBase &
>(x));
129 #ifdef HAVE_SYMENGINE_MPC
130 void LatexPrinter::bvisit(
const ComplexMPC &x)
132 bvisit(
static_cast<const ComplexBase &
>(x));
136 void LatexPrinter::bvisit(
const Infty &x)
138 if (x.is_negative_infinity()) {
140 }
else if (x.is_positive_infinity()) {
143 str_ =
"\\tilde{\\infty}";
147 void LatexPrinter::bvisit(
const NaN &x)
149 str_ =
"\\mathrm{NaN}";
152 void LatexPrinter::bvisit(
const Constant &x)
156 }
else if (
eq(x, *E)) {
158 }
else if (
eq(x, *EulerGamma)) {
160 }
else if (
eq(x, *Catalan)) {
162 }
else if (
eq(x, *GoldenRatio)) {
165 throw NotImplementedError(
"Constant " + x.get_name()
166 +
" is not implemented.");
170 void LatexPrinter::bvisit(
const Derivative &x)
172 const auto &symbols = x.get_symbols();
174 if (symbols.size() == 1) {
175 if (free_symbols(*x.get_arg()).
size() == 1) {
176 s <<
"\\frac{d}{d " << apply(*symbols.begin());
178 s <<
"\\frac{\\partial}{\\partial " << apply(*symbols.begin());
181 s <<
"\\frac{\\partial^" << symbols.size() <<
"}{";
183 auto it = symbols.begin();
184 RCP<const Basic>
prev = *it;
186 for (; it != symbols.end(); ++it) {
187 if (
neq(*prev, **it)) {
189 s <<
"\\partial " << apply(*prev) <<
" ";
191 s <<
"\\partial " << apply(*prev) <<
"^" <<
count <<
" ";
200 s <<
"\\partial " << apply(*prev) <<
" ";
202 s <<
"\\partial " << apply(*prev) <<
"^" <<
count <<
" ";
205 s <<
"} " << apply(x.get_arg());
209 void LatexPrinter::bvisit(
const Subs &x)
212 o <<
"\\left. " << apply(x.get_arg()) <<
"\\right|_{\\substack{";
213 for (
auto p = x.get_dict().begin(); p != x.get_dict().end(); p++) {
214 if (p != x.get_dict().begin()) {
217 o << apply(p->first) <<
"=" << apply(p->second);
223 void LatexPrinter::bvisit(
const Equality &x)
226 s << apply(x.get_arg1()) <<
" = " << apply(x.get_arg2());
230 void LatexPrinter::bvisit(
const Unequality &x)
233 s << apply(x.get_arg1()) <<
" \\neq " << apply(x.get_arg2());
237 void LatexPrinter::bvisit(
const LessThan &x)
240 s << apply(x.get_arg1()) <<
" \\leq " << apply(x.get_arg2());
244 void LatexPrinter::bvisit(
const StrictLessThan &x)
247 s << apply(x.get_arg1()) <<
" < " << apply(x.get_arg2());
251 std::string latex(
const DenseMatrix &m,
const unsigned max_rows,
252 const unsigned max_cols)
254 const unsigned int nrows = m.nrows();
255 const unsigned int ncols = m.ncols();
256 unsigned int nrows_display = nrows;
257 if (nrows > max_rows)
258 nrows_display = max_rows - 1;
259 unsigned int ncols_display = ncols;
260 if (ncols > max_cols)
261 ncols_display = max_cols - 1;
264 s <<
"\\left[\\begin{matrix}" <<
std::endl;
267 if (ncols_display < ncols) {
268 end_of_line =
" & \\cdots" + end_of_line;
270 for (
unsigned int row_index = 0; row_index < nrows_display; row_index++) {
271 for (
unsigned int column_index = 0; column_index < ncols_display;
273 RCP<const Basic> v = m.get(row_index, column_index);
277 throw SymEngineException(
278 "cannot display uninitialized element");
282 if (column_index < ncols_display - 1)
287 if (nrows_display < nrows) {
288 for (
unsigned int column_index = 0; column_index < ncols_display;
291 if (column_index < ncols_display - 1)
296 s <<
"\\end{matrix}\\right]\n";
301 void LatexPrinter::bvisit(
const Interval &x)
304 if (x.get_left_open())
308 s << *x.get_start() <<
", " << *x.get_end();
309 if (x.get_right_open())
316 void LatexPrinter::bvisit(
const BooleanAtom &x)
319 str_ =
"\\mathrm{True}";
321 str_ =
"\\mathrm{False}";
325 void LatexPrinter::bvisit(
const And &x)
328 auto container = x.get_container();
329 if (is_a<Or>(**container.begin()) or is_a<Xor>(**container.begin())) {
330 s << parenthesize(apply(*container.begin()));
332 s << apply(*container.begin());
335 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
337 if (is_a<Or>(**it) or is_a<Xor>(**it)) {
338 s << parenthesize(apply(*it));
346 void LatexPrinter::bvisit(
const Or &x)
349 auto container = x.get_container();
350 if (is_a<And>(**container.begin()) or is_a<Xor>(**container.begin())) {
351 s << parenthesize(apply(*container.begin()));
353 s << apply(*container.begin());
356 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
358 if (is_a<And>(**it) or is_a<Xor>(**it)) {
359 s << parenthesize(apply(*it));
367 void LatexPrinter::bvisit(
const Xor &x)
370 auto container = x.get_container();
371 if (is_a<Or>(**container.begin()) or is_a<And>(**container.begin())) {
372 s << parenthesize(apply(*container.begin()));
374 s << apply(*container.begin());
377 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
379 if (is_a<Or>(**it) or is_a<And>(**it)) {
380 s << parenthesize(apply(*it));
388 void LatexPrinter::print_with_args(
const Basic &x,
const std::string &join,
391 vec_basic v = x.get_args();
392 s << apply(*v.begin());
394 for (
auto it = ++(v.begin()); it != v.end(); ++it) {
395 s <<
" " << join <<
" " << apply(*it);
399 void LatexPrinter::bvisit(
const Not &x)
401 str_ =
"\\neg " + apply(*x.get_arg());
404 void LatexPrinter::bvisit(
const Union &x)
407 print_with_args(x,
"\\cup", s);
411 void LatexPrinter::bvisit(
const Intersection &x)
414 print_with_args(x,
"\\cap", s);
418 void LatexPrinter::bvisit(
const Complement &x)
421 s << apply(x.get_universe()) <<
" \\setminus " << apply(x.get_container());
425 void LatexPrinter::bvisit(
const ImageSet &x)
428 s <<
"\\left\\{" << apply(*x.get_expr()) <<
"\\; |\\; ";
429 s << apply(*x.get_symbol());
430 s <<
" \\in " << apply(*x.get_baseset()) <<
"\\right\\}";
434 void LatexPrinter::bvisit(
const ConditionSet &x)
437 s <<
"\\left\\{" << apply(*x.get_symbol()) <<
"\\; |\\; ";
438 s << apply(x.get_condition()) <<
"\\right\\}";
442 void LatexPrinter::bvisit(
const EmptySet &x)
447 void LatexPrinter::bvisit(
const Complexes &x)
449 str_ =
"\\mathbb{C}";
452 void LatexPrinter::bvisit(
const Reals &x)
454 str_ =
"\\mathbb{R}";
457 void LatexPrinter::bvisit(
const Rationals &x)
459 str_ =
"\\mathbb{Q}";
462 void LatexPrinter::bvisit(
const Integers &x)
464 str_ =
"\\mathbb{Z}";
467 void LatexPrinter::bvisit(
const Naturals &x)
469 str_ =
"\\mathbb{N}";
472 void LatexPrinter::bvisit(
const Naturals0 &x)
474 str_ =
"\\mathbb{N}_0";
477 void LatexPrinter::bvisit(
const FiniteSet &x)
481 print_with_args(x,
",", s);
486 void LatexPrinter::bvisit(
const Contains &x)
489 s << apply(x.get_expr()) <<
" \\in " << apply(x.get_set());
498 bool LatexPrinter::split_mul_coef()
507 for (
unsigned i = 0; i < names.
size(); i++) {
508 if (names[i] !=
"") {
509 names[i] =
"\\operatorname{" + names[i] +
"}";
512 names[SYMENGINE_SIN] =
"\\sin";
513 names[SYMENGINE_COS] =
"\\cos";
514 names[SYMENGINE_TAN] =
"\\tan";
515 names[SYMENGINE_COT] =
"\\cot";
516 names[SYMENGINE_CSC] =
"\\csc";
517 names[SYMENGINE_SEC] =
"\\sec";
518 names[SYMENGINE_ATAN2] =
"\\operatorname{atan_2}";
519 names[SYMENGINE_SINH] =
"\\sinh";
520 names[SYMENGINE_COSH] =
"\\cosh";
521 names[SYMENGINE_TANH] =
"\\tanh";
522 names[SYMENGINE_COTH] =
"\\coth";
523 names[SYMENGINE_LOG] =
"\\log";
524 names[SYMENGINE_ZETA] =
"\\zeta";
525 names[SYMENGINE_LAMBERTW] =
"\\operatorname{W}";
526 names[SYMENGINE_DIRICHLET_ETA] =
"\\eta";
527 names[SYMENGINE_KRONECKERDELTA] =
"\\delta_";
528 names[SYMENGINE_LEVICIVITA] =
"\\varepsilon_";
529 names[SYMENGINE_LOWERGAMMA] =
"\\gamma";
530 names[SYMENGINE_UPPERGAMMA] =
"\\Gamma";
531 names[SYMENGINE_BETA] =
"\\operatorname{B}";
532 names[SYMENGINE_LOG] =
"\\log";
533 names[SYMENGINE_GAMMA] =
"\\Gamma";
534 names[SYMENGINE_TRUNCATE] =
"\\operatorname{truncate}";
535 names[SYMENGINE_PRIMEPI] =
"\\pi";
539 void LatexPrinter::bvisit(
const Function &x)
543 o << names_[x.get_type_code()] <<
"{";
544 vec_basic vec = x.get_args();
545 o << parenthesize(apply(vec)) <<
"}";
549 void LatexPrinter::bvisit(
const Floor &x)
552 o <<
"\\lfloor{" << apply(x.get_arg()) <<
"}\\rfloor";
556 void LatexPrinter::bvisit(
const Ceiling &x)
559 o <<
"\\lceil{" << apply(x.get_arg()) <<
"}\\rceil";
563 void LatexPrinter::bvisit(
const Abs &x)
566 o <<
"\\left|" << apply(x.get_arg()) <<
"\\right|";
572 return "\\left(" + expr +
"\\right)";
576 const RCP<const Basic> &b)
579 o <<
"e^{" << apply(b) <<
"}";
581 o <<
"\\sqrt{" << apply(a) <<
"}";
582 }
else if (is_a<Rational>(*b)
583 and
eq(*
static_cast<const Rational &
>(*b).get_num(), *one)) {
584 o <<
"\\sqrt[" << apply(
static_cast<const Rational &
>(*b).get_den())
585 <<
"]{" << apply(a) <<
"}";
587 o << parenthesizeLE(a, PrecedenceEnum::Pow);
589 auto b_str = apply(b);
590 if (b_str.size() > 1) {
591 o <<
"^{" << b_str <<
"}";
601 return "\\frac{" + num +
"}{" + den +
"}";
604 void LatexPrinter::bvisit(
const Piecewise &x)
607 s <<
"\\begin{cases} ";
608 const auto &vec = x.get_vec();
609 auto it = vec.begin();
610 auto it_last = --vec.end();
611 while (it != vec.end()) {
612 s << apply(it->first);
614 if (
eq(*it->second, *boolTrue)) {
615 s <<
" & \\text{otherwise} \\end{cases}";
617 s <<
" & \\text{for}\\: ";
618 s << apply(it->second);
619 s <<
" \\end{cases}";
622 s <<
" & \\text{for}\\: ";
623 s << apply(it->second);
631 void LatexPrinter::bvisit(
const Tuple &x)
634 vec_basic vec = x.get_args();
635 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