From b23a2dfdcd478b00a11c6c2184fbe197a3ac5bfb Mon Sep 17 00:00:00 2001 From: Alexei Sheplyakov Date: Sun, 28 Jul 2013 18:43:06 +0300 Subject: [PATCH] [bugfix] factor_univariate(): handle polinomials over rationals (no segfaults any more). --- check/CMakeLists.txt | 1 + check/Makefile.am | 4 ++++ check/factor_univariate_bug.cpp | 21 +++++++++++++++++++++ ginac/factor.cpp | 12 +++++++++++- 4 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 check/factor_univariate_bug.cpp diff --git a/check/CMakeLists.txt b/check/CMakeLists.txt index 0243617c..0445a4a1 100644 --- a/check/CMakeLists.txt +++ b/check/CMakeLists.txt @@ -33,6 +33,7 @@ set(ginac_tests exam_mod_gcd exam_cra bugme_chinrem_gcd + factor_univariate_bug pgcd_relatively_prime_bug pgcd_infinite_loop) diff --git a/check/Makefile.am b/check/Makefile.am index 7aaed071..e17e5a59 100644 --- a/check/Makefile.am +++ b/check/Makefile.am @@ -30,6 +30,7 @@ EXAMS = exam_paranoia \ exam_misc \ exam_mod_gcd \ bugme_chinrem_gcd \ + factor_univariate_bug \ pgcd_relatively_prime_bug \ pgcd_infinite_loop \ exam_cra @@ -257,6 +258,9 @@ time_parser_LDADD = ../ginac/libginac.la bugme_chinrem_gcd_SOURCES = bugme_chinrem_gcd.cpp bugme_chinrem_gcd_LDADD = ../ginac/libginac.la +factor_univariate_bug_SOURCES = factor_univariate_bug.cpp +factor_univariate_bug_LDADD = ../ginac/libginac.la + pgcd_relatively_prime_bug_SOURCES = pgcd_relatively_prime_bug.cpp pgcd_relatively_prime_bug_LDADD = ../ginac/libginac.la diff --git a/check/factor_univariate_bug.cpp b/check/factor_univariate_bug.cpp new file mode 100644 index 00000000..80a7ce4c --- /dev/null +++ b/check/factor_univariate_bug.cpp @@ -0,0 +1,21 @@ +/** + * @file factor_upoly_q_bug.cpp Check for a bug in factor_univariate(). + * + * factor_univariate() didn't check if the argument is an integer polynomial, + * the result was a segfault. + */ +#include "ginac.h" +#include +using namespace GiNaC; +using namespace std; + +int main(int argc, char** argv) +{ + cout << "checking if factor() handles rational polynomials. "; + parser p; + ex e = p("174247781*x^2-1989199947807987/200000000000000*x"); + ex ef = factor(e); + ex diff = (e - ef).expand(); + cout << "yes" << endl; + return 0; +} diff --git a/ginac/factor.cpp b/ginac/factor.cpp index 945b25e6..24f828cb 100644 --- a/ginac/factor.cpp +++ b/ginac/factor.cpp @@ -1509,7 +1509,17 @@ static ex factor_univariate(const ex& poly, const ex& x, unsigned int& prime) cl_modint_ring R; unsigned int trials = 0; unsigned int minfactors = 0; - cl_I lc = lcoeff(prim) * the(ex_to(cont).to_cl_N()); + + const numeric& cont_n = ex_to(cont); + cl_I i_cont; + if (cont_n.is_integer()) { + i_cont = the(cont_n.to_cl_N()); + } else { + // poly \in Q[x] => poly = q ipoly, ipoly \in Z[x], q \in Q + // factor(poly) \equiv q factor(ipoly) + i_cont = cl_I(1); + } + cl_I lc = lcoeff(prim)*i_cont; upvec factors; while ( trials < 2 ) { umodpoly modpoly; -- 2.49.0