[STATEMENT]
theorem FNTT_NTT_gen_eq: "length numbers = 2^l \<Longrightarrow> 2^l \<le> n \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
proof(induction l arbitrary: numbers)
[PROOF STATE]
proof (state)
goal (2 subgoals):
 1. \<And>numbers. \<lbrakk>length numbers = 2 ^ 0; 2 ^ 0 \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
 2. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
case 0
[PROOF STATE]
proof (state)
this:
length numbers = 2 ^ 0
2 ^ 0 \<le> n

goal (2 subgoals):
 1. \<And>numbers. \<lbrakk>length numbers = 2 ^ 0; 2 ^ 0 \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
 2. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
then
[PROOF STATE]
proof (chain)
picking this:
length numbers = 2 ^ 0
2 ^ 0 \<le> n
[PROOF STEP]
show ?case
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ 0
2 ^ 0 \<le> n

goal (1 subgoal):
 1. FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
unfolding NTT_gen_def ntt_gen_def
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ 0
2 ^ 0 \<le> n

goal (1 subgoal):
 1. FNTT numbers = map (\<lambda>i. \<Sum>j = 0..<length numbers. numbers ! j * \<omega> ^ (n div length numbers * i * j)) [0..<length numbers]
[PROOF STEP]
by (auto simp: length_Suc_conv)
[PROOF STATE]
proof (state)
this:
FNTT numbers = NTT_gen (length numbers) numbers

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
next
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
case (Suc l)
[PROOF STATE]
proof (state)
this:
\<lbrakk>length ?numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT ?numbers = NTT_gen (length ?numbers) ?numbers
length numbers = 2 ^ Suc l
2 ^ Suc l \<le> n

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
text \<open>We define some lists that are used during the recursive call.\<close>
[PROOF STATE]
proof (state)
this:
\<lbrakk>length ?numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT ?numbers = NTT_gen (length ?numbers) ?numbers
length numbers = 2 ^ Suc l
2 ^ Suc l \<le> n

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
define numbers1 where "numbers1 = [numbers!i .  i <- (filter even [0..<length numbers])]"
[PROOF STATE]
proof (state)
this:
numbers1 = map ((!) numbers) (filter even [0..<length numbers])

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
define numbers2 where "numbers2 = [numbers!i .  i <- (filter odd [0..<length numbers])]"
[PROOF STATE]
proof (state)
this:
numbers2 = map ((!) numbers) (filter odd [0..<length numbers])

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
define fntt1 where "fntt1 = FNTT numbers1"
[PROOF STATE]
proof (state)
this:
fntt1 = FNTT numbers1

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
define fntt2 where "fntt2 = FNTT numbers2"
[PROOF STATE]
proof (state)
this:
fntt2 = FNTT numbers2

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
define sum1 where
    "sum1 = map2 (+) fntt1 (map2 ( \<lambda> x k.  x*(\<omega>^( (n div (length numbers)) * k)))
                   fntt2 [0..<((length numbers) div 2)])"
[PROOF STATE]
proof (state)
this:
sum1 = map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
define sum2 where
    "sum2 = map2 (-) fntt1 (map2 ( \<lambda> x k.  x*(\<omega>^( (n div (length numbers)) * k)))
                   fntt2 [0..<((length numbers) div 2)])"
[PROOF STATE]
proof (state)
this:
sum2 = map2 (-) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
define l1 where "l1 = length numbers1"
[PROOF STATE]
proof (state)
this:
l1 = length numbers1

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
define l2 where "l2 = length numbers2"
[PROOF STATE]
proof (state)
this:
l2 = length numbers2

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
define llen where "llen = length numbers"
[PROOF STATE]
proof (state)
this:
llen = length numbers

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
text \<open>Properties of those lists.\<close>
[PROOF STATE]
proof (state)
this:
llen = length numbers

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
have numbers1_even: "length numbers1 = 2^l"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length numbers1 = 2 ^ l
[PROOF STEP]
using numbers1_def length_even_filter Suc
[PROOF STATE]
proof (prove)
using this:
numbers1 = map ((!) numbers) (filter even [0..<length numbers])
length (map ?f (filter even [0..<?l])) = ?l - ?l div 2
\<lbrakk>length ?numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT ?numbers = NTT_gen (length ?numbers) ?numbers
length numbers = 2 ^ Suc l
2 ^ Suc l \<le> n

goal (1 subgoal):
 1. length numbers1 = 2 ^ l
[PROOF STEP]
by simp
[PROOF STATE]
proof (state)
this:
length numbers1 = 2 ^ l

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
have numbers2_even: "length numbers2 = 2^l"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length numbers2 = 2 ^ l
[PROOF STEP]
using numbers2_def length_odd_filter Suc
[PROOF STATE]
proof (prove)
using this:
numbers2 = map ((!) numbers) (filter odd [0..<length numbers])
length (map ?f (filter odd [0..<?l])) = ?l div 2
\<lbrakk>length ?numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT ?numbers = NTT_gen (length ?numbers) ?numbers
length numbers = 2 ^ Suc l
2 ^ Suc l \<le> n

goal (1 subgoal):
 1. length numbers2 = 2 ^ l
[PROOF STEP]
by simp
[PROOF STATE]
proof (state)
this:
length numbers2 = 2 ^ l

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
have numbers1_fntt: "fntt1 = NTT_gen (2^l) numbers1"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt1 = NTT_gen (2 ^ l) numbers1
[PROOF STEP]
using fntt1_def Suc.IH[of numbers1] numbers1_even Suc(3)
[PROOF STATE]
proof (prove)
using this:
fntt1 = FNTT numbers1
\<lbrakk>length numbers1 = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers1 = NTT_gen (length numbers1) numbers1
length numbers1 = 2 ^ l
2 ^ Suc l \<le> n

goal (1 subgoal):
 1. fntt1 = NTT_gen (2 ^ l) numbers1
[PROOF STEP]
by simp
[PROOF STATE]
proof (state)
this:
fntt1 = NTT_gen (2 ^ l) numbers1

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
hence fntt1_by_index: "fntt1 ! i = ntt_gen numbers1 (2^l) i" if "i < 2^l" for i
[PROOF STATE]
proof (prove)
using this:
fntt1 = NTT_gen (2 ^ l) numbers1

goal (1 subgoal):
 1. fntt1 ! i = ntt_gen numbers1 (2 ^ l) i
[PROOF STEP]
unfolding NTT_gen_def
[PROOF STATE]
proof (prove)
using this:
fntt1 = map (ntt_gen numbers1 (2 ^ l)) [0..<length numbers1]

goal (1 subgoal):
 1. fntt1 ! i = ntt_gen numbers1 (2 ^ l) i
[PROOF STEP]
by (simp add: numbers1_even that)
[PROOF STATE]
proof (state)
this:
?i < 2 ^ l \<Longrightarrow> fntt1 ! ?i = ntt_gen numbers1 (2 ^ l) ?i

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
have numbers2_fntt: "fntt2 = NTT_gen (2^l) numbers2"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt2 = NTT_gen (2 ^ l) numbers2
[PROOF STEP]
using fntt2_def Suc.IH[of numbers2] numbers2_even Suc(3)
[PROOF STATE]
proof (prove)
using this:
fntt2 = FNTT numbers2
\<lbrakk>length numbers2 = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers2 = NTT_gen (length numbers2) numbers2
length numbers2 = 2 ^ l
2 ^ Suc l \<le> n

goal (1 subgoal):
 1. fntt2 = NTT_gen (2 ^ l) numbers2
[PROOF STEP]
by simp
[PROOF STATE]
proof (state)
this:
fntt2 = NTT_gen (2 ^ l) numbers2

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
hence fntt2_by_index: "fntt2 ! i = ntt_gen numbers2 (2^l) i" if "i < 2^l" for i
[PROOF STATE]
proof (prove)
using this:
fntt2 = NTT_gen (2 ^ l) numbers2

goal (1 subgoal):
 1. fntt2 ! i = ntt_gen numbers2 (2 ^ l) i
[PROOF STEP]
unfolding NTT_gen_def
[PROOF STATE]
proof (prove)
using this:
fntt2 = map (ntt_gen numbers2 (2 ^ l)) [0..<length numbers2]

goal (1 subgoal):
 1. fntt2 ! i = ntt_gen numbers2 (2 ^ l) i
[PROOF STEP]
by (simp add: numbers2_even that)
[PROOF STATE]
proof (state)
this:
?i < 2 ^ l \<Longrightarrow> fntt2 ! ?i = ntt_gen numbers2 (2 ^ l) ?i

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
have fntt1_length: "length fntt1 = 2^l"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length fntt1 = 2 ^ l
[PROOF STEP]
unfolding numbers1_fntt NTT_gen_def numbers1_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length (map (ntt_gen (map ((!) numbers) (filter even [0..<length numbers])) (2 ^ l)) [0..<length (map ((!) numbers) (filter even [0..<length numbers]))]) = 2 ^ l
[PROOF STEP]
using numbers1_def numbers1_even
[PROOF STATE]
proof (prove)
using this:
numbers1 = map ((!) numbers) (filter even [0..<length numbers])
length numbers1 = 2 ^ l

