Skip to content

Commit 4b60ea3

Browse files
author
Dominic Price
committed
Add option to display expressions as fractions using Kernel.display_fractions
1 parent e793772 commit 4b60ea3

File tree

4 files changed

+93
-0
lines changed

4 files changed

+93
-0
lines changed

core/DisplayTeX.cc

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,64 @@ void DisplayTeX::print_productlike(std::ostream& str, Ex::iterator it, const std
565565
if(needs_brackets(it))
566566
str << "\\left(";
567567

568+
if (kernel.display_fractions) {
569+
// If one (or more) of the factors is a negative power, split into top and
570+
// bottom parts and print as a fraction
571+
Ex pos("\\prod"), neg("\\prod");
572+
for (Ex::sibling_iterator beg = it.begin(), end = it.end(); beg != end; ++beg) {
573+
bool is_negexp = false;
574+
if (*beg->name == "\\pow") {
575+
Ex::sibling_iterator exponent = beg.begin();
576+
++exponent;
577+
if (*exponent->name == "1" && *exponent->multiplier < 0) {
578+
is_negexp = true;
579+
if (*exponent->multiplier == -1) {
580+
neg.append_child(neg.begin(), (Ex::iterator)beg.begin());
581+
}
582+
else {
583+
auto pos = neg.append_child(neg.begin(), (Ex::iterator)beg);
584+
exponent = pos.begin();
585+
++exponent;
586+
multiply(exponent->multiplier, -1);
587+
}
588+
}
589+
}
590+
if (!is_negexp) {
591+
pos.append_child(pos.begin(), (Ex::iterator)beg);
592+
}
593+
}
594+
595+
if (neg.begin().begin() != neg.begin().end()) {
596+
auto mult = *it->multiplier;
597+
if (mult < 0) {
598+
str << "-";
599+
mult *= -1;
600+
}
601+
if (mult.get_den() == 1) {
602+
multiply(pos.begin()->multiplier, mult);
603+
}
604+
else {
605+
multiply(pos.begin()->multiplier, mult.get_num());
606+
multiply(neg.begin()->multiplier, mult.get_den());
607+
}
608+
str << "\\frac{";
609+
if (pos.begin().begin() == pos.begin().end()) {
610+
pos.begin()->name = name_set.insert("1").first;
611+
print_other(str, pos.begin());
612+
}
613+
else {
614+
print_productlike(str, pos.begin(), inbetween);
615+
}
616+
str << "}{";
617+
print_productlike(str, neg.begin(), inbetween);
618+
str << "}";
619+
620+
if (needs_brackets(it))
621+
str << "\\right)";
622+
return;
623+
}
624+
}
625+
568626
// The multiplier needs to be inside the brackets, otherwise things like
569627
// \pow{ 2/3 \prod{a}{b} }{c} do not print correctly.
570628

@@ -688,6 +746,38 @@ void DisplayTeX::print_powlike(std::ostream& str, Ex::iterator it)
688746
++exp;
689747
assert(exp!=tree.end(it));
690748

749+
if (kernel.display_fractions && exp->is_rational() && *exp->multiplier < 0) {
750+
auto mult = *it->multiplier;
751+
bool mult_is_int = mult.get_den() == 1;
752+
if (mult < 0) {
753+
str << "-";
754+
mult *= -1;
755+
}
756+
str << "\\frac{";
757+
if (mult_is_int)
758+
str << mult;
759+
else
760+
str << mult.get_num();
761+
str << "}{";
762+
if (*exp->multiplier == -1) {
763+
Ex copy(arg);
764+
if (!mult_is_int)
765+
multiply(copy.begin()->multiplier, mult.get_den());
766+
dispatch(str, copy.begin());
767+
}
768+
else {
769+
Ex copy(it);
770+
exp = copy.begin().begin();
771+
++exp;
772+
multiply(exp->multiplier, -1);
773+
if (!mult_is_int)
774+
copy.begin()->multiplier = rat_set.insert(mult.get_den()).first;
775+
print_powlike(str, copy.begin());
776+
}
777+
str << "}";
778+
return;
779+
}
780+
691781
if(*it->multiplier!=1)
692782
print_multiplier(str, it);
693783

core/Kernel.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Kernel::Kernel(bool inject_defaults)
2828
, call_embedded_python_functions(false)
2929
, warning_level(warn_t::warning)
3030
, warning_callback(nullptr)
31+
, display_fractions(false)
3132
{
3233
if (inject_defaults) {
3334
inject_property(new Distributable(), ex_from_string("\\prod{#}"), 0);

core/Kernel.hh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ namespace cadabra {
3030
/// Settings.
3131
enum class scalar_backend_t { sympy, mathematica } scalar_backend;
3232
bool call_embedded_python_functions;
33+
bool display_fractions;
3334

3435

3536
const static std::string version;

core/pythoncdb/py_kernel.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ namespace cadabra {
120120
.def_readonly_static("version", &Kernel::version)
121121
.def_readonly_static("build", &Kernel::build)
122122
.def_readonly("scalar_backend", &Kernel::scalar_backend)
123+
.def_readwrite("display_fractions", &Kernel::display_fractions)
123124
.def("warn", &Kernel::warn, pybind11::arg("msg"), pybind11::arg("level") = 0)
124125
.def("configure_warnings", kernel_configure_warnings);
125126

0 commit comments

Comments
 (0)