/*
Copyright (C) 2009, 2015 William Hart
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See .
*/
#include
#include "flint.h"
#include "ulong_extras.h"
ulong
n_gcdinv(ulong * s, ulong x, ulong y)
{
slong v1, v2, t2;
ulong d, r, quot, rem;
FLINT_ASSERT(y > x);
v1 = 0;
v2 = 1;
r = x;
x = y;
/* y and x both have top bit set */
if ((slong) (x & r) < 0)
{
d = x - r;
t2 = v2;
x = r;
v2 = v1 - v2;
v1 = t2;
r = d;
}
/* second value has second msb set */
while ((slong) (r << 1) < 0)
{
d = x - r;
if (d < r) /* quot = 1 */
{
t2 = v2;
x = r;
v2 = v1 - v2;
v1 = t2;
r = d;
}
else if (d < (r << 1)) /* quot = 2 */
{
x = r;
t2 = v2;
v2 = v1 - (v2 << 1);
v1 = t2;
r = d - x;
}
else /* quot = 3 */
{
x = r;
t2 = v2;
v2 = v1 - 3 * v2;
v1 = t2;
r = d - (x << 1);
}
}
while (r)
{
/* overflow not possible due to top 2 bits of r not being set */
if (x < (r << 2)) /* if quot < 4 */
{
d = x - r;
if (d < r) /* quot = 1 */
{
t2 = v2;
x = r;
v2 = v1 - v2;
v1 = t2;
r = d;
}
else if (d < (r << 1)) /* quot = 2 */
{
x = r;
t2 = v2;
v2 = v1 - (v2 << 1);
v1 = t2;
r = d - x;
}
else /* quot = 3 */
{
x = r;
t2 = v2;
v2 = v1 - 3 * v2;
v1 = t2;
r = d - (x << 1);
}
}
else
{
quot = x / r;
rem = x - r * quot;
x = r;
t2 = v2;
v2 = v1 - quot * v2;
v1 = t2;
r = rem;
}
}
if (v1 < WORD(0))
v1 += y;
(*s) = v1;
return x;
}