Require Import Coq.ZArith.BinInt.
Require Import Coq.micromega.Lia.
Require Import Coq.ZArith.ZArith.

Local Open Scope Z_scope.

Module ZLib.


forall n : Z, n mod 2 = 0 \/ n mod 2 = 1

forall n : Z, n mod 2 = 0 \/ n mod 2 = 1
n:Z

n mod 2 = 0 \/ n mod 2 = 1
n:Z
H:0 < 2 -> 0 <= n mod 2 < 2

n mod 2 = 0 \/ n mod 2 = 1
lia. Qed.

forall a b : Z, b <> 0 -> a mod b = 0 -> a / b * b = a

forall a b : Z, b <> 0 -> a mod b = 0 -> a / b * b = a
a, b:Z
H:b <> 0
H0:a mod b = 0

a / b * b = a
a, b:Z
H:b <> 0
H0:a mod b = 0
A:forall a b c : Z, b <> 0 -> c <> 0 -> c * a / (c * b) = a / b

a / b * b = a
a, b:Z
H:b <> 0
H0:a mod b = 0
A:1 <> 0 -> b <> 0 -> b * a / (b * 1) = a / 1

a / b * b = a
a, b:Z
H:b <> 0
H0:a mod b = 0
A:1 <> 0 -> b <> 0 -> b * a / b = a / 1

a / b * b = a
a, b:Z
H:b <> 0
H0:a mod b = 0
A:1 <> 0 -> b <> 0 -> b * a / b = a

a / b * b = a
a, b:Z
H:b <> 0
H0:a mod b = 0
A:1 <> 0 -> b <> 0 -> b * a / b = a

b * (a / b) = a
a, b:Z
H:b <> 0
H0:a mod b = 0
A:1 <> 0 -> b <> 0 -> b * a / b = a

b * a / b = a
a, b:Z
H:b <> 0
H0:a mod b = 0
A:1 <> 0 -> b <> 0 -> b * a / b = a
(b | a)
a, b:Z
H:b <> 0
H0:a mod b = 0
A:1 <> 0 -> b <> 0 -> b * a / b = a

b * a / b = a
apply A; congruence.
a, b:Z
H:b <> 0
H0:a mod b = 0
A:1 <> 0 -> b <> 0 -> b * a / b = a

(b | a)
apply Z.mod_divide; assumption. Qed.

forall m : Z, m mod 0 = 0

forall m : Z, m mod 0 = 0
m:Z

m mod 0 = 0
destruct m; reflexivity. Qed.

forall a b m : Z, a mod m = 0 -> b mod m = 0 -> (a - b) mod m = 0

forall a b m : Z, a mod m = 0 -> b mod m = 0 -> (a - b) mod m = 0
a, b, m:Z

a mod m = 0 -> b mod m = 0 -> (a - b) mod m = 0
a, b, m:Z
E1:a mod m = 0
E2:b mod m = 0

(a - b) mod m = 0
a, b, m:Z
E1:a mod m = 0
E2:b mod m = 0

(a mod m - b mod m) mod m = 0
a, b, m:Z
E1:a mod m = 0
E2:b mod m = 0

(0 - b mod m) mod m = 0
a, b, m:Z
E1:a mod m = 0
E2:b mod m = 0

(0 - 0) mod m = 0
reflexivity. Qed.

forall a b m : Z, a mod m = 0 -> b mod m = 0 -> (a + b) mod m = 0

forall a b m : Z, a mod m = 0 -> b mod m = 0 -> (a + b) mod m = 0
a, b, m:Z

a mod m = 0 -> b mod m = 0 -> (a + b) mod m = 0
a, b, m:Z
E1:a mod m = 0
E2:b mod m = 0

(a + b) mod m = 0
a, b, m:Z
E1:a mod m = 0
E2:b mod m = 0

(a mod m + b mod m) mod m = 0
a, b, m:Z
E1:a mod m = 0
E2:b mod m = 0

(0 + b mod m) mod m = 0
a, b, m:Z
E1:a mod m = 0
E2:b mod m = 0

(0 + 0) mod m = 0
reflexivity. Qed.

forall a b : Z, (a * b) mod a = 0

forall a b : Z, (a * b) mod a = 0
a, b:Z

(a * b) mod a = 0
a, b:Z

(b * a) mod a = 0
apply Z_mod_mult. Qed.

