------------------------------------------------------------------------------
-- Definition of the gcd of two natural numbers using the Euclid's algorithm
------------------------------------------------------------------------------

{-# OPTIONS --exact-split              #-}
{-# OPTIONS --no-sized-types           #-}
{-# OPTIONS --no-universe-polymorphism #-}
{-# OPTIONS --without-K                #-}

module LTC-PCF.Program.GCD.Total.GCD where

open import LTC-PCF.Base
open import LTC-PCF.Data.Nat
open import LTC-PCF.Data.Nat.Inequalities
open import LTC-PCF.Loop

------------------------------------------------------------------------------
-- In GHC ≥ 7.2.1 the gcd is a total function, i.e. gcd 0 0 = 0.

-- Let T = D → D → D be a type. Instead of defining gcdh : T → T, we
-- use the LTC-PCF λ-abstraction and application to avoid use a
-- polymorphic fixed-point operator.

gcdh : D  D
gcdh g = lam  m  lam  n 
           if (iszero₁ n)
             then m
             else (if (iszero₁ m)
                     then n
                     else (if (gt m n)
                             then g · (m  n) · n
                             else g · m · (n  m)))))

gcd : D  D  D
gcd m n = fix gcdh · m · n