@@ -403,12 +403,8 @@ theorem shiftLeftRec_eq {x : BitVec w₁} {y : BitVec w₂} {n : Nat} :
403
403
induction n generalizing x y
404
404
case zero =>
405
405
ext i
406
- simp only [shiftLeftRec_zero, twoPow_zero, Nat.reduceAdd, truncate_one]
407
- suffices (y &&& 1 #w₂) = zeroExtend w₂ (ofBool (y.getLsb 0 )) by simp [this]
408
- ext i
409
- by_cases h : (↑i : Nat) = 0
410
- · simp [h, Bool.and_comm]
411
- · simp [h]; omega
406
+ simp only [shiftLeftRec_zero, twoPow_zero, Nat.reduceAdd, truncate_one,
407
+ and_one_eq_zeroExtend_ofBool_getLsb]
412
408
case succ n ih =>
413
409
simp only [shiftLeftRec_succ, and_twoPow]
414
410
rw [ih]
@@ -431,4 +427,67 @@ theorem shiftLeft_eq_shiftLeftRec (x : BitVec w₁) (y : BitVec w₂) :
431
427
· simp [of_length_zero]
432
428
· simp [shiftLeftRec_eq]
433
429
430
+ /- ### Logical shift right (ushiftRight) recurrence for bitblasting -/
431
+
432
+ /--
433
+ `ushiftRightRec x y n` shifts `x` logically to the right by the first `n` bits of `y`.
434
+
435
+ The theorem `shiftRight_eq_ushiftRightRec` proves the equivalence
436
+ of `(x >>> y)` and `ushiftRightRec`.
437
+
438
+ Together with equations `ushiftRightRec_zero`, `ushiftRightRec_succ`,
439
+ this allows us to unfold `ushiftRight` into a circuit for bitblasting.
440
+ -/
441
+ def ushiftRightRec (x : BitVec w₁) (y : BitVec w₂) (n : Nat) : BitVec w₁ :=
442
+ let shiftAmt := (y &&& (twoPow w₂ n))
443
+ match n with
444
+ | 0 => x >>> shiftAmt
445
+ | n + 1 => (ushiftRightRec x y n) >>> shiftAmt
446
+
447
+ @[simp]
448
+ theorem ushiftRightRec_zero (x : BitVec w₁) (y : BitVec w₂) :
449
+ ushiftRightRec x y 0 = x >>> (y &&& twoPow w₂ 0 ) := by
450
+ simp [ushiftRightRec]
451
+
452
+ @[simp]
453
+ theorem ushiftRightRec_succ (x : BitVec w₁) (y : BitVec w₂) :
454
+ ushiftRightRec x y (n + 1 ) = (ushiftRightRec x y n) >>> (y &&& twoPow w₂ (n + 1 )) := by
455
+ simp [ushiftRightRec]
456
+
457
+ /--
458
+ If `y &&& z = 0`, `x >>> (y ||| z) = x >>> y >>> z`.
459
+ This follows as `y &&& z = 0` implies `y ||| z = y + z`,
460
+ and thus `x >>> (y ||| z) = x >>> (y + z) = x >>> y >>> z`.
461
+ -/
462
+ theorem ushiftRight'_or_of_and_eq_zero {x : BitVec w₁} {y z : BitVec w₂}
463
+ (h : y &&& z = 0 #w₂) :
464
+ x >>> (y ||| z) = x >>> y >>> z := by
465
+ simp [← add_eq_or_of_and_eq_zero _ _ h, toNat_add_of_and_eq_zero h, shiftRight_add]
466
+
467
+ theorem ushiftRightRec_eq (x : BitVec w₁) (y : BitVec w₂) (n : Nat) :
468
+ ushiftRightRec x y n = x >>> (y.truncate (n + 1 )).zeroExtend w₂ := by
469
+ induction n generalizing x y
470
+ case zero =>
471
+ ext i
472
+ simp only [ushiftRightRec_zero, twoPow_zero, Nat.reduceAdd,
473
+ and_one_eq_zeroExtend_ofBool_getLsb, truncate_one]
474
+ case succ n ih =>
475
+ simp only [ushiftRightRec_succ, and_twoPow]
476
+ rw [ih]
477
+ by_cases h : y.getLsb (n + 1 ) <;> simp only [h, ↓reduceIte]
478
+ · rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsb_true h,
479
+ ushiftRight'_or_of_and_eq_zero]
480
+ simp
481
+ · simp [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsb_false (i := n + 1 ), h]
482
+
483
+ /--
484
+ Show that `x >>> y` can be written in terms of `ushiftRightRec`.
485
+ This can be unfolded in terms of `ushiftRightRec_zero`, `ushiftRightRec_succ` for bitblasting.
486
+ -/
487
+ theorem shiftRight_eq_ushiftRightRec (x : BitVec w₁) (y : BitVec w₂) :
488
+ x >>> y = ushiftRightRec x y (w₂ - 1 ) := by
489
+ rcases w₂ with rfl | w₂
490
+ · simp [of_length_zero]
491
+ · simp [ushiftRightRec_eq]
492
+
434
493
end BitVec
0 commit comments