Theory NegatePhase
subsection ‹NegateNode Phase›
theory NegatePhase
  imports
    Common
begin
phase NegateNode
  terminating size
begin
lemma bin_negative_cancel:
 "-1 * (-1 * ((x::('a::len) word))) = x"
  by auto
lemma val_negative_cancel:
  assumes "val[-(new_int b v)] ≠ UndefVal"
  shows   "val[-(-(new_int b v))] = val[new_int b v]"
  by simp
lemma val_distribute_sub:
  assumes "x ≠ UndefVal ∧ y ≠ UndefVal"
  shows   "val[-(x - y)] = val[y - x]"
  by (cases x; cases y; auto)
lemma exp_distribute_sub:
  shows "exp[-(x - y)] ≥ exp[y - x]"
  by (auto simp: val_distribute_sub evaltree_not_undef)
thm_oracles exp_distribute_sub
lemma exp_negative_cancel:
  shows "exp[-(-x)] ≥ exp[x]"
  apply auto
  by (metis (no_types, opaque_lifting) eval_unused_bits_zero intval_negate.elims new_int.simps
      intval_negate.simps(1) minus_equation_iff take_bit_dist_neg) 
 
lemma exp_negative_shift: 
  assumes "stamp_expr x = IntegerStamp b' lo hi" 
  and     "unat y = (b' - 1)"
  shows   "exp[-(x >> (const (new_int b y)))] ≥ exp[x >>> (const (new_int b y))]"
  apply auto
  subgoal premises p for m p xa
  proof - 
    obtain xa where xa: "[m,p] ⊢ x ↦ xa"
      using p(2) by auto
    then have 1: "val[-(xa >> (IntVal b (take_bit b y)))] ≠ UndefVal"
      using evalDet p(1,2) by blast
    then have 2: "val[xa >> (IntVal b (take_bit b y))] ≠ UndefVal"
      by auto
    then have 4: "sint (signed_take_bit (b - Suc (0::nat)) (take_bit b y)) < (2::int) ^ b div (2::int)"
      by (metis Suc_le_lessD Suc_pred eval_bits_1_64 int_power_div_base p(4) zero_less_numeral
          signed_take_bit_int_less_exp_word size64 unfold_const wsst_TYs(3))
    then have 5: "(0::nat) < b"
      using eval_bits_1_64 p(4) by blast
    then have 6: "b ⊑ (64::nat)"
      using eval_bits_1_64 p(4) by blast
    then have 7: "[m,p] ⊢ BinaryExpr BinURightShift x
                 (ConstantExpr (IntVal b (take_bit b y))) ↦ 
                  intval_negate (intval_right_shift xa (IntVal b (take_bit b y)))"
      apply (cases y; auto)
      subgoal premises p for n
        proof - 
          have sg1: "y = word_of_nat n"
            by (simp add: p(1))
          then have sg2: "n < (18446744073709551616::nat)"
            by (simp add: p(2))
          then have sg3: "b ⊑ (64::nat)"
            by (simp add: "6")
          then have sg4: "[m,p] ⊢ BinaryExpr BinURightShift x
                 (ConstantExpr (IntVal b (take_bit b (word_of_nat n)))) ↦ 
                  intval_negate (intval_right_shift xa (IntVal b (take_bit b (word_of_nat n))))"
             sorry
          then show ?thesis
            by simp
        qed 
      done
    then show ?thesis
      by (metis evalDet p(2) xa)
  qed 
  done
text ‹Optimisations›
optimization NegateCancel: "-(-(x)) ⟼ x"
  using exp_negative_cancel by blast 
optimization DistributeSubtraction: "-(x - y) ⟼ (y - x)"
  apply (smt (verit, best) add.left_commute add_2_eq_Suc' add_diff_cancel_left' is_ConstantExpr_def
         less_Suc_eq_0_disj plus_1_eq_Suc size.simps(11) size_binary_const size_non_add
         zero_less_diff exp_distribute_sub nat_add_left_cancel_less less_add_eq_less add_Suc lessI
         trans_less_add2 size_binary_rhs Suc_eq_plus1 Nat.add_0_right old.nat.inject
         zero_less_Suc)
   using exp_distribute_sub by simp
optimization NegativeShift: "-(x >> (const (new_int b y))) ⟼ x >>> (const (new_int b y))
                                   when (stamp_expr x = IntegerStamp b' lo hi ∧ unat y = (b' - 1))"
  using exp_negative_shift by simp 
end 
end