Skip to content
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
54 changes: 45 additions & 9 deletions ops/core.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@
ival-==
ival-!=
ival-if
ival-mobilize
ival-and
ival-or
ival-not
Expand Down Expand Up @@ -661,27 +662,62 @@
(ival (endpoint lo #f) (endpoint hi #f) err? err))

(define (ival-fmin x y)
(ival (endpoint-min2 (ival-lo x) (ival-lo y) 'down)
(endpoint-min2 (ival-hi x) (ival-hi y) 'up)
(or (ival-err? x) (ival-err? y))
(or (ival-err x) (ival-err y))))
(match-define (ival (endpoint xlo xlo!) (endpoint xhi xhi!) xerr? xerr) x)
(match-define (ival (endpoint ylo ylo!) (endpoint yhi yhi!) yerr? yerr) y)
(define lo (bf 0))
(define hi (bf 0))
(define lo-exact? (= 0 (mpfr-min! lo xlo ylo 'down)))
(define hi-exact? (= 0 (mpfr-min! hi xhi yhi 'up)))
;; For lower endpoints (which can only move upward under refinement),
;; a fixed minimum is stable if one fixed endpoint is <= the other.
(define lo-stable?
(cond
[(and xlo! ylo!) #t]
[xlo! (bflte? xlo ylo)]
[ylo! (bflte? ylo xlo)]
[else #f]))
(define lo! (and lo-exact? lo-stable?))
;; For upper endpoints (which can only move downward), a fixed minimum is
;; only guaranteed when both endpoints are fixed.
(define hi! (and hi-exact? xhi! yhi!))
(ival (endpoint lo lo!) (endpoint hi hi!) (or xerr? yerr?) (or xerr yerr)))

(define (ival-fmax x y)
(ival (endpoint-max2 (ival-lo x) (ival-lo y) 'down)
(endpoint-max2 (ival-hi x) (ival-hi y) 'up)
(or (ival-err? x) (ival-err? y))
(or (ival-err x) (ival-err y))))
(match-define (ival (endpoint xlo xlo!) (endpoint xhi xhi!) xerr? xerr) x)
(match-define (ival (endpoint ylo ylo!) (endpoint yhi yhi!) yerr? yerr) y)
(define lo (bf 0))
(define hi (bf 0))
(define lo-exact? (= 0 (mpfr-max! lo xlo ylo 'down)))
(define hi-exact? (= 0 (mpfr-max! hi xhi yhi 'up)))
;; For lower endpoints (which can only move upward), a fixed maximum is
;; only guaranteed when both endpoints are fixed.
(define lo! (and lo-exact? xlo! ylo!))
;; For upper endpoints (which can only move downward), a fixed maximum is
;; stable if one fixed endpoint is >= the other.
(define hi-stable?
(cond
[(and xhi! yhi!) #t]
[xhi! (bfgte? xhi yhi)]
[yhi! (bfgte? yhi xhi)]
[else #f]))
(define hi! (and hi-exact? hi-stable?))
(ival (endpoint lo lo!) (endpoint hi hi!) (or xerr? yerr?) (or xerr yerr)))

(define (ival-copysign x y)
(match-define (ival xlo xhi xerr? xerr) (ival-fabs x))
(define can-zero (or (bfzero? (ival-lo-val y)) (bfzero? (ival-hi-val y))))
;; 0 is both positive and negative because we don't handle signed zero well
(define can-neg (or (= (mpfr-sign (ival-lo-val y)) -1) can-zero))
(define can-pos (or (= (mpfr-sign (ival-hi-val y)) 1) can-zero))
(define sign-immovable? (and can-neg can-pos (ival-lo-fixed? y) (ival-hi-fixed? y)))
(define err? (or (ival-err? y) xerr?))
(define err (or (ival-err y) xerr))
(match* (can-neg can-pos)
[(#t #t) (ival (rnd 'down epunary bfneg xhi) (rnd 'up epunary bfcopy xhi) err? err)]
[(#t #t)
(define out (ival (rnd 'down epunary bfneg xhi) (rnd 'up epunary bfcopy xhi) err? err))
(if sign-immovable?
out
(ival-mobilize out))]
[(#t #f) (ival (rnd 'down epunary bfneg xhi) (rnd 'up epunary bfneg xlo) err? err)]
[(#f #t) (ival xlo xhi err? err)]
[(#f #f)
Expand Down
7 changes: 6 additions & 1 deletion ops/pow.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -161,4 +161,9 @@
[(or (= (mpfr-sign (ival-lo-val x)) 1) (bfzero? (ival-lo-val x))) (ival-pow-pos x y)]
[else
(define-values (neg pos) (split-ival x 0.bf))
(ival-union (ival-pow-neg neg y) (ival-pow-pos pos y))]))
(define out (ival-union (ival-pow-neg neg y) (ival-pow-pos pos y)))
;; If x straddles 0 with movable endpoints, a refinement can drop one
;; branch entirely, so branch-derived endpoint fixedness is not stable.
(if (and (ival-lo-fixed? x) (ival-hi-fixed? x))
out
(ival-mobilize out))]))
5 changes: 4 additions & 1 deletion test.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,10 @@
(with-check-info (['split-argument k] ['ilo ilo] ['ihi ihi] ['iylo iylo] ['iyhi iyhi])
(check-ival-equals? iy
(parameterize ([bf-precision out-prec])
(ival-union iylo iyhi))))))
(ival-union iylo iyhi)))
;; Refining an input argument should refine the output.
(check ival-refines? iy iylo)
(check ival-refines? iy iyhi))))
(when (or (ival-lo-fixed? iy) (ival-hi-fixed? iy))
(define iy*
(parameterize ([bf-precision 128])
Expand Down