goal (1 subgoal):
 1. length (map (ntt_gen (map ((!) numbers) (filter even [0..<length numbers])) (2 ^ l)) [0..<length (map ((!) numbers) (filter even [0..<length numbers]))]) = 2 ^ l
[PROOF STEP]
by force
[PROOF STATE]
proof (state)
this:
length fntt1 = 2 ^ l

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
have fntt2_length: "length fntt2 = 2^l"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length fntt2 = 2 ^ l
[PROOF STEP]
unfolding numbers2_fntt NTT_gen_def numbers2_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length (map (ntt_gen (map ((!) numbers) (filter odd [0..<length numbers])) (2 ^ l)) [0..<length (map ((!) numbers) (filter odd [0..<length numbers]))]) = 2 ^ l
[PROOF STEP]
using numbers2_def numbers2_even
[PROOF STATE]
proof (prove)
using this:
numbers2 = map ((!) numbers) (filter odd [0..<length numbers])
length numbers2 = 2 ^ l

goal (1 subgoal):
 1. length (map (ntt_gen (map ((!) numbers) (filter odd [0..<length numbers])) (2 ^ l)) [0..<length (map ((!) numbers) (filter odd [0..<length numbers]))]) = 2 ^ l
[PROOF STEP]
by force
[PROOF STATE]
proof (state)
this:
length fntt2 = 2 ^ l

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
text \<open>We show that the list resulting from $FNTT$ is equal to the $NTT$ list.
         First, we prove $FNTT$ and $NTT$ to be equal concerning their first halves.\<close>
[PROOF STATE]
proof (state)
this:
length fntt2 = 2 ^ l

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
have before_half: "map (ntt_gen numbers llen) [0..<(llen div 2)] = sum1"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] = sum1
[PROOF STEP]
proof-
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] = sum1
[PROOF STEP]
text \<open>Length is important, since we want to use list lemmas later on.\<close>
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] = sum1
[PROOF STEP]
have 00:"length (map (ntt_gen numbers llen) [0..<(llen div 2)]) =  length sum1"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length (map (ntt_gen numbers llen) [0..<llen div 2]) = length sum1
[PROOF STEP]
unfolding sum1_def llen_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length (map (ntt_gen numbers (length numbers)) [0..<length numbers div 2]) = length (map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]))
[PROOF STEP]
using Suc(2) map2_length[of _ fntt2 "[0..<length numbers div 2]"]
       map2_length[of "(+)" fntt1 "(map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])"]
       fntt1_length fntt2_length
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
length (map2 ?f fntt2 [0..<length numbers div 2]) = min (length fntt2) (length [0..<length numbers div 2])
length (map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])) = min (length fntt1) (length (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]))
length fntt1 = 2 ^ l
length fntt2 = 2 ^ l

goal (1 subgoal):
 1. length (map (ntt_gen numbers (length numbers)) [0..<length numbers div 2]) = length (map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]))
[PROOF STEP]
by (simp add: mult_2)
[PROOF STATE]
proof (state)
this:
length (map (ntt_gen numbers llen) [0..<llen div 2]) = length sum1

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] = sum1
[PROOF STEP]
have 01:"length sum1 = 2^l"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length sum1 = 2 ^ l
[PROOF STEP]
unfolding sum1_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length (map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])) = 2 ^ l
[PROOF STEP]
using "00" Suc.prems(1) sum1_def
[PROOF STATE]
proof (prove)
using this:
length (map (ntt_gen numbers llen) [0..<llen div 2]) = length sum1
length numbers = 2 ^ Suc l
sum1 = map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])

goal (1 subgoal):
 1. length (map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])) = 2 ^ l
[PROOF STEP]
unfolding llen_def
[PROOF STATE]
proof (prove)
using this:
length (map (ntt_gen numbers (length numbers)) [0..<length numbers div 2]) = length sum1
length numbers = 2 ^ Suc l
sum1 = map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])

goal (1 subgoal):
 1. length (map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])) = 2 ^ l
[PROOF STEP]
by auto
[PROOF STATE]
proof (state)
this:
length sum1 = 2 ^ l

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] = sum1
[PROOF STEP]
text \<open>We show equality by extensionality w.r.t. indices.\<close>
[PROOF STATE]
proof (state)
this:
length sum1 = 2 ^ l

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] = sum1
[PROOF STEP]
have 02:"(map (ntt_gen numbers llen) [0..<(llen div 2)]) ! i = sum1 ! i"
       if "i < 2^l" for i
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
proof-
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
text \<open>First simplify this term.\<close>
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
have 000:"(map (ntt_gen numbers llen) [0..<(llen div 2)]) ! i =
                   ntt_gen numbers llen i"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = ntt_gen numbers llen i
[PROOF STEP]
using "00" "01" that
[PROOF STATE]
proof (prove)
using this:
length (map (ntt_gen numbers llen) [0..<llen div 2]) = length sum1
length sum1 = 2 ^ l
i < 2 ^ l

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = ntt_gen numbers llen i
[PROOF STEP]
by auto
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [0..<llen div 2] ! i = ntt_gen numbers llen i

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
text \<open>Expand the definition of $sum1$ and massage the result.\<close>
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [0..<llen div 2] ! i = ntt_gen numbers llen i

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [0..<llen div 2] ! i = ntt_gen numbers llen i

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
have 001:"sum1 ! i = (fntt1!i) + (fntt2!i) * (\<omega>^((n div llen) * i))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. sum1 ! i = fntt1 ! i + fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
unfolding sum1_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]) ! i = fntt1 ! i + fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
using map2_index
         "00" "01" NTT_gen_def add.left_neutral diff_zero fntt1_length length_map length_upt map2_map_map map_nth nth_upt numbers2_even numbers2_fntt that llen_def
[PROOF STATE]
proof (prove)
using this:
\<lbrakk>?i < length ?xs; ?i < length ?ys\<rbrakk> \<Longrightarrow> map2 ?f ?xs ?ys ! ?i = ?f (?xs ! ?i) (?ys ! ?i)
length (map (ntt_gen numbers llen) [0..<llen div 2]) = length sum1
length sum1 = 2 ^ l
NTT_gen ?degr ?numbers = map (ntt_gen ?numbers ?degr) [0..<length ?numbers]
(0::?'a) + ?a = ?a
?a - (0::?'a) = ?a
length fntt1 = 2 ^ l
length (map ?f ?xs) = length ?xs
length [?i..<?j] = ?j - ?i
map2 ?h (map ?f ?xs) (map ?g ?xs) = map (\<lambda>x. ?h (?f x) (?g x)) ?xs
map ((!) ?xs) [0..<length ?xs] = ?xs
?i + ?k < ?j \<Longrightarrow> [?i..<?j] ! ?k = ?i + ?k
length numbers2 = 2 ^ l
fntt2 = NTT_gen (2 ^ l) numbers2
i < 2 ^ l
llen = length numbers

goal (1 subgoal):
 1. map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]) ! i = fntt1 ! i + fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
by force
[PROOF STATE]
proof (state)
this:
sum1 ! i = fntt1 ! i + fntt2 ! i * \<omega> ^ (n div llen * i)

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
sum1 ! i = fntt1 ! i + fntt2 ! i * \<omega> ^ (n div llen * i)

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
have 002:"(fntt1!i) = (\<Sum>j=0..<l1. (numbers1 ! j) * \<omega>^((n div (2^l))*i*j))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt1 ! i = (\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
[PROOF STEP]
unfolding l1_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt1 ! i = (\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
[PROOF STEP]
using fntt1_by_index[of i] that
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt1 ! i = ntt_gen numbers1 (2 ^ l) i
i < 2 ^ l

goal (1 subgoal):
 1. fntt1 ! i = (\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
[PROOF STEP]
unfolding ntt_gen_def
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt1 ! i = (\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
i < 2 ^ l

goal (1 subgoal):
 1. fntt1 ! i = (\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
[PROOF STEP]
by simp
[PROOF STATE]
proof (state)
this:
fntt1 ! i = (\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
have 003:"... = (\<Sum>j=0..<l1. (numbers ! (2*j)) * \<omega>^((n div llen)*i*(2*j)))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)))
[PROOF STEP]
apply (rule sum_rules(2))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. \<And>j. j < l1 \<Longrightarrow> numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
subgoal for j
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l1 \<Longrightarrow> numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
unfolding numbers1_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<length numbers]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
apply(subst llen_def[symmetric])
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
proof-
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
assume ass: "j < l1 "
[PROOF STATE]
proof (state)
this:
j < l1

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
hence "map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)"
[PROOF STATE]
proof (prove)
using this:
j < l1

goal (1 subgoal):
 1. map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)
[PROOF STEP]
using  nth_map[of j "filter even [0..<length numbers]" "(!) numbers" ]
[PROOF STATE]
proof (prove)
using this:
j < l1
j < length (filter even [0..<length numbers]) \<Longrightarrow> map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)

goal (1 subgoal):
 1. map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)
[PROOF STEP]
unfolding l1_def numbers1_def
[PROOF STATE]
proof (prove)
using this:
j < length (map ((!) numbers) (filter even [0..<length numbers]))
j < length (filter even [0..<length numbers]) \<Longrightarrow> map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)

