#line 2 "../src/kernel/none/ratlift.c"
static ulong
get_vmax(GEN r, long lb, long lbb)
{
long lr = lb - lgefint(r);
ulong vmax;
if (lr > 1)
vmax = ULONG_MAX;
else
{
long lbr = bfffo(*int_MSW(r));
lr = lr*BITS_IN_LONG - lbb + lbr;
if ((ulong)lr > BITS_IN_LONG)
vmax = ULONG_MAX;
else if (lr == 0)
vmax = 1UL;
else
vmax = 1UL << (lr-1);
}
return vmax;
}
int
Fp_ratlift(GEN x, GEN m, GEN amax, GEN bmax, GEN *a, GEN *b)
{
GEN d, d1, v, v1, q, r;
pari_sp av = avma, av1;
long lb, lbb, s, s0;
ulong vmax;
ulong xu, xu1, xv, xv1;
int lhmres;
if (!signe(x)) { *a = gen_0; *b = gen_1; return 1; }
if (!signe(amax)) return 0;
if (cmpii(x,amax) <= 0) { *a = icopy(x); *b = gen_1; return 1; }
(void)new_chunk(lgefint(bmax) + lgefint(amax));
d = m; d1 = x;
v = gen_0; v1 = gen_1;
lb = lgefint(bmax);
lbb = bfffo(*int_MSW(bmax));
s = 1;
av1 = avma;
while (lgefint(d) > 3 && signe(d1))
{
r = addii(v,v1);
if (cmpii(r,bmax) > 0) { avma = av; return 0; }
vmax = get_vmax(r, lb, lbb);
lhmres = lgcdii((ulong *)d, (ulong *)d1, &xu, &xu1, &xv, &xv1, vmax);
if (lhmres)
{
if (lhmres == 1 || lhmres == -1)
{
s = -s;
if (xv1 == 1)
{
v = v1; v1 = r;
r = subii(d,d1); d = d1; d1 = r;
}
else
{
r = subii(d, mului(xv1,d1)); d = d1; d1 = r;
r = addii(v, mului(xv1,v1)); v = v1; v1 = r;
}
}
else
{
r = subii(muliu(d,xu), muliu(d1,xv));
d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r;
r = addii(muliu(v,xu), muliu(v1,xv));
v1 = addii(muliu(v,xu1), muliu(v1,xv1)); v = r;
if (lhmres&1) { togglesign(d); s = -s; } else togglesign(d1);
}
if (cmpii(v1,bmax) > 0)
{
avma = av;
if (cmpii(d,amax) > 0) return 0;
*a = icopy(d); setsigne(*a,-s);
*b = icopy(v); return 1;
}
if (cmpii(d1,amax) <= 0)
{
avma = av;
if (signe(d1)) { *a = icopy(d1); setsigne(*a,s); } else *a = gen_0;
*b = icopy(v1); return 1;
}
}
if (lhmres <= 0 && signe(d1))
{
q = dvmdii(d,d1,&r);
d = d1; d1 = r;
r = addii(v, mulii(q,v1));
v = v1; v1 = r;
s = -s;
if (cmpii(v1,bmax) > 0) { avma = av; return 0; }
if (cmpii(d1,amax) <= 0)
{
avma = av;
if (signe(d1)) { *a = icopy(d1); setsigne(*a,s); } else *a = gen_0;
*b = icopy(v1); return 1;
}
}
if (gc_needed(av,1))
{
if(DEBUGMEM>1) pari_warn(warnmem,"ratlift");
gerepileall(av1, 4, &d, &d1, &v, &v1);
}
}
while (signe(d1))
{
r = addii(v,v1);
if (cmpii(r,bmax) > 0) { avma = av; return 0; }
vmax = get_vmax(r, lb, lbb);
(void)rgcduu((ulong)*int_MSW(d), (ulong)*int_MSW(d1), vmax, &xu, &xu1, &xv, &xv1, &s0);
if (xv1 == 1)
{
v = v1; v1 = r;
r = subii(d,d1); d = d1; d1 = r;
s = -s;
}
else if (xu == 0)
{
r = subii(d, mului(xv1,d1)); d = d1; d1 = r;
r = addii(v, mului(xv1,v1)); v = v1; v1 = r;
s = -s;
}
else
{
r = subii(muliu(d,xu), muliu(d1,xv));
d1 = subii(muliu(d,xu1), muliu(d1,xv1)); d = r;
r = addii(muliu(v,xu), muliu(v1,xv));
v1 = addii(muliu(v,xu1), muliu(v1,xv1)); v = r;
if (s0 < 0) { togglesign(d); s = -s; } else togglesign(d1);
}
if (cmpii(v1,bmax) > 0)
{
avma = av;
if (cmpii(d,amax) > 0) return 0;
*a = icopy(d); setsigne(*a,-s);
*b = icopy(v); return 1;
}
if (cmpii(d1,amax) <= 0)
{
avma = av;
if (signe(d1)) { *a = icopy(d1); setsigne(*a,s); } else *a = gen_0;
*b = icopy(v1); return 1;
}
}
pari_err_BUG("ratlift failed to catch d1 == 0");
return 0;
}