diff --git a/src/CHANGELOG b/src/CHANGELOG index d8998db3b..13ef8b86e 100644 --- a/src/CHANGELOG +++ b/src/CHANGELOG @@ -1,141 +1,20 @@ -ECL 9.8.4: +ECL 9.9.1: ========== -* Bugs fixed: - - - si_{set,get}_finalizer were not exported from ecl.dll and thus the library - TRIVIAL-GARBAGE failed to build in Windows - - - The MSVC port did not define @ECL_LDRPATH@ and failed to build ecl.dll - - - The sequence functions did not understand the newest specialized array types. - * Visible changes: - - The configuration flag --with-__thread now defaults to NO because many - platforms do not support it and GCC does not complain, making reliable - detection impossible. + - When embedded, ECL may coexist with code that uses the GMP library in + different ways, and sometimes that code may use different memory allocation + routines. In order to solve this problem ECL introduces a new option, + ECL_OPT_SET_GMP_MEMORY_FUNCTIONS, which determines whether GMP will use the + Boehm-Weiser garbage collector to allocate memory or not. - - For further compatibility with SBCL, ECL now supports two additional - buffer types :FULL and :LINE which are compatible with :FULLY-BUFFERED - and :LINE-BUFFERED (Thanks to Matthew Mondor) - - - The sockets library can now be loaded using either (REQUIRE 'SOCKETS) - or (REQUIRE 'SB-BSD-SOCKETS). - -ECL 9.8.3: -========== - -* Bugs fixed: - - - FLOAT-SIGN ignored the second argument. - -ECL 9.8.2: -========== - -* Bugs fixed: - - - The C inline expansion for sin, cos, and tan were wrong due to three - recently introduced typos. - - - The C inline form of SQRT did not work when ECL was built with - --enable-longdouble. - - - When building FASL files, the output file name was not surrounded by - double quotes, thus breaking when the file name had spaces (only - mingw32). - -* Visible changes: - - - A new configuration flag, --enable-rpath, allows hardcoding in ECL the - location of its shared library. This is not needed in Windows, it should - work on all supported platforms and its purpose is to simplify the - installation of ECL in nonstandard locations. - - -ECL 9.8.1: -========== - -* Important notes: - - - The GMP library had to be patched to build with latest versions of GCC. - Since our patch only covers the main header and there might be some corners - left, it is recommended to build ECL against a better maintained version of - the library, such as MPIR or the versions supplied by your operating system. - - - ECL now builds properly on a large number of platforms, including Windows - with and without Microsoft compilers. However, not always are all the - configuration options available or well supported. The fault is not always - ECL's, but also the libraries it depends on. Some of these problems are - detailed below, some are to be found. As a guide, the minimally supported - flags for each platform are those use for the automated testing process - http://ecls.sourceforge.net/logs.html - -* Ports: - - - The Windows/MSVC port now boots also when built without support for Unicode. - - - The Windows/mingw32 port builds without threads. For multithreading, the - user will have to build version 7.2-alpha2 of the garbage collector - manually and build ECL with it. - - - The NetBSD port builds with default values using the garbage collector - in the pkgsrc distribution. - - - The Solaris port (Intel and Sparc) now builds with the given libraries (GMP - and Boehm). - -* Compiler: - - - The compiler now understands FFI types :[u]int{8,16,32,64}-t. - - - The FFI code emitted to convert from a lisp type to :uint or :unsigned-int - rejected bignum inputs, even if they were in the range from 0 to UINT_MAX. - Similar problem with :int - -* Visible changes: - - - New functions ecl_make_[u]int(), ecl_make_[u]long(), ecl_to_[u]int(), - ecl_to_[u]long(), ecl_to_bool(), ecl_make_bool(), convert between C types - and cl_object. - - - The C structures ecl_array, ecl_vector, ecl_base_string and ecl_string have - changed. Instead of using bitfields for hasfillp and adjustable we now - use a single integer field, and handle the bits manually. See the - new macros ECL_ADJUSTABLE_ARRAY_P and ECL_ARRAY_HAS_FILL_POINTER_P. - - - Four new command-line arguments, --encoding, --input-encoding, - --output-encoding and --error-encoding, allow the user to change the - external formats of the default streams. - - - For places defined with the simple form of DEFSETF, SETF now produces - a simpler expansion, without a surrounding LET* form. - - - The dynamic FFI is now implemented using libffi. This extends the portability - and removes the previous, error prone implementation. - - - A new function, (SI:SAFE-EVAL form env &optional error-value), can be used - to evaluate lisp forms in a safe way. If supplied three values, when an - error happens, it returns ERROR-VALUE; otherwise it will invoke a debugger. - - - Two new functions, ecl_read_from_cstring(s) and - ecl_read_from_cstring_safe(s,v) read an object from a C string (char *). The - first one is unsafe and will enter a debugger when there is a syntax - error. The second one will return V when an error happens. - - - Modules which are loaded with REQUIRE, but which belong to ECL, are now - registered with ASDF and can be used in dependencies. - -* Bugs fixed: - - - SI:GET-LIBRARY-PATHNAME did not work properly in Windows. - - - STEP did not work properly because the bytecompiler introduced an extra - opcode after STEPCALL. - - - --enable-slow-config works again. - - - EXT:CHDIR got broken when using Unicode. + - The previous change also implies that ECL must do all bignum computations + using GMP-allocated numbers that are then automatically freed. More + precisely, this is done using big_register[0-2]_get() and + big_register_normalize() everywhere and operating destructively on those + numbers. These functions have been made aware of the fact that GMP may + use other allocation routines and always call mpz_clear() to free memory. ;;; Local Variables: *** ;;; mode:text *** diff --git a/src/c/big.d b/src/c/big.d index 297f02d6e..ce4c53d12 100644 --- a/src/c/big.d +++ b/src/c/big.d @@ -39,54 +39,60 @@ cl_object big_register0_get(void) { - cl_env.big_register[0]->big.big_size = 0; - return cl_env.big_register[0]; + cl_object output = cl_env.big_register[0]; + output->big.big_limbs = cl_env.big_register_limbs[0]; + output->big.big_size = 0; + output->big.big_dim = BIGNUM_REGISTER_SIZE; + return output; } cl_object big_register1_get(void) { - cl_env.big_register[1]->big.big_size = 0; - return cl_env.big_register[1]; + cl_object output = cl_env.big_register[1]; + output->big.big_limbs = cl_env.big_register_limbs[1]; + output->big.big_size = 0; + output->big.big_dim = BIGNUM_REGISTER_SIZE; + return output; } cl_object big_register2_get(void) { - cl_env.big_register[2]->big.big_size = 0; - return cl_env.big_register[2]; + cl_object output = cl_env.big_register[2]; + output->big.big_limbs = cl_env.big_register_limbs[2]; + output->big.big_size = 0; + output->big.big_dim = BIGNUM_REGISTER_SIZE; + return output; } void big_register_free(cl_object x) { - /* FIXME! Is this thread safe? */ - if (x == cl_env.big_register[0]) - x->big.big_limbs = cl_env.big_register_limbs[0]; - else if (x == cl_env.big_register[1]) - x->big.big_limbs = cl_env.big_register_limbs[1]; - else if (x == cl_env.big_register[2]) - x->big.big_limbs = cl_env.big_register_limbs[2]; - else - ecl_internal_error("big_register_free: unknown register"); - x->big.big_size = 0; - x->big.big_dim = BIGNUM_REGISTER_SIZE; + /* We only need to free the integer when it has been reallocated */ + if (x->big.big_dim > BIGNUM_REGISTER_SIZE) { + mpz_clear(x->big.big_num); + } +} + +cl_object +big_copy(cl_object old) +{ + cl_object new_big = ecl_alloc_object(t_bignum); + cl_index dim, bytes; + new_big->big.big_size = old->big.big_size; + new_big->big.big_dim = dim = old->big.big_dim; + bytes = dim * sizeof(mp_limb_t); + new_big->big.big_limbs = ecl_alloc_atomic(bytes); + memcpy(new_big->big.big_limbs, old->big.big_limbs, bytes); + return new_big; } cl_object big_register_copy(cl_object old) { - cl_object new_big = ecl_alloc_object(t_bignum); - if (old->big.big_dim > BIGNUM_REGISTER_SIZE) { - /* The object already has suffered a mpz_realloc() so - we can use the pointer */ - new_big->big = old->big; - big_register_free(old); - } else { - /* As the bignum points to the cl_env.big_register_limbs[] area - we must duplicate its contents. */ - mpz_init_set(new_big->big.big_num,old->big.big_num); - } + cl_object new_big = big_copy(old); + big_register_free(old); return new_big; } @@ -94,62 +100,26 @@ cl_object big_register_normalize(cl_object x) { int s = x->big.big_size; - mp_limb_t y; if (s == 0) - return(MAKE_FIXNUM(0)); - y = x->big.big_limbs[0]; + return(MAKE_FIXNUM(0)); if (s == 1) { - if (y <= MOST_POSITIVE_FIXNUM) - return(MAKE_FIXNUM(y)); + mp_limb_t y = x->big.big_limbs[0]; + if (y <= MOST_POSITIVE_FIXNUM) + return MAKE_FIXNUM(y); } else if (s == -1) { - if (y <= -MOST_NEGATIVE_FIXNUM) - return(MAKE_FIXNUM(-y)); + mp_limb_t y = x->big.big_limbs[0]; + if (y <= -MOST_NEGATIVE_FIXNUM) + return MAKE_FIXNUM(-y); } return big_register_copy(x); } -/* - * Different from mpz_init since we initialize with NULL limbs - */ - -static cl_object -big_alloc(int size) -{ - volatile cl_object x = ecl_alloc_object(t_bignum); - if (size <= 0) - ecl_internal_error("negative or zero size for bignum in big_alloc"); - x->big.big_dim = size; - x->big.big_size = 0; - x->big.big_limbs = (mp_limb_t *)ecl_alloc_atomic_align(size * sizeof(mp_limb_t), sizeof(mp_limb_t)); - return(x); -} - cl_object bignum1(cl_fixnum val) { - volatile cl_object z = ecl_alloc_object(t_bignum); - mpz_init_set_si(z->big.big_num, val); - return(z); -} - -cl_object -bignum2(mp_limb_t hi, mp_limb_t lo) -{ - cl_object z; - - z = big_alloc(2); - z->big.big_size = 2; - z->big.big_limbs[0] = lo; - z->big.big_limbs[1] = hi; - return(z); -} - -cl_object -big_copy(cl_object x) -{ - volatile cl_object y = ecl_alloc_object(t_bignum); - mpz_init_set(y->big.big_num, x->big.big_num); - return(y); + cl_object aux = big_register0_get(); + mpz_init_set_si(aux->big.big_num, val); + return big_register_copy(aux); } /* @@ -176,88 +146,6 @@ big_copy(cl_object x) #define big_compare(x, y) mpz_cmp(x->big.big_num, y->big.big_num) */ -/* - big_complement(x) destructively takes - the complement of bignum x. - -#define big_complement(x) mpz_neg(x->big.big_num, x->big.num); -*/ - -/* - big_minus(x) returns the complement of bignum x. -*/ -cl_object -big_minus(cl_object x) -{ - volatile cl_object y = big_copy(x); - mpz_neg(y->big.big_num, y->big.big_num); - return y; -} - -/* - big_add_ui(x, i) destructively adds non-negative int i - to bignum x. - I should be non-negative. - - mpz_add_ui(x->big.big_num, x->big.big_num, i) -*/ - -/* - big_sub_ui(x, i) destructively subtracts non-negative int i - from bignum x. - I should be non-negative. - - mpz_sub_ui(x->big.big_num, x->big.big_num, i) -*/ - -/* - big_mul_ui(x, i) destructively multiplies non-negative bignum x - by non-negative int i. - I should be non-negative. - X should be non-negative. - - mpn_mul(&x->big.big_limbs, &x->big.big_limbs, x->big.big_size, &i, 1) -*/ - -/* - big_div_ui(x, i) destructively divides non-negative bignum x - by positive int i. - X will hold the remainder of the division. - div_int_big(i, x) returns the remainder of the division. - I should be positive. - X should be non-negative. - - mp_limb_t q[x->big.big_size]; - mpn_div(q, &x->big.big_limbs, &x->big.big_size, &i, 1), x -*/ - -/* - big_plus(x, y) returns the sum of bignum x and bignum y. - X and y may be any bignum. -*/ -cl_object -big_plus(cl_object x, cl_object y) -{ - volatile cl_object z = big_register0_get(); - mpz_add(z->big.big_num, x->big.big_num, y->big.big_num); - return(big_register_copy(z)); -} - -cl_object -big_normalize(cl_object x) -{ - int s = x->big.big_size; - mp_limb_t y; - if (s == 0) - return(MAKE_FIXNUM(0)); - y = x->big.big_limbs[0]; - if (s == 1 && y <= MOST_POSITIVE_FIXNUM) - return(MAKE_FIXNUM(y)); - if (s == -1 && y <= -MOST_NEGATIVE_FIXNUM) - return(MAKE_FIXNUM(-y)); - return(x); -} - static void * mp_alloc(size_t size) { @@ -286,7 +174,6 @@ void init_big_registers(cl_env_ptr env) int i; for (i = 0; i < 3; i++) { env->big_register[i] = ecl_alloc_object(t_bignum); - big_register_free(env->big_register[i]); } } @@ -294,5 +181,6 @@ void init_big(cl_env_ptr env) { init_big_registers(env); - mp_set_memory_functions(mp_alloc, mp_realloc, mp_free); + if (ecl_get_option(ECL_OPT_SET_GMP_MEMORY_FUNCTIONS)) + mp_set_memory_functions(mp_alloc, mp_realloc, mp_free); } diff --git a/src/c/big_ll.d b/src/c/big_ll.d index e8aeef6af..d0c75c950 100644 --- a/src/c/big_ll.d +++ b/src/c/big_ll.d @@ -68,7 +68,6 @@ big_alloc(int size) return x; } - cl_object bignum1(cl_fixnum val) { @@ -95,35 +94,6 @@ big_copy(cl_object x) return(y); } -/* - big_minus(x) returns the complement of bignum x. -*/ -cl_object -big_minus(cl_object x) -{ - volatile cl_object y = big_copy(x); - y->big.big_num = -x->big.big_num; - return y; -} - -cl_object -big_plus(cl_object x, cl_object y) -{ - volatile cl_object z = big_register0_get(); - z->big.big_num = x->big.big_num + y->big.big_num; - return(big_register_copy(z)); -} - -cl_object -big_normalize(cl_object x) -{ - if (x->big.big_num == 0ll) - return(MAKE_FIXNUM(0)); - if (x->big.big_num <= MOST_POSITIVE_FIXNUM && x->big.big_num >= MOST_NEGATIVE_FIXNUM) - return(MAKE_FIXNUM(x->big.big_num)); - return(x); -} - int big_num_t_sgn(big_num_t x) { return ( x == (big_num_t)0 ) ? 0 : (x < (big_num_t)0) ? -1 : 1; diff --git a/src/c/main.d b/src/c/main.d index 35b98018f..3e95d82d0 100644 --- a/src/c/main.d +++ b/src/c/main.d @@ -81,6 +81,7 @@ static cl_fixnum option_values[ECL_OPT_LIMIT+1] = { 256*1024*1024, /* ECL_OPT_HEAP_SIZE */ 1024*1024, /* ECL_OPT_HEAP_SAFETY_AREA */ 0, /* ECL_OPT_THREAD_INTERRUPT_SIGNAL */ + 1, /* ECL_OPT_SET_GMP_MEMORY_FUNCTIONS */ 0}; #if !defined(GBC_BOEHM) @@ -588,6 +589,8 @@ cl_boot(int argc, char **argv) cl_core.gentemp_prefix = make_constant_base_string("T"); cl_core.gentemp_counter = MAKE_FIXNUM(0); + init_number(); + ECL_SET(@'si::c-int-max', ecl_make_integer(INT_MAX)); ECL_SET(@'si::c-int-min', ecl_make_integer(INT_MIN)); ECL_SET(@'si::c-long-max', ecl_make_integer(LONG_MAX)); @@ -595,7 +598,6 @@ cl_boot(int argc, char **argv) ECL_SET(@'si::c-uint-max', ecl_make_unsigned_integer(UINT_MAX)); ECL_SET(@'si::c-ulong-max', ecl_make_unsigned_integer(ULONG_MAX)); - init_number(); init_unixtime(); #ifdef ECL_THREADS diff --git a/src/c/num_arith.d b/src/c/num_arith.d index 0bcefaf78..f0c9d3979 100644 --- a/src/c/num_arith.d +++ b/src/c/num_arith.d @@ -15,6 +15,7 @@ */ #include +#include #include #pragma fenv_access on @@ -34,13 +35,8 @@ cl_object fixnum_times(cl_fixnum i, cl_fixnum j) { cl_object x = big_register0_get(); - -#ifdef WITH_GMP - mpz_set_si(x->big.big_num, i); - mpz_mul_si(x->big.big_num, x->big.big_num, (long int)j); -#else /* WITH_GMP */ - x->big.big_num = (big_num_t)i * (big_num_t)j; -#endif /* WITH_GMP */ + big_set_si(x, i); + big_mul_si(x, x, j); return big_register_normalize(x); } @@ -50,17 +46,14 @@ big_times_fix(cl_object b, cl_fixnum i) cl_object z; if (i == 1) - return(b); - if (i == -1) - return(big_minus(b)); + return b; z = big_register0_get(); -#ifdef WITH_GMP - mpz_mul_si(z->big.big_num, b->big.big_num, (long int)i); -#else /* WITH_GMP */ - z->big.big_num = b->big.big_num * i; -#endif /* WITH_GMP */ - z = big_register_normalize(z); - return(z); + if (i == -1) { + big_complement(z, b); + } else { + big_mul_si(z, b, i); + } + return big_register_normalize(z); } static cl_object @@ -68,13 +61,8 @@ big_times_big(cl_object x, cl_object y) { cl_object z; z = big_register0_get(); -#ifdef WITH_GMP - mpz_mul(z->big.big_num, x->big.big_num, y->big.big_num); -#else /* WITH_GMP */ - z->big.big_num = x->big.big_num * y->big.big_num; -#endif /* WITH_GMP */ - z = big_register_normalize(z); - return(z); + big_mul(z, x, y); + return big_register_normalize(z); } cl_object @@ -91,8 +79,7 @@ ecl_times(cl_object x, cl_object y) return big_times_fix(y, fix(x)); case t_ratio: z = ecl_times(x, y->ratio.num); - z = ecl_make_ratio(z, y->ratio.den); - return(z); + return ecl_make_ratio(z, y->ratio.den); #ifdef ECL_SHORT_FLOAT case t_shortfloat: return make_shortfloat(fix(x) * ecl_short_float(y)); @@ -118,8 +105,7 @@ ecl_times(cl_object x, cl_object y) return big_times_big(x, y); case t_ratio: z = ecl_times(x, y->ratio.num); - z = ecl_make_ratio(z, y->ratio.den); - return(z); + return ecl_make_ratio(z, y->ratio.den); #ifdef ECL_SHORT_FLOAT case t_shortfloat: return make_shortfloat(ecl_to_double(x) * ecl_short_float(y)); @@ -142,13 +128,11 @@ ecl_times(cl_object x, cl_object y) case t_fixnum: case t_bignum: z = ecl_times(x->ratio.num, y); - z = ecl_make_ratio(z, x->ratio.den); - return(z); + return ecl_make_ratio(z, x->ratio.den); case t_ratio: z = ecl_times(x->ratio.num,y->ratio.num); z1 = ecl_times(x->ratio.den,y->ratio.den); - z = ecl_make_ratio(z, z1); - return(z); + return ecl_make_ratio(z, z1); #ifdef ECL_SHORT_FLOAT case t_shortfloat: return make_shortfloat(ecl_to_double(x) * ecl_short_float(y)); @@ -240,7 +224,7 @@ ecl_times(cl_object x, cl_object y) case t_complex: { COMPLEX: /* INV: x is real, y is complex */ return ecl_make_complex(ecl_times(x, y->complex.real), - ecl_times(x, y->complex.imag)); + ecl_times(x, y->complex.imag)); } default: FEtype_error_number(y); @@ -285,7 +269,7 @@ ecl_times(cl_object x, cl_object y) z12 = ecl_times(x->complex.imag, y->complex.imag); z21 = ecl_times(x->complex.imag, y->complex.real); z22 = ecl_times(x->complex.real, y->complex.imag); - return(ecl_make_complex(ecl_minus(z11, z12), ecl_plus(z21, z22))); + return ecl_make_complex(ecl_minus(z11, z12), ecl_plus(z21, z22)); } default: FEtype_error_number(x); @@ -322,14 +306,10 @@ ecl_plus(cl_object x, cl_object y) if ((i = fix(x)) == 0) return(y); z = big_register0_get(); -#ifdef WITH_GMP if (i > 0) - mpz_add_ui(z->big.big_num, y->big.big_num, (unsigned long)i); + big_add_ui(z, y, i); else - mpz_sub_ui(z->big.big_num, y->big.big_num, (unsigned long)(-i)); -#else /* WITH_GMP */ - z->big.big_num = y->big.big_num + i; -#endif /* WITH_GMP */ + big_sub_ui(z, y, -i); z = big_register_normalize(z); return(z); case t_ratio: @@ -362,25 +342,19 @@ ecl_plus(cl_object x, cl_object y) if ((j = fix(y)) == 0) return(x); z = big_register0_get(); -#ifdef WITH_GMP if (j > 0) - mpz_add_ui(z->big.big_num, x->big.big_num, (unsigned long)j); + big_add_ui(z, x, j); else - mpz_sub_ui(z->big.big_num, x->big.big_num, (unsigned long)(-j)); -#else /* WITH_GMP */ - z->big.big_num = x->big.big_num + j; -#endif /* WITH_GMP */ - z = big_register_normalize(z); - return(z); + big_sub_ui(z, x, (-j)); + return big_register_normalize(z); case t_bignum: - z = big_plus(x, y); - z = big_normalize(z); - return(z); + z = big_register0_get(); + big_add(z, x, y); + return big_register_normalize(z); case t_ratio: z = ecl_times(x, y->ratio.den); z = ecl_plus(z, y->ratio.num); - z = ecl_make_ratio(z, y->ratio.den); - return(z); + return ecl_make_ratio(z, y->ratio.den); #ifdef ECL_SHORT_FLOAT case t_shortfloat: return make_shortfloat(ecl_to_double(x) + ecl_short_float(y)); @@ -404,15 +378,13 @@ ecl_plus(cl_object x, cl_object y) case t_bignum: z = ecl_times(x->ratio.den, y); z = ecl_plus(x->ratio.num, z); - z = ecl_make_ratio(z, x->ratio.den); - return(z); + return ecl_make_ratio(z, x->ratio.den); case t_ratio: z1 = ecl_times(x->ratio.num,y->ratio.den); z = ecl_times(x->ratio.den,y->ratio.num); z = ecl_plus(z1, z); z1 = ecl_times(x->ratio.den,y->ratio.den); - z = ecl_make_ratio(z, z1); - return(z); + return ecl_make_ratio(z, z1); #ifdef ECL_SHORT_FLOAT case t_shortfloat: return make_shortfloat(ecl_to_double(x) + ecl_short_float(y)); @@ -534,8 +506,7 @@ ecl_plus(cl_object x, cl_object y) } z = ecl_plus(x->complex.real, y->complex.real); z1 = ecl_plus(x->complex.imag, y->complex.imag); - z = ecl_make_complex(z, z1); - return(z); + return ecl_make_complex(z, z1); default: FEtype_error_number(x); } @@ -565,28 +536,22 @@ ecl_minus(cl_object x, cl_object y) case t_fixnum: if ((k = fix(x) - fix(y)) >= MOST_NEGATIVE_FIXNUM && k <= MOST_POSITIVE_FIXNUM) - return(MAKE_FIXNUM(k)); + return MAKE_FIXNUM(k); else - return(bignum1(k)); + return bignum1(k); case t_bignum: z = big_register0_get(); i = fix(x); -#ifdef WITH_GMP if (i > 0) - mpz_sub_ui(z->big.big_num, y->big.big_num, (unsigned long)i); + big_sub_ui(z, y, i); else - mpz_add_ui(z->big.big_num, y->big.big_num, (unsigned long)(-i)); -#else /* WITH_GMP */ - z->big.big_num = (big_num_t)i - y->big.big_num; -#endif /* WITH_GMP */ - big_complement(z); - z = big_register_normalize(z); - return(z); + big_add_ui(z, y, -i); + big_complement(z, z); + return big_register_normalize(z); case t_ratio: z = ecl_times(x, y->ratio.den); z = ecl_minus(z, y->ratio.num); - z = ecl_make_ratio(z, y->ratio.den); - return(z); + return ecl_make_ratio(z, y->ratio.den); #ifdef ECL_SHORT_FLOAT case t_shortfloat: return make_shortfloat(fix(x) - ecl_short_float(y)); @@ -610,26 +575,19 @@ ecl_minus(cl_object x, cl_object y) if ((j = fix(y)) == 0) return(x); z = big_register0_get(); -#ifdef WITH_GMP if (j > 0) - mpz_sub_ui(z->big.big_num, x->big.big_num, (unsigned long)j); + big_sub_ui(z, x, j); else - mpz_add_ui(z->big.big_num, x->big.big_num, (unsigned long)(-j)); -#else /* WITH_GMP */ - z->big.big_num = x->big.big_num - j; -#endif /* WITH_GMP */ - z = big_register_normalize(z); - return(z); + big_add_ui(z, x, -j); + return big_register_normalize(z); case t_bignum: - y = big_minus(y); - z = big_plus(x, y); - z = big_normalize(z); - return(z); + z = big_register0_get(); + big_sub(z, x, y); + return big_register_normalize(z); case t_ratio: z = ecl_times(x, y->ratio.den); z = ecl_minus(z, y->ratio.num); - z = ecl_make_ratio(z, y->ratio.den); - return(z); + return ecl_make_ratio(z, y->ratio.den); #ifdef ECL_SHORT_FLOAT case t_shortfloat: return make_shortfloat(ecl_to_double(x) - ecl_short_float(y)); @@ -653,15 +611,13 @@ ecl_minus(cl_object x, cl_object y) case t_bignum: z = ecl_times(x->ratio.den, y); z = ecl_minus(x->ratio.num, z); - z = ecl_make_ratio(z, x->ratio.den); - return(z); + return ecl_make_ratio(z, x->ratio.den); case t_ratio: z = ecl_times(x->ratio.num,y->ratio.den); z1 = ecl_times(x->ratio.den,y->ratio.num); z = ecl_minus(z, z1); z1 = ecl_times(x->ratio.den,y->ratio.den); - z = ecl_make_ratio(z, z1); - return(z); + return ecl_make_ratio(z, z1); #ifdef ECL_SHORT_FLOAT case t_shortfloat: return make_shortfloat(ecl_to_double(x) - ecl_short_float(y)); @@ -777,7 +733,7 @@ ecl_minus(cl_object x, cl_object y) #endif COMPLEX: return ecl_make_complex(ecl_minus(x, y->complex.real), - ecl_negate(y->complex.imag)); + ecl_negate(y->complex.imag)); case t_complex: if (type_of(y) != t_complex) { z = ecl_minus(x->complex.real, y); @@ -798,7 +754,7 @@ cl_conjugate(cl_object c) switch (type_of(c)) { case t_complex: c = ecl_make_complex(c->complex.real, - ecl_negate(c->complex.imag)); + ecl_negate(c->complex.imag)); case t_fixnum: case t_bignum: case t_ratio: @@ -833,11 +789,7 @@ ecl_negate(cl_object x) } case t_bignum: z = big_register0_get(); -#ifdef WITH_GMP - mpz_neg(z->big.big_num, x->big.big_num); -#else /* WITH_GMP */ - z->big.big_num = -(x->big.big_num); -#endif /* WITH_GMP */ + big_complement(z, x); return big_register_normalize(z); case t_ratio: @@ -845,7 +797,7 @@ ecl_negate(cl_object x) z = ecl_alloc_object(t_ratio); z->ratio.num = z1; z->ratio.den = x->ratio.den; - return(z); + return z; #ifdef ECL_SHORT_FLOAT case t_shortfloat: @@ -854,12 +806,12 @@ ecl_negate(cl_object x) case t_singlefloat: z = ecl_alloc_object(t_singlefloat); sf(z) = -sf(x); - return(z); + return z; case t_doublefloat: z = ecl_alloc_object(t_doublefloat); df(z) = -df(x); - return(z); + return z; #ifdef ECL_LONG_FLOAT case t_longfloat: return ecl_make_longfloat(-ecl_long_float(x)); @@ -867,9 +819,7 @@ ecl_negate(cl_object x) case t_complex: z = ecl_negate(x->complex.real); z1 = ecl_negate(x->complex.imag); - z = ecl_make_complex(z, z1); - return(z); - + return ecl_make_complex(z, z1); default: FEtype_error_number(x); } @@ -905,12 +855,10 @@ ecl_divide(cl_object x, cl_object y) x = ecl_negate(x); y = ecl_negate(y); } - z = ecl_make_ratio(x, y); - return(z); + return ecl_make_ratio(x, y); case t_ratio: z = ecl_times(x, y->ratio.den); - z = ecl_make_ratio(z, y->ratio.num); - return(z); + return ecl_make_ratio(z, y->ratio.num); #ifdef ECL_SHORT_FLAOT case t_shortfloat: return make_shortfloat(ecl_to_double(x) / ecl_short_float(y)); @@ -935,13 +883,11 @@ ecl_divide(cl_object x, cl_object y) FEdivision_by_zero(x, y); case t_bignum: z = ecl_times(x->ratio.den, y); - z = ecl_make_ratio(x->ratio.num, z); - return(z); + return ecl_make_ratio(x->ratio.num, z); case t_ratio: z = ecl_times(x->ratio.num,y->ratio.den); z1 = ecl_times(x->ratio.den,y->ratio.num); - z = ecl_make_ratio(z, z1); - return(z); + return ecl_make_ratio(z, z1); #ifdef ECL_SHORT_FLOAT case t_shortfloat: return make_shortfloat(ecl_to_double(x) / ecl_short_float(y)); @@ -1101,14 +1047,10 @@ ecl_integer_divide(cl_object x, cl_object y) * MOST_NEGATIVE_FIXNUM = - MOST_POSITIVE_FIXNUM. */ if (-MOST_NEGATIVE_FIXNUM > MOST_POSITIVE_FIXNUM) { -#ifdef WITH_GMP - if (mpz_cmp_si(y->big.big_num, -fix(x))) + if (big_cmp_si(y, -fix(x))) return MAKE_FIXNUM(0); else return MAKE_FIXNUM(-1); -#else /* WITH_GMP */ - return y->big.big_num != -fix(x) ? MAKE_FIXNUM(0) : MAKE_FIXNUM(-1); -#endif /* WITH_GMP */ } else { return MAKE_FIXNUM(0); } @@ -1118,20 +1060,12 @@ ecl_integer_divide(cl_object x, cl_object y) if (tx == t_bignum) { cl_object q = big_register0_get(); if (ty == t_bignum) { -#ifdef WITH_GMP - mpz_tdiv_q(q->big.big_num, x->big.big_num, y->big.big_num); -#else /* WITH_GMP */ - q->big.big_num = x->big.big_num / y->big.big_num; -#endif /* WITH_GMP */ + big_tdiv_q(q, x, y); } else if (ty == t_fixnum) { long j = fix(y); -#ifdef WITH_GMP - mpz_tdiv_q_ui(q->big.big_num, x->big.big_num, (unsigned long)labs(j)); + big_tdiv_q_ui(q, x, labs(j)); if (j < 0) - mpz_neg(q->big.big_num, q->big.big_num); -#else /* WITH_GMP */ - q->big.big_num = x->big.big_num / j; -#endif /* WITH_GMP */ + big_complement(q, q); } else { FEtype_error_integer(y); } @@ -1217,8 +1151,7 @@ ecl_gcd(cl_object x, cl_object y) } } #endif /* WITH_GMP */ - gcd = big_register_normalize(gcd); - return(gcd); + return big_register_normalize(gcd); default: FEtype_error_integer(y); } @@ -1249,8 +1182,7 @@ ecl_one_plus(cl_object x) case t_ratio: z = ecl_plus(x->ratio.num, x->ratio.den); - z = ecl_make_ratio(z, x->ratio.den); - return(z); + return ecl_make_ratio(z, x->ratio.den); #ifdef ECL_SHORT_FLOAT case t_shortfloat: @@ -1273,8 +1205,7 @@ ecl_one_plus(cl_object x) case t_complex: z = ecl_one_plus(x->complex.real); - z = ecl_make_complex(z, x->complex.imag); - return(z); + return ecl_make_complex(z, x->complex.imag); default: FEtype_error_number(x); @@ -1301,12 +1232,11 @@ ecl_one_minus(cl_object x) return (cl_object)((cl_fixnum)x - ((cl_fixnum)MAKE_FIXNUM(1) - FIXNUM_TAG)); case t_bignum: - return(ecl_minus(x, MAKE_FIXNUM(1))); + return ecl_minus(x, MAKE_FIXNUM(1)); case t_ratio: z = ecl_minus(x->ratio.num, x->ratio.den); - z = ecl_make_ratio(z, x->ratio.den); - return(z); + return ecl_make_ratio(z, x->ratio.den); #ifdef ECL_SHORT_FLOAT case t_shortfloat: @@ -1330,8 +1260,7 @@ ecl_one_minus(cl_object x) case t_complex: z = ecl_one_minus(x->complex.real); - z = ecl_make_complex(z, x->complex.imag); - return(z); + return ecl_make_complex(z, x->complex.imag); default: FEtype_error_real(x); diff --git a/src/c/num_log.d b/src/c/num_log.d index b224f8017..bcf5cfdce 100644 --- a/src/c/num_log.d +++ b/src/c/num_log.d @@ -328,7 +328,6 @@ static bignum_bit_operator bignum_operations[16] = { static cl_object log_op(cl_narg narg, int op, cl_va_list ARGS) { -#if 1 cl_object x, y; /* FIXME! This can be optimized */ x = cl_va_arg(ARGS); @@ -341,66 +340,6 @@ log_op(cl_narg narg, int op, cl_va_list ARGS) } while (--narg); } return x; -#else - cl_object x, numi; - bit_operator fix_log_op; - bignum_bit_operator big_log_op; - int i = 1; - cl_fixnum j; - - x = cl_va_arg(ARGS); - switch (type_of(x)) { - case t_fixnum: - break; - case t_bignum: - x = big_copy(x); /* since big_log_op clobbers it */ - goto BIG_OP; - default: - FEtype_error_integer(x); - } - if (narg == 1) - return x; - j = fix(x); - fix_log_op = fixnum_operations[op]; - for (; i < narg; i++) { - numi = cl_va_arg(ARGS); - switch (type_of(numi)) { - case t_fixnum: - j = (*fix_log_op)(j, fix(numi)); - break; - case t_bignum: - big_log_op = bignum_operations[op]; - x = bignum1(j); - goto BIG_OP2; - default: - FEtype_error_integer(numi); - } - } - return(MAKE_FIXNUM(j)); - -BIG_OP: - if (narg == 1) - return x; - big_log_op = bignum_operations[op]; - for (; i < narg; i++) { - numi = cl_va_arg(ARGS); - switch (type_of(numi)) { - case t_fixnum: { - cl_object z = big_register1_get(); - mpz_set_si(z->big.big_num, fix(numi)); - (*big_log_op)(x, z); - big_register_free(z); - break; - } - case t_bignum: BIG_OP2: - (*big_log_op)(x, numi); - break; - default: - FEtype_error_integer(numi); - } - } - return(big_normalize(x)); -#endif } cl_object @@ -410,49 +349,42 @@ ecl_boole(int op, cl_object x, cl_object y) case t_fixnum: switch (type_of(y)) { case t_fixnum: { - cl_fixnum (*fix_log_op)(cl_fixnum, cl_fixnum); - fix_log_op = fixnum_operations[op]; - return MAKE_FIXNUM((*fix_log_op)(fix(x), fix(y))); + cl_fixnum z = fixnum_operations[op](fix(x), fix(y)); + return MAKE_FIXNUM(z); } case t_bignum: { - void (*big_log_op)(cl_object, cl_object); - big_log_op = bignum_operations[op]; - x = bignum1(fix(x)); - (*big_log_op)(x, y); - break; + cl_object x_copy = big_register0_get(); + big_set_si(x_copy, fix(x)); + bignum_operations[op](x_copy, y); + return big_register_normalize(x_copy); } default: FEtype_error_integer(y); } break; case t_bignum: { - void (*big_log_op)(cl_object, cl_object); - big_log_op = bignum_operations[op]; - x = big_copy(x); + cl_object x_copy = big_register0_get(); + big_set(x_copy, x); switch (type_of(y)) { case t_fixnum: { cl_object z = big_register1_get(); -#ifdef WITH_GMP - mpz_set_si(z->big.big_num, fix(y)); -#else /* WITH_GMP */ - z->big.big_num = fix(y); -#endif /* WITH_GMP */ - (*big_log_op)(x, z); + big_set_si(z,fix(y)); + bignum_operations[op](x_copy, z); big_register_free(z); break; } case t_bignum: - (*big_log_op)(x,y); + bignum_operations[op](x_copy, y); break; default: FEtype_error_integer(y); } - break; + return big_register_normalize(x_copy); } default: FEtype_error_integer(x); } - return big_normalize(x); + return x; } cl_object @@ -546,7 +478,7 @@ ecl_ash(cl_object x, cl_fixnum w) y->big.big_num <<= w; #endif /* WITH_GMP */ } - return(big_register_normalize(y)); + return big_register_normalize(y); } int diff --git a/src/c/number.d b/src/c/number.d index cdd24ef42..df157a7bb 100644 --- a/src/c/number.d +++ b/src/c/number.d @@ -128,13 +128,9 @@ cl_object ecl_make_integer(cl_fixnum l) { if (l > MOST_POSITIVE_FIXNUM || l < MOST_NEGATIVE_FIXNUM) { - cl_object z = ecl_alloc_object(t_bignum); -#ifdef WITH_GMP - mpz_init_set_si(z->big.big_num, l); -#else /* WITH_GMP */ - z->big.big_num = l; -#endif /* WITH_GMP */ - return z; + cl_object z = big_register0_get(); + big_set_si(z, l); + return big_register_copy(z); } return MAKE_FIXNUM(l); } @@ -143,13 +139,9 @@ cl_object ecl_make_unsigned_integer(cl_index l) { if (l > MOST_POSITIVE_FIXNUM) { - cl_object z = ecl_alloc_object(t_bignum); -#ifdef WITH_GMP - mpz_init_set_ui(z->big.big_num, l); -#else /* WITH_GMP */ - z->big.big_num = l; -#endif /* WITH_GMP */ - return z; + cl_object z = big_register0_get(); + big_set_ui(z, l); + return big_register_copy(z); } return MAKE_FIXNUM(l); } @@ -890,13 +882,9 @@ double_to_integer(double d) if (d <= MOST_POSITIVE_FIXNUM && d >= MOST_NEGATIVE_FIXNUM) return MAKE_FIXNUM((cl_fixnum)d); else { - cl_object x = big_register0_get(); -#ifdef WITH_GMP - mpz_set_d(x->big.big_num, d); -#else /* WITH_GMP */ - x->big.big_num = (big_num_t)d; -#endif /* WITH_GMP */ - return big_register_copy(x); + cl_object z = big_register0_get(); + big_set_d(z, d); + return big_register_copy(z); } } @@ -906,13 +894,9 @@ float_to_integer(float d) if (d <= MOST_POSITIVE_FIXNUM && d >= MOST_NEGATIVE_FIXNUM) return MAKE_FIXNUM((cl_fixnum)d); else { - cl_object x = big_register0_get(); -#ifdef WITH_GMP - mpz_set_d(x->big.big_num, d); -#else /* WITH_GMP */ - x->big.big_num = (big_num_t)d; -#endif /* WITH_GMP */ - return big_register_copy(x); + cl_object z = big_register0_get(); + big_set_d(z, d); + return big_register_copy(z); } } diff --git a/src/c/read.d b/src/c/read.d index 675dd084b..f935437ff 100644 --- a/src/c/read.d +++ b/src/c/read.d @@ -604,11 +604,11 @@ ecl_parse_integer(cl_object str, cl_index start, cl_index end, if (d < 0) { break; } - big_mul_ui(integer_part, radix); - big_add_ui(integer_part, d); + big_mul_ui(integer_part, integer_part, radix); + big_add_ui(integer_part, integer_part, d); } if (sign < 0) { - big_complement(integer_part); + big_complement(integer_part, integer_part); } output = big_register_normalize(integer_part); *ep = i; diff --git a/src/h/external.h b/src/h/external.h index e2b5fc701..0ab69fab8 100644 --- a/src/h/external.h +++ b/src/h/external.h @@ -369,9 +369,6 @@ extern ECL_API cl_object bignum2(cl_fixnum hi, cl_fixnum lo); #endif /* WITH_GMP */ extern ECL_API cl_object big_set_fixnum(cl_object x, cl_object fix); extern ECL_API cl_object big_copy(cl_object x); -extern ECL_API cl_object big_minus(cl_object x); -extern ECL_API cl_object big_plus(cl_object x, cl_object y); -extern ECL_API cl_object big_normalize(cl_object x); extern ECL_API double big_to_double(cl_object x); @@ -911,6 +908,7 @@ typedef enum { ECL_OPT_HEAP_SIZE, ECL_OPT_HEAP_SAFETY_AREA, ECL_OPT_THREAD_INTERRUPT_SIGNAL, + ECL_OPT_SET_GMP_MEMORY_FUNCTIONS, ECL_OPT_LIMIT } ecl_option; diff --git a/src/h/number.h b/src/h/number.h index e2dcfddec..267dee1e4 100644 --- a/src/h/number.h +++ b/src/h/number.h @@ -14,32 +14,52 @@ */ #ifdef WITH_GMP +#define big_set(x,y) mpz_set((x)->big.big_num,(y)->big.big_num) #define big_odd_p(x) ((mpz_get_ui(x->big.big_num) & 1) != 0) #define big_even_p(x) ((mpz_get_ui(x->big.big_num) & 1) == 0) #define big_zerop(x) ((x)->big.big_size == 0) #define big_sign(x) ((x)->big.big_size) #define big_compare(x, y) mpz_cmp(x->big.big_num, y->big.big_num) -#define big_complement(x) mpz_neg(x->big.big_num, x->big.big_num) -#define big_add_ui(x, i) mpz_add_ui(x->big.big_num, x->big.big_num, i) -#define big_mul_ui(x, i) mpz_mul_ui(x->big.big_num, x->big.big_num, i) +#define big_complement(z, x) mpz_neg((z)->big.big_num,(x)->big.big_num) +#define big_add(z, x, y) mpz_add((z)->big.big_num,(x)->big.big_num,(y)->big.big_num) +#define big_sub(z, x, y) mpz_sub((z)->big.big_num,(x)->big.big_num,(y)->big.big_num) +#define big_mul(z, x, y) mpz_mul((z)->big.big_num,(x)->big.big_num,(y)->big.big_num) +#define big_add_ui(z, x, i) mpz_add_ui(z->big.big_num, x->big.big_num, i) +#define big_sub_ui(z, x, i) mpz_sub_ui(z->big.big_num, x->big.big_num, i) +#define big_mul_ui(z, x, y) mpz_mul_ui((z)->big.big_num,(x)->big.big_num,(y)) +#define big_mul_si(z, x, y) mpz_mul_si((z)->big.big_num,(x)->big.big_num,(y)) #define big_set_ui(x, i) mpz_set_ui(x->big.big_num, (unsigned long int)i) -#define big_set_si(x, i) mpz_set_ui(x->big.big_num, (long int)i) +#define big_set_si(x, i) mpz_set_si(x->big.big_num, (long int)i) #define big_to_double(x) mpz_get_d(x->big.big_num) #define big_to_long(x) mpz_get_si(x->big.big_num) #define big_to_ulong(x) mpz_get_ui(x->big.big_num) +#define big_cmp_si(x,y) mpz_cmp_si((x)->big.big_num,(y)) +#define big_tdiv_q(q, x, y) mpz_tdiv_q((q)->big.big_num,(x)->big.big_num,(y)->big.big_num) +#define big_tdiv_q_ui(q, x, y) mpz_tdiv_q_ui((q)->big.big_num, (x)->big.big_num, (y)) +#define big_set_d(x, d) mpz_set_d((x)->big.big_num, (d)) #else /* WITH_GMP */ +#define big_set(x,y) ((x)->big.big_num = (y)->big.big_num) extern int big_num_t_sgn(big_num_t x); #define big_odd_p(x) ((int)((x)->big.big_num&1) != 0) #define big_even_p(x) ((int)((x)->big.big_num&1) == 0) #define big_zerop(x) ((x)->big.big_num == (big_num_t)0) #define big_sign(x) big_num_t_sgn((x)->big.big_num) #define big_compare(x,y) big_num_t_sgn((x)->big.big_num - (y)->big.big_num) -#define big_complement(x) ((x)->big.big_num = -((x)->big.big_num)) -#define big_add_ui(x, i) ((x)->big.big_num += (unsigned long)(i)) -#define big_mul_ui(x, i) ((x)->big.big_num *= (unsigned long)(i)) +#define big_complement(z, x) ((z)->big.big_num = -((x)->big.big_num)) +#define big_add(z, x, y) (z)->big.big_num = (x)->big.big_num+(y)->big.big_num +#define big_sub(z, x, y) (z)->big.big_num = (x)->big.big_num-(y)->big.big_num +#define big_mul(z, x, y) (z)->big.big_num = (x)->big.big_num*(y)->big.big_num +#define big_add_ui(z, x, y) ((z)->big.big_num = (x)->big.big_num+(unsigned long)(y)) +#define big_sub_ui(z, x, y) ((z)->big.big_num = (x)->big.big_num-(unsigned long)(y)) +#define big_mul_ui(z, x, y) ((x)->big.big_num = (x)->big.big_num*(unsigned long)(y)) +#define big_mul_si(z, x, y) (z)->big.big_num = (x)->big.big_num*(y) #define big_set_ui(x, i) ((x)->big.big_num = ((big_num_t)((unsigned long int)i))) #define big_set_si(x, i) ((x)->big.big_num = ((big_num_t)((long int)i))) #define big_to_double(x) ((double)((x)->big.big_num)) #define big_to_long(x) ((long int)((x)->big.big_num)) #define big_to_ulong(x) ((unsigned long int)((x)->big.big_num)) +#define big_cmp_si(x, y) ((x)->big.big_num!=(y)) +#define big_tdiv_q(q, x, y) ((q)->big.big_num = (x)->big.big_num / (y)->big.big_num) +#define big_tdiv_q_ui(q, x, y) ((q)->big.big_num = (x)->big.big_num / (y)) +#define big_set_d(x, d) ((x)->big.big_num = (big_num_t)(d)) #endif /* WITH_GMP */