From 51136f3ef42cddb30e8dc98c2a2947c3058c60e4 Mon Sep 17 00:00:00 2001 From: japhie Date: Mon, 19 Sep 2005 21:52:46 +0000 Subject: [PATCH] - Added possibility of configuring --without-gmp when cross-compiling to reduce memory usage when true bignums aren't needed (doesn't work for native compilation because compiler needs bignums). --- src/CHANGELOG | 4 + src/aclocal.m4 | 18 ++++ src/c/Makefile.in | 2 +- src/c/big_ll.d | 145 +++++++++++++++++++++++++++ src/c/gbc-new.d | 2 + src/c/gbc.d | 2 + src/c/hash.d | 4 + src/c/main.d | 9 +- src/c/num_arith.d | 67 ++++++++++++- src/c/num_co.d | 38 +++++++ src/c/num_log.d | 101 ++++++++++++++++++- src/c/number.d | 27 ++++- src/c/print.d | 37 +++++++ src/configure | 245 ++++++++++++++++++++++++++++++---------------- src/configure.in | 42 ++++---- src/h/config.h.in | 5 + src/h/ecl-cmp.h | 2 + src/h/ecl.h | 2 + src/h/external.h | 6 ++ src/h/number.h | 17 ++++ src/h/object.h | 17 ++++ 21 files changed, 685 insertions(+), 107 deletions(-) create mode 100644 src/c/big_ll.d diff --git a/src/CHANGELOG b/src/CHANGELOG index 7055457bd..88d21db31 100644 --- a/src/CHANGELOG +++ b/src/CHANGELOG @@ -29,6 +29,10 @@ ECL 0.9h - The code walker is no longer needed and has been removed from the core. It will be available in the contributed packages. + - Possibility of configure --without-gmp when cross-compiling (there are no + true bignums then, just long long int if possible; doesn't work with native + compilation because compiler needs true bignums). + * Visible changes: - The code for handling command line options has been redesigned. Now multiple diff --git a/src/aclocal.m4 b/src/aclocal.m4 index 4bb9f9b9d..6c0b8ee8d 100644 --- a/src/aclocal.m4 +++ b/src/aclocal.m4 @@ -1,4 +1,22 @@ dnl -*- autoconf -*- + +dnl -------------------------------------------------------------- +dnl http://autoconf-archive.cryp.to/ac_c_long_long_.html +dnl Provides a test for the existance of the long long int type and defines HAVE_LONG_LONG if it is found. +AC_DEFUN([AC_C_LONG_LONG], +[AC_CACHE_CHECK(for long long int, ac_cv_c_long_long, +[if test "$GCC" = yes; then + ac_cv_c_long_long=yes + else + AC_TRY_COMPILE(,[long long int i;], + ac_cv_c_long_long=yes, + ac_cv_c_long_long=no) + fi]) + if test $ac_cv_c_long_long = yes; then + AC_DEFINE(HAVE_LONG_LONG, 1, [compiler understands long long]) + fi +]) + dnl -------------------------------------------------------------- dnl Add *feature* for conditional compilation. AC_DEFUN([ECL_ADD_FEATURE], [ diff --git a/src/c/Makefile.in b/src/c/Makefile.in index 2109fa5a0..15e1c5d97 100644 --- a/src/c/Makefile.in +++ b/src/c/Makefile.in @@ -41,7 +41,7 @@ OBJS = main.o symbol.o package.o list.o\ instance.o gfun.o reference.o character.o\ file.o read.o print.o error.o string.o cfun.o\ typespec.o assignment.o \ - predicate.o big.o number.o\ + predicate.o number.o\ num_pred.o num_comp.o num_arith.o num_sfun.o num_co.o\ num_log.o num_rand.o array.o sequence.o cmpaux.o\ macros.o backq.o stacks.o \ diff --git a/src/c/big_ll.d b/src/c/big_ll.d new file mode 100644 index 000000000..628d71f74 --- /dev/null +++ b/src/c/big_ll.d @@ -0,0 +1,145 @@ +/* + big_ll.c -- Bignum emulation with long long. + */ +/* + Copyright (c) 2005, Maciek Pasternacki. + + ECL is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + See file '../Copyright' for full details. +*/ + +#include "ecl.h" +#include "internal.h" + +cl_object +big_register0_get(void) +{ + cl_env.big_register[0]->big.big_num = 0ll; + return cl_env.big_register[0]; +} + +cl_object +big_register1_get(void) +{ + cl_env.big_register[1]->big.big_num = 0ll; + return cl_env.big_register[1]; +} + +cl_object +big_register2_get(void) +{ + cl_env.big_register[2]->big.big_num = 0ll; + return cl_env.big_register[2]; +} + +void +big_register_free(cl_object x) {} + +cl_object +big_register_copy(cl_object old) +{ + cl_object new_big = cl_alloc_object(t_bignum); + new_big->big.big_num = old->big.big_num; + return new_big; +} + +cl_object +big_register_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 big_register_copy(x); +} + +static cl_object +big_alloc(int size) +{ + volatile cl_object x = cl_alloc_object(t_bignum); + if (size <= 0) + error("negative or zero size for bignum in big_alloc"); + x->big.big_num = 0ll; + return x; +} + + +cl_object +bignum1(cl_fixnum val) +{ + volatile cl_object z = cl_alloc_object(t_bignum); + z->big.big_num = val; + return(z); +} + +cl_object +bignum2(cl_fixnum hi, cl_fixnum lo) +{ + cl_object z; + + z = big_alloc(2); + z->big.big_num = hi<<32 + lo; + return(z); +} + +cl_object +big_copy(cl_object x) +{ + volatile cl_object y = cl_alloc_object(t_bignum); + y->big.big_num = x->big.big_num; + 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; +} + + +void init_big_registers(void) +{ + int i; + for (i = 0; i < 3; i++) { + cl_env.big_register[i] = cl_alloc_object(t_bignum); + cl_env.big_register[i]->big.big_num = 0ll; + } +} + +void +init_big(void) +{ + init_big_registers(); +} diff --git a/src/c/gbc-new.d b/src/c/gbc-new.d index c0d83cf2d..bb0c19539 100644 --- a/src/c/gbc-new.d +++ b/src/c/gbc-new.d @@ -133,6 +133,7 @@ BEGIN: switch (type_of(x)) { case t_bignum: +#ifdef WITH_GMP if (collect_blocks) { /* GMP may set num.alloc before actually allocating anything. With these checks we make sure we do not move anything @@ -143,6 +144,7 @@ BEGIN: size_t size = x->big.big_dim * sizeof(mp_limb_t); if (size) mark_contblock(limbs, size); } +#endif /* WITH_GMP */ break; case t_ratio: diff --git a/src/c/gbc.d b/src/c/gbc.d index 2d4f26077..ce166c895 100644 --- a/src/c/gbc.d +++ b/src/c/gbc.d @@ -129,6 +129,7 @@ BEGIN: switch (type_of(x)) { case t_bignum: { +#ifdef WITH_GMP /* GMP may set num.alloc before actually allocating anything. With these checks we make sure we do not move anything we don't have to. Besides, we use big_dim as the size @@ -137,6 +138,7 @@ BEGIN: cl_ptr limbs = (cl_ptr)x->big.big_limbs; cl_index size = x->big.big_dim * sizeof(mp_limb_t); if (size) mark_contblock(limbs, size); +#endif /* WITH_GMP */ break; } case t_ratio: diff --git a/src/c/hash.d b/src/c/hash.d index 5c52a2969..a021288a2 100644 --- a/src/c/hash.d +++ b/src/c/hash.d @@ -120,8 +120,12 @@ _hash_eql(cl_hashkey h, cl_object x) BEGIN: switch (type_of(x)) { case t_bignum: +#ifdef WITH_GMP return hash_string(h, (unsigned char*)x->big.big_limbs, labs(x->big.big_size) * sizeof(mp_limb_t)); +#else /* WITH_GMP */ + return hash_word(h, (uint32_t)(x->big.big_num)); +#endif /* WITH_GMP */ case t_ratio: h = _hash_eql(h, x->ratio.num); return _hash_eql(h, x->ratio.den); diff --git a/src/c/main.d b/src/c/main.d index e9e0442b3..00bf626a9 100644 --- a/src/c/main.d +++ b/src/c/main.d @@ -377,16 +377,19 @@ cl_boot(int argc, char **argv) cl_list(8, @'&optional', @'&rest', @'&key', @'&allow-other-keys', @'&aux', @'&whole', @'&environment', @'&body')); - features = cl_list(5, + features = cl_list(4, make_keyword("ECL"), make_keyword("COMMON"), - make_keyword("ANSI-CL"), - make_keyword("COMMON-LISP"), make_keyword(ECL_ARCHITECTURE), make_keyword("FFI")); #define ADD_FEATURE(name) features = CONS(make_keyword(name),features) +#ifdef WITH_GMP + ADD_FEATURE("COMMON-LISP"); + ADD_FEATURE("ANSI-CL"); +#endif /* WITH_GMP */ + #if defined(GBC_BOEHM) ADD_FEATURE("BOEHM-GC"); #endif diff --git a/src/c/num_arith.d b/src/c/num_arith.d index db68435b0..2ed605040 100644 --- a/src/c/num_arith.d +++ b/src/c/num_arith.d @@ -32,8 +32,12 @@ 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 */ return big_register_normalize(x); } @@ -47,7 +51,11 @@ big_times_fix(cl_object b, cl_fixnum i) if (i == -1) return(big_minus(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); } @@ -57,7 +65,11 @@ 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); } @@ -212,10 +224,14 @@ number_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); 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 */ z = big_register_normalize(z); return(z); case t_ratio: @@ -240,10 +256,14 @@ number_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); 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); case t_bignum: @@ -365,10 +385,14 @@ number_minus(cl_object x, cl_object y) 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); 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); @@ -392,10 +416,14 @@ number_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); 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); case t_bignum: @@ -528,7 +556,11 @@ number_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 */ return big_register_normalize(z); case t_ratio: @@ -703,10 +735,14 @@ 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))) 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); } @@ -716,12 +752,20 @@ 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 */ } 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)); 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 */ } else { FEtype_error_integer(y); } @@ -785,7 +829,28 @@ get_gcd(cl_object x, cl_object y) y = bignum1(fix(y)); case t_bignum: gcd = big_register0_get(); - mpz_gcd(gcd->big.big_num, x->big.big_num, y->big.big_num); +#ifdef WITH_GMP + mpz_gcd(gcd->big.big_num, x->big.big_num, y->big.big_num); /* FIXME!!! */ +#else /* WITH_GMP */ + { + big_num_t i = x->big.big_num, j = y->big.big_num; + while ( 1 ) { + big_num_t k; + if ( ibig.big_num = k; + break; + } + k = i % j; + i = j; + j = k; + } + } +#endif /* WITH_GMP */ gcd = big_register_normalize(gcd); return(gcd); default: diff --git a/src/c/num_co.d b/src/c/num_co.d index ee04dfbe6..8f39416d2 100644 --- a/src/c/num_co.d +++ b/src/c/num_co.d @@ -47,7 +47,11 @@ double_to_integer(double d) 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); } } @@ -59,7 +63,11 @@ float_to_integer(float d) 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); } } @@ -213,9 +221,14 @@ floor2(cl_object x, cl_object y) */ cl_object q = big_register0_get(); cl_object r = big_register1_get(); +#ifdef WITH_GMP cl_object j = big_register2_get(); mpz_set_si(j->big.big_num, fix(x)); mpz_fdiv_qr(q->big.big_num, r->big.big_num, j->big.big_num, y->big.big_num); +#else /* WITH_GMP */ + q->big.big_num = (big_num_t)fix(x) / y->big.big_num; + r->big.big_num = (big_num_t)fix(x) % y->big.big_num; +#endif /* WITH_GMP */ VALUES(0) = big_register_normalize(q); VALUES(1) = big_register_normalize(r); break; @@ -249,9 +262,14 @@ floor2(cl_object x, cl_object y) case t_fixnum: { /* BIG / FIX */ cl_object q = big_register0_get(); cl_object r = big_register1_get(); +#ifdef WITH_GMP cl_object j = big_register2_get(); mpz_set_si(j->big.big_num, fix(y)); mpz_fdiv_qr(q->big.big_num, r->big.big_num, x->big.big_num, j->big.big_num); +#else /* WITH_GMP */ + q->big.big_num = x->big.big_num / fix(y); + r->big.big_num = x->big.big_num % fix(y); +#endif /* WITH_GMP */ VALUES(0) = big_register_normalize(q); VALUES(1) = big_register_normalize(r); break; @@ -259,7 +277,12 @@ floor2(cl_object x, cl_object y) case t_bignum: { /* BIG / BIG */ cl_object q = big_register0_get(); cl_object r = big_register1_get(); +#ifdef WITH_GMP mpz_fdiv_qr(q->big.big_num, r->big.big_num, x->big.big_num, y->big.big_num); +#else /* WITH_GMP */ + q = x->big.big_num / y->big.big_num; + r = x->big.big_num % y->big.big_num; +#endif /* WITH_GMP */ VALUES(0) = big_register_normalize(q); VALUES(1) = big_register_normalize(r); break; @@ -392,9 +415,14 @@ ceiling2(cl_object x, cl_object y) */ cl_object q = big_register0_get(); cl_object r = big_register1_get(); +#ifdef WITH_GMP cl_object j = big_register2_get(); mpz_set_si(j->big.big_num, fix(x)); mpz_cdiv_qr(q->big.big_num, r->big.big_num, j->big.big_num, y->big.big_num); +#else /* WITH_GMP */ + q = (big_num_t)fix(x) / y->big.big_num; + r = (big_num_t)fix(x) % y->big.big_num; +#endif /* WITH_GMP */ VALUES(0) = big_register_normalize(q); VALUES(1) = big_register_normalize(r); break; @@ -428,9 +456,14 @@ ceiling2(cl_object x, cl_object y) case t_fixnum: { /* BIG / FIX */ cl_object q = big_register0_get(); cl_object r = big_register1_get(); +#ifdef WITH_GMP cl_object j = big_register2_get(); mpz_set_si(j->big.big_num, fix(y)); mpz_cdiv_qr(q->big.big_num, r->big.big_num, x->big.big_num, j->big.big_num); +#else /* WITH_GMP */ + q = x->big.big_num / fix(y); + r = x->big.big_num % fix(y); +#endif /* WITH_GMP */ VALUES(0) = big_register_normalize(q); VALUES(1) = big_register_normalize(r); break; @@ -438,7 +471,12 @@ ceiling2(cl_object x, cl_object y) case t_bignum: { /* BIG / BIG */ cl_object q = big_register0_get(); cl_object r = big_register1_get(); +#ifdef WITH_GMP mpz_cdiv_qr(q->big.big_num, r->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; + r->big.big_num = x->big.big_num % y->big.big_num; +#endif /* WITH_GMP */ VALUES(0) = big_register_normalize(q); VALUES(1) = big_register_normalize(r); break; diff --git a/src/c/num_log.d b/src/c/num_log.d index 4797f9dd4..0f0eabce0 100644 --- a/src/c/num_log.d +++ b/src/c/num_log.d @@ -31,7 +31,11 @@ ior_op(cl_fixnum i, cl_fixnum j) static void mpz_ior_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_ior(i->big.big_num, i->big.big_num, j->big.big_num); +#else /* WITH_GMP */ + i->big.big_num |= j->big.big_num; +#endif /* WITH_GMP */ } static cl_fixnum @@ -43,7 +47,11 @@ xor_op(cl_fixnum i, cl_fixnum j) static void mpz_xor_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_xor(i->big.big_num, i->big.big_num, j->big.big_num); +#else /* WITH_GMP */ + i->big.big_num ^= j->big.big_num; +#endif /* WITH_GMP */ } static cl_fixnum @@ -55,7 +63,11 @@ and_op(cl_fixnum i, cl_fixnum j) static void mpz_and_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_and(i->big.big_num, i->big.big_num, j->big.big_num); +#else /* WITH_GMP */ + i->big.big_num &= j->big.big_num; +#endif /* WITH_GMP */ } static cl_fixnum @@ -67,8 +79,12 @@ eqv_op(cl_fixnum i, cl_fixnum j) static void mpz_eqv_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_xor(i->big.big_num, i->big.big_num, j->big.big_num); mpz_com(i->big.big_num, i->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = ~(i->big.big_num ^ j->big.big_num); +#endif /* WITH_GMP */ } static cl_fixnum @@ -80,8 +96,12 @@ nand_op(cl_fixnum i, cl_fixnum j) static void mpz_nand_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_and(i->big.big_num, i->big.big_num, j->big.big_num); mpz_com(i->big.big_num, i->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = ~(i->big.big_num & j->big.big_num); +#endif /* WITH_GMP */ } static cl_fixnum @@ -93,8 +113,12 @@ nor_op(cl_fixnum i, cl_fixnum j) static void mpz_nor_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_ior(i->big.big_num, i->big.big_num, j->big.big_num); mpz_com(i->big.big_num, i->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = ~(i->big.big_num | j->big.big_num); +#endif /* WITH_GMP */ } static cl_fixnum @@ -106,8 +130,12 @@ andc1_op(cl_fixnum i, cl_fixnum j) static void mpz_andc1_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_com(i->big.big_num, i->big.big_num); mpz_and(i->big.big_num, i->big.big_num, j->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = (~i->big.big_num) & (big_num_t)j; +#endif /* WITH_GMP */ } static cl_fixnum @@ -121,9 +149,13 @@ static void mpz_orc1_op(cl_object, cl_object); static void mpz_andc2_op(cl_object i, cl_object j) { +#ifdef WITH_GMP /* (i & ~j) = ~((~i) | j) */ mpz_orc1_op(i, j); mpz_com(i->big.big_num, i->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = i->big.big_num & (~j->big.big_num); +#endif /* WITH_GMP */ } static cl_fixnum @@ -135,8 +167,12 @@ orc1_op(cl_fixnum i, cl_fixnum j) static void mpz_orc1_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_com(i->big.big_num, i->big.big_num); mpz_ior(i->big.big_num, i->big.big_num, j->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = (~i->big.big_num) | j->big.big_num; +#endif /* WITH_GMP */ } static cl_fixnum @@ -148,9 +184,13 @@ orc2_op(cl_fixnum i, cl_fixnum j) static void mpz_orc2_op(cl_object i, cl_object j) { +#ifdef WITH_GMP /* (i | ~j) = ~((~i) & j) */ mpz_andc1_op(i, j); mpz_com(i->big.big_num, i->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = i->big.big_num | (~j->big.big_num); +#endif /* WITH_GMP */ } static cl_fixnum @@ -162,7 +202,11 @@ b_clr_op(cl_fixnum i, cl_fixnum j) static void mpz_b_clr_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_set_si(i->big.big_num, 0); +#else /* WITH_GMP */ + i->big.big_num = 0ll; +#endif /* WITH_GMP */ } static cl_fixnum @@ -174,7 +218,11 @@ b_set_op(cl_fixnum i, cl_fixnum j) static void mpz_b_set_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_set_si(i->big.big_num, -1); +#else /* WITH_GMP */ + i->big.big_num = -1ll; +#endif /* WITH_GMP */ } static cl_fixnum @@ -197,7 +245,11 @@ b_2_op(cl_fixnum i, cl_fixnum j) static void mpz_b_2_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_set(i->big.big_num, j->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = j->big.big_num; +#endif /* WITH_GMP */ } static cl_fixnum @@ -209,7 +261,11 @@ b_c1_op(cl_fixnum i, cl_fixnum j) static void mpz_b_c1_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_com(i->big.big_num, i->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = ~i->big.big_num; +#endif /* WITH_GMP */ } static cl_fixnum @@ -221,7 +277,11 @@ b_c2_op(cl_fixnum i, cl_fixnum j) static void mpz_b_c2_op(cl_object i, cl_object j) { +#ifdef WITH_GMP mpz_com(i->big.big_num, j->big.big_num); +#else /* WITH_GMP */ + i->big.big_num = ~j->big.big_num; +#endif /* WITH_GMP */ } typedef cl_fixnum (*bit_operator)(cl_fixnum, cl_fixnum); @@ -371,7 +431,11 @@ ecl_boole(int op, cl_object x, cl_object y) 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_register_free(z); break; @@ -410,6 +474,7 @@ count_bits(cl_object x) break; } case t_bignum: +#ifdef WITH_GMP if (big_sign(x) >= 0) count = mpz_popcount(x->big.big_num); else { @@ -418,6 +483,15 @@ count_bits(cl_object x) count = mpz_popcount(z->big.big_num); big_register_free(z); } +#else /* WITH_GMP */ + { + big_num_t i = x->big.big_num; + if ( i<0 ) + i = ~i; + for ( count=0 ; i ; i >>= 1 ) + if ( i&1 ) count++; + } +#endif /* WITH_GMP */ break; default: FEtype_error_integer(x); @@ -454,13 +528,22 @@ ecl_ash(cl_object x, cl_fixnum w) } return MAKE_FIXNUM(y); } +#ifdef WITH_GMP mpz_div_2exp(y->big.big_num, x->big.big_num, bits); +#else /* WITH_GMP */ + y->big.big_num = x->big.big_num >> bits; +#endif /* WITH_GMP */ } else { +#ifdef WITH_GMP if (FIXNUMP(x)) { mpz_set_si(y->big.big_num, fix(x)); x = y; } mpz_mul_2exp(y->big.big_num, x->big.big_num, (unsigned long)w); +#else /* WITH_GMP */ + y->big.big_num = FIXNUMP(x) ? fix(x) : x->big.big_num; + y->big.big_num <<= w; +#endif /* WITH_GMP */ } return(big_register_normalize(y)); } @@ -577,7 +660,15 @@ cl_logbitp(cl_object p, cl_object x) i = ((y >> n) & 1); } } else { +#ifdef WITH_GMP i = mpz_tstbit(x->big.big_num, n); +#else /* WITH_GMP */ + if ( n >= 8*sizeof(big_num_t) ) { + i = (x->big.big_num < 0); + } else { + i = (x->big.big_num >> n) & 1; + } +#endif /* WITH_GMP */ } } else { assert_type_non_negative_integer(p); @@ -645,9 +736,17 @@ cl_integer_length(cl_object x) count = ecl_fixnum_bit_length(i); break; case t_bignum: - if (mpz_sgn(x->big.big_num) < 0) + if (big_sign(x) < 0) x = cl_lognot(x); +#ifdef WITH_GMP count = mpz_sizeinbase(x->big.big_num, 2); +#else /* WITH_GMP */ + for ( i=(8*sizeof(big_num_t))-1 ; i>0 ; i-- ) + if ( (x->big.big_num >> i) & 1 ) { + count = i; + break; + } +#endif /* WITH_GMP */ break; default: FEtype_error_integer(x); diff --git a/src/c/number.d b/src/c/number.d index a8c4b24eb..6ead62462 100644 --- a/src/c/number.d +++ b/src/c/number.d @@ -37,9 +37,14 @@ fixint(cl_object x) if (FIXNUMP(x)) return fix(x); if (type_of(x) == t_bignum) { +#ifdef WITH_GMP if (mpz_fits_slong_p(x->big.big_num)) { return mpz_get_si(x->big.big_num); } +#else /* WITH_GMP */ + if ( !((cl_fixnum)x->big.big_num < x->big.big_num) ) + return (cl_fixnum)x->big.big_num; +#endif /* WITH_GMP */ } FEwrong_type_argument(@'fixnum', x); } @@ -52,9 +57,15 @@ fixnnint(cl_object x) if (i >= 0) return i; } else if (type_of(x) == t_bignum) { +#ifdef WITH_GMP if (mpz_fits_ulong_p(x->big.big_num)) { return mpz_get_ui(x->big.big_num); } +#else /* WITH_GMP */ + if ( x->big.big_num >= 0 + && !((cl_fixnum)x->big.big_num < x->big.big_num) ) + return (cl_fixnum)x->big.big_num; +#endif /* WITH_GMP */ } cl_error(9, @'simple-type-error', @':format-control', make_constant_string("Not a non-negative fixnum ~S"), @@ -68,7 +79,11 @@ make_integer(cl_fixnum l) { if (l > MOST_POSITIVE_FIXNUM || l < MOST_NEGATIVE_FIXNUM) { cl_object z = cl_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; } return MAKE_FIXNUM(l); @@ -79,7 +94,11 @@ make_unsigned_integer(cl_index l) { if (l > MOST_POSITIVE_FIXNUM) { cl_object z = cl_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; } return MAKE_FIXNUM(l); @@ -215,8 +234,9 @@ number_to_double(cl_object x) return(big_to_double(x)); case t_ratio: { +#ifdef WITH_GMP double output; - mpq_t aux; + mpq_t aux; mpq_init(aux); if (FIXNUMP(x->ratio.num)) { mpz_set_si(mpq_numref(aux), fix(x->ratio.num)); @@ -231,6 +251,11 @@ number_to_double(cl_object x) output = mpq_get_d(aux); mpq_clear(aux); return output; +#else /* WITH_GMP */ + return (double)(FIXNUMP(x->ratio.num) ? fix(x->ratio.num) : x->ratio.num->big.big_num) / + (double)(FIXNUMP(x->ratio.den) ? fix(x->ratio.den) : x->ratio.den->big.big_num); +#endif /* WITH_GMP */ + } case t_shortfloat: return((double)(sf(x))); diff --git a/src/c/print.d b/src/c/print.d index 65065e27e..cfc4a69bc 100644 --- a/src/c/print.d +++ b/src/c/print.d @@ -596,6 +596,8 @@ write_double(double d, int e, bool shortp, cl_object stream) } +#ifdef WITH_GMP + struct powers { cl_object number; cl_index n_digits; @@ -661,6 +663,29 @@ write_bignum(cl_object x, cl_object stream) #endif } +#else /* WITH_GMP */ + +static void +write_positive_bignum(big_num_t x, cl_object stream) +{ + /* The maximum number of digits is achieved for base 2 and it + is always < 8*sizeof(big_num_t) */ + int base = ecl_print_base(); + short digits[8*sizeof(big_num_t)]; + int j = 0; + if (x == (big_num_t)0) { + digits[j++] = '0'; + } else do { + digits[j++] = ecl_digit_char((cl_fixnum)(x % (big_num_t)base), base); + x /= base; + } while (x > (big_num_t)0); + /* while (len-- > j) + write_ch('0', stream); */ + while (j-- > 0) + write_ch(digits[j], stream); +} +#endif /* WITH_GMP */ + static bool all_dots(cl_object s) { @@ -981,7 +1006,19 @@ si_write_ugly_object(cl_object x, cl_object stream) int print_base = ecl_print_base(); if (print_radix && print_base != 10) write_base(print_base, stream); +#ifdef WITH_GMP write_bignum(x, stream); +#else /* WITH_GMP */ + if ( big_zerop(x) ) { + write_ch('0', stream); + } else if ( big_sign(x) < 0 ) { + write_ch('-', stream); + write_positive_bignum(-(x->big.big_num), stream); + } else { + write_positive_bignum(x->big.big_num, stream); + } +#endif /* WITH_GMP */ + if (print_radix && print_base == 10) write_ch('.', stream); break; diff --git a/src/configure b/src/configure index 32f59a485..40d4a4def 100755 --- a/src/configure +++ b/src/configure @@ -1,5 +1,5 @@ #! /bin/sh -# From configure.in Revision: 1.110 . +# From configure.in Revision: 1.111 . # Guess values for system-dependent variables and create Makefiles. # Generated by GNU Autoconf 2.59 for ecl 0.9g. # @@ -751,22 +751,6 @@ ac_env_target_alias_set=${target_alias+set} ac_env_target_alias_value=$target_alias ac_cv_env_target_alias_set=${target_alias+set} ac_cv_env_target_alias_value=$target_alias -ac_env_CC_set=${CC+set} -ac_env_CC_value=$CC -ac_cv_env_CC_set=${CC+set} -ac_cv_env_CC_value=$CC -ac_env_CFLAGS_set=${CFLAGS+set} -ac_env_CFLAGS_value=$CFLAGS -ac_cv_env_CFLAGS_set=${CFLAGS+set} -ac_cv_env_CFLAGS_value=$CFLAGS -ac_env_LDFLAGS_set=${LDFLAGS+set} -ac_env_LDFLAGS_value=$LDFLAGS -ac_cv_env_LDFLAGS_set=${LDFLAGS+set} -ac_cv_env_LDFLAGS_value=$LDFLAGS -ac_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_env_CPPFLAGS_value=$CPPFLAGS -ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} -ac_cv_env_CPPFLAGS_value=$CPPFLAGS ac_env_CXX_set=${CXX+set} ac_env_CXX_value=$CXX ac_cv_env_CXX_set=${CXX+set} @@ -843,10 +827,6 @@ _ACEOF X features: --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR - -System types: - --build=BUILD configure for building on BUILD [guessed] - --host=HOST cross-compile to build programs to run on HOST [BUILD] _ACEOF fi @@ -867,43 +847,35 @@ Optional Features: --enable-local-boehm Deprecated! See --enable-boehm --enable-slow-config use GMP to guess compiler/linker flags (no|yes, default=NO) - --enable-local-gmp Deprecated! See --with-system-gmp - --enable-opcode8 interpreter uses 8-bit codes (default=NO, only works - on Intel) Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --with-cross-config=f supply configuration for a cross compiler --with-system-boehm Deprecated! See --enable-boehm - --with-gmp=args supply arguments for configuring GMP library - --with-system-gmp use already installed GMP library (default=auto) - --with-__thread Enable __thread thread-local variables (supported by - NPTL-aware glibc and maybe Windows) - --with-cxx build ECL using C++ compiler (default=NO) - --with-tcp include socket interface (default=NO) - --with-clx include CLX library (default=NO) - --with-clos-streams user defined stream objects (default=YES) - --with-cmuformat use CMUCL's FORMAT routine (default=YES) - --with-asdf include ASDF building facility (default=YES if - shared library support is on) - --with-cmp build in the compiler (default=YES) - --with-x use the X Window System + --with-gmp=args +with_gmp=""supply arguments for configuring GMP library -Some influential environment variables: - CC C compiler command - CFLAGS C compiler flags - LDFLAGS linker flags, e.g. -L if you have libraries in a - nonstandard directory - CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have - headers in a nonstandard directory + + --with-system-gmp use already installed GMP library (default=auto) +# Check whether --with-system-gmp or --without-system-gmp was given. +if test "${with_system_gmp+set}" = set; then + withval="$with_system_gmp" + +else + with_system_gmp="auto" +fi; + + --enable-local-gmp Deprecated! See --with-system-gmp +# Check whether --enable-local-gmp or --disable-local-gmp was given. +if test "${enable_local_gmp+set}" = set; then + enableval="$enable_local_gmp" + { echo "$as_me:$LINENO: WARNING: --with-local-gmp is deprecated + --with-x use the X Window System CXX C++ compiler command CXXFLAGS C++ compiler flags CPP C preprocessor -Use these variables to override the choices made by `configure' or to help -it to find libraries and programs with nonstandard names/locations. - _ACEOF fi @@ -1447,33 +1419,24 @@ fi; # Check whether --with-gmp or --without-gmp was given. if test "${with_gmp+set}" = set; then withval="$with_gmp" - -fi; - - -# Check whether --with-system-gmp or --without-system-gmp was given. -if test "${with_system_gmp+set}" = set; then - withval="$with_system_gmp" - + use --with-system-gmp instead!" >&5 +echo "$as_me: WARNING: --with-local-gmp is deprecated else - with_system_gmp="auto" -fi; - -# Check whether --enable-local-gmp or --disable-local-gmp was given. -if test "${enable_local_gmp+set}" = set; then - enableval="$enable_local_gmp" - { echo "$as_me:$LINENO: WARNING: --with-local-gmp is deprecated, use --with-system-gmp instead!" >&5 -echo "$as_me: WARNING: --with-local-gmp is deprecated, use --with-system-gmp instead!" >&2;} + use --with-system-gmp instead!" >&2;} with_system_gmp="${enableval}" fi; + --with-__thread Enable __thread thread-local variables (supported by + NPTL-aware glibc and maybe Windows) # Check whether --with-__thread or --without-__thread was given. if test "${with___thread+set}" = set; then withval="$with___thread" fi; + --enable-opcode8 interpreter uses 8-bit codes (default=NO, only works + on Intel) # Check whether --enable-opcode8 or --disable-opcode8 was given. if test "${enable_opcode8+set}" = set; then enableval="$enable_opcode8" @@ -1483,6 +1446,7 @@ else fi; + --with-cxx build ECL using C++ compiler (default=NO) # Check whether --with-cxx or --without-cxx was given. if test "${with_cxx+set}" = set; then withval="$with_cxx" @@ -1492,6 +1456,7 @@ else fi; + --with-tcp include socket interface (default=NO) # Check whether --with-tcp or --without-tcp was given. if test "${with_tcp+set}" = set; then withval="$with_tcp" @@ -1501,6 +1466,7 @@ else fi; + --with-clx include CLX library (default=NO) # Check whether --with-clx or --without-clx was given. if test "${with_clx+set}" = set; then withval="$with_clx" @@ -1510,6 +1476,7 @@ else fi; + --with-clos-streams user defined stream objects (default=YES) # Check whether --with-clos-streams or --without-clos-streams was given. if test "${with_clos_streams+set}" = set; then withval="$with_clos_streams" @@ -1519,6 +1486,7 @@ else fi; + --with-cmuformat use CMUCL's FORMAT routine (default=YES) # Check whether --with-cmuformat or --without-cmuformat was given. if test "${with_cmuformat+set}" = set; then withval="$with_cmuformat" @@ -1528,6 +1496,8 @@ else fi; + --with-asdf include ASDF building facility (default=YES if + shared library support is on) # Check whether --with-asdf or --without-asdf was given. if test "${with_asdf+set}" = set; then withval="$with_asdf" @@ -1537,6 +1507,7 @@ else fi; + --with-cmp build in the compiler (default=YES) # Check whether --with-cmp or --without-cmp was given. if test "${with_cmp+set}" = set; then withval="$with_cmp" @@ -1557,6 +1528,9 @@ SUBDIRS=c LSP_FEATURES='*features*' + +System types: + --build=BUILD configure for building on BUILD guessed # Make sure we can run config.sub. $ac_config_sub sun4 >/dev/null 2>&1 || { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 @@ -1584,11 +1558,12 @@ fi echo "$as_me:$LINENO: result: $ac_cv_build" >&5 echo "${ECHO_T}$ac_cv_build" >&6 build=$ac_cv_build -build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +build_cpu=`echo $ac_cv_build | sed 's/^\(^-*\)-\(^-*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\(^-*\)-\(^-*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\(^-*\)-\(^-*\)-\(.*\)$/\3/'` + --host=HOST cross-compile to build programs to run on HOST BUILD echo "$as_me:$LINENO: checking host system type" >&5 echo $ECHO_N "checking host system type... $ECHO_C" >&6 if test "${ac_cv_host+set}" = set; then @@ -1606,9 +1581,9 @@ fi echo "$as_me:$LINENO: result: $ac_cv_host" >&5 echo "${ECHO_T}$ac_cv_host" >&6 host=$ac_cv_host -host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` -host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` -host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` +host_cpu=`echo $ac_cv_host | sed 's/^\(^-*\)-\(^-*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\(^-*\)-\(^-*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\(^-*\)-\(^-*\)-\(.*\)$/\3/'` @@ -1618,6 +1593,33 @@ ac_cpp='$CPP $CPPFLAGS' ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' ac_compiler_gnu=$ac_cv_c_compiler_gnu + +Some influential environment variables: + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + CC C compiler command +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC + CFLAGS C compiler flags +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS + CPPFLAGS C/C++ preprocessor flags, e.g. -I if you have + headers in a nonstandard directory +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS if test -n "$ac_tool_prefix"; then # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. set dummy ${ac_tool_prefix}gcc; ac_word=$2 @@ -1970,7 +1972,7 @@ ac_clean_files="$ac_clean_files a.out a.exe b.out" # of exeext. echo "$as_me:$LINENO: checking for C compiler default output file name" >&5 echo $ECHO_N "checking for C compiler default output file name... $ECHO_C" >&6 -ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest^ *//'` if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 (eval $ac_link_default) 2>&5 ac_status=$? @@ -1988,7 +1990,8 @@ for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out do test -f "$ac_file" || continue case $ac_file in - *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj +fi; ;; conftest.$ac_ext ) # This is the source file. @@ -4068,8 +4071,9 @@ _ACEOF fi -if test ${with_system_gmp} = "auto"; then - echo "$as_me:$LINENO: checking for __gmpz_init in -lgmp" >&5 +if test "x${with_gmp}" != "xno"; then + if test ${with_system_gmp} = "auto"; then + echo "$as_me:$LINENO: checking for __gmpz_init in -lgmp" >&5 echo $ECHO_N "checking for __gmpz_init in -lgmp... $ECHO_C" >&6 if test "${ac_cv_lib_gmp___gmpz_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -4139,10 +4143,10 @@ else with_system_gmp=no fi -fi + fi -if test "${with_system_gmp}" = "yes"; then - echo "$as_me:$LINENO: checking for __gmpz_init in -lgmp" >&5 + if test "${with_system_gmp}" = "yes"; then + echo "$as_me:$LINENO: checking for __gmpz_init in -lgmp" >&5 echo $ECHO_N "checking for __gmpz_init in -lgmp... $ECHO_C" >&6 if test "${ac_cv_lib_gmp___gmpz_init+set}" = set; then echo $ECHO_N "(cached) $ECHO_C" >&6 @@ -4214,17 +4218,17 @@ echo "$as_me: error: System gmp library requested but not found." >&2;} { (exit 1); exit 1; }; } fi -else - SUBDIRS="${SUBDIRS} gmp" - CORE_LIBS="-leclgmp ${CORE_LIBS}" - if test ${enable_shared} = "no"; then - LIBRARIES="${LIBRARIES} ${LIBPREFIX}eclgmp.${LIBEXT}" + else + SUBDIRS="${SUBDIRS} gmp" + CORE_LIBS="-leclgmp ${CORE_LIBS}" + if test ${enable_shared} = "no"; then + LIBRARIES="${LIBRARIES} ${LIBPREFIX}eclgmp.${LIBEXT}" + fi fi fi - echo "$as_me:$LINENO: checking for X" >&5 echo $ECHO_N "checking for X... $ECHO_C" >&6 @@ -6190,6 +6194,71 @@ _ACEOF fi +echo "$as_me:$LINENO: checking for long long int" >&5 +echo $ECHO_N "checking for long long int... $ECHO_C" >&6 +if test "${ac_cv_c_long_long+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$GCC" = yes; then + ac_cv_c_long_long=yes + else + cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +long long int i; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" + || test ! -s conftest.err' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_c_long_long=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_c_long_long=no +fi +rm -f conftest.err conftest.$ac_objext conftest.$ac_ext + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_c_long_long" >&5 +echo "${ECHO_T}$ac_cv_c_long_long" >&6 + if test $ac_cv_c_long_long = yes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_LONG_LONG 1 +_ACEOF + + fi + echo "$as_me:$LINENO: checking whether byte ordering is bigendian" >&5 @@ -9672,9 +9741,19 @@ echo "$as_me: Configuring included Boehm GC library:" >&6;} fi fi -if test "${with_system_gmp}" = "no" ; then +if test "${with_gmp}" = "no" ; then + { echo "$as_me:$LINENO: Not using GMP library at all. Are you sure?" >&5 +echo "$as_me: Not using GMP library at all. Are you sure?" >&6;} + EXTRA_OBJS="${EXTRA_OBJS} big_ll.o" +elif test "${with_system_gmp}" = "no" ; then { echo "$as_me:$LINENO: Configuring included GMP library:" >&5 echo "$as_me: Configuring included GMP library:" >&6;} + EXTRA_OBJS="${EXTRA_OBJS} big.o" + +cat >>confdefs.h <<\_ACEOF +#define WITH_GMP 1 +_ACEOF + test -d gmp && rm -rf gmp if mkdir gmp; then (destdir=`${PWDCMD}`; cd gmp; CC="${CC} ${PICFLAG}" \ diff --git a/src/configure.in b/src/configure.in index 57e5de1d6..5818fda95 100644 --- a/src/configure.in +++ b/src/configure.in @@ -64,7 +64,8 @@ AC_ARG_WITH(system-boehm, AC_ARG_WITH(gmp, AS_HELP_STRING( [--with-gmp=args], - [supply arguments for configuring GMP library])) + [supply arguments for configuring GMP library] + [], [with_gmp=""]) AC_ARG_WITH(system-gmp, AS_HELP_STRING( [--with-system-gmp], @@ -261,23 +262,24 @@ fi dnl ---------------------------------------------------------------------- dnl GNU multiprecision library -if test ${with_system_gmp} = "auto"; then - AC_CHECK_LIB( [gmp], [__gmpz_init], - [with_system_gmp=yes], [with_system_gmp=no] ) -fi - -if test "${with_system_gmp}" = "yes"; then - AC_CHECK_LIB( [gmp], [__gmpz_init], - [FASL_LIBS="${FASL_LIBS} -lgmp"], - [AC_MSG_ERROR([System gmp library requested but not found.])]) -else - SUBDIRS="${SUBDIRS} gmp" - CORE_LIBS="-leclgmp ${CORE_LIBS}" - if test ${enable_shared} = "no"; then - LIBRARIES="${LIBRARIES} ${LIBPREFIX}eclgmp.${LIBEXT}" +if test "x${with_gmp}" != "xno"; then + if test ${with_system_gmp} = "auto"; then + AC_CHECK_LIB( [gmp], [__gmpz_init], + [with_system_gmp=yes], [with_system_gmp=no] ) fi -fi + if test "${with_system_gmp}" = "yes"; then + AC_CHECK_LIB( [gmp], [__gmpz_init], + [FASL_LIBS="${FASL_LIBS} -lgmp"], + [AC_MSG_ERROR([System gmp library requested but not found.])]) + else + SUBDIRS="${SUBDIRS} gmp" + CORE_LIBS="-leclgmp ${CORE_LIBS}" + if test ${enable_shared} = "no"; then + LIBRARIES="${LIBRARIES} ${LIBPREFIX}eclgmp.${LIBEXT}" + fi + fi +fi dnl ===================================================================== dnl Checks for header files @@ -306,6 +308,7 @@ AC_TYPE_SIZE_T dnl !!! DNLed AC_STRUCT_TM AC_C_VOLATILE AC_CHECK_TYPES([ptrdiff_t]) +AC_C_LONG_LONG dnl !!! end autoscan dnl !!! dnled in original @@ -446,8 +449,13 @@ fi dnl ---------------------------------------------------------------------- dnl Configure local GMP if needed -if test "${with_system_gmp}" = "no" ; then +if test "${with_gmp}" = "no" ; then + AC_MSG_NOTICE(Not using GMP library at all. Are you sure?) + EXTRA_OBJS="${EXTRA_OBJS} big_ll.o" +elif test "${with_system_gmp}" = "no" ; then AC_MSG_NOTICE(Configuring included GMP library:) + EXTRA_OBJS="${EXTRA_OBJS} big.o" + AC_DEFINE( [WITH_GMP], [1], [Use GMP for bignums] ) test -d gmp && rm -rf gmp if mkdir gmp; then (destdir=`${PWDCMD}`; cd gmp; CC="${CC} ${PICFLAG}" \ diff --git a/src/h/config.h.in b/src/h/config.h.in index ea280907d..274558274 100644 --- a/src/h/config.h.in +++ b/src/h/config.h.in @@ -25,6 +25,9 @@ #define ECL_DYNAMIC_VV #endif +/* Use GNU Multiple Precision library for bignums */ +#undef WITH_GMP + /* Userland threads? */ #undef ECL_THREADS @@ -191,6 +194,8 @@ typedef unsigned @CL_FIXNUM_TYPE@ cl_hashkey; #undef HAVE_SIGPROCMASK /* isatty() checks whether a file is connected to a */ #undef HAVE_ISATTY +/* compiler understands long long */ +#undef HAVE_LONG_LONG /* what characters are used to mark beginning of new line */ #undef ECL_NEWLINE_IS_CRLF diff --git a/src/h/ecl-cmp.h b/src/h/ecl-cmp.h index 5b6b4b6ba..33be00c9a 100644 --- a/src/h/ecl-cmp.h +++ b/src/h/ecl-cmp.h @@ -53,7 +53,9 @@ typedef unsigned short uint16_t; # define end_critical_section() #endif +#ifdef WITH_GMP #include +#endif /* WITH_GMP */ #include #include #include diff --git a/src/h/ecl.h b/src/h/ecl.h index 875c58824..4aa38dbb7 100644 --- a/src/h/ecl.h +++ b/src/h/ecl.h @@ -54,7 +54,9 @@ typedef unsigned short uint16_t; # define end_critical_section() #endif +#ifdef WITH_GMP #include +#endif /* WITH_GMP */ #include #include #ifndef _ARGS diff --git a/src/h/external.h b/src/h/external.h index 4af243ad0..9509853ef 100644 --- a/src/h/external.h +++ b/src/h/external.h @@ -92,7 +92,9 @@ struct cl_env_struct { /* Note: if you change the size of these registers, change also BIGNUM_REGISTER_SIZE in config.h */ cl_object big_register[3]; +#ifdef WITH_GMP mp_limb_t big_register_limbs[3][16]; +#endif /* WITH_GMP */ #ifdef ECL_THREADS cl_object own_process; @@ -301,7 +303,11 @@ extern cl_object big_register_copy(cl_object x); extern cl_object big_register_normalize(cl_object x); extern void big_register_free(cl_object x); extern cl_object bignum1(cl_fixnum val); +#ifdef WITH_GMP extern cl_object bignum2(mp_limb_t hi, mp_limb_t lo); +#else /* WITH_GMP */ +extern cl_object bignum2(cl_fixnum hi, cl_fixnum lo); +#endif /* WITH_GMP */ extern cl_object big_set_fixnum(cl_object x, cl_object fix); extern cl_object big_copy(cl_object x); extern cl_object big_minus(cl_object x); diff --git a/src/h/number.h b/src/h/number.h index b0a0e7d1c..ed3b6549d 100644 --- a/src/h/number.h +++ b/src/h/number.h @@ -12,6 +12,7 @@ See file '../Copyright' for full details. */ +#ifdef WITH_GMP #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) @@ -25,3 +26,19 @@ #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) +#else /* WITH_GMP */ +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_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)) +#endif /* WITH_GMP */ diff --git a/src/h/object.h b/src/h/object.h index f85dff938..6119bf423 100644 --- a/src/h/object.h +++ b/src/h/object.h @@ -92,6 +92,8 @@ struct ecl_longfloat { }; #define lf(obje) (obje)->LF.LFVAL +#ifdef WITH_GMP + struct ecl_bignum { HEADER; mpz_t big_num; @@ -100,6 +102,21 @@ struct ecl_bignum { #define big_size big_num->_mp_size #define big_limbs big_num->_mp_d +#else /* WITH_GMP */ + +# ifdef HAVE_LONG_LONG + typedef long long int big_num_t; +# else /* HAVE_LONG_LONG */ + typedef long int big_num_t; /* would it work? */ +# endif /* HAVE_LONG_LONG */ + +struct ecl_bignum { + HEADER; + big_num_t big_num; +}; + +#endif /* WITH_GMP */ + struct ecl_ratio { HEADER; cl_object den; /* denominator, must be an integer */