#include <stdio.h>
#include <string.h>
#ifdef _CIVL
#include <civlc.cvh>
#pragma CIVL ACSL
#endif

#ifdef _CIVL
$input int ni,nj;
$assume(ni > 1);
$assume(nj > 1);
$input double uin[ni][nj];
#endif

int main(int argc, char** argv) {
  int i,j,ir,jr;
  double u1[ni][nj];
  double u2[ni][nj];

  $havoc(&i); $havoc(&j);
  $assume($forall (int i : 0 .. ni-1) 
	  ($forall (int j : 0 .. nj-1) u1[i][j] == 0 && u2[i][j] == 0)
	  );

  double tmp1[ni][nj];

  $assume($forall (int i : 1 .. ni-2) 
	  ($forall (int j : 1 .. nj-2) tmp1[i][j] == uin[i][j] * uin[i][j])
	  );
  $assume($forall (int i, j | i == 0 || i == ni-1 || j == 0 || j == nj-1) tmp1[i][j] == 0);
  memcpy(u1, tmp1, sizeof(double) * ni * nj);

  double tmp2[ni][nj];

  $assume($forall (int i | 1 <= i && i < ni - 2 && i % 2 != 0) 
	  ($forall (int j | 1 <= j && j < nj - 2 && j % 2 != 0)
	   tmp2[i][j] == uin[i][j]*uin[i][j] &&
	   tmp2[i+1][j] == uin[i+1][j]*uin[i+1][j] &&
	   tmp2[i][j+1] == uin[i][j+1]*uin[i][j+1] &&
	   tmp2[i+1][j+1] == uin[i+1][j+1]*uin[i+1][j+1])
	  );
  $assume($forall (int i, j | i == 0 || i == ni-1 || j == 0 || j == nj-1) tmp2[i][j] == 0);
  memcpy(u2, tmp2, sizeof(double) * ni * nj);
    // remainder
  if(i==ni-2) {
    /*@ loop invariant 1 <= jr && jr <= nj-1;
      @ loop invariant \forall int t; 1 <= t && t < jr ==>
      @                    u2[i][t] == uin[i][t]*uin[i][t];
      @ loop assigns   jr, u2[i][1 .. nj-2];
      @*/
    for(jr=1;jr<nj-1;jr++) {
      u2[i][jr] = uin[i][jr]*uin[i][jr];
    }
  }
  if(j==nj-2) {
    /*@ loop invariant 1 <= ir && ir <= ni-1;
      @ loop invariant \forall int t; 1 <= t && t < ir ==>
      @                    u2[t][j] == uin[t][j]*uin[t][j];
      @ loop assigns   ir, u2[1 .. ni-2][j];
      @*/
    for(ir=1;ir<ni-1;ir++) {
      u2[ir][j] = uin[ir][j]*uin[ir][j];
    }
  }
  if(i==ni-2 && j==nj-2) u2[i][j] = uin[i][j]*uin[i][j];

  $assert($forall (int i: 0 .. ni-1) 
	  ($forall (int j: 0 .. nj-1) u1[i][j] == u2[i][j])
	  );
}
