summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libguile/num2integral.i.c100
-rw-r--r--libguile/numbers.c81
2 files changed, 97 insertions, 84 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:
diff --git a/libguile/numbers.c b/libguile/numbers.c
index 62fb3d918..154974d24 100644
--- a/libguile/numbers.c
+++ b/libguile/numbers.c
@@ -4258,12 +4258,47 @@ scm_i_big2dbl (SCM b)
# endif
#endif
+/* Parameters for creating integer conversion routines.
+
+ Define the following preprocessor macros before including
+ "libguile/num2integral.i.c":
+
+ NUM2INTEGRAL - the name of the function for converting from a
+ Scheme object to the integral type. This function
+ will be defined when including "num2integral.i.c".
+
+ INTEGRAL2NUM - the name of the function for converting from the
+ integral type to a Scheme object. This function
+ will be defined.
+
+ INTEGRAL2BIG - the name of an internal function that createas a
+ bignum from the integral type. This function will
+ be defined. The name should start with "scm_i_".
+
+ ITYPE - the name of the integral type.
+
+ UNSIGNED - Define this when ITYPE is an unsigned type. Do not
+ define it otherwise.
+
+ UNSIGNED_ITYPE
+ - the name of the the unsigned variant of the
+ integral type. If you don't define this, it defaults
+ to "unsigned ITYPE" for signed types and simply "ITYPE"
+ for unsigned ones.
+
+ SIZEOF_ITYPE - an expression giving the size of the integral type in
+ bytes. This expression must be computable by the
+ preprocessor. If you don't know a value for this,
+ don't define it. The purpose of this parameter is
+ mainly to suppress some warnings. The generated
+ code will work correctly without it.
+*/
+
#define NUM2INTEGRAL scm_num2short
#define INTEGRAL2NUM scm_short2num
#define INTEGRAL2BIG scm_i_short2big
#define ITYPE short
-#define MIN_VALUE SHRT_MIN
-#define MAX_VALUE SHRT_MAX
+#define SIZEOF_ITYPE SIZEOF_SHORT
#include "libguile/num2integral.i.c"
#define NUM2INTEGRAL scm_num2ushort
@@ -4271,15 +4306,14 @@ scm_i_big2dbl (SCM b)
#define INTEGRAL2BIG scm_i_ushort2big
#define UNSIGNED
#define ITYPE unsigned short
-#define MAX_VALUE USHRT_MAX
+#define SIZEOF_ITYPE SIZEOF_SHORT
#include "libguile/num2integral.i.c"
#define NUM2INTEGRAL scm_num2int
#define INTEGRAL2NUM scm_int2num
#define INTEGRAL2BIG scm_i_int2big
#define ITYPE int
-#define MIN_VALUE INT_MIN
-#define MAX_VALUE INT_MAX
+#define SIZEOF_ITYPE SIZEOF_INT
#include "libguile/num2integral.i.c"
#define NUM2INTEGRAL scm_num2uint
@@ -4287,15 +4321,14 @@ scm_i_big2dbl (SCM b)
#define INTEGRAL2BIG scm_i_uint2big
#define UNSIGNED
#define ITYPE unsigned int
-#define MAX_VALUE UINT_MAX
+#define SIZEOF_ITYPE SIZEOF_INT
#include "libguile/num2integral.i.c"
#define NUM2INTEGRAL scm_num2long
#define INTEGRAL2NUM scm_long2num
#define INTEGRAL2BIG scm_i_long2big
#define ITYPE long
-#define MIN_VALUE LONG_MIN
-#define MAX_VALUE LONG_MAX
+#define SIZEOF_ITYPE SIZEOF_LONG
#include "libguile/num2integral.i.c"
#define NUM2INTEGRAL scm_num2ulong
@@ -4303,40 +4336,23 @@ scm_i_big2dbl (SCM b)
#define INTEGRAL2BIG scm_i_ulong2big
#define UNSIGNED
#define ITYPE unsigned long
-#define MAX_VALUE ULONG_MAX
+#define SIZEOF_ITYPE SIZEOF_LONG
#include "libguile/num2integral.i.c"
-#ifndef PTRDIFF_MIN
-/* the below is not really guaranteed to work (I think), but probably does: */
-#define PTRDIFF_MIN ((ptrdiff_t) ((ptrdiff_t)1 << (sizeof (ptrdiff_t)*8 - 1)))
-/* this prevents num2integral.c.i from using PTRDIFF_MIN in
- preprocessor expressions. */
-#define NO_PREPRO_MAGIC
-#endif
-
-#ifndef PTRDIFF_MAX
-#define PTRDIFF_MAX (~ PTRDIFF_MIN)
-#endif
-
#define NUM2INTEGRAL scm_num2ptrdiff
#define INTEGRAL2NUM scm_ptrdiff2num
#define INTEGRAL2BIG scm_i_ptrdiff2big
#define ITYPE ptrdiff_t
-#define MIN_VALUE PTRDIFF_MIN
-#define MAX_VALUE PTRDIFF_MAX
+#define UNSIGNED_ITYPE size_t
+#define SIZEOF_ITYPE SIZEOF_PTRDIFF_T
#include "libguile/num2integral.i.c"
-#ifndef SIZE_MAX
-#define SIZE_MAX ((size_t) (-1))
-#define NO_PREPRO_MAGIC
-#endif
-
#define NUM2INTEGRAL scm_num2size
#define INTEGRAL2NUM scm_size2num
#define INTEGRAL2BIG scm_i_size2big
#define UNSIGNED
#define ITYPE size_t
-#define MAX_VALUE SIZE_MAX
+#define SIZEOF_ITYPE SIZEOF_SIZE_T
#include "libguile/num2integral.i.c"
#ifdef HAVE_LONG_LONGS
@@ -4349,9 +4365,7 @@ scm_i_big2dbl (SCM b)
#define INTEGRAL2NUM scm_long_long2num
#define INTEGRAL2BIG scm_i_long_long2big
#define ITYPE long long
-#define MIN_VALUE LLONG_MIN
-#define MAX_VALUE LLONG_MAX
-#define NO_PREPRO_MAGIC
+#define SIZEOF_ITYPE SIZEOF_LONG_LONG
#include "libguile/num2integral.i.c"
#define NUM2INTEGRAL scm_num2ulong_long
@@ -4359,8 +4373,7 @@ scm_i_big2dbl (SCM b)
#define INTEGRAL2BIG scm_i_ulong_long2big
#define UNSIGNED
#define ITYPE unsigned long long
-#define MAX_VALUE ULLONG_MAX
-#define NO_PREPRO_MAGIC
+#define SIZEOF_ITYPE SIZEOF_LONG_LONG
#include "libguile/num2integral.i.c"
#endif /* HAVE_LONG_LONGS */