forall a b : Z, b <> 0 -> (a + b) mod b = a mod b

forall a b : Z, b <> 0 -> (a + b) mod b = a mod b
a, b:Z
H:b <> 0

(a + b) mod b = a mod b
a, b:Z
H:b <> 0

(a + b mod b) mod b = a mod b
a, b:Z
H:b <> 0

(a + 0) mod b = a mod b
a, b:Z
H:b <> 0

a mod b = a mod b
reflexivity. Qed.

forall a n : Z, a mod 2 ^ n = a -> 2 ^ n = 0 /\ a = 0 \/ 0 <= a < 2 ^ n

forall a n : Z, a mod 2 ^ n = a -> 2 ^ n = 0 /\ a = 0 \/ 0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a

2 ^ n = 0 /\ a = 0 \/ 0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
C:n < 0 \/ 0 <= n

2 ^ n = 0 /\ a = 0 \/ 0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
C:n < 0

2 ^ n = 0 /\ a = 0 \/ 0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
C:0 <= n
2 ^ n = 0 /\ a = 0 \/ 0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
C:n < 0

2 ^ n = 0 /\ a = 0 \/ 0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
C:n < 0

2 ^ n = 0 /\ a = 0
a, n:Z
H:a mod 0 = a
C:n < 0

0 = 0 /\ a = 0
a, n:Z
H:0 = a
C:n < 0

0 = 0 /\ a = 0
auto.
a, n:Z
H:a mod 2 ^ n = a
C:0 <= n

2 ^ n = 0 /\ a = 0 \/ 0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
C:0 <= n

0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
C:0 <= n

0 <= a mod 2 ^ n < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
C:0 <= n

0 < 2 ^ n
apply Z.pow_pos_nonneg; lia. Qed.

forall a n : Z, a mod 2 ^ n = a -> 0 <= n -> 0 <= a < 2 ^ n

forall a n : Z, a mod 2 ^ n = a -> 0 <= n -> 0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
H0:0 <= n

0 <= a < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
H0:0 <= n

0 <= a mod 2 ^ n < 2 ^ n
a, n:Z
H:a mod 2 ^ n = a
H0:0 <= n

0 < 2 ^ n
apply Z.pow_pos_nonneg; lia. Qed.

forall n : Z, 0 <= 2 ^ n

forall n : Z, 0 <= 2 ^ n
n:Z

0 <= 2 ^ n
n:Z

0 <= 2
lia. Qed.

forall n : Z, 0 <= n -> 0 < 2 ^ n

forall n : Z, 0 <= n -> 0 < 2 ^ n
n:Z
H:0 <= n

0 < 2 ^ n
apply Z.pow_pos_nonneg; lia. Qed.

forall i : Z, 0 < i -> 2 ^ i = 2 * 2 ^ (i - 1)

forall i : Z, 0 < i -> 2 ^ i = 2 * 2 ^ (i - 1)
i:Z
H:0 < i

2 ^ i = 2 * 2 ^ (i - 1)
i:Z
H:0 < i

2 ^ i = 2 ^ Z.succ (i - 1)
i:Z
H:0 < i

i = Z.succ (i - 1)
lia. Qed.

forall i : Z, 0 <= i -> 2 ^ (i - 1) = 2 ^ i / 2

forall i : Z, 0 <= i -> 2 ^ (i - 1) = 2 ^ i / 2
i:Z
H:0 <= i

2 ^ (i - 1) = 2 ^ i / 2
i:Z
H:0 <= i
C:i = 0 \/ 0 < i

2 ^ (i - 1) = 2 ^ i / 2
i:Z
H:0 <= i
C:i = 0

2 ^ (i - 1) = 2 ^ i / 2
i:Z
H:0 <= i
C:0 < i
2 ^ (i - 1) = 2 ^ i / 2
i:Z
H:0 <= i
C:i = 0

2 ^ (i - 1) = 2 ^ i / 2
H:0 <= 0

2 ^ (0 - 1) = 2 ^ 0 / 2
reflexivity.
i:Z
H:0 <= i
C:0 < i

2 ^ (i - 1) = 2 ^ i / 2
i:Z
H:0 <= i
C:0 < i

2 ^ i / 2 ^ 1 = 2 ^ i / 2
reflexivity. Qed.

