104 lines
3.3 KiB
Plaintext
Raw Normal View History

2026-04-14 19:55:28 +01:00
%% div.elf - Divisibility on Natural Numbers
%%
%% We define:
%% - divides D N: D divides N (D | N), meaning N = D * K for some K
%% ============================================================
%% DIVISIBILITY
%% ============================================================
%% D divides N if there exists K such that D * K = N
divides : nat -> nat -> type.
divides/intro : divides D N
<- mult D K N.
%% ============================================================
%% BASIC DIVISIBILITY FACTS
%% ============================================================
%% 1 divides everything: 1 | N
one-divides : {N:nat} divides (s z) N -> type.
%mode one-divides +N -D.
one-divides/base : one-divides N (divides/intro Dmult)
<- mult-left-one N Dmult.
%worlds () (one-divides _ _).
%total {} (one-divides _ _).
%% Everything divides 0: N | 0
divides-zero : {N:nat} divides N z -> type.
%mode divides-zero +N -D.
%% For any N, mult N z z holds (mult/z pattern doesn't work here)
%% We need to use mult-right-z
divides-zero/base : divides-zero N (divides/intro D)
<- mult-right-z N D.
%worlds () (divides-zero _ _).
%total {} (divides-zero _ _).
%% N divides itself: N | N (reflexivity)
divides-refl : {N:nat} divides N N -> type.
%mode divides-refl +N -D.
divides-refl/base : divides-refl N (divides/intro Dmult)
<- mult-right-one N Dmult.
%worlds () (divides-refl _ _).
%total {} (divides-refl _ _).
%% ============================================================
%% DIVISION WITH REMAINDER (EUCLIDEAN DIVISION)
%% ============================================================
%% For D > 0 and any N, there exist unique Q, R with N = D*Q + R and R < D
%% We represent this as: divmod N D Q R means N = D*Q + R and R < D
divmod : nat -> nat -> nat -> nat -> type.
%% Base case: if N < D, then Q = 0, R = N
divmod/lt : divmod N D z N
<- lt N D.
%% Recursive case: if N >= D, we need to compute (N - D) div D
%% This requires a subtraction relation, which we'll define
%% Subtraction: sub A B C means A = B + C (so C = A - B when B <= A)
sub : nat -> nat -> nat -> type.
sub/z : sub N z N.
sub/s : sub (s A) (s B) C
<- sub A B C.
%% Now we can define divmod for the recursive case
divmod/ge : divmod N D (s Q) R
<- le D N %% D <= N
<- sub N D M %% M = N - D
<- divmod M D Q R. %% M = D*Q + R, so N = D*(Q+1) + R
%% ============================================================
%% GCD (Greatest Common Divisor)
%% ============================================================
%% Euclidean algorithm: gcd(A, 0) = A, gcd(A, B) = gcd(B, A mod B)
%% We define gcd using the Euclidean algorithm
%% gcd A B G means G is the GCD of A and B
gcd : nat -> nat -> nat -> type.
gcd/z : gcd A z A. %% gcd(A, 0) = A
gcd/s : gcd A (s B) G
<- divmod A (s B) Q R %% A = (s B)*Q + R with R < s B
<- gcd (s B) R G. %% G = gcd(s B, R)
%% ============================================================
%% COPRIMALITY
%% ============================================================
%% A and B are coprime if gcd(A, B) = 1
coprime : nat -> nat -> type.
coprime/intro : coprime A B
<- gcd A B (s z).