mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 11:50:28 +02:00
Improve code in scm_gcd for inum/inum case
* libguile/numbers.c (scm_gcd): Improve implementation of inum/inum case to be more clear and efficient.
This commit is contained in:
parent
f57ea23ac8
commit
a2dead1b0f
1 changed files with 30 additions and 24 deletions
|
@ -3889,52 +3889,58 @@ SCM_PRIMITIVE_GENERIC (scm_i_gcd, "gcd", 0, 2, 1,
|
||||||
SCM
|
SCM
|
||||||
scm_gcd (SCM x, SCM y)
|
scm_gcd (SCM x, SCM y)
|
||||||
{
|
{
|
||||||
if (SCM_UNBNDP (y))
|
if (SCM_UNLIKELY (SCM_UNBNDP (y)))
|
||||||
return SCM_UNBNDP (x) ? SCM_INUM0 : scm_abs (x);
|
return SCM_UNBNDP (x) ? SCM_INUM0 : scm_abs (x);
|
||||||
|
|
||||||
if (SCM_I_INUMP (x))
|
if (SCM_LIKELY (SCM_I_INUMP (x)))
|
||||||
{
|
{
|
||||||
if (SCM_I_INUMP (y))
|
if (SCM_LIKELY (SCM_I_INUMP (y)))
|
||||||
{
|
{
|
||||||
scm_t_inum xx = SCM_I_INUM (x);
|
scm_t_inum xx = SCM_I_INUM (x);
|
||||||
scm_t_inum yy = SCM_I_INUM (y);
|
scm_t_inum yy = SCM_I_INUM (y);
|
||||||
scm_t_inum u = xx < 0 ? -xx : xx;
|
scm_t_inum u = xx < 0 ? -xx : xx;
|
||||||
scm_t_inum v = yy < 0 ? -yy : yy;
|
scm_t_inum v = yy < 0 ? -yy : yy;
|
||||||
scm_t_inum result;
|
scm_t_inum result;
|
||||||
if (xx == 0)
|
if (SCM_UNLIKELY (xx == 0))
|
||||||
result = v;
|
result = v;
|
||||||
else if (yy == 0)
|
else if (SCM_UNLIKELY (yy == 0))
|
||||||
result = u;
|
result = u;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
scm_t_inum k = 1;
|
int k = 0;
|
||||||
scm_t_inum t;
|
|
||||||
/* Determine a common factor 2^k */
|
/* Determine a common factor 2^k */
|
||||||
while (!(1 & (u | v)))
|
while (((u | v) & 1) == 0)
|
||||||
{
|
{
|
||||||
k <<= 1;
|
k++;
|
||||||
u >>= 1;
|
u >>= 1;
|
||||||
v >>= 1;
|
v >>= 1;
|
||||||
}
|
}
|
||||||
/* Now, any factor 2^n can be eliminated */
|
/* Now, any factor 2^n can be eliminated */
|
||||||
if (u & 1)
|
if ((u & 1) == 0)
|
||||||
t = -v;
|
while ((u & 1) == 0)
|
||||||
|
u >>= 1;
|
||||||
|
else
|
||||||
|
while ((v & 1) == 0)
|
||||||
|
v >>= 1;
|
||||||
|
/* Both u and v are now odd. Subtract the smaller one
|
||||||
|
from the larger one to produce an even number, remove
|
||||||
|
more factors of two, and repeat. */
|
||||||
|
while (u != v)
|
||||||
|
{
|
||||||
|
if (u > v)
|
||||||
|
{
|
||||||
|
u -= v;
|
||||||
|
while ((u & 1) == 0)
|
||||||
|
u >>= 1;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t = u;
|
v -= u;
|
||||||
b3:
|
while ((v & 1) == 0)
|
||||||
t = SCM_SRS (t, 1);
|
v >>= 1;
|
||||||
}
|
}
|
||||||
if (!(1 & t))
|
}
|
||||||
goto b3;
|
result = u << k;
|
||||||
if (t > 0)
|
|
||||||
u = t;
|
|
||||||
else
|
|
||||||
v = -t;
|
|
||||||
t = u - v;
|
|
||||||
if (t != 0)
|
|
||||||
goto b3;
|
|
||||||
result = u * k;
|
|
||||||
}
|
}
|
||||||
return (SCM_POSFIXABLE (result)
|
return (SCM_POSFIXABLE (result)
|
||||||
? SCM_I_MAKINUM (result)
|
? SCM_I_MAKINUM (result)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue