(* specification 
 *****************)
 (*
    It is easy, by a sequence of unshifts (right shifts) to
    compute, not only the integer logarithm (base 2 ) of a positive
    integer, but also to know  wether this logarithm is exact;
    the additionnal cost is a boolean variable, initialized with
    true, and set to false the first time a division by 2 returns a
    non null rest.
*)


 (*
  Sketch of the (imperative) program:
 
  n := n0;
  p:= O;
  b := true; /* n0=2^p * n  */

  while (n>O)  
  {
    if (b)  /* n0=2^p * n  */
      {
         if(n is even) 
            { p:=p+1;
              n:=unshift(n);
              b:=true}
         else
             {p:=p+1;
              n:=unshift(n);
              b:=false}
      }
     else   /* 2^p * n < n0 < 2^p(n+1) /\ n>0 */
      {
       p:=p+1;
       n:=unshift(n);
       b:=false}
    }
    return (p,b);
 *)

 
 
 (* computation states  
 **************************)
 
  Record state : Set := mkstate
    {state_n : nat; state_p : nat; state_b : bool}.(* specification 
 *****************)
 (*
    It is easy, by a sequence of unshifts (right shifts) to
    compute, not only the integer logarithm (base 2 ) of a positive
    integer, but also to know  wether this logarithm is exact;
    the additionnal cost is a boolean variable, initialized with
    true, and set to false the first time a division by 2 returns a
    non null rest.
*)


 (*
  Sketch of the (imperative) program:
 
  n := n0;
  p:= O;
  b := true; /* n0=2^p * n  */

  while (n>O)  
  {
    if (b)  /* n0=2^p * n  */
      {
         if(n is even) 
            { p:=p+1;
              n:=unshift(n);
              b:=true}
         else
             {p:=p+1;
              n:=unshift(n);
              b:=false}
      }
     else   /* 2^p * n < n0 < 2^p(n+1) /\ n>0 */
      {
       p:=p+1;
       n:=unshift(n);
       b:=false}
    }
    return (p,b);
 *)

 
 
 (* computation states  
 **************************)
 
  Record state : Set := mkstate
    {state_n : nat; state_p : nat; state_b : bool}.(* specification 
 *****************)
 (*
    It is easy, by a sequence of unshifts (right shifts) to
    compute, not only the integer logarithm (base 2 ) of a positive
    integer, but also to know  wether this logarithm is exact;
    the additionnal cost is a boolean variable, initialized with
    true, and set to false the first time a division by 2 returns a
    non null rest.
*)


 (*
  Sketch of the (imperative) program:
 
  n := n0;
  p:= O;
  b := true; /* n0=2^p * n  */

  while (n>O)  
  {
    if (b)  /* n0=2^p * n  */
      {
         if(n is even) 
            { p:=p+1;
              n:=unshift(n);
              b:=true}
         else
             {p:=p+1;
              n:=unshift(n);
              b:=false}
      }
     else   /* 2^p * n < n0 < 2^p(n+1) /\ n>0 */
      {
       p:=p+1;
       n:=unshift(n);
       b:=false}
    }
    return (p,b);
 *)

 
 
 (* computation states  
 **************************)
 
  Record state : Set := mkstate
    {state_n : nat; state_p : nat; state_b : bool}.(* specification 
 *****************)
 (*
    It is easy, by a sequence of unshifts (right shifts) to
    compute, not only the integer logarithm (base 2 ) of a positive
    integer, but also to know  wether this logarithm is exact;
    the additionnal cost is a boolean variable, initialized with
    true, and set to false the first time a division by 2 returns a
    non null rest.
*)


 (*
  Sketch of the (imperative) program:
 
  n := n0;
  p:= O;
  b := true; /* n0=2^p * n  */

  while (n>O)  
  {
    if (b)  /* n0=2^p * n  */
      {
         if(n is even) 
            { p:=p+1;
              n:=unshift(n);
              b:=true}
         else
             {p:=p+1;
              n:=unshift(n);
              b:=false}
      }
     else   /* 2^p * n < n0 < 2^p(n+1) /\ n>0 */
      {
       p:=p+1;
       n:=unshift(n);
       b:=false}
    }
    return (p,b);
 *)

 
 
 (* computation states  
 **************************)
 
  Record state : Set := mkstate
    {state_n : nat; state_p : nat; state_b : bool}.(* specification 
 *****************)
 (*
    It is easy, by a sequence of unshifts (right shifts) to
    compute, not only the integer logarithm (base 2 ) of a positive
    integer, but also to know  wether this logarithm is exact;
    the additionnal cost is a boolean variable, initialized with
    true, and set to false the first time a division by 2 returns a
    non null rest.
*)


 (*
  Sketch of the (imperative) program:
 
  n := n0;
  p:= O;
  b := true; /* n0=2^p * n  */

  while (n>O)  
  {
    if (b)  /* n0=2^p * n  */
      {
         if(n is even) 
            { p:=p+1;
              n:=unshift(n);
              b:=true}
         else
             {p:=p+1;
              n:=unshift(n);
              b:=false}
      }
     else   /* 2^p * n < n0 < 2^p(n+1) /\ n>0 */
      {
       p:=p+1;
       n:=unshift(n);
       b:=false}
    }
    return (p,b);
 *)

 
 
 (* computation states  
 **************************)
 
  Record state : Set := mkstate
    {state_n : nat; state_p : nat; state_b : bool}.Inductive ok : state -> Prop :=
    | oktrue : forall p : nat, n0 = two_power p -> ok (mkstate one p true)
    | okfalse :
        forall p : nat,
        two_power p < n0 -> n0 < two_power (S p) -> ok (mkstate one p false).Inductive ok : state -> Prop :=
    | oktrue : forall p : nat, n0 = two_power p -> ok (mkstate one p true)
    | okfalse :
        forall p : nat,
        two_power p < n0 -> n0 < two_power (S p) -> ok (mkstate one p false).Inductive ok : state -> Prop :=
    | oktrue : forall p : nat, n0 = two_power p -> ok (mkstate one p true)
    | okfalse :
        forall p : nat,
        two_power p < n0 -> n0 < two_power (S p) -> ok (mkstate one p false).(* loop parameters *)
 (* exit predicate  (when to stop looping)
 ************************************************)
 
  Inductive final : state -> Prop :=
      mkfinal : forall (p : nat) (b : bool), final (mkstate one p b).(* loop parameters *)
 (* exit predicate  (when to stop looping)
 ************************************************)
 
  Inductive final : state -> Prop :=
      mkfinal : forall (p : nat) (b : bool), final (mkstate one p b).(* loop invariant 
 *****************)
  (* in a state (mkstate n p b), the boolean b expresses
     the exactness of the logarithm to compute *)

  Inductive invar : state -> Prop :=
    | exact :
        forall n p : nat,
        n0 = two_power p * n -> 0 < n -> invar (mkstate n p true)
    | inexact :
        forall n p : nat,
        two_power p * n < n0 ->
        n0 < two_power p * S n -> 0 < n -> invar (mkstate n p false).(* loop invariant 
 *****************)
  (* in a state (mkstate n p b), the boolean b expresses
     the exactness of the logarithm to compute *)

  Inductive invar : state -> Prop :=
    | exact :
        forall n p : nat,
        n0 = two_power p * n -> 0 < n -> invar (mkstate n p true)
    | inexact :
        forall n p : nat,
        two_power p * n < n0 ->
        n0 < two_power p * S n -> 0 < n -> invar (mkstate n p false).(* loop invariant 
 *****************)
  (* in a state (mkstate n p b), the boolean b expresses
     the exactness of the logarithm to compute *)

  Inductive invar : state -> Prop :=
    | exact :
        forall n p : nat,
        n0 = two_power p * n -> 0 < n -> invar (mkstate n p true)
    | inexact :
        forall n p : nat,
        two_power p * n < n0 ->
        n0 < two_power p * S n -> 0 < n -> invar (mkstate n p false).(* termination order  (hope it's well founded !)
 ************************************************)
 
  Definition stat_order := ltof state state_n.

(* Specifications: *)
Lemma decomp : forall s : state, s = mkstate (state_n s) (state_p s) (state_b s).
Lemma invar_inv1 : forall n p : nat, invar (mkstate n p true) -> n0 = two_power p * n.
Lemma invar_inv2 : forall n p : nat, invar (mkstate n p false) -> two_power p * n < n0 /\ n0 < two_power p * S n.
Lemma invar_inv3 : forall (n p : nat) (b : bool), invar (mkstate n p b) -> 0 < n.
Lemma final_inv : forall (n p : nat) (b : bool), final (mkstate n p b) -> n = one.
Lemma not_final : forall (n p : nat) (b : bool), invar (mkstate n p b) -> ~ final (mkstate n p b) -> one < n.
Lemma wf_stat_order : well_founded stat_order.
Lemma log2_impl : log2_spec n0.