reserve A for preIfWhileAlgebra;
reserve A for Euclidean preIfWhileAlgebra;
reserve X for non empty countable set;
reserve T for Subset of Funcs(X, INT);
reserve f for Euclidean ExecutionFunction of A, Funcs(X, INT), T;
reserve A for Euclidean preIfWhileAlgebra,
  X for non empty countable set,
   z for (Element of X),
  s,s9 for (Element of Funcs(X, INT)),
  T for Subset of Funcs(X, INT),
  f for Euclidean ExecutionFunction of A, Funcs(X, INT), T,
  v for INT-Variable of A,f,
  t for INT-Expression of A,f;
reserve i for Integer;
reserve b for (Element of X),
  g for Euclidean ExecutionFunction of A, Funcs(X, INT), Funcs(X, INT)\(b,0);

theorem :: Correctness of Euclid algorithm
  for x,y,z being Variable of g st ex d being Function st d.b = 0 & d.x
  = 1 & d.y = 2 & d.z = 3 for s being Element of Funcs(X, INT) for n,m being
Element of NAT st n = s.x & m = s.y & n > m holds g.(s, while(y gt 0, z:=x\;z%=
  y\;x:=y\;y:=z)).x = n gcd m
proof
  set h = g;
  set S = Funcs(X, INT);
  set T = S\(b,0);
  let x,y,z be Variable of h;
  given d being Function such that
A1: d.b = 0 and
A2: d.x = 1 and
A3: d.y = 2 and
A4: d.z = 3;
  set C = y gt 0;
  set I = z:=x\;z%=y\;x:=y\;y:=z;
  let s be Element of Funcs(X, INT);
  reconsider fin = h.(s, while(C,I)) as Element of S;
  defpred Q[Element of S] means fin.x divides $1.x & fin.x divides $1.y;
A5: for s being Element of S st Q[h.(s,C) qua Element of S] holds Q[s] by A1,A2
,A3,Th38;
A6: for s being Element of S st Q[h.(h.(s,C),I) qua Element of S] & h.(s,C)
  in T holds Q[h.(s,C) qua Element of S]
  proof
    let s be Element of S;
    assume
A7: Q[h.(h.(s,C),I) qua Element of S];
    reconsider s1 = h.(s,C) as Element of S;
    reconsider s2 = h.(s1,I) as Element of S;
A8: s.y <= 0 implies s1.b = 0 by Th38;
A9: s1.x = s.x by A1,A2,Th38;
A10: s2.y = s1.x mod s1.y by A1,A2,A3,A4,Lm1;
A11: s2.x = s1.y by A1,A2,A3,A4,Lm1;
A12: s1.y = s.y by A1,A3,Th38;
    assume h.(s,C) in T;
    then s.x = (s.x div s.y)*(s2.x)+s2.y*1 by A9,A12,A8,A11,A10,Th2,NEWTON:66;
    hence thesis by A1,A2,A3,A4,A7,A9,Lm1,WSIERP_1:5;
  end;
  reconsider s1 = h.(s, C) as Element of S;
A13: s1.y = s.y by A1,A3,Th38;
A14: s.y <= 0 implies s1.b = 0 by Th38;
  let n,m be Element of NAT;
  defpred P[Element of S] means n gcd m divides $1.x & n gcd m divides $1.y &
  $1.x > $1.y & $1.y >= 0;
  defpred R[Element of S] means $1.y > 0;
  assume that
A15: n = s.x and
A16: m = s.y and
A17: n > m;
  s.y > 0 implies s1.b = 1 by Th38;
  then s1 in T iff m > 0 by A16,A14,Th2;
  then
A18: h iteration_terminates_for I\;C, h.(s,C) by A1,A2,A3,A4,A16,A13,Lm1;
A19: for s being Element of S st P[s] & s in T & R[s] holds P[h.(s,I)]
  proof
    let s be Element of S;
    reconsider s99 = h.(s, I) as Element of S;
    assume
A20: P[s];
    then reconsider n9 = s.x, m9 = s.y as Element of NAT by INT_1:3;
    assume that
    s in T and
A21: R[s];
A22: s99.x = s.y by A1,A2,A3,A4,Lm1;
A23: s99.y = s.x mod s.y by A1,A2,A3,A4,Lm1;
    n gcd m divides n9 mod m9 by A20,NAT_D:11;
    hence thesis by A20,A21,A22,A23,NEWTON:65;
  end;
A24: for s being Element of S st P[s] holds P[h.(s,C) qua Element of S] & (h
  .(s,C) in T iff R[h.(s,C) qua Element of S])
  proof
    let s be Element of S;
    assume
A25: P[s];
    reconsider s9 = h.(s,C) as Element of S;
    s9.y = s.y by A1,A3,Th38;
    hence P[h.(s,C) qua Element of S] by A1,A2,A25,Th38;
A26: s.y <= 0 implies s9.b = 0 by Th38;
    s.y > 0 implies s9.b = 1 by Th38;
    hence thesis by A26,Th2,Th38;
  end;
A27: P[s] by A15,A16,A17,NAT_D:def 5;
A28: P[h.(s,while(C,I)) qua Element of S] & not R[h.(s,while(C,I)) qua
  Element of S] from AOFA_000:sch 5(A27,A18,A19,A24);
  then fin.y = 0;
  then
A29: Q[h.(s,while(C,I)) qua Element of S] by INT_2:12;
  Q[s] from AOFA_000:sch 6(A29,A18,A6,A5);
  then fin.x divides n gcd m by A15,A16,INT_2:22;
  then fin.x = n gcd m or fin.x = -(n gcd m) by A28,INT_2:11;
  hence thesis by A28;
end;
