-
Notifications
You must be signed in to change notification settings - Fork 847
Add internal block type for use in the compiler. IncrementalBuilder only maintains two states
#11750
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add internal block type for use in the compiler. IncrementalBuilder only maintains two states
#11750
Changes from all commits
bf5d851
27b1e6a
dce6baa
33b6493
a83952a
0a78706
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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 | ||
TIHan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| 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() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing capacity <- count or ToImmutable here, as capacity could be anything.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this is fine.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I completely missed the the length summing loop, yep it's fine! |
||
|
|
||
| let forall predicate (arr: block<'T>) = | ||
TIHan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| 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) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Test for empty initially |
||
| 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 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you don't know the length it doesn't matter too much if you do ToImmutable. You'll do a copy by changing capacity anyway.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Changing the capacity will only copy if the count is different.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair enough :) |
||
| builder.MoveToImmutable() | ||
|
|
||
| let isEmpty (arr: block<_>) = arr.IsEmpty | ||
|
|
||
| let fold folder state (arr: block<_>) = | ||
| let f = OptimizedClosures.FSharpFunc<_, _, _>.Adapt(folder) | ||
TIHan marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| let mutable state = state | ||
| for i = 0 to arr.Length - 1 do | ||
| state <- f.Invoke(state, arr.[i]) | ||
| state | ||
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -604,3 +604,4 @@ module ArrayParallel = | |
|
|
||
| let inline map f (arr: 'T []) = | ||
| arr |> mapi (fun _ item -> f item) | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.