mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-04-30 03:40:34 +02:00
Reimplement scm_{to,from}_{int32,uint32}
* libguile/numbers.c (scm_to_int32, scm_from_int32, scm_to_uint32): (scm_from_uint32): Reimplement inline. * libguile/integers.c (make_bignum_2): (make_bignum_from_uint64): (negative_uint32_to_int32): (positive_uint32_to_int32): (bignum_to_int32): (bignum_to_uint32): (scm_integer_from_int32): (scm_integer_from_uint32): (scm_integer_to_int32_z): (scm_integer_to_uint32_z): Better int32 support for 32-bit machines.
This commit is contained in:
parent
27910181c5
commit
717e787da6
3 changed files with 171 additions and 25 deletions
|
@ -182,21 +182,25 @@ make_bignum_1 (int is_negative, mp_limb_t limb)
|
||||||
return is_negative ? negate_bignum(z) : z;
|
return is_negative ? negate_bignum(z) : z;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SCM_SIZEOF_LONG == 4
|
||||||
|
static struct scm_bignum *
|
||||||
|
make_bignum_2 (int is_negative, mp_limb_t lo, mp_limb_t hi)
|
||||||
|
{
|
||||||
|
struct scm_bignum *z = allocate_bignum (2);
|
||||||
|
z->limbs[0] = lo;
|
||||||
|
z->limbs[1] = hi;
|
||||||
|
return is_negative ? negate_bignum(z) : z;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static struct scm_bignum *
|
static struct scm_bignum *
|
||||||
make_bignum_from_uint64 (uint64_t val)
|
make_bignum_from_uint64 (uint64_t val)
|
||||||
{
|
{
|
||||||
#if SCM_SIZEOF_LONG == 4
|
#if SCM_SIZEOF_LONG == 4
|
||||||
mp_limb_t lo = val, hi = val >> 32;
|
if (val > UINT32_MAX)
|
||||||
struct scm_bignum *z = allocate_bignum (hi ? 2 : 1);
|
return make_bignum_2 (0, val, val >> 32);
|
||||||
z->limbs[0] = lo;
|
|
||||||
if (hi)
|
|
||||||
z->limbs[1] = hi;
|
|
||||||
return z;
|
|
||||||
#else
|
|
||||||
struct scm_bignum *z = allocate_bignum (1);
|
|
||||||
z->limbs[0] = val;
|
|
||||||
return z;
|
|
||||||
#endif
|
#endif
|
||||||
|
return make_bignum_1 (0, val);
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct scm_bignum *
|
static struct scm_bignum *
|
||||||
|
@ -384,6 +388,59 @@ bignum_to_uint64 (struct scm_bignum *z, uint64_t *val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SCM_SIZEOF_LONG == 4
|
||||||
|
static int
|
||||||
|
negative_uint32_to_int32 (uint32_t magnitude, int32_t *val)
|
||||||
|
{
|
||||||
|
if (magnitude > long_magnitude (INT32_MIN))
|
||||||
|
return 0;
|
||||||
|
*val = negative_long (magnitude);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
positive_uint32_to_int32 (uint32_t magnitude, int32_t *val)
|
||||||
|
{
|
||||||
|
if (magnitude > INT32_MAX)
|
||||||
|
return 0;
|
||||||
|
*val = magnitude;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bignum_to_int32 (struct scm_bignum *z, int32_t *val)
|
||||||
|
{
|
||||||
|
switch (bignum_size (z))
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
return negative_uint32_to_int32 (bignum_limbs (z)[0], val);
|
||||||
|
case 0:
|
||||||
|
*val = 0;
|
||||||
|
return 1;
|
||||||
|
case 1:
|
||||||
|
return positive_uint32_to_int32 (bignum_limbs (z)[0], val);
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
bignum_to_uint32 (struct scm_bignum *z, uint32_t *val)
|
||||||
|
{
|
||||||
|
switch (bignum_size (z))
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
*val = 0;
|
||||||
|
return 1;
|
||||||
|
case 1:
|
||||||
|
*val = bignum_limbs (z)[0];
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bignum_cmp_long (struct scm_bignum *z, long l)
|
bignum_cmp_long (struct scm_bignum *z, long l)
|
||||||
{
|
{
|
||||||
|
@ -2921,6 +2978,36 @@ scm_integer_exact_quotient_zz (struct scm_bignum *n, struct scm_bignum *d)
|
||||||
return take_mpz (q);
|
return take_mpz (q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SCM_SIZEOF_LONG == 4
|
||||||
|
SCM
|
||||||
|
scm_integer_from_int32 (int32_t n)
|
||||||
|
{
|
||||||
|
if (SCM_FIXABLE (n))
|
||||||
|
return SCM_I_MAKINUM (n);
|
||||||
|
return scm_from_bignum (long_to_bignum (n));
|
||||||
|
}
|
||||||
|
|
||||||
|
SCM
|
||||||
|
scm_integer_from_uint32 (uint32_t n)
|
||||||
|
{
|
||||||
|
if (SCM_POSFIXABLE (n))
|
||||||
|
return SCM_I_MAKINUM (n);
|
||||||
|
return scm_from_bignum (ulong_to_bignum (n));
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
scm_integer_to_int32_z (struct scm_bignum *z, int32_t *val)
|
||||||
|
{
|
||||||
|
return bignum_to_int32 (z, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
scm_integer_to_uint32_z (struct scm_bignum *z, uint32_t *val)
|
||||||
|
{
|
||||||
|
return bignum_to_uint32 (z, val);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SCM
|
SCM
|
||||||
scm_integer_from_int64 (int64_t n)
|
scm_integer_from_int64 (int64_t n)
|
||||||
{
|
{
|
||||||
|
|
|
@ -199,9 +199,15 @@ SCM_INTERNAL SCM scm_integer_exact_quotient_zi (struct scm_bignum *n,
|
||||||
SCM_INTERNAL SCM scm_integer_exact_quotient_zz (struct scm_bignum *n,
|
SCM_INTERNAL SCM scm_integer_exact_quotient_zz (struct scm_bignum *n,
|
||||||
struct scm_bignum *d);
|
struct scm_bignum *d);
|
||||||
|
|
||||||
|
#if SCM_SIZEOF_LONG == 4
|
||||||
|
SCM_INTERNAL SCM scm_integer_from_int32 (int32_t n);
|
||||||
|
SCM_INTERNAL SCM scm_integer_from_uint32 (uint32_t n);
|
||||||
|
SCM_INTERNAL int scm_integer_to_int32_z (struct scm_bignum *z, int32_t *val);
|
||||||
|
SCM_INTERNAL int scm_integer_to_uint32_z (struct scm_bignum *z, uint32_t *val);
|
||||||
|
#endif
|
||||||
|
|
||||||
SCM_INTERNAL int scm_integer_to_int64_z (struct scm_bignum *z, int64_t *val);
|
SCM_INTERNAL int scm_integer_to_int64_z (struct scm_bignum *z, int64_t *val);
|
||||||
SCM_INTERNAL int scm_integer_to_uint64_z (struct scm_bignum *z, uint64_t *val);
|
SCM_INTERNAL int scm_integer_to_uint64_z (struct scm_bignum *z, uint64_t *val);
|
||||||
|
|
||||||
SCM_INTERNAL SCM scm_integer_from_int64 (int64_t n);
|
SCM_INTERNAL SCM scm_integer_from_int64 (int64_t n);
|
||||||
SCM_INTERNAL SCM scm_integer_from_uint64 (uint64_t n);
|
SCM_INTERNAL SCM scm_integer_from_uint64 (uint64_t n);
|
||||||
|
|
||||||
|
|
|
@ -6958,21 +6958,74 @@ scm_from_uint16 (uint16_t arg)
|
||||||
return SCM_I_MAKINUM (arg);
|
return SCM_I_MAKINUM (arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TYPE int32_t
|
int32_t
|
||||||
#define TYPE_MIN INT32_MIN
|
scm_to_int32 (SCM arg)
|
||||||
#define TYPE_MAX INT32_MAX
|
{
|
||||||
#define SIZEOF_TYPE 4
|
#if SCM_SIZEOF_LONG == 4
|
||||||
#define SCM_TO_TYPE_PROTO(arg) scm_to_int32 (arg)
|
if (SCM_I_INUMP (arg))
|
||||||
#define SCM_FROM_TYPE_PROTO(arg) scm_from_int32 (arg)
|
return SCM_I_INUM (arg);
|
||||||
#include "conv-integer.i.c"
|
else if (!SCM_BIGP (arg))
|
||||||
|
scm_wrong_type_arg_msg (NULL, 0, arg, "exact integer");
|
||||||
|
int32_t ret;
|
||||||
|
if (scm_integer_to_int32_z (scm_bignum (arg), &ret))
|
||||||
|
return ret;
|
||||||
|
range_error (arg, scm_integer_from_int32 (INT32_MIN),
|
||||||
|
scm_integer_from_int32 (INT32_MAX));
|
||||||
|
#elif SCM_SIZEOF_LONG == 8
|
||||||
|
return inum_in_range (arg, INT32_MIN, INT32_MAX);
|
||||||
|
#else
|
||||||
|
#error bad inum size
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#define TYPE uint32_t
|
SCM
|
||||||
#define TYPE_MIN 0
|
scm_from_int32 (int32_t arg)
|
||||||
#define TYPE_MAX UINT32_MAX
|
{
|
||||||
#define SIZEOF_TYPE 4
|
#if SCM_SIZEOF_LONG == 4
|
||||||
#define SCM_TO_TYPE_PROTO(arg) scm_to_uint32 (arg)
|
return scm_integer_from_int32 (arg);
|
||||||
#define SCM_FROM_TYPE_PROTO(arg) scm_from_uint32 (arg)
|
#elif SCM_SIZEOF_LONG == 8
|
||||||
#include "conv-uinteger.i.c"
|
return SCM_I_MAKINUM (arg);
|
||||||
|
#else
|
||||||
|
#error bad inum size
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
scm_to_uint32 (SCM arg)
|
||||||
|
{
|
||||||
|
#if SCM_SIZEOF_LONG == 4
|
||||||
|
if (SCM_I_INUMP (arg))
|
||||||
|
{
|
||||||
|
if (SCM_I_INUM (arg) > 0)
|
||||||
|
return SCM_I_INUM (arg);
|
||||||
|
}
|
||||||
|
else if (SCM_BIGP (arg))
|
||||||
|
{
|
||||||
|
uint32_t ret;
|
||||||
|
if (scm_integer_to_uint32_z (scm_bignum (arg), &ret))
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
scm_wrong_type_arg_msg (NULL, 0, arg, "exact integer");
|
||||||
|
range_error (arg, 0, scm_integer_from_uint32 (UINT32_MAX));
|
||||||
|
#elif SCM_SIZEOF_LONG == 8
|
||||||
|
return inum_in_range (arg, 0, UINT32_MAX);
|
||||||
|
#else
|
||||||
|
#error bad inum size
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
SCM
|
||||||
|
scm_from_uint32 (uint32_t arg)
|
||||||
|
{
|
||||||
|
#if SCM_SIZEOF_LONG == 4
|
||||||
|
return scm_integer_from_uint32 (arg);
|
||||||
|
#elif SCM_SIZEOF_LONG == 8
|
||||||
|
return SCM_I_MAKINUM (arg);
|
||||||
|
#else
|
||||||
|
#error bad inum size
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#define TYPE scm_t_wchar
|
#define TYPE scm_t_wchar
|
||||||
#define TYPE_MIN (int32_t)-1
|
#define TYPE_MIN (int32_t)-1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue