[GiNaC-list] gcd: wrong sign of cofactor (heur_gcd is broken?)
Sheplyakov Alexei
varg at theor.jinr.ru
Tue Mar 22 13:33:08 CET 2005
Hello!
This simple program fails:
#include <iostream>
#include <stdexcept>
#include <cassert>
#include <ginac/ginac.h>
using namespace std;
using namespace GiNaC;
int main(int argc, char** argv)
{
symbol x("x");
symbol y("y");
ex a = pow(x,2) - pow(y,2);
ex b = pow(x,4) - pow(y, 4);
ex ca, cb;
cout << "GCD(" << a << ", " << b << ") = ";
ex ab_gcd = gcd(a, b, &ca, &cb, false);
cout << ab_gcd << endl;
assert((a-ca*ab_gcd).expand().is_zero());
assert((b-cb*ab_gcd).expand().is_zero());
return 0;
}
Documentation (normal.cpp:1256) says
\begin{quote}
/*
* Compute GCD (Greatest Common Divisor) of multivariate
* polynomials a(X) and b(X) in Z[X]. Optionally also compute
* the cofactors of a and b, defined by a = ca * gcd(a, b)
* and b = cb * gcd(a, b).
*/
\end{quote}
so this behaviour is probably a bug.
I've got a patch to fix it (see attachment #1), but I'm not sure if
it is correct.
Relevant part of gdb session is attached too.
P.S.
I use GiNaC 1.3.1 from CVS, g++-3.4 from Debian testing.
--
Best regards,
Alexei
-------------- next part --------------
Index: normal.cpp
===================================================================
RCS file: /home/cvs/GiNaC/ginac/normal.cpp,v
retrieving revision 1.94.2.3
diff -r1.94.2.3 normal.cpp
1250,1253d1249
< ex lc = g.lcoeff(x);
< if (is_exactly_a<numeric>(lc) && ex_to<numeric>(lc).is_negative())
< return -g;
< else
-------------- next part --------------
// Apply evaluation homomorphism and calculate GCD |#1 0xb7efcb23 in GiNaC::gcd (a=@0xbfffec40,
ex cp, cq; | b=@0xbfffec50, ca=0xbfffebd0, cb=0xbfffebf0,
ex gamma = heur_gcd(p.subs(x == xi, subs_options::no_pa| check_args=false)
ttern), q.subs(x == xi, subs_options::no_pattern), &cp, &cq| at ../../ginac-1.3.1-orig/ginac/normal.cpp:1462
, var+1).expand(); |#2 0x08049cd2 in main (argc=1, argv=0xbfffed24)
if (!is_exactly_a<fail>(gamma)) { | at gcd_bugreport.cpp:16
|(gdb) call a.dbgprint()
// Reconstruct polynomial from GCD of mapped polynomi|-y^2+x^2
als |(gdb) call b.dbgprint()
ex g = interpolate(gamma, xi, x, maxdeg); |-y^4+x^4
|(gdb) call gc.value.debug_print()
// Remove integer content |(cl_I) 1
g /= g.integer_content(); |(gdb) call g.dbgprint()
|-y^2+x^2
// If the calculated polynomial divides both p and q,|(gdb) call lc.dbgprint()
this is the GCD |-1
ex dummy; |(gdb) call ca->dbgprint()
if (divide_in_z(p, g, ca ? *ca : dummy, var) && divid|1
e_in_z(q, g, cb ? *cb : dummy, var)) { |(gdb) call cb->dbgprint()
g *= gc; |y^2+x^2
// I think one needs just return g; here [-A.S.] |(gdb)
ex lc = g.lcoeff(x); |
if (is_exactly_a<numeric>(lc) && ex_to<numeric>(lc)|
.is_negative()) |
return -g; |[No File] [RO]------------------------- 0,0-1 ------- All
else |int main(int argc, char** argv)
return g; |{
} | symbol x("x");
} | symbol y("y");
| ex a = pow(x,2) - pow(y,2);
// Next evaluation point | ex b = pow(x,4) - pow(y, 4);
xi = iquo(xi * isqrt(isqrt(xi)) * numeric(73794), numer| ex ca, cb;
ic(27011)); | cout << "GCD(" << a << ", " << b << ") = ";
} | ex ab_gcd = gcd(a, b, &ca, &cb, false);
return (new fail())->setflag(status_flags::dynallocated);| cout << ab_gcd << endl;
} | cout << "a cofactor: " << ca << endl;
| cout << "b cofactor: " << cb << endl;
|
More information about the GiNaC-list
mailing list