Definition mkInjections (m1 m1' m2:mem) (j k l: meminj)
:  meminj * meminj * block * block :=
if plt (Mem.nextblock m1) (Mem.nextblock m1')
then mkInjectionsN (Pos.to_nat (Mem.nextblock m1') - Pos.to_nat(Mem.nextblock m1))
(Mem.nextblock m1)
(Mem.nextblock m2) j k l
else (j,k,Mem.nextblock m1,Mem.nextblock m2).

(* Specifications: *)
Lemma mkInjections_0: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2')),
( Pos.le (Mem.nextblock m1') (Mem.nextblock m1)  /\
Mem.nextblock  m1 = n1' /\ Mem.nextblock  m2 = n2' /\
j' = j /\ k' = k) \/
(exists N, (N > 0)%nat /\
(Mem.nextblock  m1 + (Pos.of_nat N) = n1')%positive /\
(n1' = Mem.nextblock  m1') /\
(Mem.nextblock  m2 + (Pos.of_nat N) = n2')%positive).
Lemma mkInjections_1_injinc: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(VB: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m1 b1),
inject_incr j j'.
Lemma mkInjections_1_injsep: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2')),
inject_separated j j' m1 m2.
Lemma mkInjections_2_injinc: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(VB: forall b1 b2 ofs2, k b1 = Some(b2,ofs2) -> Mem.valid_block m2 b1),
inject_incr k k'.
Lemma mkInjections_2_injsep: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(VB: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m1 b1)
m3 (Sep:inject_separated (compose_meminj j k) l m1 m3),
inject_separated k k' m2 m3.
Lemma mkInjections_3: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
b1 b2 ofs2,
j' b1 = Some(b2,ofs2) ->
(j b1 = Some (b2,ofs2)) \/
(b1 = Mem.nextblock m1 /\ b2 = Mem.nextblock m2 /\ ofs2 = 0) \/
(exists m, (b1 = Mem.nextblock m1 + m /\ b2=Mem.nextblock m2 + m)%positive /\ ofs2=0).
Lemma mkInjections_3V: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(HJ: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> (b1 < Mem.nextblock m1 /\ b2 < Mem.nextblock m2)%positive)
(HK: forall b2 b3 ofs3, k b2 = Some(b3,ofs3) -> (b2 < Mem.nextblock m2)%positive)
b1 b2 ofs2,
j' b1 = Some(b2,ofs2) ->
(j b1 = Some (b2,ofs2) /\ (b1 < Mem.nextblock m1 /\ b2 < Mem.nextblock m2)%positive) \/
(b1 = Mem.nextblock m1 /\ b2=Mem.nextblock m2 /\ ofs2=0 /\ (b1 < n1' /\ b2<n2')%positive) \/
(exists m, (b1 = Mem.nextblock m1 + m)%positive /\ (b2=Mem.nextblock m2 + m)%positive /\
ofs2=0 /\ (b1 < n1' /\ b2<n2')%positive).
Lemma mkInjections_4: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2')) b2 b3 ofs3,
k' b2 = Some(b3,ofs3) ->
k b2 = Some (b3,ofs3) \/
(b2 = Mem.nextblock m2 /\ l (Mem.nextblock m1) = Some(b3,ofs3)) \/
(exists m, (b2 = Mem.nextblock m2 + m)%positive /\
l ((Mem.nextblock m1+m)%positive) = Some(b3,ofs3)).
Lemma mkInjections_4Val: forall m1 m1' m2  j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2  j k l = (j',k',n1',n2'))
(HK: forall b2 b3 ofs3, k b2 = Some(b3,ofs3) -> (b2 < Mem.nextblock m2)%positive) b2 b3 ofs3,
k' b2 = Some(b3,ofs3) ->
(k b2 = Some (b3,ofs3) /\ (b2 < Mem.nextblock m2)%positive) \/
(b2 = Mem.nextblock m2 /\ l (Mem.nextblock m1) = Some(b3, ofs3) /\ (b2 < n2')%positive) \/
(exists m, (b2 = Mem.nextblock m2 + m)%positive /\
l ((Mem.nextblock m1+m)%positive) = Some(b3,ofs3) /\ (b2 < n2')%positive).
Lemma mkInjections_7: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
b (HB: (b < n1')%positive),
((Mem.nextblock m1 <= b)%positive -> j' b  <> None) /\
((b < Mem.nextblock m1)%positive -> j' b = j b).
Lemma mkInjections_6: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2')) b (J': j' b = None),
j b = None.
Lemma mkInjections_5: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(VBj1: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m1 b1)
(VBj2: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m2 b2)
(VBk2: forall b1 b2 ofs2, k b1 = Some(b2,ofs2) -> Mem.valid_block m2 b1)
(VBl1: forall b1 b2 ofs2, l b1 = Some(b2,ofs2) -> (b1 < n1')%positive)
b2 (HB: (b2 < n2')%positive),
k' b2 = None ->
(Mem.valid_block m2 b2 /\ k b2 = None) \/
(b2 = Mem.nextblock m2 /\ l (Mem.nextblock m1) = None) \/
(exists m, b2 = ((Mem.nextblock m2) + m)%positive /\
l ((Mem.nextblock m1+m)%positive) = None).
Lemma J12'_no_overlap: forall m1 m2 j12
(MInj12 : Mem.inject j12 m1 m2) m1' (Fwd1: mem_forward m1 m1') j23 m3
(MInj23 : Mem.inject j23 m2 m3) j' j12' j23' n1' n2'
(HeqMKI: mkInjections m1 m1' m2 j12 j23 j' = (j12', j23',n1',n2')),
Mem.meminj_no_overlap j12' m1'.
Lemma mkInjections_composememinj: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(InjIncr: inject_incr (compose_meminj j k) l) m3
(InjSep: inject_separated (compose_meminj j k) l m1 m3)
(VBj1: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m1 b1)
(VBj2: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m2 b2)
(VBk2: forall b1 b2 ofs2, k b1 = Some(b2,ofs2) -> Mem.valid_block m2 b1)
(VBL1': forall b1 b3 ofs3, l b1 = Some (b3, ofs3) -> (b1 < n1')%positive),
l = compose_meminj j' k'.
Lemma mkInjections_0: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2')),
( Pos.le (Mem.nextblock m1') (Mem.nextblock m1)  /\
Mem.nextblock  m1 = n1' /\ Mem.nextblock  m2 = n2' /\
j' = j /\ k' = k) \/
(exists N, (N > 0)%nat /\
(Mem.nextblock  m1 + (Pos.of_nat N) = n1')%positive /\
(n1' = Mem.nextblock  m1') /\
(Mem.nextblock  m2 + (Pos.of_nat N) = n2')%positive).
Lemma mkInjections_1_injinc: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(VB: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m1 b1),
inject_incr j j'.
Lemma mkInjections_1_injsep: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2')),
inject_separated j j' m1 m2.
Lemma mkInjections_2_injinc: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(VB: forall b1 b2 ofs2, k b1 = Some(b2,ofs2) -> Mem.valid_block m2 b1),
inject_incr k k'.
Lemma mkInjections_2_injsep: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(VB: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m1 b1)
m3 (Sep:inject_separated (compose_meminj j k) l m1 m3),
inject_separated k k' m2 m3.
Lemma mkInjections_3: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
b1 b2 ofs2,
j' b1 = Some(b2,ofs2) ->
(j b1 = Some (b2,ofs2)) \/
(b1 = Mem.nextblock m1 /\ b2 = Mem.nextblock m2 /\ ofs2 = 0) \/
(exists m, (b1 = Mem.nextblock m1 + m /\ b2=Mem.nextblock m2 + m)%positive /\ ofs2=0).
Lemma mkInjections_3V: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(HJ: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> (b1 < Mem.nextblock m1 /\ b2 < Mem.nextblock m2)%positive)
(HK: forall b2 b3 ofs3, k b2 = Some(b3,ofs3) -> (b2 < Mem.nextblock m2)%positive)
b1 b2 ofs2,
j' b1 = Some(b2,ofs2) ->
(j b1 = Some (b2,ofs2) /\ (b1 < Mem.nextblock m1 /\ b2 < Mem.nextblock m2)%positive) \/
(b1 = Mem.nextblock m1 /\ b2=Mem.nextblock m2 /\ ofs2=0 /\ (b1 < n1' /\ b2<n2')%positive) \/
(exists m, (b1 = Mem.nextblock m1 + m)%positive /\ (b2=Mem.nextblock m2 + m)%positive /\
ofs2=0 /\ (b1 < n1' /\ b2<n2')%positive).
Lemma mkInjections_4: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2')) b2 b3 ofs3,
k' b2 = Some(b3,ofs3) ->
k b2 = Some (b3,ofs3) \/
(b2 = Mem.nextblock m2 /\ l (Mem.nextblock m1) = Some(b3,ofs3)) \/
(exists m, (b2 = Mem.nextblock m2 + m)%positive /\
l ((Mem.nextblock m1+m)%positive) = Some(b3,ofs3)).
Lemma mkInjections_4Val: forall m1 m1' m2  j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2  j k l = (j',k',n1',n2'))
(HK: forall b2 b3 ofs3, k b2 = Some(b3,ofs3) -> (b2 < Mem.nextblock m2)%positive) b2 b3 ofs3,
k' b2 = Some(b3,ofs3) ->
(k b2 = Some (b3,ofs3) /\ (b2 < Mem.nextblock m2)%positive) \/
(b2 = Mem.nextblock m2 /\ l (Mem.nextblock m1) = Some(b3, ofs3) /\ (b2 < n2')%positive) \/
(exists m, (b2 = Mem.nextblock m2 + m)%positive /\
l ((Mem.nextblock m1+m)%positive) = Some(b3,ofs3) /\ (b2 < n2')%positive).
Lemma mkInjections_7: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
b (HB: (b < n1')%positive),
((Mem.nextblock m1 <= b)%positive -> j' b  <> None) /\
((b < Mem.nextblock m1)%positive -> j' b = j b).
Lemma mkInjections_6: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2')) b (J': j' b = None),
j b = None.
Lemma mkInjections_5: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(VBj1: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m1 b1)
(VBj2: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m2 b2)
(VBk2: forall b1 b2 ofs2, k b1 = Some(b2,ofs2) -> Mem.valid_block m2 b1)
(VBl1: forall b1 b2 ofs2, l b1 = Some(b2,ofs2) -> (b1 < n1')%positive)
b2 (HB: (b2 < n2')%positive),
k' b2 = None ->
(Mem.valid_block m2 b2 /\ k b2 = None) \/
(b2 = Mem.nextblock m2 /\ l (Mem.nextblock m1) = None) \/
(exists m, b2 = ((Mem.nextblock m2) + m)%positive /\
l ((Mem.nextblock m1+m)%positive) = None).
Lemma J12'_no_overlap: forall m1 m2 j12
(MInj12 : Mem.inject j12 m1 m2) m1' (Fwd1: mem_forward m1 m1') j23 m3
(MInj23 : Mem.inject j23 m2 m3) j' j12' j23' n1' n2'
(HeqMKI: mkInjections m1 m1' m2 j12 j23 j' = (j12', j23',n1',n2')),
Mem.meminj_no_overlap j12' m1'.
Lemma mkInjections_composememinj: forall m1 m1' m2 j k l j' k' n1' n2'
(HI: mkInjections m1 m1' m2 j k l = (j',k',n1',n2'))
(InjIncr: inject_incr (compose_meminj j k) l) m3
(InjSep: inject_separated (compose_meminj j k) l m1 m3)
(VBj1: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m1 b1)
(VBj2: forall b1 b2 ofs2, j b1 = Some(b2,ofs2) -> Mem.valid_block m2 b2)
(VBk2: forall b1 b2 ofs2, k b1 = Some(b2,ofs2) -> Mem.valid_block m2 b1)
(VBL1': forall b1 b3 ofs3, l b1 = Some (b3, ofs3) -> (b1 < n1')%positive),
l = compose_meminj j' k'.