We Trusted What We Proved! Greatest Common Divisors: Theorem, Proof and Algorithm in PowerEpsilon

Similar documents
1 Elementary number theory

ELEMENTARY NUMBER THEORY AND METHODS OF PROOF

UCT Algorithm Circle: Number Theory

Lecture 1. Introduction

Integers and Mathematical Induction

CS 310 Advanced Data Structures and Algorithms

COP 4516: Math for Programming Contest Notes

SEQUENCES, MATHEMATICAL INDUCTION, AND RECURSION

Provably Correct Software

CS2 Algorithms and Data Structures Note 1

Math Introduction to Advanced Mathematics

MAT 243 Test 2 SOLUTIONS, FORM A

CS3110 Spring 2017 Lecture 6 Building on Problem Set 1

CS/COE 1501 cs.pitt.edu/~bill/1501/ More Math

COMPSCI 230 Discrete Math Prime Numbers January 24, / 15

How Efficient Can Fully Verified Functional Programs Be - A Case Study of Graph Traversal Algorithms

ABriefOverviewofAgda A Functional Language with Dependent Types

Theorem Proving Principles, Techniques, Applications Recursion

Creating a new data type

CS3110 Spring 2017 Lecture 9 Inductive proofs of specifications

Recursion. Lars-Henrik Eriksson. Functional Programming 1. Based on a presentation by Tjark Weber and notes by Sven-Olof Nyström

Programming with dependent types: passing fad or useful tool?

Introduction to Coq Proof Assistant

Euclid's Algorithm. MA/CSSE 473 Day 06. Student Questions Odd Pie Fight Euclid's algorithm (if there is time) extended Euclid's algorithm

Theorem proving. PVS theorem prover. Hoare style verification PVS. More on embeddings. What if. Abhik Roychoudhury CS 6214

Lemma (x, y, z) is a Pythagorean triple iff (y, x, z) is a Pythagorean triple.

Introduction to Sets and Logic (MATH 1190)

Assertions & Verification & Example Loop Invariants Example Exam Questions

Solutions to the Second Midterm Exam

CS3110 Spring 2017 Lecture 7 Specifications using types continued

Proposal: k-d Tree Algorithm for k-point Matching

Mathematical Induction

Lecture 10: Strongly Connected Components, Biconnected Graphs

Maximum flows & Maximum Matchings

Assertions & Verification Example Exam Questions

ELEMENTARY NUMBER THEORY AND METHODS OF PROOF

CS 157: Assignment 5

Lecture slides & distribution files:

Introduction to Programming in C Department of Computer Science and Engineering\ Lecture No. #02 Introduction: GCD

overview overview who practicalities introduction data structures and algorithms lecture 1 sorting insertion sort pseudo code merge sort

15 212: Principles of Programming. Some Notes on Induction

ELEMENTARY NUMBER THEORY AND METHODS OF PROOF

CSE 215: Foundations of Computer Science Recitation Exercises Set #4 Stony Brook University. Name: ID#: Section #: Score: / 4

Algorithm Design: GCD

CS3110 Spring 2016 Lecture 5 Modules for Rational Numbers

CSE-321 Programming Languages 2010 Midterm

Introduction to the Calculus of Inductive Definitions

Foundations of Computer Science Spring Mathematical Preliminaries

1 Elementary number theory

Scan Scheduling Specification and Analysis

SCHOOL OF ENGINEERING & BUILT ENVIRONMENT. Mathematics. Numbers & Number Systems

UNIT-II NUMBER THEORY

arxiv: v1 [cs.dm] 1 Jul 2016

Line Graphs and Circulants

Algorithmic number theory Cryptographic hardness assumptions. Table of contents

Summary of Course Coverage

CS3110 Spring 2017 Lecture 18: Binary Search Trees

Computable Euclidean Domains

CS 3410 Ch 7 Recursion

COE428 Lecture Notes Week 1 (Week of January 9, 2017)

Introduction to the Theory of Computation, Sipser, PWS, ISBN X, 1996

Mathematics. Jaehyun Park. CS 97SI Stanford University. June 29, 2015

On Meaning Preservation of a Calculus of Records

Content Development for Distance Education in Advanced University Mathematics Using Mizar

Math 302 Introduction to Proofs via Number Theory. Robert Jewett (with small modifications by B. Ćurgus)

CS3110 Spring 2017 Lecture 10 a Module for Rational Numbers

From Math to Machine A formal derivation of an executable Krivine Machine Wouter Swierstra Brouwer Seminar

A Deterministic Polynomial-time Algorithm for the Clique Problem and the Equality of P and NP Complexity Classes

CSCI2100B Data Structures Introduction

CMSC 330: Organization of Programming Languages. Lambda Calculus Encodings

Week - 01 Lecture - 03 Euclid's Algorithm for gcd. Let us continue with our running example of gcd to explore more issues involved with program.

SEQUENCES, MATHEMATICAL INDUCTION, AND RECURSION

Distributed minimum spanning tree problem

CS3110 Spring 2017 Lecture 8 Specifications continued

Constrained Types and their Expressiveness

The Cheapest Way to Obtain Solution by Graph-Search Algorithms

CMSC 330: Organization of Programming Languages

CHAPTER 8. Copyright Cengage Learning. All rights reserved.

On Jeśmanowicz Conjecture Concerning Pythagorean Triples

Transforming Programs into Recursive Functions

Modified Farey Sequences

LECTURE 16. Functional Programming

Lecture Notes on Induction and Recursion

Applied Cryptography and Network Security

CMSC 330: Organization of Programming Languages

1KOd17RMoURxjn2 CSE 20 DISCRETE MATH Fall

Computing Fundamentals 2 Introduction to CafeOBJ

Discrete Mathematics Lecture 4. Harper Langston New York University

Automata and Formal Languages - CM0081 Introduction to Agda

IS BINARY ENCODING APPROPRIATE FOR THE PROBLEM-LANGUAGE RELATIONSHIP?

Exponentiation. Evaluation of Polynomial. A Little Smarter. Horner s Rule. Chapter 5 Recursive Algorithms 2/19/2016 A 2 M = (A M ) 2 A M+N = A M A N

STRUCTURE EXITS, NOT LOOPS

Ch 3.4 The Integers and Division

COMP6700/2140 Recursive Operations

PACKING DIGRAPHS WITH DIRECTED CLOSED TRAILS

DESIGN OF A COMPOSITE ARITHMETIC UNIT FOR RATIONAL NUMBERS

Recursion and Induction: Haskell; Primitive Data Types; Writing Function Definitions

Advanced algorithms. topological ordering, minimum spanning tree, Union-Find problem. Jiří Vyskočil, Radek Mařík 2012

Using Templates to Introduce Time Efficiency Analysis in an Algorithms Course

Coq projects for type theory 2018

Transcription:

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