We Trusted What We Proved! Greatest Common Divisors: Theorem, Proof and Algorithm in PowerEpsilon Ming-Yuan Zhu CoreTek Systems, Inc. 11 th Floor, 1109, CEC Building 6 South Zhongguancun Street Beijing 100086 People s Republic of China Abstract In this paper, we present a formal development of greatest common divisor algorithm with the mechanical proof development system PowerEpsilon. 1 Introduction In this paper, we present a proof development system called PowerEpsilon [11, 12], based on a constructive type theory which can be used as a formal system for actually proof development 1. PowerEpsilon, currently developed and maintained by author, is a strongly-typed polymorphic functional programming language based on Martin-Löf s type theory [8, 6, 7] and the calculus of constructions [4]. In PowerEpsilon, the concept of limit of type universe hierarchies (Kind) and a scheme for inductive define types are introduced. The system can be used as both a programming language with a very rich set of data structures and a metalanguage for formalizing constructive mathematics. The system has been implemented using the software development system AUTOSTAR constructed by author [10]. PowerEpsilon is a proof checker much similar to other mechanical proof checkers, such as COQ [1], HOL[5], Isabelle[9] and Nuprl [2], which are completely formal user-controlled systems. The aim of this paper is to derive a algorithm for computing the greatest common divisors of two given natural numbers using PowerEpsilon. 1.1 The Algorithm for Greatest Common Divisor - Euclid 1.1.1 Euclid Algorithm The Euclid algorithm for calculating the greatest common divisor was established based on the following theorem. Theorem 1.1 GCD(a, b) = GCD(b, a mod b). The proof is outlined as follows: a can be represented as a = kb + rthen we have r = a mod b Suppose that d is a common divisor of a and b, then d a, d b, since r = a - kbhence d r, Therefore, d is the common divisor of (b, a mod b). Suppose that d is the common divisor of (b, a mod b), then d b, d r, but a = kb + r hence, d is also the common divisor of (a, b). Since the common divisors of (a, b) and (b, a mod b) are same, the greatest common divisor must also the same. 1 This work is supported in part by the TRUSTIE Project of Hi-Tech Research and Development Program of China (863 Program) under Grant No. 2007AA010304, by the Open Fund of the State Key Laboratory of Software Development Environment under Grant No. SKLSDE-2010KF-0X, Beijing University of Aeronautics and Astronautics, and by the National Basic Research Program of China (973 Program) under Grant No. 2005CB321901 1
2 Statement Theorem 2.1 a, b N. d N. @(Is GCD, a, b, d). dec GCDThm2 : @(Is_GCD, a, b, d); What we need actually is the following theorem: Theorem 2.2 f N N N. a, b N. @(Is GCD, a, b, @(f, a, b)). dec GCDThm3 :?(f : [Nat -> Nat -> Nat]) @(Is_GCD, a, b, @(f, a, b)); 3 Definitions 3.1 Divisibility dec Dividable : [Nat -> Nat -> Type(0)]; def Dividable = \(n1 : Nat, n2 : Nat)?(m : Nat) let n = @(TIMES, n2, m) in @(Equal, Nat, n1, n); dec DivideReflLem : @(Dividable, a, a); dec DivideReflProp : let n = @(TIMES, a, II) in @(Equal, Nat, a, n); def DivideReflLem = \(a : Nat) let m = II in <m, @(DivideReflProp, a)>; dec OneDivideLem : @(Dividable, a, II); dec ZeroDivideLem : @(Dividable, OO, a); dec DivideLELem :!(a : Nat, m : Nat) [@(Dividable, a, m) -> @(NLe, m, a)]; 2
dec MultDivideLem :!(k : Nat, a : Nat, d : Nat) [@(Dividable, a, d) -> @(Dividable, @(TIMES, k, a), @(TIMES, k, d))]; 3.2 Common Divisors def CDCond = \(n1 : Nat, n2 : Nat, cd : Nat) @(And, @(Dividable, n1, cd), @(Dividable, n2, cd)); 3.3 Greatest Common Divisors def GCDCond = \(n1 : Nat, n2 : Nat, gcd : Nat) @(And, @(CDCond, n1, n2, gcd),!(m : Nat) [@(CDCond, n1, n2, m) -> @(NLe, m, gcd)]); dec Is_GCD : [Nat -> Nat -> Nat -> Prop]; def Is_GCD = GCDCond; 4 Proof 4.1 Trivial Properties of GCDCond 4.1.1 Reflexivity dec IsGCDRefLem : @(Is_GCD, a, a, a); dec IsGCDRefLem1 : @(CDCond, a, a, a); def IsGCDRefLem1 = \(a : Nat) let P = @(Dividable, a, a) in let p = @(DivideReflLem, a) in @(ANDS, P, P, p, p); dec IsGCDRefLem2 :!(m : Nat) [@(CDCond, a, a, m) -> @(NLe, m, a)]; 3
def IsGCDRefLem = \(a : Nat) let A1 = @(CDCond, a, a, a), A2 =!(m : Nat) [@(CDCond, a, a, m) -> @(NLe, m, a)] in let a1 = @(IsGCDRefLem1, a), a2 = @(IsGCDRefLem2, a) in @(ANDS, A1, A2, a1, a2); 4.2 Symmetry dec IsGCDSymLem :!(a : Nat, b : Nat, d : Nat) [@(Is_GCD, a, b, d) -> @(Is_GCD, b, a, d)]; dec IsGCDSymLem1 :!(a : Nat, b : Nat, d : Nat) [@(CDCond, a, b, d) -> @(CDCond, b, a, d)]; dec IsGCDSymLem2 :!(a : Nat, b : Nat, d : Nat) [!(m : Nat) [@(CDCond, a, b, m) -> @(NLe, m, d)] ->!(m : Nat) [@(CDCond, b, a, m) -> @(NLe, m, d)]]; def IsGCDSymLem = \(a : Nat, b : Nat, d : Nat) \(p : @(Is_GCD, a, b, d)) let P1 = @(CDCond, a, b, d), P2 =!(m : Nat) [@(CDCond, a, b, m) -> @(NLe, m, d)] in let p1 = @(PJ1, P1, P2, p), p2 = @(PJ2, P1, P2, p) in let Q1 = @(CDCond, b, a, d), Q2 =!(m : Nat) [@(CDCond, b, a, m) -> @(NLe, m, d)] in let q1 = @(IsGCDSymLem1, a, b, d, p1), q2 = @(IsGCDSymLem2, a, b, d, p2) in @(ANDS, Q1, Q2, q1, q2); 4.3 Zero Property dec IsGCDZeroLem : @(Is_GCD, a, OO, a); dec IsGCDZeroLem1 : @(CDCond, a, OO, a); def IsGCDZeroLem1 = \(a : Nat) let P1 = @(Dividable, a, a), P2 = @(Dividable, OO, a) in let p1 = @(DivideReflLem, a), 4
p2 = @(ZeroDivideLem, a) in @(ANDS, P1, P2, p1, p2); dec IsGCDZeroLem2 :!(m : Nat) [@(CDCond, a, OO, m) -> @(NLe, m, a)]; def IsGCDZeroLem = \(a : Nat) let P1 = @(CDCond, a, OO, a), P2 =!(m : Nat) [@(CDCond, a, OO, m) -> @(NLe, m, a)] in let p1 = @(IsGCDZeroLem1, a), p2 = @(IsGCDZeroLem2, a) in @(ANDS, P1, P2, p1, p2); dec IsGCDZeroLemm : @(Is_GCD, OO, a, a); 4.4 Equality dec IsGCDEqLem : @(Is_GCD, a, a, a); 4.5 Theorem of CDCond dec CDLem2 :!(d : Nat) [@(Dividable, a, d) -> @(Dividable, b, d) -> @(Dividable, @(MOD, a, b), d)]; dec CDLem20 :!(d : Nat) [@(CDCond, a, b, d) -> @(CDCond, b, @(MOD, a, b), d)]; def CDLem20 = \(d : Nat) \(p : @(CDCond, a, b, d)) let P1 = @(Dividable, a, d), P2 = @(Dividable, b, d) in let p1 = @(PJ1, P1, P2, p), p2 = @(PJ2, P1, P2, p) in let q = @(CDLem2, a, b, d, p1, p2) in let Q = @(Dividable, @(MOD, a, b), d) in @(ANDS, P2, Q, p2, q); dec CDLem3 : 5
!(d : Nat) [@(Dividable, b, d) -> @(Dividable, @(MOD, a, b), d) -> @(Dividable, a, d)]; dec CDLem30 :!(d : Nat) [@(CDCond, b, @(MOD, a, b), d) -> @(CDCond, a, b, d)]; def CDLem30 = \(d : Nat) \(p : @(CDCond, b, @(MOD, a, b), d)) let P1 = @(Dividable, b, d), P2 = @(Dividable, @(MOD, a, b), d) in let p1 = @(PJ1, P1, P2, p), p2 = @(PJ2, P1, P2, p) in let q = @(CDLem3, a, b, d, p1, p2) in let Q = @(Dividable, a, d) in @(ANDS, Q, P1, q, p1); 4.6 Theorem and Proof of GCDThmm dec GCDThmm :!(a : Nat, b : Nat, d : Nat) [@(GCDCond, b, @(MOD, a, b), d) -> @(GCDCond, a, b, d)]; def GCDThmm = \(a : Nat, b : Nat, d : Nat, q : @(GCDCond, b, @(MOD, a, b), d)) let Q1 = @(CDCond, b, @(MOD, a, b), d), Q2 =!(m : Nat) [@(CDCond, b, @(MOD, a, b), m) -> @(NLe, m, d)] in let q1 = @(PJ1, Q1, Q2, q), q2 = @(PJ2, Q1, Q2, q) in let P1 = @(CDCond, a, b, d), P2 =!(m : Nat) [@(CDCond, a, b, m) -> @(NLe, m, d)] in let p1 = @(CDLem30, a, b, d, q1), p2 = \(m : Nat, w : @(CDCond, a, b, m)) let u = @(CDLem20, a, b, m, w) in @(q2, m, u) in @(ANDS, P1, P2, p1, p2); 4.7 Proof of GCDThm2 def MkGCDCond = \(a : Nat, b : Nat, d : Nat, p : @(GCDCond, a, b, d)) <d, p>; dec GCDThm21 : 6
[@(Equal, Nat, b, OO) -> @(GCDCond, a, b, d)]; def GCDThm21 = \(p : @(Equal, Nat, b, OO)) let d = a, q = @(IsGCDZeroLem, a) in let r = @(Symm_Eq, Nat, b, OO, p) in let P = \(x : Nat) @(GCDCond, a, x, d) in @(MkGCDCond, a, b, d, @(r, P, q)); dec GCDThm22 : [@(Equal, Nat, a, OO) -> @(GCDCond, a, b, d)]; def GCDThm22 = \(p : @(Equal, Nat, a, OO)) let d = b, q = @(IsGCDZeroLemm, b) in let r = @(Symm_Eq, Nat, a, OO, p) in let P = \(x : Nat) @(GCDCond, x, b, d) in @(MkGCDCond, a, b, d, @(r, P, q)); dec GCDThm23 : [@(NGe, a, b) -> @(GCDCond, b, @(MOD, a, b), d) -> @(GCDCond, a, b, d)]; def GCDThm23 = \(a : Nat, b : Nat, w : @(NGe, a, b)) \(p : @(GCDCond, b, @(MOD, a, b), d)) let d = @(FST, p), q = @(SND, p) in @(MkGCDCond, a, b, d, @(GCDThmm, a, b, d, q)); dec GCDThm24 : [@(NLs, a, b) -> @(GCDCond, b, a, d) -> @(GCDCond, a, b, d)]; def GCDThm24 = \(a : Nat, b : Nat, w : @(NLs, a, b)) \(p : @(GCDCond, b, a, d)) let d = @(FST, p), q = @(SND, p) in @(MkGCDCond, a, b, d, @(IsGCDSymLem, b, a, d, q)); dec GCDInduct : [[@(Equal, Nat, a, OO) -> @(GCDCond, a, b, d)] -> 7
[@(Equal, Nat, b, OO) -> @(GCDCond, a, b, d)] -> [@(NLs, a, b) -> @(GCDCond, b, a, d) -> @(GCDCond, a, b, d)] -> [@(NGe, a, b) -> @(GCDCond, b, @(MOD, a, b), d) -> @(GCDCond, a, b, d)] -> @(GCDCond, a, b, d)]; 4.8 Proofs of GCDThm2 and GCDThm3 4.8.1 Proof of GCDThm2 def GCDThm2 = @(GCDInduct, a, b, @(GCDThm22, a, b), @(GCDThm21, a, b), @(GCDThm24, a, b), @(GCDThm23, a, b)); 4.8.2 Lemma of Choice dec ChoiceLem2 :!(A : Prop, B : Prop, C : Prop)!(P : [A -> B -> C -> Type(0)]) [!(x : A, y : B)?(z : C) @(P, x, y, z) ->?(f : [A -> B -> C])!(x : A, y : B) @(P, x, y, @(f, x, y))]; def ChoiceLem2 = \(A : Prop, B : Prop, C : Prop) \(P : [A -> B -> C -> Type(0)]) \(l :!(x : A, y : B)?(z : C) @(P, x, y, z)) let f = \(x : A, y : B) @(FST, @(l, x, y)) in let p = \(x : A, y : B, a : @(P, x, y, @(f, x, y))) a in let q = \(x : A, y : B) @(p, x, y, @(SND, @(l, x, y))) in <f, q>; 4.8.3 Proof of GCDThm3 def GCDThm3 = @(ChoiceLem2, Nat, Nat, Nat, GCDCond, GCDThm2); 4.9 Algorithm Derived dec GCD : [Nat -> Nat -> Nat]; def GCD = 8
Nat, @(IS_ZERO, a), b, Nat, @(IS_ZERO, b), a, Nat, @(LESS, a, b), @(GCD, b, a), @(GCD, b, @(MOD, a, b))))); The Euclid algorithm was derived from this theorem, the algorithm represented in C++ is described as follows: void swap(int &a, int &b) { int c = a; a = b; b = c; } int gcd(int a, int b) { if (0 == a) { return b; } if (0 == b) { return a; } if (a > b) { swap(a, b); } int c; for (c = a mon b; c > 0; c = a mod b) { a = b; b = c; } return b; } 5 Proof of Binary Algorithm 5.1 Binary GCD algorithm The binary GCD algorithm, also known as Stein s algorithm[3], is an algorithm that computes the greatest common divisor of two nonnegative integers. It gains a measure of efficiency over the ancient Euclidean algorithm by replacing divisions and multiplications with shifts, which are cheaper when operating on the binary representation used by modern computers. This is particularly critical on embedded platforms that have no direct processor support for division. Although the algorithm was first published by the Israeli physicist and programmer Josef Stein in 1967, it may have been known in first-century China. 9
5.2 Informal Description of Algorithm The algorithm reduces the problem of finding the GCD by repeatedly applying these identities: 1. GCD(0, v) = v, because everything divides zero, and v is the largest number that divides v. Similarly, GCD(u, 0) = u. GCD(0, 0) is not typically defined, but it is convenient to set GCD(0, 0) = 0. 2. If u and v are both even, then GCD(u, v) = 2 GCD(u/2, v/2), because 2 is a common divisor. 3. If u is even and v is odd, then GCD(u, v) = GCD(u/2, v), because 2 is not a common divisor. Similarly, if u is odd and v is even, then GCD(u, v) = GCD(u, v/2). 4. If u and v are both odd, and u v, then GCD(u, v) = GCD((u - v)/2, v). If both are odd and u < v, then GCD(u, v) = GCD((v - u)/2, u). These are combinations of one step of the simple Euclidean algorithm, which uses subtraction at each step, and an application of step 3 above. The division by 2 results in an integer because the difference of two odd numbers is even. 5. Repeat steps 3C4 until u = v, or (one more step) until u = 0. In either case, the GCD is 2kv, where k is the number of common factors of 2 found in step 2. Since this definition is tail-recursive, a loop can be used to replace the recursion. The algorithm requires O((log2 uv)2) worst-case time, or in other words time proportional to the square of the number of bits in u and v together. Although each step reduces at least one of the operands by at least a factor of 2, the subtract and shift operations do not take constant time for very large integers (although they re still quite fast in practice, requiring about one operation per word of the representation). 5.3 Definitions def IsEven = \(a : Nat)?(a2 : Nat) @(Equal, Nat, a, @(TIMES, I2, a2)); def IsOdd = \(a : Nat)?(a2 : Nat) @(Equal, Nat, a, @(SS, @(TIMES, I2, a2))); 5.4 Theorem for Stein Algorithm 5.4.1 Theorem SteinGCDThm0 Theorem 5.1 a N. @(GCDCond, a, a, a). dec SteinGCDThm0 : @(GCDCond, a, a, a); def SteinGCDThm0 = \(a : Nat) @(IsGCDRefLem, a); Theorem 5.2 k, a, b, d N. @(GCDCond, a, b, d) @(GCDCond, k a, k b, k d). 10
5.4.2 Theorem SteinGCDThm1 dec SteinGCDThm1 :!(k : Nat, a : Nat, b : Nat, d : Nat) [@(GCDCond, a, b, d) -> @(GCDCond, @(TIMES, k, a), @(TIMES, k, b), @(TIMES, k, d))]; 5.4.2.1 Lemma SteinGCDLem11 Lemma 5.1 k, a, b, d N. @(CDCond, a, b, d) @(CDCond, k a, k b, k d). dec SteinGCDLem11 :!(k : Nat, a : Nat, b : Nat, d : Nat) [@(CDCond, a, b, d) -> @(CDCond, @(TIMES, k, a), @(TIMES, k, b), @(TIMES, k, d))]; def SteinGCDLem11 = \(k : Nat, a : Nat, b : Nat, d : Nat) \(p : @(CDCond, a, b, d)) let P1 = @(Dividable, a, d), P2 = @(Dividable, b, d) in let p1 = @(PJ1, P1, P2, p), p2 = @(PJ2, P1, P2, p) in let Q1 = @(Dividable, @(TIMES, k, a), @(TIMES, k, d)), Q2 = @(Dividable, @(TIMES, k, b), @(TIMES, k, d)) in let q1 = @(MultDivideLem, k, a, d, p1), q2 = @(MultDivideLem, k, b, d, p2) in @(ANDS, Q1, Q2, q1, q2); 5.4.2.2 Lemma SteinGCDLem12 Lemma 5.2 k, a, b, d N. ( m N. @(CDCond, a, b, m) m d) ( m N. @(CDCond, k a, k b, m) m k d). dec SteinGCDLem12 :!(k : Nat, a : Nat, b : Nat, d : Nat) [!(m : Nat) [@(CDCond, a, b, m) -> @(NLe, m, d)] ->!(m : Nat) [@(CDCond, @(TIMES, k, a), @(TIMES, k, b), m) -> @(NLe, m, @(TIMES, k, d))]]; dec MultiDivideLem :!(k : Nat, a : Nat, b : Nat, km : Nat) [@(Dividable, @(TIMES, k, a), km) -> @(Dividable, @(TIMES, k, b), km) ->?(n : Nat, m : Nat) @(And, @(Equal, Nat, km, @(TIMES, n, m)), @(And, @(Dividable, k, n), @(CDCond, a, b, m)))]; dec NatTimeLELem :!(a : Nat, b : Nat, c : Nat, d : Nat) [@(NLe, a, c) -> @(NLe, b, d) -> 11
@(NLe, @(TIMES, a, b), @(TIMES, c, d))]; dec NLeEqTranLem :!(a : Nat, b : Nat, c : Nat) [@(Equal, Nat, a, b) -> @(NLe, b, c) -> @(NLe, a, c)]; def NLeEqTranLem = \(a : Nat, b : Nat, c : Nat) \(p1 : @(Equal, Nat, a, b), p2 : @(NLe, b, c)) let P = \(x : Nat) @(NLe, x, c) in let q = @(Symm_Eq, Nat, a, b, p1) in @(q, P, p2); def SteinGCDLem12 = \(k : Nat, a : Nat, b : Nat, d : Nat) \(p :!(m : Nat) [@(CDCond, a, b, m) -> @(NLe, m, d)]) \(km : Nat) \(q : @(CDCond, @(TIMES, k, a), @(TIMES, k, b), km)) let Q1 = @(Dividable, @(TIMES, k, a), km), Q2 = @(Dividable, @(TIMES, k, b), km) in let q1 = @(PJ1, Q1, Q2, q), q2 = @(PJ2, Q1, Q2, q) in let r = @(MultiDivideLem, k, a, b, km, q1, q2) in let kk = @(FST, r), mm = @(FST, @(SND, r)), rr = @(SND, @(SND, r)) in let R1 = @(Equal, Nat, km, @(TIMES, kk, mm)), R2 = @(Dividable, k, kk), R3 = @(CDCond, a, b, mm) in let r1 = @(PJ1, R1, @(And, R2, R3), rr), r2 = @(PJ1, R2, R3, @(PJ2, R1, @(And, R2, R3), rr)), r3 = @(PJ2, R2, R3, @(PJ2, R1, @(And, R2, R3), rr)) in let u1 = @(p, mm, r3), u2 = @(DivideLELem, k, kk, r2), u3 = @(NatTimeLELem, kk, mm, k, d, u2, u1) in @(NLeEqTranLem, km, @(TIMES, kk, mm), @(TIMES, k, d), r1, u3); 5.4.2.3 Proof of SteinGCDThm1 def SteinGCDThm1 = \(k : Nat, a : Nat, b : Nat, d : Nat) \(p : @(GCDCond, a, b, d)) let ka = @(TIMES, k, a), kb = @(TIMES, k, b), kd = @(TIMES, k, d) in let P1 = @(CDCond, a, b, d), P2 =!(m : Nat) [@(CDCond, a, b, m) -> @(NLe, m, d)] in let p1 = @(PJ1, P1, P2, p), p2 = @(PJ2, P1, P2, p) in let Q1 = @(CDCond, ka, kb, kd), Q2 =!(m : Nat) [@(CDCond, ka, kb, m) -> @(NLe, m, kd)] in let q1 = @(SteinGCDLem11, k, a, b, d, p1), q2 = @(SteinGCDLem12, k, a, b, d, p2) in @(ANDS, Q1, Q2, q1, q2); 12
5.5 Proofs Theorem 5.3 a, b N. b = 0 d N. @(GCDCond, a, b, d). dec GCDThm21 : [@(Equal, Nat, b, OO) -> @(GCDCond, a, b, d)]; def GCDThm21 = \(p : @(Equal, Nat, b, OO)) let d = a, q = @(IsGCDZeroLem, a) in let r = @(Symm_Eq, Nat, b, OO, p) in let P = \(x : Nat) @(GCDCond, a, x, d) in @(MkGCDCond, a, b, d, @(r, P, q)); Theorem 5.4 a, b N. a = 0 d N. @(GCDCond, a, b, d). dec GCDThm22 : [@(Equal, Nat, a, OO) -> @(GCDCond, a, b, d)]; def GCDThm22 = \(p : @(Equal, Nat, a, OO)) let d = b, q = @(IsGCDZeroLemm, b) in let r = @(Symm_Eq, Nat, a, OO, p) in let P = \(x : Nat) @(GCDCond, x, b, d) in @(MkGCDCond, a, b, d, @(r, P, q)); Theorem 5.5 a, b N. a = b d N. @(GCDCond, a, b, d). dec GCDThm23 : [@(Equal, Nat, a, b) -> @(GCDCond, a, b, d)]; def GCDThm23 = \(p : @(Equal, Nat, a, b)) let d = a, q = @(IsGCDEqLem, a) in let P = \(x : Nat) @(GCDCond, a, x, d) in @(MkGCDCond, a, b, d, @(p, P, q)); Theorem 5.6 a, b N. @(IsEven, a) @(IsEven, b) d N. @(GCDCond, a/2, b/2, d) d N. @(GCDCond, a, b, d). dec GCDThm24 : [@(IsEven, a) -> 13
@(IsEven, b) -> let a2 = @(DIV, a, I2), b2 = @(DIV, b, I2) in @(GCDCond, a2, b2, d) -> @(GCDCond, a, b, d)]; dec GCDLem24 :!(a : Nat, b : Nat, d : Nat) [@(IsEven, a) -> @(IsEven, b) -> let a2 = @(DIV, a, I2), b2 = @(DIV, b, I2) in [@(GCDCond, a2, b2, d) -> let dd = @(TIMES, I2, d) in @(GCDCond, a, b, dd)]]; dec Time2Div2EqLem : @(Equal, Nat, @(TIMES, I2, @(DIV, a, I2)), a); def GCDLem24 = \(a : Nat, b : Nat, d : Nat) \(p1 : @(IsEven, a), p2 : @(IsEven, b)) let a2 = @(DIV, a, I2), b2 = @(DIV, b, I2) in \(p3 : @(GCDCond, a2, b2, d)) let P = \(x : Nat) @(GCDCond, x, @(TIMES, I2, b2), @(TIMES, I2, d)), Q = \(x : Nat) @(GCDCond, a, x, @(TIMES, I2, d)) in let q1 = @(SteinGCDThm1, I2, a2, b2, d, p3), q2 = @(Time2Div2EqLem, a, P, q1) in @(Time2Div2EqLem, b, Q, q2); def GCDThm24 = \(p1 : @(IsEven, a), p2 : @(IsEven, b)) let a2 = @(DIV, a, I2), b2 = @(DIV, b, I2) in \(p3 : @(GCDCond, a2, b2, d)) let d = @(FST, p3), q = @(SND, p3) in let dd = @(TIMES, I2, d), qq = @(GCDLem24, a, b, d, p1, p2, q) in @(MkGCDCond, a, b, dd, qq); Theorem 5.7 a, b N. @(IsEven, a) @(IsOdd, b) d N. @(GCDCond, a/2, b, d) d N. @(GCDCond, a, b, d). dec GCDThm25 : [@(IsEven, a) -> @(IsOdd, b) -> 14
let a2 = @(DIV, a, I2) in @(GCDCond, a2, b, d) -> @(GCDCond, a, b, d)]; dec GCDLem251 :!(a : Nat, b : Nat, d : Nat) [@(IsEven, a) -> @(IsOdd, b) -> let a2 = @(DIV, a, I2) in [@(CDCond, a2, b, d) -> @(CDCond, a, b, d)]]; dec GCDLem252 :!(a : Nat, b : Nat, d : Nat) [@(IsEven, a) -> @(IsOdd, b) -> let a2 = @(DIV, a, I2) in [!(m : Nat) [@(CDCond, a2, b, m) -> @(NLe, m, d)] ->!(m : Nat) [@(CDCond, a, b, m) -> @(NLe, m, d)]]]; def GCDThm25 = \(p1 : @(IsEven, a), p2 : @(IsOdd, b)) let a2 = @(DIV, a, I2) in \(p3 : @(GCDCond, a2, b, d)) let d = @(FST, p3), q = @(SND, p3) in let Q1 = @(CDCond, a2, b, d), Q2 =!(m : Nat) [@(CDCond, a2, b, m) -> @(NLe, m, d)] in let q1 = @(PJ1, Q1, Q2, q), q2 = @(PJ2, Q1, Q2, q) in let R1 = @(CDCond, a, b, d), R2 =!(m : Nat) [@(CDCond, a, b, m) -> @(NLe, m, d)] in let r1 = @(GCDLem251, a, b, d, p1, p2, q1), r2 = @(GCDLem252, a, b, d, p1, p2, q2) in let r = @(ANDS, R1, R2, r1, r2) in @(MkGCDCond, a, b, d, r); Theorem 5.8 a, b N. @(IsOdd, a) @(IsEven, b) d N. @(GCDCond, a, b/2, d) d N. @(GCDCond, a, b, d). dec GCDThm26 : [@(IsOdd, a) -> @(IsEven, b) -> let b2 = @(DIV, b, I2) in @(GCDCond, a, b2, d) -> @(GCDCond, a, b, d)]; def GCDThm26 = \(p1 : @(IsOdd, a), 15
p2 : @(IsEven, b)) let b2 = @(DIV, b, I2) in \(p3 : @(GCDCond, a, b2, d)) let d = @(FST, p3), q = @(SND, p3) in let q1 = @(IsGCDSymLem, a, b2, d, q), q2 = @(MkGCDCond, b2, a, d, q1), q3 = @(GCDThm25, b, a, p2, p1, q2) in let dd = @(FST, q3), qq = @(SND, q3) in @(MkGCDCond, a, b, dd, @(IsGCDSymLem, b, a, dd, qq)); Theorem 5.9 a, b N. @(IsOdd, a) @(IsOdd, b) a b d N. @(GCDCond, (a b)/2, b, d) d N. @(GCDCond, a, b, d). dec GCDThm27 : [@(IsOdd, a) -> @(IsOdd, b) -> @(NGe, a, b) -> let amb = @(DIV, @(MINUS, a, b), I2) in @(GCDCond, amb, b, d) -> @(GCDCond, a, b, d)]; dec OddMinusEvenLem : [@(IsOdd, a) -> @(IsOdd, b) -> @(NGe, a, b) -> let amb = @(MINUS, a, b) in @(IsEven, amb)]; dec GCDMinusLem :!(a : Nat, b : Nat, d : Nat) [@(NGe, a, b) -> let amb = @(MINUS, a, b) in [@(GCDCond, amb, b, d) -> @(GCDCond, a, b, d)]]; def GCDThm27 = \(p1 : @(IsOdd, a), p2 : @(IsOdd, b), p3 : @(NGe, a, b)) let amb = @(DIV, @(MINUS, a, b), I2) in \(p4 : @(GCDCond, amb, b, d)) let q1 = @(OddMinusEvenLem, a, b, p1, p2, p3), q2 = @(GCDThm25, @(MINUS, a, b), b, q1, p2, p4) in let d = @(FST, q2), q = @(SND, q2) in let q3 = @(GCDMinusLem, a, b, d, p3, q) in @(MkGCDCond, a, b, d, q3); 16
Theorem 5.10 a, b N. @(IsOdd, a) @(IsOdd, b) b a d N. @(GCDCond, a, (b a)/2, d) d N. @(GCDCond, a, b, d). dec GCDThm28 : [@(IsOdd, a) -> @(IsOdd, b) -> @(NGe, b, a) -> let bma = @(DIV, @(MINUS, b, a), I2) in @(GCDCond, a, bma, d) -> @(GCDCond, a, b, d)]; def GCDThm28 = \(p1 : @(IsOdd, a), p2 : @(IsOdd, b), p3 : @(NGe, b, a)) let bma = @(DIV, @(MINUS, b, a), I2) in \(p4 : @(GCDCond, a, bma, d)) let d = @(FST, p4), q = @(SND, p4) in let q1 = @(IsGCDSymLem, a, bma, d, q), q2 = @(MkGCDCond, bma, a, d, q1), q3 = @(GCDThm27, b, a, p2, p1, p3, q2) in let dd = @(FST, q3), qq = @(SND, q3) in @(MkGCDCond, a, b, dd, @(IsGCDSymLem, b, a, dd, qq)); dec GCDInduct : [[@(Equal, Nat, a, OO) -> @(GCDCond, a, b, d)] -> [@(Equal, Nat, b, OO) -> @(GCDCond, a, b, d)] -> [@(Equal, Nat, a, b) -> @(GCDCond, a, b, d)] -> [@(IsEven, a) -> @(IsEven, b) -> let a2 = @(DIV, a, I2), b2 = @(DIV, b, I2) in @(GCDCond, a2, b2, d) -> @(GCDCond, a, b, d)] -> [@(IsEven, a) -> @(IsOdd, b) -> let a2 = @(DIV, a, I2) in @(GCDCond, a2, b, d) -> @(GCDCond, a, b, d)] -> [@(IsOdd, a) -> @(IsEven, b) -> let b2 = @(DIV, b, I2) in @(GCDCond, a, b2, d) -> @(GCDCond, a, b, d)] -> 17
[@(IsOdd, a) -> @(IsOdd, b) -> @(NGe, a, b) -> let amb = @(DIV, @(MINUS, a, b), I2) in @(GCDCond, amb, b, d) -> @(GCDCond, a, b, d)] -> [@(IsOdd, a) -> @(IsOdd, b) -> @(NGe, b, a) -> let bma = @(DIV, @(MINUS, b, a), I2) in @(GCDCond, a, bma, d) -> @(GCDCond, a, b, d)] -> @(GCDCond, a, b, d)]; def GCDThm2 = @(GCDInduct, a, b, @(GCDThm22, a, b), @(GCDThm21, a, b), @(GCDThm23, a, b), @(GCDThm24, a, b), @(GCDThm25, a, b), @(GCDThm26, a, b), @(GCDThm27, a, b), @(GCDThm28, a, b)); def GCDThm3 = @(ChoiceLem2, Nat, Nat, Nat, GCDCond, GCDThm2); 5.6 Algorithm Derived dec GCD : [Nat -> Nat -> Nat]; def GCD = Nat, @(IS_ZERO, a), b, Nat, @(IS_ZERO, b), a, Nat, @(EQUAL, a, b), a, Nat, 18
@(AND, @(IS_EVEN, a), @(IS_EVEN, b)), let a2 = @(DIV, a, I2), b2 = @(DIV, b, I2) in @(GCD, a2, b2), Nat, @(AND, @(IS_EVEN, a), @(IS_ODD, b)), let a2 = @(DIV, a, I2) in @(GCD, a2, b), Nat, @(AND, @(IS_ODD, a), @(IS_EVEN, b)), let b2 = @(DIV, b, I2) in @(GCD, a, b2), Nat, @(AND, @(AND, @(IS_ODD, a), @(IS_ODD, b)), @(NGE, a, b)), let amb = @(DIV, @(MINUS, a, b), I2) in @(GCD, amb, b), Nat, @(AND, @(AND, @(IS_ODD, a), @(IS_ODD, b)), @(NGE, b, a)), let bma = @(DIV, @(MINUS, b, a), I2) in @(GCD, a, bma), ERR_NAT)))))))); 5.7 Implementation in C Following is an implementation of the algorithm in C, taking two (non-negative) integer arguments u and v. It first removes all common factors of 2 using identity 2, then computes the GCD of the remaining numbers using identities 3 and 4, and combines these to form the final answer. typedef unsigned long long uint64; uint64 gcd(uint64 u, uint64 v) { int shift; /* GCD(0, x) := x */ if (u == 0 v == 0) return u v; /* Let shift := lg K, where K is the greatest power of 2 dividing both u and v. */ for (shift = 0; ((u v) & 1) == 0; ++shift) { u >>= 1; v >>= 1; } while ((u & 1) == 0) u >>= 1; /* From here on, u is always odd. */ do 19
{ while ((v & 1) == 0) /* Loop X */ v >>= 1; /* Now u and v are both odd, so diff(u, v) is even. Let u = min(u, v), v = diff(u, v)/2. */ if (u < v) { v -= u; } else { uint64 diff = u - v; u = v; v = diff; } v >>= 1; } while (v!= 0); } return u << shift; References [1] Yves Bettot and Pierre Castéran. Interactive Theorem Proving and Program Development. Springer-Verlag, 2004. [2] R. L. Constable and et al. Implementing Mathematics with the Nuprl Proof Development System. Prentice-Hall Inc., Englewood Cliffs, New Jersey, 1986. [3] Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. Introduction to Algorithms. MIT Press and McGraw-Hill, second edition, 2001. [4] J.-Y. Girard. Proofs and Types. Cambridge University Press, Cambridge, UK, 1989. [5] Michael J. C. Gordon and Thomas F. Melham. Introduction to HOL: a theorem proving environment for higher order logic. Cambridge University Press, 1993. [6] P. Martin-Löf. An intuitionistic theory of types: Predicative part. In Proceedings of Logic Colloquium 1973. North- Holland, 1973. [7] P. Martin-Löf. Constructive mathematics and computer programming. In Proceedings of Six International Congress for Logic, Methodology, and Philosophy of Science, Amsterdam, 1982. North-Holland. [8] P. Martin-Löf. Intuitionistic Type Theory. Studies in Proof Theory, Vol. 1. Bibliopolis, Naples, 1984. [9] L. C. Paulson. A foundation of the simple theory of types for Isabelle. In P. Martin-Löf and G. Mints, editors, COLOG-88, LNCS 417. International Conference on Computer Logic, Springer-Verlag, 1988. [10] M.-Y. Zhu. AUTOSTAR - a software development system. ACM SIGPLAN Notices, 23(3), 1989. [11] M.-Y. Zhu and C.-W. Wang. A higher-order lambda calculus: PowerEpsilon. Technical report, Beijing Institute of Systems Engineering, Beijing, 1991. [12] M.-Y. Zhu and C.-W. Wang. Program derivation in PowerEpsilon. In Proceedings of COMPSAC 92, Chicago, September 1992. 20