1
Fork 0
mirror of https://git.savannah.gnu.org/git/guile.git synced 2025-06-19 02:00:26 +02:00

Clean up <, reimplement in terms of integer lib

* libguile/numbers.c (scm_is_less_than, scm_is_greater_than):
(scm_is_less_than_or_equal, scm_is_greater_than_or_equal): New internal
functions.
(scm_less_p, scm_gr_p, scm_leq_p, scm_geq_p): Use new helpers.  Dispatch
to generics if operands aren't real -- a tightening relative to the
previous check which was just for numbers.
* libguile/integers.h:
* libguile/integers.c (scm_is_integer_less_than_ir):
(scm_is_integer_less_than_ri):
(scm_is_integer_less_than_zz):
(scm_is_integer_less_than_zr):
(scm_is_integer_less_than_rz):
(scm_is_integer_positive_z):
(scm_is_integer_negative_z): New internal functions.
This commit is contained in:
Andy Wingo 2022-01-04 13:54:12 +01:00
parent 44bee08512
commit 54d7722523
3 changed files with 200 additions and 178 deletions

View file

@ -2411,3 +2411,94 @@ scm_is_integer_equal_zc (struct scm_bignum *x, double real, double imag)
{
return imag == 0.0 && scm_is_integer_equal_zr (x, real);
}
int
scm_is_integer_less_than_ir (scm_t_inum x, double y)
{
/* We can safely take the ceiling of y without changing the
result of x<y, given that x is an integer. */
y = ceil (y);
/* In the following comparisons, it's important that the right
hand side always be a power of 2, so that it can be
losslessly converted to a double even on 64-bit
machines. */
if (y >= (double) (SCM_MOST_POSITIVE_FIXNUM+1))
return 1;
else if (!(y > (double) SCM_MOST_NEGATIVE_FIXNUM))
/* The condition above is carefully written to include the
case where y==NaN. */
return 0;
else
/* y is a finite integer that fits in an inum. */
return x < (scm_t_inum) y;
}
int
scm_is_integer_less_than_ri (double x, scm_t_inum y)
{
/* We can safely take the floor of x without changing the
result of x<y, given that y is an integer. */
x = floor (x);
/* In the following comparisons, it's important that the right
hand side always be a power of 2, so that it can be
losslessly converted to a double even on 64-bit
machines. */
if (x < (double) SCM_MOST_NEGATIVE_FIXNUM)
return 1;
else if (!(x < (double) (SCM_MOST_POSITIVE_FIXNUM+1)))
/* The condition above is carefully written to include the
case where x==NaN. */
return 0;
else
/* x is a finite integer that fits in an inum. */
return (scm_t_inum) x < y;
}
int
scm_is_integer_less_than_zz (struct scm_bignum *x, struct scm_bignum *y)
{
mpz_t zx, zy;
alias_bignum_to_mpz (x, zx);
alias_bignum_to_mpz (y, zy);
int cmp = mpz_cmp (zx, zy);
scm_remember_upto_here_2 (x, y);
return cmp < 0;
}
int
scm_is_integer_less_than_zr (struct scm_bignum *x, double y)
{
if (isnan (y))
return 0;
mpz_t zx;
alias_bignum_to_mpz (x, zx);
int cmp = mpz_cmp_d (zx, y);
scm_remember_upto_here_1 (x);
return cmp < 0;
}
int
scm_is_integer_less_than_rz (double x, struct scm_bignum *y)
{
if (isnan (x))
return 0;
mpz_t zy;
alias_bignum_to_mpz (y, zy);
int cmp = mpz_cmp_d (zy, x);
scm_remember_upto_here_1 (y);
return cmp > 0;
}
int
scm_is_integer_positive_z (struct scm_bignum *x)
{
return bignum_is_positive (x);
}
int
scm_is_integer_negative_z (struct scm_bignum *x)
{
return bignum_is_negative (x);
}