/* Mergesort, version with additional invariants * 15-122 Principles of Imperative Computation, Fall 2010 * Frank Pfenning */ bool is_sorted(int[] A, int lower, int upper) //@requires 0 <= lower && lower <= upper && upper <= \length(A); { int i; for (i = lower; i < upper-1; i++) //@loop_invariant lower == upper || (lower <= i && i <= upper-1); if (!(A[i] <= A[i+1])) return false; return true; } /* merge(A, lower, mid, upper) merges two adjacent sorted * segments A[lower..mid) and A[mid..upper) into A[lower..upper) * This is the fully explicit version, with all invariants */ void merge(int[] A, int lower, int mid, int upper) //@requires 0 <= lower && lower < mid && mid < upper && upper <= \length(A); //@requires is_sorted(A, lower, mid) && is_sorted(A, mid, upper); //@ensures is_sorted(A, lower, upper); { int[] B = alloc_array(int, upper-lower); int i = lower; int j = mid; int k = 0; while (i < mid && j < upper) //@loop_invariant lower <= i && i <= mid; //@loop_invariant mid <= j && j <= upper; //@loop_invariant k == (i-lower)+(j-mid); //@loop_invariant is_sorted(B, 0, k); //@loop_invariant is_sorted(A, i, mid) && is_sorted(A, j, upper); /*@loop_invariant k == 0 || ((i == mid || B[k-1] <= A[i]) && (j == upper || B[k-1] <= A[j])); @*/ { if (A[i] <= A[j]) { B[k] = A[i]; i++; } else { B[k] = A[j]; j++; } k++; } //@assert i == mid || j == upper; while (i < mid) //@loop_invariant lower <= i && i <= mid && k == (i-lower)+(j-mid); //@loop_invariant is_sorted(B, 0, k) && is_sorted(A, i, mid); //@loop_invariant k == 0 || i == mid || B[k-1] <= A[i]; { B[k] = A[i]; i++; k++; } while (j < upper) //@loop_invariant mid <= j && j <= upper && k == (i-lower)+(j-mid); //@loop_invariant is_sorted(B, 0, k) && is_sorted(A, j, upper); //@loop_invariant k == 0 || j == upper || B[k-1] <= A[j]; { B[k] = A[j]; j++; k++; } //@assert k == upper-lower && is_sorted(B, 0, upper-lower); for (k = 0; k < upper-lower; k++) //@loop_invariant lower <= lower+k && lower+k <= upper; A[lower+k] = B[k]; } void mergesort (int[] A, int lower, int upper) //@requires 0 <= lower && lower <= upper && upper <= \length(A); // modifies A; //@ensures is_sorted(A, lower, upper); { if (upper-lower <= 1) return; else { int mid = lower + (upper-lower)/2; mergesort(A, lower, mid); //@assert is_sorted(A, lower, mid); mergesort(A, mid, upper); //@assert is_sorted(A, mid, upper); merge(A, lower, mid, upper); } }