Auxiliary implementation lemmas

module Impl.Bignum.Lemmas

Let’s move lemmas to a separate module. It’ll be cleaner!

module B = LowStar.Buffer
module ST = FStar.HyperStack.ST
module HS = FStar.HyperStack
module S = FStar.Seq

module U32 = FStar.UInt32
module U64 = FStar.UInt64

I oftentimes use Spec to refer to the spec of the current module.

module Spec = Spec.Bignum

This module only contains operators, and is meant to be opened.

open LowStar.BufferOps
open FStar.HyperStack.ST

#set-options "--max_fuel 0 --max_ifuel 0"

This is my little library of sequence lemmas that I always carry with me.

let lemma_slice (#a: Type) (s: S.seq a) (i: nat): Lemma
  (requires (i <= S.length s))
  (ensures (S.equal (S.append (S.slice s 0 i) (S.slice s i (S.length s))) s))

let lemma_slice_ijk (#a: Type) (s: S.seq a) (i j k: nat): Lemma
  (requires (i <= j /\ j <= k /\ k <= S.length s))
  (ensures (S.equal (S.append (S.slice s i j) (S.slice s j k)) (S.slice s i k)))

#push-options "--fuel 1"
let v_zero_tail (x: Spec.t): Lemma
  (requires Spec.v x = 0 /\ S.length x > 0)
  // Two notes:
  // i) discrepancy between B.sub that takes a length as its last argument and
  //    S.slice that takes an index
  // ii) doing this in terms of slice since the spec of sub is in terms of
  //     slice; using tail would require lemma_tl all over again
  (ensures Spec.v (S.slice x 1 (S.length x)) = 0)

let rec v_all_zeroes (x: Spec.t): Lemma
  (requires x `S.equal` S.create (S.length x) 0ul)
  (ensures Spec.v x == 0)
  (decreases (S.length x))
  if S.length x = 0 then
    v_all_zeroes (S.tail x)

let lemma_empty #a (x: S.seq a): Lemma
  (requires S.length x = 0)
  (ensures x `S.equal` S.empty)

let max32 (x y: U32.t): U32.t =
  if x `` y then x else y

let max_fact (z x y: U32.t): Lemma
  (requires U32.(
    x >^ 0ul /\ y >^ 0ul /\ z >^ 0ul /\
    U32.v z == U32.v (max32 x y) + 1))
    U32.(v (z -^ 1ul) == U32.v (max32 (x -^ 1ul) (y -^ 1ul)) + 1))

let slice_create #a (i: nat) (s: S.seq a): Lemma
  (requires S.length s > 0 /\ i + 1 < S.length s)
  (ensures S.slice s i (i + 1) `S.equal` S.create 1 (S.index s i))