1 #include <symengine/printers/latex.h>
2 #include <symengine/printers.h>
8 std::string latex(
const Basic &x)
14 void print_rational_class(
const rational_class &r, std::ostringstream &s)
16 if (get_den(r) == 1) {
19 s <<
"\\frac{" << get_num(r) <<
"}{" << get_den(r) <<
"}";
23 void LatexPrinter::bvisit(
const Symbol &x)
25 str_ = _print_symbol(x.get_name());
28 std::string LatexPrinter::_print_symbol(
const std::string &name)
30 if (name.find(
'\\') != std::string::npos
31 or name.find(
'{') != std::string::npos) {
35 return _print_symbol(name.substr(1, name.size() - 1));
37 std::vector<std::string> greeks
38 = {
"alpha",
"beta",
"gamma",
"Gamma",
"delta",
"Delta",
"epsilon",
39 "zeta",
"eta",
"theta",
"Theta",
"iota",
"kappa",
"lambda",
40 "Lambda",
"mu",
"nu",
"xi",
"omicron",
"pi",
"Pi",
41 "rho",
"sigma",
"Sigma",
"tau",
"upsilon",
"Upsilon",
"phi",
42 "Phi",
"chi",
"psi",
"Psi",
"omega",
"Omega"};
44 for (
auto &letter : greeks) {
50 size_t idx = name.find(
"_");
51 if (idx == std::string::npos || idx == name.size() - 1) {
53 }
else if (idx < name.size() - 2) {
54 return _print_symbol(name.substr(0, idx)) +
"_{"
55 + _print_symbol(name.substr(idx + 1, name.size() - idx - 1))
58 return _print_symbol(name.substr(0, idx)) +
"_"
59 + name.substr(idx + 1, name.size() - idx - 1);
63 void LatexPrinter::bvisit(
const Rational &x)
65 const auto &
rational = x.as_rational_class();
71 void LatexPrinter::bvisit(
const Complex &x)
75 print_rational_class(x.real_, s);
77 if (mp_sign(x.imaginary_) == 1) {
83 if (x.imaginary_ != mp_sign(x.imaginary_)) {
84 print_rational_class(mp_abs(x.imaginary_), s);
90 if (x.imaginary_ != mp_sign(x.imaginary_)) {
91 print_rational_class(x.imaginary_, s);
94 if (mp_sign(x.imaginary_) == 1) {
104 void LatexPrinter::bvisit(
const ComplexBase &x)
106 RCP<const Number> imag = x.imaginary_part();
107 if (imag->is_negative()) {
108 std::string str = apply(imag);
109 str = str.substr(1, str.length() - 1);
110 str_ = apply(x.real_part()) +
" - " + str +
"j";
112 str_ = apply(x.real_part()) +
" + " + apply(imag) +
"j";
115 void LatexPrinter::bvisit(
const ComplexDouble &x)
117 bvisit(
static_cast<const ComplexBase &
>(x));
120 #ifdef HAVE_SYMENGINE_MPC
121 void LatexPrinter::bvisit(
const ComplexMPC &x)
123 bvisit(
static_cast<const ComplexBase &
>(x));
127 void LatexPrinter::bvisit(
const Infty &x)
129 if (x.is_negative_infinity()) {
131 }
else if (x.is_positive_infinity()) {
134 str_ =
"\\tilde{\\infty}";
138 void LatexPrinter::bvisit(
const NaN &x)
140 str_ =
"\\mathrm{NaN}";
143 void LatexPrinter::bvisit(
const Constant &x)
147 }
else if (
eq(x, *E)) {
149 }
else if (
eq(x, *EulerGamma)) {
151 }
else if (
eq(x, *Catalan)) {
153 }
else if (
eq(x, *GoldenRatio)) {
156 throw NotImplementedError(
"Constant " + x.get_name()
157 +
" is not implemented.");
161 void LatexPrinter::bvisit(
const Derivative &x)
163 const auto &symbols = x.get_symbols();
164 std::ostringstream s;
165 if (symbols.size() == 1) {
166 if (free_symbols(*x.get_arg()).size() == 1) {
167 s <<
"\\frac{d}{d " << apply(*symbols.begin());
169 s <<
"\\frac{\\partial}{\\partial " << apply(*symbols.begin());
172 s <<
"\\frac{\\partial^" << symbols.size() <<
"}{";
174 auto it = symbols.begin();
175 RCP<const Basic> prev = *it;
177 for (; it != symbols.end(); ++it) {
178 if (
neq(*prev, **it)) {
180 s <<
"\\partial " << apply(*prev) <<
" ";
182 s <<
"\\partial " << apply(*prev) <<
"^" << count <<
" ";
191 s <<
"\\partial " << apply(*prev) <<
" ";
193 s <<
"\\partial " << apply(*prev) <<
"^" << count <<
" ";
196 s <<
"} " << apply(x.get_arg());
200 void LatexPrinter::bvisit(
const Subs &x)
202 std::ostringstream o;
203 o <<
"\\left. " << apply(x.get_arg()) <<
"\\right|_{\\substack{";
204 for (
auto p = x.get_dict().begin(); p != x.get_dict().end(); p++) {
205 if (p != x.get_dict().begin()) {
208 o << apply(p->first) <<
"=" << apply(p->second);
214 void LatexPrinter::bvisit(
const Equality &x)
216 std::ostringstream s;
217 s << apply(x.get_arg1()) <<
" = " << apply(x.get_arg2());
221 void LatexPrinter::bvisit(
const Unequality &x)
223 std::ostringstream s;
224 s << apply(x.get_arg1()) <<
" \\neq " << apply(x.get_arg2());
228 void LatexPrinter::bvisit(
const LessThan &x)
230 std::ostringstream s;
231 s << apply(x.get_arg1()) <<
" \\leq " << apply(x.get_arg2());
235 void LatexPrinter::bvisit(
const StrictLessThan &x)
237 std::ostringstream s;
238 s << apply(x.get_arg1()) <<
" < " << apply(x.get_arg2());
242 std::string latex(
const DenseMatrix &m,
const unsigned max_rows,
243 const unsigned max_cols)
245 const unsigned int nrows = m.nrows();
246 const unsigned int ncols = m.ncols();
247 unsigned int nrows_display = nrows;
248 if (nrows > max_rows)
249 nrows_display = max_rows - 1;
250 unsigned int ncols_display = ncols;
251 if (ncols > max_cols)
252 ncols_display = max_cols - 1;
254 std::ostringstream s;
255 s <<
"\\left[\\begin{matrix}" << std::endl;
257 std::string end_of_line =
" \\\\\n";
258 if (ncols_display < ncols) {
259 end_of_line =
" & \\cdots" + end_of_line;
261 for (
unsigned int row_index = 0; row_index < nrows_display; row_index++) {
262 for (
unsigned int column_index = 0; column_index < ncols_display;
264 RCP<const Basic> v = m.get(row_index, column_index);
268 throw SymEngineException(
269 "cannot display uninitialized element");
273 if (column_index < ncols_display - 1)
278 if (nrows_display < nrows) {
279 for (
unsigned int column_index = 0; column_index < ncols_display;
282 if (column_index < ncols_display - 1)
287 s <<
"\\end{matrix}\\right]\n";
292 void LatexPrinter::bvisit(
const Interval &x)
294 std::ostringstream s;
295 if (x.get_left_open())
299 s << *x.get_start() <<
", " << *x.get_end();
300 if (x.get_right_open())
307 void LatexPrinter::bvisit(
const BooleanAtom &x)
310 str_ =
"\\mathrm{True}";
312 str_ =
"\\mathrm{False}";
316 void LatexPrinter::bvisit(
const And &x)
318 std::ostringstream s;
319 auto container = x.get_container();
320 if (is_a<Or>(**container.begin()) or is_a<Xor>(**container.begin())) {
321 s << parenthesize(apply(*container.begin()));
323 s << apply(*container.begin());
326 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
328 if (is_a<Or>(**it) or is_a<Xor>(**it)) {
329 s << parenthesize(apply(*it));
337 void LatexPrinter::bvisit(
const Or &x)
339 std::ostringstream s;
340 auto container = x.get_container();
341 if (is_a<And>(**container.begin()) or is_a<Xor>(**container.begin())) {
342 s << parenthesize(apply(*container.begin()));
344 s << apply(*container.begin());
347 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
349 if (is_a<And>(**it) or is_a<Xor>(**it)) {
350 s << parenthesize(apply(*it));
358 void LatexPrinter::bvisit(
const Xor &x)
360 std::ostringstream s;
361 auto container = x.get_container();
362 if (is_a<Or>(**container.begin()) or is_a<And>(**container.begin())) {
363 s << parenthesize(apply(*container.begin()));
365 s << apply(*container.begin());
368 for (
auto it = ++(container.begin()); it != container.end(); ++it) {
370 if (is_a<Or>(**it) or is_a<And>(**it)) {
371 s << parenthesize(apply(*it));
379 void LatexPrinter::print_with_args(
const Basic &x,
const std::string &join,
380 std::ostringstream &s)
382 vec_basic v = x.get_args();
383 s << apply(*v.begin());
385 for (
auto it = ++(v.begin()); it != v.end(); ++it) {
386 s <<
" " << join <<
" " << apply(*it);
390 void LatexPrinter::bvisit(
const Not &x)
392 str_ =
"\\neg " + apply(*x.get_arg());
395 void LatexPrinter::bvisit(
const Union &x)
397 std::ostringstream s;
398 print_with_args(x,
"\\cup", s);
402 void LatexPrinter::bvisit(
const Intersection &x)
404 std::ostringstream s;
405 print_with_args(x,
"\\cap", s);
409 void LatexPrinter::bvisit(
const Complement &x)
411 std::ostringstream s;
412 s << apply(x.get_universe()) <<
" \\setminus " << apply(x.get_container());
416 void LatexPrinter::bvisit(
const ImageSet &x)
418 std::ostringstream s;
419 s <<
"\\left\\{" << apply(*x.get_expr()) <<
"\\; |\\; ";
420 s << apply(*x.get_symbol());
421 s <<
" \\in " << apply(*x.get_baseset()) <<
"\\right\\}";
425 void LatexPrinter::bvisit(
const ConditionSet &x)
427 std::ostringstream s;
428 s <<
"\\left\\{" << apply(*x.get_symbol()) <<
"\\; |\\; ";
429 s << apply(x.get_condition()) <<
"\\right\\}";
433 void LatexPrinter::bvisit(
const EmptySet &x)
438 void LatexPrinter::bvisit(
const Complexes &x)
440 str_ =
"\\mathbb{C}";
443 void LatexPrinter::bvisit(
const Reals &x)
445 str_ =
"\\mathbb{R}";
448 void LatexPrinter::bvisit(
const Rationals &x)
450 str_ =
"\\mathbb{Q}";
453 void LatexPrinter::bvisit(
const Integers &x)
455 str_ =
"\\mathbb{Z}";
458 void LatexPrinter::bvisit(
const Naturals &x)
460 str_ =
"\\mathbb{N}";
463 void LatexPrinter::bvisit(
const Naturals0 &x)
465 str_ =
"\\mathbb{N}_0";
468 void LatexPrinter::bvisit(
const FiniteSet &x)
470 std::ostringstream s;
472 print_with_args(x,
",", s);
477 void LatexPrinter::bvisit(
const Contains &x)
479 std::ostringstream s;
480 s << apply(x.get_expr()) <<
" \\in " << apply(x.get_set());
484 std::string LatexPrinter::print_mul()
489 bool LatexPrinter::split_mul_coef()
494 std::vector<std::string> init_latex_printer_names()
496 std::vector<std::string> names = init_str_printer_names();
498 for (
unsigned i = 0; i < names.size(); i++) {
499 if (names[i] !=
"") {
500 names[i] =
"\\operatorname{" + names[i] +
"}";
503 names[SYMENGINE_SIN] =
"\\sin";
504 names[SYMENGINE_COS] =
"\\cos";
505 names[SYMENGINE_TAN] =
"\\tan";
506 names[SYMENGINE_COT] =
"\\cot";
507 names[SYMENGINE_CSC] =
"\\csc";
508 names[SYMENGINE_SEC] =
"\\sec";
509 names[SYMENGINE_ATAN2] =
"\\operatorname{atan_2}";
510 names[SYMENGINE_SINH] =
"\\sinh";
511 names[SYMENGINE_COSH] =
"\\cosh";
512 names[SYMENGINE_TANH] =
"\\tanh";
513 names[SYMENGINE_COTH] =
"\\coth";
514 names[SYMENGINE_LOG] =
"\\log";
515 names[SYMENGINE_ZETA] =
"\\zeta";
516 names[SYMENGINE_LAMBERTW] =
"\\operatorname{W}";
517 names[SYMENGINE_DIRICHLET_ETA] =
"\\eta";
518 names[SYMENGINE_KRONECKERDELTA] =
"\\delta_";
519 names[SYMENGINE_LEVICIVITA] =
"\\varepsilon_";
520 names[SYMENGINE_LOWERGAMMA] =
"\\gamma";
521 names[SYMENGINE_UPPERGAMMA] =
"\\Gamma";
522 names[SYMENGINE_BETA] =
"\\operatorname{B}";
523 names[SYMENGINE_LOG] =
"\\log";
524 names[SYMENGINE_GAMMA] =
"\\Gamma";
525 names[SYMENGINE_TRUNCATE] =
"\\operatorname{truncate}";
526 names[SYMENGINE_PRIMEPI] =
"\\pi";
530 void LatexPrinter::bvisit(
const Function &x)
532 static const std::vector<std::string> names_ = init_latex_printer_names();
533 std::ostringstream o;
534 o << names_[x.get_type_code()] <<
"{";
535 vec_basic vec = x.get_args();
536 o << parenthesize(apply(vec)) <<
"}";
540 void LatexPrinter::bvisit(
const Floor &x)
542 std::ostringstream o;
543 o <<
"\\lfloor{" << apply(x.get_arg()) <<
"}\\rfloor";
547 void LatexPrinter::bvisit(
const Ceiling &x)
549 std::ostringstream o;
550 o <<
"\\lceil{" << apply(x.get_arg()) <<
"}\\rceil";
554 void LatexPrinter::bvisit(
const Abs &x)
556 std::ostringstream o;
557 o <<
"\\left|" << apply(x.get_arg()) <<
"\\right|";
561 std::string LatexPrinter::parenthesize(
const std::string &expr)
563 return "\\left(" + expr +
"\\right)";
566 void LatexPrinter::_print_pow(std::ostringstream &o,
const RCP<const Basic> &a,
567 const RCP<const Basic> &b)
570 o <<
"e^{" << apply(b) <<
"}";
572 o <<
"\\sqrt{" << apply(a) <<
"}";
573 }
else if (is_a<Rational>(*b)
574 and
eq(*
static_cast<const Rational &
>(*b).get_num(), *one)) {
575 o <<
"\\sqrt[" << apply(
static_cast<const Rational &
>(*b).get_den())
576 <<
"]{" << apply(a) <<
"}";
578 o << parenthesizeLE(a, PrecedenceEnum::Pow);
580 auto b_str = apply(b);
581 if (b_str.size() > 1) {
582 o <<
"^{" << b_str <<
"}";
589 std::string LatexPrinter::print_div(
const std::string &num,
590 const std::string &den,
bool paren)
592 return "\\frac{" + num +
"}{" + den +
"}";
595 void LatexPrinter::bvisit(
const Piecewise &x)
597 std::ostringstream s;
598 s <<
"\\begin{cases} ";
599 const auto &vec = x.get_vec();
600 auto it = vec.begin();
601 auto it_last = --vec.end();
602 while (it != vec.end()) {
603 s << apply(it->first);
605 if (
eq(*it->second, *boolTrue)) {
606 s <<
" & \\text{otherwise} \\end{cases}";
608 s <<
" & \\text{for}\\: ";
609 s << apply(it->second);
610 s <<
" \\end{cases}";
613 s <<
" & \\text{for}\\: ";
614 s << apply(it->second);
622 void LatexPrinter::bvisit(
const Tuple &x)
624 std::ostringstream o;
625 vec_basic vec = x.get_args();
626 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