diff options
-rw-r--r-- | libguile/num2integral.i.c | 100 | ||||
-rw-r--r-- | libguile/numbers.c | 81 |
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 */ |