X-Git-Url: https://www.ginac.de/ginac.git//ginac.git?p=ginac.git;a=blobdiff_plain;f=ginac%2Ffactor.cpp;h=2b77d1b0110f3e327216a11a20510b901a6b93ee;hp=e9b2569b57f6f654d7e1f48819d9c2c28f09cbf1;hb=8cffcdf13d817a47f217f1a1043317d95969e070;hpb=792cda15eb0089edccdc0a89e7c39e58e940b87b diff --git a/ginac/factor.cpp b/ginac/factor.cpp index e9b2569b..2b77d1b0 100644 --- a/ginac/factor.cpp +++ b/ginac/factor.cpp @@ -33,7 +33,7 @@ */ /* - * GiNaC Copyright (C) 1999-2015 Johannes Gutenberg University Mainz, Germany + * GiNaC Copyright (C) 1999-2019 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 @@ -66,7 +66,6 @@ #include "add.h" #include -#include #include #include #include @@ -916,8 +915,7 @@ static void berlekamp(const umodpoly& a, upvec& upv) return; } - list factors; - factors.push_back(a); + list factors = {a}; unsigned int size = 1; unsigned int r = 1; unsigned int q = cl_I_to_uint(R->modulus); @@ -937,8 +935,7 @@ static void berlekamp(const umodpoly& a, upvec& upv) div(*u, g, uo); if ( equal_one(uo) ) { throw logic_error("berlekamp: unexpected divisor."); - } - else { + } else { *u = uo; } factors.push_back(g); @@ -1021,8 +1018,7 @@ static void modsqrfree(const umodpoly& a, upvec& factors, vector& mult) mult[i] *= prime; } } - } - else { + } else { umodpoly ap; expt_1_over_p(a, prime, ap); size_t previ = mult.size(); @@ -1107,8 +1103,7 @@ static void same_degree_factor(const umodpoly& a, upvec& upv) for ( size_t i=0; i primes; - if ( primes.size() == 0 ) { - primes.push_back(3); primes.push_back(5); primes.push_back(7); + if (primes.empty()) { + primes = {3, 5, 7}; } if ( p >= primes.back() ) { unsigned int candidate = primes.back() + 2; while ( true ) { size_t n = primes.size()/2; for ( size_t i=0; i p ) break; + if (candidate > p) + break; } return candidate; } @@ -1405,8 +1401,7 @@ public: if ( len > n/2 ) return false; fill(k.begin(), k.begin()+len, 1); fill(k.begin()+len+1, k.end(), 0); - } - else { + } else { k[last++] = 0; k[last] = 1; } @@ -1429,8 +1424,7 @@ private: if ( d ) { if ( cache[pos].size() >= d ) { lr[group] = lr[group] * cache[pos][d-1]; - } - else { + } else { if ( cache[pos].size() == 0 ) { cache[pos].push_back(factors[pos] * factors[pos+1]); } @@ -1444,8 +1438,7 @@ private: } lr[group] = lr[group] * cache[pos].back(); } - } - else { + } else { lr[group] = lr[group] * factors[pos]; } } while ( i < n ); @@ -1456,8 +1449,7 @@ private: lr[1] = one; if ( n > 6 ) { split_cached(); - } - else { + } else { for ( size_t i=0; i(e) || is_a(e) ) { return e.map(*this); @@ -1843,8 +1830,7 @@ struct make_modular_map : public map_function { numeric n(R->retract(emod)); if ( n > halfmod ) { return n-mod; - } - else { + } else { return n; } } @@ -1887,7 +1873,8 @@ static vector multivar_diophant(const vector& a_, const ex& x, const ex& { vector a = a_; - const cl_modint_ring R = find_modint_ring(expt_pos(cl_I(p),k)); + const cl_I modulus = expt_pos(cl_I(p),k); + const cl_modint_ring R = find_modint_ring(modulus); const size_t r = a.size(); const size_t nu = I.size() + 1; @@ -1937,8 +1924,7 @@ static vector multivar_diophant(const vector& a_, const ex& x, const ex& e = make_modular(buf, R); } } - } - else { + } else { upvec amod; for ( size_t i=0; i multivar_diophant(const vector& a_, const ex& x, const ex& if ( is_a(c) ) { nterms = c.nops(); z = c.op(0); - } - else { + } else { nterms = 1; z = c; } @@ -1962,16 +1947,13 @@ static vector multivar_diophant(const vector& a_, const ex& x, const ex& cl_I cm = the(ex_to(z.lcoeff(x)).to_cl_N()); upvec delta_s = univar_diophant(amod, x, m, p, k); cl_MI modcm; - cl_I poscm = cm; - while ( poscm < 0 ) { - poscm = poscm + expt_pos(cl_I(p),k); - } + cl_I poscm = plusp(cm) ? cm : mod(cm, modulus); modcm = cl_MI(R, poscm); for ( size_t j=0; j 1 ) { + if ( nterms > 1 && i+1 != nterms ) { z = c.op(i+1); } } @@ -2085,15 +2067,9 @@ static ex hensel_multivar(const ex& a, const ex& x, const vector& I, acand *= U[i]; } if ( expand(a-acand).is_zero() ) { - lst res; - for ( size_t i=0; i(vn) ) { - vnlst = lst(vn); + vnlst = lst{vn}; } else { ex vnfactors = factor(vn); @@ -2325,8 +2301,7 @@ static ex factor_multivariate(const ex& poly, const exset& syms) for ( size_t i=1; i(ufaclst.op(i+1).lcoeff(x)); for ( int j=ftilde.size()-1; j>=0; --j ) { @@ -2441,7 +2415,7 @@ static ex factor_multivariate(const ex& poly, const exset& syms) // try Hensel lifting ex res = hensel_multivar(pp, x, epv, prime, l, modfactors, C); - if ( res != lst() ) { + if ( res != lst{} ) { ex result = cont * unit; for ( size_t i=0; i(e) ) { syms.insert(e); @@ -2486,8 +2460,7 @@ static ex factor_sqrfree(const ex& poly) int ld = poly.ldegree(x); ex res = factor_univariate(expand(poly/pow(x, ld)), x); return res * pow(x,ld); - } - else { + } else { ex res = factor_univariate(poly, x); return res; } @@ -2504,7 +2477,7 @@ static ex factor_sqrfree(const ex& poly) struct apply_factor_map : public map_function { unsigned options; apply_factor_map(unsigned options_) : options(options_) { } - ex operator()(const ex& e) + ex operator()(const ex& e) override { if ( e.info(info_flags::polynomial) ) { return factor(e, options); @@ -2514,26 +2487,51 @@ struct apply_factor_map : public map_function { for ( size_t i=0; i void +factor_iter(const ex &e, F yield) +{ + if (is_a(e)) { + for (const auto &f : e) { + if (is_a(f)) { + yield(f.op(0), f.op(1)); + } else { + yield(f, ex(1)); + } + } + } else { + if (is_a(e)) { + yield(e.op(0), e.op(1)); + } else { + yield(e, ex(1)); + } + } +} -/** Interface function to the outside world. It checks the arguments, tries a - * square free factorization, and then calls factor_sqrfree to do the hard - * work. +/** This function factorizes a polynomial. It checks the arguments, + * tries a square free factorization, and then calls factor_sqrfree + * to do the hard work. + * + * This function expands its argument, so for polynomials with + * explicit factors it's better to call it on each one separately + * (or use factor() which does just that). */ -ex factor(const ex& poly, unsigned options) +static ex factor1(const ex& poly, unsigned options) { // check arguments if ( !poly.info(info_flags::polynomial) ) { @@ -2560,47 +2558,35 @@ ex factor(const ex& poly, unsigned options) ex sfpoly = sqrfree(poly.expand(), syms); // factorize the square free components - if ( is_a(sfpoly) ) { - // case: (polynomial)^exponent - const ex& base = sfpoly.op(0); - if ( !is_a(base) ) { - // simple case: (monomial)^exponent - return sfpoly; - } - ex f = factor_sqrfree(base); - return pow(f, sfpoly.op(1)); - } - if ( is_a(sfpoly) ) { - // case: multiple factors - ex res = 1; - for ( size_t i=0; i(t) ) { - const ex& base = t.op(0); - if ( !is_a(base) ) { - res *= t; - } - else { - ex f = factor_sqrfree(base); - res *= pow(f, t.op(1)); - } - } - else if ( is_a(t) ) { - ex f = factor_sqrfree(t); - res *= f; + ex res = 1; + factor_iter(sfpoly, + [&](const ex &f, const ex &k) { + if ( is_a(f) ) { + res *= pow(factor_sqrfree(f), k); + } else { + // simple case: (monomial)^exponent + res *= pow(f, k); } - else { - res *= t; - } - } - return res; - } - if ( is_a(sfpoly) ) { - return poly; - } - // case: (polynomial) - ex f = factor_sqrfree(sfpoly); - return f; + }); + return res; +} + +} // anonymous namespace + +/** Interface function to the outside world. It uses factor1() + * on each of the explicitly present factors of poly. + */ +ex factor(const ex& poly, unsigned options) +{ + ex result = 1; + factor_iter(poly, + [&](const ex &f1, const ex &k1) { + factor_iter(factor1(f1, options), + [&](const ex &f2, const ex &k2) { + result *= pow(f2, k1*k2); + }); + }); + return result; } } // namespace GiNaC