/* @ maintaining -1 <= i && i <= a.length;
  @ maintaining sum
  @            == (\sum int j;
  @                   i <= j && 0 <= j && j < a.length;
  @                   (\bigint)a[j]);
  @ decreasing i; @*/
// @ assert i < 0 && -1 <= i && i <= a.length;
// @ hence_by (i < 0 && -1 <= i) ==> i == -1;
// @ assert i == -1 && i <= a.length;
// @ assert sum == (\sum int j; 0 <= j && j < a.length; (\bigint)a[j]);
// @ set i = 0;
// @ set collection.elementType = \type(int);
// @ unreachable;
// @ debug x = x + 1;
// @ debug aList.add(y);
---Contract---
//@ ghost int oldx = x;
        //@ ghost \bigint p = 0;
        /*@ maintaining 0 <= x && x <= oldx;
          @ maintaining z == y * (oldx - x);
	  @ maintaining (\bigint)z == p;
          @ decreasing  x;
	  @*/
---Contract---
//@ ghost \locset oldPcDep = UpdateAbstraction.pcDep;         //entering conditional
//@ set UpdateAbstraction.pcDep = \set_union(UpdateAbstraction.pcDep, UpdateAbstraction.hDep); //entering conditional
--- Contract ---
loop_invariant
     (\forall short j; true; true)
     ;
--- Contract ---
/*@ loop_contract normal_behavior
  @ requires i <= 42;
  @ ensures i == 42;
  @*/
--- Contract ---
/*@
   loop_invariant i >= 0 && i <= length &&
      srcOffset + i >= 0 && srcOffset + i <= src.length &&
      destOffset + i >= 0 && destOffset + i <= dest.length &&
     (\forall short j; j >= 0 && j< length;
         dest[destOffset + j] == (j<i ? \old(src[srcOffset + j]) : \old(dest[destOffset + j]))
     )
   ;
   loop_invariant<savedHeap>
     (\forall short j; j >= 0 && j < length;
        \backup(dest[destOffset + j]) ==
          ((j >= i || \backup(\transactionUpdated(dest))) ?
              \old(\backup(dest[destOffset + j])) :
              \old(src[srcOffset + j]))
     );
   decreases length - i;
   assignable<heap><savedHeap> dest[destOffset..destOffset+length-1];
@*/
--- Contract ---
//@ set cause = arg0;
--- Contract ---
//@ set message = arg0;
//@ set cause = arg1;
--- Contract ---
//@ assert true;
--- Contract ---
//@ assume true;
--- Contract ---
/*@ loop_invariant
          @   0 <= k && k <= a.length
          @   && (\forall int i; 0 <= i && i < k; a[i] <= max)
          @   && (k == 0 ==> max == 0)
          @   && (k > 0 ==> (\exists int i; 0 <= i && i < k; max == a[i]))
          @   && sum == (\sum int i; 0 <= i && i< k; a[i])
          @   && sum <= k * max;
          @
          @  assignable sum, max;
          @  decreases a.length - k;
          @*/
--- Contract ---
merge_point;
--- Contract ---
merge_point
merge_proc "MergeByPredicateAbstraction"
merge_params {conjunctive: (int x) -> {x >= 0, (x == \old(b) || x == -\old(b))}};