Skip to content

Commit c05cb79

Browse files
committed
Implement version of Data.Nat.Binary.fromℕ that runs in O(log n)
1 parent f0c53d6 commit c05cb79

File tree

1 file changed

+29
-5
lines changed

1 file changed

+29
-5
lines changed

src/Data/Nat/Binary/Base.agda

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,17 @@
1313
module Data.Nat.Binary.Base where
1414

1515
open import Algebra.Core using (Op₂)
16+
import Data.Fin.Base as Fin
1617
open import Data.Nat.Base as ℕ using (ℕ)
18+
open import Data.Nat.DivMod using (_divMod_; result)
19+
open import Data.Nat.Properties
20+
open import Data.Nat.Induction using (<-rec)
21+
open import Data.Product using (_,_)
1722
open import Data.Sum.Base using (_⊎_)
18-
open import Function.Base using (_on_)
23+
open import Function.Base using (case_of_; _on_; _$_)
1924
open import Level using (0ℓ)
2025
open import Relation.Binary.Core using (Rel)
21-
open import Relation.Binary.PropositionalEquality using (_≡_)
26+
open import Relation.Binary.PropositionalEquality as ≡ using (_≡_)
2227
open import Relation.Nullary using (¬_)
2328

2429
------------------------------------------------------------------------
@@ -112,10 +117,29 @@ toℕ zero = 0
112117
toℕ 2[1+ x ] = 2 ℕ.* (ℕ.suc (toℕ x))
113118
toℕ 1+[2 x ] = ℕ.suc (2 ℕ.* (toℕ x))
114119

115-
-- Costs O(n), could be improved using `_/_` and `_%_`
116120
fromℕ : ℕᵇ
117-
fromℕ 0 = zero
118-
fromℕ (ℕ.suc n) = suc (fromℕ n)
121+
fromℕ = <-rec (λ _ ℕᵇ) λ
122+
{ ℕ.zero _ zero
123+
; (ℕ.suc n) p case n divMod 2 of λ
124+
{ (result q Fin.zero prop)
125+
-- n is even so suc n is odd
126+
1+[2 p q $ ℕ.s≤s $ begin
127+
q ≡˘⟨ *-identityʳ q ⟩
128+
q ℕ.* 1 ≤⟨ *-monoʳ-≤ q (ℕ.s≤s ℕ.z≤n) ⟩
129+
q ℕ.* 2 ≡˘⟨ prop ⟩
130+
n ∎
131+
]
132+
; (result q (Fin.suc Fin.zero) prop)
133+
-- n is odd so suc n is even
134+
2[1+ p q $ ℕ.s≤s $ begin
135+
q ≡˘⟨ *-identityʳ q ⟩
136+
q ℕ.* 1 ≤⟨ *-monoʳ-≤ q (ℕ.s≤s ℕ.z≤n) ⟩
137+
q ℕ.* 2 <⟨ ≤-reflexive (≡.sym prop) ⟩
138+
n ∎
139+
]
140+
}
141+
}
142+
where open ≤-Reasoning
119143

120144
-- An alternative ordering lifted from ℕ
121145

0 commit comments

Comments
 (0)