2 ||M|| This file is part of HELM, an Hypertextual, Electronic
3 ||A|| Library of Mathematics, developed at the Computer Science
4 ||T|| Department of the University of Bologna, Italy.
7 ||A|| This file is distributed under the terms of the
8 \ / GNU General Public License Version 2
10 V_______________________________________________________________ *)
12 include "basics/types.ma".
13 include "arithmetics/div_and_mod.ma".
15 definition sameF_upto: nat → ∀A.relation(nat→A) ≝
16 λk.λA.λf,g.∀i. i < k → f i = g i.
18 definition sameF_p: nat → (nat → bool) →∀A.relation(nat→A) ≝
19 λk,p,A,f,g.∀i. i < k → p i = true → f i = g i.
21 lemma sameF_upto_le: ∀A,f,g,n,m.
22 n ≤m → sameF_upto m A f g → sameF_upto n A f g.
23 #A #f #g #n #m #lenm #samef #i #ltin @samef /2/
26 lemma sameF_p_le: ∀A,p,f,g,n,m.
27 n ≤m → sameF_p m p A f g → sameF_p n p A f g.
28 #A #p #f #g #n #m #lenm #samef #i #ltin #pi @samef /2/
32 definition sumF ≝ λA.λf,g:nat → A.λn,i.
33 if_then_else ? (leb n i) (g (i-n)) (f i).
35 lemma sumF_unfold: ∀A,f,g,n,i.
36 sumF A f g n i = if_then_else ? (leb n i) (g (i-n)) (f i).
40 λA,B.λf:nat→A.λg:nat→B.λm,x.〈 f(div x m), g(mod x m) 〉.
43 let rec bigop (n:nat) (p:nat → bool) (B:Type[0])
44 (nil: B) (op: B → B → B) (f: nat → B) ≝
49 [true ⇒ op (f k) (bigop k p B nil op f)
50 |false ⇒ bigop k p B nil op f]
53 notation "\big [ op , nil ]_{ ident i < n | p } f"
55 for @{'bigop $n $op $nil (λ${ident i}. $p) (λ${ident i}. $f)}.
57 notation "\big [ op , nil ]_{ ident i < n } f"
59 for @{'bigop $n $op $nil (λ${ident i}.true) (λ${ident i}. $f)}.
61 interpretation "bigop" 'bigop n op nil p f = (bigop n p ? nil op f).
63 notation "\big [ op , nil ]_{ ident j ∈ [a,b[ | p } f"
65 for @{'bigop ($b-$a) $op $nil (λ${ident j}.((λ${ident j}.$p) (${ident j}+$a)))
66 (λ${ident j}.((λ${ident j}.$f)(${ident j}+$a)))}.
68 notation "\big [ op , nil ]_{ ident j ∈ [a,b[ } f"
70 for @{'bigop ($b-$a) $op $nil (λ${ident j}.((λ${ident j}.true) (${ident j}+$a)))
71 (λ${ident j}.((λ${ident j}.$f)(${ident j}+$a)))}.
73 (* notation "\big [ op , nil ]_{( term 50) a ≤ ident j < b | p } f"
75 for @{\big[$op,$nil]_{${ident j} < ($b-$a) | ((λ${ident j}.$p) (${ident j}+$a))}((λ${ident j}.$f)(${ident j}+$a))}.
78 interpretation "bigop" 'bigop n op nil p f = (bigop n p ? nil op f).
80 lemma bigop_Strue: ∀k,p,B,nil,op.∀f:nat→B. p k = true →
81 \big[op,nil]_{i < S k | p i}(f i) =
82 op (f k) (\big[op,nil]_{i < k | p i}(f i)).
83 #k #p #B #nil #op #f #H normalize >H // qed.
85 lemma bigop_Sfalse: ∀k,p,B,nil,op.∀f:nat→B. p k = false →
86 \big[op,nil]_{ i < S k | p i}(f i) =
87 \big[op,nil]_{i < k | p i}(f i).
88 #k #p #B #nil #op #f #H normalize >H // qed.
90 lemma same_bigop : ∀k,p1,p2,B,nil,op.∀f,g:nat→B.
91 sameF_upto k bool p1 p2 → sameF_p k p1 B f g →
92 \big[op,nil]_{i < k | p1 i}(f i) =
93 \big[op,nil]_{i < k | p2 i}(g i).
94 #k #p1 #p2 #B #nil #op #f #g (elim k) //
95 #n #Hind #samep #samef normalize >Hind /2/
96 <(samep … (le_n …)) cases(true_or_false (p1 n)) #H1 >H1
97 normalize // <(samef … (le_n …) H1) //
100 theorem pad_bigop: ∀k,n,p,B,nil,op.∀f:nat→B. n ≤ k →
101 \big[op,nil]_{i < n | p i}(f i)
102 = \big[op,nil]_{i < k | if_then_else ? (leb n i) false (p i)}(f i).
103 #k #n #p #B #nil #op #f #lenk (elim lenk)
104 [@same_bigop #i #lti // >(not_le_to_leb_false …) /2/
105 |#j #leup #Hind >bigop_Sfalse >(le_to_leb_true … leup) //
108 record Aop (A:Type[0]) (nil:A) : Type[0] ≝
110 nill:∀a. op nil a = a;
111 nilr:∀a. op a nil = a;
112 assoc: ∀a,b,c.op a (op b c) = op (op a b) c
115 theorem bigop_sum: ∀k1,k2,p1,p2,B.∀nil.∀op:Aop B nil.∀f,g:nat→B.
116 op (\big[op,nil]_{i<k1|p1 i}(f i)) \big[op,nil]_{i<k2|p2 i}(g i) =
117 \big[op,nil]_{i<k1+k2|if_then_else ? (leb k2 i) (p1 (i-k2)) (p2 i)}
118 (if_then_else ? (leb k2 i) (f (i-k2)) (g i)).
119 #k1 #k2 #p1 #p2 #B #nil #op #f #g (elim k1)
120 [normalize >nill @same_bigop #i #lti
121 >(lt_to_leb_false … lti) normalize /2/
122 |#i #Hind normalize <minus_plus_m_m (cases (p1 i))
123 >(le_to_leb_true … (le_plus_n …)) normalize <Hind //
128 lemma plus_minus1: ∀a,b,c. c ≤ b → a + (b -c) = a + b -c.
129 #a #b #c #lecb @sym_eq @plus_to_minus >(commutative_plus c)
130 >associative_plus <plus_minus_m_m //
133 theorem bigop_I: ∀n,p,B.∀nil.∀op:Aop B nil.∀f:nat→B.
134 \big[op,nil]_{i∈[0,n[ |p i}(f i) = \big[op,nil]_{i < n|p i}(f i).
135 #n #p #B #nil #op #f <minus_n_O @same_bigop //
138 theorem bigop_sumI: ∀a,b,c,p,B.∀nil.∀op:Aop B nil.∀f:nat→B.
140 \big[op,nil]_{i∈[a,c[ |p i}(f i) =
141 op (\big[op,nil]_{i ∈ [b,c[ |p i}(f i))
142 \big[op,nil]_{i ∈ [a,b[ |p i}(f i).
143 #a #b # c #p #B #nil #op #f #leab #lebc
144 >(plus_minus_m_m (c-a) (b-a)) in ⊢ (??%?) /2/
145 >minus_plus >(commutative_plus a) <plus_minus_m_m //
146 >bigop_sum (cut (∀i. b -a ≤ i → i+a = i-(b-a)+b))
147 [#i #lei >plus_minus // <plus_minus1
148 [@eq_f @sym_eq @plus_to_minus /2/ | /2/]]
149 #H @same_bigop #i #ltic @leb_elim normalize // #lei <H //
152 theorem bigop_a: ∀a,b,B.∀nil.∀op:Aop B nil.∀f:nat→B. a ≤ b →
153 \big[op,nil]_{i∈[a,S b[ }(f i) =
154 op (\big[op,nil]_{i ∈ [a,b[ }(f (S i))) (f a).
155 #a #b #B #nil #op #f #leab
156 >(bigop_sumI a (S a) (S b)) [|@le_S_S //|//] @eq_f2
157 [@same_bigop // |<minus_Sn_n normalize @nilr]
160 theorem bigop_0: ∀n,B.∀nil.∀op:Aop B nil.∀f:nat→B.
161 \big[op,nil]_{i < S n}(f i) =
162 op (\big[op,nil]_{i < n}(f (S i))) (f 0).
164 <bigop_I >bigop_a [|//] @eq_f2 [|//] <minus_n_O
168 theorem bigop_prod: ∀k1,k2,p1,p2,B.∀nil.∀op:Aop B nil.∀f: nat →nat → B.
169 \big[op,nil]_{x<k1|p1 x}(\big[op,nil]_{i<k2|p2 x i}(f x i)) =
170 \big[op,nil]_{i<k1*k2|andb (p1 (div i k2)) (p2 (div i k2) (i \mod k2))}
171 (f (div i k2) (i \mod k2)).
172 #k1 #k2 #p1 #p2 #B #nil #op #f (elim k1) //
173 #n #Hind cases(true_or_false (p1 n)) #Hp1
174 [>bigop_Strue // >Hind >bigop_sum @same_bigop
175 #i #lti @leb_elim // #lei cut (i = n*k2+(i-n*k2)) /2/
176 #eqi [|#H] (>eqi in ⊢ (???%))
177 >div_plus_times /2/ >Hp1 >(mod_plus_times …) /2/
178 |>bigop_Sfalse // >Hind >(pad_bigop (S n*k2)) // @same_bigop
179 #i #lti @leb_elim // #lei cut (i = n*k2+(i-n*k2)) /2/
180 #eqi >eqi in ⊢ (???%) >div_plus_times /2/
184 record ACop (A:Type[0]) (nil:A) : Type[0] ≝
186 comm: ∀a,b.aop a b = aop b a
189 lemma bigop_op: ∀k,p,B.∀nil.∀op:ACop B nil.∀f,g: nat → B.
190 op (\big[op,nil]_{i<k|p i}(f i)) (\big[op,nil]_{i<k|p i}(g i)) =
191 \big[op,nil]_{i<k|p i}(op (f i) (g i)).
192 #k #p #B #nil #op #f #g (elim k) [normalize @nill]
193 -k #k #Hind (cases (true_or_false (p k))) #H
194 [>bigop_Strue // >bigop_Strue // >bigop_Strue //
195 <assoc <assoc in ⊢ (???%) @eq_f >assoc >comm in ⊢ (??(????%?)?)
197 |>bigop_Sfalse // >bigop_Sfalse // >bigop_Sfalse //
201 lemma bigop_diff: ∀p,B.∀nil.∀op:ACop B nil.∀f:nat → B.∀i,n.
203 \big[op,nil]_{x<n|p x}(f x)=
204 op (f i) (\big[op,nil]_{x<n|andb(notb(eqb i x))(p x)}(f x)).
205 #p #B #nil #op #f #i #n (elim n)
207 |#n #Hind #lein #pi cases (le_to_or_lt_eq … (le_S_S_to_le …lein)) #Hi
208 [cut (andb(notb(eqb i n))(p n) = (p n))
209 [>(not_eq_to_eqb_false … (lt_to_not_eq … Hi)) //] #Hcut
210 cases (true_or_false (p n)) #pn
211 [>bigop_Strue // >bigop_Strue //
212 >assoc >(comm ?? op (f i) (f n)) <assoc >Hind //
213 |>bigop_Sfalse // >bigop_Sfalse // >Hind //
215 |<Hi >bigop_Strue // @eq_f >bigop_Sfalse
216 [@same_bigop // #k #ltki >not_eq_to_eqb_false /2/
224 record range (A:Type[0]): Type[0] ≝
225 {enum:nat→A; upto:nat; filter:nat→bool}.
227 definition sub_hk: (nat→nat)→(nat→nat)→∀A:Type[0].relation (range A) ≝
228 λh,k,A,I,J.∀i.i<(upto A I) → (filter A I i)=true →
230 ∧ filter A J (h i) = true
233 definition iso: ∀A:Type[0].relation (range A) ≝
235 (∀i. i < (upto A I) → (filter A I i) = true →
236 enum A I i = enum A J (h i)) ∧
237 sub_hk h k A I J ∧ sub_hk k h A J I.
239 lemma sub_hkO: ∀h,k,A,I,J. upto A I = 0 → sub_hk h k A I J.
240 #h #k #A #I #J #up0 #i #lti >up0 @False_ind /2/
243 lemma sub0_to_false: ∀h,k,A,I,J. upto A I = 0 → sub_hk h k A J I →
244 ∀i. i < upto A J → filter A J i = false.
245 #h #k #A #I #J #up0 #sub #i #lti cases(true_or_false (filter A J i)) //
246 #ptrue (cases (sub i lti ptrue)) * #hi @False_ind /2/
249 lemma sub_lt: ∀A,e,p,n,m. n ≤ m →
250 sub_hk (λx.x) (λx.x) A (mk_range A e n p) (mk_range A e m p).
251 #A #e #f #n #m #lenm #i #lti #fi % // % /2/
254 theorem transitive_sub: ∀h1,k1,h2,k2,A,I,J,K.
255 sub_hk h1 k1 A I J → sub_hk h2 k2 A J K →
256 sub_hk (λx.h2(h1 x)) (λx.k1(k2 x)) A I K.
257 #h1 #k1 #h2 #k2 #A #I #J #K #sub1 #sub2 #i #lti #fi
258 cases(sub1 i lti fi) * #lth1i #fh1i #ei
259 cases(sub2 (h1 i) lth1i fh1i) * #H1 #H2 #H3 % // % //
262 theorem bigop_iso: ∀n1,n2,p1,p2,B.∀nil.∀op:ACop B nil.∀f1,f2.
263 iso B (mk_range B f1 n1 p1) (mk_range B f2 n2 p2) →
264 \big[op,nil]_{i<n1|p1 i}(f1 i) = \big[op,nil]_{i<n2|p2 i}(f2 i).
265 #n1 #n2 #p1 #p2 #B #nil #op #f1 #f2 * #h * #k * * #same
266 @(le_gen ? n1) #i (generalize in match p2) (elim i)
267 [(elim n2) // #m #Hind #p2 #_ #sub1 #sub2
269 [@(Hind ? (le_O_n ?)) [/2/ | @(transitive_sub … (sub_lt …) sub2) //]
270 |@(sub0_to_false … sub2) //
272 |#n #Hind #p2 #ltn #sub1 #sub2 (cut (n ≤n1)) [/2/] #len
273 cases(true_or_false (p1 n)) #p1n
274 [>bigop_Strue // (cases (sub1 n (le_n …) p1n)) * #hn #p2hn #eqn
275 >(bigop_diff … (h n) n2) // >same //
277 [#i #ltin #p1i (cases (sub1 i (le_S … ltin) p1i)) *
278 #h1i #p2h1i #eqi % // % // >not_eq_to_eqb_false normalize //
279 @(not_to_not ??? (lt_to_not_eq ? ? ltin)) //
280 |#j #ltj #p2j (cases (sub2 j ltj (andb_true_r …p2j))) *
281 #ltkj #p1kj #eqj % // % //
282 (cases (le_to_or_lt_eq …(le_S_S_to_le …ltkj))) //
283 #eqkj @False_ind generalize in match p2j @eqb_elim
286 |>bigop_Sfalse // @(Hind ? len)
287 [@(transitive_sub … (sub_lt …) sub1) //
288 |#i #lti #p2i cases(sub2 i lti p2i) * #ltki #p1ki #eqi
289 % // % // cases(le_to_or_lt_eq …(le_S_S_to_le …ltki)) //
298 record Dop (A:Type[0]) (nil:A): Type[0] ≝
301 null: \forall a. prod a nil = nil;
302 distr: ∀a,b,c:A. prod a (sum b c) = sum (prod a b) (prod a c)
305 theorem bigop_distr: ∀n,p,B,nil.∀R:Dop B nil.\forall f,a.
306 let aop \def sum B nil R in
307 let mop \def prod B nil R in
308 mop a \big[aop,nil]_{i<n|p i}(f i) =
309 \big[aop,nil]_{i<n|p i}(mop a (f i)).
310 #n #p #B #nil #R #f #a normalize (elim n) [@null]
311 #n #Hind (cases (true_or_false (p n))) #H
312 [>bigop_Strue // >bigop_Strue // >(distr B nil R) >Hind //
313 |>bigop_Sfalse // >bigop_Sfalse //
320 notation "Σ_{ ident i < n | p } f"
322 for @{'bigop $n plus 0 (λ${ident i}.p) (λ${ident i}. $f)}.
324 notation "Σ_{ ident i < n } f"
326 for @{'bigop $n plus 0 (λ${ident i}.true) (λ${ident i}. $f)}.
328 notation "Σ_{ ident j ∈ [a,b[ } f"
330 for @{'bigop ($b-$a) plus 0 (λ${ident j}.((λ${ident j}.true) (${ident j}+$a)))
331 (λ${ident j}.((λ${ident j}.$f)(${ident j}+$a)))}.
333 notation "Σ_{ ident j ∈ [a,b[ | p } f"
335 for @{'bigop ($b-$a) plus 0 (λ${ident j}.((λ${ident j}.$p) (${ident j}+$a)))
336 (λ${ident j}.((λ${ident j}.$f)(${ident j}+$a)))}.
338 notation "Π_{ ident i < n | p} f"
340 for @{'bigop $n times 1 (λ${ident i}.$p) (λ${ident i}. $f)}.
342 notation "Π_{ ident i < n } f"
344 for @{'bigop $n times 1 (λ${ident i}.true) (λ${ident i}. $f)}.
346 notation "Π_{ ident j ∈ [a,b[ } f"
348 for @{'bigop ($b-$a) times 1 (λ${ident j}.((λ${ident j}.true) (${ident j}+$a)))
349 (λ${ident j}.((λ${ident j}.$f)(${ident j}+$a)))}.
351 notation "Π_{ ident j ∈ [a,b[ | p } f"
353 for @{'bigop ($b-$a) times 1 (λ${ident j}.((λ${ident j}.$p) (${ident j}+$a)))
354 (λ${ident j}.((λ${ident j}.$f)(${ident j}+$a)))}.
359 definition p_ord_times \def
362 [pair q r \Rightarrow r*m+q].
364 theorem eq_p_ord_times: \forall p,m,x.
365 p_ord_times p m x = (ord_rem x p)*m+(ord x p).
366 intros.unfold p_ord_times. unfold ord_rem.
372 theorem div_p_ord_times:
373 \forall p,m,x. ord x p < m \to p_ord_times p m x / m = ord_rem x p.
374 intros.rewrite > eq_p_ord_times.
375 apply div_plus_times.
379 theorem mod_p_ord_times:
380 \forall p,m,x. ord x p < m \to p_ord_times p m x \mod m = ord x p.
381 intros.rewrite > eq_p_ord_times.
382 apply mod_plus_times.
386 lemma lt_times_to_lt_O: \forall i,n,m:nat. i < n*m \to O < m.
388 elim (le_to_or_lt_eq O ? (le_O_n m))
392 rewrite < times_n_O in H.
393 apply (not_le_Sn_O ? H)
397 theorem iter_p_gen_knm:
400 \forall plusA: A \to A \to A.
401 (symmetric A plusA) \to
402 (associative A plusA) \to
403 (\forall a:A.(plusA a baseA) = a)\to
404 \forall g: nat \to A.
405 \forall h2:nat \to nat \to nat.
406 \forall h11,h12:nat \to nat.
408 \forall p1,p21:nat \to bool.
409 \forall p22:nat \to nat \to bool.
410 (\forall x. x < k \to p1 x = true \to
411 p21 (h11 x) = true \land p22 (h11 x) (h12 x) = true
412 \land h2 (h11 x) (h12 x) = x
413 \land (h11 x) < n \land (h12 x) < m) \to
414 (\forall i,j. i < n \to j < m \to p21 i = true \to p22 i j = true \to
415 p1 (h2 i j) = true \land
416 h11 (h2 i j) = i \land h12 (h2 i j) = j
417 \land h2 i j < k) \to
418 iter_p_gen k p1 A g baseA plusA =
419 iter_p_gen n p21 A (\lambda x:nat.iter_p_gen m (p22 x) A (\lambda y. g (h2 x y)) baseA plusA) baseA plusA.
421 rewrite < (iter_p_gen2' n m p21 p22 ? ? ? ? H H1 H2).
423 apply (eq_iter_p_gen_gh A baseA plusA H H1 H2 g ? (\lambda x.(h11 x)*m+(h12 x)))
425 elim (H4 (i/m) (i \mod m));clear H4
429 |apply (lt_times_to_lt_div ? ? ? H5)
431 apply (lt_times_to_lt_O ? ? ? H5)
432 |apply (andb_true_true ? ? H6)
433 |apply (andb_true_true_r ? ? H6)
436 elim (H4 (i/m) (i \mod m));clear H4
443 apply (lt_times_to_lt_O ? ? ? H5)
444 |apply (lt_times_to_lt_div ? ? ? H5)
446 apply (lt_times_to_lt_O ? ? ? H5)
447 |apply (andb_true_true ? ? H6)
448 |apply (andb_true_true_r ? ? H6)
451 elim (H4 (i/m) (i \mod m));clear H4
455 |apply (lt_times_to_lt_div ? ? ? H5)
457 apply (lt_times_to_lt_O ? ? ? H5)
458 |apply (andb_true_true ? ? H6)
459 |apply (andb_true_true_r ? ? H6)
466 rewrite > div_plus_times
467 [rewrite > mod_plus_times
480 rewrite > div_plus_times
481 [rewrite > mod_plus_times
492 apply (lt_to_le_to_lt ? ((h11 j)*m+m))
493 [apply monotonic_lt_plus_r.
496 change with ((S (h11 j)*m) \le n*m).
497 apply monotonic_le_times_l.
503 theorem iter_p_gen_divides:
506 \forall plusA: A \to A \to A.
507 \forall n,m,p:nat.O < n \to prime p \to Not (divides p n) \to
508 \forall g: nat \to A.
509 (symmetric A plusA) \to (associative A plusA) \to (\forall a:A.(plusA a baseA) = a)
513 iter_p_gen (S (n*(exp p m))) (\lambda x.divides_b x (n*(exp p m))) A g baseA plusA =
514 iter_p_gen (S n) (\lambda x.divides_b x n) A
515 (\lambda x.iter_p_gen (S m) (\lambda y.true) A (\lambda y.g (x*(exp p y))) baseA plusA) baseA plusA.
518 [rewrite < (iter_p_gen2 ? ? ? ? ? ? ? ? H3 H4 H5).
520 (iter_p_gen (S n*S m) (\lambda x:nat.divides_b (x/S m) n) A
521 (\lambda x:nat.g (x/S m*(p)\sup(x\mod S m))) baseA plusA) )
523 apply (eq_iter_p_gen_gh ? ? ? ? ? ? g ? (p_ord_times p (S m)))
528 lapply (divides_b_true_to_lt_O ? ? H H7).
529 apply divides_to_divides_b_true
530 [rewrite > (times_n_O O).
533 |apply lt_O_exp.assumption
536 [apply divides_b_true_to_divides.assumption
537 |apply (witness ? ? (p \sup (m-i \mod (S m)))).
538 rewrite < exp_plus_times.
541 apply plus_minus_m_m.
542 autobatch by le_S_S_to_le, lt_mod_m_m, lt_O_S;
546 lapply (divides_b_true_to_lt_O ? ? H H7).
548 rewrite > (p_ord_exp1 p ? (i \mod (S m)) (i/S m))
549 [change with ((i/S m)*S m+i \mod S m=i).
556 apply (trans_divides ? (i/ S m))
558 apply divides_b_true_to_divides;assumption]
565 change with ((i/S m) < S n).
566 apply (lt_times_to_lt_l m).
567 apply (le_to_lt_to_lt ? i);[2:assumption]
568 autobatch by eq_plus_to_le, div_mod, lt_O_S.
578 [rewrite > div_p_ord_times
579 [apply divides_to_divides_b_true
582 |apply (divides_b_true_to_lt_O ? ? ? H7).
583 rewrite > (times_n_O O).
585 [assumption|apply lt_O_exp.assumption]
587 |cut (n = ord_rem (n*(exp p m)) p)
589 apply divides_to_divides_ord_rem
590 [apply (divides_b_true_to_lt_O ? ? ? H7).
591 rewrite > (times_n_O O).
593 [assumption|apply lt_O_exp.assumption]
594 |rewrite > (times_n_O O).
596 [assumption|apply lt_O_exp.assumption]
598 |apply divides_b_true_to_divides.
602 rewrite > (p_ord_exp1 p ? m n)
612 |cut (m = ord (n*(exp p m)) p)
615 apply divides_to_le_ord
616 [apply (divides_b_true_to_lt_O ? ? ? H7).
617 rewrite > (times_n_O O).
619 [assumption|apply lt_O_exp.assumption]
620 |rewrite > (times_n_O O).
622 [assumption|apply lt_O_exp.assumption]
624 |apply divides_b_true_to_divides.
628 rewrite > (p_ord_exp1 p ? m n)
638 [rewrite > div_p_ord_times
639 [rewrite > mod_p_ord_times
640 [rewrite > sym_times.
644 |apply (divides_b_true_to_lt_O ? ? ? H7).
645 rewrite > (times_n_O O).
647 [assumption|apply lt_O_exp.assumption]
649 |cut (m = ord (n*(exp p m)) p)
652 apply divides_to_le_ord
653 [apply (divides_b_true_to_lt_O ? ? ? H7).
654 rewrite > (times_n_O O).
656 [assumption|apply lt_O_exp.assumption]
657 |rewrite > (times_n_O O).
659 [assumption|apply lt_O_exp.assumption]
661 |apply divides_b_true_to_divides.
665 rewrite > (p_ord_exp1 p ? m n)
675 |cut (m = ord (n*(exp p m)) p)
678 apply divides_to_le_ord
679 [apply (divides_b_true_to_lt_O ? ? ? H7).
680 rewrite > (times_n_O O).
682 [assumption|apply lt_O_exp.assumption]
683 |rewrite > (times_n_O O).
685 [assumption|apply lt_O_exp.assumption]
687 |apply divides_b_true_to_divides.
691 rewrite > (p_ord_exp1 p ? m n)
700 rewrite > eq_p_ord_times.
702 apply (lt_to_le_to_lt ? (S m +ord_rem j p*S m))
705 cut (m = ord (n*(p \sup m)) p)
707 apply divides_to_le_ord
708 [apply (divides_b_true_to_lt_O ? ? ? H7).
709 rewrite > (times_n_O O).
711 [assumption|apply lt_O_exp.assumption]
712 |rewrite > (times_n_O O).
714 [assumption|apply lt_O_exp.assumption]
716 |apply divides_b_true_to_divides.
721 rewrite > (p_ord_exp1 p ? m n)
728 |change with (S (ord_rem j p)*S m \le S n*S m).
731 cut (n = ord_rem (n*(p \sup m)) p)
736 |rewrite > (times_n_O O).
738 [assumption|apply lt_O_exp.assumption]
740 |apply divides_to_divides_ord_rem
741 [apply (divides_b_true_to_lt_O ? ? ? H7).
742 rewrite > (times_n_O O).
744 [assumption|apply lt_O_exp.assumption]
745 |rewrite > (times_n_O O).
747 [assumption|apply lt_O_exp.assumption]
749 |apply divides_b_true_to_divides.
755 rewrite > (p_ord_exp1 p ? m n)
767 elim (divides_b (x/S m) n);reflexivity
771 |elim H1.apply lt_to_le.assumption
777 theorem iter_p_gen_2_eq:
780 \forall plusA: A \to A \to A.
781 (symmetric A plusA) \to
782 (associative A plusA) \to
783 (\forall a:A.(plusA a baseA) = a)\to
784 \forall g: nat \to nat \to A.
785 \forall h11,h12,h21,h22: nat \to nat \to nat.
787 \forall p11,p21:nat \to bool.
788 \forall p12,p22:nat \to nat \to bool.
789 (\forall i,j. i < n2 \to j < m2 \to p21 i = true \to p22 i j = true \to
790 p11 (h11 i j) = true \land p12 (h11 i j) (h12 i j) = true
791 \land h21 (h11 i j) (h12 i j) = i \land h22 (h11 i j) (h12 i j) = j
792 \land h11 i j < n1 \land h12 i j < m1) \to
793 (\forall i,j. i < n1 \to j < m1 \to p11 i = true \to p12 i j = true \to
794 p21 (h21 i j) = true \land p22 (h21 i j) (h22 i j) = true
795 \land h11 (h21 i j) (h22 i j) = i \land h12 (h21 i j) (h22 i j) = j
796 \land (h21 i j) < n2 \land (h22 i j) < m2) \to
798 (\lambda x:nat .iter_p_gen m1 (p12 x) A (\lambda y. g x y) baseA plusA)
801 (\lambda x:nat .iter_p_gen m2 (p22 x) A (\lambda y. g (h11 x y) (h12 x y)) baseA plusA )
805 rewrite < (iter_p_gen2' ? ? ? ? ? ? ? ? H H1 H2).
806 letin ha:= (\lambda x,y.(((h11 x y)*m1) + (h12 x y))).
807 letin ha12:= (\lambda x.(h21 (x/m1) (x \mod m1))).
808 letin ha22:= (\lambda x.(h22 (x/m1) (x \mod m1))).
811 (iter_p_gen n2 p21 A (\lambda x:nat. iter_p_gen m2 (p22 x) A
812 (\lambda y:nat.(g (((h11 x y)*m1+(h12 x y))/m1) (((h11 x y)*m1+(h12 x y))\mod m1))) baseA plusA ) baseA plusA))
814 apply (iter_p_gen_knm A baseA plusA H H1 H2 (\lambda e. (g (e/m1) (e \mod m1))) ha ha12 ha22);intros
815 [ elim (and_true ? ? H6).
818 [ cut((x \mod m1) < m1)
819 [ elim (H4 ? ? Hcut1 Hcut2 H7 H8).
847 | apply (lt_times_n_to_lt m1)
849 | apply (le_to_lt_to_lt ? x)
850 [ apply (eq_plus_to_le ? ? (x \mod m1)).
857 | apply not_le_to_lt.unfold.intro.
858 generalize in match H5.
859 apply (le_n_O_elim ? H9).
864 | elim (H3 ? ? H5 H6 H7 H8).
869 cut(((h11 i j)*m1 + (h12 i j))/m1 = (h11 i j))
870 [ cut(((h11 i j)*m1 + (h12 i j)) \mod m1 = (h12 i j))
874 [ apply true_to_true_to_andb_true
895 [ apply (lt_to_le_to_lt ? ((h11 i j)*m1 + m1) )
899 | rewrite > sym_plus.
900 rewrite > (sym_times (h11 i j) m1).
901 rewrite > times_n_Sm.
906 | apply not_le_to_lt.unfold.intro.
907 generalize in match H12.
908 apply (le_n_O_elim ? H11).
912 | apply not_le_to_lt.unfold.intro.
913 generalize in match H10.
914 apply (le_n_O_elim ? H11).
919 | rewrite > (mod_plus_times m1 (h11 i j) (h12 i j)).
923 | rewrite > (div_plus_times m1 (h11 i j) (h12 i j)).
928 | apply (eq_iter_p_gen1)
929 [ intros. reflexivity
931 apply (eq_iter_p_gen1)
932 [ intros. reflexivity
934 rewrite > (div_plus_times)
935 [ rewrite > (mod_plus_times)
937 | elim (H3 x x1 H5 H7 H6 H8).
940 | elim (H3 x x1 H5 H7 H6 H8).
948 theorem iter_p_gen_iter_p_gen:
951 \forall plusA: A \to A \to A.
952 (symmetric A plusA) \to
953 (associative A plusA) \to
954 (\forall a:A.(plusA a baseA) = a)\to
955 \forall g: nat \to nat \to A.
957 \forall p11,p21:nat \to bool.
958 \forall p12,p22:nat \to nat \to bool.
959 (\forall x,y. x < n \to y < m \to
960 (p11 x \land p12 x y) = (p21 y \land p22 y x)) \to
962 (\lambda x:nat.iter_p_gen m (p12 x) A (\lambda y. g x y) baseA plusA)
965 (\lambda y:nat.iter_p_gen n (p22 y) A (\lambda x. g x y) baseA plusA )
968 apply (iter_p_gen_2_eq A baseA plusA H H1 H2 (\lambda x,y. g x y) (\lambda x,y.y) (\lambda x,y.x) (\lambda x,y.y) (\lambda x,y.x)
969 n m m n p11 p21 p12 p22)
975 [apply (andb_true_true ? (p12 j i)).
977 [rewrite > H6.rewrite > H7.reflexivity
981 |apply (andb_true_true_r (p11 j)).
983 [rewrite > H6.rewrite > H7.reflexivity
1001 [apply (andb_true_true ? (p22 j i)).
1003 [rewrite > H6.rewrite > H7.reflexivity
1007 |apply (andb_true_true_r (p21 j)).
1009 [rewrite > H6.rewrite > H7.reflexivity