@@ -469,29 +469,33 @@ urem a b
469
469
(ql, rl) = al `divMod` max 1 bh -- assume that division by 0 does not happen
470
470
(qh, rh) = ah `divMod` max 1 bl -- assume that division by 0 does not happen
471
471
472
- -- | Least and greatest nonzero values in a domain, according to the
473
- -- unsigned ordering.
474
- rbounds :: BVDomain w -> (Integer , Integer )
475
- rbounds a =
472
+ -- | Pairs of nonzero integers @(lo, hi)@ such that @1\/lo <= 1\/hi@.
473
+ -- This pair represents the set of all nonzero integers @x@ such that
474
+ -- @1\/lo <= 1\/x <= 1\/hi@.
475
+ data ReciprocalRange = ReciprocalRange Integer Integer
476
+
477
+ -- | Nonzero signed values in a domain with the least and greatest
478
+ -- reciprocals.
479
+ rbounds :: (1 <= w ) => NatRepr w -> BVDomain w -> ReciprocalRange
480
+ rbounds w a =
476
481
case a of
477
- BVDAny mask -> ( 1 , mask)
482
+ BVDAny _ -> ReciprocalRange ( - 1 ) 1
478
483
BVDInterval mask al aw
479
- | ah > mask + 1 -> (1 , mask)
480
- | otherwise -> (max 1 al, min mask aw)
481
- where ah = al + aw
484
+ | ah > mask + 1 -> ReciprocalRange (- 1 ) 1
485
+ | otherwise -> ReciprocalRange (signed (min mask ah)) (signed (max 1 al))
486
+ where
487
+ ah = al + aw
488
+ signed x = if x < halfRange w then x else x - (mask + 1 )
482
489
483
490
-- | Interval arithmetic for integer division (rounding towards 0).
484
- -- The argument ranges @(al, ah)@ and @(bl, bh)@ should satisfy @al <=
485
- -- ah@ and @1\/bl >= 1\/bh@. That is, if @bl@ and @bh@ have the same
486
- -- sign, then we require @bl <= bh@, but if they have opposite signs
487
- -- then we require @bl > bh@. Given @a@ and @b@ with @al <= a <= ah@
488
- -- and @1\/bl >= 1\/b >= 1/bh@, @sdivRange (al, ah) (bl, bh)@ returns
489
- -- @(ql, qh)@ such that @ql <= a `quot` b <= qh@.
490
- sdivRange :: (Integer , Integer ) -> (Integer , Integer ) -> (Integer , Integer )
491
- sdivRange (al, ah) (bl, bh) = (ql, qh)
491
+ -- Given @a@ and @b@ with @al <= a <= ah@ and @1\/bl <= 1\/b <= 1/bh@,
492
+ -- @sdivRange (al, ah) (ReciprocalRange bl bh)@ returns @(ql, qh)@
493
+ -- such that @ql <= a `quot` b <= qh@.
494
+ sdivRange :: (Integer , Integer ) -> ReciprocalRange -> (Integer , Integer )
495
+ sdivRange (al, ah) (ReciprocalRange bl bh) = (ql, qh)
492
496
where
493
- (ql1, qh1) = scaleDownRange (al, ah) bl
494
- (ql2, qh2) = scaleDownRange (al, ah) bh
497
+ (ql1, qh1) = scaleDownRange (al, ah) bh
498
+ (ql2, qh2) = scaleDownRange (al, ah) bl
495
499
ql = min ql1 ql2
496
500
qh = max qh1 qh2
497
501
@@ -507,7 +511,7 @@ sdiv :: (1 <= w) => NatRepr w -> BVDomain w -> BVDomain w -> BVDomain w
507
511
sdiv w a b = interval mask ql (qh - ql)
508
512
where
509
513
mask = bvdMask a
510
- (ql, qh) = sdivRange (sbounds w a) (sbounds w b)
514
+ (ql, qh) = sdivRange (sbounds w a) (rbounds w b)
511
515
512
516
srem :: (1 <= w ) => NatRepr w -> BVDomain w -> BVDomain w -> BVDomain w
513
517
srem w a b =
@@ -524,7 +528,7 @@ srem w a b =
524
528
mask = bvdMask a
525
529
(al, ah) = sbounds w a
526
530
(bl, bh) = sbounds w b
527
- (ql, qh) = sdivRange (al, ah) (rbounds b)
531
+ (ql, qh) = sdivRange (al, ah) (rbounds w b)
528
532
rl = if al < 0 then min (bl+ 1 ) (- bh+ 1 ) else 0
529
533
rh = if ah > 0 then max (- bl- 1 ) (bh- 1 ) else 0
530
534
aw = ah - al
0 commit comments