X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Fnormal.cpp;h=f985573a5f6da669dba179ba91049f6b242c6cac;hp=334bf95ae78647b496a193cd5d47b2f60269b090;hb=a405eece0da232b296c4b400a89df4f43e39232d;hpb=51cdfef2f7b38d28ad4228152ae07f78dd2fe7e9 diff --git a/ginac/normal.cpp b/ginac/normal.cpp index 334bf95a..f985573a 100644 --- a/ginac/normal.cpp +++ b/ginac/normal.cpp @@ -36,7 +36,6 @@ #include "inifcns.h" #include "lst.h" #include "mul.h" -#include "ncmul.h" #include "numeric.h" #include "power.h" #include "relational.h" @@ -386,7 +385,7 @@ ex quo(const ex &a, const ex &b, const symbol &x, bool check_args) term = rcoeff / blcoeff; else { if (!divide(rcoeff, blcoeff, term, false)) - return *new ex(fail()); + return (new fail())->setflag(status_flags::dynallocated); } term *= power(x, rdeg - bdeg); q += term; @@ -439,7 +438,7 @@ ex rem(const ex &a, const ex &b, const symbol &x, bool check_args) term = rcoeff / blcoeff; else { if (!divide(rcoeff, blcoeff, term, false)) - return *new ex(fail()); + return (new fail())->setflag(status_flags::dynallocated); } term *= power(x, rdeg - bdeg); r -= (term * b).expand(); @@ -1283,7 +1282,7 @@ ex mul::smod(const numeric &xi) const it++; } #endif // def DO_GINAC_ASSERT - mul * mulcopyp=new mul(*this); + mul * mulcopyp = new mul(*this); GINAC_ASSERT(is_ex_exactly_of_type(overall_coeff,numeric)); mulcopyp->overall_coeff = GiNaC::smod(ex_to_numeric(overall_coeff),xi); mulcopyp->clearflag(status_flags::evaluated); @@ -1333,7 +1332,7 @@ static ex heur_gcd(const ex &a, const ex &b, ex *ca, ex *cb, sym_desc_vec::const // Algorithms only works for non-vanishing input polynomials if (a.is_zero() || b.is_zero()) - return *new ex(fail()); + return (new fail())->setflag(status_flags::dynallocated); // GCD of two numeric values -> CLN if (is_ex_exactly_of_type(a, numeric) && is_ex_exactly_of_type(b, numeric)) { @@ -1367,7 +1366,7 @@ static ex heur_gcd(const ex &a, const ex &b, ex *ca, ex *cb, sym_desc_vec::const // 6 tries maximum for (int t=0; t<6; t++) { if (xi.int_length() * maxdeg > 100000) { -//std::clog << "giving up heur_gcd, xi.int_length = " << xi.int_length() << ", maxdeg = " << maxdeg << endl; +//std::clog << "giving up heur_gcd, xi.int_length = " << xi.int_length() << ", maxdeg = " << maxdeg << std::endl; throw gcdheu_failed(); } @@ -1425,7 +1424,7 @@ static ex heur_gcd(const ex &a, const ex &b, ex *ca, ex *cb, sym_desc_vec::const // Next evaluation point xi = iquo(xi * isqrt(isqrt(xi)) * numeric(73794), numeric(27011)); } - return *new ex(fail()); + return (new fail())->setflag(status_flags::dynallocated); } @@ -1599,20 +1598,20 @@ factored_b: int min_ldeg = std::min(ldeg_a,ldeg_b); if (min_ldeg > 0) { ex common = power(x, min_ldeg); -//std::clog << "trivial common factor " << common << endl; +//std::clog << "trivial common factor " << common << std::endl; return gcd((aex / common).expand(), (bex / common).expand(), ca, cb, false) * common; } // Try to eliminate variables if (var->deg_a == 0) { -//std::clog << "eliminating variable " << x << " from b" << endl; +//std::clog << "eliminating variable " << x << " from b" << std::endl; ex c = bex.content(x); ex g = gcd(aex, c, ca, cb, false); if (cb) *cb *= bex.unit(x) * bex.primpart(x, c); return g; } else if (var->deg_b == 0) { -//std::clog << "eliminating variable " << x << " from a" << endl; +//std::clog << "eliminating variable " << x << " from a" << std::endl; ex c = aex.content(x); ex g = gcd(c, bex, ca, cb, false); if (ca) @@ -1626,10 +1625,10 @@ factored_b: try { g = heur_gcd(aex, bex, ca, cb, var); } catch (gcdheu_failed) { - g = *new ex(fail()); + g = fail(); } if (is_ex_exactly_of_type(g, fail)) { -//std::clog << "heuristics failed" << endl; +//std::clog << "heuristics failed" << std::endl; #if STATISTICS heur_gcd_failed++; #endif @@ -1700,7 +1699,6 @@ ex lcm(const ex &a, const ex &b, bool check_args) * @return vector of factors sorted in ascending degree */ static exvector sqrfree_yun(const ex &a, const symbol &x) { - int i = 0; exvector res; ex w = a; ex z = w.diff(x); @@ -1716,7 +1714,6 @@ static exvector sqrfree_yun(const ex &a, const symbol &x) z = y - w.diff(x); g = gcd(w, z); res.push_back(g); - ++i; } while (!z.is_zero()); return res; } @@ -1879,7 +1876,7 @@ static ex frac_cancel(const ex &n, const ex &d) ex den = d; numeric pre_factor = _num1(); -//std::clog << "frac_cancel num = " << num << ", den = " << den << endl; +//std::clog << "frac_cancel num = " << num << ", den = " << den << std::endl; // Handle trivial case where denominator is 1 if (den.is_equal(_ex1())) @@ -1918,7 +1915,7 @@ static ex frac_cancel(const ex &n, const ex &d) } // Return result as list -//std::clog << " returns num = " << num << ", den = " << den << ", pre_factor = " << pre_factor << endl; +//std::clog << " returns num = " << num << ", den = " << den << ", pre_factor = " << pre_factor << std::endl; return (new lst(num * pre_factor.numer(), den * pre_factor.denom()))->setflag(status_flags::dynallocated); } @@ -1956,10 +1953,10 @@ ex add::normal(lst &sym_lst, lst &repl_lst, int level) const // Add fractions sequentially exvector::const_iterator num_it = nums.begin(), num_itend = nums.end(); exvector::const_iterator den_it = dens.begin(), den_itend = dens.end(); -//std::clog << " num = " << *num_it << ", den = " << *den_it << endl; +//std::clog << " num = " << *num_it << ", den = " << *den_it << std::endl; ex num = *num_it++, den = *den_it++; while (num_it != num_itend) { -//std::clog << " num = " << *num_it << ", den = " << *den_it << endl; +//std::clog << " num = " << *num_it << ", den = " << *den_it << std::endl; ex next_num = *num_it++, next_den = *den_it++; // Trivially add sequences of fractions with identical denominators @@ -1975,7 +1972,7 @@ ex add::normal(lst &sym_lst, lst &repl_lst, int level) const num = ((num * co_den2) + (next_num * co_den1)).expand(); den *= co_den2; // this is the lcm(den, next_den) } -//std::clog << " common denominator = " << den << endl; +//std::clog << " common denominator = " << den << std::endl; // Cancel common factors from num/den return frac_cancel(num, den); @@ -2121,9 +2118,9 @@ ex ex::normal(int level) const return e.op(0) / e.op(1); } -/** Numerator of an expression. If the expression is not of the normal form - * "numerator/denominator", it is first converted to this form and then the - * numerator is returned. +/** Get numerator of an expression. If the expression is not of the normal + * form "numerator/denominator", it is first converted to this form and + * then the numerator is returned. * * @see ex::normal * @return numerator */ @@ -2141,9 +2138,9 @@ ex ex::numer(void) const return e.op(0); } -/** Denominator of an expression. If the expression is not of the normal form - * "numerator/denominator", it is first converted to this form and then the - * denominator is returned. +/** Get denominator of an expression. If the expression is not of the normal + * form "numerator/denominator", it is first converted to this form and + * then the denominator is returned. * * @see ex::normal * @return denominator */ @@ -2161,6 +2158,26 @@ ex ex::denom(void) const return e.op(1); } +/** Get numerator and denominator of an expression. If the expresison is not + * of the normal form "numerator/denominator", it is first converted to this + * form and then a list [numerator, denominator] is returned. + * + * @see ex::normal + * @return a list [numerator, denominator] */ +ex ex::numer_denom(void) const +{ + lst sym_lst, repl_lst; + + ex e = bp->normal(sym_lst, repl_lst, 0); + GINAC_ASSERT(is_ex_of_type(e, lst)); + + // Re-insert replaced symbols + if (sym_lst.nops() > 0) + return e.subs(sym_lst, repl_lst); + else + return e; +} + /** Default implementation of ex::to_rational(). It replaces the object with a * temporary symbol.