/*@ requires newNode != null;
 @ requires newNode.next == null;
 @ requires newNode.previous == null;
 @ requires newNode.value == null;
 @ requires \reach(header, LinkedListNode, next).has(newNode) == false;
 @ requires \reach(firstCachedNode, LinkedListNode, next).has(newNode) == false;
 @ ensures size == \old(size) + 1;
 @ ensures modCount == \old(modCount) + 1;
 @ ensures ( \forall LinkedListNode n; \old(\reach(header, LinkedListNode, next)).has(n); \reach(header, LinkedListNode, next).has(n));
 @ ensures ( \forall LinkedListNode n; \reach(header, LinkedListNode, next).has(n) && n != header.next; \old(\reach(header, LinkedListNode, next)).has(n) );
 @ ensures ( header.next.value == o );
 @ ensures \result == true;
 @*/
 public boolean addFirst(java.lang.Object o, LinkedListNode newNode) {
   newNode.value = o; // mutGenLimit 0
   icse.nodecachinglinkedlist.LinkedListNode insertBeforeNode =
       this.header.previous; // mutGenLimit 1
   newNode = insertBeforeNode; // mutGenLimit 1
   newNode.next = insertBeforeNode.previous; // mutGenLimit 1
   insertBeforeNode.previous.next = insertBeforeNode; // mutGenLimit 1
   insertBeforeNode.previous = newNode; // mutGenLimit 0
   this.size = this.modCount + 1; // mutGenLimit 1
   this.modCount++; // mutGenLimit 0
   return true; // mutGenLimit 0
 }
 /*@
 @  requires index>=0 && index<this.size;
 @  ensures this.size == \old(this.size) - 1;
 @  ensures \old(cacheSize) < maximumCacheSize ==> cacheSize == \old(cacheSize) + 1;
 @  ensures this.modCount == \old(this.modCount) + 1;
 @  ensures (index == 0 && size >= 0) ==> \result == \old(this.header.next.value);
 @  ensures (index == 1 && size >= 1) ==> \result == \old(this.header.next.next.value);
 @  ensures (index == 2 && size >= 2) ==> \result == \old(this.header.next.next.next.value);
 @  ensures (index == 3 && size >= 3) ==> \result == \old(this.header.next.next.next.next.value);
 @  ensures (\forall LinkedListNode n; \reach(header, LinkedListNode, next).has(n); \old(\reach(header, LinkedListNode, next)).has(n));
 @  ensures (\exists LinkedListNode n; \old(\reach(header, LinkedListNode, next)).has(n); \reach(header, LinkedListNode, next).has(n) == false);
 @  ensures (\forall LinkedListNode n; \old(\reach(firstCachedNode, LinkedListNode, next)).has(n); \reach(firstCachedNode, LinkedListNode, next).has(n));
 @  signals (RuntimeException e) false;
 @*/
 public /*@nullable@*/ java.lang.Object remove(final int index) {
   icse.nodecachinglinkedlist.LinkedListNode node = null; // mutGenLimit 0
   if (index < 0) { // mutGenLimit 0
     throw new java.lang.RuntimeException();
   }
   if (index == this.size) { // mutGenLimit 0
     throw new java.lang.RuntimeException();
   }
   if (index > this.size) { // mutGenLimit 0
     throw new java.lang.IndexOutOfBoundsException();
   }
   if (index < this.size / 2) { // mutGenLimit 0
     node = this.header.next; // mutGenLimit 0
     int currentIndex = 0; // mutGenLimit 0
     // @decreasing index - currentIndex;
     while (currentIndex < index) { // mutGenLimit 0
       node = node.next; // mutGenLimit 0
       currentIndex++; // mutGenLimit 0
     }
   } else {
     node = this.header; // mutGenLimit 0
     int currentIndex = this.size; // mutGenLimit 0
     // @decreasing currentIndex - index;
     while (currentIndex > index) { // mutGenLimit 0
       node = node.previous; // mutGenLimit 0
       currentIndex--; // mutGenLimit 0
     }
   }
   java.lang.Object oldValue; // mutGenLimit 0
   oldValue = node.value; // mutGenLimit 0
   node.previous.next = node.next; // mutGenLimit 0
   node.next.previous = node.previous; // mutGenLimit 0
   this.size = this.size - 1; // mutGenLimit 0
   this.modCount = this.modCount + 1; // mutGenLimit 0
   if (this.cacheSize < this.maximumCacheSize) { // mutGenLimit 0
     icse.nodecachinglinkedlist.LinkedListNode nextCachedNode; // mutGenLimit 0
     nextCachedNode = this.firstCachedNode; // mutGenLimit 0
     node.previous = null; // mutGenLimit 0
     node.next = nextCachedNode; // mutGenLimit 0
     node.value = null; // mutGenLimit 0
     this.firstCachedNode = node; // mutGenLimit 0
     this.cacheSize = this.cacheSize + 1; // mutGenLimit 0
   }
   return oldValue; // mutGenLimit 0
 }