goal (1 subgoal):
 1. map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)
[PROOF STEP]
by (metis length_map)
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
have "filter even [0..<llen] ! j = 2 * j"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. filter even [0..<llen] ! j = 2 * j
[PROOF STEP]
using
            filter_even_nth[of j "llen" "2^l"] Suc(2)  ass numbers1_def numbers1_even
[PROOF STATE]
proof (prove)
using this:
\<lbrakk>2 * j < llen; 2 * 2 ^ l = llen\<rbrakk> \<Longrightarrow> filter even [0..<llen] ! j = 2 * j
length numbers = 2 ^ Suc l
j < l1
numbers1 = map ((!) numbers) (filter even [0..<length numbers])
length numbers1 = 2 ^ l

goal (1 subgoal):
 1. filter even [0..<llen] ! j = 2 * j
[PROOF STEP]
unfolding llen_def l1_def
[PROOF STATE]
proof (prove)
using this:
\<lbrakk>2 * j < length numbers; 2 * 2 ^ l = length numbers\<rbrakk> \<Longrightarrow> filter even [0..<length numbers] ! j = 2 * j
length numbers = 2 ^ Suc l
j < length numbers1
numbers1 = map ((!) numbers) (filter even [0..<length numbers])
length numbers1 = 2 ^ l

goal (1 subgoal):
 1. filter even [0..<length numbers] ! j = 2 * j
[PROOF STEP]
by fastforce
[PROOF STATE]
proof (state)
this:
filter even [0..<llen] ! j = 2 * j

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
filter even [0..<llen] ! j = 2 * j

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
have "n div llen * (2 * j) = ((n div (2 ^ l))  * j)"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
using Suc(2) two_powrs_div[of l N] n_two_pot two_powr_div Suc(3) llen_def
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
l < N \<Longrightarrow> 2 ^ N div 2 ^ Suc l * 2 = 2 ^ N div 2 ^ l
n = 2 ^ N
?j < ?i \<Longrightarrow> 2 ^ ?i div 2 ^ ?j = 2 ^ (?i - ?j)
2 ^ Suc l \<le> n
llen = length numbers

goal (1 subgoal):
 1. n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
by (metis One_nat_def div_if mult.assoc nat_less_le not_less_eq numeral_2_eq_2 power_eq_0_iff power_inject_exp zero_neq_numeral)
[PROOF STATE]
proof (state)
this:
n div llen * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
ultimately
[PROOF STATE]
proof (chain)
picking this:
map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)
filter even [0..<llen] ! j = 2 * j
n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
show "map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) =
                   numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))"
[PROOF STATE]
proof (prove)
using this:
map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)
filter even [0..<llen] ! j = 2 * j
n div llen * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
unfolding llen_def l1_def l2_def
[PROOF STATE]
proof (prove)
using this:
map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)
filter even [0..<length numbers] ! j = 2 * j
n div length numbers * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. map ((!) numbers) (filter even [0..<length numbers]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div length numbers * i * (2 * j))
[PROOF STEP]
by (metis (mono_tags, lifting) mult.assoc mult.left_commute)
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))

goal:
No subgoals!
[PROOF STEP]
qed
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
(\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
(\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
have 004:
          "(fntt2!i) * (\<omega>^((n div llen) * i)) =
               (\<Sum>j=0..<l2.(numbers2 ! j) * \<omega>^((n div (2^l))*i*j+ (n div llen) * i))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))
[PROOF STEP]
apply(rule trans[where s = "(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i))"])
[PROOF STATE]
proof (prove)
goal (2 subgoals):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i))
 2. (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i)) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))
[PROOF STEP]
subgoal
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i))
[PROOF STEP]
unfolding l2_def llen_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div length numbers * i) = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div length numbers * i))
[PROOF STEP]
using fntt2_by_index[of i] that sum_in[of _ "(\<omega>^((n div llen) * i))" "l2"] comm_semiring_1_class.semiring_normalization_rules(26)[of \<omega>]
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = ntt_gen numbers2 (2 ^ l) i
i < 2 ^ l
(\<Sum>ia = 0..<l2. ?f ia * \<omega> ^ (n div llen * i)) = sum ?f {0..<l2} * \<omega> ^ (n div llen * i)
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)

goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div length numbers * i) = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div length numbers * i))
[PROOF STEP]
unfolding ntt_gen_def
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j))
i < 2 ^ l
(\<Sum>ia = 0..<l2. ?f ia * \<omega> ^ (n div llen * i)) = sum ?f {0..<l2} * \<omega> ^ (n div llen * i)
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)

goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div length numbers * i) = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div length numbers * i))
[PROOF STEP]
using sum_rules
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j))
i < 2 ^ l
(\<Sum>ia = 0..<l2. ?f ia * \<omega> ^ (n div llen * i)) = sum ?f {0..<l2} * \<omega> ^ (n div llen * i)
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)
(\<Sum>i = 0..<?x. ?f i * ?y) = sum ?f {0..<?x} * ?y
(\<And>i. i < ?x \<Longrightarrow> ?f i = ?g i) \<Longrightarrow> sum ?f {0..<?x} = sum ?g {0..<?x}
sum ?f {0..<?x} - sum ?g {0..<?x} = (\<Sum>i = 0..<?x. ?f i - ?g i)
(\<Sum>i = 0..<?x. sum (?f i) {0..<?y}) = (\<Sum>j = 0..<?y. \<Sum>i = 0..<?x. ?f i j)
(\<Sum>i = 0..<?x. ?c) = of_int_mod_ring (int ?x) * ?c
?r1.0 < ?r2.0 \<Longrightarrow> sum ?f {0..<?r1.0} + sum ?f {?r1.0..<?r2.0} = sum ?f {0..<?r2.0}
(\<Sum>l = ?a..<?b. ?f (l + ?c)) = sum ?f {?a + ?c..<?b + ?c}

goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div length numbers * i) = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div length numbers * i))
[PROOF STEP]
apply presburger
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i)) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))
[PROOF STEP]
apply (rule sum_rules(2))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. \<And>j. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i) = numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
[PROOF STEP]
subgoal for j
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i) = numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
[PROOF STEP]
using fntt2_by_index[of i] that sum_in[of _ "(\<omega>^((n div llen) * i))" "l2"] comm_semiring_1_class.semiring_normalization_rules(26)[of \<omega>]
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = ntt_gen numbers2 (2 ^ l) i
i < 2 ^ l
(\<Sum>ia = 0..<l2. ?f ia * \<omega> ^ (n div llen * i)) = sum ?f {0..<l2} * \<omega> ^ (n div llen * i)
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i) = numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
[PROOF STEP]
unfolding ntt_gen_def
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j))
i < 2 ^ l
(\<Sum>ia = 0..<l2. ?f ia * \<omega> ^ (n div llen * i)) = sum ?f {0..<l2} * \<omega> ^ (n div llen * i)
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i) = numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
[PROOF STEP]
apply auto
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
have 005: "\<dots> = (\<Sum>j=0..<l2. (numbers ! (2*j+1) * \<omega>^((n div llen)*i*(2*j+1))))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
[PROOF STEP]
apply (rule sum_rules(2))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. \<And>j. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
subgoal for j
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
unfolding numbers2_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<length numbers]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
apply(subst llen_def[symmetric])
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
proof-
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
assume ass: "j < l2 "
[PROOF STATE]
proof (state)
this:
j < l2

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
hence "map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)"
[PROOF STATE]
proof (prove)
using this:
j < l2

goal (1 subgoal):
 1. map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)
[PROOF STEP]
using  nth_map
[PROOF STATE]
proof (prove)
using this:
j < l2
?n < length ?xs \<Longrightarrow> map ?f ?xs ! ?n = ?f (?xs ! ?n)

goal (1 subgoal):
 1. map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)
[PROOF STEP]
unfolding l2_def numbers2_def llen_def
[PROOF STATE]
proof (prove)
using this:
j < length (map ((!) numbers) (filter odd [0..<length numbers]))
?n < length ?xs \<Longrightarrow> map ?f ?xs ! ?n = ?f (?xs ! ?n)

goal (1 subgoal):
 1. map ((!) numbers) (filter odd [0..<length numbers]) ! j = numbers ! (filter odd [0..<length numbers] ! j)
[PROOF STEP]
by (metis length_map)
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
have "filter odd [0..<llen] ! j = 2 * j +1"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. filter odd [0..<llen] ! j = 2 * j + 1
[PROOF STEP]
using
            filter_odd_nth[of j "length numbers" "2^l"] Suc(2)  ass numbers2_def numbers2_even
