#line 2 "../src/kernel/gmp/gcdext.c"
int
invmod(GEN a, GEN b, GEN *res)
{
if (!signe(b)) { *res=absi(a); return 0; }
if (NLIMBS(b) < INVMOD_GMP_LIMIT)
return invmod_pari(a,b,res);
{
pari_sp av = avma;
GEN ca, cb, u, d;
long l, su, sa = signe(a), lb,lna;
mp_size_t lu;
GEN na;
if (!sa) { avma = av; *res = absi(b); return 0; }
if (signe(b) < 0) b = negi(b);
if (abscmpii(a, b) < 0)
na = sa > 0? addii(a, b): subii(a, b);
else
na = a;
lb = lgefint(b); lna = lgefint(na);
ca = icopy_ef(na,lna+1);
cb = icopy_ef( b,lb+1);
u = cgeti(lna+1);
d = cgeti(lna+1);
l = mpn_gcdext(LIMBS(d), LIMBS(u), &lu, LIMBS(ca), NLIMBS(ca), LIMBS(cb), NLIMBS(cb));
d[1] = evalsigne(1)|evallgefint(l+2);
if (!is_pm1(d)) {avma=av; *res=icopy(d); return 0;}
su = lu?((sa ^ lu) < 0)? -1: 1: 0;
u[1] = evalsigne(su) | evallgefint(labs(lu)+2);
if (su < 0) u = addii(u, b);
avma=av; *res=icopy(u); return 1;
}
}
GEN
bezout(GEN a, GEN b, GEN *pu, GEN *pv)
{
long s, sa, sb;
ulong g;
ulong xu,xu1,xv,xv1;
s = abscmpii(a,b);
if (s < 0) { swap(a,b); pswap(pu,pv); }
sa = signe(a); sb = signe(b);
if (!sb)
{
if (pv) *pv = gen_0;
switch(sa)
{
case 0: if (pu) *pu = gen_0; return gen_0;
case 1: if (pu) *pu = gen_1; return icopy(a);
case -1: if (pu) *pu = gen_m1; return negi(a);
}
}
if (s == 0)
{
if (pu) *pu = gen_0;
if (sb > 0)
{ if (pv) *pv = gen_1; return icopy(b); }
else
{ if (pv) *pv = gen_m1; return negi(b); }
}
if (lgefint(a) == 3)
{
g = xxgcduu((ulong)a[2], (ulong)b[2], 0, &xu, &xu1, &xv, &xv1, &s);
sa = s > 0 ? sa : -sa;
sb = s > 0 ? -sb : sb;
if (pu)
{
if (xu == 0) *pu = gen_0;
else if (xu == 1) *pu = sa < 0 ? gen_m1 : gen_1;
else if (xu == 2) *pu = sa < 0 ? gen_m2 : gen_2;
else
{
*pu = cgeti(3);
(*pu)[1] = evalsigne(sa)|evallgefint(3);
(*pu)[2] = xu;
}
}
if (pv)
{
if (xv == 1) *pv = sb < 0 ? gen_m1 : gen_1;
else if (xv == 2) *pv = sb < 0 ? gen_m2 : gen_2;
else
{
*pv = cgeti(3);
(*pv)[1] = evalsigne(sb)|evallgefint(3);
(*pv)[2] = xv;
}
}
if (g == 1) return gen_1;
else if (g == 2) return gen_2;
else return utoipos(g);
}
else
{
pari_sp av = avma;
GEN ca = icopy_ef(a,lgefint(a)+1);
GEN cb = icopy_ef(b,lgefint(b)+1);
GEN u = cgeti(lgefint(a)+1), v = NULL;
GEN d = cgeti(lgefint(a)+1);
long su,l;
mp_size_t lu;
l = mpn_gcdext(LIMBS(d), LIMBS(u), &lu, LIMBS(ca), NLIMBS(ca), LIMBS(cb), NLIMBS(cb));
if (lu<=0)
{
if (lu==0) su=0;
else {su=-1;lu=-lu;}
}
else
su=1;
if (sa<0) su=-su;
d[1] = evalsigne(1)|evallgefint(l+2);
u[1] = evalsigne(su)|evallgefint(lu+2);
if (pv) v=diviiexact(subii(d,mulii(u,a)),b);
avma = av;
if (pu) *pu=icopy(u);
if (pv) *pv=icopy(v);
return icopy(d);
}
}