Skip to content

Commit 6699412

Browse files
authored
Merge pull request #138 from herbie-fp/direct-rounding-pow
Direct rounding for `ival-pow` and `ival-pow2`
2 parents fc97a4b + c4c1986 commit 6699412

File tree

3 files changed

+43
-34
lines changed

3 files changed

+43
-34
lines changed

mpfr.rkt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@
138138
(define mpfr-atan2!
139139
(get-mpfr-fun 'mpfr_atan2 (_fun _mpfr-pointer _mpfr-pointer _mpfr-pointer _rnd_t -> _int)))
140140

141+
(define mpfr-pow2! (get-mpfr-fun 'mpfr_sqr (_fun _mpfr-pointer _mpfr-pointer _rnd_t -> _int)))
142+
141143
(define mpfr-set! (get-mpfr-fun 'mpfr_set (_fun _mpfr-pointer _mpfr-pointer _rnd_t -> _void)))
142144

143145
(define mpfr-set-prec! set-mpfr-prec!)
@@ -346,5 +348,6 @@
346348
mpfr-log!
347349
mpfr-const-pi!
348350
mpfr-atan2!
351+
mpfr-pow2!
349352
mpfr-set-prec!
350353
mpfr-set!)

ops/core.rkt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@
3232
ival-union
3333
ival-split
3434
(rename-out [monotonic monotonic->ival] [comonotonic comonotonic->ival])
35+
define*
36+
immutable
37+
monotonic-mpfr!
38+
comonotonic-mpfr!
39+
monotonic-mpfr
40+
comonotonic-mpfr
3541
ival-illegal
3642
ival-pi
3743
ival-e

ops/pow.rkt

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@
1313
[(and (< (mpfr-exp (ival-hi-val x)) 1) (not (bfinfinite? (ival-hi-val x)))) -1]
1414
[else 0]))
1515

16-
(define (eppow a a! b b! a-class b-class)
17-
(when (bfzero? a)
18-
(set! a 0.bf)) ; Handle (-0)^(-1)
19-
(define-values (val exact?) (bf-return-exact? bfexpt (list a b)))
20-
(values val
16+
(define (eppow! out a a! b b! a-class b-class rnd)
17+
(define base (if (bfzero? a) 0.bf a)) ; Handle (-0)^(-1)
18+
(mpfr-set-prec! out (bf-precision))
19+
(define exact? (= 0 (mpfr-pow! out base b rnd)))
20+
(values out
2121
(or (and a! b! exact?)
22-
(and a! (bf=? a 1.bf))
23-
(and a! (bfzero? a) (not (= b-class 0)))
24-
(and a! (bfinfinite? a) (not (= b-class 0)))
22+
(and a! (bf=? base 1.bf))
23+
(and a! (bfzero? base) (not (= b-class 0)))
24+
(and a! (bfinfinite? base) (not (= b-class 0)))
2525
(and b! (bfzero? b))
2626
(and b! (bfinfinite? b) (not (= a-class 0))))))
2727

@@ -39,24 +39,25 @@
3939
(define y-class (classify-ival y))
4040

4141
(define (mk-pow a b c d)
42+
(define out (new-ival (bf-precision)))
4243
(define-values (lo lo!)
43-
(rnd 'down
44-
eppow
45-
(endpoint-val a)
46-
(endpoint-immovable? a)
47-
(endpoint-val b)
48-
(endpoint-immovable? b)
49-
x-class
50-
y-class))
44+
(eppow! (ival-lo-val out)
45+
(endpoint-val a)
46+
(endpoint-immovable? a)
47+
(endpoint-val b)
48+
(endpoint-immovable? b)
49+
x-class
50+
y-class
51+
'down))
5152
(define-values (hi hi!)
52-
(rnd 'up
53-
eppow
54-
(endpoint-val c)
55-
(endpoint-immovable? c)
56-
(endpoint-val d)
57-
(endpoint-immovable? d)
58-
x-class
59-
y-class))
53+
(eppow! (ival-hi-val out)
54+
(endpoint-val c)
55+
(endpoint-immovable? c)
56+
(endpoint-val d)
57+
(endpoint-immovable? d)
58+
x-class
59+
y-class
60+
'up))
6061

6162
(define-values (real-lo! real-hi!)
6263
(cond
@@ -69,17 +70,16 @@
6970
;; Can't use >=, even though exp2-overflow-threshold is a
7071
;; power of 2, because mpfr-exp is offset by 1 from the real
7172
;; exponent, which matters when we add them.
73+
(define log2-base (bf 0))
74+
(define (log2-sum-exceeds-threshold? exponent-value base-value)
75+
(mpfr-log2! log2-base base-value 'zero)
76+
(> (+ (mpfr-exp exponent-value) (mpfr-exp log2-base)) (mpfr-exp exp2-overflow-threshold)))
77+
7278
(define must-overflow
73-
(and (bfinfinite? hi)
74-
(= (* x-class y-class) 1)
75-
(> (+ (mpfr-exp bval) (mpfr-exp (rnd 'zero bflog2 aval)))
76-
(mpfr-exp exp2-overflow-threshold))))
79+
(and (bfinfinite? hi) (= (* x-class y-class) 1) (log2-sum-exceeds-threshold? bval aval)))
7780

7881
(define must-underflow
79-
(and (bfzero? lo)
80-
(= (* x-class y-class) -1)
81-
(> (+ (mpfr-exp dval) (mpfr-exp (rnd 'zero bflog2 cval)))
82-
(mpfr-exp exp2-overflow-threshold))))
82+
(and (bfzero? lo) (= (* x-class y-class) -1) (log2-sum-exceeds-threshold? dval cval)))
8383

8484
(define real-lo! (or lo! must-underflow (and (bfzero? lo) a! b!)))
8585
(define real-hi! (or hi! must-underflow must-overflow (and (bfinfinite? hi) c! d!)))
@@ -152,8 +152,8 @@
152152
(let ([pospow (ival-pow-pos (ival-exact-fabs x) y)])
153153
(ival-then (ival-assert ival-maybe) (ival-union (ival-neg pospow) pospow)))))
154154

155-
(define (ival-pow2 x)
156-
((monotonic->ival (lambda (x) (bfmul x x))) (ival-pre-fabs x)))
155+
(define* ival-pow2! (lambda (out x) ((monotonic-mpfr! mpfr-pow2!) out (ival-pre-fabs x))))
156+
(define* ival-pow2 (immutable ival-pow2!))
157157

158158
(define (ival-pow x y)
159159
(cond

0 commit comments

Comments
 (0)