Skip to content

Commit 9ca0b69

Browse files
committed
Further direct rounding implementation
1 parent ecf1421 commit 9ca0b69

File tree

4 files changed

+178
-83
lines changed

4 files changed

+178
-83
lines changed

mpfr.rkt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@
128128

129129
(define mpfr-set! (get-mpfr-fun 'mpfr_set (_fun _mpfr-pointer _mpfr-pointer _rnd_t -> _void)))
130130

131+
(define mpfr-const-pi! (get-mpfr-fun 'mpfr_const_pi (_fun _mpfr-pointer _rnd_t -> _int)))
132+
133+
(define mpfr-atan2!
134+
(get-mpfr-fun 'mpfr_atan2 (_fun _mpfr-pointer _mpfr-pointer _mpfr-pointer _rnd_t -> _int)))
135+
131136
(define (mpfr-new! prec)
132137
(define bf (make-mpfr 0 0 0 #f))
133138
(mpfr-init2! bf prec)
@@ -332,4 +337,6 @@
332337
mpfr-log!
333338
mpfr-set-prec!
334339
mpfr-new!
335-
mpfr-set!)
340+
mpfr-set!
341+
mpfr-const-pi!
342+
mpfr-atan2!)

ops/core.rkt

Lines changed: 58 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,18 @@
147147
(ormap identity as))
148148

149149
(define (ival-pi)
150-
(ival (endpoint (rnd 'down pi.bf) #f) (endpoint (rnd 'up pi.bf) #f) #f #f))
150+
(define lo (mpfr-new! (bf-precision)))
151+
(define hi (mpfr-new! (bf-precision)))
152+
(mpfr-const-pi! lo 'down)
153+
(mpfr-const-pi! hi 'up)
154+
(ival (endpoint lo #f) (endpoint hi #f) #f #f))
151155

152156
(define (ival-e)
153-
(ival (endpoint (rnd 'down bfexp 1.bf) #f) (endpoint (rnd 'up bfexp 1.bf) #f) #f #f))
157+
(define lo (mpfr-new! (bf-precision)))
158+
(define hi (mpfr-new! (bf-precision)))
159+
(mpfr-exp! lo 1.bf 'down)
160+
(mpfr-exp! hi 1.bf 'up)
161+
(ival (endpoint lo #f) (endpoint hi #f) #f #f))
154162

155163
(define (ival-bool b)
156164
(ival (endpoint b #t) (endpoint b #t) #f #f))
@@ -187,25 +195,29 @@
187195
[(bfnegative? (ival-hi-val x)) -1]
188196
[else 0]))
189197

190-
(define (endpoint-min2 e1 e2)
198+
(define (endpoint-min2 e1 e2 rnd)
191199
(match-define (endpoint x x!) e1)
192200
(match-define (endpoint y y!) e2)
193-
(define out (bfmin2 x y))
201+
(define src (endpoint-val (if (bflte? x y) e1 e2)))
202+
(define out (mpfr-new! (bf-precision)))
203+
(mpfr-set! out src rnd)
194204
(endpoint out (or (and (bf=? out x) x!) (and (bf=? out y) y!))))
195205

196-
(define (endpoint-max2 e1 e2)
206+
(define (endpoint-max2 e1 e2 rnd)
197207
(match-define (endpoint x x!) e1)
198208
(match-define (endpoint y y!) e2)
199-
(define out (bfmax2 x y))
209+
(define src (endpoint-val (if (bfgte? x y) e1 e2)))
210+
(define out (mpfr-new! (bf-precision)))
211+
(mpfr-set! out src rnd)
200212
(endpoint out (or (and (bf=? out x) x!) (and (bf=? out y) y!))))
201213

202214
(define (ival-union x y)
203215
(cond
204216
[(ival-err x) (struct-copy ival y [err? #t])]
205217
[(ival-err y) (struct-copy ival x [err? #t])]
206218
[(bigfloat? (ival-lo-val x))
207-
(ival (rnd 'down endpoint-min2 (ival-lo x) (ival-lo y))
208-
(rnd 'up endpoint-max2 (ival-hi x) (ival-hi y))
219+
(ival (endpoint-min2 (ival-lo x) (ival-lo y) 'down)
220+
(endpoint-max2 (ival-hi x) (ival-hi y) 'up)
209221
(or (ival-err? x) (ival-err? y))
210222
(and (ival-err x) (ival-err y)))]
211223
[(boolean? (ival-lo-val x))
@@ -226,6 +238,13 @@
226238
(define exact? (= 0 (mpfr-fun! out a rnd)))
227239
(endpoint out (and a! exact?)))
228240

241+
(define (epbinary! out mpfr-fun! a-endpoint b-endpoint rnd)
242+
(match-define (endpoint a a!) a-endpoint)
243+
(match-define (endpoint b b!) b-endpoint)
244+
(mpfr-set-prec! out (bf-precision))
245+
(define exact? (= 0 (mpfr-fun! out a b rnd)))
246+
(endpoint out (and a! b! exact?)))
247+
229248
(define ((monotonic-mpfr mpfr-fn!) x)
230249
(match-define (ival lo hi err? err) x)
231250
(define out (new-ival))
@@ -279,7 +298,6 @@
279298
(or xerr? (bflte? xlo lo) (bfgte? xhi hi))
280299
(or xerr (bflte? xhi lo) (bfgte? xlo hi))))
281300

282-
;; TODO: rewrite this for new functions
283301
(define ((overflows-at fn lo hi) x)
284302
(match-define (ival (endpoint xlo xlo!) (endpoint xhi xhi!) xerr? xerr) x)
285303
(match-define (ival (endpoint ylo ylo!) (endpoint yhi yhi!) yerr? yerr) (fn x))
@@ -316,7 +334,6 @@
316334
(f x)))
317335

318336
(define* ival-rint (monotonic-mpfr mpfr-rint!))
319-
;; TODO: move these to monotonic-mpfr
320337
(define* ival-round (monotonic (fix-rounding bfround)))
321338
(define* ival-ceil (monotonic (fix-rounding bfceiling)))
322339
(define* ival-floor (monotonic (fix-rounding bffloor)))
@@ -332,19 +349,26 @@
332349
(define tmp2 (mpfr-new! (bf-precision)))
333350
(define abs-lo (epunary! tmp1 mpfr-abs! (ival-lo x) 'up))
334351
(define abs-hi (epunary! tmp2 mpfr-abs! (ival-hi x) 'up))
335-
(ival (endpoint (bf 0) (and xlo! xhi!)) (endpoint-max2 abs-lo abs-hi) xerr? xerr)]))
352+
(ival (endpoint (bf 0) (and xlo! xhi!)) (endpoint-max2 abs-lo abs-hi 'nearest) xerr? xerr)]))
336353

337354
;; These functions execute ival-fabs and ival-neg with input's precision
338355
(define (ival-max-prec x)
339356
(max (bigfloat-precision (ival-lo-val x)) (bigfloat-precision (ival-hi-val x))))
340357

358+
;; TODO: Cleanup, use begin1
341359
(define (ival-exact-fabs x)
342-
(parameterize ([bf-precision (ival-max-prec x)])
343-
(ival-fabs x)))
360+
(define saved-prec (bf-precision))
361+
(bf-precision (ival-max-prec x))
362+
(define result (ival-fabs x))
363+
(bf-precision saved-prec)
364+
result)
344365

345366
(define (ival-exact-neg x)
346-
(parameterize ([bf-precision (ival-max-prec x)])
347-
(ival-neg x)))
367+
(define saved-prec (bf-precision))
368+
(bf-precision (ival-max-prec x))
369+
(define result (ival-neg x))
370+
(bf-precision saved-prec)
371+
result)
348372

349373
;; Since MPFR has a cap on exponents, no value can be more than twice MAX_VAL
350374
(define exp-overflow-threshold (bfadd (bflog (bfprev +inf.bf)) 1.bf))
@@ -398,7 +422,9 @@
398422
(define err (or (ival-err x) (ival-err y)))
399423

400424
(define (mkatan a b c d)
401-
(ival (rnd 'down epfn bfatan2 a b) (rnd 'up epfn bfatan2 c d) err? err))
425+
(define lo-out (mpfr-new! (bf-precision)))
426+
(define hi-out (mpfr-new! (bf-precision)))
427+
(ival (epbinary! lo-out mpfr-atan2! a b 'down) (epbinary! hi-out mpfr-atan2! c d 'up) err? err))
402428

403429
(match* ((classify-ival-strict x) (classify-ival-strict y))
404430
[(-1 -1) (mkatan yhi xlo ylo xhi)]
@@ -409,19 +435,25 @@
409435
[(0 1) (mkatan ylo xhi ylo xlo)]
410436
[(-1 1) (mkatan yhi xhi ylo xlo)]
411437
[(_ 0)
412-
(ival (endpoint (bfneg (rnd 'up pi.bf)) #f)
413-
(endpoint (rnd 'up pi.bf) #f)
438+
(define pi-int (ival-pi))
439+
(define hi-out (mpfr-new! (bf-precision)))
440+
(define lo-out (mpfr-new! (bf-precision)))
441+
(mpfr-set! hi-out (endpoint-val (ival-hi pi-int)) 'up)
442+
(mpfr-neg! lo-out (endpoint-val (ival-hi pi-int)) 'down)
443+
(ival (endpoint lo-out #f)
444+
(endpoint hi-out #f)
414445
(or err? (bfgte? (ival-hi-val x) 0.bf))
415446
(or err
416447
(and (bfzero? (ival-lo-val x))
417448
(bfzero? (ival-hi-val x))
418449
(bfzero? (ival-lo-val y))
419450
(bfzero? (ival-hi-val y)))))]))
420451

421-
(define*
422-
ival-cosh
423-
(compose (overflows-at (monotonic-mpfr mpfr-cosh!) (bfneg acosh-overflow-threshold) acosh-overflow-threshold)
424-
ival-exact-fabs))
452+
(define* ival-cosh
453+
(compose (overflows-at (monotonic-mpfr mpfr-cosh!)
454+
(bfneg acosh-overflow-threshold)
455+
acosh-overflow-threshold)
456+
ival-exact-fabs))
425457
(define*
426458
ival-sinh
427459
(overflows-at (monotonic-mpfr mpfr-sinh!) (bfneg sinh-overflow-threshold) sinh-overflow-threshold))
@@ -534,14 +566,14 @@
534566
(ival (endpoint lo #f) (endpoint hi #f) err? err))
535567

536568
(define (ival-fmin x y)
537-
(ival (rnd 'down endpoint-min2 (ival-lo x) (ival-lo y))
538-
(rnd 'up endpoint-min2 (ival-hi x) (ival-hi y))
569+
(ival (endpoint-min2 (ival-lo x) (ival-lo y) 'down)
570+
(endpoint-min2 (ival-hi x) (ival-hi y) 'up)
539571
(or (ival-err? x) (ival-err? y))
540572
(or (ival-err x) (ival-err y))))
541573

542574
(define (ival-fmax x y)
543-
(ival (rnd 'down endpoint-max2 (ival-lo x) (ival-lo y))
544-
(rnd 'up endpoint-max2 (ival-hi x) (ival-hi y))
575+
(ival (endpoint-max2 (ival-lo x) (ival-lo y) 'down)
576+
(endpoint-max2 (ival-hi x) (ival-hi y) 'up)
545577
(or (ival-err? x) (ival-err? y))
546578
(or (ival-err x) (ival-err y))))
547579

ops/pow.rkt

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -56,17 +56,17 @@
5656
;; Can't use >=, even though exp2-overflow-threshold is a
5757
;; power of 2, because mpfr-exp is offset by 1 from the real
5858
;; exponent, which matters when we add them.
59+
(define (log2-sum-exceeds-threshold? exponent-value base-value)
60+
(let ([log2-base (mpfr-new! (bf-precision))])
61+
(mpfr-log2! log2-base base-value 'zero)
62+
(> (+ (mpfr-exp exponent-value) (mpfr-exp log2-base))
63+
(mpfr-exp exp2-overflow-threshold))))
64+
5965
(define must-overflow
60-
(and (bfinfinite? hi)
61-
(= (* x-class y-class) 1)
62-
(> (+ (mpfr-exp bval) (mpfr-exp (rnd 'zero bflog2 aval)))
63-
(mpfr-exp exp2-overflow-threshold))))
66+
(and (bfinfinite? hi) (= (* x-class y-class) 1) (log2-sum-exceeds-threshold? bval aval)))
6467

6568
(define must-underflow
66-
(and (bfzero? lo)
67-
(= (* x-class y-class) -1)
68-
(> (+ (mpfr-exp dval) (mpfr-exp (rnd 'zero bflog2 cval)))
69-
(mpfr-exp exp2-overflow-threshold))))
69+
(and (bfzero? lo) (= (* x-class y-class) -1) (log2-sum-exceeds-threshold? dval cval)))
7070

7171
(define real-lo! (or lo! must-underflow (and (bfzero? lo) a! b!)))
7272
(define real-hi! (or hi! must-underflow must-overflow (and (bfinfinite? hi) c! d!)))

0 commit comments

Comments
 (0)