| summaryrefslogtreecommitdiff | 
diff options
Diffstat (limited to 'src/sequence/sequence.c')
| -rw-r--r-- | src/sequence/sequence.c | 170 | 
1 files changed, 170 insertions, 0 deletions
| diff --git a/src/sequence/sequence.c b/src/sequence/sequence.c new file mode 100644 index 0000000..852b05c --- /dev/null +++ b/src/sequence/sequence.c @@ -0,0 +1,170 @@ +#include <stdlib.h> +#include <string.h> + +#include "../core/index.h" + +#include "sequence.h" + +/* + * Bypass rendundant ZoO_START_OF_SEQUENCE_ID at the start of a sequence. + */ +/*@ +   requires +   ( +      \valid(sequence+ (0 .. sequence_length)) +      || (sequence_length == 0) +   ); +   requires \separated(sequence, sequence_offset); + +   assigns (*sequence_offset); + +   ensures (*sequence_offset < sequence_length); + +   ensures +   ( +      (*sequence_offset == 0) +      || (sequence[0 .. *sequence_offset] == ZoO_START_OF_SEQUENCE_ID) +   ); + +   ensures +   ( +      (*sequence_offset == sequence_length) +      || (sequence[*sequence_offset + 1] != ZoO_START_OF_SEQUENCE_ID) +   ); + +@*/ +static void bypass_redundant_sos +( +   const ZoO_index sequence [const restrict], +   const size_t sequence_length, +   size_t sequence_offset [const restrict static 1] +) +{ +   ZoO_index i; + +   *sequence_offset = 0; + +   /*@ +      loop invariant 0 <= i <= sequence_length; +      loop invariant (*sequence_offset <= i); +      loop invariant +      ( +         (*sequence_offset == 0) +         || (sequence[*sequence_offset] == ZoO_START_OF_SEQUENCE_ID) +      ); +      loop invariant +         ( +            (i == 0) || (sequence[0 .. (i - 1)] == ZoO_START_OF_SEQUENCE_ID) +         ); +      loop assigns i, *sequence_offset; +      loop variant (sequence_length - i); +   @*/ +   for (i = 0; i < sequence_length; ++i) +   { +      if (sequence[i] != ZoO_START_OF_SEQUENCE_ID) +      { +         return; +      } +      else if (sequence[i] == ZoO_START_OF_SEQUENCE_ID) +      { +         *sequence_offset = i; +      } +   } +} + + +/* See "sequence.h" */ +/*@ +   \requires +   ( +      \valid(sequence_a+ (0 .. sequence_a_length)) +      || (sequence_a_length == 0) +   ); + +   \requires +   ( +      \valid(sequence_b+ (0 .. sequence_b_length)) +      || (sequence_b_length == 0) +   ); + +   assigns \result; +@*/ +int ZoO_sequence_cmp +( +   const ZoO_index sequence_a [const], +   size_t sequence_a_length, +   const ZoO_index sequence_b [const], +   size_t sequence_b_length +) +{ +   size_t min_length, a, b; +   size_t a_offset, b_offset; +   size_t i; +   /*@ ghost size_t actual_a_length, actual_b_length; @*/ + +   bypass_redundant_sos(sequence_a, sequence_a_length, &a_offset); +   bypass_redundant_sos(sequence_b, sequence_b_length, &b_offset); + +   /*@ ghost actual_a_length = sequence_a_length; @*/ +   /*@ ghost actual_b_length = sequence_b_length; @*/ + +   /*@ assert (a_offset <= sequence_a_length); @*/ +   sequence_a_length -= a_offset; +   /*@ assert (b_offset <= sequence_b_length); @*/ +   sequence_b_length -= b_offset; + +   if (sequence_a_length < sequence_b_length) +   { +      min_length = sequence_a_length; +   } +   else +   { +      min_length = sequence_b_length; +   } + +   /*@ assert (min_length <= sequence_a_length); @*/ +   /*@ assert (min_length <= sequence_b_length); @*/ + +   /*@ assert (min_length + a_offset <= actual_a_length); @*/ +   /*@ assert (min_length + b_offset <= actual_b_length); @*/ + +   /*@ +      loop invariant 0 <= i <= min_length; +      loop assigns i; +      loop variant (min_length - i); +   @*/ +   for (i = 0; i < min_length; ++i) +   { +      /*@ assert ((i + a_offset) < actual_a_length); @*/ +      a = sequence_a[i + a_offset]; +      /*@ assert ((i + b_offset) < actual_b_length); @*/ +      b = sequence_b[i + b_offset]; + +      if (a < b) +      { +         return -1; +      } +      else if (b > a) +      { +         return 1; +      } +      else if ((a == ZoO_END_OF_SEQUENCE_ID) && (b == ZoO_END_OF_SEQUENCE_ID)) +      { +         return 0; +      } +   } + +   if (sequence_a_length > sequence_b_length) +   { +      return 1; +   } +   else if (sequence_a_length < sequence_b_length) +   { +      return -1; +   } +   else +   { +      return 0; +   } +} + | 


