{-# OPTIONS --cubical #-}

module Data.Binary.Testing where

open import Data.Binary.Increment
open import Data.Binary.Definition
open import Agda.Builtin.List
open import Data.Binary.Helpers
open import Agda.Builtin.Strict

force : š”¹ → š”¹
force 0ᵇ = 0ᵇ
force (1ᵇ xs) = primForce (force xs) 1ᵇ_
force (2ᵇ xs) = primForce (force xs) 2ᵇ_

inc′ : š”¹ → š”¹
inc′ 0ᵇ = 1ᵇ 0ᵇ
inc′ (1ᵇ xs) = 2ᵇ xs
inc′ (2ᵇ xs) = primForce (inc′ xs) 1ᵇ_

up-to : ā„• → List š”¹
up-to = go 0ᵇ
  where
  go : š”¹ → ā„• → List š”¹
  go i zero    = []
  go i (suc n) = primForce i Ī» i → i ∷ go (inc′ i) n

up-to′ : ā„• → List ā„•
up-to′ = go zero
  where
  go : ā„• → ā„• → List ā„•
  go i zero = []
  go i (suc n) = i ∷ go (suc i) n

module _ {A : Set} (f : A → A → A) where
  comb′ : A → List A → List A → List A
  comb′ x []       zs = zs
  comb′ x (y ∷ ys) zs = f x y ∷ comb′ x ys zs

  comb : List A → List A → List A
  comb []       ys = []
  comb (x ∷ xs) ys = comb′ x ys (comb xs ys)

forces : List š”¹ → List š”¹
forces [] = []
forces (x ∷ xs) = primForce (force x) Ī» x′ → primForce (forces xs) Ī» xs′ → x′ ∷ xs′

open import Data.Binary.Conversion.Fast
open import Data.Binary.Properties.Helpers using (_≔_; refl) public
open import Agda.Builtin.Bool using (true)

perf-test : (š”¹ → š”¹ → š”¹) → ā„• → Set
perf-test f n = true ≔ primForce (forces (comb f (up-to n) (up-to n))) (Ī» _ → true) 

map : {A B : Set} → (A → B) → List A → List B
map _ [] = []
map f (x ∷ xs) = f x ∷ map f xs

test : (š”¹ → š”¹ → š”¹) → (ā„• → ā„• → ā„•) → ā„• → Set
test f g n =
  let xs = comb f (up-to n) (up-to n)
      ys = comb g (up-to′ n) (up-to′ n)
  in xs ≔ forces (map ⟦_ā‡‘āŸ§ ys)