forall a b : Z, 0 <= a -> 0 < b -> a / b * b <= a

forall a b : Z, 0 <= a -> 0 < b -> a / b * b <= a
a, b:Z
H:0 <= a
H0:0 < b

a / b * b <= a
a, b:Z
H:0 <= a
H0:0 < b
P:b <> 0 -> a mod b = a - a / b * b

a / b * b <= a
a, b:Z
H:0 <= a
H0:0 < b
P:b <> 0 -> a mod b = a - a / b * b
Q:0 <= a -> 0 < b -> 0 <= a mod b < b

a / b * b <= a
lia. Qed.

forall a i : Z, 0 <= a -> 0 <= i -> Z.testbit a i = true -> 2 ^ i <= a

forall a i : Z, 0 <= a -> 0 <= i -> Z.testbit a i = true -> 2 ^ i <= a
a, i:Z
H:0 <= a
H0:0 <= i
H1:Z.testbit a i = true

2 ^ i <= a
a, i:Z
H:0 <= a
H0:0 <= i
H1:(a / 2 ^ i) mod 2 = 1

2 ^ i <= a
a, i:Z
H:0 <= a
H0:0 <= i
H1:(a / 2 ^ i) mod 2 = 1
H2:0 < 2 ^ i

2 ^ i <= a
a, i:Z
H:0 <= a
H0:0 <= i
H1:(a / 2 ^ i) mod 2 = 1
H2:0 < 2 ^ i

2 ^ i <= a / 2 ^ i * 2 ^ i
a, i:Z
H:0 <= a
H0:0 <= i
H1:(a / 2 ^ i) mod 2 = 1
H2:0 < 2 ^ i

1 * 2 ^ i <= a / 2 ^ i * 2 ^ i
a, i:Z
H:0 <= a
H0:0 <= i
H1:(a / 2 ^ i) mod 2 = 1
H2:0 < 2 ^ i

1 <= a / 2 ^ i
a, i:Z
H:0 <= a
H0:0 <= i
H1:(a / 2 ^ i) mod 2 = 1
H2:0 < 2 ^ i
H3:0 <= a -> 0 < 2 ^ i -> 0 <= a / 2 ^ i

1 <= a / 2 ^ i
a, i:Z
H:0 <= a
H0:0 <= i
H1:(a / 2 ^ i) mod 2 = 1
H2:0 < 2 ^ i
H3:0 <= a -> 0 < 2 ^ i -> 0 <= a / 2 ^ i

a / 2 ^ i <> 0
a, i:Z
H:0 <= a
H0:0 <= i
H1:(a / 2 ^ i) mod 2 = 1
H2:0 < 2 ^ i
H3:0 <= a -> 0 < 2 ^ i -> 0 <= a / 2 ^ i
E:a / 2 ^ i = 0

False
a, i:Z
H:0 <= a
H0:0 <= i
H1:0 mod 2 = 1
H2:0 < 2 ^ i
H3:0 <= a -> 0 < 2 ^ i -> 0 <= a / 2 ^ i
E:a / 2 ^ i = 0

False
a, i:Z
H:0 <= a
H0:0 <= i
H1:0 = 1
H2:0 < 2 ^ i
H3:0 <= a -> 0 < 2 ^ i -> 0 <= a / 2 ^ i
E:a / 2 ^ i = 0

False
discriminate H1. Qed.

forall a b c d : Z, 0 < d -> a <= b <= c -> a / d <= b / d <= c / d

forall a b c d : Z, 0 < d -> a <= b <= c -> a / d <= b / d <= c / d
a, b, c, d:Z
H:0 < d
H1:a <= b
H2:b <= c

a / d <= b / d
a, b, c, d:Z
H:0 < d
H1:a <= b
H2:b <= c
b / d <= c / d
a, b, c, d:Z
H:0 < d
H1:a <= b
H2:b <= c

a / d <= b / d
apply (Z.div_le_mono _ _ _ H H1).
a, b, c, d:Z
H:0 < d
H1:a <= b
H2:b <= c

b / d <= c / d
apply (Z.div_le_mono _ _ _ H H2). Qed.

forall a i : Z, 0 <= i -> 2 ^ i <= a < 2 ^ (i + 1) -> Z.testbit a i = true

