Skip to content

Commit 16b8d81

Browse files
authored
Merge pull request #3 from bksaiki/fix-ordinal
Fix ordinal (again)
2 parents a8192f9 + 6143d0b commit 16b8d81

File tree

4 files changed

+75
-80
lines changed

4 files changed

+75
-80
lines changed

private/ffi.rkt

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -146,17 +146,6 @@
146146
(mpfr-subnormalize r t (mpfr-rounding-mode)))
147147
r)
148148

149-
(define mpfr-sum-fun
150-
(get-mpfr-fun 'mpfr_sum (_fun _mpfr-pointer (_list i _mpfr-pointer) _ulong _rnd_t -> _int)))
151-
152-
(define (mpfr-sum xs)
153-
(define r (bf 0))
154-
(define t (mpfr-sum-fun r xs (length xs) (mpfr-rounding-mode)))
155-
(mpfr-check-range r 0 (mpfr-rounding-mode))
156-
(when (mpfr-subnormalize?)
157-
(mpfr-subnormalize r t (mpfr-rounding-mode)))
158-
r)
159-
160149
(define (mpfr-set x)
161150
(define v (if (bigfloat? x) (bfcopy x) (bf x)))
162151
(mpfr-check-range v 0 (mpfr-rounding-mode))

private/gfl.rkt

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,9 @@
7575
(gfl-exponent) (gfl-bits)))
7676

7777
(define (gfl->ordinal x)
78-
(define sig (- (gfl-bits) (gfl-exponent)))
78+
(define sig (- (gflonum-nb x) (gflonum-ex x)))
7979
(define-values (emin emax) (ex->ebounds (gflonum-ex x) sig))
80-
((mpfr-eval emin emax sig) (curryr mpfr->ordinal (gfl-exponent) sig) (gflonum-val x)))
80+
((mpfr-eval emin emax sig) (curryr mpfr->ordinal (gflonum-ex x) sig) (gflonum-val x)))
8181

8282
(define (string->gfl x)
8383
(define sig (- (gfl-bits) (gfl-exponent)))
@@ -279,66 +279,63 @@
279279

280280
;;;;;;;;;;;;;;;;;;; Variadic operators ;;;;;;;;;;;;;;;;
281281

282-
(define (mpfrv+ emin emax sig . xs)
283-
(cond
284-
[(null? xs) 0.bf]
285-
[else
286-
(define xs1 (cdr xs))
287-
(cond
288-
[(null? xs1) (car xs)]
289-
[else
290-
(define xs2 (cdr xs1))
291-
(cond
292-
[(null? xs2) ((mpfr-eval emin emax sig) mpfr-add (car xs) (car xs1))]
293-
[else ((mpfr-eval emin emax sig) mpfr-sum xs)])])]))
294-
295-
(define (mpfrv- emin emax sig x . xs)
296-
(cond
297-
[(null? xs) (mpfr-neg x)]
298-
[(null? (cdr xs)) ((mpfr-eval emin emax sig) mpfr-sub x (car xs))]
299-
[else (mpfr-neg (apply mpfrv+ emin emax sig (mpfr-neg x) xs))]))
300-
301-
(define (mpfrv* emin emax sig . xs)
302-
(cond
303-
[(null? xs) 1.bf]
304-
[else
305-
(let loop ([x (car xs)] [xs (cdr xs)])
306-
(cond
307-
[(null? xs) x]
308-
[else (loop ((mpfr-eval emin emax sig) mpfr-mul x (car xs)) (cdr xs))]))]))
309-
310-
(define (mpfrv/ emin emax sig x . xs)
311-
(cond
312-
[(null? xs) ((mpfr-eval emin emax sig) mpfr-div 1.bf x)]
313-
[else
314-
(let loop ([x x] [xs xs])
315-
(cond
316-
[(null? xs) x]
317-
[else (loop ((mpfr-eval emin emax sig) mpfr-div x (car xs)) (cdr xs))]))]))
282+
(define (mpfrv+ . xs)
283+
(match xs
284+
[(list) 0.bf]
285+
[(list x) (bfcopy x)]
286+
[(list x y rest ...)
287+
(for/fold ([sum (mpfr-add x y)]) ([z (in-list rest)])
288+
(mpfr-add sum z))]))
289+
290+
(define (mpfrv- x . xs)
291+
(match xs
292+
[(list) (mpfr-neg x)]
293+
[(list y rest ...)
294+
(for/fold ([diff (mpfr-sub x y)]) ([z (in-list rest)])
295+
(mpfr-sub diff z))]))
296+
297+
(define (mpfrv* . xs)
298+
(match xs
299+
[(list) 1.bf]
300+
[(list x) (bfcopy x)]
301+
[(list x y rest ...)
302+
(for/fold ([prod (mpfr-mul x y)]) ([z (in-list rest)])
303+
(mpfr-mul prod z))]))
304+
305+
(define (mpfrv/ x . xs)
306+
(match xs
307+
[(list) (mpfr-div 1.bf x)]
308+
[(list y rest ...)
309+
(for/fold ([quo (mpfr-div x y)]) ([z (in-list rest)])
310+
(mpfr-div quo z))]))
318311

319312
(define (gfl+ . args)
320313
(define sig (- (gfl-bits) (gfl-exponent)))
321314
(define-values (emin emax) (ex->ebounds (gfl-exponent) sig))
322-
(gflonum (apply mpfrv+ emin emax sig (map gflonum-val args))
323-
(gfl-exponent) (gfl-bits)))
315+
(gflonum (apply (mpfr-eval emin emax sig) mpfrv+ (map gflonum-val args))
316+
(gfl-exponent)
317+
(gfl-bits)))
324318

