{-# OPTIONS --prop --rewriting #-}
module Examples.Gcd.Clocked where
open import Calf.CostMonoid
import Calf.CostMonoids as CM
open import Calf CM.ℕ-CostMonoid
open import Calf.Types.Nat
open import Data.Nat using (_≤_; z≤n)
open import Calf.Types.Unit
open import Calf.Types.Bounded CM.ℕ-CostMonoid
open import Calf.Types.BoundedFunction CM.ℕ-CostMonoid
open import Data.Nat.DivMod
open import Relation.Binary.PropositionalEquality as P
open import Data.Product
open import Examples.Gcd.Euclid
gcd/clocked : cmp (Π nat λ _ → Π gcd/i λ _ → F nat)
gcd/clocked zero (x , y , h) = ret x
gcd/clocked (suc k) (x , 0 , h) = ret {nat} x
gcd/clocked (suc k) (x , suc y , h) =
bind {mod-tp x (suc y) triv} (F nat) (mod x (suc y) triv)
λ { (z , eqn2) →
let h2 = P.subst (λ k → suc k ≤ suc y) (P.sym eqn2) (m%n<n x _) in
gcd/clocked k (suc y , z , h2) }
gcd : cmp (Π gcd/i λ _ → F nat)
gcd i = gcd/clocked (gcd/depth i) i
gcd/clocked≤gcd/depth : ∀ k i → IsBounded nat (gcd/clocked k i) (gcd/depth i)
gcd/clocked≤gcd/depth zero i = bound/relax (λ _ → z≤n) bound/ret
gcd/clocked≤gcd/depth (suc k) (x , zero , h) = bound/ret
gcd/clocked≤gcd/depth (suc k) (x , y@(suc _) , h) rewrite gcd/depth-unfold-suc {h = h} =
bound/step 1 _ (gcd/clocked≤gcd/depth k (y , x % y , m%n<n x _))
gcd≤gcd/depth : ∀ i → IsBounded nat (gcd i) (gcd/depth i)
gcd≤gcd/depth i = gcd/clocked≤gcd/depth (gcd/depth i) i
gcd/bounded : cmp (Ψ gcd/i (λ { _ → nat }) gcd/depth)
gcd/bounded = gcd , gcd≤gcd/depth