[PROOF STATE]
proof (prove)
using this:
\<lbrakk>2 * j < length numbers; 2 * 2 ^ l = length numbers\<rbrakk> \<Longrightarrow> filter odd [0..<length numbers] ! j = 2 * j + 1
length numbers = 2 ^ Suc l
j < l2
numbers2 = map ((!) numbers) (filter odd [0..<length numbers])
length numbers2 = 2 ^ l

goal (1 subgoal):
 1. filter odd [0..<llen] ! j = 2 * j + 1
[PROOF STEP]
unfolding l2_def numbers2_def llen_def
[PROOF STATE]
proof (prove)
using this:
\<lbrakk>2 * j < length numbers; 2 * 2 ^ l = length numbers\<rbrakk> \<Longrightarrow> filter odd [0..<length numbers] ! j = 2 * j + 1
length numbers = 2 ^ Suc l
j < length (map ((!) numbers) (filter odd [0..<length numbers]))
map ((!) numbers) (filter odd [0..<length numbers]) = map ((!) numbers) (filter odd [0..<length numbers])
length (map ((!) numbers) (filter odd [0..<length numbers])) = 2 ^ l

goal (1 subgoal):
 1. filter odd [0..<length numbers] ! j = 2 * j + 1
[PROOF STEP]
by fastforce
[PROOF STATE]
proof (state)
this:
filter odd [0..<llen] ! j = 2 * j + 1

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
filter odd [0..<llen] ! j = 2 * j + 1

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
have "n div llen * (2 * j) = ((n div (2 ^ l))  * j)"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
using Suc(2) two_powrs_div[of l N] n_two_pot two_powr_div Suc(3) llen_def
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
l < N \<Longrightarrow> 2 ^ N div 2 ^ Suc l * 2 = 2 ^ N div 2 ^ l
n = 2 ^ N
?j < ?i \<Longrightarrow> 2 ^ ?i div 2 ^ ?j = 2 ^ (?i - ?j)
2 ^ Suc l \<le> n
llen = length numbers

goal (1 subgoal):
 1. n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
by (metis One_nat_def div_if mult.assoc nat_less_le not_less_eq numeral_2_eq_2 power_eq_0_iff power_inject_exp zero_neq_numeral)
[PROOF STATE]
proof (state)
this:
n div llen * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
ultimately
[PROOF STATE]
proof (chain)
picking this:
map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)
filter odd [0..<llen] ! j = 2 * j + 1
n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
show
            " map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
                = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))"
[PROOF STATE]
proof (prove)
using this:
map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)
filter odd [0..<llen] ! j = 2 * j + 1
n div llen * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
unfolding llen_def
[PROOF STATE]
proof (prove)
using this:
map ((!) numbers) (filter odd [0..<length numbers]) ! j = numbers ! (filter odd [0..<length numbers] ! j)
filter odd [0..<length numbers] ! j = 2 * j + 1
n div length numbers * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. map ((!) numbers) (filter odd [0..<length numbers]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div length numbers * i * (2 * j + 1))
[PROOF STEP]
by (smt (z3) Groups.mult_ac(2) distrib_left mult.right_neutral mult_2 mult_cancel_left)
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))

goal:
No subgoals!
[PROOF STEP]
qed
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
then
[PROOF STATE]
proof (chain)
picking this:
(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
[PROOF STEP]
show ?thesis
[PROOF STATE]
proof (prove)
using this:
(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
using 000 001 002 003 004 005
[PROOF STATE]
proof (prove)
using this:
(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
map (ntt_gen numbers llen) [0..<llen div 2] ! i = ntt_gen numbers llen i
sum1 ! i = fntt1 ! i + fntt2 ! i * \<omega> ^ (n div llen * i)
fntt1 ! i = (\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
(\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)))
fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))
(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i
[PROOF STEP]
unfolding sum1_def llen_def l1_def l2_def
[PROOF STATE]
proof (prove)
using this:
(\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i)) = (\<Sum>j = 0..<length numbers2. numbers ! (2 * j + 1) * \<omega> ^ (n div length numbers * i * (2 * j + 1)))
map (ntt_gen numbers (length numbers)) [0..<length numbers div 2] ! i = ntt_gen numbers (length numbers) i
map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]) ! i = fntt1 ! i + fntt2 ! i * \<omega> ^ (n div length numbers * i)
fntt1 ! i = (\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
(\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<length numbers1. numbers ! (2 * j) * \<omega> ^ (n div length numbers * i * (2 * j)))
fntt2 ! i * \<omega> ^ (n div length numbers * i) = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i))
(\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i)) = (\<Sum>j = 0..<length numbers2. numbers ! (2 * j + 1) * \<omega> ^ (n div length numbers * i * (2 * j + 1)))

goal (1 subgoal):
 1. map (ntt_gen numbers (length numbers)) [0..<length numbers div 2] ! i = map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]) ! i
[PROOF STEP]
using sum_splice_other_way_round[of "\<lambda> d.  numbers ! d  * \<omega> ^ (n div length numbers * i * d)" "2^l"] Suc(2)
[PROOF STATE]
proof (prove)
using this:
(\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i)) = (\<Sum>j = 0..<length numbers2. numbers ! (2 * j + 1) * \<omega> ^ (n div length numbers * i * (2 * j + 1)))
map (ntt_gen numbers (length numbers)) [0..<length numbers div 2] ! i = ntt_gen numbers (length numbers) i
map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]) ! i = fntt1 ! i + fntt2 ! i * \<omega> ^ (n div length numbers * i)
fntt1 ! i = (\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
(\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<length numbers1. numbers ! (2 * j) * \<omega> ^ (n div length numbers * i * (2 * j)))
fntt2 ! i * \<omega> ^ (n div length numbers * i) = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i))
(\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i)) = (\<Sum>j = 0..<length numbers2. numbers ! (2 * j + 1) * \<omega> ^ (n div length numbers * i * (2 * j + 1)))
(\<Sum>j = 0..<2 ^ l. numbers ! (2 * j) * \<omega> ^ (n div length numbers * i * (2 * j))) + (\<Sum>j = 0..<2 ^ l. numbers ! (2 * j + 1) * \<omega> ^ (n div length numbers * i * (2 * j + 1))) = (\<Sum>j = 0..<2 * 2 ^ l. numbers ! j * \<omega> ^ (n div length numbers * i * j))
length numbers = 2 ^ Suc l

goal (1 subgoal):
 1. map (ntt_gen numbers (length numbers)) [0..<length numbers div 2] ! i = map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]) ! i
[PROOF STEP]
unfolding ntt_gen_def
[PROOF STATE]
proof (prove)
using this:
(\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i)) = (\<Sum>j = 0..<length numbers2. numbers ! (2 * j + 1) * \<omega> ^ (n div length numbers * i * (2 * j + 1)))
map (\<lambda>i. \<Sum>j = 0..<length numbers. numbers ! j * \<omega> ^ (n div length numbers * i * j)) [0..<length numbers div 2] ! i = (\<Sum>j = 0..<length numbers. numbers ! j * \<omega> ^ (n div length numbers * i * j))
map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]) ! i = fntt1 ! i + fntt2 ! i * \<omega> ^ (n div length numbers * i)
fntt1 ! i = (\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
(\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<length numbers1. numbers ! (2 * j) * \<omega> ^ (n div length numbers * i * (2 * j)))
fntt2 ! i * \<omega> ^ (n div length numbers * i) = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i))
(\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div length numbers * i)) = (\<Sum>j = 0..<length numbers2. numbers ! (2 * j + 1) * \<omega> ^ (n div length numbers * i * (2 * j + 1)))
(\<Sum>j = 0..<2 ^ l. numbers ! (2 * j) * \<omega> ^ (n div length numbers * i * (2 * j))) + (\<Sum>j = 0..<2 ^ l. numbers ! (2 * j + 1) * \<omega> ^ (n div length numbers * i * (2 * j + 1))) = (\<Sum>j = 0..<2 * 2 ^ l. numbers ! j * \<omega> ^ (n div length numbers * i * j))
length numbers = 2 ^ Suc l

goal (1 subgoal):
 1. map (\<lambda>i. \<Sum>j = 0..<length numbers. numbers ! j * \<omega> ^ (n div length numbers * i * j)) [0..<length numbers div 2] ! i = map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]) ! i
[PROOF STEP]
by (smt (z3) Groups.mult_ac(2) numbers1_even numbers2_even power_Suc2)
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [0..<llen div 2] ! i = sum1 ! i

goal:
No subgoals!
[PROOF STEP]
qed
[PROOF STATE]
proof (state)
this:
?i < 2 ^ l \<Longrightarrow> map (ntt_gen numbers llen) [0..<llen div 2] ! ?i = sum1 ! ?i

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] = sum1
[PROOF STEP]
then
[PROOF STATE]
proof (chain)
picking this:
?i < 2 ^ l \<Longrightarrow> map (ntt_gen numbers llen) [0..<llen div 2] ! ?i = sum1 ! ?i
[PROOF STEP]
show ?thesis
[PROOF STATE]
proof (prove)
using this:
?i < 2 ^ l \<Longrightarrow> map (ntt_gen numbers llen) [0..<llen div 2] ! ?i = sum1 ! ?i

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [0..<llen div 2] = sum1
[PROOF STEP]
by  (metis "00" "01" nth_equalityI)
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [0..<llen div 2] = sum1

