Partition.qrz

// ============================================================================
// Name:        Partition
// Description: Let a[0..n-1] be an array of numbers with x = a[0]. Permute the
//              elements and set the index p such that the following holds:
//              - a[i] <= x for 0 <= i < p
//              - a[p] = x
//              - a[i] > x for p < i < n
// References:  D. Gries. The Science of Programming. Springer, 1981.
// Parameters:  SIZE (size of array)
//              INFINITE (use variables with infinite bit width)
//              BITS (bit width for finite variables)
// ============================================================================

#ifndef SIZE
#define SIZE 4u
#endif

#ifdef INFINITE
#define TYPE int
#else
#ifndef BITS
#define BITS 4u
#endif
#define TYPE int[BITS]
#endif

module Partition(TYPE b[SIZE], &a[SIZE], &x, nat[sizeOf(SIZE)] &p, &q, event &ready, &fault)
   implements PartitionSpec(ready, fault) {
   sequence(nat[sizeOf(SIZE-1u)] i=0u .. (SIZE-1u))
      a[i] = b[i];

   x = a[0u];
   q = 1u;
   p = SIZE-1u;

   while(q <= p) {
      if(a[q] <= x)
         next(q) = q+1u;
      else
         if(a[p] > x)
            next(p) = p-1u;
         else {
            next(a[q]) = a[p];
            next(a[p]) = a[q];
            next(q) = q+1u;
            next(p) = p-1u;
         }
      pause;
   }

   if(p > 0) {
      next(a[0u]) = a[p];
      next(a[p]) = a[0u];
   }
   pause;

   emit ready;
   CheckSpec(a, x, p, q, fault);
}

module CheckSpec(TYPE &a[SIZE], &x, nat[sizeOf(SIZE)] &p, &q, event &fault) {
   q = 0u;
   while(q < p) {
      if(a[q] > x)
         emit fault;
      next(q) = q+1u;
      pause;
   }
   if(a[q] != x)
      emit fault;
   next(q) = q+1u;
   pause;
   while(q < SIZE) {
      if(a[q] <= x)
         emit fault;
      next(q) = q+1u;
      pause;
   }
}

spec PartitionSpec(event ready, fault) {
   termination: A F ready;
   correctness: A G !fault;
}