Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ordinal (again) #3

Merged
merged 3 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 0 additions & 11 deletions private/ffi.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -146,17 +146,6 @@
(mpfr-subnormalize r t (mpfr-rounding-mode)))
r)

(define mpfr-sum-fun
(get-mpfr-fun 'mpfr_sum (_fun _mpfr-pointer (_list i _mpfr-pointer) _ulong _rnd_t -> _int)))

(define (mpfr-sum xs)
(define r (bf 0))
(define t (mpfr-sum-fun r xs (length xs) (mpfr-rounding-mode)))
(mpfr-check-range r 0 (mpfr-rounding-mode))
(when (mpfr-subnormalize?)
(mpfr-subnormalize r t (mpfr-rounding-mode)))
r)

(define (mpfr-set x)
(define v (if (bigfloat? x) (bfcopy x) (bf x)))
(mpfr-check-range v 0 (mpfr-rounding-mode))
Expand Down
89 changes: 43 additions & 46 deletions private/gfl.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -75,9 +75,9 @@
(gfl-exponent) (gfl-bits)))

(define (gfl->ordinal x)
(define sig (- (gfl-bits) (gfl-exponent)))
(define sig (- (gflonum-nb x) (gflonum-ex x)))
(define-values (emin emax) (ex->ebounds (gflonum-ex x) sig))
((mpfr-eval emin emax sig) (curryr mpfr->ordinal (gfl-exponent) sig) (gflonum-val x)))
((mpfr-eval emin emax sig) (curryr mpfr->ordinal (gflonum-ex x) sig) (gflonum-val x)))

(define (string->gfl x)
(define sig (- (gfl-bits) (gfl-exponent)))
Expand Down Expand Up @@ -279,66 +279,63 @@

;;;;;;;;;;;;;;;;;;; Variadic operators ;;;;;;;;;;;;;;;;

(define (mpfrv+ emin emax sig . xs)
(cond
[(null? xs) 0.bf]
[else
(define xs1 (cdr xs))
(cond
[(null? xs1) (car xs)]
[else
(define xs2 (cdr xs1))
(cond
[(null? xs2) ((mpfr-eval emin emax sig) mpfr-add (car xs) (car xs1))]
[else ((mpfr-eval emin emax sig) mpfr-sum xs)])])]))

(define (mpfrv- emin emax sig x . xs)
(cond
[(null? xs) (mpfr-neg x)]
[(null? (cdr xs)) ((mpfr-eval emin emax sig) mpfr-sub x (car xs))]
[else (mpfr-neg (apply mpfrv+ emin emax sig (mpfr-neg x) xs))]))

(define (mpfrv* emin emax sig . xs)
(cond
[(null? xs) 1.bf]
[else
(let loop ([x (car xs)] [xs (cdr xs)])
(cond
[(null? xs) x]
[else (loop ((mpfr-eval emin emax sig) mpfr-mul x (car xs)) (cdr xs))]))]))

(define (mpfrv/ emin emax sig x . xs)
(cond
[(null? xs) ((mpfr-eval emin emax sig) mpfr-div 1.bf x)]
[else
(let loop ([x x] [xs xs])
(cond
[(null? xs) x]
[else (loop ((mpfr-eval emin emax sig) mpfr-div x (car xs)) (cdr xs))]))]))
(define (mpfrv+ . xs)
(match xs
[(list) 0.bf]
[(list x) (bfcopy x)]
[(list x y rest ...)
(for/fold ([sum (mpfr-add x y)]) ([z (in-list rest)])
(mpfr-add sum z))]))

(define (mpfrv- x . xs)
(match xs
[(list) (mpfr-neg x)]
[(list y rest ...)
(for/fold ([diff (mpfr-sub x y)]) ([z (in-list rest)])
(mpfr-sub diff z))]))

(define (mpfrv* . xs)
(match xs
[(list) 1.bf]
[(list x) (bfcopy x)]
[(list x y rest ...)
(for/fold ([prod (mpfr-mul x y)]) ([z (in-list rest)])
(mpfr-mul prod z))]))

(define (mpfrv/ x . xs)
(match xs
[(list) (mpfr-div 1.bf x)]
[(list y rest ...)
(for/fold ([quo (mpfr-div x y)]) ([z (in-list rest)])
(mpfr-div quo z))]))

(define (gfl+ . args)
(define sig (- (gfl-bits) (gfl-exponent)))
(define-values (emin emax) (ex->ebounds (gfl-exponent) sig))
(gflonum (apply mpfrv+ emin emax sig (map gflonum-val args))
(gfl-exponent) (gfl-bits)))
(gflonum (apply (mpfr-eval emin emax sig) mpfrv+ (map gflonum-val args))
(gfl-exponent)
(gfl-bits)))

(define (gfl- head . rest)
(define sig (- (gfl-bits) (gfl-exponent)))
(define-values (emin emax) (ex->ebounds (gfl-exponent) sig))
(gflonum (apply mpfrv- emin emax sig (gflonum-val head) (map gflonum-val rest))
(gfl-exponent) (gfl-bits)))
(gflonum (apply (mpfr-eval emin emax sig) mpfrv- (gflonum-val head) (map gflonum-val rest))
(gfl-exponent)
(gfl-bits)))

