// verifast_options{disable_overflow_check target:ILP32}
/*
Printing consecutive cubes, by Cohen
http://www.cs.upc.edu/~erodri/webpage/polynomial_invariants/cohencu.htm
*/

extern void abort(void);
//@ requires true;
//@ ensures true;
void reach_error()
//@ requires false;
//@ ensures true;
{}extern unsigned short __VERIFIER_nondet_ushort(void);
//@ requires true;
//@ ensures true;
void assume_abort_if_not(int cond) 
//@ requires true;
//@ ensures (cond != 0);
{  if(!cond) {abort();}
}
void __VERIFIER_assert(int cond) 
//@ requires (cond != 0);
//@ ensures (cond != 0);
{    if (!(cond)) {
    ERROR:
        {reach_error();}
    }
    return;
}

int main() 
//@ requires module(cohencu_ll_valuebound20__verifast_instrumented, true);
//@ ensures junk();
{
    //@ open_module(); 
    short a;
    long long n, x, y, z;
    a = __VERIFIER_nondet_ushort();
    assume_abort_if_not(a>=0 && a<=20);

    n = 0;
    x = 0;
    y = 1;
    z = 6;

while (1)
//@ invariant ((((((((((3 * (n * n)) + ((n * n) * n)) + (n * 3)) + 1) == (y + x)) && (a <= 20)) && (((n * 6) + 6) == z)) && (0 <= a)) && (((n * n) * n) == x)) && ((n < (a + 1)) || ((z * x) == ((x * 12) + ((a * x) * 6)))));
    {
        __VERIFIER_assert(z == 6 * n + 6);
        __VERIFIER_assert(y == 3 * n * n + 3 * n + 1);
        __VERIFIER_assert(x == n * n * n);
	__VERIFIER_assert(y*z - 18*x - 12*y + 2*z - 6 == 0);
	__VERIFIER_assert((z*z) - 12*y - 6*z + 12 == 0);
        if (!(n <= a))
            break;

        n = n + 1;
        x = x + y;
        y = y + z;
        z = z + 6;
    }

    __VERIFIER_assert(z == 6*n + 6);
    __VERIFIER_assert(6*a*x - x*z + 12*x == 0);
    __VERIFIER_assert(a*z - 6*a - 2*y + 2*z - 10 == 0);
    __VERIFIER_assert(2*y*y - 3*x*z - 18*x - 10*y + 3*z - 10 == 0);
    __VERIFIER_assert(z*z - 12*y - 6*z + 12 == 0);
    __VERIFIER_assert(y*z - 18*x - 12*y + 2*z - 6 == 0);
    
    return 0;
}