goal:
No subgoals!
[PROOF STEP]
qed
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [0..<llen div 2] = sum1

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
text \<open>We show equality for the indices in the second halves.\<close>
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [0..<llen div 2] = sum1

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
have after_half: "map (ntt_gen numbers llen) [(llen div 2)..<llen] = sum2"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] = sum2
[PROOF STEP]
proof-
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] = sum2
[PROOF STEP]
have 00:"length (map (ntt_gen numbers llen) [(llen div 2)..<llen]) =  length sum2"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length (map (ntt_gen numbers llen) [llen div 2..<llen]) = length sum2
[PROOF STEP]
unfolding sum2_def llen_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length (map (ntt_gen numbers (length numbers)) [length numbers div 2..<length numbers]) = length (map2 (-) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]))
[PROOF STEP]
using Suc(2) map2_length map2_length fntt1_length fntt2_length
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
length (map2 ?f ?xs ?ys) = min (length ?xs) (length ?ys)
length (map2 ?f ?xs ?ys) = min (length ?xs) (length ?ys)
length fntt1 = 2 ^ l
length fntt2 = 2 ^ l

goal (1 subgoal):
 1. length (map (ntt_gen numbers (length numbers)) [length numbers div 2..<length numbers]) = length (map2 (-) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]))
[PROOF STEP]
by (simp add: mult_2)
[PROOF STATE]
proof (state)
this:
length (map (ntt_gen numbers llen) [llen div 2..<llen]) = length sum2

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] = sum2
[PROOF STEP]
have 01:"length sum2 = 2^l"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length sum2 = 2 ^ l
[PROOF STEP]
unfolding sum1_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. length sum2 = 2 ^ l
[PROOF STEP]
using "00" Suc.prems(1) sum1_def llen_def
[PROOF STATE]
proof (prove)
using this:
length (map (ntt_gen numbers llen) [llen div 2..<llen]) = length sum2
length numbers = 2 ^ Suc l
sum1 = map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])
llen = length numbers

goal (1 subgoal):
 1. length sum2 = 2 ^ l
[PROOF STEP]
by auto
[PROOF STATE]
proof (state)
this:
length sum2 = 2 ^ l

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] = sum2
[PROOF STEP]
text \<open>Equality for every index.\<close>
[PROOF STATE]
proof (state)
this:
length sum2 = 2 ^ l

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] = sum2
[PROOF STEP]
have 02:"(map (ntt_gen numbers llen)  [(llen div 2)..<llen]) ! i = sum2 ! i"
       if "i < 2^l" for i
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
proof-
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 000:"(map (ntt_gen numbers llen)  [(llen div 2)..<llen]) ! i =  ntt_gen numbers llen (2^l+i)"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = ntt_gen numbers llen (2 ^ l + i)
[PROOF STEP]
unfolding llen_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map (ntt_gen numbers (length numbers)) [length numbers div 2..<length numbers] ! i = ntt_gen numbers (length numbers) (2 ^ l + i)
[PROOF STEP]
by (simp add: Suc.prems(1) that)
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [llen div 2..<llen] ! i = ntt_gen numbers llen (2 ^ l + i)

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 001:" (map2 (\<lambda>x y. x * \<omega> ^ (n div llen * y)) fntt2 [0..<llen div 2]) ! i =
                  fntt2 ! i * \<omega> ^ (n div llen * i)"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map2 (\<lambda>x y. x * \<omega> ^ (n div llen * y)) fntt2 [0..<llen div 2] ! i = fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
using  Suc(2) that
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
i < 2 ^ l

goal (1 subgoal):
 1. map2 (\<lambda>x y. x * \<omega> ^ (n div llen * y)) fntt2 [0..<llen div 2] ! i = fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
by (simp add:  fntt2_length  llen_def)
[PROOF STATE]
proof (state)
this:
map2 (\<lambda>x y. x * \<omega> ^ (n div llen * y)) fntt2 [0..<llen div 2] ! i = fntt2 ! i * \<omega> ^ (n div llen * i)

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 003: "- fntt2 ! i * \<omega> ^ (n div llen * i) =
                    fntt2 ! i * \<omega> ^ (n div llen * (i+ llen div 2))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. - fntt2 ! i * \<omega> ^ (n div llen * i) = fntt2 ! i * \<omega> ^ (n div llen * (i + llen div 2))
[PROOF STEP]
using Suc(2) omega_div_exp_min1[of l]
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
2 ^ Suc l \<le> n \<Longrightarrow> (\<omega> ^ (n div 2 ^ Suc l)) ^ 2 ^ l = - 1

goal (1 subgoal):
 1. - fntt2 ! i * \<omega> ^ (n div llen * i) = fntt2 ! i * \<omega> ^ (n div llen * (i + llen div 2))
[PROOF STEP]
unfolding llen_def
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
2 ^ Suc l \<le> n \<Longrightarrow> (\<omega> ^ (n div 2 ^ Suc l)) ^ 2 ^ l = - 1

goal (1 subgoal):
 1. - fntt2 ! i * \<omega> ^ (n div length numbers * i) = fntt2 ! i * \<omega> ^ (n div length numbers * (i + length numbers div 2))
[PROOF STEP]
by (smt (z3) Suc.prems(2) mult.commute mult.left_commute mult_1s_ring_1(2) neq0_conv nonzero_mult_div_cancel_left numeral_One pos2 power_Suc power_add power_mult)
[PROOF STATE]
proof (state)
this:
- fntt2 ! i * \<omega> ^ (n div llen * i) = fntt2 ! i * \<omega> ^ (n div llen * (i + llen div 2))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
hence 004:"sum2 ! i = (fntt1!i) - (fntt2!i) * (\<omega>^((n div llen) * i))"
[PROOF STATE]
proof (prove)
using this:
- fntt2 ! i * \<omega> ^ (n div llen * i) = fntt2 ! i * \<omega> ^ (n div llen * (i + llen div 2))

goal (1 subgoal):
 1. sum2 ! i = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
unfolding sum2_def llen_def
[PROOF STATE]
proof (prove)
using this:
- fntt2 ! i * \<omega> ^ (n div length numbers * i) = fntt2 ! i * \<omega> ^ (n div length numbers * (i + length numbers div 2))

goal (1 subgoal):
 1. map2 (-) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2]) ! i = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div length numbers * i)
[PROOF STEP]
by (simp add: Suc.prems(1) fntt1_length fntt2_length that)
[PROOF STATE]
proof (state)
this:
sum2 ! i = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 005:"(fntt1!i) =
                     (\<Sum>j=0..<l1. (numbers1 ! j) * \<omega>^((n div (2^l))*i*j))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt1 ! i = (\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
[PROOF STEP]
using fntt1_by_index that
[PROOF STATE]
proof (prove)
using this:
?i < 2 ^ l \<Longrightarrow> fntt1 ! ?i = ntt_gen numbers1 (2 ^ l) ?i
i < 2 ^ l

goal (1 subgoal):
 1. fntt1 ! i = (\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
[PROOF STEP]
unfolding ntt_gen_def l1_def
[PROOF STATE]
proof (prove)
using this:
?i < 2 ^ l \<Longrightarrow> fntt1 ! ?i = (\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * ?i * j))
i < 2 ^ l

goal (1 subgoal):
 1. fntt1 ! i = (\<Sum>j = 0..<length numbers1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
[PROOF STEP]
by simp
[PROOF STATE]
proof (state)
this:
fntt1 ! i = (\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 006:"\<dots> =(\<Sum>j=0..<l1. (numbers ! (2*j)) * \<omega>^((n div llen)*i*(2*j)))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)))
[PROOF STEP]
apply (rule sum_rules(2))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. \<And>j. j < l1 \<Longrightarrow> numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
subgoal for j
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l1 \<Longrightarrow> numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
unfolding numbers1_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<length numbers]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
apply(subst llen_def[symmetric])
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
proof-
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
assume ass: "j < l1 "
[PROOF STATE]
proof (state)
this:
j < l1

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
hence "map ((!) numbers) (filter even [0..<llen]) ! j = numbers ! (filter even [0..<llen] ! j)"
[PROOF STATE]
proof (prove)
using this:
j < l1

goal (1 subgoal):
 1. map ((!) numbers) (filter even [0..<llen]) ! j = numbers ! (filter even [0..<llen] ! j)
[PROOF STEP]
using  nth_map
[PROOF STATE]
proof (prove)
using this:
j < l1
?n < length ?xs \<Longrightarrow> map ?f ?xs ! ?n = ?f (?xs ! ?n)

goal (1 subgoal):
 1. map ((!) numbers) (filter even [0..<llen]) ! j = numbers ! (filter even [0..<llen] ! j)
[PROOF STEP]
unfolding llen_def l1_def numbers1_def
[PROOF STATE]
proof (prove)
using this:
j < length (map ((!) numbers) (filter even [0..<length numbers]))
?n < length ?xs \<Longrightarrow> map ?f ?xs ! ?n = ?f (?xs ! ?n)

goal (1 subgoal):
 1. map ((!) numbers) (filter even [0..<length numbers]) ! j = numbers ! (filter even [0..<length numbers] ! j)
[PROOF STEP]
by (metis length_map)
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter even [0..<llen]) ! j = numbers ! (filter even [0..<llen] ! j)

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter even [0..<llen]) ! j = numbers ! (filter even [0..<llen] ! j)

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
have "filter even [0..<llen] ! j = 2 * j"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. filter even [0..<llen] ! j = 2 * j
[PROOF STEP]
using
            filter_even_nth Suc(2)  ass numbers1_def numbers1_even llen_def l1_def