325319
(define (gfl- head . rest)
326320
(define sig (- (gfl-bits) (gfl-exponent)))
327321
(define-values (emin emax) (ex->ebounds (gfl-exponent) sig))
328-
(gflonum (apply mpfrv- emin emax sig (gflonum-val head) (map gflonum-val rest))
329-
(gfl-exponent) (gfl-bits)))
322+
(gflonum (apply (mpfr-eval emin emax sig) mpfrv- (gflonum-val head) (map gflonum-val rest))
323+
(gfl-exponent)
324+
(gfl-bits)))
330325

331326
(define (gfl* . args)
332327
(define sig (- (gfl-bits) (gfl-exponent)))
333328
(define-values (emin emax) (ex->ebounds (gfl-exponent) sig))
334-
(gflonum (apply mpfrv* emin emax sig (map gflonum-val args))
335-
(gfl-exponent) (gfl-bits)))
329+
(gflonum (apply (mpfr-eval emin emax sig) mpfrv* (map gflonum-val args))
330+
(gfl-exponent)
331+
(gfl-bits)))
336332

337333
(define (gfl/ head . rest)
338334
(define sig (- (gfl-bits) (gfl-exponent)))
339335
(define-values (emin emax) (ex->ebounds (gfl-exponent) sig))
340-
(gflonum (apply mpfrv/ emin emax sig (gflonum-val head) (map gflonum-val rest))
341-
(gfl-exponent) (gfl-bits)))
336+
(gflonum (apply (mpfr-eval emin emax sig) mpfrv/ (gflonum-val head) (map gflonum-val rest))
337+
(gfl-exponent)
338+
(gfl-bits)))
342339

