Module Align
Require Import Coqlib ZArith Psatz IntFacts.
Require Import BigNumPrelude.
Open Scope Z_scope.
Lemma align_plus:
forall al z,
al = 1 \/
al = 2 \/
al = 4 \/
al = 8 ->
align (
align z al) 8 =
align z 8.
Proof.
intros al z.
unfold align.
intros.
elim_div.
assert (
al <> 0)
by lia.
intuition subst;
lia.
Qed.
Lemma align_align:
forall z a (
apos:
a > 0),
align (
align z a)
a =
align z a.
Proof.
Lemma align_ge1:
forall sz al,
al > 0 ->
exists b, 0 <=
b <
al /\
align sz al =
sz +
b /\
b = (
al - 1 - (
sz - 1 -
al * ((
sz - 1) /
al))).
Proof.
intros.
generalize (
align_le sz al H).
destruct (
align_divides sz al H).
rewrite H0.
intros.
unfold align in H0.
rewrite <-
H0.
replace ((
sz+
al-1)/
al)
with (1+ ((
sz-1)/
al)).
{
replace ((1+ ((
sz-1)/
al))*
al)
with (
al + (
sz -1)/
al *
al).
{
rewrite Z.mul_comm.
replace (
al * ((
sz - 1) /
al))
with
(
al * ((
sz - 1) /
al) + (
sz-1)
mod al - (
sz-1)
mod al)
by omega.
rewrite <-
Z.div_mod by omega.
rewrite Z.mod_eq by omega.
exists (
al - 1 - (
sz - 1 -
al * ((
sz - 1) /
al))).
split;
try omega.
{
elim_div.
assert (
al <> 0)
by omega.
intuition.
}
}
rewrite Z.mul_add_distr_r.
omega.
}
{
replace (
sz +
al - 1)
with ((
sz -1) + 1*
al)
by omega.
rewrite Z_div_plus_full by omega.
omega.
}
Qed.
Lemma align_add:
forall al sz sz',
al > 0 ->
0 <=
sz <=
sz' ->
align sz al <=
align sz'
al.
Proof.
intros.
generalize (
align_ge1 sz al H)
(
align_ge1 sz'
al H).
intros [
b [
A [
B C]]] [
c [
D [
E F]]].
destruct (
zlt (
sz'-
sz)
al);
try intuition omega.
assert (
exists d, 0 <=
d <
al /\
sz' =
sz +
d).
{
clear -
H0 H l.
exists (
sz'-
sz).
intuition try omega.
}
destruct H1 as [
d [
ENC EQ]].
rewrite EQ in *.
clear EQ.
rewrite B;
rewrite E.
cut (
al * ((
sz - 1) /
al) <=
(
al * ((
sz +
d - 1) /
al)));
intros;
try omega.
apply Z.mul_le_mono_nonneg_l;
try omega.
apply Z.div_le_mono;
try omega.
Qed.
Lemma align_distr:
forall al (
AlPos:
al > 0)
z z1,
align z al +
align z1 al =
align (
align z al +
z1)
al.
Proof.
Lemma align_refl:
forall al (
AlPos:
al > 0),
align al al =
al.
Proof.
intros.
unfold align.
elim_div.
intuition.
assert (
al * (2 -
z) - 1 =
z0)
by lia.
subst.
assert (
al * (2-
z) <=
al)
by lia.
clear H2.
assert (
al * (1 -
z) <= 0).
lia.
assert (1 -
z <= 0).
apply Z.le_mul_0 in H2.
destr.
assert (
z >= 1)
by lia.
destruct (
zlt z 2).
assert (
z = 1)
by lia.
subst;
lia.
assert (2 -
z <= 0)
by lia.
apply Z.mul_le_mono_nonneg_l with (
p:=
al)
in H5;
try lia.
Qed.
Lemma align_0:
forall al,
al > 0 ->
align 0
al = 0.
Proof.
intros.
unfold align.
elim_div.
intuition.
assert (
al * (1 -
z) - 1 =
z0)
by lia.
subst.
clear H0.
assert (
al * (1 -
z) <=
al * 1)
by lia.
assert (0 <=
al * (1 - (1-
z)))
by lia.
apply Z.mul_nonneg_cancel_l in H1;
try lia.
assert (
z >= 0)
by lia.
clear H1 H0 H3.
destruct (
zlt z 1).
assert (
z = 0).
lia.
subst.
lia.
assert (1 -
z <= 0)
by lia.
apply Z.mul_le_mono_nonneg_l with (
p:=
al)
in H0;
try lia.
Qed.