[PROOF STATE]
proof (prove)
using this:
\<lbrakk>2 * ?j < ?l; 2 * ?x = ?l\<rbrakk> \<Longrightarrow> filter even [0..<?l] ! ?j = 2 * ?j
length numbers = 2 ^ Suc l
j < l1
numbers1 = map ((!) numbers) (filter even [0..<length numbers])
length numbers1 = 2 ^ l
llen = length numbers
l1 = length numbers1

goal (1 subgoal):
 1. filter even [0..<llen] ! j = 2 * j
[PROOF STEP]
by fastforce
[PROOF STATE]
proof (state)
this:
filter even [0..<llen] ! j = 2 * j

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
filter even [0..<llen] ! j = 2 * j

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
have "n div llen * (2 * j) = ((n div (2 ^ l))  * j)"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
using Suc(2) two_powrs_div[of l N] n_two_pot two_powr_div Suc(3) llen_def
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
l < N \<Longrightarrow> 2 ^ N div 2 ^ Suc l * 2 = 2 ^ N div 2 ^ l
n = 2 ^ N
?j < ?i \<Longrightarrow> 2 ^ ?i div 2 ^ ?j = 2 ^ (?i - ?j)
2 ^ Suc l \<le> n
llen = length numbers

goal (1 subgoal):
 1. n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
by (metis One_nat_def div_if mult.assoc nat_less_le not_less_eq numeral_2_eq_2 power_eq_0_iff power_inject_exp zero_neq_numeral)
[PROOF STATE]
proof (state)
this:
n div llen * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
ultimately
[PROOF STATE]
proof (chain)
picking this:
map ((!) numbers) (filter even [0..<llen]) ! j = numbers ! (filter even [0..<llen] ! j)
filter even [0..<llen] ! j = 2 * j
n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
show
              "map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) =
                        numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))"
[PROOF STATE]
proof (prove)
using this:
map ((!) numbers) (filter even [0..<llen]) ! j = numbers ! (filter even [0..<llen] ! j)
filter even [0..<llen] ! j = 2 * j
n div llen * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))
[PROOF STEP]
by (metis (mono_tags, lifting) mult.assoc mult.left_commute)
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter even [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j) = numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))

goal:
No subgoals!
[PROOF STEP]
qed
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
(\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 007:"\<dots> = (\<Sum>j=0..<l1. (numbers ! (2*j)) * \<omega>^((n div llen)*(2^l + i)*(2*j))) "
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j)))
[PROOF STEP]
apply (rule sum_rules(2))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. \<And>j. j < l1 \<Longrightarrow> numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)) = numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j))
[PROOF STEP]
subgoal for j
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l1 \<Longrightarrow> numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)) = numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j))
[PROOF STEP]
using Suc(2) Suc(3) omega_div_exp_min1[of l] llen_def l1_def numbers1_def
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
2 ^ Suc l \<le> n
2 ^ Suc l \<le> n \<Longrightarrow> (\<omega> ^ (n div 2 ^ Suc l)) ^ 2 ^ l = - 1
llen = length numbers
l1 = length numbers1
numbers1 = map ((!) numbers) (filter even [0..<length numbers])

goal (1 subgoal):
 1. j < l1 \<Longrightarrow> numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)) = numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j))
[PROOF STEP]
apply(smt (verit, del_insts) add.commute minus_power_mult_self mult_2 mult_minus1_right power_add power_mult)
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
(\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
(\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 008: "(fntt2!i) * (\<omega>^((n div llen) * i)) =
                      (\<Sum>j=0..<l2. (numbers2 ! j) * \<omega>^((n div (2^l))*i*j+ (n div llen) * i))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))
[PROOF STEP]
apply(rule trans[where s = "(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i))"])
[PROOF STATE]
proof (prove)
goal (2 subgoals):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i))
 2. (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i)) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))
[PROOF STEP]
subgoal
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i))
[PROOF STEP]
using fntt2_by_index[of i] that sum_in comm_semiring_1_class.semiring_normalization_rules(26)[of \<omega>]
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = ntt_gen numbers2 (2 ^ l) i
i < 2 ^ l
(\<Sum>i = 0..<?x. ?f i * ?y) = sum ?f {0..<?x} * ?y
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)

goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i))
[PROOF STEP]
unfolding ntt_gen_def
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j))
i < 2 ^ l
(\<Sum>i = 0..<?x. ?f i * ?y) = sum ?f {0..<?x} * ?y
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)

goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i))
[PROOF STEP]
using sum_rules l2_def
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j))
i < 2 ^ l
(\<Sum>i = 0..<?x. ?f i * ?y) = sum ?f {0..<?x} * ?y
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)
(\<Sum>i = 0..<?x. ?f i * ?y) = sum ?f {0..<?x} * ?y
(\<And>i. i < ?x \<Longrightarrow> ?f i = ?g i) \<Longrightarrow> sum ?f {0..<?x} = sum ?g {0..<?x}
sum ?f {0..<?x} - sum ?g {0..<?x} = (\<Sum>i = 0..<?x. ?f i - ?g i)
(\<Sum>i = 0..<?x. sum (?f i) {0..<?y}) = (\<Sum>j = 0..<?y. \<Sum>i = 0..<?x. ?f i j)
(\<Sum>i = 0..<?x. ?c) = of_int_mod_ring (int ?x) * ?c
?r1.0 < ?r2.0 \<Longrightarrow> sum ?f {0..<?r1.0} + sum ?f {?r1.0..<?r2.0} = sum ?f {0..<?r2.0}
(\<Sum>l = ?a..<?b. ?f (l + ?c)) = sum ?f {?a + ?c..<?b + ?c}
l2 = length numbers2

goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i))
[PROOF STEP]
apply presburger
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i)) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))
[PROOF STEP]
apply (rule sum_rules(2))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. \<And>j. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i) = numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
[PROOF STEP]
subgoal for j
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i) = numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
[PROOF STEP]
using fntt2_by_index[of i] that sum_in comm_semiring_1_class.semiring_normalization_rules(26)[of \<omega>]
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = ntt_gen numbers2 (2 ^ l) i
i < 2 ^ l
(\<Sum>i = 0..<?x. ?f i * ?y) = sum ?f {0..<?x} * ?y
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i) = numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
[PROOF STEP]
unfolding ntt_gen_def
[PROOF STATE]
proof (prove)
using this:
i < 2 ^ l \<Longrightarrow> fntt2 ! i = (\<Sum>j = 0..<length numbers2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j))
i < 2 ^ l
(\<Sum>i = 0..<?x. ?f i * ?y) = sum ?f {0..<?x} * ?y
\<omega> ^ ?p * \<omega> ^ ?q = \<omega> ^ (?p + ?q)

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j) * \<omega> ^ (n div llen * i) = numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
[PROOF STEP]
apply auto
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 009: "\<dots> = (\<Sum>j=0..<l2. (numbers ! (2*j+1) * \<omega>^((n div llen)*i*(2*j+1))))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
[PROOF STEP]
apply (rule sum_rules(2))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. \<And>j. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
subgoal for j
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
unfolding numbers2_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<length numbers]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
apply(subst llen_def[symmetric])
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
proof-
[PROOF STATE]
proof (state)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
assume ass: "j < l2 "
[PROOF STATE]
proof (state)
this:
j < l2

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
hence "map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)"
[PROOF STATE]
proof (prove)
using this:
j < l2

goal (1 subgoal):
 1. map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)
[PROOF STEP]
using  nth_map llen_def l2_def numbers2_def
[PROOF STATE]
proof (prove)
using this:
j < l2
?n < length ?xs \<Longrightarrow> map ?f ?xs ! ?n = ?f (?xs ! ?n)
llen = length numbers
l2 = length numbers2
numbers2 = map ((!) numbers) (filter odd [0..<length numbers])

goal (1 subgoal):
 1. map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)
[PROOF STEP]
by (metis length_map)
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
have "filter odd [0..<llen] ! j = 2 * j +1"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. filter odd [0..<llen] ! j = 2 * j + 1
[PROOF STEP]
using
            filter_odd_nth Suc(2)  ass numbers2_def numbers2_even llen_def l2_def