forall a i : Z, 0 <= i -> 2 ^ i <= a < 2 ^ (i + 1) -> Z.testbit a i = true
a, i:Z
H:0 <= i
H0:2 ^ i <= a < 2 ^ (i + 1)

Z.testbit a i = true
a, i:Z
H:0 <= i
H0:2 ^ i <= a < 2 ^ (i + 1)

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:2 ^ i <= a
B:a < 2 ^ (i + 1)

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:2 ^ i <= a
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:2 ^ i / 2 ^ i <= a / 2 ^ i
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:1 <= a / 2 ^ i
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:1 <= a / 2 ^ i
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i
P:a < 2 ^ i * 2 -> a / 2 ^ i < 2

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:1 <= a / 2 ^ i
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i
P:a < 2 * 2 ^ i -> a / 2 ^ i < 2

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:1 <= a / 2 ^ i
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i
P:a < 2 * 2 ^ (i + 1 - 1) -> a / 2 ^ (i + 1 - 1) < 2

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:1 <= a / 2 ^ i
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i
P:a < 2 ^ (i + 1) -> a / 2 ^ (i + 1 - 1) < 2

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:1 <= a / 2 ^ i
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i
P:a / 2 ^ (i + 1 - 1) < 2

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:1 <= a / 2 ^ i
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i
P:a / 2 ^ i < 2

(a / 2 ^ i) mod 2 = 1
a, i:Z
H:0 <= i
A:1 <= a / 2 ^ i
B:a < 2 ^ (i + 1)
Q:0 < 2 ^ i
P:a / 2 ^ i < 2

1 mod 2 = 1
reflexivity. Qed.

forall a i : Z, 0 <= a < 2 ^ i -> 0 < i -> Z.testbit a (i - 1) = false -> a < 2 ^ (i - 1)

forall a i : Z, 0 <= a < 2 ^ i -> 0 < i -> Z.testbit a (i - 1) = false -> a < 2 ^ (i - 1)
a, i:Z
H:0 <= a < 2 ^ i
H0:0 < i
H1:Z.testbit a (i - 1) = false

a < 2 ^ (i - 1)
a, i:Z
H:0 <= a < 2 ^ i
H0:0 < i
H1:Z.testbit a (i - 1) = false
C:2 ^ (i - 1) <= a < 2 ^ i \/ a < 2 ^ (i - 1)

a < 2 ^ (i - 1)
a, i:Z
H:0 <= a < 2 ^ i
H0:0 < i
H1:Z.testbit a (i - 1) = false
C:2 ^ (i - 1) <= a < 2 ^ i

False
a, i:Z
H:0 <= a < 2 ^ i
H0:0 < i
H1:Z.testbit a (i - 1) = false
C:2 ^ (i - 1) <= a < 2 ^ i

Z.testbit a (i - 1) = true
a, i:Z
H:0 <= a < 2 ^ i
H0:0 < i
H1:Z.testbit a (i - 1) = false
C:2 ^ (i - 1) <= a < 2 ^ (i - 1 + 1)

Z.testbit a (i - 1) = true
apply testbit_true_nonneg'; lia. Qed.

forall sz n : Z, - 2 ^ (sz - 1) <= n < 2 ^ (sz - 1) -> 0 < sz

forall sz n : Z, - 2 ^ (sz - 1) <= n < 2 ^ (sz - 1) -> 0 < sz
sz, n:Z
H:- 2 ^ (sz - 1) <= n < 2 ^ (sz - 1)

0 < sz
sz, n:Z
H:- 2 ^ (sz - 1) <= n < 2 ^ (sz - 1)
C:0 < sz \/ sz - 1 < 0

0 < sz
sz, n:Z
H:- 2 ^ (sz - 1) <= n < 2 ^ (sz - 1)
C:sz - 1 < 0

False
sz, n:Z
H:- 0 <= n < 0
C:sz - 1 < 0

False
lia. Qed.

forall base a b c d : Z, 0 <= b < base -> 0 <= d < base -> base * a + b = base * c + d -> b = d

forall base a b c d : Z, 0 <= b < base -> 0 <= d < base -> base * a + b = base * c + d -> b = d
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d

b = d
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d
P:forall a b q r : Z, 0 <= r < b \/ b < r <= 0 -> a = b * q + r -> r = a mod b

b = d
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d
P:forall a : Z, 0 <= d < base \/ base < d <= 0 -> a = base * c + d -> d = a mod base

