X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fmul.cpp;h=f60937069bea7dc00abd5e0bbe8dd3947af19a6a;hp=7ca04ef36ecb09696bc7b8affe89c60dfa1942c8;hb=0f617ea4ea1dc6a33cae5e2ce518b26d8055c177;hpb=35287d4fef8dc61a10966091ff662eeb9444f87a diff --git a/ginac/mul.cpp b/ginac/mul.cpp index 7ca04ef3..f6093706 100644 --- a/ginac/mul.cpp +++ b/ginac/mul.cpp @@ -141,25 +141,32 @@ void mul::print(const print_context & c, unsigned level) const while (it != itend) { // If the first argument is a negative integer power, it gets printed as "1.0/" - if (it == seq.begin() && ex_to(it->coeff).is_integer() && it->coeff.info(info_flags::negative)) { - if (is_a(c)) + bool needclosingparenthesis = false; + if (it == seq.begin() && it->coeff.info(info_flags::negint)) { + if (is_a(c)) { c.s << "recip("; - else + needclosingparenthesis = true; + } else c.s << "1.0/"; } // If the exponent is 1 or -1, it is left out if (it->coeff.is_equal(_ex1) || it->coeff.is_equal(_ex_1)) it->rest.print(c, precedence()); - else { + else if (it->coeff.info(info_flags::negint)) // Outer parens around ex needed for broken gcc-2.95 parser: - (ex(power(it->rest, abs(ex_to(it->coeff))))).print(c, level); - } + (ex(power(it->rest, -ex_to(it->coeff)))).print(c, level); + else + // Outer parens around ex needed for broken gcc-2.95 parser: + (ex(power(it->rest, ex_to(it->coeff)))).print(c, level); + + if (needclosingparenthesis) + c.s << ")"; // Separator is "/" for negative integer powers, "*" otherwise ++it; if (it != itend) { - if (ex_to(it->coeff).is_integer() && it->coeff.info(info_flags::negative)) + if (it->coeff.info(info_flags::negint)) c.s << "/"; else c.s << "*"; @@ -186,8 +193,6 @@ void mul::print(const print_context & c, unsigned level) const c.s << "("; } - bool first = true; - // First print the overall numeric coefficient numeric coeff = ex_to(overall_coeff); if (coeff.csgn() == -1) @@ -213,17 +218,51 @@ void mul::print(const print_context & c, unsigned level) const // Then proceed with the remaining factors epvector::const_iterator it = seq.begin(), itend = seq.end(); - while (it != itend) { - if (!first) { - if (is_a(c)) - c.s << ' '; + if (is_a(c)) { + + // Separate factors into those with negative numeric exponent + // and all others + exvector neg_powers, others; + while (it != itend) { + GINAC_ASSERT(is_a(it->coeff)); + if (ex_to(it->coeff).is_negative()) + neg_powers.push_back(recombine_pair_to_ex(expair(it->rest, -(it->coeff)))); else - c.s << '*'; + others.push_back(recombine_pair_to_ex(*it)); + ++it; + } + + if (!neg_powers.empty()) { + + // Factors with negative exponent are printed as a fraction + c.s << "\\frac{"; + mul(others).eval().print(c); + c.s << "}{"; + mul(neg_powers).eval().print(c); + c.s << "}"; + } else { - first = false; + + // All other factors are printed in the ordinary way + exvector::const_iterator vit = others.begin(), vitend = others.end(); + while (vit != vitend) { + c.s << ' '; + vit->print(c, precedence()); + ++vit; + } + } + + } else { + + bool first = true; + while (it != itend) { + if (!first) + c.s << '*'; + else + first = false; + recombine_pair_to_ex(*it).print(c, precedence()); + ++it; } - recombine_pair_to_ex(*it).print(c, precedence()); - ++it; } if (precedence() <= level) { @@ -686,7 +725,7 @@ ex mul::expand(unsigned options) const (cit->coeff.is_equal(_ex1))) { ++number_of_adds; if (is_ex_exactly_of_type(last_expanded, add)) { -#if 1 +#if 0 // Expand a product of two sums, simple and robust version. const add & add1 = ex_to(last_expanded); const add & add2 = ex_to(cit->rest); @@ -696,21 +735,25 @@ ex mul::expand(unsigned options) const exvector distrseq; distrseq.reserve(n2); for (int i1=0; i1 setflag(status_flags::dynallocated); - distrseq.clear(); } last_expanded = tmp_accu; #else // Expand a product of two sums, aggressive version. - // Caring for the overall coefficients in separate loops can give - // a performance gain of up to 20%! - const add & add1 = ex_to(last_expanded); - const add & add2 = ex_to(cit->rest); + // Caring for the overall coefficients in separate loops can + // sometimes give a performance gain of up to 15%! + + const int sizedifference = ex_to(last_expanded).seq.size()-ex_to(cit->rest).seq.size(); + // add2 is for the inner loop and should be the bigger of the two sums + // in the presence of asymptotically good sorting: + const add& add1 = (sizedifference<0 ? ex_to(last_expanded) : ex_to(cit->rest)); + const add& add2 = (sizedifference<0 ? ex_to(cit->rest) : ex_to(last_expanded)); const epvector::const_iterator add1begin = add1.seq.begin(); const epvector::const_iterator add1end = add1.seq.end(); const epvector::const_iterator add2begin = add2.seq.begin(); @@ -734,8 +777,7 @@ ex mul::expand(unsigned options) const distrseq.push_back(expair(i->rest, ex_to(i->coeff).mul_dyn(ex_to(add2.overall_coeff)))); } // Compute the new overall coefficient and put it together: - ex tmp_accu = (new add(distrseq, ex_to(add1.overall_coeff).mul(ex_to(add2.overall_coeff))))-> - setflag(status_flags::dynallocated); + ex tmp_accu = (new add(distrseq, add1.overall_coeff*add2.overall_coeff))->setflag(status_flags::dynallocated); // Multiply explicitly all non-numeric terms of add1 and add2: for (epvector::const_iterator i1=add1begin; i1!=add1end; ++i1) { // We really have to combine terms here in order to compactify @@ -747,7 +789,7 @@ ex mul::expand(unsigned options) const // since that would violate an invariant of expairseq: const ex rest = (new mul(i1->rest, i2->rest))->setflag(status_flags::dynallocated); if (is_ex_exactly_of_type(rest, numeric)) - oc *= ex_to(rest).mul_dyn(ex_to(i1->coeff).mul_dyn(ex_to(i2->coeff))); + oc += ex_to(rest).mul(ex_to(i1->coeff).mul(ex_to(i2->coeff))); else distrseq.push_back(expair(rest, ex_to(i1->coeff).mul_dyn(ex_to(i2->coeff)))); }