X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fnormal.cpp;h=231ef7e868c5be449ecc67ac1cf43f3c63264ffd;hp=a8a1e1eb1bd3f7282418eff3160f2ba1a25114e6;hb=63f3e977f92d51ea173382a9b7c4c3b18bda7b8e;hpb=ec3f0adc471cd6205e81115111070421c8477c6e diff --git a/ginac/normal.cpp b/ginac/normal.cpp index a8a1e1eb..231ef7e8 100644 --- a/ginac/normal.cpp +++ b/ginac/normal.cpp @@ -6,7 +6,7 @@ * computation, square-free factorization and rational function normalization. */ /* - * GiNaC Copyright (C) 1999-2016 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2018 Johannes Gutenberg University Mainz, Germany * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -146,7 +146,7 @@ struct sym_desc { /** Maximum number of terms of leading coefficient of symbol in both polynomials */ size_t max_lcnops; - /** Commparison operator for sorting */ + /** Comparison operator for sorting */ bool operator<(const sym_desc &x) const { if (max_deg == x.max_deg) @@ -270,9 +270,15 @@ static numeric lcm_of_coefficients_denominators(const ex &e) * @param lcm LCM to multiply in */ static ex multiply_lcm(const ex &e, const numeric &lcm) { + if (lcm.is_equal(*_num1_p)) + // e * 1 -> e; + return e; + if (is_exactly_a(e)) { + // (a*b*...)*lcm -> (a*lcma)*(b*lcmb)*...*(lcm/(lcma*lcmb*...)) size_t num = e.nops(); - exvector v; v.reserve(num + 1); + exvector v; + v.reserve(num + 1); numeric lcm_accum = *_num1_p; for (size_t i=0; i(v); } else if (is_exactly_a(e)) { + // (a+b+...)*lcm -> a*lcm+b*lcm+... size_t num = e.nops(); - exvector v; v.reserve(num); + exvector v; + v.reserve(num); for (size_t i=0; i(v); } else if (is_exactly_a(e)) { - if (is_a(e.op(0))) - return e * lcm; - else - return pow(multiply_lcm(e.op(0), lcm.power(ex_to(e.op(1)).inverse())), e.op(1)); - } else - return e * lcm; + if (!is_a(e.op(0))) { + // (b^e)*lcm -> (b*lcm^(1/e))^e if lcm^(1/e) ∈ ℚ (i.e. not a float) + // but not for symbolic b, as evaluation would undo this again + numeric root_of_lcm = lcm.power(ex_to(e.op(1)).inverse()); + if (root_of_lcm.is_rational()) + return pow(multiply_lcm(e.op(0), root_of_lcm), e.op(1)); + } + } + // can't recurse down into e + return dynallocate(e, lcm); } @@ -1536,7 +1548,7 @@ ex gcd(const ex &a, const ex &b, ex *ca, ex *cb, bool check_args, unsigned optio // The symbol with least degree which is contained in both polynomials // is our main variable - sym_desc_vec::iterator vari = sym_stats.begin(); + auto vari = sym_stats.begin(); while ((vari != sym_stats.end()) && (((vari->ldeg_b == 0) && (vari->deg_b == 0)) || ((vari->ldeg_a == 0) && (vari->deg_a == 0)))) @@ -2386,47 +2398,11 @@ ex ex::to_rational(exmap & repl) const return bp->to_rational(repl); } -// GiNaC 1.1 compatibility function -ex ex::to_rational(lst & repl_lst) const -{ - // Convert lst to exmap - exmap m; - for (auto & it : repl_lst) - m.insert(std::make_pair(it.op(0), it.op(1))); - - ex ret = bp->to_rational(m); - - // Convert exmap back to lst - repl_lst.remove_all(); - for (auto & it : m) - repl_lst.append(it.first == it.second); - - return ret; -} - ex ex::to_polynomial(exmap & repl) const { return bp->to_polynomial(repl); } -// GiNaC 1.1 compatibility function -ex ex::to_polynomial(lst & repl_lst) const -{ - // Convert lst to exmap - exmap m; - for (auto & it : repl_lst) - m.insert(std::make_pair(it.op(0), it.op(1))); - - ex ret = bp->to_polynomial(m); - - // Convert exmap back to lst - repl_lst.remove_all(); - for (auto & it : m) - repl_lst.append(it.first == it.second); - - return ret; -} - /** Default implementation of ex::to_rational(). This replaces the object with * a temporary symbol. */ ex basic::to_rational(exmap & repl) const