[PROOF STATE]
proof (prove)
using this:
\<lbrakk>2 * ?j < ?l; 2 * ?x = ?l\<rbrakk> \<Longrightarrow> filter odd [0..<?l] ! ?j = 2 * ?j + 1
length numbers = 2 ^ Suc l
j < l2
numbers2 = map ((!) numbers) (filter odd [0..<length numbers])
length numbers2 = 2 ^ l
llen = length numbers
l2 = length numbers2

goal (1 subgoal):
 1. filter odd [0..<llen] ! j = 2 * j + 1
[PROOF STEP]
by fastforce
[PROOF STATE]
proof (state)
this:
filter odd [0..<llen] ! j = 2 * j + 1

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
moreover
[PROOF STATE]
proof (state)
this:
filter odd [0..<llen] ! j = 2 * j + 1

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
have "n div llen * (2 * j) = ((n div (2 ^ l))  * j)"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
using Suc(2) two_powrs_div[of l N] n_two_pot two_powr_div Suc(3) llen_def
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
l < N \<Longrightarrow> 2 ^ N div 2 ^ Suc l * 2 = 2 ^ N div 2 ^ l
n = 2 ^ N
?j < ?i \<Longrightarrow> 2 ^ ?i div 2 ^ ?j = 2 ^ (?i - ?j)
2 ^ Suc l \<le> n
llen = length numbers

goal (1 subgoal):
 1. n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
by (metis One_nat_def div_if mult.assoc nat_less_le not_less_eq numeral_2_eq_2 power_eq_0_iff power_inject_exp zero_neq_numeral)
[PROOF STATE]
proof (state)
this:
n div llen * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
ultimately
[PROOF STATE]
proof (chain)
picking this:
map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)
filter odd [0..<llen] ! j = 2 * j + 1
n div llen * (2 * j) = n div 2 ^ l * j
[PROOF STEP]
show
             "map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)
                 = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))"
[PROOF STATE]
proof (prove)
using this:
map ((!) numbers) (filter odd [0..<llen]) ! j = numbers ! (filter odd [0..<llen] ! j)
filter odd [0..<llen] ! j = 2 * j + 1
n div llen * (2 * j) = n div 2 ^ l * j

goal (1 subgoal):
 1. map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))
[PROOF STEP]
by (smt (z3) Groups.mult_ac(2) distrib_left mult.right_neutral mult_2 mult_cancel_left)
[PROOF STATE]
proof (state)
this:
map ((!) numbers) (filter odd [0..<llen]) ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))

goal:
No subgoals!
[PROOF STEP]
qed
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 010: " (fntt2!i) * (\<omega>^((n div llen) * i)) = (\<Sum>j=0..<l2. (numbers ! (2*j+1) * \<omega>^((n div llen)*i*(2*j+1)))) "
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
[PROOF STEP]
using 008 009
[PROOF STATE]
proof (prove)
using this:
fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))
(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))

goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
[PROOF STEP]
by presburger
[PROOF STATE]
proof (state)
this:
fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 011: " - (fntt2!i) * (\<omega>^((n div llen) * i)) =
                  (\<Sum>j=0..<l2. - (numbers ! (2*j+1) * \<omega>^((n div llen)*i*(2*j+1)))) "
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. - fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))))
[PROOF STEP]
apply(rule neg_cong)
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. - (- fntt2 ! i * \<omega> ^ (n div llen * i)) = - (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))))
[PROOF STEP]
apply(rule trans[of _ "fntt2 ! i * \<omega> ^ (n div llen * i)"])
[PROOF STATE]
proof (prove)
goal (2 subgoals):
 1. - (- fntt2 ! i * \<omega> ^ (n div llen * i)) = fntt2 ! i * \<omega> ^ (n div llen * i)
 2. fntt2 ! i * \<omega> ^ (n div llen * i) = - (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))))
[PROOF STEP]
subgoal
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. - (- fntt2 ! i * \<omega> ^ (n div llen * i)) = fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
by simp
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = - (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))))
[PROOF STEP]
apply(rule trans[where s="(\<Sum>j=0..<l2. (numbers ! (2*j+1) * \<omega>^((n div llen)*i*(2*j+1))))"])
[PROOF STATE]
proof (prove)
goal (2 subgoals):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
 2. (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))) = - (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))))
[PROOF STEP]
subgoal
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
[PROOF STEP]
using 008 009
[PROOF STATE]
proof (prove)
using this:
fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i))
(\<Sum>j = 0..<l2. numbers2 ! j * \<omega> ^ (n div 2 ^ l * i * j + n div llen * i)) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))

goal (1 subgoal):
 1. fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
[PROOF STEP]
by simp
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))) = - (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))))
[PROOF STEP]
apply(rule sym)
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. - (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
[PROOF STEP]
using sum_neg_in[of _ "l2"]
[PROOF STATE]
proof (prove)
using this:
- sum ?f {0..<l2} = (\<Sum>j = 0..<l2. - ?f j)

goal (1 subgoal):
 1. - (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))
[PROOF STEP]
apply simp
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
- fntt2 ! i * \<omega> ^ (n div llen * i) = (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 012: "\<dots> = (\<Sum>j=0..<l2. (numbers ! (2*j+1) * \<omega>^((n div llen)*(2^l+i)*(2*j+1))))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1)))
[PROOF STEP]
apply(rule sum_rules(2))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. \<And>j. j < l2 \<Longrightarrow> - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1))
[PROOF STEP]
subgoal for j
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. j < l2 \<Longrightarrow> - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1))
[PROOF STEP]
using Suc(2) Suc(3) omega_div_exp_min1[of l] llen_def l2_def
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l
2 ^ Suc l \<le> n
2 ^ Suc l \<le> n \<Longrightarrow> (\<omega> ^ (n div 2 ^ Suc l)) ^ 2 ^ l = - 1
llen = length numbers
l2 = length numbers2

goal (1 subgoal):
 1. j < l2 \<Longrightarrow> - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))) = numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1))
[PROOF STEP]
apply (smt (z3) add.commute exp_rule mult.assoc mult_minus1_right plus_1_eq_Suc power_add power_minus1_odd power_mult)
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
(\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))) = (\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 013:"fntt1 ! i = (\<Sum>j = 0..<2 ^ l. numbers!(2*j) * \<omega> ^ (n div llen * (2^l + i) * (2*j)))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. fntt1 ! i = (\<Sum>j = 0..<2 ^ l. numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j)))
[PROOF STEP]
using 005 006 007 numbers1_even llen_def  l1_def
[PROOF STATE]
proof (prove)
using this:
fntt1 ! i = (\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j))
(\<Sum>j = 0..<l1. numbers1 ! j * \<omega> ^ (n div 2 ^ l * i * j)) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j)))
(\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * i * (2 * j))) = (\<Sum>j = 0..<l1. numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j)))
length numbers1 = 2 ^ l
llen = length numbers
l1 = length numbers1

goal (1 subgoal):
 1. fntt1 ! i = (\<Sum>j = 0..<2 ^ l. numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j)))
[PROOF STEP]
by auto
[PROOF STATE]
proof (state)
this:
fntt1 ! i = (\<Sum>j = 0..<2 ^ l. numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j)))

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have 014: "(\<Sum>j = 0..<2 ^ l. numbers ! (2*j + 1) * \<omega> ^ (n div llen* (2^l + i) * (2*j + 1))) =
                    - fntt2 ! i * \<omega> ^ (n div llen * i)"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<2 ^ l. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1))) = - fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
using  trans[OF l2_def numbers2_even]  sym[OF 012] sym[OF 011]
[PROOF STATE]
proof (prove)
using this:
l2 = 2 ^ l
(\<Sum>j = 0..<l2. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1))) = (\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1))))
(\<Sum>j = 0..<l2. - (numbers ! (2 * j + 1) * \<omega> ^ (n div llen * i * (2 * j + 1)))) = - fntt2 ! i * \<omega> ^ (n div llen * i)

goal (1 subgoal):
 1. (\<Sum>j = 0..<2 ^ l. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1))) = - fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
by simp
[PROOF STATE]
proof (state)
this:
(\<Sum>j = 0..<2 ^ l. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1))) = - fntt2 ! i * \<omega> ^ (n div llen * i)

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
have "ntt_gen numbers llen (2 ^ l + i) = (fntt1!i) - (fntt2!i) * (\<omega>^((n div llen) * i))"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. ntt_gen numbers llen (2 ^ l + i) = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
unfolding ntt_gen_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<length numbers. numbers ! j * \<omega> ^ (n div llen * (2 ^ l + i) * j)) = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
apply(subst Suc(2))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<Sum>j = 0..<2 ^ Suc l. numbers ! j * \<omega> ^ (n div llen * (2 ^ l + i) * j)) = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
using  sum_splice[of "\<lambda> d.  numbers ! d  * \<omega> ^ (n div llen * (2^l+i) * d)" "2^l"] sym[OF 013]  014 Suc(2)
[PROOF STATE]
proof (prove)
using this:
(\<Sum>ia = 0..<2 * 2 ^ l. numbers ! ia * \<omega> ^ (n div llen * (2 ^ l + i) * ia)) = (\<Sum>ia = 0..<2 ^ l. numbers ! (2 * ia) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * ia))) + (\<Sum>ia = 0..<2 ^ l. numbers ! (2 * ia + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * ia + 1)))
(\<Sum>j = 0..<2 ^ l. numbers ! (2 * j) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j))) = fntt1 ! i
(\<Sum>j = 0..<2 ^ l. numbers ! (2 * j + 1) * \<omega> ^ (n div llen * (2 ^ l + i) * (2 * j + 1))) = - fntt2 ! i * \<omega> ^ (n div llen * i)
length numbers = 2 ^ Suc l

