1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-04-30 11:50:28 +02:00

Implement abs with new integer lib

* libguile/integers.c (scm_integer_abs_i, scm_integer_abs_z): New
internal functions.
* libguile/integers.h: Declare internal functions.
* libguile/numbers.c (scm_abs): Use the new functions.
This commit is contained in:
Andy Wingo 2021-12-03 14:23:51 +01:00
parent 5321899b9a
commit 44c654aa3e
3 changed files with 27 additions and 16 deletions

View file

@ -244,3 +244,25 @@ scm_is_integer_odd_z (SCM z)
{ {
return bignum_limbs (scm_bignum (z))[0] & 1; return bignum_limbs (scm_bignum (z))[0] & 1;
} }
SCM
scm_integer_abs_i (scm_t_inum i)
{
if (i >= 0)
return SCM_I_MAKINUM (i);
unsigned long abs = long_magnitude (i);
if (SCM_LIKELY (SCM_POSFIXABLE (abs)))
return SCM_I_MAKINUM (abs);
return ulong_to_bignum (abs);
}
SCM
scm_integer_abs_z (SCM z)
{
if (!bignum_is_negative (scm_bignum (z)))
return z;
return SCM_PACK (negate_bignum (clone_bignum (scm_bignum (z))));
}

View file

@ -26,6 +26,9 @@
SCM_INTERNAL int scm_is_integer_odd_i (scm_t_inum i); SCM_INTERNAL int scm_is_integer_odd_i (scm_t_inum i);
SCM_INTERNAL int scm_is_integer_odd_z (SCM z); SCM_INTERNAL int scm_is_integer_odd_z (SCM z);
SCM_INTERNAL SCM scm_integer_abs_i (scm_t_inum i);
SCM_INTERNAL SCM scm_integer_abs_z (SCM z);
#endif /* SCM_INTEGERS_H */ #endif /* SCM_INTEGERS_H */

View file

@ -919,15 +919,7 @@ SCM_PRIMITIVE_GENERIC (scm_abs, "abs", 1, 0, 0,
#define FUNC_NAME s_scm_abs #define FUNC_NAME s_scm_abs
{ {
if (SCM_I_INUMP (x)) if (SCM_I_INUMP (x))
{ return scm_integer_abs_i (SCM_I_INUM (x));
scm_t_inum xx = SCM_I_INUM (x);
if (xx >= 0)
return x;
else if (SCM_POSFIXABLE (-xx))
return SCM_I_MAKINUM (-xx);
else
return scm_i_inum2big (-xx);
}
else if (SCM_LIKELY (SCM_REALP (x))) else if (SCM_LIKELY (SCM_REALP (x)))
{ {
double xx = SCM_REAL_VALUE (x); double xx = SCM_REAL_VALUE (x);
@ -941,13 +933,7 @@ SCM_PRIMITIVE_GENERIC (scm_abs, "abs", 1, 0, 0,
return x; return x;
} }
else if (SCM_BIGP (x)) else if (SCM_BIGP (x))
{ return scm_integer_abs_z (x);
const int sgn = mpz_sgn (SCM_I_BIG_MPZ (x));
if (sgn < 0)
return scm_i_clonebig (x, 0);
else
return x;
}
else if (SCM_FRACTIONP (x)) else if (SCM_FRACTIONP (x))
{ {
if (scm_is_false (scm_negative_p (SCM_FRACTION_NUMERATOR (x)))) if (scm_is_false (scm_negative_p (SCM_FRACTION_NUMERATOR (x))))