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:
parent
44bee08512
commit
54d7722523
3 changed files with 200 additions and 178 deletions
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue