From eaf68e6e858260dba6106e7c2f9bcc744175b450 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Fri, 16 Nov 2012 21:53:05 -0700 Subject: [PATCH] GMP and MPFR as pre-build libraries for Mac OS X and Windows Also, add versions for Unix references, and adjust the way that missing bindings are handled. --- .../math/private/bigfloat/bigfloat-mpfr.rkt | 4 - collects/math/private/bigfloat/mpfr.rkt | 93 +++++++++---------- collects/math/scribblings/math-bigfloat.scrbl | 30 +----- collects/meta/dist-specs.rkt | 3 + collects/scribblings/main/license.scrbl | 9 +- src/Makefile.in | 1 + src/get-libs.rkt | 17 ++++ src/mac/README.txt | 5 + src/mac/install-libs.rkt | 2 + src/worksp/build.bat | 2 + 10 files changed, 84 insertions(+), 82 deletions(-) diff --git a/collects/math/private/bigfloat/bigfloat-mpfr.rkt b/collects/math/private/bigfloat/bigfloat-mpfr.rkt index c7e90de221..b859a81dd1 100644 --- a/collects/math/private/bigfloat/bigfloat-mpfr.rkt +++ b/collects/math/private/bigfloat/bigfloat-mpfr.rkt @@ -9,8 +9,6 @@ (require/typed "mpfr.rkt" ;; Library stuffs - [get-mpfr-lib-dirs ((U 'unix 'windows 'macosx) -> (Listof Path-String))] - [set-mpfr-lib-dirs! ((U 'unix 'windows 'macosx) (Listof Path-String) -> Void)] [mpfr-available? (-> Boolean)] ;; Parameters [bf-rounding-mode (Parameterof Rounding-Mode)] @@ -141,8 +139,6 @@ (provide ;; Library stuffs - get-mpfr-lib-dirs - set-mpfr-lib-dirs! mpfr-available? ;; Parameters bf-rounding-mode diff --git a/collects/math/private/bigfloat/mpfr.rkt b/collects/math/private/bigfloat/mpfr.rkt index 32f31d433e..710fa0bc4f 100644 --- a/collects/math/private/bigfloat/mpfr.rkt +++ b/collects/math/private/bigfloat/mpfr.rkt @@ -3,6 +3,8 @@ (require ffi/unsafe ffi/unsafe/cvector ffi/unsafe/custodian + ffi/unsafe/define + racket/runtime-path racket/list racket/promise racket/serialize @@ -13,8 +15,6 @@ (provide ;; Library stuffs - get-mpfr-lib-dirs - set-mpfr-lib-dirs! mpfr-available? ;; Parameters bf-rounding-mode @@ -57,48 +57,36 @@ ;; use MPFR for functions that don't have a Typed Racket implementation yet. On systems without MPFR, ;; no exceptions will be raised unless a user tries to use those functions. -(define mpfr-lib-dirs - (make-hasheq '((macosx . ("/usr/local/lib" - "/opt/local/lib" - "/sw/local/lib"))))) +(define-runtime-path libgmp-so + (case (system-type) + [(macosx) '(so "libgmp.10.dylib")] + [(windows) '(so "libgmp-10.dll")] + [else '(so "libgmp")])) +(define-runtime-path libmpfr-so + (case (system-type) + [(macosx) '(so "libmpfr.4.dylib")] + [(windows) '(so "libmpfr-4.dll")] + [else '(so "libmpfr")])) -(define (set-mpfr-lib-dirs! os dirs) - (hash-set! mpfr-lib-dirs os dirs)) +(define gmp-lib (ffi-lib libgmp-so '("10" "3" "") #:fail (λ () #f))) +(define mpfr-lib (ffi-lib libmpfr-so '("4" "1" "") #:fail (λ () #f))) -(define (get-mpfr-lib-dirs os) - (hash-ref mpfr-lib-dirs os '())) +(define-syntax-rule (get-gmp-fun name type) + (get-ffi-obj name gmp-lib type (make-not-available name))) -(define (get-lib-dirs) - (hash-ref mpfr-lib-dirs (system-type) '())) - -(define libgmp (lazy (ffi-lib "libgmp" #:get-lib-dirs get-lib-dirs))) -(define libmpfr (lazy (ffi-lib "libmpfr" #:get-lib-dirs get-lib-dirs))) - -(define-syntax-rule (get-gmp-fun name args ...) - (let () - (define fun (lazy (get-ffi-obj name (force libgmp) args ...))) - (λ xs (apply (force fun) xs)))) - -(define-syntax-rule (get-mpfr-fun name args ...) - (let () - (define fun (lazy (get-ffi-obj name (force libmpfr) args ...))) - (λ xs (apply (force fun) xs)))) +(define-syntax get-mpfr-fun + (syntax-rules () + [(_ name type) (get-mpfr-fun name type (make-not-available name))] + [(_ name type fail-thunk) (get-ffi-obj name mpfr-lib type fail-thunk)])) + (define mpfr-free-cache (get-mpfr-fun 'mpfr_free_cache (_fun -> _void))) #;; This may be crashing Racket (define mpfr-shutdown (register-custodian-shutdown mpfr-free-cache (λ (free) (free)))) -(define (mpfr-available?*) - (and (ffi-lib? (ffi-lib "libgmp" #:get-lib-dirs get-lib-dirs #:fail (λ () #f))) - (ffi-lib? (ffi-lib "libmpfr" #:get-lib-dirs get-lib-dirs #:fail (λ () #f))) - #t)) - -(define mpfr-available? - (let ([val #f]) - (λ () (or val (let ([v (mpfr-available?*)]) - (set! val v) - v))))) +(define (mpfr-available?) + (and gmp-lib mpfr-lib)) ;; =================================================================================================== ;; Parameters: rounding mode, bit precision, printing @@ -285,9 +273,10 @@ (define mpfr-signbit (get-mpfr-fun 'mpfr_signbit (_fun _mpfr-pointer -> _int))) (define mpfr-get-exp (get-mpfr-fun 'mpfr_get_exp (_fun _mpfr-pointer -> _exp_t))) (define mpfr-get-z-2exp - (with-handlers ([exn? (λ _ (get-mpfr-fun 'mpfr_get_z_exp - (_fun _mpz-pointer _mpfr-pointer -> _exp_t)))]) - (get-mpfr-fun 'mpfr_get_z_2exp (_fun _mpz-pointer _mpfr-pointer -> _exp_t)))) + (get-mpfr-fun 'mpfr_get_z_2exp (_fun _mpz-pointer _mpfr-pointer -> _exp_t) + (lambda () + (get-mpfr-fun 'mpfr_get_z_exp + (_fun _mpz-pointer _mpfr-pointer -> _exp_t))))) ;; bigfloat-precision : bigfloat -> integer ;; Returns the maximum number of nonzero bits in the significand. @@ -389,7 +378,7 @@ (define mpfr-get-d (get-mpfr-fun 'mpfr_get_d (_fun _mpfr-pointer _rnd_t -> _double))) (define mpfr-get-z (get-mpfr-fun 'mpfr_get_z (_fun _mpz-pointer _mpfr-pointer _rnd_t -> _int))) (define mpz-get-si (get-mpfr-fun '__gmpz_get_si (_fun _mpz-pointer -> _long))) -(define mpz-fits-long? (get-mpfr-fun '__gmpz_fits_slong_p (_fun _mpz-pointer -> _int))) +(define mpz-fits-long? (get-gmp-fun '__gmpz_fits_slong_p (_fun _mpz-pointer -> _int))) ;; size+limbs->integer : integer (listof integer) -> integer ;; Converts a size (which may be negative) and a limb list into an integer. @@ -534,18 +523,20 @@ (define (bigfloat-custom-write x port mode) (write-string - (cond [(bfzero? x) (if (= 0 (bigfloat-sign x)) "0.bf" "-0.bf")] - [(bfrational? x) - (define str (bigfloat->string x)) - (cond [(regexp-match #rx"\\.|e" str) - (define exp (bigfloat-exponent x)) - (define prec (bigfloat-precision x)) - (if ((abs exp) . > . (* prec 2)) - (format "(bf \"~a\")" str) - (format "(bf #e~a)" str))] - [else (format "(bf ~a)" str)])] - [(bfinfinite? x) (if (= 0 (bigfloat-sign x)) "+inf.bf" "-inf.bf")] - [else "+nan.bf"]) + (if (mpfr-available?) + (cond [(bfzero? x) (if (= 0 (bigfloat-sign x)) "0.bf" "-0.bf")] + [(bfrational? x) + (define str (bigfloat->string x)) + (cond [(regexp-match #rx"\\.|e" str) + (define exp (bigfloat-exponent x)) + (define prec (bigfloat-precision x)) + (if ((abs exp) . > . (* prec 2)) + (format "(bf \"~a\")" str) + (format "(bf #e~a)" str))] + [else (format "(bf ~a)" str)])] + [(bfinfinite? x) (if (= 0 (bigfloat-sign x)) "+inf.bf" "-inf.bf")] + [else "+nan.bf"]) + "#") port)) ;; =================================================================================================== diff --git a/collects/math/scribblings/math-bigfloat.scrbl b/collects/math/scribblings/math-bigfloat.scrbl index 2152cde5a8..7247b24b59 100644 --- a/collects/math/scribblings/math-bigfloat.scrbl +++ b/collects/math/scribblings/math-bigfloat.scrbl @@ -711,9 +711,10 @@ Canonicalizing bigfloats won't change answers computed from them. @section[#:tag "loading"]{Loading the MPFR Library} -@racketmodname[math/bigfloat] depends directly on one library: MPFR, which on the filesystem is -named @tt{libmpfr}. MPFR itself depends on @hyperlink["http://gmplib.org/"]{GMP}, the -GNU Multiple Precision Arithmetic Library, which on the filesystem is named @tt{libgmp}. +The @racketmodname[math/bigfloat] library depends directly on one library: MPFR, which on the filesystem is +named something like @filepath{libmpfr.so}, but with a platform-specific suffix. +MPFR itself depends on @hyperlink["http://gmplib.org/"]{GMP}, the +GNU Multiple Precision Arithmetic Library, which on the filesystem is named @filepath{libgmp.so}. If @racket[(mpfr-available?)] is @racket[#t], both of these libraries have been loaded by the Racket runtime, and everything in @racketmodname[math/bigfloat] should work. @@ -727,29 +728,6 @@ see @racket[set-mpfr-lib-dirs!]. @defproc[(mpfr-available?) Boolean]{ Returns @racket[#t] when both GMP and MPFR are available; @racket[#f] otherwise. -Calling this function will cause Racket's runtime to load @tt{libgmp} and @tt{libmpfr} -if they haven't already been loaded. -} - -@defproc[(get-mpfr-lib-dirs [system (U 'unix 'windows 'macosx)]) - (Listof Path-String)]{ -Returns the extra search paths used to find @tt{libgmp} and @tt{libmpfr}, for the given -@racket[system]. -@examples[#:eval untyped-eval - (get-mpfr-lib-dirs 'macosx)] -} - -@defproc[(set-mpfr-lib-dirs! [system (U 'unix 'windows 'macosx)] - [paths (Listof Path-String)]) - Void]{ -Sets the extra search @racket[paths] used to find @tt{libgmp} and @tt{libmpfr}, for the -given @racket[system], overriding the previous paths. - -If you know that @tt{libmpfr} resides on your system in the directory @racket{}, -but @racket[(mpfr-available?)] returns @racket[#f], try something like the following: -@racketblock[(require math/bigfloat) - (set-mpfr-lib-dirs! (system-type) '("")) - (mpfr-available?)] } @(close-eval untyped-eval) diff --git a/collects/meta/dist-specs.rkt b/collects/meta/dist-specs.rkt index 673f1af398..d0278fbbd1 100644 --- a/collects/meta/dist-specs.rkt +++ b/collects/meta/dist-specs.rkt @@ -583,6 +583,9 @@ plt-extras :+= "uchat/") ; Matthias doesn't want this in now (package: "test-engine/") +;; -------------------- math +dr-extras :+= (package: "math") + ;; -------------------- stepper plt-extras :+= (package: "stepper") diff --git a/collects/scribblings/main/license.scrbl b/collects/scribblings/main/license.scrbl index f44d5059ef..0a16e82503 100644 --- a/collects/scribblings/main/license.scrbl +++ b/collects/scribblings/main/license.scrbl @@ -75,10 +75,17 @@ Racket software includes or extends the following copyrighted material: @copyright{ GNU MP Library - Copyright (c) 1992, 1993, 1994, 1996 + Copyright (c) 1991, 1992, 1993, 1994, 1996, 1999, 2000, 2007 Free Software Foundation, Inc. } +@copyright{ + GNU MPFR Library + Copyright (c) 2000-2012 + Free Software Foundation, Inc. + Contributed by the AriC and Caramel projects, INRIA. +} + @copyright{ GNU lightning Copyright (c) 1994, 1995, 1996, 1999, 2000, 2001, 2002 diff --git a/src/Makefile.in b/src/Makefile.in index 3a3f26afae..f2ef538f58 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -81,6 +81,7 @@ plain-install: install-common-first: mkdir -p $(ALLDIRINFO) + @RUN_RACKET_CGC@ -c "$(srcdir)/get-libs.rkt" math "$(DESTDIR)$(libpltdir)" install-common-middle: $(MAKE) @MAKE_COPYTREE@-run diff --git a/src/get-libs.rkt b/src/get-libs.rkt index 745c49c73b..96295cb209 100644 --- a/src/get-libs.rkt +++ b/src/get-libs.rkt @@ -21,6 +21,23 @@ ["libiconv-2.dll" 1378028] ["libeay32.dll" 1503232] ["ssleay32.dll" 309760]]] + ;; Math Libraries + '[math + [i386-macosx + ["libgmp.10.dylib" 399304] + ["libmpfr.4.dylib" 398552]] + [x86_64-macosx + ["libgmp.10.dylib" 429684] + ["libmpfr.4.dylib" 676320]] + [ppc-macosx + ["libgmp.10.dylib" 387588] + ["libmpfr.4.dylib" 553892]] + [win32/i386 + ["libgmp-10.dll" 394766] + ["libmpfr-4.dll" 411662]] + [win32/x86_64 + ["libgmp-10.dll" 386048] + ["libmpfr-4.dll" 441344]]] ;; GUI Libraries [list 'gui diff --git a/src/mac/README.txt b/src/mac/README.txt index e895fd5869..f12f777544 100644 --- a/src/mac/README.txt +++ b/src/mac/README.txt @@ -9,6 +9,8 @@ Get these packages (or newer, if compatible): libffi-3.0.10.tar.gz [PowerPC: skip] glib-2.31.14.tar.gz [PowerPC: glib-2.22.4.tar.gz] pango-1.29.5.tar.gz [PowerPC: pango-1.28.0.tar.gz] + gmp-5.0.5.tar.gz + mpfr-3.1.1.tar.gz libjpeg62 (maybe in binary form) PSMTabBarControl, probably from @@ -46,6 +48,7 @@ Patches: // can modify the array (which is not allowed) NSArray *copyOfCells = [NSArray arrayWithArray: _cells]; NSEnumerator *enumerator = [copyOfCells objectEnumerator]; + gcc-4.0: gmp/gmp.h:424: __gnu_inline__ => __weak__ Configures (where is some temporary area): pkg-config: --prefix= @@ -59,6 +62,8 @@ Configures (where is some temporary area): add "-lresolv" to link command for "libgio"] Pango: PATH=/bin:... --without-x --with-included-modules=yes --with-dynamic-modules=no --prefix= [PowerPC: same as glib for "libtool"; use PATH for `make', too] + gmp: --prefix= + mpfr: CFLAGS=-I/include LDFLAGS=-L/lib --prefix= To support 10.4, add CC=gcc-4.0 diff --git a/src/mac/install-libs.rkt b/src/mac/install-libs.rkt index ee151107a1..3a94b799a6 100644 --- a/src/mac/install-libs.rkt +++ b/src/mac/install-libs.rkt @@ -20,6 +20,8 @@ "libcairo.2" "libpixman-1.0" "libpng15.15" + "libgmp.10" + "libmpfr.4" "libjpeg.62")) (define (fixup p p-new) diff --git a/src/worksp/build.bat b/src/worksp/build.bat index dc7aa0bf23..4b0c7efd1c 100644 --- a/src/worksp/build.bat +++ b/src/worksp/build.bat @@ -25,6 +25,8 @@ if errorlevel 1 exit /B 1 if errorlevel 1 exit /B 1 ..\..\racket -cu ..\get-libs.rkt com ..\..\lib if errorlevel 1 exit /B 1 +..\..\racket -cu ..\get-libs.rkt math ..\..\lib +if errorlevel 1 exit /B 1 cd mzstart devenv mzstart.sln /Build "Release|%BUILDMODE%"