b = d
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d
P:0 <= d < base \/ base < d <= 0 -> d = (base * a + b) mod base

b = d
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d
P:0 <= d < base \/ base < d <= 0 -> d = (base * a + b) mod base

b = (base * a + b) mod base
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d
P:0 <= d < base \/ base < d <= 0 -> d = (base * a + b) mod base

b = ((base * a) mod base + b) mod base
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d
P:0 <= d < base \/ base < d <= 0 -> d = (base * a + b) mod base

b = ((a * base) mod base + b) mod base
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d
P:0 <= d < base \/ base < d <= 0 -> d = (base * a + b) mod base

b = (0 + b) mod base
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d
P:0 <= d < base \/ base < d <= 0 -> d = (base * a + b) mod base

b = b mod base
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d
P:0 <= d < base \/ base < d <= 0 -> d = (base * a + b) mod base

b = b
reflexivity. Qed.

forall base a b c d : Z, 0 <= b < base -> 0 <= d < base -> base * a + b = base * c + d -> a = c

forall base a b c d : Z, 0 <= b < base -> 0 <= d < base -> base * a + b = base * c + d -> a = c
base, a, b, c, d:Z
H:0 <= b < base
H0:0 <= d < base
H1:base * a + b = base * c + d

a = c
nia. Qed.

forall n : Z, n < 0 -> Z.to_nat n = 0%nat

forall n : Z, n < 0 -> Z.to_nat n = 0%nat
n:Z
H:n < 0

Z.to_nat n = 0%nat
destruct n; (lia||reflexivity). Qed. End ZLib. Module ZExtra.

forall x y m : Z, 0 < m -> x mod m = 0 -> y mod m = 0 -> x <> y -> x + m > y -> y + m <= x

forall x y m : Z, 0 < m -> x mod m = 0 -> y mod m = 0 -> x <> y -> x + m > y -> y + m <= x
x, y, m:Z

0 < m -> x mod m = 0 -> y mod m = 0 -> x <> y -> x + m > y -> y + m <= x
x, y, m:Z
POS:0 < m
XMOD:x mod m = 0
YMOD:y mod m = 0
NEQ:x <> y
H:x + m > y

y + m <= x
x, y, m:Z
POS:0 < m
XMOD:x mod m = 0
YMOD:y mod m = 0
NEQ:x <> y
H:x + m > y
g:y + m > x

y + m <= x
x, y, m:Z
POS:0 < m
XMOD:x mod m = 0
YMOD:(m | y)
NEQ:x <> y
H:x + m > y
g:y + m > x

y + m <= x
x, y, m:Z
POS:0 < m
XMOD:(m | x)
YMOD:(m | y)
NEQ:x <> y
H:x + m > y
g:y + m > x

y + m <= x
y, m:Z
POS:0 < m
x':Z
YMOD:(m | y)
g:y + m > x' * m
H:x' * m + m > y
NEQ:x' * m <> y

y + m <= x' * m
m:Z
POS:0 < m
x', y':Z
NEQ:x' * m <> y' * m
H:x' * m + m > y' * m
g:y' * m + m > x' * m

y' * m + m <= x' * m
m:Z
POS:0 < m
x', y':Z
H:x' * m + m > y' * m
g:y' * m + m > x' * m
NEQ':x' <> y'

y' * m + m <= x' * m
m:Z
POS:0 < m
x', y':Z
H:Z.succ x' * m > y' * m
g:y' * m + m > x' * m
NEQ':x' <> y'

y' * m + m <= x' * m
m:Z
POS:0 < m
x', y':Z
H:Z.succ x' * m > y' * m
g:Z.succ y' * m > x' * m
NEQ':x' <> y'

y' * m + m <= x' * m
apply Zmult_gt_reg_r in H; apply Zmult_gt_reg_r in g; lia. Qed.

forall x y : positive, (x < y)%positive -> x <> y

forall x y : positive, (x < y)%positive -> x <> y
lia. Qed.

forall x y : positive, (y < x)%positive -> x <> y

forall x y : positive, (y < x)%positive -> x <> y
lia. Qed.

forall x y n : positive, (x <= y)%positive -> (x < y + n)%positive

forall x y n : positive, (x <= y)%positive -> (x < y + n)%positive
lia. Qed. End ZExtra.