summaryrefslogtreecommitdiff
path: root/libguile/num2integral.i.c
diff options
context:
space:
mode:
authorMarius Vollmer <mvo@zagadka.de>2001-11-12 01:12:37 +0000
committerMarius Vollmer <mvo@zagadka.de>2001-11-12 01:12:37 +0000
commit3d2e8ceb97e7f8ba975d73028f8b7a258d349556 (patch)
tree48891d8811bd791db6c26181afbe89712e55b72e /libguile/num2integral.i.c
parentfdf773fa8f5079ea9194d6a0ed01631d4ccd99a9 (diff)
downloadguile-3d2e8ceb97e7f8ba975d73028f8b7a258d349556.tar.gz
* numbers.c: Document macros to define when including
num2integral.i.c. MAX_VALUE and MIN_VALU are no longer used, we now rely on SIZEOF_ macros that have been figured out at configure time. * num2integral.i.c: Adapt to new interface. (NUM2INTEGRAL): Test whether a fixnum can be represented in the target type by casting it and checking whether it is still the same. Do not try to handle bignums for integral types that are smaller than fixnums. When handling bignums, collect the magnituse first into a unsigned type, and correctly check for overflow. (INTEGRAL2BIG): Do not use MIN_VALUE explicitely by observing that only -MIN_VALUE can still be negative of all negative numbers (in twos-complement).
Diffstat (limited to 'libguile/num2integral.i.c')
-rw-r--r--libguile/num2integral.i.c100
1 files changed, 50 insertions, 50 deletions
diff --git a/libguile/num2integral.i.c b/libguile/num2integral.i.c
index fa1d8c6ec..b6e8a9b5f 100644
--- a/libguile/num2integral.i.c
+++ b/libguile/num2integral.i.c
@@ -1,5 +1,19 @@
/* this file is #include'd (many times) by numbers.c */
+#ifndef UNSIGNED_ITYPE
+#ifdef UNSIGNED
+#define UNSIGNED_ITYPE ITYPE
+#else
+#define UNSIGNED_ITYPE unsigned ITYPE
+#endif
+#endif
+
+#define UNSIGNED_ITYPE_MAX (~((UNSIGNED_ITYPE)0))
+
+#ifndef SIZEOF_ITYPE
+#define SIZEOF_ITYPE (2*SIZEOF_SCM_T_BITS)
+#endif
+
ITYPE
NUM2INTEGRAL (SCM num, unsigned long int pos, const char *s_caller)
{
@@ -19,11 +33,7 @@ NUM2INTEGRAL (SCM num, unsigned long int pos, const char *s_caller)
return (ITYPE) n;
else
{ /* an inum can be out of range, so check */
- if (n > (scm_t_signed_bits)MAX_VALUE
-#ifndef UNSIGNED
- || n < (scm_t_signed_bits)MIN_VALUE
-#endif
- )
+ if (((ITYPE)n) != n)
scm_out_of_range (s_caller, num);
else
return (ITYPE) n;
@@ -31,8 +41,9 @@ NUM2INTEGRAL (SCM num, unsigned long int pos, const char *s_caller)
}
else if (SCM_BIGP (num))
{ /* bignum */
-
- ITYPE res = 0;
+#if SIZEOF_ITYPE >= SIZEOF_SCM_T_BITS
+
+ UNSIGNED_ITYPE pos_res = 0;
size_t l;
#ifdef UNSIGNED
@@ -42,22 +53,17 @@ NUM2INTEGRAL (SCM num, unsigned long int pos, const char *s_caller)
for (l = SCM_NUMDIGS (num); l--;)
{
- ITYPE new = SCM_I_BIGUP (ITYPE, res) + SCM_BDIGITS (num)[l];
- if (new < res
-#ifndef UNSIGNED
- && !(new == MIN_VALUE && l == 0)
-#endif
- )
+ if (pos_res > SCM_BIGDN (UNSIGNED_ITYPE_MAX))
scm_out_of_range (s_caller, num);
- res = new;
+ pos_res = SCM_I_BIGUP (ITYPE, pos_res) + SCM_BDIGITS (num)[l];
}
#ifdef UNSIGNED
- return res;
+ return pos_res;
#else
if (SCM_BIGSIGN (num))
{
- res = -res;
+ ITYPE res = -((ITYPE)pos_res);
if (res <= 0)
return res;
else
@@ -65,12 +71,18 @@ NUM2INTEGRAL (SCM num, unsigned long int pos, const char *s_caller)
}
else
{
+ ITYPE res = (ITYPE)pos_res;
if (res >= 0)
return res;
else
scm_out_of_range (s_caller, num);
}
#endif
+
+#else /* SIZEOF_ITYPE >= SIZEOF_SCM_T_BITS */
+ scm_out_of_range (s_caller, num);
+#endif
+
}
else
scm_wrong_type_arg (s_caller, pos, num);
@@ -79,43 +91,22 @@ NUM2INTEGRAL (SCM num, unsigned long int pos, const char *s_caller)
SCM
INTEGRAL2NUM (ITYPE n)
{
- /* Determine at compile time whether we need to porferm the FIXABLE
- test or not. This is not done to get more optimal code out of
- the compiler (it can figure this out on its already), but to
- avoid a spurious warning.
+ /* If we know the size of the type, determine at compile time
+ whether we need to perform the FIXABLE test or not. This is not
+ done to get more optimal code out of the compiler (it can figure
+ this out on its own already), but to avoid a spurious warning.
+ If we don't know the size, assume that the test must be done.
*/
-#ifdef NEED_CHECK
-#undef NEED_CHECK
-#endif
-
-#ifdef NO_PREPRO_MAGIC
-#define NEED_CHECK
-#else
-#ifdef UNSIGNED
-#if MAX_VALUE>SCM_MOST_POSITIVE_FIXNUM
-#define NEED_CHECK
-#endif
-#else
-#if MIN_VALUE<SCM_MOST_NEGATIVE_FIXNUM || MAX_VALUE>SCM_MOST_POSITIVE_FIXNUM
-#define NEED_CHECK
-#endif
-#endif
-#endif
-
+#if SIZEOF_ITYPE >= SIZEOF_SCM_T_BITS
#ifndef UNSIGNED
-#ifdef NEED_CHECK
if (SCM_FIXABLE (n))
-#endif
#else
-#ifdef NEED_CHECK
if (SCM_POSFIXABLE (n))
#endif
#endif
return SCM_MAKINUM ((scm_t_signed_bits) n);
-#undef NEED_CHECK
-
#ifdef SCM_BIGDIG
return INTEGRAL2BIG (n);
#else
@@ -142,10 +133,17 @@ INTEGRAL2BIG (ITYPE n)
#endif
#ifndef UNSIGNED
- if (n == MIN_VALUE)
- /* special case */
- n_digits =
- (sizeof (ITYPE) + sizeof (SCM_BIGDIG) - 1) / sizeof (SCM_BIGDIG);
+ /* If n is still negative here, it must be the minimum value of the
+ type (assuming twos-complement, but we are tied to that anyway).
+ If this is the case, we can not count the number of digits by
+ right-shifting n until it is zero.
+ */
+ if (n < 0)
+ {
+ /* special case */
+ n_digits =
+ (sizeof (ITYPE) + sizeof (SCM_BIGDIG) - 1) / sizeof (SCM_BIGDIG);
+ }
else
#endif
{
@@ -175,11 +173,13 @@ INTEGRAL2BIG (ITYPE n)
#undef INTEGRAL2NUM
#undef INTEGRAL2BIG
#undef NUM2INTEGRAL
+#ifdef UNSIGNED
#undef UNSIGNED
+#endif
#undef ITYPE
-#undef MIN_VALUE
-#undef MAX_VALUE
-#undef NO_PREPRO_MAGIC
+#undef SIZEOF_ITYPE
+#undef UNSIGNED_ITYPE
+#undef UNSIGNED_ITYPE_MAX
/*
Local Variables: