@@ -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,102 @@ 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
+ def ushiftRight_rec (x : BitVec w₁) (y : BitVec w₂) (n : Nat) : BitVec w₁ :=
433
+ let shiftAmt := (y &&& (twoPow w₂ n))
434
+ match n with
435
+ | 0 => x >>> shiftAmt
436
+ | n + 1 => (ushiftRight_rec x y n) >>> shiftAmt
437
+
438
+ @[simp]
439
+ theorem ushiftRight_rec_zero (x : BitVec w₁) (y : BitVec w₂) :
440
+ ushiftRight_rec x y 0 = x >>> (y &&& twoPow w₂ 0 ) := by
441
+ simp [ushiftRight_rec]
442
+
443
+ @[simp]
444
+ theorem ushiftRight_rec_succ (x : BitVec w₁) (y : BitVec w₂) :
445
+ ushiftRight_rec x y (n + 1 ) =
446
+ (ushiftRight_rec x y n) >>> (y &&& twoPow w₂ (n + 1 )) := by
447
+ simp [ushiftRight_rec]
448
+
449
+ theorem ushiftRight'_ushiftRight' {x y z : BitVec w} :
450
+ x >>> y >>> z = x >>> (y.toNat + z.toNat) := by
451
+ simp [shiftRight_add]
452
+
453
+ theorem ushiftRight_or_eq_ushiftRight_ushiftRight_of_and_eq_zero {x : BitVec w₁} {y z : BitVec w₂}
454
+ (h : y &&& z = 0 #w₂) :
455
+ x >>> (y ||| z) = x >>> y >>> z := by
456
+ simp [← add_eq_or_of_and_eq_zero _ _ h, toNat_add_of_and_eq_zero h, shiftRight_add]
457
+
458
+ theorem getLsb_ushiftRight' (x : BitVec w₁) (y : BitVec w₂) (i : Nat) :
459
+ (x >>> y).getLsb i = x.getLsb (y.toNat + i) := by
460
+ simp [getLsb_ushiftRight]
461
+
462
+ theorem ushiftRight_rec_eq (x : BitVec w₁) (y : BitVec w₂) (n : Nat) :
463
+ ushiftRight_rec x y n = x >>> (y.truncate (n + 1 )).zeroExtend w₂ := by
464
+ induction n generalizing x y
465
+ case zero =>
466
+ ext i
467
+ simp only [ushiftRight_rec_zero, twoPow_zero, Nat.reduceAdd,
468
+ and_one_eq_zeroExtend_ofBool_getLsb, truncate_one]
469
+ case succ n ih =>
470
+ simp only [ushiftRight_rec_succ, and_twoPow]
471
+ rw [ih]
472
+ by_cases h : y.getLsb (n + 1 ) <;> simp only [h, ↓reduceIte]
473
+ · rw [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsb_true h]
474
+ rw [ushiftRight_or_eq_ushiftRight_ushiftRight_of_and_eq_zero]
475
+ simp
476
+ · simp [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsb_false (i := n + 1 ), h]
477
+
478
+ theorem shiftRight_eq_shiftRight_rec (x : BitVec w₁) (y : BitVec w₂) :
479
+ x >>> y = ushiftRight_rec x y (w₂ - 1 ) := by
480
+ rcases w₂ with rfl | w₂
481
+ · simp [of_length_zero]
482
+ · simp [ushiftRight_rec_eq]
483
+
484
+ /- ### Arithmetic shift right (sshiftRight) recurrence -/
485
+
486
+ def sshiftRightRec (x : BitVec w) (y : BitVec w₂) (n : Nat) : BitVec w :=
487
+ let shiftAmt := (y &&& (twoPow w₂ n))
488
+ match n with
489
+ | 0 => x.sshiftRight' shiftAmt
490
+ | n + 1 => (sshiftRightRec x y n).sshiftRight' shiftAmt
491
+
492
+ @[simp]
493
+ theorem sshiftRightRec_zero_eq (x : BitVec w) (y : BitVec w₂) :
494
+ sshiftRightRec x y 0 = x.sshiftRight' (y &&& 1 #w₂) := by
495
+ simp only [sshiftRightRec, twoPow_zero]
496
+
497
+ @[simp]
498
+ theorem sshiftRightRec_succ_eq (x : BitVec w) (y : BitVec w₂) (n : Nat) :
499
+ sshiftRightRec x y (n + 1 ) = (sshiftRightRec x y n).sshiftRight' (y &&& twoPow w₂ (n + 1 )) := by
500
+ simp [sshiftRightRec]
501
+
502
+ theorem sshiftRight_or_eq_sshiftRight_sshiftRight_of_and_eq_zero {x : BitVec w} {y z : BitVec w₂}
503
+ (h : y &&& z = 0 #w₂) :
504
+ x.sshiftRight' (y ||| z) = (x.sshiftRight' y).sshiftRight' z := by
505
+ simp [sshiftRight', ← add_eq_or_of_and_eq_zero _ _ h,
506
+ toNat_add_of_and_eq_zero h, sshiftRight'_add]
507
+
508
+ theorem sshiftRightRec_eq (x : BitVec w₁) (y : BitVec w₂) (n : Nat) :
509
+ sshiftRightRec x y n = x.sshiftRight' ((y.truncate (n + 1 )).zeroExtend w₂) := by
510
+ induction n generalizing x y
511
+ case zero =>
512
+ ext i
513
+ simp [ushiftRight_rec_zero, twoPow_zero, Nat.reduceAdd, and_one_eq_zeroExtend_ofBool_getLsb,
514
+ truncate_one]
515
+ case succ n ih =>
516
+ simp only [sshiftRightRec_succ_eq, and_twoPow, ih]
517
+ by_cases h : y.getLsb (n + 1 ) <;> simp [h]
518
+ · simp [zeroExtend_truncate_succ_eq_zeroExtend_truncate_or_twoPow_of_getLsb_true h,
519
+ sshiftRight_or_eq_sshiftRight_sshiftRight_of_and_eq_zero]
520
+ · simp [zeroExtend_truncate_succ_eq_zeroExtend_truncate_of_getLsb_false (i := n + 1 ), h]
521
+
522
+ theorem sshiftRight_eq_sshiftRightRec (x : BitVec w₁) (y : BitVec w₂) :
523
+ (x.sshiftRight' y).getLsb i = (sshiftRightRec x y (w₂ - 1 )).getLsb i := by
524
+ rcases w₂ with rfl | w₂
525
+ · simp [of_length_zero]
526
+ · simp [sshiftRightRec_eq]
527
+
434
528
end BitVec
0 commit comments