//// Non-negativity domain // Defining the conditions datatype condition = nonneg | unknown predicate P(c : condition, i : int) { if c == nonneg then i >= 0 else true } // Defining the merge function method merge(c1 : condition, c2 : condition) returns (c : condition) ensures forall x :: P(c1, x) || P(c2, x) ==> P(c, x) { if c1 == nonneg && c2 == nonneg { return nonneg; } else { return unknown; } } // Defining transfer functions method plus(c1 : condition, c2 : condition) returns (c : condition) ensures forall x, y :: P(c1, x) && P(c2, y) ==> P(c, x + y) { if c1 == nonneg && c2 == nonneg { return nonneg; } else { return unknown; } } method intConst(x : int) returns (c : condition) ensures forall x :: P(c, x) { if x >= 0 { return nonneg; } else { return unknown; } } // a.Length method aLength() returns (c : condition) ensures forall a : array :: P(c, a.Length) { return nonneg; } // Defining the refinement functions method compareTrue(c1 : condition, c2 : condition) returns (c1' : condition, c2' : condition) ensures forall x, y :: P(c1, x) && P(c2, y) && x >= y ==> P(c1', x) && P(c2', y) { c1' := c1; c2' := c2; if c2 == nonneg { c1' := nonneg; } } method compareFalse(c1 : condition, c2 : condition) returns (c1' : condition, c2' : condition) ensures forall x, y :: P(c1, x) && P(c2, y) && !(x >= y) ==> P(c1', x) && P(c2', y) { c1' := c1; c2' := c2; if c1 == nonneg { c2' := nonneg; } } // Intervals datatype ival = Fin(a : int, b : int) | LInf(b : int) | RInf(a : int) | Inf predicate Pival(c : ival, i : int) { if c.Fin? then c.a <= i <= c.b else if c.LInf? then i <= c.b else if c.RInf? then c.a <= i else true } function method min(x : int, y : int) : int { if x < y then x else y } function method max(x : int, y : int) : int { if x < y then y else x } method merge_ival(c1 : ival, c2 : ival) returns (c : ival) ensures forall x :: Pival(c1, x) || Pival(c2, x) ==> Pival(c, x) { var lft := (c1.Fin? || c1.RInf?) && (c2.Fin? || c2.RInf?); var rgt := (c1.Fin? || c1.LInf?) && (c2.Fin? || c2.LInf?); if lft && rgt { return Fin(min(c1.a, c2.a), max(c1.b, c2.b)); } else if lft { return RInf(min(c1.a, c2.a)); } else if rgt { return LInf(max(c1.b, c2.b)); } else { return Inf; } } method plus_ival(c1 : ival, c2 : ival) returns (c : ival) ensures forall x, y :: Pival(c1, x) && Pival(c2, y) ==> Pival(c, x + y) { var lft := (c1.Fin? || c1.RInf?) && (c2.Fin? || c2.RInf?); var rgt := (c1.Fin? || c1.LInf?) && (c2.Fin? || c2.LInf?); if lft && rgt { return Fin(c1.a + c2.a, c1.b + c2.b); } else if lft { return RInf(c1.a + c2.a); } else if rgt { return LInf(c1.b + c2.b); } else { return Inf; } }