[GiNaC-list] code: extended gcd
Ralf Stephan
ralf at ark.in-berlin.de
Sun Oct 3 19:41:03 CEST 2004
Hello,
please include the following snippet. Its application domain depends
on that of quo() which is univariate, currently. It is tested but not
heavily so. It is not optimized.
Thanks,
ralf
Input: x,y rational polynomials
Computes u,v,d such that ux+vy = gcd(x,y).
/////////// Extended GCD
ex xgcd (const ex& a, const ex& b, ex& u, ex& v, const symbol& s)
{
const ex& x = a.normal();
const ex& y = b.normal();
if (is_exactly_a<numeric>(x) && is_exactly_a<numeric>(y)
&& x.info(info_flags::integer) && y.info(info_flags::integer)) {
cln::cl_I cu, cv, cr;
cr = cln::xgcd (cln::the<cln::cl_I>(ex_to<numeric>(x).to_cl_N()),
cln::the<cln::cl_I>(ex_to<numeric>(y).to_cl_N()),
&cu, &cv);
u = numeric(cu); v = numeric(cv);
return numeric(cr);
}
if (is_exactly_a<numeric>(y) && y.info(info_flags::integer)) {
u = 0;
v = numeric(1)/y;
return 1;
}
if (is_exactly_a<numeric>(x) && x.info(info_flags::integer)) {
v = 0;
u = numeric(1)/x;
return 1;
}
if (x.info(info_flags::rational_polynomial)
&& y.info(info_flags::rational_polynomial)) {
ex d, p, q;
d = gcd (x, y);
int dx = degree(x, s), dy = degree(y, s);
if (dx < dy)
{ p = y; q = x; }
else
{ p = x; q = y; }
ex u1,u2,u3,v1,v2,v3,w1,w2,w3;
u1 = p; u2 = 1; u3 = 0;
v1 = q; v2 = 0; v3 = 1;
while (!v1.is_zero()) {
ex Q = quo (u1, v1, s);
w1 = u1 - Q*v1;
w2 = u2 - Q*v2;
w3 = u3 - Q*v3;
u1 = v1.expand(); u2 = v2.expand(); u3 = v3.expand();
v1 = w1.expand(); v2 = w2.expand(); v3 = w3.expand();
}
u = (u2 / ((u1/d).normal())).expand();
v = (u3 / ((u1/d).normal())).expand();
//cerr << "CHK: " << (u*x+v*y).expand() << endl << flush;
return d;
}
throw invalid_argument("xgcd(): not a rational polynomial");
}
More information about the GiNaC-list
mailing list