343340
(define (gflmax2 x y)
344341
(cond

private/mpfr.rkt

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
mpfr-lgamma
1212
mpfr-jn
1313
mpfr-yn
14-
mpfr-sum
1514
mpfr-set
1615
mpfr-set-ebounds!)
1716

@@ -104,46 +103,55 @@
104103
(define (infinite-ordinal es sig)
105104
(arithmetic-shift (sub1 (expt 2 es)) (sub1 sig)))
106105

107-
(define (ordinal->mpfr x es sig)
108-
(define bound (invalid-ordinal es sig))
106+
(define (ordinal->mpfr x es p)
107+
(define bound (invalid-ordinal es p))
109108
(unless (< (- bound) x bound)
110109
(error 'ordinal->mpfr "ordinal out of bounds ~a" x))
111110
(let loop ([x x])
112111
(cond
113112
[(zero? x) 0.bf]
114113
[(negative? x) (bf- (loop (- x)))]
115-
[(> x (infinite-ordinal es sig)) +nan.bf]
116-
[(= x (infinite-ordinal es sig)) +inf.bf]
114+
[(> x (infinite-ordinal es p)) +nan.bf]
115+
[(= x (infinite-ordinal es p)) +inf.bf]
117116
[else ; non-zero, real number
118-
(define msize (sub1 sig))
119117
(define expmin (sub1 (mpfr-get-emin)))
120-
(define ebits (arithmetic-shift x (- msize)))
121-
(define mbits (bitwise-and x (sub1 (expt 2 msize))))
118+
(define mask (sub1 (expt 2 (sub1 p))))
119+
(define mbits (bitwise-and x mask))
120+
(define ebits (arithmetic-shift x (- (sub1 p))))
122121
(cond
123122
[(zero? ebits) ; subnormal
124123
(bf mbits expmin)]
125124
[else ; normal number
126-
(define c (+ (expt 2 msize) mbits))
125+
(define c (+ (expt 2 (sub1 p)) mbits))
127126
(define exp (+ (sub1 ebits) expmin))
128127
(bf c exp)])])))
129128

130-
(define (mpfr->ordinal x es sig)
129+
(define (mpfr->ordinal x es p)
131130
(let loop ([x x])
132131
(cond
133132
[(bfzero? x) 0]
134133
[(bfnegative? x) (- (loop (bf- x)))]
135-
[(bfnan? x) (add1 (infinite-ordinal es sig))]
136-
[(bfinfinite? x) (infinite-ordinal es sig)]
134+
[(bfnan? x) (add1 (infinite-ordinal es p))]
135+
[(bfinfinite? x) (infinite-ordinal es p)]
137136
[else
138-
(define-values (c exp) (bigfloat->sig+exp x))
139-
(define e (+ exp (bigfloat-precision x) -1))
137+
; format constants
138+
; with subnormalization MPFR's emin is not what you think it is
140139
(define expmin (sub1 (mpfr-get-emin)))
141-
(define emin (+ expmin sig -1))
140+
(define emin (+ expmin p -1))
141+
; extract fields
142+
; per MPFR documentation, `mpfr_get_z_2exp(x)` extracts the integer
143+
; using the (full) initialization precision of `x`.
144+
(define-values (c exp) (bigfloat->sig+exp x))
145+
(define e (+ exp (sub1 p)))
142146
(cond
143-
[(< e emin) ; subnormal
144-
(define shift (- exp expmin))
145-
(arithmetic-shift c shift)]
146-
[else ; normal
147-
(define ebits (add1 (- exp expmin)))
148-
(define mbits (bitwise-and c (sub1 (expt 2 (sub1 sig)))))
149-
(+ (arithmetic-shift ebits (sub1 sig)) mbits)])])))
147+
[(< e emin)
148+
; subnormal number
149+
; since `x` is fully normalized `exp < expmin`
150+
(define shift (- expmin exp))
151+
(arithmetic-shift c (- shift))]
152+
[else
153+
; normal number
154+
(define mask (sub1 (expt 2 (sub1 p))))
155+
(define mbits (bitwise-and mask c))
156+
(define ebits (add1 (- e emin)))
157+
(+ (arithmetic-shift ebits (sub1 p)) mbits)])])))

tests/test.rkt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@
101101
; (check-equal? (gfl- 0.gfl) -0.gfl)
102102
; (check-equal? (gfl- -0.gfl) 0.gfl)
103103

104-
(for ([bits '(13 15 29 27 43 75 139 14 16 18 22 24 140)])
104+
; (for ([bits '(13 15 29 27 43 75 139 14 16 18 22 24 140)])
105+
(for ([bits '(13)])
105106
(parameterize ([gfl-bits bits])
106107
;; +max.gfl/-max.gfl
107108
; (check-equal? (gfl- +max.gfl) -max.gfl)

0 commit comments

Comments
 (0)