packages feed

MiniAgda-0.2014.1.9: test/succeed/gcd-either.ma

-- 2011-12-16 Andreas, gcd example

sized data Nat : Size -> Set 
{ zero : [i : Size] -> Nat ($ i)
; suc  : [i : Size] -> Nat i -> Nat ($ i)
}

-- subtracting two numbers with minus yields the difference
-- plus a bit indicating the bigger number of the two

data Either : +Size -> +Size -> Set
{ left  : [i,j : Size] -> Nat i -> Either i j
; right : [i,j : Size] -> Nat j -> Either i j
}

fun minus : [i,j : Size] -> Nat i -> Nat j -> Either i j
{ minus i j (zero (i > i'))   m                 = right i j m 
; minus i j (suc  (i > i') n) (zero (j > j'))   = left i j (suc i' n)
; minus i j (suc  (i > i') n) (suc  (j > j') m) = minus i' j' n m
}

{- UNUSED
fun esuc : [i,j : Size] -> Either i j -> Either $i $j
{ esuc i j (left  .i .j n) = left  $i $j (suc i n)
; esuc i j (right .i .j n) = right $i $j (suc j n)
}
-}

mutual {

  fun gcd : [i,j : Size] -> Nat i -> Nat j -> Nat #
  { gcd i j (zero (i > i')) m = m
  ; gcd i j (suc (i > i') n) (zero (j > j')) = suc i' n
  ; gcd i j (suc (i > i') n) (suc (j > j') m) = 
      gcd_aux i j i' j' n m (minus i' j' n m)
  }

  fun gcd_aux : [i,j : Size] -> [i' < i] -> [j' < j] -> Nat i' -> Nat j' ->
                Either i' j' -> Nat #
  { gcd_aux i j i' j' n m (left  .i' .j' n') = gcd i' j n' (suc j' m)
  ; gcd_aux i j i' j' n m (right .i' .j' m') = gcd i j' (suc i' n) m'
  }

}