File: number.mlw

package info (click to toggle)
why3 1.8.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 45,020 kB
  • sloc: xml: 185,443; ml: 111,224; ansic: 3,998; sh: 2,578; makefile: 2,568; java: 865; python: 720; javascript: 290; lisp: 205; pascal: 173
file content (208 lines) | stat: -rw-r--r-- 5,466 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208

(** {1 Number theory} *)


(** {2 Parity properties} *)

module Parity

  use int.Int

  predicate even (n: int) = exists k: int. n = 2 * k
  predicate odd (n: int) = exists k: int. n = 2 * k + 1

  lemma even_or_odd: forall n: int. even n \/ odd n

  lemma even_not_odd: forall n: int. even n -> not (odd n)
  lemma odd_not_even: forall n: int. odd n -> not (even n)

  lemma even_odd: forall n: int. even n -> odd (n + 1)
  lemma odd_even: forall n: int. odd n -> even (n + 1)

  lemma even_even: forall n: int. even n -> even (n + 2)
  lemma odd_odd: forall n: int. odd n -> odd (n + 2)

  lemma even_2k: forall k: int. even (2 * k)
  lemma odd_2k1: forall k: int. odd (2 * k + 1)

  use int.ComputerDivision

  lemma even_mod2 :
    forall n:int. even n <-> mod n 2 = 0

end

(** {2 Divisibility} *)

module Divisibility

  use export int.Int
  use int.ComputerDivision

  let predicate divides (d:int) (n:int)
    ensures { result <-> exists q:int. n = q * d }
  = if d = 0 then n = 0 else mod n d = 0

  lemma divides_refl: forall n:int. divides n n
  lemma divides_1_n : forall n:int. divides 1 n
  lemma divides_0   : forall n:int. divides n 0

  lemma divides_left : forall a b c: int. divides a b -> divides (c*a) (c*b)
  lemma divides_right: forall a b c: int. divides a b -> divides (a*c) (b*c)

  lemma divides_oppr: forall a b: int. divides a b -> divides a (-b)
  lemma divides_oppl: forall a b: int. divides a b -> divides (-a) b
  lemma divides_oppr_rev: forall a b: int. divides (-a) b -> divides a b
  lemma divides_oppl_rev: forall a b: int. divides a (-b) -> divides a b

  lemma divides_plusr:
    forall a b c: int. divides a b -> divides a c -> divides a (b + c)
  lemma divides_minusr:
    forall a b c: int. divides a b -> divides a c -> divides a (b - c)
  lemma divides_multl:
    forall a b c: int. divides a b -> divides a (c * b)
  lemma divides_multr:
    forall a b c: int. divides a b -> divides a (b * c)

  lemma divides_factorl: forall a b: int. divides a (b * a)
  lemma divides_factorr: forall a b: int. divides a (a * b)

  lemma divides_n_1: forall n: int. divides n 1 -> n = 1 \/ n = -1

  lemma divides_antisym:
    forall a b: int. divides a b -> divides b a -> a = b \/ a = -b

  lemma divides_trans:
    forall a b c: int. divides a b -> divides b c -> divides a c

  use int.Abs

  lemma divides_bounds:
    forall a b: int. divides a b -> b <> 0 -> abs a <= abs b

  use int.EuclideanDivision as ED

  lemma mod_divides_euclidean:
    forall a b: int. b <> 0 -> ED.mod a b = 0 -> divides b a
  lemma divides_mod_euclidean:
    forall a b: int. b <> 0 -> divides b a -> ED.mod a b = 0

  use int.ComputerDivision as CD

  lemma mod_divides_computer:
    forall a b: int. b <> 0 -> CD.mod a b = 0 -> divides b a
  lemma divides_mod_computer:
    forall a b: int. b <> 0 -> divides b a -> CD.mod a b = 0

  use Parity

  lemma even_divides: forall a: int. even a <-> divides 2 a
  lemma odd_divides: forall a: int. odd a <-> not (divides 2 a)

end

(** {2 Greateast Common Divisor} *)

module Gcd

  use export int.Int
  use Divisibility

  function gcd int int : int

  axiom gcd_nonneg: forall a b: int. 0 <= gcd a b
  axiom gcd_def1  : forall a b: int. divides (gcd a b) a
  axiom gcd_def2  : forall a b: int. divides (gcd a b) b
  axiom gcd_def3  :
    forall a b x: int. divides x a -> divides x b -> divides x (gcd a b)
  axiom gcd_unique:
    forall a b d: int.
    0 <= d -> divides d a -> divides d b ->
    (forall x: int. divides x a -> divides x b -> divides x d) ->
    d = gcd a b

  (* gcd is associative commutative *)

  clone algebra.AC with type t = int, function op = gcd

  lemma gcd_0_pos: forall a: int. 0 <= a -> gcd a 0 = a
  lemma gcd_0_neg: forall a: int. a <  0 -> gcd a 0 = -a

  lemma gcd_opp: forall a b: int. gcd a b = gcd (-a) b

  lemma gcd_euclid: forall a b q: int. gcd a b = gcd a (b - q * a)

  use int.ComputerDivision as CD

  lemma Gcd_computer_mod:
    forall a b: int [gcd b (CD.mod a b)].
    b <> 0 -> gcd b (CD.mod a b) = gcd a b

  use int.EuclideanDivision as ED

  lemma Gcd_euclidean_mod:
    forall a b: int [gcd b (ED.mod a b)].
    b <> 0 -> gcd b (ED.mod a b) = gcd a b

  lemma gcd_mult: forall a b c: int. 0 <= c -> gcd (c * a) (c * b) = c * gcd a b

end

(** {2 Prime numbers} *)

module Prime

  use export int.Int
  use Divisibility

  predicate prime (p: int) =
    2 <= p /\ forall n: int. 1 < n < p -> not (divides n p)

  lemma not_prime_1: not (prime 1)
  lemma prime_2    : prime 2
  lemma prime_3    : prime 3

  lemma prime_divisors:
    forall p: int. prime p ->
    forall d: int. divides d p -> d = 1 \/ d = -1 \/ d = p \/ d = -p

  lemma small_divisors:
    forall p: int. 2 <= p ->
    (forall d: int. 2 <= d -> prime d -> 1 < d*d <= p -> not (divides d p)) ->
    prime p

  use Parity

  lemma even_prime: forall p: int. prime p -> even p -> p = 2

  lemma odd_prime: forall p: int. prime p -> p >= 3 -> odd p

end

(** {2 Coprime numbers} *)

module Coprime

  use export int.Int
  use Divisibility
  use Gcd

  predicate coprime (a b: int) = gcd a b = 1

  use Prime

  lemma prime_coprime:
    forall p: int.
    prime p <-> 2 <= p && forall n:int. 1 <= n < p -> coprime n p

  lemma Gauss:
    forall a b c:int. divides a (b*c) /\ coprime a b -> divides a c

  lemma Euclid:
    forall p a b:int.
      prime p /\ divides p (a*b) -> divides p a \/ divides p b

  lemma gcd_coprime:
    forall a b c. coprime a b -> gcd a (b*c) = gcd a c

end