blob: 341ad4393021c3ff67773de0ae7ed08ecc5974fa [file]
/-
Copyright (c) 2020 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.Array.Basic
universes u v w
structure Subarray (α : Type u) where
as : Array α
start : Nat
stop : Nat
h₁ : start ≤ stop
h₂ : stop ≤ as.size
namespace Subarray
@[inline] unsafe def forInUnsafe {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (s : Subarray α) (b : β) (f : α → β → m (ForInStep β)) : m β :=
let sz := USize.ofNat s.stop
let rec @[specialize] loop (i : USize) (b : β) : m β := do
if i < sz then
let a := s.as.uget i lcProof
match (← f a b) with
| ForInStep.done b => pure b
| ForInStep.yield b => loop (i+1) b
else
pure b
loop (USize.ofNat s.start) b
-- TODO: provide reference implementation
@[implementedBy Subarray.forInUnsafe]
protected constant forIn {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (s : Subarray α) (b : β) (f : α → β → m (ForInStep β)) : m β :=
pure b
instance : ForIn m (Subarray α) α where
forIn := Subarray.forIn
@[inline]
def foldlM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : β → α → m β) (init : β) (as : Subarray α) : m β :=
as.as.foldlM f (init := init) (start := as.start) (stop := as.stop)
@[inline]
def foldrM {α : Type u} {β : Type v} {m : Type v → Type w} [Monad m] (f : α → β → m β) (init : β) (as : Subarray α) : m β :=
as.as.foldrM f (init := init) (start := as.stop) (stop := as.start)
@[inline]
def anyM {α : Type u} {m : Type → Type w} [Monad m] (p : α → m Bool) (as : Subarray α) : m Bool :=
as.as.anyM p (start := as.start) (stop := as.stop)
@[inline]
def allM {α : Type u} {m : Type → Type w} [Monad m] (p : α → m Bool) (as : Subarray α) : m Bool :=
as.as.allM p (start := as.start) (stop := as.stop)
@[inline]
def forM {α : Type u} {m : Type v → Type w} [Monad m] (f : α → m PUnit) (as : Subarray α) : m PUnit :=
as.as.forM f (start := as.start) (stop := as.stop)
@[inline]
def forRevM {α : Type u} {m : Type v → Type w} [Monad m] (f : α → m PUnit) (as : Subarray α) : m PUnit :=
as.as.forRevM f (start := as.stop) (stop := as.start)
@[inline]
def foldl {α : Type u} {β : Type v} (f : β → α → β) (init : β) (as : Subarray α) : β :=
Id.run <| as.foldlM f (init := init)
@[inline]
def foldr {α : Type u} {β : Type v} (f : α → β → β) (init : β) (as : Subarray α) : β :=
Id.run <| as.foldrM f (init := init)
@[inline]
def any {α : Type u} (p : α → Bool) (as : Subarray α) : Bool :=
Id.run <| as.anyM p
@[inline]
def all {α : Type u} (p : α → Bool) (as : Subarray α) : Bool :=
Id.run <| as.allM p
end Subarray
namespace Array
variable {α : Type u}
def toSubarray (as : Array α) (start stop : Nat) : Subarray α :=
if h₂ : stop ≤ as.size then
if h₁ : start ≤ stop then
{ as := as, start := start, stop := stop, h₁ := h₁, h₂ := h₂ }
else
{ as := as, start := stop, stop := stop, h₁ := Nat.leRefl _, h₂ := h₂ }
else
if h₁ : start ≤ as.size then
{ as := as, start := start, stop := as.size, h₁ := h₁, h₂ := Nat.leRefl _ }
else
{ as := as, start := as.size, stop := as.size, h₁ := Nat.leRefl _, h₂ := Nat.leRefl _ }
def ofSubarray (s : Subarray α) : Array α := do
let mut as := mkEmpty (s.stop - s.start)
for a in s do
as := as.push a
return as
def extract (as : Array α) (start stop : Nat) : Array α :=
ofSubarray (as.toSubarray start stop)
instance : Coe (Subarray α) (Array α) := ⟨ofSubarray⟩
syntax:max term noWs "[" term ":" term "]" : term
syntax:max term noWs "[" term ":" "]" : term
syntax:max term noWs "[" ":" term "]" : term
macro_rules
| `($a[$start : $stop]) => `(Array.toSubarray $a $start $stop)
| `($a[ : $stop]) => `(Array.toSubarray $a 0 $stop)
| `($a[$start : ]) => `(let a := $a; Array.toSubarray a $start a.size)
end Array
def Subarray.toArray (s : Subarray α) : Array α :=
Array.ofSubarray s
instance : HAppend (Subarray α) (Subarray α) (Array α) where
hAppend x y := x.toArray ++ y.toArray