(define (gfl* . args)
(define sig (- (gfl-bits) (gfl-exponent)))
(define-values (emin emax) (ex->ebounds (gfl-exponent) sig))
(gflonum (apply mpfrv* emin emax sig (map gflonum-val args))
(gfl-exponent) (gfl-bits)))
(gflonum (apply (mpfr-eval emin emax sig) mpfrv* (map gflonum-val args))
(gfl-exponent)
(gfl-bits)))

(define (gfl/ head . rest)
(define sig (- (gfl-bits) (gfl-exponent)))
(define-values (emin emax) (ex->ebounds (gfl-exponent) sig))
(gflonum (apply mpfrv/ emin emax sig (gflonum-val head) (map gflonum-val rest))
(gfl-exponent) (gfl-bits)))
(gflonum (apply (mpfr-eval emin emax sig) mpfrv/ (gflonum-val head) (map gflonum-val rest))
(gfl-exponent)
(gfl-bits)))

(define (gflmax2 x y)
(cond
Expand Down
52 changes: 30 additions & 22 deletions private/mpfr.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
mpfr-lgamma
mpfr-jn
mpfr-yn
mpfr-sum
mpfr-set
mpfr-set-ebounds!)

Expand Down Expand Up @@ -104,46 +103,55 @@
(define (infinite-ordinal es sig)
(arithmetic-shift (sub1 (expt 2 es)) (sub1 sig)))

(define (ordinal->mpfr x es sig)
(define bound (invalid-ordinal es sig))
(define (ordinal->mpfr x es p)
(define bound (invalid-ordinal es p))
(unless (< (- bound) x bound)
(error 'ordinal->mpfr "ordinal out of bounds ~a" x))
(let loop ([x x])
(cond
[(zero? x) 0.bf]
[(negative? x) (bf- (loop (- x)))]
[(> x (infinite-ordinal es sig)) +nan.bf]
[(= x (infinite-ordinal es sig)) +inf.bf]
[(> x (infinite-ordinal es p)) +nan.bf]
[(= x (infinite-ordinal es p)) +inf.bf]
[else ; non-zero, real number
(define msize (sub1 sig))
(define expmin (sub1 (mpfr-get-emin)))
(define ebits (arithmetic-shift x (- msize)))
(define mbits (bitwise-and x (sub1 (expt 2 msize))))
(define mask (sub1 (expt 2 (sub1 p))))
(define mbits (bitwise-and x mask))
(define ebits (arithmetic-shift x (- (sub1 p))))
(cond
[(zero? ebits) ; subnormal
(bf mbits expmin)]
[else ; normal number
(define c (+ (expt 2 msize) mbits))
(define c (+ (expt 2 (sub1 p)) mbits))
(define exp (+ (sub1 ebits) expmin))
(bf c exp)])])))

(define (mpfr->ordinal x es sig)
(define (mpfr->ordinal x es p)
(let loop ([x x])
(cond
[(bfzero? x) 0]
[(bfnegative? x) (- (loop (bf- x)))]
[(bfnan? x) (add1 (infinite-ordinal es sig))]
[(bfinfinite? x) (infinite-ordinal es sig)]
[(bfnan? x) (add1 (infinite-ordinal es p))]
[(bfinfinite? x) (infinite-ordinal es p)]
[else
(define-values (c exp) (bigfloat->sig+exp x))
(define e (+ exp (bigfloat-precision x) -1))
; format constants
; with subnormalization MPFR's emin is not what you think it is
(define expmin (sub1 (mpfr-get-emin)))
(define emin (+ expmin sig -1))
(define emin (+ expmin p -1))
; extract fields
; per MPFR documentation, `mpfr_get_z_2exp(x)` extracts the integer
; using the (full) initialization precision of `x`.
(define-values (c exp) (bigfloat->sig+exp x))
(define e (+ exp (sub1 p)))
(cond
[(< e emin) ; subnormal
(define shift (- exp expmin))
(arithmetic-shift c shift)]
[else ; normal
(define ebits (add1 (- exp expmin)))
(define mbits (bitwise-and c (sub1 (expt 2 (sub1 sig)))))
(+ (arithmetic-shift ebits (sub1 sig)) mbits)])])))
[(< e emin)
; subnormal number
; since `x` is fully normalized `exp < expmin`
(define shift (- expmin exp))
(arithmetic-shift c (- shift))]
[else
; normal number
(define mask (sub1 (expt 2 (sub1 p))))
(define mbits (bitwise-and mask c))
(define ebits (add1 (- e emin)))
(+ (arithmetic-shift ebits (sub1 p)) mbits)])])))
3 changes: 2 additions & 1 deletion tests/test.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,8 @@
; (check-equal? (gfl- 0.gfl) -0.gfl)
; (check-equal? (gfl- -0.gfl) 0.gfl)

(for ([bits '(13 15 29 27 43 75 139 14 16 18 22 24 140)])
; (for ([bits '(13 15 29 27 43 75 139 14 16 18 22 24 140)])
(for ([bits '(13)])
(parameterize ([gfl-bits bits])
;; +max.gfl/-max.gfl
; (check-equal? (gfl- +max.gfl) -max.gfl)
Expand Down
Loading