#line 2 "../src/kernel/none/gcd.c"
static ulong
resiu(GEN y, ulong x)
{
long i, ly = lgefint(y);
ulong xi = get_Fl_red(x);
LOCAL_HIREMAINDER;
hiremainder = 0;
for (i=2; i<ly; i++) (void)divll_pre(y[i],x,xi);
return hiremainder;
}
static void
gcd_plus_minus(GEN x, GEN y, GEN res)
{
pari_sp av = avma;
long lx = lgefint(x)-1;
long ly = lgefint(y)-1, lt,m,i;
GEN t;
if ((x[lx]^y[ly]) & 3)
t = addiispec(x+2,y+2,lx-1,ly-1);
else
t = subiispec(x+2,y+2,lx-1,ly-1);
lt = lgefint(t)-1; while (!t[lt]) lt--;
m = vals(t[lt]); lt++;
if (m == 0)
{
for (i = 2; i < lt; i++) res[i] = t[i];
}
else if (t[2] >> m)
{
shift_right(res,t, 2,lt, 0,m);
}
else
{
lt--; t++;
shift_right(res,t, 2,lt, t[1],m);
}
res[1] = evalsigne(1)|evallgefint(lt);
avma = av;
}
GEN
gcdii(GEN a, GEN b)
{
long v, w;
pari_sp av;
GEN t, p1;
switch (abscmpii(a,b))
{
case 0: return absi(a);
case -1: swap(a,b);
}
if (!signe(b)) return absi(a);
if (lgefint(a)==3)
return igcduu((ulong)a[2], (ulong)b[2]);
if (lgefint(b)==3)
{
ulong u = resiu(a,(ulong)b[2]);
if (!u) return absi(b);
return igcduu((ulong)b[2], u);
}
av = avma; (void)new_chunk(lgefint(b));
t = remii(a,b);
if (!signe(t)) { avma = av; return absi(b); }
a = b; b = t;
v = vali(a); a = shifti(a,-v); setabssign(a);
w = vali(b); b = shifti(b,-w); setabssign(b);
if (w < v) v = w;
switch(abscmpii(a,b))
{
case 0: avma = av; a = shifti(a,v); return a;
case -1: swap(a,b);
}
if (is_pm1(b)) { avma = av; return int2n(v); }
while (lgefint(a) > 3)
{
gcd_plus_minus(a,b, t);
if (is_pm1(t)) { avma = av; return int2n(v); }
switch(abscmpii(t,b))
{
case -1: p1 = a; a = b; b = t; t = p1; break;
case 1: swap(a,t); break;
case 0: avma = av; b = shifti(b,v); return b;
}
}
{
long r[] = {evaltyp(t_INT)|_evallg(3), evalsigne(1)|evallgefint(3), 0};
r[2] = (long) gcduodd((ulong)b[2], (ulong)a[2]);
avma = av; return shifti(r,v);
}
}