X-Git-Url: http://git.hcoop.net/bpt/guile.git/blobdiff_plain/54cbf8c6dcae9fe4925186c6f46718e7b45932fe..1fc3fc11ffea3b5c0b1844306244b3f4a52c1067:/libguile/numbers.h diff --git a/libguile/numbers.h b/libguile/numbers.h index cef2b863b..bba336bd4 100644 --- a/libguile/numbers.h +++ b/libguile/numbers.h @@ -3,7 +3,8 @@ #ifndef SCM_NUMBERS_H #define SCM_NUMBERS_H -/* Copyright (C) 1995,1996,1998,2000,2001,2002,2003,2004,2005, 2006, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +/* Copyright (C) 1995,1996,1998,2000,2001,2002,2003,2004,2005, 2006, + * 2008, 2009, 2010, 2011, 2013, 2014 Free Software Foundation, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License @@ -48,19 +49,43 @@ typedef scm_t_int32 scm_t_wchar; #define SCM_MOST_POSITIVE_FIXNUM ((SCM_T_SIGNED_BITS_MAX-3)/4) #define SCM_MOST_NEGATIVE_FIXNUM (-SCM_MOST_POSITIVE_FIXNUM-1) -/* SCM_SRS is signed right shift */ -#if (-1 == (((-1) << 2) + 2) >> 2) -# define SCM_SRS(x, y) ((x) >> (y)) +/* SCM_SRS (X, Y) is signed right shift, defined as floor (X / 2^Y), + where Y must be non-negative and less than the width in bits of X. + It's common for >> to do this, but the C standards do not specify + what happens when X is negative. + + NOTE: X must not perform side effects. */ +#if (-1 >> 2 == -1) && (-4 >> 2 == -1) && (-5 >> 2 == -2) && (-8 >> 2 == -2) +# define SCM_SRS(x, y) ((x) >> (y)) #else -# define SCM_SRS(x, y) ((x) < 0 ? ~((~(x)) >> (y)) : ((x) >> (y))) -#endif /* (-1 == (((-1) << 2) + 2) >> 2) */ +# define SCM_SRS(x, y) \ + ((x) < 0 \ + ? -1 - (scm_t_signed_bits) (~(scm_t_bits)(x) >> (y)) \ + : ((x) >> (y))) +#endif + +/* The first implementation of SCM_I_INUM below depends on behavior that + is specified by GNU C but not by C standards, namely that when + casting to a signed integer of width N, the value is reduced modulo + 2^N to be within range of the type. The second implementation below + should be portable to all conforming C implementations, but may be + less efficient if the compiler is not sufficiently clever. + + NOTE: X must not perform side effects. */ +#ifdef __GNUC__ +# define SCM_I_INUM(x) (SCM_SRS ((scm_t_signed_bits) SCM_UNPACK (x), 2)) +#else +# define SCM_I_INUM(x) \ + (SCM_UNPACK (x) > LONG_MAX \ + ? -1 - (scm_t_signed_bits) (~SCM_UNPACK (x) >> 2) \ + : (scm_t_signed_bits) (SCM_UNPACK (x) >> 2)) +#endif #define SCM_I_INUMP(x) (2 & SCM_UNPACK (x)) #define SCM_I_NINUMP(x) (!SCM_I_INUMP (x)) #define SCM_I_MAKINUM(x) \ - (SCM_PACK ((((scm_t_signed_bits) (x)) << 2) + scm_tc2_int)) -#define SCM_I_INUM(x) (SCM_SRS ((scm_t_signed_bits) SCM_UNPACK (x), 2)) + (SCM_PACK ((((scm_t_bits) (x)) << 2) + scm_tc2_int)) /* SCM_FIXABLE is true if its long argument can be encoded in an SCM_INUM. */ #define SCM_POSFIXABLE(n) ((n) <= SCM_MOST_POSITIVE_FIXNUM) @@ -204,7 +229,8 @@ SCM_API SCM scm_logbit_p (SCM n1, SCM n2); SCM_API SCM scm_lognot (SCM n); SCM_API SCM scm_modulo_expt (SCM n, SCM k, SCM m); SCM_API SCM scm_integer_expt (SCM z1, SCM z2); -SCM_API SCM scm_ash (SCM n, SCM cnt); +SCM_API SCM scm_ash (SCM n, SCM count); +SCM_API SCM scm_round_ash (SCM n, SCM count); SCM_API SCM scm_bit_extract (SCM n, SCM start, SCM end); SCM_API SCM scm_logcount (SCM n); SCM_API SCM scm_integer_length (SCM n); @@ -240,6 +266,7 @@ SCM_API SCM scm_complex_p (SCM x); SCM_API SCM scm_real_p (SCM x); SCM_API SCM scm_rational_p (SCM z); SCM_API SCM scm_integer_p (SCM x); +SCM_API SCM scm_exact_integer_p (SCM x); SCM_API SCM scm_inexact_p (SCM x); SCM_API int scm_is_inexact (SCM x); SCM_API SCM scm_num_eq_p (SCM x, SCM y); @@ -328,6 +355,7 @@ SCM_INTERNAL void scm_i_print_complex (double real, double imag, SCM port); /* conversion functions for integers */ SCM_API int scm_is_integer (SCM val); +SCM_API int scm_is_exact_integer (SCM val); SCM_API int scm_is_signed_integer (SCM val, scm_t_intmax min, scm_t_intmax max); SCM_API int scm_is_unsigned_integer (SCM val, @@ -500,6 +528,46 @@ SCM_API SCM scm_from_mpz (mpz_t rop); #endif #endif +#if SCM_SIZEOF_SCM_T_PTRDIFF == 4 +#define scm_to_ptrdiff_t scm_to_int32 +#define scm_from_ptrdiff_t scm_from_int32 +#else +#if SCM_SIZEOF_SCM_T_PTRDIFF == 8 +#define scm_to_ptrdiff_t scm_to_int64 +#define scm_from_ptrdiff_t scm_from_int64 +#else +#error sizeof(scm_t_ptrdiff) is not 4 or 8. +#endif +#endif + +#if SCM_SIZEOF_INTPTR_T == 0 +/* No intptr_t; use size_t functions. */ +#define scm_to_intptr_t scm_to_ssize_t +#define scm_from_intptr_t scm_from_ssize_t +#elif SCM_SIZEOF_INTPTR_T == 4 +#define scm_to_intptr_t scm_to_int32 +#define scm_from_intptr_t scm_from_int32 +#elif SCM_SIZEOF_INTPTR_T == 8 +#define scm_to_intptr_t scm_to_int64 +#define scm_from_intptr_t scm_from_int64 +#else +#error sizeof(intptr_t) is not 4 or 8. +#endif + +#if SCM_SIZEOF_UINTPTR_T == 0 +/* No uintptr_t; use size_t functions. */ +#define scm_to_uintptr_t scm_to_size_t +#define scm_from_uintptr_t scm_from_size_t +#elif SCM_SIZEOF_UINTPTR_T == 4 +#define scm_to_uintptr_t scm_to_uint32 +#define scm_from_uintptr_t scm_from_uint32 +#elif SCM_SIZEOF_UINTPTR_T == 8 +#define scm_to_uintptr_t scm_to_uint64 +#define scm_from_uintptr_t scm_from_uint64 +#else +#error sizeof(uintptr_t) is not 4 or 8. +#endif + /* conversion functions for double */ SCM_API int scm_is_real (SCM val);