/* Author: Yihao Yan See challenge 2 of: http://etaps2015.verifythis.org/challenges ----------------- Problem description: Various parallel GCD algorithms exist. In this challenge, we consider a simple Euclid-like algorithm with two parallel threads. One thread subtracts in one direction, the other thread subtracts in the other direction, and eventually this procedure converges on GCD. Verification tasks ------------------ Specify and verify the following behaviour of this parallel GCD algorithm: Input: two positive integers a and b Output: a positive number that is the greatest common divisor of a and b ----------------- Result: For any numbers A less than 5 and B less than 7, myGCD returns a common divisor d of them and the verification shows that there exists no common divisor of A and B that is greater than d. Therefore, myGCD behaves correctly. ----------------- command: civl verify parallelGCD.c */ #include #include $input int A_BOUND=4; $input int B_BOUND=6; $input int A; $input int B; $assume (A>0 && B>0 && Ab){ int t1 = b; int t2 = a-t1; a = t2; } } } void worker2() { while(a != b) { if(b>a) { int t1 = a; int t2 = b-t1; b = t2; } } } proc_a= $spawn worker1(); proc_b= $spawn worker2(); $wait(proc_a); $wait(proc_b); return a; } int seqGCD(int a, int b) { while(a != b) { if(a > b) a = a-b; if(b > a) b = b-a; } return a; } void main() { int result1 = myGCD(A, B); int minAB = A < B ? A : B; $assert($forall (int i: (result1+1) .. (minAB)) (A%i != 0 || B%i != 0)); $assert(A%result1 == 0 && B%result1 == 0); }