src/HOL/Word/WordShift.thy
changeset 24333 e77ea0ea7f2c
child 24350 4d74f37c6367
equal deleted inserted replaced
24332:e3a2b75b1cf9 24333:e77ea0ea7f2c
       
     1 (* 
       
     2     ID:         $Id$
       
     3     Author:     Jeremy Dawson and Gerwin Klein, NICTA
       
     4 
       
     5   contains theorems to do with shifting, rotating, splitting words
       
     6 *)
       
     7 
       
     8 theory WordShift imports WordBitwise begin
       
     9 
       
    10 section "Bit shifting"
       
    11 
       
    12 lemma shiftl1_number [simp] :
       
    13   "shiftl1 (number_of w) = number_of (w BIT bit.B0)"
       
    14   apply (unfold shiftl1_def word_number_of_def)
       
    15   apply (simp add: word_ubin.norm_eq_iff [symmetric] word_ubin.eq_norm)
       
    16   apply (subst refl [THEN bintrunc_BIT_I, symmetric])
       
    17   apply (subst bintrunc_bintrunc_min)
       
    18   apply simp
       
    19   done
       
    20 
       
    21 lemma shiftl1_0 [simp] : "shiftl1 0 = 0"
       
    22   unfolding word_0_no shiftl1_number by auto
       
    23 
       
    24 lemmas shiftl1_def_u = shiftl1_def [folded word_number_of_def]
       
    25 
       
    26 lemma shiftl1_def_s: "shiftl1 w = number_of (sint w BIT bit.B0)"
       
    27   by (rule trans [OF _ shiftl1_number]) simp
       
    28 
       
    29 lemma shiftr1_0 [simp] : "shiftr1 0 = 0"
       
    30   unfolding shiftr1_def 
       
    31   by simp (simp add: word_0_wi)
       
    32 
       
    33 lemma sshiftr1_0 [simp] : "sshiftr1 0 = 0"
       
    34   apply (unfold sshiftr1_def)
       
    35   apply simp
       
    36   apply (simp add : word_0_wi)
       
    37   done
       
    38 
       
    39 lemma sshiftr1_n1 [simp] : "sshiftr1 -1 = -1"
       
    40   unfolding sshiftr1_def by auto
       
    41 
       
    42 lemma shiftl_0 [simp] : "(0::'a::len0 word) << n = 0"
       
    43   unfolding shiftl_def by (induct n) auto
       
    44 
       
    45 lemma shiftr_0 [simp] : "(0::'a::len0 word) >> n = 0"
       
    46   unfolding shiftr_def by (induct n) auto
       
    47 
       
    48 lemma sshiftr_0 [simp] : "0 >>> n = 0"
       
    49   unfolding sshiftr_def by (induct n) auto
       
    50 
       
    51 lemma sshiftr_n1 [simp] : "-1 >>> n = -1"
       
    52   unfolding sshiftr_def by (induct n) auto
       
    53 
       
    54 lemma nth_shiftl1: "shiftl1 w !! n = (n < size w & n > 0 & w !! (n - 1))"
       
    55   apply (unfold shiftl1_def word_test_bit_def)
       
    56   apply (simp add: nth_bintr word_ubin.eq_norm word_size)
       
    57   apply (cases n)
       
    58    apply auto
       
    59   done
       
    60 
       
    61 lemma nth_shiftl' [rule_format]:
       
    62   "ALL n. ((w::'a::len0 word) << m) !! n = (n < size w & n >= m & w !! (n - m))"
       
    63   apply (unfold shiftl_def)
       
    64   apply (induct "m")
       
    65    apply (force elim!: test_bit_size)
       
    66   apply (clarsimp simp add : nth_shiftl1 word_size)
       
    67   apply arith
       
    68   done
       
    69 
       
    70 lemmas nth_shiftl = nth_shiftl' [unfolded word_size] 
       
    71 
       
    72 lemma nth_shiftr1: "shiftr1 w !! n = w !! Suc n"
       
    73   apply (unfold shiftr1_def word_test_bit_def)
       
    74   apply (simp add: nth_bintr word_ubin.eq_norm)
       
    75   apply safe
       
    76   apply (drule bin_nth.Suc [THEN iffD2, THEN bin_nth_uint_imp])
       
    77   apply simp
       
    78   done
       
    79 
       
    80 lemma nth_shiftr: 
       
    81   "\<And>n. ((w::'a::len0 word) >> m) !! n = w !! (n + m)"
       
    82   apply (unfold shiftr_def)
       
    83   apply (induct "m")
       
    84    apply (auto simp add : nth_shiftr1)
       
    85   done
       
    86    
       
    87 (* see paper page 10, (1), (2), shiftr1_def is of the form of (1),
       
    88   where f (ie bin_rest) takes normal arguments to normal results,
       
    89   thus we get (2) from (1) *)
       
    90 
       
    91 lemma uint_shiftr1: "uint (shiftr1 w) = bin_rest (uint w)" 
       
    92   apply (unfold shiftr1_def word_ubin.eq_norm bin_rest_trunc_i)
       
    93   apply (subst bintr_uint [symmetric, OF order_refl])
       
    94   apply (simp only : bintrunc_bintrunc_l)
       
    95   apply simp 
       
    96   done
       
    97 
       
    98 lemma nth_sshiftr1: 
       
    99   "sshiftr1 w !! n = (if n = size w - 1 then w !! n else w !! Suc n)"
       
   100   apply (unfold sshiftr1_def word_test_bit_def)
       
   101   apply (simp add: nth_bintr word_ubin.eq_norm
       
   102                    bin_nth.Suc [symmetric] word_size 
       
   103              del: bin_nth.simps)
       
   104   apply (simp add: nth_bintr uint_sint del : bin_nth.simps)
       
   105   apply (auto simp add: bin_nth_sint)
       
   106   done
       
   107 
       
   108 lemma nth_sshiftr [rule_format] : 
       
   109   "ALL n. sshiftr w m !! n = (n < size w & 
       
   110     (if n + m >= size w then w !! (size w - 1) else w !! (n + m)))"
       
   111   apply (unfold sshiftr_def)
       
   112   apply (induct_tac "m")
       
   113    apply (simp add: test_bit_bl)
       
   114   apply (clarsimp simp add: nth_sshiftr1 word_size)
       
   115   apply safe
       
   116        apply arith
       
   117       apply arith
       
   118      apply (erule thin_rl)
       
   119      apply (case_tac n)
       
   120       apply safe
       
   121       apply simp
       
   122      apply simp
       
   123     apply (erule thin_rl)
       
   124     apply (case_tac n)
       
   125      apply safe
       
   126      apply simp
       
   127     apply simp
       
   128    apply arith+
       
   129   done
       
   130     
       
   131 lemma shiftr1_div_2: "uint (shiftr1 w) = uint w div 2"
       
   132   apply (unfold shiftr1_def bin_rest_div)
       
   133   apply (rule word_uint.Abs_inverse)
       
   134   apply (simp add: uints_num pos_imp_zdiv_nonneg_iff)
       
   135   apply (rule xtr7)
       
   136    prefer 2
       
   137    apply (rule zdiv_le_dividend)
       
   138     apply auto
       
   139   done
       
   140 
       
   141 lemma sshiftr1_div_2: "sint (sshiftr1 w) = sint w div 2"
       
   142   apply (unfold sshiftr1_def bin_rest_div [symmetric])
       
   143   apply (simp add: word_sbin.eq_norm)
       
   144   apply (rule trans)
       
   145    defer
       
   146    apply (subst word_sbin.norm_Rep [symmetric])
       
   147    apply (rule refl)
       
   148   apply (subst word_sbin.norm_Rep [symmetric])
       
   149   apply (unfold One_nat_def)
       
   150   apply (rule sbintrunc_rest)
       
   151   done
       
   152 
       
   153 lemma shiftr_div_2n: "uint (shiftr w n) = uint w div 2 ^ n"
       
   154   apply (unfold shiftr_def)
       
   155   apply (induct "n")
       
   156    apply simp
       
   157   apply (simp add: shiftr1_div_2 mult_commute
       
   158                    zdiv_zmult2_eq [symmetric])
       
   159   done
       
   160 
       
   161 lemma sshiftr_div_2n: "sint (sshiftr w n) = sint w div 2 ^ n"
       
   162   apply (unfold sshiftr_def)
       
   163   apply (induct "n")
       
   164    apply simp
       
   165   apply (simp add: sshiftr1_div_2 mult_commute
       
   166                    zdiv_zmult2_eq [symmetric])
       
   167   done
       
   168 
       
   169 subsection "shift functions in terms of lists of bools"
       
   170 
       
   171 lemmas bshiftr1_no_bin [simp] = 
       
   172   bshiftr1_def [where w="number_of ?w", unfolded to_bl_no_bin]
       
   173 
       
   174 lemma bshiftr1_bl: "to_bl (bshiftr1 b w) = b # butlast (to_bl w)"
       
   175   unfolding bshiftr1_def by (rule word_bl.Abs_inverse) simp
       
   176 
       
   177 lemma shiftl1_of_bl: "shiftl1 (of_bl bl) = of_bl (bl @ [False])"
       
   178   unfolding uint_bl of_bl_no 
       
   179   by (simp add: bl_to_bin_aux_append bl_to_bin_def)
       
   180 
       
   181 lemmas shiftl1_bl = shiftl1_of_bl 
       
   182   [where bl = "to_bl (?w :: ?'a :: len0 word)", simplified]
       
   183 
       
   184 lemma bl_shiftl1:
       
   185   "to_bl (shiftl1 (w :: 'a :: len word)) = tl (to_bl w) @ [False]"
       
   186   apply (simp add: shiftl1_bl word_rep_drop drop_Suc drop_Cons')
       
   187   apply (fast intro!: Suc_leI)
       
   188   done
       
   189 
       
   190 lemma shiftr1_bl: "shiftr1 w = of_bl (butlast (to_bl w))"
       
   191   apply (unfold shiftr1_def uint_bl of_bl_def)
       
   192   apply (simp add: butlast_rest_bin word_size)
       
   193   apply (simp add: bin_rest_trunc [symmetric, unfolded One_nat_def])
       
   194   done
       
   195 
       
   196 lemma bl_shiftr1: 
       
   197   "to_bl (shiftr1 (w :: 'a :: len word)) = False # butlast (to_bl w)"
       
   198   unfolding shiftr1_bl
       
   199   by (simp add : word_rep_drop len_gt_0 [THEN Suc_leI])
       
   200 
       
   201 
       
   202 (* relate the two above : TODO - remove the :: len restriction on
       
   203   this theorem and others depending on it *)
       
   204 lemma shiftl1_rev: 
       
   205   "shiftl1 (w :: 'a :: len word) = word_reverse (shiftr1 (word_reverse w))"
       
   206   apply (unfold word_reverse_def)
       
   207   apply (rule word_bl.Rep_inverse' [symmetric])
       
   208   apply (simp add: bl_shiftl1 bl_shiftr1 word_bl.Abs_inverse)
       
   209   apply (cases "to_bl w")
       
   210    apply auto
       
   211   done
       
   212 
       
   213 lemma shiftl_rev: 
       
   214   "shiftl (w :: 'a :: len word) n = word_reverse (shiftr (word_reverse w) n)"
       
   215   apply (unfold shiftl_def shiftr_def)
       
   216   apply (induct "n")
       
   217    apply (auto simp add : shiftl1_rev)
       
   218   done
       
   219 
       
   220 lemmas rev_shiftl =
       
   221   shiftl_rev [where w = "word_reverse ?w1", simplified, standard]
       
   222 
       
   223 lemmas shiftr_rev = rev_shiftl [THEN word_rev_gal', standard]
       
   224 lemmas rev_shiftr = shiftl_rev [THEN word_rev_gal', standard]
       
   225 
       
   226 lemma bl_sshiftr1:
       
   227   "to_bl (sshiftr1 (w :: 'a :: len word)) = hd (to_bl w) # butlast (to_bl w)"
       
   228   apply (unfold sshiftr1_def uint_bl word_size)
       
   229   apply (simp add: butlast_rest_bin word_ubin.eq_norm)
       
   230   apply (simp add: sint_uint)
       
   231   apply (rule nth_equalityI)
       
   232    apply clarsimp
       
   233   apply clarsimp
       
   234   apply (case_tac i)
       
   235    apply (simp_all add: hd_conv_nth length_0_conv [symmetric]
       
   236                         nth_bin_to_bl bin_nth.Suc [symmetric] 
       
   237                         nth_sbintr 
       
   238                    del: bin_nth.Suc)
       
   239    apply force
       
   240   apply (rule impI)
       
   241   apply (rule_tac f = "bin_nth (uint w)" in arg_cong)
       
   242   apply simp
       
   243   done
       
   244 
       
   245 lemma drop_shiftr: 
       
   246   "drop n (to_bl ((w :: 'a :: len word) >> n)) = take (size w - n) (to_bl w)" 
       
   247   apply (unfold shiftr_def)
       
   248   apply (induct n)
       
   249    prefer 2
       
   250    apply (simp add: drop_Suc bl_shiftr1 butlast_drop [symmetric])
       
   251    apply (rule butlast_take [THEN trans])
       
   252   apply (auto simp: word_size)
       
   253   done
       
   254 
       
   255 lemma drop_sshiftr: 
       
   256   "drop n (to_bl ((w :: 'a :: len word) >>> n)) = take (size w - n) (to_bl w)"
       
   257   apply (unfold sshiftr_def)
       
   258   apply (induct n)
       
   259    prefer 2
       
   260    apply (simp add: drop_Suc bl_sshiftr1 butlast_drop [symmetric])
       
   261    apply (rule butlast_take [THEN trans])
       
   262   apply (auto simp: word_size)
       
   263   done
       
   264 
       
   265 lemma take_shiftr [rule_format] :
       
   266   "n <= size (w :: 'a :: len word) --> take n (to_bl (w >> n)) = 
       
   267     replicate n False" 
       
   268   apply (unfold shiftr_def)
       
   269   apply (induct n)
       
   270    prefer 2
       
   271    apply (simp add: bl_shiftr1)
       
   272    apply (rule impI)
       
   273    apply (rule take_butlast [THEN trans])
       
   274   apply (auto simp: word_size)
       
   275   done
       
   276 
       
   277 lemma take_sshiftr' [rule_format] :
       
   278   "n <= size (w :: 'a :: len word) --> hd (to_bl (w >>> n)) = hd (to_bl w) & 
       
   279     take n (to_bl (w >>> n)) = replicate n (hd (to_bl w))" 
       
   280   apply (unfold sshiftr_def)
       
   281   apply (induct n)
       
   282    prefer 2
       
   283    apply (simp add: bl_sshiftr1)
       
   284    apply (rule impI)
       
   285    apply (rule take_butlast [THEN trans])
       
   286   apply (auto simp: word_size)
       
   287   done
       
   288 
       
   289 lemmas hd_sshiftr = take_sshiftr' [THEN conjunct1, standard]
       
   290 lemmas take_sshiftr = take_sshiftr' [THEN conjunct2, standard]
       
   291 
       
   292 lemma atd_lem: "take n xs = t ==> drop n xs = d ==> xs = t @ d"
       
   293   by (auto intro: append_take_drop_id [symmetric])
       
   294 
       
   295 lemmas bl_shiftr = atd_lem [OF take_shiftr drop_shiftr]
       
   296 lemmas bl_sshiftr = atd_lem [OF take_sshiftr drop_sshiftr]
       
   297 
       
   298 lemma shiftl_of_bl: "of_bl bl << n = of_bl (bl @ replicate n False)"
       
   299   unfolding shiftl_def
       
   300   by (induct n) (auto simp: shiftl1_of_bl replicate_app_Cons_same)
       
   301 
       
   302 lemmas shiftl_bl =
       
   303   shiftl_of_bl [where bl = "to_bl (?w :: ?'a :: len0 word)", simplified]
       
   304 
       
   305 lemmas shiftl_number [simp] = shiftl_def [where w="number_of ?w"]
       
   306 
       
   307 lemma bl_shiftl:
       
   308   "to_bl (w << n) = drop n (to_bl w) @ replicate (min (size w) n) False"
       
   309   by (simp add: shiftl_bl word_rep_drop word_size min_def)
       
   310 
       
   311 lemma shiftl_zero_size: 
       
   312   fixes x :: "'a::len0 word"
       
   313   shows "size x <= n ==> x << n = 0"
       
   314   apply (unfold word_size)
       
   315   apply (rule word_eqI)
       
   316   apply (clarsimp simp add: shiftl_bl word_size test_bit_of_bl nth_append)
       
   317   done
       
   318 
       
   319 (* note - the following results use 'a :: len word < number_ring *)
       
   320 
       
   321 lemma shiftl1_2t: "shiftl1 (w :: 'a :: len word) = 2 * w"
       
   322   apply (simp add: shiftl1_def_u)
       
   323   apply (simp only:  double_number_of_BIT [symmetric])
       
   324   apply simp
       
   325   done
       
   326 
       
   327 lemma shiftl1_p: "shiftl1 (w :: 'a :: len word) = w + w"
       
   328   apply (simp add: shiftl1_def_u)
       
   329   apply (simp only: double_number_of_BIT [symmetric])
       
   330   apply simp
       
   331   done
       
   332 
       
   333 lemma shiftl_t2n: "shiftl (w :: 'a :: len word) n = 2 ^ n * w"
       
   334   unfolding shiftl_def 
       
   335   by (induct n) (auto simp: shiftl1_2t power_Suc)
       
   336 
       
   337 lemma shiftr1_bintr [simp]:
       
   338   "(shiftr1 (number_of w) :: 'a :: len0 word) = 
       
   339     number_of (bin_rest (bintrunc (len_of TYPE ('a)) w))" 
       
   340   unfolding shiftr1_def word_number_of_def
       
   341   by (simp add : word_ubin.eq_norm)
       
   342 
       
   343 lemma sshiftr1_sbintr [simp] :
       
   344   "(sshiftr1 (number_of w) :: 'a :: len word) = 
       
   345     number_of (bin_rest (sbintrunc (len_of TYPE ('a) - 1) w))" 
       
   346   unfolding sshiftr1_def word_number_of_def
       
   347   by (simp add : word_sbin.eq_norm)
       
   348 
       
   349 lemma shiftr_no': 
       
   350   "w = number_of bin ==> 
       
   351   (w::'a::len0 word) >> n = number_of ((bin_rest ^ n) (bintrunc (size w) bin))"
       
   352   apply clarsimp
       
   353   apply (rule word_eqI)
       
   354   apply (auto simp: nth_shiftr nth_rest_power_bin nth_bintr word_size)
       
   355   done
       
   356 
       
   357 lemma sshiftr_no': 
       
   358   "w = number_of bin ==> w >>> n = number_of ((bin_rest ^ n) 
       
   359     (sbintrunc (size w - 1) bin))"
       
   360   apply clarsimp
       
   361   apply (rule word_eqI)
       
   362   apply (auto simp: nth_sshiftr nth_rest_power_bin nth_sbintr word_size)
       
   363    apply (subgoal_tac "na + n = len_of TYPE('a) - Suc 0", simp, simp)+
       
   364   done
       
   365 
       
   366 lemmas sshiftr_no [simp] = 
       
   367   sshiftr_no' [where w = "number_of ?w", OF refl, unfolded word_size]
       
   368 
       
   369 lemmas shiftr_no [simp] = 
       
   370   shiftr_no' [where w = "number_of ?w", OF refl, unfolded word_size]
       
   371 
       
   372 lemma shiftr1_bl_of': 
       
   373   "us = shiftr1 (of_bl bl) ==> length bl <= size us ==> 
       
   374     us = of_bl (butlast bl)"
       
   375   by (clarsimp simp: shiftr1_def of_bl_def word_size butlast_rest_bl2bin 
       
   376                      word_ubin.eq_norm trunc_bl2bin)
       
   377 
       
   378 lemmas shiftr1_bl_of = refl [THEN shiftr1_bl_of', unfolded word_size]
       
   379 
       
   380 lemma shiftr_bl_of' [rule_format]: 
       
   381   "us = of_bl bl >> n ==> length bl <= size us --> 
       
   382    us = of_bl (take (length bl - n) bl)"
       
   383   apply (unfold shiftr_def)
       
   384   apply hypsubst
       
   385   apply (unfold word_size)
       
   386   apply (induct n)
       
   387    apply clarsimp
       
   388   apply clarsimp
       
   389   apply (subst shiftr1_bl_of)
       
   390    apply simp
       
   391   apply (simp add: butlast_take)
       
   392   done
       
   393 
       
   394 lemmas shiftr_bl_of = refl [THEN shiftr_bl_of', unfolded word_size]
       
   395 
       
   396 lemmas shiftr_bl = word_bl.Rep' [THEN eq_imp_le, THEN shiftr_bl_of,
       
   397   simplified word_size, simplified, THEN eq_reflection, standard]
       
   398 
       
   399 lemma msb_shift': "msb (w::'a::len word) <-> (w >> (size w - 1)) ~= 0"
       
   400   apply (unfold shiftr_bl word_msb_alt)
       
   401   apply (simp add: word_size Suc_le_eq take_Suc)
       
   402   apply (cases "hd (to_bl w)")
       
   403    apply (auto simp: word_1_bl word_0_bl 
       
   404                      of_bl_rep_False [where n=1 and bs="[]", simplified])
       
   405   done
       
   406 
       
   407 lemmas msb_shift = msb_shift' [unfolded word_size]
       
   408 
       
   409 lemma align_lem_or [rule_format] :
       
   410   "ALL x m. length x = n + m --> length y = n + m --> 
       
   411     drop m x = replicate n False --> take m y = replicate m False --> 
       
   412     app2 op | x y = take m x @ drop m y"
       
   413   apply (induct_tac y)
       
   414    apply force
       
   415   apply clarsimp
       
   416   apply (case_tac x, force)
       
   417   apply (case_tac m, auto)
       
   418   apply (drule sym)
       
   419   apply auto
       
   420   apply (induct_tac list, auto)
       
   421   done
       
   422 
       
   423 lemma align_lem_and [rule_format] :
       
   424   "ALL x m. length x = n + m --> length y = n + m --> 
       
   425     drop m x = replicate n False --> take m y = replicate m False --> 
       
   426     app2 op & x y = replicate (n + m) False"
       
   427   apply (induct_tac y)
       
   428    apply force
       
   429   apply clarsimp
       
   430   apply (case_tac x, force)
       
   431   apply (case_tac m, auto)
       
   432   apply (drule sym)
       
   433   apply auto
       
   434   apply (induct_tac list, auto)
       
   435   done
       
   436 
       
   437 lemma aligned_bl_add_size':
       
   438   "size x - n = m ==> n <= size x ==> drop m (to_bl x) = replicate n False ==>
       
   439     take m (to_bl y) = replicate m False ==> 
       
   440     to_bl (x + y) = take m (to_bl x) @ drop m (to_bl y)"
       
   441   apply (subgoal_tac "x AND y = 0")
       
   442    prefer 2
       
   443    apply (rule word_bl.Rep_eqD)
       
   444    apply (simp add: bl_word_and to_bl_0)
       
   445    apply (rule align_lem_and [THEN trans])
       
   446        apply (simp_all add: word_size)[5]
       
   447    apply (rule_tac f = "%n. replicate n False" in arg_cong)
       
   448    apply simp
       
   449   apply (subst word_plus_and_or [symmetric])
       
   450   apply (simp add : bl_word_or)
       
   451   apply (rule align_lem_or)
       
   452      apply (simp_all add: word_size)
       
   453   done
       
   454 
       
   455 lemmas aligned_bl_add_size = refl [THEN aligned_bl_add_size']
       
   456 
       
   457 subsection "Mask"
       
   458 
       
   459 lemma nth_mask': "m = mask n ==> test_bit m i = (i < n & i < size m)"
       
   460   apply (unfold mask_def test_bit_bl)
       
   461   apply (simp only: word_1_bl [symmetric] shiftl_of_bl)
       
   462   apply (clarsimp simp add: word_size)
       
   463   apply (simp only: of_bl_no mask_lem number_of_succ add_diff_cancel2)
       
   464   apply (fold of_bl_no)
       
   465   apply (simp add: word_1_bl)
       
   466   apply (rule test_bit_of_bl [THEN trans, unfolded test_bit_bl word_size])
       
   467   apply auto
       
   468   done
       
   469 
       
   470 lemmas nth_mask [simp] = refl [THEN nth_mask']
       
   471 
       
   472 lemma mask_bl: "mask n = of_bl (replicate n True)"
       
   473   by (auto simp add : test_bit_of_bl word_size intro: word_eqI)
       
   474 
       
   475 lemma mask_bin: "mask n = number_of (bintrunc n Numeral.Min)"
       
   476   by (auto simp add: nth_bintr word_size intro: word_eqI)
       
   477 
       
   478 lemma and_mask_bintr: "w AND mask n = number_of (bintrunc n (uint w))"
       
   479   apply (rule word_eqI)
       
   480   apply (simp add: nth_bintr word_size word_ops_nth_size)
       
   481   apply (auto simp add: test_bit_bin)
       
   482   done
       
   483 
       
   484 lemma and_mask_no: "number_of i AND mask n = number_of (bintrunc n i)" 
       
   485   by (auto simp add : nth_bintr word_size word_ops_nth_size intro: word_eqI)
       
   486 
       
   487 lemmas and_mask_wi = and_mask_no [unfolded word_number_of_def] 
       
   488 
       
   489 lemma bl_and_mask:
       
   490   "to_bl (w AND mask n :: 'a :: len word) = 
       
   491     replicate (len_of TYPE('a) - n) False @ 
       
   492     drop (len_of TYPE('a) - n) (to_bl w)"
       
   493   apply (rule nth_equalityI)
       
   494    apply simp
       
   495   apply (clarsimp simp add: to_bl_nth word_size)
       
   496   apply (simp add: word_size word_ops_nth_size)
       
   497   apply (auto simp add: word_size test_bit_bl nth_append nth_rev)
       
   498   done
       
   499 
       
   500 lemmas and_mask_mod_2p = 
       
   501   and_mask_bintr [unfolded word_number_of_alt no_bintr_alt]
       
   502 
       
   503 lemma and_mask_lt_2p: "uint (w AND mask n) < 2 ^ n"
       
   504   apply (simp add : and_mask_bintr no_bintr_alt)
       
   505   apply (rule xtr8)
       
   506    prefer 2
       
   507    apply (rule pos_mod_bound)
       
   508   apply auto
       
   509   done
       
   510 
       
   511 lemmas eq_mod_iff = trans [symmetric, OF int_mod_lem eq_sym_conv]
       
   512 
       
   513 lemma mask_eq_iff: "(w AND mask n) = w <-> uint w < 2 ^ n"
       
   514   apply (simp add: and_mask_bintr word_number_of_def)
       
   515   apply (simp add: word_ubin.inverse_norm)
       
   516   apply (simp add: eq_mod_iff bintrunc_mod2p min_def)
       
   517   apply (fast intro!: lt2p_lem)
       
   518   done
       
   519 
       
   520 lemma and_mask_dvd: "2 ^ n dvd uint w = (w AND mask n = 0)"
       
   521   apply (simp add: zdvd_iff_zmod_eq_0 and_mask_mod_2p)
       
   522   apply (simp add: word_uint.norm_eq_iff [symmetric] word_of_int_homs)
       
   523   apply (subst word_uint.norm_Rep [symmetric])
       
   524   apply (simp only: bintrunc_bintrunc_min bintrunc_mod2p [symmetric] min_def)
       
   525   apply auto
       
   526   done
       
   527 
       
   528 lemma and_mask_dvd_nat: "2 ^ n dvd unat w = (w AND mask n = 0)"
       
   529   apply (unfold unat_def)
       
   530   apply (rule trans [OF _ and_mask_dvd])
       
   531   apply (unfold dvd_def) 
       
   532   apply auto 
       
   533   apply (drule uint_ge_0 [THEN nat_int.Abs_inverse' [simplified], symmetric])
       
   534   apply (simp add : int_mult int_power)
       
   535   apply (simp add : nat_mult_distrib nat_power_eq)
       
   536   done
       
   537 
       
   538 lemma word_2p_lem: 
       
   539   "n < size w ==> w < 2 ^ n = (uint (w :: 'a :: len word) < 2 ^ n)"
       
   540   apply (unfold word_size word_less_alt word_number_of_alt)
       
   541   apply (clarsimp simp add: word_of_int_power_hom word_uint.eq_norm 
       
   542                             int_mod_eq'
       
   543                   simp del: word_of_int_bin)
       
   544   done
       
   545 
       
   546 lemma less_mask_eq: "x < 2 ^ n ==> x AND mask n = (x :: 'a :: len word)"
       
   547   apply (unfold word_less_alt word_number_of_alt)
       
   548   apply (clarsimp simp add: and_mask_mod_2p word_of_int_power_hom 
       
   549                             word_uint.eq_norm
       
   550                   simp del: word_of_int_bin)
       
   551   apply (drule xtr8 [rotated])
       
   552   apply (rule int_mod_le)
       
   553   apply (auto simp add : mod_pos_pos_trivial)
       
   554   done
       
   555 
       
   556 lemmas mask_eq_iff_w2p =
       
   557   trans [OF mask_eq_iff word_2p_lem [symmetric], standard]
       
   558 
       
   559 lemmas and_mask_less' = 
       
   560   iffD2 [OF word_2p_lem and_mask_lt_2p, simplified word_size, standard]
       
   561 
       
   562 lemma and_mask_less_size: "n < size x ==> x AND mask n < 2^n"
       
   563   unfolding word_size by (erule and_mask_less')
       
   564 
       
   565 lemma word_mod_2p_is_mask':
       
   566   "c = 2 ^ n ==> c > 0 ==> x mod c = (x :: 'a :: len word) AND mask n" 
       
   567   by (clarsimp simp add: word_mod_def uint_2p and_mask_mod_2p) 
       
   568 
       
   569 lemmas word_mod_2p_is_mask = refl [THEN word_mod_2p_is_mask'] 
       
   570 
       
   571 lemma mask_eqs:
       
   572   "(a AND mask n) + b AND mask n = a + b AND mask n"
       
   573   "a + (b AND mask n) AND mask n = a + b AND mask n"
       
   574   "(a AND mask n) - b AND mask n = a - b AND mask n"
       
   575   "a - (b AND mask n) AND mask n = a - b AND mask n"
       
   576   "a * (b AND mask n) AND mask n = a * b AND mask n"
       
   577   "(b AND mask n) * a AND mask n = b * a AND mask n"
       
   578   "(a AND mask n) + (b AND mask n) AND mask n = a + b AND mask n"
       
   579   "(a AND mask n) - (b AND mask n) AND mask n = a - b AND mask n"
       
   580   "(a AND mask n) * (b AND mask n) AND mask n = a * b AND mask n"
       
   581   "- (a AND mask n) AND mask n = - a AND mask n"
       
   582   "word_succ (a AND mask n) AND mask n = word_succ a AND mask n"
       
   583   "word_pred (a AND mask n) AND mask n = word_pred a AND mask n"
       
   584   using word_of_int_Ex [where x=a] word_of_int_Ex [where x=b]
       
   585   by (auto simp: and_mask_wi bintr_ariths bintr_arith1s new_word_of_int_homs)
       
   586 
       
   587 lemma mask_power_eq:
       
   588   "(x AND mask n) ^ k AND mask n = x ^ k AND mask n"
       
   589   using word_of_int_Ex [where x=x]
       
   590   by (clarsimp simp: and_mask_wi word_of_int_power_hom bintr_ariths)
       
   591 
       
   592 
       
   593 subsection "Revcast"
       
   594 
       
   595 lemmas revcast_def' = revcast_def [simplified]
       
   596 lemmas revcast_def'' = revcast_def' [simplified word_size]
       
   597 lemmas revcast_no_def [simp] =
       
   598   revcast_def' [where w="number_of ?w", unfolded word_size]
       
   599 
       
   600 lemma to_bl_revcast: 
       
   601   "to_bl (revcast w :: 'a :: len0 word) = 
       
   602    takefill False (len_of TYPE ('a)) (to_bl w)"
       
   603   apply (unfold revcast_def' word_size)
       
   604   apply (rule word_bl.Abs_inverse)
       
   605   apply simp
       
   606   done
       
   607 
       
   608 lemma revcast_rev_ucast': 
       
   609   "cs = [rc, uc] ==> rc = revcast (word_reverse w) ==> uc = ucast w ==> 
       
   610     rc = word_reverse uc"
       
   611   apply (unfold ucast_def revcast_def' Let_def word_reverse_def)
       
   612   apply (clarsimp simp add : to_bl_of_bin takefill_bintrunc)
       
   613   apply (simp add : word_bl.Abs_inverse word_size)
       
   614   done
       
   615 
       
   616 lemmas revcast_rev_ucast = revcast_rev_ucast' [OF refl refl refl]
       
   617 
       
   618 lemmas revcast_ucast = revcast_rev_ucast
       
   619   [where w = "word_reverse ?w1", simplified word_rev_rev, standard]
       
   620 
       
   621 lemmas ucast_revcast = revcast_rev_ucast [THEN word_rev_gal', standard]
       
   622 lemmas ucast_rev_revcast = revcast_ucast [THEN word_rev_gal', standard]
       
   623 
       
   624 
       
   625 -- "linking revcast and cast via shift"
       
   626 
       
   627 lemmas wsst_TYs = source_size target_size word_size
       
   628 
       
   629 lemma revcast_down_uu': 
       
   630   "rc = revcast ==> source_size rc = target_size rc + n ==> 
       
   631     rc (w :: 'a :: len word) = ucast (w >> n)"
       
   632   apply (simp add: revcast_def')
       
   633   apply (rule word_bl.Rep_inverse')
       
   634   apply (rule trans, rule ucast_down_drop)
       
   635    prefer 2
       
   636    apply (rule trans, rule drop_shiftr)
       
   637    apply (auto simp: takefill_alt wsst_TYs)
       
   638   done
       
   639 
       
   640 lemma revcast_down_us': 
       
   641   "rc = revcast ==> source_size rc = target_size rc + n ==> 
       
   642     rc (w :: 'a :: len word) = ucast (w >>> n)"
       
   643   apply (simp add: revcast_def')
       
   644   apply (rule word_bl.Rep_inverse')
       
   645   apply (rule trans, rule ucast_down_drop)
       
   646    prefer 2
       
   647    apply (rule trans, rule drop_sshiftr)
       
   648    apply (auto simp: takefill_alt wsst_TYs)
       
   649   done
       
   650 
       
   651 lemma revcast_down_su': 
       
   652   "rc = revcast ==> source_size rc = target_size rc + n ==> 
       
   653     rc (w :: 'a :: len word) = scast (w >> n)"
       
   654   apply (simp add: revcast_def')
       
   655   apply (rule word_bl.Rep_inverse')
       
   656   apply (rule trans, rule scast_down_drop)
       
   657    prefer 2
       
   658    apply (rule trans, rule drop_shiftr)
       
   659    apply (auto simp: takefill_alt wsst_TYs)
       
   660   done
       
   661 
       
   662 lemma revcast_down_ss': 
       
   663   "rc = revcast ==> source_size rc = target_size rc + n ==> 
       
   664     rc (w :: 'a :: len word) = scast (w >>> n)"
       
   665   apply (simp add: revcast_def')
       
   666   apply (rule word_bl.Rep_inverse')
       
   667   apply (rule trans, rule scast_down_drop)
       
   668    prefer 2
       
   669    apply (rule trans, rule drop_sshiftr)
       
   670    apply (auto simp: takefill_alt wsst_TYs)
       
   671   done
       
   672 
       
   673 lemmas revcast_down_uu = refl [THEN revcast_down_uu']
       
   674 lemmas revcast_down_us = refl [THEN revcast_down_us']
       
   675 lemmas revcast_down_su = refl [THEN revcast_down_su']
       
   676 lemmas revcast_down_ss = refl [THEN revcast_down_ss']
       
   677 
       
   678 lemma cast_down_rev: 
       
   679   "uc = ucast ==> source_size uc = target_size uc + n ==> 
       
   680     uc w = revcast ((w :: 'a :: len word) << n)"
       
   681   apply (unfold shiftl_rev)
       
   682   apply clarify
       
   683   apply (simp add: revcast_rev_ucast)
       
   684   apply (rule word_rev_gal')
       
   685   apply (rule trans [OF _ revcast_rev_ucast])
       
   686   apply (rule revcast_down_uu [symmetric])
       
   687   apply (auto simp add: wsst_TYs)
       
   688   done
       
   689 
       
   690 lemma revcast_up': 
       
   691   "rc = revcast ==> source_size rc + n = target_size rc ==> 
       
   692     rc w = (ucast w :: 'a :: len word) << n" 
       
   693   apply (simp add: revcast_def')
       
   694   apply (rule word_bl.Rep_inverse')
       
   695   apply (simp add: takefill_alt)
       
   696   apply (rule bl_shiftl [THEN trans])
       
   697   apply (subst ucast_up_app)
       
   698   apply (auto simp add: wsst_TYs)
       
   699   apply (drule sym)
       
   700   apply (simp add: min_def)
       
   701   done
       
   702 
       
   703 lemmas revcast_up = refl [THEN revcast_up']
       
   704 
       
   705 lemmas rc1 = revcast_up [THEN 
       
   706   revcast_rev_ucast [symmetric, THEN trans, THEN word_rev_gal, symmetric]]
       
   707 lemmas rc2 = revcast_down_uu [THEN 
       
   708   revcast_rev_ucast [symmetric, THEN trans, THEN word_rev_gal, symmetric]]
       
   709 
       
   710 lemmas ucast_up =
       
   711  rc1 [simplified rev_shiftr [symmetric] revcast_ucast [symmetric]]
       
   712 lemmas ucast_down = 
       
   713   rc2 [simplified rev_shiftr revcast_ucast [symmetric]]
       
   714 
       
   715 
       
   716 subsection "Slices"
       
   717 
       
   718 lemmas slice1_no_bin [simp] =
       
   719   slice1_def [where w="number_of ?w", unfolded to_bl_no_bin]
       
   720 
       
   721 lemmas slice_no_bin [simp] = 
       
   722    trans [OF slice_def [THEN meta_eq_to_obj_eq] 
       
   723              slice1_no_bin [THEN meta_eq_to_obj_eq], 
       
   724           unfolded word_size, standard]
       
   725 
       
   726 lemma slice1_0 [simp] : "slice1 n 0 = 0"
       
   727   unfolding slice1_def by (simp add : to_bl_0)
       
   728 
       
   729 lemma slice_0 [simp] : "slice n 0 = 0"
       
   730   unfolding slice_def by auto
       
   731 
       
   732 lemma slice_take': "slice n w = of_bl (take (size w - n) (to_bl w))"
       
   733   unfolding slice_def' slice1_def
       
   734   by (simp add : takefill_alt word_size)
       
   735 
       
   736 lemmas slice_take = slice_take' [unfolded word_size]
       
   737 
       
   738 -- "shiftr to a word of the same size is just slice, 
       
   739     slice is just shiftr then ucast"
       
   740 lemmas shiftr_slice = trans
       
   741   [OF shiftr_bl [THEN meta_eq_to_obj_eq] slice_take [symmetric], standard]
       
   742 
       
   743 lemma slice_shiftr: "slice n w = ucast (w >> n)"
       
   744   apply (unfold slice_take shiftr_bl)
       
   745   apply (rule ucast_of_bl_up [symmetric])
       
   746   apply (simp add: word_size)
       
   747   done
       
   748 
       
   749 lemma nth_slice: 
       
   750   "(slice n w :: 'a :: len0 word) !! m = 
       
   751    (w !! (m + n) & m < len_of TYPE ('a))"
       
   752   unfolding slice_shiftr 
       
   753   by (simp add : nth_ucast nth_shiftr)
       
   754 
       
   755 lemma slice1_down_alt': 
       
   756   "sl = slice1 n w ==> fs = size sl ==> fs + k = n ==> 
       
   757     to_bl sl = takefill False fs (drop k (to_bl w))"
       
   758   unfolding slice1_def word_size of_bl_def uint_bl
       
   759   by (clarsimp simp: word_ubin.eq_norm bl_bin_bl_rep_drop drop_takefill)
       
   760 
       
   761 lemma slice1_up_alt': 
       
   762   "sl = slice1 n w ==> fs = size sl ==> fs = n + k ==> 
       
   763     to_bl sl = takefill False fs (replicate k False @ (to_bl w))"
       
   764   apply (unfold slice1_def word_size of_bl_def uint_bl)
       
   765   apply (clarsimp simp: word_ubin.eq_norm bl_bin_bl_rep_drop 
       
   766                         takefill_append [symmetric])
       
   767   apply (rule_tac f = "%k. takefill False (len_of TYPE('a))
       
   768     (replicate k False @ bin_to_bl (len_of TYPE('b)) (uint w))" in arg_cong)
       
   769   apply arith
       
   770   done
       
   771     
       
   772 lemmas sd1 = slice1_down_alt' [OF refl refl, unfolded word_size]
       
   773 lemmas su1 = slice1_up_alt' [OF refl refl, unfolded word_size]
       
   774 lemmas slice1_down_alt = le_add_diff_inverse [THEN sd1]
       
   775 lemmas slice1_up_alts = 
       
   776   le_add_diff_inverse [symmetric, THEN su1] 
       
   777   le_add_diff_inverse2 [symmetric, THEN su1]
       
   778 
       
   779 lemma ucast_slice1: "ucast w = slice1 (size w) w"
       
   780   unfolding slice1_def ucast_bl
       
   781   by (simp add : takefill_same' word_size)
       
   782 
       
   783 lemma ucast_slice: "ucast w = slice 0 w"
       
   784   unfolding slice_def by (simp add : ucast_slice1)
       
   785 
       
   786 lemmas slice_id = trans [OF ucast_slice [symmetric] ucast_id]
       
   787 
       
   788 lemma revcast_slice1': 
       
   789   "rc = revcast w ==> slice1 (size rc) w = rc"
       
   790   unfolding slice1_def revcast_def' by (simp add : word_size)
       
   791 
       
   792 lemmas revcast_slice1 = refl [THEN revcast_slice1']
       
   793 
       
   794 lemma slice1_tf_tf': 
       
   795   "to_bl (slice1 n w :: 'a :: len0 word) = 
       
   796    rev (takefill False (len_of TYPE('a)) (rev (takefill False n (to_bl w))))"
       
   797   unfolding slice1_def by (rule word_rev_tf)
       
   798 
       
   799 lemmas slice1_tf_tf = slice1_tf_tf'
       
   800   [THEN word_bl.Rep_inverse', symmetric, standard]
       
   801 
       
   802 lemma rev_slice1:
       
   803   "n + k = len_of TYPE('a) + len_of TYPE('b) \<Longrightarrow> 
       
   804   slice1 n (word_reverse w :: 'b :: len0 word) = 
       
   805   word_reverse (slice1 k w :: 'a :: len0 word)"
       
   806   apply (unfold word_reverse_def slice1_tf_tf)
       
   807   apply (rule word_bl.Rep_inverse')
       
   808   apply (rule rev_swap [THEN iffD1])
       
   809   apply (rule trans [symmetric])
       
   810   apply (rule tf_rev)
       
   811    apply (simp add: word_bl.Abs_inverse)
       
   812   apply (simp add: word_bl.Abs_inverse)
       
   813   done
       
   814 
       
   815 lemma rev_slice': 
       
   816   "res = slice n (word_reverse w) ==> n + k + size res = size w ==> 
       
   817     res = word_reverse (slice k w)"
       
   818   apply (unfold slice_def word_size)
       
   819   apply clarify
       
   820   apply (rule rev_slice1)
       
   821   apply arith
       
   822   done
       
   823 
       
   824 lemmas rev_slice = refl [THEN rev_slice', unfolded word_size]
       
   825 
       
   826 lemmas sym_notr = 
       
   827   not_iff [THEN iffD2, THEN not_sym, THEN not_iff [THEN iffD1]]
       
   828 
       
   829 -- {* problem posed by TPHOLs referee:
       
   830       criterion for overflow of addition of signed integers *}
       
   831 
       
   832 lemma sofl_test:
       
   833   "(sint (x :: 'a :: len word) + sint y = sint (x + y)) = 
       
   834      ((((x+y) XOR x) AND ((x+y) XOR y)) >> (size x - 1) = 0)"
       
   835   apply (unfold word_size)
       
   836   apply (cases "len_of TYPE('a)", simp) 
       
   837   apply (subst msb_shift [THEN sym_notr])
       
   838   apply (simp add: word_ops_msb)
       
   839   apply (simp add: word_msb_sint)
       
   840   apply safe
       
   841        apply simp_all
       
   842      apply (unfold sint_word_ariths)
       
   843      apply (unfold word_sbin.set_iff_norm [symmetric] sints_num)
       
   844      apply safe
       
   845         apply (insert sint_range' [where x=x])
       
   846         apply (insert sint_range' [where x=y])
       
   847         defer 
       
   848         apply (simp (no_asm), arith)
       
   849        apply (simp (no_asm), arith)
       
   850       defer
       
   851       defer
       
   852       apply (simp (no_asm), arith)
       
   853      apply (simp (no_asm), arith)
       
   854     apply (rule notI [THEN notnotD],
       
   855            drule leI not_leE,
       
   856            drule sbintrunc_inc sbintrunc_dec,      
       
   857            simp)+
       
   858   done
       
   859 
       
   860 
       
   861 section "Split and cat"
       
   862 
       
   863 lemmas word_split_bin' = word_split_def [THEN meta_eq_to_obj_eq, standard]
       
   864 lemmas word_cat_bin' = word_cat_def [THEN meta_eq_to_obj_eq, standard]
       
   865 
       
   866 lemma word_rsplit_no:
       
   867   "(word_rsplit (number_of bin :: 'b :: len0 word) :: 'a word list) = 
       
   868     map number_of (bin_rsplit (len_of TYPE('a :: len)) 
       
   869       (len_of TYPE('b), bintrunc (len_of TYPE('b)) bin))"
       
   870   apply (unfold word_rsplit_def word_no_wi)
       
   871   apply (simp add: word_ubin.eq_norm)
       
   872   done
       
   873 
       
   874 lemmas word_rsplit_no_cl [simp] = word_rsplit_no
       
   875   [unfolded bin_rsplitl_def bin_rsplit_l [symmetric]]
       
   876 
       
   877 lemma test_bit_cat:
       
   878   "wc = word_cat a b ==> wc !! n = (n < size wc & 
       
   879     (if n < size b then b !! n else a !! (n - size b)))"
       
   880   apply (unfold word_cat_bin' test_bit_bin)
       
   881   apply (auto simp add : word_ubin.eq_norm nth_bintr bin_nth_cat word_size)
       
   882   apply (erule bin_nth_uint_imp)
       
   883   done
       
   884 
       
   885 lemma word_cat_bl: "word_cat a b = of_bl (to_bl a @ to_bl b)"
       
   886   apply (unfold of_bl_def to_bl_def word_cat_bin')
       
   887   apply (simp add: bl_to_bin_app_cat)
       
   888   done
       
   889 
       
   890 lemma of_bl_append:
       
   891   "(of_bl (xs @ ys) :: 'a :: len word) = of_bl xs * 2^(length ys) + of_bl ys"
       
   892   apply (unfold of_bl_def)
       
   893   apply (simp add: bl_to_bin_app_cat bin_cat_num)
       
   894   apply (simp add: word_of_int_power_hom [symmetric] new_word_of_int_hom_syms)
       
   895   done
       
   896 
       
   897 lemma of_bl_False [simp]:
       
   898   "of_bl (False#xs) = of_bl xs"
       
   899   by (rule word_eqI)
       
   900      (auto simp add: test_bit_of_bl nth_append)
       
   901 
       
   902 lemma of_bl_True: 
       
   903   "(of_bl (True#xs)::'a::len word) = 2^length xs + of_bl xs"
       
   904   by (subst of_bl_append [where xs="[True]", simplified])
       
   905      (simp add: word_1_bl)
       
   906 
       
   907 lemma of_bl_Cons:
       
   908   "of_bl (x#xs) = of_bool x * 2^length xs + of_bl xs"
       
   909   by (cases x) (simp_all add: of_bl_True)
       
   910 
       
   911 lemma split_uint_lem: "bin_split n (uint (w :: 'a :: len0 word)) = (a, b) ==> 
       
   912   a = bintrunc (len_of TYPE('a) - n) a & b = bintrunc (len_of TYPE('a)) b"
       
   913   apply (frule word_ubin.norm_Rep [THEN ssubst])
       
   914   apply (drule bin_split_trunc1)
       
   915   apply (drule sym [THEN trans])
       
   916   apply assumption
       
   917   apply safe
       
   918   done
       
   919 
       
   920 lemma word_split_bl': 
       
   921   "std = size c - size b ==> (word_split c = (a, b)) ==> 
       
   922     (a = of_bl (take std (to_bl c)) & b = of_bl (drop std (to_bl c)))"
       
   923   apply (unfold word_split_bin')
       
   924   apply safe
       
   925    defer
       
   926    apply (clarsimp split: prod.splits)
       
   927    apply (drule word_ubin.norm_Rep [THEN ssubst])
       
   928    apply (drule split_bintrunc)
       
   929    apply (simp add : of_bl_def bl2bin_drop word_size
       
   930        word_ubin.norm_eq_iff [symmetric] min_def del : word_ubin.norm_Rep)    
       
   931   apply (clarsimp split: prod.splits)
       
   932   apply (frule split_uint_lem [THEN conjunct1])
       
   933   apply (unfold word_size)
       
   934   apply (cases "len_of TYPE('a) >= len_of TYPE('b)")
       
   935    defer
       
   936    apply (simp add: word_0_bl word_0_wi_Pls)
       
   937   apply (simp add : of_bl_def to_bl_def)
       
   938   apply (subst bin_split_take1 [symmetric])
       
   939     prefer 2
       
   940     apply assumption
       
   941    apply simp
       
   942   apply (erule thin_rl)
       
   943   apply (erule arg_cong [THEN trans])
       
   944   apply (simp add : word_ubin.norm_eq_iff [symmetric])
       
   945   done
       
   946 
       
   947 lemma word_split_bl: "std = size c - size b ==> 
       
   948     (a = of_bl (take std (to_bl c)) & b = of_bl (drop std (to_bl c))) <-> 
       
   949     word_split c = (a, b)"
       
   950   apply (rule iffI)
       
   951    defer
       
   952    apply (erule (1) word_split_bl')
       
   953   apply (case_tac "word_split c")
       
   954   apply (auto simp add : word_size)
       
   955   apply (frule word_split_bl' [rotated])
       
   956   apply (auto simp add : word_size)
       
   957   done
       
   958 
       
   959 lemma word_split_bl_eq:
       
   960    "(word_split (c::'a::len word) :: ('c :: len0 word * 'd :: len0 word)) =
       
   961       (of_bl (take (len_of TYPE('a::len) - len_of TYPE('d::len0)) (to_bl c)),
       
   962        of_bl (drop (len_of TYPE('a) - len_of TYPE('d)) (to_bl c)))"
       
   963   apply (rule word_split_bl [THEN iffD1])
       
   964   apply (unfold word_size)
       
   965   apply (rule refl conjI)+
       
   966   done
       
   967 
       
   968 -- "keep quantifiers for use in simplification"
       
   969 lemma test_bit_split':
       
   970   "word_split c = (a, b) --> (ALL n m. b !! n = (n < size b & c !! n) & 
       
   971     a !! m = (m < size a & c !! (m + size b)))"
       
   972   apply (unfold word_split_bin' test_bit_bin)
       
   973   apply (clarify)
       
   974   apply (clarsimp simp: word_ubin.eq_norm nth_bintr word_size split: prod.splits)
       
   975   apply (drule bin_nth_split)
       
   976   apply safe
       
   977        apply (simp_all add: add_commute)
       
   978    apply (erule bin_nth_uint_imp)+
       
   979   done
       
   980 
       
   981 lemmas test_bit_split = 
       
   982   test_bit_split' [THEN mp, simplified all_simps, standard]
       
   983 
       
   984 lemma test_bit_split_eq: "word_split c = (a, b) <-> 
       
   985   ((ALL n::nat. b !! n = (n < size b & c !! n)) &
       
   986     (ALL m::nat. a !! m = (m < size a & c !! (m + size b))))"
       
   987   apply (rule_tac iffI)
       
   988    apply (rule_tac conjI)
       
   989     apply (erule test_bit_split [THEN conjunct1])
       
   990    apply (erule test_bit_split [THEN conjunct2])
       
   991   apply (case_tac "word_split c")
       
   992   apply (frule test_bit_split)
       
   993   apply (erule trans)
       
   994   apply (fastsimp intro ! : word_eqI simp add : word_size)
       
   995   done
       
   996 
       
   997 -- {* this odd result is analogous to ucast\_id, 
       
   998       result to the length given by the result type *}
       
   999 
       
  1000 lemma word_cat_id: "word_cat a b = b"
       
  1001   unfolding word_cat_bin' by (simp add: word_ubin.inverse_norm)
       
  1002 
       
  1003 -- "limited hom result"
       
  1004 lemma word_cat_hom:
       
  1005   "len_of TYPE('a::len0) <= len_of TYPE('b::len0) + len_of TYPE ('c::len0)
       
  1006   ==>
       
  1007   (word_cat (word_of_int w :: 'b word) (b :: 'c word) :: 'a word) = 
       
  1008   word_of_int (bin_cat w (size b) (uint b))"
       
  1009   apply (unfold word_cat_def word_size) 
       
  1010   apply (clarsimp simp add : word_ubin.norm_eq_iff [symmetric]
       
  1011       word_ubin.eq_norm bintr_cat min_def)
       
  1012   apply arith
       
  1013   done
       
  1014 
       
  1015 lemma word_cat_split_alt:
       
  1016   "size w <= size u + size v ==> word_split w = (u, v) ==> word_cat u v = w"
       
  1017   apply (rule word_eqI)
       
  1018   apply (drule test_bit_split)
       
  1019   apply (clarsimp simp add : test_bit_cat word_size)
       
  1020   apply safe
       
  1021   apply arith
       
  1022   done
       
  1023 
       
  1024 lemmas word_cat_split_size = 
       
  1025   sym [THEN [2] word_cat_split_alt [symmetric], standard]
       
  1026 
       
  1027 
       
  1028 subsection "Split and slice"
       
  1029 
       
  1030 lemma split_slices: 
       
  1031   "word_split w = (u, v) ==> u = slice (size v) w & v = slice 0 w"
       
  1032   apply (drule test_bit_split)
       
  1033   apply (rule conjI)
       
  1034    apply (rule word_eqI, clarsimp simp: nth_slice word_size)+
       
  1035   done
       
  1036 
       
  1037 lemma slice_cat1':
       
  1038   "wc = word_cat a b ==> size wc >= size a + size b ==> slice (size b) wc = a"
       
  1039   apply safe
       
  1040   apply (rule word_eqI)
       
  1041   apply (simp add: nth_slice test_bit_cat word_size)
       
  1042   done
       
  1043 
       
  1044 lemmas slice_cat1 = refl [THEN slice_cat1']
       
  1045 lemmas slice_cat2 = trans [OF slice_id word_cat_id]
       
  1046 
       
  1047 lemma cat_slices:
       
  1048   "a = slice n c ==> b = slice 0 c ==> n = size b ==> \  
       
  1049     size a + size b >= size c ==> word_cat a b = c"
       
  1050   apply safe
       
  1051   apply (rule word_eqI)
       
  1052   apply (simp add: nth_slice test_bit_cat word_size)
       
  1053   apply safe
       
  1054   apply arith
       
  1055   done
       
  1056 
       
  1057 lemma word_split_cat_alt:
       
  1058   "w = word_cat u v ==> size u + size v <= size w ==> word_split w = (u, v)"
       
  1059   apply (case_tac "word_split ?w")
       
  1060   apply (rule trans, assumption)
       
  1061   apply (drule test_bit_split)
       
  1062   apply safe
       
  1063    apply (rule word_eqI, clarsimp simp: test_bit_cat word_size)+
       
  1064   done
       
  1065 
       
  1066 lemmas word_cat_bl_no_bin [simp] =
       
  1067   word_cat_bl [where a="number_of ?a" 
       
  1068                  and b="number_of ?b", 
       
  1069                unfolded to_bl_no_bin]
       
  1070 
       
  1071 lemmas word_split_bl_no_bin [simp] =
       
  1072   word_split_bl_eq [where c="number_of ?c", unfolded to_bl_no_bin]
       
  1073 
       
  1074 -- {* this odd result arises from the fact that the statement of the
       
  1075       result implies that the decoded words are of the same type, 
       
  1076       and therefore of the same length, as the original word *}
       
  1077 
       
  1078 lemma word_rsplit_same: "word_rsplit w = [w]"
       
  1079   unfolding word_rsplit_def by (simp add : bin_rsplit_all)
       
  1080 
       
  1081 lemma word_rsplit_empty_iff_size:
       
  1082   "(word_rsplit w = []) = (size w = 0)" 
       
  1083   unfolding word_rsplit_def bin_rsplit_def word_size
       
  1084   by (simp add: bin_rsplit_aux_simp_alt Let_def split: split_split)
       
  1085 
       
  1086 lemma test_bit_rsplit:
       
  1087   "sw = word_rsplit w ==> m < size (hd sw :: 'a :: len word) ==> 
       
  1088     k < length sw ==> (rev sw ! k) !! m = (w !! (k * size (hd sw) + m))"
       
  1089   apply (unfold word_rsplit_def word_test_bit_def)
       
  1090   apply (rule trans)
       
  1091    apply (rule_tac f = "%x. bin_nth x m" in arg_cong)
       
  1092    apply (rule nth_map [symmetric])
       
  1093    apply simp
       
  1094   apply (rule bin_nth_rsplit)
       
  1095      apply simp_all
       
  1096   apply (simp add : word_size rev_map map_compose [symmetric])
       
  1097   apply (rule trans)
       
  1098    defer
       
  1099    apply (rule map_ident [THEN fun_cong])
       
  1100   apply (rule refl [THEN map_cong])
       
  1101   apply (simp add : word_ubin.eq_norm)
       
  1102   apply (erule bin_rsplit_size_sign [OF len_gt_0 refl])
       
  1103   done
       
  1104 
       
  1105 lemma word_rcat_bl: "word_rcat wl == of_bl (concat (map to_bl wl))"
       
  1106   unfolding word_rcat_def to_bl_def' of_bl_def
       
  1107   by (clarsimp simp add : bin_rcat_bl map_compose)
       
  1108 
       
  1109 lemma size_rcat_lem':
       
  1110   "size (concat (map to_bl wl)) = length wl * size (hd wl)"
       
  1111   unfolding word_size by (induct wl) auto
       
  1112 
       
  1113 lemmas size_rcat_lem = size_rcat_lem' [unfolded word_size]
       
  1114 
       
  1115 lemmas td_gal_lt_len = len_gt_0 [THEN td_gal_lt, standard]
       
  1116 
       
  1117 lemma nth_rcat_lem' [rule_format] :
       
  1118   "sw = size (hd wl  :: 'a :: len word) ==> (ALL n. n < size wl * sw --> 
       
  1119     rev (concat (map to_bl wl)) ! n = 
       
  1120     rev (to_bl (rev wl ! (n div sw))) ! (n mod sw))"
       
  1121   apply (unfold word_size)
       
  1122   apply (induct "wl")
       
  1123    apply clarsimp
       
  1124   apply (clarsimp simp add : nth_append size_rcat_lem)
       
  1125   apply (simp (no_asm_use) only:  mult_Suc [symmetric] 
       
  1126          td_gal_lt_len less_Suc_eq_le mod_div_equality')
       
  1127   apply clarsimp
       
  1128   done
       
  1129 
       
  1130 lemmas nth_rcat_lem = refl [THEN nth_rcat_lem', unfolded word_size]
       
  1131 
       
  1132 lemma test_bit_rcat:
       
  1133   "sw = size (hd wl :: 'a :: len word) ==> rc = word_rcat wl ==> rc !! n = 
       
  1134     (n < size rc & n div sw < size wl & (rev wl) ! (n div sw) !! (n mod sw))"
       
  1135   apply (unfold word_rcat_bl word_size)
       
  1136   apply (clarsimp simp add : 
       
  1137     test_bit_of_bl size_rcat_lem word_size td_gal_lt_len)
       
  1138   apply safe
       
  1139    apply (auto simp add : 
       
  1140     test_bit_bl word_size td_gal_lt_len [THEN iffD2, THEN nth_rcat_lem])
       
  1141   done
       
  1142 
       
  1143 lemma foldl_eq_foldr [rule_format] :
       
  1144   "ALL x. foldl op + x xs = foldr op + (x # xs) (0 :: 'a :: comm_monoid_add)" 
       
  1145   by (induct xs) (auto simp add : add_assoc)
       
  1146 
       
  1147 lemmas test_bit_cong = arg_cong [where f = "test_bit", THEN fun_cong]
       
  1148 
       
  1149 lemmas test_bit_rsplit_alt = 
       
  1150   trans [OF nth_rev_alt [THEN test_bit_cong] 
       
  1151   test_bit_rsplit [OF refl asm_rl diff_Suc_less]]
       
  1152 
       
  1153 -- "lazy way of expressing that u and v, and su and sv, have same types"
       
  1154 lemma word_rsplit_len_indep':
       
  1155   "[u,v] = p ==> [su,sv] = q ==> word_rsplit u = su ==> 
       
  1156     word_rsplit v = sv ==> length su = length sv"
       
  1157   apply (unfold word_rsplit_def)
       
  1158   apply (auto simp add : bin_rsplit_len_indep)
       
  1159   done
       
  1160 
       
  1161 lemmas word_rsplit_len_indep = word_rsplit_len_indep' [OF refl refl refl refl]
       
  1162 
       
  1163 lemma length_word_rsplit_size: 
       
  1164   "n = len_of TYPE ('a :: len) ==> 
       
  1165     (length (word_rsplit w :: 'a word list) <= m) = (size w <= m * n)"
       
  1166   apply (unfold word_rsplit_def word_size)
       
  1167   apply (clarsimp simp add : bin_rsplit_len_le)
       
  1168   done
       
  1169 
       
  1170 lemmas length_word_rsplit_lt_size = 
       
  1171   length_word_rsplit_size [unfolded Not_eq_iff linorder_not_less [symmetric]]
       
  1172 
       
  1173 lemma length_word_rsplit_exp_size: 
       
  1174   "n = len_of TYPE ('a :: len) ==> 
       
  1175     length (word_rsplit w :: 'a word list) = (size w + n - 1) div n"
       
  1176   unfolding word_rsplit_def by (clarsimp simp add : word_size bin_rsplit_len)
       
  1177 
       
  1178 lemma length_word_rsplit_even_size: 
       
  1179   "n = len_of TYPE ('a :: len) ==> size w = m * n ==> 
       
  1180     length (word_rsplit w :: 'a word list) = m"
       
  1181   by (clarsimp simp add : length_word_rsplit_exp_size given_quot_alt)
       
  1182 
       
  1183 lemmas length_word_rsplit_exp_size' = refl [THEN length_word_rsplit_exp_size]
       
  1184 
       
  1185 (* alternative proof of word_rcat_rsplit *)
       
  1186 lemmas tdle = iffD2 [OF split_div_lemma refl, THEN conjunct1] 
       
  1187 lemmas dtle = xtr4 [OF tdle mult_commute]
       
  1188 
       
  1189 lemma word_rcat_rsplit: "word_rcat (word_rsplit w) = w"
       
  1190   apply (rule word_eqI)
       
  1191   apply (clarsimp simp add : test_bit_rcat word_size)
       
  1192   apply (subst refl [THEN test_bit_rsplit])
       
  1193     apply (simp_all add: word_size 
       
  1194       refl [THEN length_word_rsplit_size [simplified le_def, simplified]])
       
  1195    apply safe
       
  1196    apply (erule xtr7, rule len_gt_0 [THEN dtle])+
       
  1197   done
       
  1198 
       
  1199 lemma size_word_rsplit_rcat_size':
       
  1200   "word_rcat (ws :: 'a :: len word list) = frcw ==> 
       
  1201     size frcw = length ws * len_of TYPE ('a) ==> 
       
  1202     size (hd [word_rsplit frcw, ws]) = size ws" 
       
  1203   apply (clarsimp simp add : word_size length_word_rsplit_exp_size')
       
  1204   apply (fast intro: given_quot_alt)
       
  1205   done
       
  1206 
       
  1207 lemmas size_word_rsplit_rcat_size = 
       
  1208   size_word_rsplit_rcat_size' [simplified]
       
  1209 
       
  1210 lemma msrevs:
       
  1211   fixes n::nat
       
  1212   shows "0 < n \<Longrightarrow> (k * n + m) div n = m div n + k"
       
  1213   and   "(k * n + m) mod n = m mod n"
       
  1214   by (auto simp: add_commute)
       
  1215 
       
  1216 lemma word_rsplit_rcat_size':
       
  1217   "word_rcat (ws :: 'a :: len word list) = frcw ==> 
       
  1218     size frcw = length ws * len_of TYPE ('a) ==> word_rsplit frcw = ws" 
       
  1219   apply (frule size_word_rsplit_rcat_size, assumption)
       
  1220   apply (clarsimp simp add : word_size)
       
  1221   apply (rule nth_equalityI, assumption)
       
  1222   apply clarsimp
       
  1223   apply (rule word_eqI)
       
  1224   apply (rule trans)
       
  1225    apply (rule test_bit_rsplit_alt)
       
  1226      apply (clarsimp simp: word_size)+
       
  1227   apply (rule trans)
       
  1228   apply (rule test_bit_rcat [OF refl refl])
       
  1229   apply (simp add : word_size msrevs)
       
  1230   apply (subst nth_rev)
       
  1231    apply arith
       
  1232   apply (simp add : le0 [THEN [2] xtr7, THEN diff_Suc_less])
       
  1233   apply safe
       
  1234   apply (simp add : diff_mult_distrib)
       
  1235   apply (rule mpl_lem)
       
  1236   apply (cases "size ws")
       
  1237    apply simp_all
       
  1238   done
       
  1239 
       
  1240 lemmas word_rsplit_rcat_size = refl [THEN word_rsplit_rcat_size']
       
  1241 
       
  1242 
       
  1243 section "Rotation"
       
  1244 
       
  1245 lemmas rotater_0' [simp] = rotater_def [where n = "0", simplified]
       
  1246 
       
  1247 lemmas word_rot_defs = word_roti_def word_rotr_def word_rotl_def
       
  1248 
       
  1249 lemma rotate_eq_mod: 
       
  1250   "m mod length xs = n mod length xs ==> rotate m xs = rotate n xs"
       
  1251   apply (rule box_equals)
       
  1252     defer
       
  1253     apply (rule rotate_conv_mod [symmetric])+
       
  1254   apply simp
       
  1255   done
       
  1256 
       
  1257 lemmas rotate_eqs [standard] = 
       
  1258   trans [OF rotate0 [THEN fun_cong] id_apply]
       
  1259   rotate_rotate [symmetric] 
       
  1260   rotate_id 
       
  1261   rotate_conv_mod 
       
  1262   rotate_eq_mod
       
  1263 
       
  1264 
       
  1265 subsection "Rotation of list to right"
       
  1266 
       
  1267 lemma rotate1_rl': "rotater1 (l @ [a]) = a # l"
       
  1268   unfolding rotater1_def by (cases l) auto
       
  1269 
       
  1270 lemma rotate1_rl [simp] : "rotater1 (rotate1 l) = l"
       
  1271   apply (unfold rotater1_def)
       
  1272   apply (cases "l")
       
  1273   apply (case_tac [2] "list")
       
  1274   apply auto
       
  1275   done
       
  1276 
       
  1277 lemma rotate1_lr [simp] : "rotate1 (rotater1 l) = l"
       
  1278   unfolding rotater1_def by (cases l) auto
       
  1279 
       
  1280 lemma rotater1_rev': "rotater1 (rev xs) = rev (rotate1 xs)"
       
  1281   apply (cases "xs")
       
  1282   apply (simp add : rotater1_def)
       
  1283   apply (simp add : rotate1_rl')
       
  1284   done
       
  1285   
       
  1286 lemma rotater_rev': "rotater n (rev xs) = rev (rotate n xs)"
       
  1287   unfolding rotater_def by (induct n) (auto intro: rotater1_rev')
       
  1288 
       
  1289 lemmas rotater_rev = rotater_rev' [where xs = "rev ?ys", simplified]
       
  1290 
       
  1291 lemma rotater_drop_take: 
       
  1292   "rotater n xs = 
       
  1293    drop (length xs - n mod length xs) xs @
       
  1294    take (length xs - n mod length xs) xs"
       
  1295   by (clarsimp simp add : rotater_rev rotate_drop_take rev_take rev_drop)
       
  1296 
       
  1297 lemma rotater_Suc [simp] : 
       
  1298   "rotater (Suc n) xs = rotater1 (rotater n xs)"
       
  1299   unfolding rotater_def by auto
       
  1300 
       
  1301 lemma rotate_inv_plus [rule_format] :
       
  1302   "ALL k. k = m + n --> rotater k (rotate n xs) = rotater m xs & 
       
  1303     rotate k (rotater n xs) = rotate m xs & 
       
  1304     rotater n (rotate k xs) = rotate m xs & 
       
  1305     rotate n (rotater k xs) = rotater m xs"
       
  1306   unfolding rotater_def rotate_def
       
  1307   by (induct n) (auto intro: funpow_swap1 [THEN trans])
       
  1308   
       
  1309 lemmas rotate_inv_rel = le_add_diff_inverse2 [symmetric, THEN rotate_inv_plus]
       
  1310 
       
  1311 lemmas rotate_inv_eq = order_refl [THEN rotate_inv_rel, simplified]
       
  1312 
       
  1313 lemmas rotate_lr [simp] = rotate_inv_eq [THEN conjunct1, standard]
       
  1314 lemmas rotate_rl [simp] =
       
  1315   rotate_inv_eq [THEN conjunct2, THEN conjunct1, standard]
       
  1316 
       
  1317 lemma rotate_gal: "(rotater n xs = ys) = (rotate n ys = xs)"
       
  1318   by auto
       
  1319 
       
  1320 lemma rotate_gal': "(ys = rotater n xs) = (xs = rotate n ys)"
       
  1321   by auto
       
  1322 
       
  1323 lemma length_rotater [simp]: 
       
  1324   "length (rotater n xs) = length xs"
       
  1325   by (simp add : rotater_rev)
       
  1326 
       
  1327 lemmas rrs0 = rotate_eqs [THEN restrict_to_left, 
       
  1328   simplified rotate_gal [symmetric] rotate_gal' [symmetric], standard]
       
  1329 lemmas rrs1 = rrs0 [THEN refl [THEN rev_iffD1]]
       
  1330 lemmas rotater_eqs = rrs1 [simplified length_rotater, standard]
       
  1331 lemmas rotater_0 = rotater_eqs (1)
       
  1332 lemmas rotater_add = rotater_eqs (2)
       
  1333 
       
  1334 
       
  1335 subsection "map, app2, commuting with rotate(r)"
       
  1336 
       
  1337 lemma last_map: "xs ~= [] ==> last (map f xs) = f (last xs)"
       
  1338   by (induct xs) auto
       
  1339 
       
  1340 lemma butlast_map:
       
  1341   "xs ~= [] ==> butlast (map f xs) = map f (butlast xs)"
       
  1342   by (induct xs) auto
       
  1343 
       
  1344 lemma rotater1_map: "rotater1 (map f xs) = map f (rotater1 xs)" 
       
  1345   unfolding rotater1_def
       
  1346   by (cases xs) (auto simp add: last_map butlast_map)
       
  1347 
       
  1348 lemma rotater_map:
       
  1349   "rotater n (map f xs) = map f (rotater n xs)" 
       
  1350   unfolding rotater_def
       
  1351   by (induct n) (auto simp add : rotater1_map)
       
  1352 
       
  1353 lemma but_last_zip [rule_format] :
       
  1354   "ALL ys. length xs = length ys --> xs ~= [] --> 
       
  1355     last (zip xs ys) = (last xs, last ys) & 
       
  1356     butlast (zip xs ys) = zip (butlast xs) (butlast ys)" 
       
  1357   apply (induct "xs")
       
  1358   apply auto
       
  1359      apply ((case_tac ys, auto simp: neq_Nil_conv)[1])+
       
  1360   done
       
  1361 
       
  1362 lemma but_last_app2 [rule_format] :
       
  1363   "ALL ys. length xs = length ys --> xs ~= [] --> 
       
  1364     last (app2 f xs ys) = f (last xs) (last ys) & 
       
  1365     butlast (app2 f xs ys) = app2 f (butlast xs) (butlast ys)" 
       
  1366   apply (induct "xs")
       
  1367   apply auto
       
  1368      apply (unfold app2_def)
       
  1369      apply ((case_tac ys, auto simp: neq_Nil_conv)[1])+
       
  1370   done
       
  1371 
       
  1372 lemma rotater1_zip:
       
  1373   "length xs = length ys ==> 
       
  1374     rotater1 (zip xs ys) = zip (rotater1 xs) (rotater1 ys)" 
       
  1375   apply (unfold rotater1_def)
       
  1376   apply (cases "xs")
       
  1377    apply auto
       
  1378    apply ((case_tac ys, auto simp: neq_Nil_conv but_last_zip)[1])+
       
  1379   done
       
  1380 
       
  1381 lemma rotater1_app2:
       
  1382   "length xs = length ys ==> 
       
  1383     rotater1 (app2 f xs ys) = app2 f (rotater1 xs) (rotater1 ys)" 
       
  1384   unfolding app2_def by (simp add: rotater1_map rotater1_zip)
       
  1385 
       
  1386 lemmas lrth = 
       
  1387   box_equals [OF asm_rl length_rotater [symmetric] 
       
  1388                  length_rotater [symmetric], 
       
  1389               THEN rotater1_app2]
       
  1390 
       
  1391 lemma rotater_app2: 
       
  1392   "length xs = length ys ==> 
       
  1393     rotater n (app2 f xs ys) = app2 f (rotater n xs) (rotater n ys)" 
       
  1394   by (induct n) (auto intro!: lrth)
       
  1395 
       
  1396 lemma rotate1_app2:
       
  1397   "length xs = length ys ==> 
       
  1398     rotate1 (app2 f xs ys) = app2 f (rotate1 xs) (rotate1 ys)" 
       
  1399   apply (unfold app2_def)
       
  1400   apply (cases xs)
       
  1401    apply (cases ys, auto simp add : rotate1_def)+
       
  1402   done
       
  1403 
       
  1404 lemmas lth = box_equals [OF asm_rl length_rotate [symmetric] 
       
  1405   length_rotate [symmetric], THEN rotate1_app2]
       
  1406 
       
  1407 lemma rotate_app2: 
       
  1408   "length xs = length ys ==> 
       
  1409     rotate n (app2 f xs ys) = app2 f (rotate n xs) (rotate n ys)" 
       
  1410   by (induct n) (auto intro!: lth)
       
  1411 
       
  1412 
       
  1413 -- "corresponding equalities for word rotation"
       
  1414 
       
  1415 lemma to_bl_rotl: 
       
  1416   "to_bl (word_rotl n w) = rotate n (to_bl w)"
       
  1417   by (simp add: word_bl.Abs_inverse' word_rotl_def)
       
  1418 
       
  1419 lemmas blrs0 = rotate_eqs [THEN to_bl_rotl [THEN trans]]
       
  1420 
       
  1421 lemmas word_rotl_eqs =
       
  1422   blrs0 [simplified word_bl.Rep' word_bl.Rep_inject to_bl_rotl [symmetric]]
       
  1423 
       
  1424 lemma to_bl_rotr: 
       
  1425   "to_bl (word_rotr n w) = rotater n (to_bl w)"
       
  1426   by (simp add: word_bl.Abs_inverse' word_rotr_def)
       
  1427 
       
  1428 lemmas brrs0 = rotater_eqs [THEN to_bl_rotr [THEN trans]]
       
  1429 
       
  1430 lemmas word_rotr_eqs =
       
  1431   brrs0 [simplified word_bl.Rep' word_bl.Rep_inject to_bl_rotr [symmetric]]
       
  1432 
       
  1433 declare word_rotr_eqs (1) [simp]
       
  1434 declare word_rotl_eqs (1) [simp]
       
  1435 
       
  1436 lemma
       
  1437   word_rot_rl [simp]:
       
  1438   "word_rotl k (word_rotr k v) = v" and
       
  1439   word_rot_lr [simp]:
       
  1440   "word_rotr k (word_rotl k v) = v"
       
  1441   by (auto simp add: to_bl_rotr to_bl_rotl word_bl.Rep_inject [symmetric])
       
  1442 
       
  1443 lemma
       
  1444   word_rot_gal:
       
  1445   "(word_rotr n v = w) = (word_rotl n w = v)" and
       
  1446   word_rot_gal':
       
  1447   "(w = word_rotr n v) = (v = word_rotl n w)"
       
  1448   by (auto simp: to_bl_rotr to_bl_rotl word_bl.Rep_inject [symmetric] 
       
  1449            dest: sym)
       
  1450 
       
  1451 lemma word_rotr_rev:
       
  1452   "word_rotr n w = word_reverse (word_rotl n (word_reverse w))"
       
  1453   by (simp add: word_bl.Rep_inject [symmetric] to_bl_word_rev
       
  1454                 to_bl_rotr to_bl_rotl rotater_rev)
       
  1455   
       
  1456 lemma word_roti_0 [simp]: "word_roti 0 w = w"
       
  1457   by (unfold word_rot_defs) auto
       
  1458 
       
  1459 lemmas abl_cong = arg_cong [where f = "of_bl"]
       
  1460 
       
  1461 lemma word_roti_add: 
       
  1462   "word_roti (m + n) w = word_roti m (word_roti n w)"
       
  1463 proof -
       
  1464   have rotater_eq_lem: 
       
  1465     "\<And>m n xs. m = n ==> rotater m xs = rotater n xs"
       
  1466     by auto
       
  1467 
       
  1468   have rotate_eq_lem: 
       
  1469     "\<And>m n xs. m = n ==> rotate m xs = rotate n xs"
       
  1470     by auto
       
  1471 
       
  1472   note rpts [symmetric, standard] = 
       
  1473     rotate_inv_plus [THEN conjunct1]
       
  1474     rotate_inv_plus [THEN conjunct2, THEN conjunct1]
       
  1475     rotate_inv_plus [THEN conjunct2, THEN conjunct2, THEN conjunct1]
       
  1476     rotate_inv_plus [THEN conjunct2, THEN conjunct2, THEN conjunct2]
       
  1477 
       
  1478   note rrp = trans [symmetric, OF rotate_rotate rotate_eq_lem]
       
  1479   note rrrp = trans [symmetric, OF rotater_add [symmetric] rotater_eq_lem]
       
  1480 
       
  1481   show ?thesis
       
  1482   apply (unfold word_rot_defs)
       
  1483   apply (simp only: split: split_if)
       
  1484   apply (safe intro!: abl_cong)
       
  1485   apply (simp_all only: to_bl_rotl [THEN word_bl.Rep_inverse'] 
       
  1486                     to_bl_rotl
       
  1487                     to_bl_rotr [THEN word_bl.Rep_inverse']
       
  1488                     to_bl_rotr)
       
  1489   apply (rule rrp rrrp rpts,
       
  1490          simp add: nat_add_distrib [symmetric] 
       
  1491                    nat_diff_distrib [symmetric])+
       
  1492   done
       
  1493 qed
       
  1494     
       
  1495 lemma word_roti_conv_mod': "word_roti n w = word_roti (n mod int (size w)) w"
       
  1496   apply (unfold word_rot_defs)
       
  1497   apply (cut_tac y="size w" in gt_or_eq_0)
       
  1498   apply (erule disjE)
       
  1499    apply simp_all
       
  1500   apply (safe intro!: abl_cong)
       
  1501    apply (rule rotater_eqs)
       
  1502    apply (simp add: word_size nat_mod_distrib)
       
  1503   apply (simp add: rotater_add [symmetric] rotate_gal [symmetric])
       
  1504   apply (rule rotater_eqs)
       
  1505   apply (simp add: word_size nat_mod_distrib)
       
  1506   apply (rule int_eq_0_conv [THEN iffD1])
       
  1507   apply (simp only: zmod_int zadd_int [symmetric])
       
  1508   apply (simp add: rdmods)
       
  1509   done
       
  1510 
       
  1511 lemmas word_roti_conv_mod = word_roti_conv_mod' [unfolded word_size]
       
  1512 
       
  1513 
       
  1514 subsection "Word rotation commutes with bit-wise operations"
       
  1515 
       
  1516 (* using locale to not pollute lemma namespace *)
       
  1517 locale word_rotate 
       
  1518 
       
  1519 context word_rotate
       
  1520 begin
       
  1521 
       
  1522 lemmas word_rot_defs' = to_bl_rotl to_bl_rotr
       
  1523 
       
  1524 lemmas blwl_syms [symmetric] = bl_word_not bl_word_and bl_word_or bl_word_xor
       
  1525 
       
  1526 lemmas lbl_lbl = trans [OF word_bl.Rep' word_bl.Rep' [symmetric]]
       
  1527 
       
  1528 lemmas ths_app2 [OF lbl_lbl] = rotate_app2 rotater_app2
       
  1529 
       
  1530 lemmas ths_map [where xs = "to_bl v"] = rotate_map rotater_map
       
  1531 
       
  1532 lemmas th1s [simplified word_rot_defs' [symmetric]] = ths_app2 ths_map
       
  1533 
       
  1534 lemma word_rot_logs:
       
  1535   "word_rotl n (NOT v) = NOT word_rotl n v"
       
  1536   "word_rotr n (NOT v) = NOT word_rotr n v"
       
  1537   "word_rotl n (x AND y) = word_rotl n x AND word_rotl n y"
       
  1538   "word_rotr n (x AND y) = word_rotr n x AND word_rotr n y"
       
  1539   "word_rotl n (x OR y) = word_rotl n x OR word_rotl n y"
       
  1540   "word_rotr n (x OR y) = word_rotr n x OR word_rotr n y"
       
  1541   "word_rotl n (x XOR y) = word_rotl n x XOR word_rotl n y"
       
  1542   "word_rotr n (x XOR y) = word_rotr n x XOR word_rotr n y"  
       
  1543   by (rule word_bl.Rep_eqD,
       
  1544       rule word_rot_defs' [THEN trans],
       
  1545       simp only: blwl_syms [symmetric],
       
  1546       rule th1s [THEN trans], 
       
  1547       rule refl)+
       
  1548 end
       
  1549 
       
  1550 lemmas word_rot_logs = word_rotate.word_rot_logs
       
  1551 
       
  1552 lemmas bl_word_rotl_dt = trans [OF to_bl_rotl rotate_drop_take,
       
  1553   simplified word_bl.Rep', standard]
       
  1554 
       
  1555 lemmas bl_word_rotr_dt = trans [OF to_bl_rotr rotater_drop_take,
       
  1556   simplified word_bl.Rep', standard]
       
  1557 
       
  1558 lemma bl_word_roti_dt': 
       
  1559   "n = nat ((- i) mod int (size (w :: 'a :: len word))) ==> 
       
  1560     to_bl (word_roti i w) = drop n (to_bl w) @ take n (to_bl w)"
       
  1561   apply (unfold word_roti_def)
       
  1562   apply (simp add: bl_word_rotl_dt bl_word_rotr_dt word_size)
       
  1563   apply safe
       
  1564    apply (simp add: zmod_zminus1_eq_if)
       
  1565    apply safe
       
  1566     apply (simp add: nat_mult_distrib)
       
  1567    apply (simp add: nat_diff_distrib [OF pos_mod_sign pos_mod_conj 
       
  1568                                       [THEN conjunct2, THEN order_less_imp_le]]
       
  1569                     nat_mod_distrib)
       
  1570   apply (simp add: nat_mod_distrib)
       
  1571   done
       
  1572 
       
  1573 lemmas bl_word_roti_dt = bl_word_roti_dt' [unfolded word_size]
       
  1574 
       
  1575 lemmas word_rotl_dt = bl_word_rotl_dt 
       
  1576   [THEN word_bl.Rep_inverse' [symmetric], standard] 
       
  1577 lemmas word_rotr_dt = bl_word_rotr_dt 
       
  1578   [THEN word_bl.Rep_inverse' [symmetric], standard]
       
  1579 lemmas word_roti_dt = bl_word_roti_dt 
       
  1580   [THEN word_bl.Rep_inverse' [symmetric], standard]
       
  1581 
       
  1582 lemma word_rotx_0 [simp] : "word_rotr i 0 = 0 & word_rotl i 0 = 0"
       
  1583   by (simp add : word_rotr_dt word_rotl_dt to_bl_0 replicate_add [symmetric])
       
  1584 
       
  1585 lemma word_roti_0' [simp] : "word_roti n 0 = 0"
       
  1586   unfolding word_roti_def by auto
       
  1587 
       
  1588 lemmas word_rotr_dt_no_bin' [simp] = 
       
  1589   word_rotr_dt [where w="number_of ?w", unfolded to_bl_no_bin]
       
  1590 
       
  1591 lemmas word_rotl_dt_no_bin' [simp] = 
       
  1592   word_rotl_dt [where w="number_of ?w", unfolded to_bl_no_bin]
       
  1593 
       
  1594 declare word_roti_def [simp]
       
  1595 
       
  1596 end
       
  1597