goal (1 subgoal):
 1. (\<Sum>j = 0..<2 ^ Suc l. numbers ! j * \<omega> ^ (n div llen * (2 ^ l + i) * j)) = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)
[PROOF STEP]
by simp
[PROOF STATE]
proof (state)
this:
ntt_gen numbers llen (2 ^ l + i) = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
thus ?thesis
[PROOF STATE]
proof (prove)
using this:
ntt_gen numbers llen (2 ^ l + i) = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
using 000 sym[OF 001] "004" sum2_def
[PROOF STATE]
proof (prove)
using this:
ntt_gen numbers llen (2 ^ l + i) = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)
map (ntt_gen numbers llen) [llen div 2..<llen] ! i = ntt_gen numbers llen (2 ^ l + i)
fntt2 ! i * \<omega> ^ (n div llen * i) = map2 (\<lambda>x y. x * \<omega> ^ (n div llen * y)) fntt2 [0..<llen div 2] ! i
sum2 ! i = fntt1 ! i - fntt2 ! i * \<omega> ^ (n div llen * i)
sum2 = map2 (-) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) fntt2 [0..<length numbers div 2])

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i
[PROOF STEP]
by simp
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [llen div 2..<llen] ! i = sum2 ! i

goal:
No subgoals!
[PROOF STEP]
qed
[PROOF STATE]
proof (state)
this:
?i < 2 ^ l \<Longrightarrow> map (ntt_gen numbers llen) [llen div 2..<llen] ! ?i = sum2 ! ?i

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] = sum2
[PROOF STEP]
then
[PROOF STATE]
proof (chain)
picking this:
?i < 2 ^ l \<Longrightarrow> map (ntt_gen numbers llen) [llen div 2..<llen] ! ?i = sum2 ! ?i
[PROOF STEP]
show ?thesis
[PROOF STATE]
proof (prove)
using this:
?i < 2 ^ l \<Longrightarrow> map (ntt_gen numbers llen) [llen div 2..<llen] ! ?i = sum2 ! ?i

goal (1 subgoal):
 1. map (ntt_gen numbers llen) [llen div 2..<llen] = sum2
[PROOF STEP]
by (metis "00" "01" list_eq_iff_nth_eq)
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [llen div 2..<llen] = sum2

goal:
No subgoals!
[PROOF STEP]
qed
[PROOF STATE]
proof (state)
this:
map (ntt_gen numbers llen) [llen div 2..<llen] = sum2

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
obtain x y xs where xyxs: "numbers = x#y#xs"
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (\<And>x y xs. numbers = x # y # xs \<Longrightarrow> thesis) \<Longrightarrow> thesis
[PROOF STEP]
using Suc(2)
[PROOF STATE]
proof (prove)
using this:
length numbers = 2 ^ Suc l

goal (1 subgoal):
 1. (\<And>x y xs. numbers = x # y # xs \<Longrightarrow> thesis) \<Longrightarrow> thesis
[PROOF STEP]
by (metis FNTT.cases add.left_neutral even_Suc even_add length_Cons list.size(3) mult_2 power_Suc power_eq_0_iff zero_neq_numeral)
[PROOF STATE]
proof (state)
this:
numbers = x # y # xs

goal (1 subgoal):
 1. \<And>l numbers. \<lbrakk>\<And>numbers. \<lbrakk>length numbers = 2 ^ l; 2 ^ l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers; length numbers = 2 ^ Suc l; 2 ^ Suc l \<le> n\<rbrakk> \<Longrightarrow> FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
show ?case
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. FNTT numbers = NTT_gen (length numbers) numbers
[PROOF STEP]
apply(subst xyxs)
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. FNTT (x # y # xs) = NTT_gen (length numbers) numbers
[PROOF STEP]
apply(subst FNTT.simps(3))
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (let nn = length (x # y # xs); nums1 = map ((!) (x # y # xs)) (filter even [0..<nn]); nums2 = map ((!) (x # y # xs)) (filter odd [0..<nn]); fntt1 = FNTT nums1; fntt2 = FNTT nums2; sum1 = map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div nn * y)) fntt2 [0..<nn div 2]) in Let (map2 (-) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div nn * y)) fntt2 [0..<nn div 2])) ((@) sum1)) = NTT_gen (length numbers) numbers
[PROOF STEP]
apply(subst xyxs[symmetric])+
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. (let nn = length numbers; nums1 = map ((!) numbers) (filter even [0..<nn]); nums2 = map ((!) numbers) (filter odd [0..<nn]); fntt1 = FNTT nums1; fntt2 = FNTT nums2; sum1 = map2 (+) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div nn * y)) fntt2 [0..<nn div 2]) in Let (map2 (-) fntt1 (map2 (\<lambda>x y. x * \<omega> ^ (n div nn * y)) fntt2 [0..<nn div 2])) ((@) sum1)) = NTT_gen (length numbers) numbers
[PROOF STEP]
unfolding Let_def
[PROOF STATE]
proof (prove)
goal (1 subgoal):
 1. map2 (+) (FNTT (map ((!) numbers) (filter even [0..<length numbers]))) (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) (FNTT (map ((!) numbers) (filter odd [0..<length numbers]))) [0..<length numbers div 2]) @ map2 (-) (FNTT (map ((!) numbers) (filter even [0..<length numbers]))) (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) (FNTT (map ((!) numbers) (filter odd [0..<length numbers]))) [0..<length numbers div 2]) = NTT_gen (length numbers) numbers
[PROOF STEP]
using map_append[of "ntt_gen numbers llen" " [0..<llen div 2]" "[llen div 2..<llen]"] before_half after_half
[PROOF STATE]
proof (prove)
using this:
map (ntt_gen numbers llen) ([0..<llen div 2] @ [llen div 2..<llen]) = map (ntt_gen numbers llen) [0..<llen div 2] @ map (ntt_gen numbers llen) [llen div 2..<llen]
map (ntt_gen numbers llen) [0..<llen div 2] = sum1
map (ntt_gen numbers llen) [llen div 2..<llen] = sum2

goal (1 subgoal):
 1. map2 (+) (FNTT (map ((!) numbers) (filter even [0..<length numbers]))) (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) (FNTT (map ((!) numbers) (filter odd [0..<length numbers]))) [0..<length numbers div 2]) @ map2 (-) (FNTT (map ((!) numbers) (filter even [0..<length numbers]))) (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) (FNTT (map ((!) numbers) (filter odd [0..<length numbers]))) [0..<length numbers div 2]) = NTT_gen (length numbers) numbers
[PROOF STEP]
unfolding llen_def sum1_def sum2_def fntt1_def fntt2_def NTT_gen_def
[PROOF STATE]
proof (prove)
using this:
map (ntt_gen numbers (length numbers)) ([0..<length numbers div 2] @ [length numbers div 2..<length numbers]) = map (ntt_gen numbers (length numbers)) [0..<length numbers div 2] @ map (ntt_gen numbers (length numbers)) [length numbers div 2..<length numbers]
map (ntt_gen numbers (length numbers)) [0..<length numbers div 2] = map2 (+) (FNTT numbers1) (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) (FNTT numbers2) [0..<length numbers div 2])
map (ntt_gen numbers (length numbers)) [length numbers div 2..<length numbers] = map2 (-) (FNTT numbers1) (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) (FNTT numbers2) [0..<length numbers div 2])

goal (1 subgoal):
 1. map2 (+) (FNTT (map ((!) numbers) (filter even [0..<length numbers]))) (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) (FNTT (map ((!) numbers) (filter odd [0..<length numbers]))) [0..<length numbers div 2]) @ map2 (-) (FNTT (map ((!) numbers) (filter even [0..<length numbers]))) (map2 (\<lambda>x y. x * \<omega> ^ (n div length numbers * y)) (FNTT (map ((!) numbers) (filter odd [0..<length numbers]))) [0..<length numbers div 2]) = map (ntt_gen numbers (length numbers)) [0..<length numbers]
[PROOF STEP]
apply (metis (no_types, lifting) Suc.prems(1) numbers1_def length_odd_filter mult_2 numbers2_def numbers2_even power_Suc upt_add_eq_append zero_le_numeral zero_le_power)
[PROOF STATE]
proof (prove)
goal:
No subgoals!
[PROOF STEP]
done
[PROOF STATE]
proof (state)
this:
FNTT numbers = NTT_gen (length numbers) numbers

goal:
No subgoals!
[PROOF STEP]
qed