Skip to content

Commit

Permalink
Add internal block type for use in the compiler. `IncrementalBuilde…
Browse files Browse the repository at this point in the history
…r` only maintains two states (#11750)

* Added IncrementalBuilderInitialState

* More changes

* Added internal 'block' type for use in the compiler. Lifting functions out of IncrementalBuilder

* using block

* Block feedback

* Use IsEmpty
  • Loading branch information
TIHan authored Jul 2, 2021
1 parent 9cbbf4c commit a85aac5
Show file tree
Hide file tree
Showing 7 changed files with 502 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,12 @@
<Compile Include="..\lib.fs">
<Link>Utilities\lib.fs</Link>
</Compile>
<Compile Include="..\block.fsi">
<Link>Utilities\block.fsi</Link>
</Compile>
<Compile Include="..\block.fs">
<Link>Utilities\block.fs</Link>
</Compile>
<Compile Include="..\rational.fsi">
<Link>Utilities\rational.fsi</Link>
</Compile>
Expand Down
187 changes: 187 additions & 0 deletions src/fsharp/block.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
module Internal.Utilities.Library.Block

open System.Collections.Immutable

type block<'T> = ImmutableArray<'T>
type blockbuilder<'T> = ImmutableArray<'T>.Builder

[<RequireQualifiedAccess>]
module BlockBuilder =

let create size : blockbuilder<'T> =
ImmutableArray.CreateBuilder(size)

[<RequireQualifiedAccess>]
module Block =

[<GeneralizableValue>]
let empty<'T> = ImmutableArray<'T>.Empty

let init n (f: int -> 'T) : block<_> =
match n with
| 0 -> ImmutableArray.Empty
| 1 -> ImmutableArray.Create(f 0)
| n ->
if n < 0 then
invalidArg "n" "Below zero."

let builder = ImmutableArray.CreateBuilder(n)
for i = 0 to n - 1 do
builder.Add(f i)
builder.MoveToImmutable()

let iter f (arr: block<'T>) =
for i = 0 to arr.Length - 1 do
f arr.[i]

let iteri f (arr: block<'T>) =
for i = 0 to arr.Length - 1 do
f i arr.[i]

let iter2 f (arr1: block<'T1>) (arr2: block<'T2>) =
if arr1.Length <> arr2.Length then
invalidOp "Block lengths do not match."

for i = 0 to arr1.Length - 1 do
f arr1.[i] arr2.[i]

let iteri2 f (arr1: block<'T1>) (arr2: block<'T2>) =
if arr1.Length <> arr2.Length then
invalidOp "Block lengths do not match."

for i = 0 to arr1.Length - 1 do
f i arr1.[i] arr2.[i]

let map (mapper: 'T -> 'U) (arr: block<'T>) : block<_> =
match arr.Length with
| 0 -> ImmutableArray.Empty
| 1 -> ImmutableArray.Create(mapper arr.[0])
| _ ->
let builder = ImmutableArray.CreateBuilder(arr.Length)
for i = 0 to arr.Length - 1 do
builder.Add(mapper arr.[i])
builder.MoveToImmutable()

let mapi (mapper: int -> 'T -> 'U) (arr: block<'T>) : block<_> =
match arr.Length with
| 0 -> ImmutableArray.Empty
| 1 -> ImmutableArray.Create(mapper 0 arr.[0])
| _ ->
let builder = ImmutableArray.CreateBuilder(arr.Length)
for i = 0 to arr.Length - 1 do
builder.Add(mapper i arr.[i])
builder.MoveToImmutable()

let map2 (mapper: 'T1 -> 'T2 -> 'T) (arr1: block<'T1>) (arr2: block<'T2>) : block<_> =
if arr1.Length <> arr2.Length then
invalidOp "Block lengths do not match."

match arr1.Length with
| 0 -> ImmutableArray.Empty
| 1 -> ImmutableArray.Create(mapper arr1.[0] arr2.[0])
| n ->
let builder = ImmutableArray.CreateBuilder(n)
for i = 0 to n - 1 do
builder.Add(mapper arr1.[i] arr2.[i])
builder.MoveToImmutable()

let mapi2 (mapper: int -> 'T1 -> 'T2 -> 'T) (arr1: block<'T1>) (arr2: block<'T2>) : block<_> =
if arr1.Length <> arr2.Length then
invalidOp "Block lengths do not match."

match arr1.Length with
| 0 -> ImmutableArray.Empty
| 1 -> ImmutableArray.Create(mapper 0 arr1.[0] arr2.[0])
| n ->
let builder = ImmutableArray.CreateBuilder(n)
for i = 0 to n - 1 do
builder.Add(mapper i arr1.[i] arr2.[i])
builder.MoveToImmutable()

let concat (arrs: block<block<'T>>) : block<'T> =
match arrs.Length with
| 0 -> ImmutableArray.Empty
| 1 -> arrs.[0]
| 2 -> arrs.[0].AddRange(arrs.[1])
| _ ->
let mutable acc = 0
for h in arrs do
acc <- acc + h.Length

let builder = ImmutableArray.CreateBuilder(acc)
for i = 0 to arrs.Length - 1 do
builder.AddRange(arrs.[i])
builder.MoveToImmutable()

let forall predicate (arr: block<'T>) =
let len = arr.Length
let rec loop i = i >= len || (predicate arr.[i] && loop (i+1))
loop 0

let forall2 predicate (arr1: block<'T1>) (arr2: block<'T2>) =
if arr1.Length <> arr2.Length then
invalidOp "Block lengths do not match."

let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(predicate)
let len1 = arr1.Length
let rec loop i = i >= len1 || (f.Invoke(arr1.[i], arr2.[i]) && loop (i+1))
loop 0

let tryFind predicate (arr: block<'T>) =
let rec loop i =
if i >= arr.Length then None else
if predicate arr.[i] then Some arr.[i] else loop (i+1)
loop 0

let tryFindIndex predicate (arr: block<'T>) =
let len = arr.Length
let rec go n = if n >= len then None elif predicate arr.[n] then Some n else go (n+1)
go 0

let tryPick chooser (arr: block<'T>) =
let rec loop i =
if i >= arr.Length then None else
match chooser arr.[i] with
| None -> loop(i+1)
| res -> res
loop 0

let ofSeq (xs: 'T seq) =
ImmutableArray.CreateRange(xs)

let append (arr1: block<'T1>) (arr2: block<'T1>) : block<_> =
arr1.AddRange(arr2)

let createOne (item: 'T) : block<_> =
ImmutableArray.Create(item)

let filter predicate (arr: block<'T>) : block<'T> =
let builder = ImmutableArray.CreateBuilder(arr.Length)
for i = 0 to arr.Length - 1 do
if predicate arr.[i] then
builder.Add(arr.[i])
builder.Capacity <- builder.Count
builder.MoveToImmutable()

let exists predicate (arr: block<'T>) =
let len = arr.Length
let rec loop i = i < len && (predicate arr.[i] || loop (i+1))
len > 0 && loop 0

let choose (chooser: 'T -> 'U option) (arr: block<'T>) : block<'U> =
let builder = ImmutableArray.CreateBuilder(arr.Length)
for i = 0 to arr.Length - 1 do
let result = chooser arr.[i]
if result.IsSome then
builder.Add(result.Value)
builder.Capacity <- builder.Count
builder.MoveToImmutable()

let isEmpty (arr: block<_>) = arr.IsEmpty

let fold folder state (arr: block<_>) =
let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(folder)
let mutable state = state
for i = 0 to arr.Length - 1 do
state <- f.Invoke(state, arr.[i])
state
63 changes: 63 additions & 0 deletions src/fsharp/block.fsi
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
[<AutoOpen>]
module internal Internal.Utilities.Library.Block

open System.Collections.Immutable

/// Type alias for System.Collections.Immutable.ImmutableArray<'T>
type block<'T> = ImmutableArray<'T>

/// Type alias for System.Collections.Immutable.ImmutableArray<'T>.Builder
type blockbuilder<'T> = ImmutableArray<'T>.Builder

[<RequireQualifiedAccess>]
module BlockBuilder =

val create : size: int -> blockbuilder<'T>

[<RequireQualifiedAccess>]
module Block =

[<GeneralizableValue>]
val empty<'T> : block<'T>

val init : n: int -> f: (int -> 'T) -> block<'T>

val iter : f: ('T -> unit) -> block<'T> -> unit

val iteri : f: (int -> 'T -> unit) -> block<'T> -> unit

val iter2 : f: ('T1 -> 'T2 -> unit) -> block<'T1> -> block<'T2> -> unit

val iteri2 : f: (int -> 'T1 -> 'T2 -> unit) -> block<'T1> -> block<'T2> -> unit

val map : mapper: ('T1 -> 'T2) -> block<'T1> -> block<'T2>

val mapi : mapper: (int -> 'T1 -> 'T2) -> block<'T1> -> block<'T2>

val concat : block<block<'T>> -> block<'T>

val forall : predicate: ('T -> bool) -> block<'T> -> bool

val forall2 : predicate: ('T1 -> 'T2 -> bool) -> block<'T1> -> block<'T2> -> bool

val tryFind : predicate: ('T -> bool) -> block<'T> -> 'T option

val tryFindIndex : predicate: ('T -> bool) -> block<'T> -> int option

val tryPick : chooser: ('T1 -> 'T2 option) -> block<'T1> -> 'T2 option

val ofSeq : seq<'T> -> block<'T>

val append : block<'T> -> block<'T> -> block<'T>

val createOne : 'T -> block<'T>

val filter : predicate: ('T -> bool) -> block<'T> -> block<'T>

val exists : predicate: ('T -> bool) -> block<'T> -> bool

val choose : chooser: ('T -> 'U option) -> block<'T> -> block<'U>

val isEmpty : block<'T> -> bool

val fold : folder: ('State -> 'T -> 'State) -> 'State -> block<'T> -> 'State
1 change: 1 addition & 0 deletions src/fsharp/lib.fs
Original file line number Diff line number Diff line change
Expand Up @@ -604,3 +604,4 @@ module ArrayParallel =

let inline map f (arr: 'T []) =
arr |> mapi (fun _ item -> f item)

Loading

0 comments on commit a85aac5

Please sign in to comment.