diff --git a/doc/ref/guile-invoke.texi b/doc/ref/guile-invoke.texi index 92208d559..856bce7b8 100644 --- a/doc/ref/guile-invoke.texi +++ b/doc/ref/guile-invoke.texi @@ -1,6 +1,6 @@ @c -*-texinfo-*- @c This is part of the GNU Guile Reference Manual. -@c Copyright (C) 1996-1997,2000-2005,2010-2011,2013-2014,2016,2019,2021 +@c Copyright (C) 1996-1997,2000-2005,2010-2011,2013-2014,2016,2019,2021-2022 @c Free Software Foundation, Inc. @c See the file guile.texi for copying conditions. @@ -424,19 +424,6 @@ Guile uses the environment variable @env{HOME}, the name of your home directory, to locate various files, such as @file{.guile} or @file{.guile_history}. -@item GUILE_INSTALL_GMP_MEMORY_FUNCTIONS -@vindex GUILE_INSTALL_GMP_MEMORY_FUNCTIONS -Guile uses the GNU multi-precision (GMP) library to implement its bigint -support. It can use an included minimal version of GMP, or the system -version, which may be more optimal. If Guile is the sole user of GMP in -the process, Guile can tell GMP to allocate its digits using -garbage-collected memory. This can be significantly faster. However -this approach is unsafe if there are other libraries loaded that use -libgmp, such as the GnuTLS library. The default is for Guile to do the -fastest safe thing: use the garbage collector for GMP when using the -included ``mini-GMP'', but not otherwise. Set this variable to nonzero -to force GMP to use garbage-collected memory, even when using system GC. - @item GUILE_JIT_THRESHOLD @vindex GUILE_JIT_THRESHOLD Guile has a just-in-time (JIT) code generator that makes running Guile diff --git a/libguile/deprecated.c b/libguile/deprecated.c index 0e0c20f28..8622e3bb8 100644 --- a/libguile/deprecated.c +++ b/libguile/deprecated.c @@ -36,6 +36,7 @@ #include "dynl.h" #include "eval.h" #include "foreign.h" +#include "finalizers.h" #include "generalized-vectors.h" #include "gc.h" #include "gsubr.h" @@ -690,6 +691,95 @@ SCM_DEFINE (scm_dynamic_unlink, "dynamic-unlink", 1, 0, 0, (SCM obj), "") #undef FUNC_NAME + + +static void +finalize_bignum (void *ptr, void *data) +{ + SCM bignum; + + bignum = SCM_PACK_POINTER (ptr); + mpz_clear (SCM_I_BIG_MPZ (bignum)); +} + +static SCM +make_bignum (void) +{ + scm_t_bits *p; + + /* Allocate one word for the type tag and enough room for an `mpz_t'. */ + p = scm_gc_malloc_pointerless (sizeof (scm_t_bits) + sizeof (mpz_t), + "bignum"); + p[0] = scm_tc16_big; + scm_i_set_finalizer (p, finalize_bignum, NULL); + + return SCM_PACK (p); +} + +/* scm_i_big2dbl() rounds to the closest representable double, + in accordance with R5RS exact->inexact. */ +double +scm_i_big2dbl (SCM b) +{ + scm_c_issue_deprecation_warning + ("scm_i_big2dbl is deprecated. Use scm_to_double instead."); + return scm_to_double (b); +} + +SCM +scm_i_long2big (long x) +{ + scm_c_issue_deprecation_warning + ("scm_i_long2big is deprecated. Use scm_from_long instead."); + /* Return a newly created bignum initialized to X. */ + SCM z = make_bignum (); + mpz_init_set_si (SCM_I_BIG_MPZ (z), x); + return z; +} + +SCM +scm_i_ulong2big (unsigned long x) +{ + scm_c_issue_deprecation_warning + ("scm_i_ulong2big is deprecated. Use scm_from_ulong instead."); + /* Return a newly created bignum initialized to X. */ + SCM z = make_bignum (); + mpz_init_set_ui (SCM_I_BIG_MPZ (z), x); + return z; +} + +SCM +scm_i_clonebig (SCM src_big, int same_sign_p) +{ + scm_c_issue_deprecation_warning + ("scm_i_clonebig is deprecated. Use scm_to_mpz/scm_from_mpz instead."); + /* Copy src_big's value, negate it if same_sign_p is false, and return. */ + SCM z = make_bignum (); + scm_to_mpz (src_big, SCM_I_BIG_MPZ (z)); + if (!same_sign_p) + mpz_neg (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (z)); + return z; +} + +SCM +scm_i_normbig (SCM b) +{ + scm_c_issue_deprecation_warning + ("scm_i_normbig is deprecated. Direct bignum bit manipulation is not " + "supported."); + /* convert a big back to a fixnum if it'll fit */ + /* presume b is a bignum */ + if (mpz_fits_slong_p (SCM_I_BIG_MPZ (b))) + { + scm_t_inum val = mpz_get_si (SCM_I_BIG_MPZ (b)); + if (SCM_FIXABLE (val)) + b = SCM_I_MAKINUM (val); + } + return b; +} + +int scm_install_gmp_memory_functions; + void diff --git a/libguile/deprecated.h b/libguile/deprecated.h index a062cbecb..be5b55676 100644 --- a/libguile/deprecated.h +++ b/libguile/deprecated.h @@ -1,7 +1,7 @@ #ifndef SCM_DEPRECATED_H #define SCM_DEPRECATED_H -/* Copyright 2003-2007,2009-2018,2020,2021 +/* Copyright 2003-2007,2009-2018,2020-2022 Free Software Foundation, Inc. This file is part of Guile. @@ -146,6 +146,19 @@ SCM_DEPRECATED SCM scm_copy_tree (SCM obj); SCM_DEPRECATED SCM scm_dynamic_unlink (SCM obj); +/* Each bignum is just an mpz_t stored in a double cell starting at word 1. */ +#if defined BUILDING_LIBGUILE || SCM_ENABLE_MINI_GMP == 0 +#define SCM_I_BIG_MPZ(x) (*((mpz_t *) (SCM_CELL_OBJECT_LOC((x),1)))) +#endif + +SCM_DEPRECATED int scm_install_gmp_memory_functions; +SCM_DEPRECATED SCM scm_i_normbig (SCM x); +SCM_DEPRECATED double scm_i_big2dbl (SCM b); +SCM_DEPRECATED SCM scm_i_long2big (long n); +SCM_DEPRECATED SCM scm_i_ulong2big (unsigned long n); +SCM_DEPRECATED SCM scm_i_clonebig (SCM src_big, int same_sign_p); + + void scm_i_init_deprecated (void); #endif diff --git a/libguile/numbers.c b/libguile/numbers.c index e62646ea2..20d525408 100644 --- a/libguile/numbers.c +++ b/libguile/numbers.c @@ -160,25 +160,6 @@ VARARG_MPZ_ITERATOR (mpz_clear) */ /* the macro above will not work as is with fractions */ - -/* In the context of Guile, it's most efficient for GMP to use libgc to - allocate MPZ values. That way Guile doesn't need to install - finalizers, which have significant overhead. Using libgc to allocate - digits also allows Guile's GC to adequately measure the memory cost - of MPZ values. - - However, if the Guile process is linked to some other user of GMP, - then probably the references from the other user of GMP to MPZ values - aren't visible to the garbage collector. So libgc could prematurely - collect values from that other GMP user. - - This isn't theoretical -- it happens for Guile-GnuTLS. GnuTLS uses - GMP, and so does Guile. But if Guile installs libgc as the allocator - for MPZ values, we break GnuTLS. - - Therefore we only install libgc as the GMP allocator if we are using - mini-gmp, which we know isn't shared with any external library. */ -int scm_install_gmp_memory_functions = SCM_ENABLE_MINI_GMP; static SCM flo0; static SCM exactly_one_half; static SCM flo_log10e; @@ -234,132 +215,6 @@ scm_from_complex_double (complex double z) -/* Clear the `mpz_t' embedded in bignum PTR. */ -static void -finalize_bignum (void *ptr, void *data) -{ - SCM bignum; - - bignum = SCM_PACK_POINTER (ptr); - mpz_clear (SCM_I_BIG_MPZ (bignum)); -} - -/* The next three functions (custom_libgmp_*) are passed to - mp_set_memory_functions (in GMP) so that memory used by the digits - themselves is known to the garbage collector. This is needed so - that GC will be run at appropriate times. Otherwise, a program which - creates many large bignums would malloc a huge amount of memory - before the GC runs. */ -static void * -custom_gmp_malloc (size_t alloc_size) -{ - return scm_gc_malloc_pointerless (alloc_size, "GMP"); -} - -static void * -custom_gmp_realloc (void *old_ptr, size_t old_size, size_t new_size) -{ - return scm_gc_realloc (old_ptr, old_size, new_size, "GMP"); -} - -static void -custom_gmp_free (void *ptr, size_t size) -{ - /* Do nothing: all memory allocated by GMP is under GC control and - will be freed when needed. */ -} - - -/* Return a new uninitialized bignum. */ -static inline SCM -make_bignum (void) -{ - scm_t_bits *p; - - /* Allocate one word for the type tag and enough room for an `mpz_t'. */ - p = scm_gc_malloc (sizeof (scm_t_bits) + sizeof (mpz_t), - "bignum"); - p[0] = scm_tc16_big; - - /* When the 'custom_gmp_*' functions are in use, no need to set a - finalizer since allocated memory is under GC control. In other - cases, set a finalizer to call 'mpz_clear', which is expensive. */ - if (!scm_install_gmp_memory_functions) - scm_i_set_finalizer (p, finalize_bignum, NULL); - - return SCM_PACK (p); -} - - -SCM -scm_i_long2big (long x) -{ - /* Return a newly created bignum initialized to X. */ - SCM z = make_bignum (); - mpz_init_set_si (SCM_I_BIG_MPZ (z), x); - return z; -} - -SCM -scm_i_ulong2big (unsigned long x) -{ - /* Return a newly created bignum initialized to X. */ - SCM z = make_bignum (); - mpz_init_set_ui (SCM_I_BIG_MPZ (z), x); - return z; -} - -SCM -scm_i_clonebig (SCM src_big, int same_sign_p) -{ - /* Copy src_big's value, negate it if same_sign_p is false, and return. */ - SCM z = make_bignum (); - mpz_init_set (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (src_big)); - if (!same_sign_p) - mpz_neg (SCM_I_BIG_MPZ (z), SCM_I_BIG_MPZ (z)); - return z; -} - -/* scm_i_big2dbl() rounds to the closest representable double, - in accordance with R5RS exact->inexact. */ -double -scm_i_big2dbl (SCM b) -{ - return scm_integer_to_double_z (scm_bignum (b)); -} - -SCM -scm_i_normbig (SCM b) -{ - /* convert a big back to a fixnum if it'll fit */ - /* presume b is a bignum */ - if (mpz_fits_slong_p (SCM_I_BIG_MPZ (b))) - { - scm_t_inum val = mpz_get_si (SCM_I_BIG_MPZ (b)); - if (SCM_FIXABLE (val)) - b = SCM_I_MAKINUM (val); - } - return b; -} - -static SCM_C_INLINE_KEYWORD SCM -scm_i_mpz2num (mpz_t b) -{ - /* convert a mpz number to a SCM number. */ - if (mpz_fits_slong_p (b)) - { - scm_t_inum val = mpz_get_si (b); - if (SCM_FIXABLE (val)) - return SCM_I_MAKINUM (val); - } - - { - SCM z = make_bignum (); - mpz_init_set (SCM_I_BIG_MPZ (z), b); - return z; - } -} - /* Make the ratio NUMERATOR/DENOMINATOR, where: 1. NUMERATOR and DENOMINATOR are exact integers 2. NUMERATOR and DENOMINATOR are reduced to lowest terms: gcd(n,d) == 1 */ @@ -6938,7 +6793,7 @@ scm_to_mpz (SCM val, mpz_t rop) SCM scm_from_mpz (mpz_t val) { - return scm_i_mpz2num (val); + return scm_integer_from_mpz (val); } int @@ -7324,20 +7179,6 @@ SCM_PRIMITIVE_GENERIC (scm_sqrt, "sqrt", 1, 0, 0, void scm_init_numbers () { - /* Give the user the chance to force the use of libgc to manage gmp - digits, if we know there are no external GMP users in this process. - Can be an important optimization for those who link external GMP, - before we switch to the MPN API. */ - if (!SCM_ENABLE_MINI_GMP) - scm_install_gmp_memory_functions - = scm_getenv_int ("GUILE_INSTALL_GMP_MEMORY_FUNCTIONS", - scm_install_gmp_memory_functions); - - if (scm_install_gmp_memory_functions) - mp_set_memory_functions (custom_gmp_malloc, - custom_gmp_realloc, - custom_gmp_free); - /* It may be possible to tune the performance of some algorithms by using * the following constants to avoid the creation of bignums. Please, before * using these values, remember the two rules of program optimization: diff --git a/libguile/numbers.h b/libguile/numbers.h index 80bc11720..fdb446e1a 100644 --- a/libguile/numbers.h +++ b/libguile/numbers.h @@ -1,7 +1,7 @@ #ifndef SCM_NUMBERS_H #define SCM_NUMBERS_H -/* Copyright 1995-1996,1998,2000-2006,2008-2011,2013-2014,2016-2018,2021,2022 +/* Copyright 1995-1996,1998,2000-2006,2008-2011,2013-2014,2016-2018,2021-2022 Free Software Foundation, Inc. This file is part of Guile. @@ -168,11 +168,6 @@ typedef long scm_t_inum; #define SCM_COMPLEX_REAL(x) (((scm_t_complex *) SCM2PTR (x))->real) #define SCM_COMPLEX_IMAG(x) (((scm_t_complex *) SCM2PTR (x))->imag) -/* Each bignum is just an mpz_t stored in a double cell starting at word 1. */ -#if defined BUILDING_LIBGUILE || SCM_ENABLE_MINI_GMP == 0 -#define SCM_I_BIG_MPZ(x) (*((mpz_t *) (SCM_CELL_OBJECT_LOC((x),1)))) -#endif - #define SCM_BIGP(x) (SCM_HAS_TYP16 (x, scm_tc16_big)) #define SCM_NUMBERP(x) (SCM_I_INUMP(x) || SCM_NUMP(x)) @@ -203,7 +198,6 @@ typedef struct scm_t_complex double imag; } scm_t_complex; - SCM_API SCM scm_exact_p (SCM x); @@ -346,13 +340,6 @@ SCM_INTERNAL SCM scm_i_product (SCM x, SCM y, SCM rest); SCM_INTERNAL SCM scm_i_divide (SCM x, SCM y, SCM rest); SCM_INTERNAL SCM scm_i_exact_integer_sqrt (SCM k); -/* bignum internal functions */ -SCM_API /* FIXME: not internal */ SCM scm_i_normbig (SCM x); -SCM_API /* FIXME: not internal */ double scm_i_big2dbl (SCM b); -SCM_API /* FIXME: not internal */ SCM scm_i_long2big (long n); -SCM_API /* FIXME: not internal */ SCM scm_i_ulong2big (unsigned long n); -SCM_API /* FIXME: not internal */ SCM scm_i_clonebig (SCM src_big, int same_sign_p); - /* ratio functions */ SCM_API SCM scm_rationalize (SCM x, SCM err); SCM_API SCM scm_numerator (SCM z); @@ -380,13 +367,13 @@ SCM_API SCM scm_from_signed_integer (intmax_t val); SCM_API SCM scm_from_unsigned_integer (uintmax_t val); SCM_API intmax_t scm_to_signed_integer (SCM val, - intmax_t min, - intmax_t max); + intmax_t min, + intmax_t max); SCM_API uintmax_t scm_to_unsigned_integer (SCM val, - uintmax_t min, - uintmax_t max); + uintmax_t min, + uintmax_t max); -SCM_API int8_t scm_to_int8 (SCM x); +SCM_API int8_t scm_to_int8 (SCM x); SCM_API SCM scm_from_int8 (int8_t x); SCM_API uint8_t scm_to_uint8 (SCM x); @@ -607,9 +594,6 @@ SCM_API double scm_c_angle (SCM z); SCM_API int scm_is_number (SCM val); -/* If nonzero, tell gmp to use GC_malloc for its allocations. */ -SCM_API int scm_install_gmp_memory_functions; - SCM_INTERNAL void scm_init_numbers (void); diff --git a/meta/build-env.in b/meta/build-env.in index 299b44f99..b48f9c245 100644 --- a/meta/build-env.in +++ b/meta/build-env.in @@ -1,6 +1,6 @@ #!/bin/sh -# Copyright (C) 2003, 2006, 2008-2012, 2016, 2017, 2021 Free Software Foundation +# Copyright (C) 2003, 2006, 2008-2012, 2016, 2017, 2021, 2022 Free Software Foundation # # This file is part of GNU Guile. # @@ -90,9 +90,6 @@ done export LTDL_LIBRARY_PATH export DYLD_LIBRARY_PATH -GUILE_INSTALL_GMP_MEMORY_FUNCTIONS=1 -export GUILE_INSTALL_GMP_MEMORY_FUNCTIONS - if [ x"$PKG_CONFIG_PATH" = x ] then PKG_CONFIG_PATH="${top_builddir}/meta"