lean4-htt/library/init/data/rbmap/basic.lean
Leonardo de Moura 1815331828 perf(library/init/data): add @[specialize] to RBMap and RBTree functions that depend on lt : a -> a -> Bool
A few commits ago, a few `RBMap` and `RBTree` functions had
the parameters `(lt : a -> a -> Prop) [DecidableRel lt]` instead of
`(lt : a -> a -> Bool)`. Recall that the compiler automatically specializes
functions with arguments of the form `[ ... ]`. Thus, after we moved to
`(lt : a -> a -> Bool)` we have to include `@[specialize]` to force the
compiler to specialize.
2019-04-03 09:16:34 -07:00

227 lines
8.1 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/-
Copyright (c) 2017 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import init.data.repr init.data.option.basic
universes u v w w'
inductive Rbcolor
| red | black
inductive RBNode (α : Type u) (β : α → Type v)
| leaf {} : RBNode
| node (color : Rbcolor) (lchild : RBNode) (key : α) (val : β key) (rchild : RBNode) : RBNode
namespace RBNode
variables {α : Type u} {β : α → Type v} {σ : Type w}
open Rbcolor Nat
def depth (f : Nat → Nat → Nat) : RBNode α β → Nat
| leaf := 0
| (node _ l _ _ r) := succ (f (depth l) (depth r))
protected def min : RBNode α β → Option (Σ k : α, β k)
| leaf := none
| (node _ leaf k v _) := some ⟨k, v⟩
| (node _ l k v _) := min l
protected def max : RBNode α β → Option (Σ k : α, β k)
| leaf := none
| (node _ _ k v leaf) := some ⟨k, v⟩
| (node _ _ k v r) := max r
@[specialize] def fold (f : σ → Π (k : α), β k → σ) : σ → RBNode α β → σ
| b leaf := b
| b (node _ l k v r) := fold (f (fold b l) k v) r
@[specialize] def mfold {m : Type w → Type w'} [Monad m] (f : σ → Π (k : α), β k → m σ) : σ → RBNode α β → m σ
| b leaf := pure b
| b (node _ l k v r) := do
b ← mfold b l,
b ← f b k v,
mfold b r
@[specialize] def revFold (f : σ → Π (k : α), β k → σ) : σ → RBNode α β → σ
| b leaf := b
| b (node _ l k v r) := revFold (f (revFold b r) k v) l
@[specialize] def all (p : Π k : α, β k → Bool) : RBNode α β → Bool
| leaf := true
| (node _ l k v r) := p k v && all l && all r
@[specialize] def any (p : Π k : α, β k → Bool) : RBNode α β → Bool
| leaf := false
| (node _ l k v r) := p k v || any l || any r
def singleton (k : α) (v : β k) : RBNode α β :=
node red leaf k v leaf
def balance1 : RBNode α β → RBNode α β → RBNode α β
| (node _ _ kv vv t) (node _ (node red l kx vx r₁) ky vy r₂) := node red (node black l kx vx r₁) ky vy (node black r₂ kv vv t)
| (node _ _ kv vv t) (node _ l₁ ky vy (node red l₂ kx vx r)) := node red (node black l₁ ky vy l₂) kx vx (node black r kv vv t)
| (node _ _ kv vv t) (node _ l ky vy r) := node black (node red l ky vy r) kv vv t
| _ _ := leaf -- unreachable
def balance2 : RBNode α β → RBNode α β → RBNode α β
| (node _ t kv vv _) (node _ (node red l kx₁ vx₁ r₁) ky vy r₂) := node red (node black t kv vv l) kx₁ vx₁ (node black r₁ ky vy r₂)
| (node _ t kv vv _) (node _ l₁ ky vy (node red l₂ kx₂ vx₂ r₂)) := node red (node black t kv vv l₁) ky vy (node black l₂ kx₂ vx₂ r₂)
| (node _ t kv vv _) (node _ l ky vy r) := node black t kv vv (node red l ky vy r)
| _ _ := leaf -- unreachable
def isRed : RBNode α β → Bool
| (node red _ _ _ _) := true
| _ := false
section insert
variables (lt : αα → Bool)
@[specialize] def ins : RBNode α β → Π k : α, β k → RBNode α β
| leaf kx vx := node red leaf kx vx leaf
| (node red a ky vy b) kx vx :=
if lt kx ky then node red (ins a kx vx) ky vy b
else if lt ky kx then node red a ky vy (ins b kx vx)
else node red a kx vx b
| (node black a ky vy b) kx vx :=
if lt kx ky then
if isRed a then balance1 (node black leaf ky vy b) (ins a kx vx)
else node black (ins a kx vx) ky vy b
else if lt ky kx then
if isRed b then balance2 (node black a ky vy leaf) (ins b kx vx)
else node black a ky vy (ins b kx vx)
else
node black a kx vx b
def setBlack : RBNode α β → RBNode α β
| (node _ l k v r) := node black l k v r
| e := e
@[inline] def insert (t : RBNode α β) (k : α) (v : β k) : RBNode α β :=
if isRed t then setBlack (ins lt t k v)
else ins lt t k v
end insert
section membership
variable (lt : αα → Bool)
@[specialize] def findCore : RBNode α β → Π k : α, Option (Σ k : α, β k)
| leaf x := none
| (node _ a ky vy b) x :=
if lt x ky then findCore a x
else if lt ky x then findCore b x
else some ⟨ky, vy⟩
@[specialize] def find {β : Type v} : RBNode α (λ _, β) → α → Option β
| leaf x := none
| (node _ a ky vy b) x :=
if lt x ky then find a x
else if lt ky x then find b x
else some vy
@[specialize] def lowerBound : RBNode α β → α → Option (Sigma β) → Option (Sigma β)
| leaf x lb := lb
| (node _ a ky vy b) x lb :=
if lt x ky then lowerBound a x lb
else if lt ky x then lowerBound b x (some ⟨ky, vy⟩)
else some ⟨ky, vy⟩
end membership
inductive WellFormed (lt : αα → Bool) : RBNode α β → Prop
| leafWff : WellFormed leaf
| insertWff {n n' : RBNode α β} {k : α} {v : β k} : WellFormed n → n' = insert lt n k v → WellFormed n'
end RBNode
open RBNode
/- TODO(Leo): define dRBMap -/
def RBMap (α : Type u) (β : Type v) (lt : αα → Bool) : Type (max u v) :=
{t : RBNode α (λ _, β) // t.WellFormed lt }
@[inline] def mkRBMap (α : Type u) (β : Type v) (lt : αα → Bool) : RBMap α β lt :=
⟨leaf, WellFormed.leafWff lt⟩
instance (α : Type u) (β : Type v) (lt : αα → Bool) : HasEmptyc (RBMap α β lt) :=
⟨mkRBMap α β lt⟩
namespace RBMap
variables {α : Type u} {β : Type v} {σ : Type w} {lt : αα → Bool}
def depth (f : Nat → Nat → Nat) (t : RBMap α β lt) : Nat :=
t.val.depth f
@[inline] def fold (f : σα → β → σ) : σ → RBMap α β lt → σ
| b ⟨t, _⟩ := t.fold f b
@[inline] def revFold (f : σα → β → σ) : σ → RBMap α β lt → σ
| b ⟨t, _⟩ := t.revFold f b
@[inline] def mfold {m : Type w → Type w'} [Monad m] (f : σα → β → m σ) : σ → RBMap α β lt → m σ
| b ⟨t, _⟩ := t.mfold f b
@[inline] def mfor {m : Type w → Type w'} [Monad m] (f : α → β → m σ) (t : RBMap α β lt) : m PUnit :=
t.mfold (λ _ k v, f k v *> pure ⟨⟩) ⟨⟩
@[inline] def isEmpty : RBMap α β lt → Bool
| ⟨leaf, _⟩ := true
| _ := false
@[specialize] def toList : RBMap α β lt → List (α × β)
| ⟨t, _⟩ := t.revFold (λ ps k v, (k, v)::ps) []
@[inline] protected def min : RBMap α β lt → Option (α × β)
| ⟨t, _⟩ :=
match t.min with
| some ⟨k, v⟩ := some (k, v)
| none := none
@[inline] protected def max : RBMap α β lt → Option (α × β)
| ⟨t, _⟩ :=
match t.max with
| some ⟨k, v⟩ := some (k, v)
| none := none
instance [HasRepr α] [HasRepr β] : HasRepr (RBMap α β lt) :=
⟨λ t, "rbmapOf " ++ repr t.toList⟩
@[inline] def insert : RBMap α β lt → α → β → RBMap α β lt
| ⟨t, w⟩ k v := ⟨t.insert lt k v, WellFormed.insertWff w rfl⟩
@[specialize] def ofList : List (α × β) → RBMap α β lt
| [] := mkRBMap _ _ _
| (⟨k,v⟩::xs) := (ofList xs).insert k v
@[inline] def findCore : RBMap α β lt → α → Option (Σ k : α, β)
| ⟨t, _⟩ x := t.findCore lt x
@[inline] def find : RBMap α β lt → α → Option β
| ⟨t, _⟩ x := t.find lt x
/-- (lowerBound k) retrieves the kv pair of the largest key smaller than or equal to `k`,
if it exists. -/
@[inline] def lowerBound : RBMap α β lt → α → Option (Σ k : α, β)
| ⟨t, _⟩ x := t.lowerBound lt x none
@[inline] def contains (t : RBMap α β lt) (a : α) : Bool :=
(t.find a).isSome
@[inline] def fromList (l : List (α × β)) (lt : αα → Bool) : RBMap α β lt :=
l.foldl (λ r p, r.insert p.1 p.2) (mkRBMap α β lt)
@[inline] def all : RBMap α β lt → (α → β → Bool) → Bool
| ⟨t, _⟩ p := t.all p
@[inline] def any : RBMap α β lt → (α → β → Bool) → Bool
| ⟨t, _⟩ p := t.any p
end RBMap
def rbmapOf {α : Type u} {β : Type v} (l : List (α × β)) (lt : αα → Bool) : RBMap α β lt :=
RBMap.fromList l lt