11/// <summary >
2- /// Parallel algorithms over arrays for the functions of <see cref =" T:Microsoft.FSharp.Collections.ArrayModule.Parallel " />
3- /// that take or return options or reference tuples (ADR 0001, D3 and D11).
2+ /// Parallel algorithms over arrays for the functions of
3+ /// <see cref =" T:Microsoft.FSharp.Collections.ArrayModule.Parallel " /> that take or return options or reference tuples
4+ /// (ADR 0001, D3 and D11).
45/// </summary >
56/// <remarks >
6- /// The algorithms take value options and tuple constructors instead, so that the default modules and the <c >Tuple</c > modules
7- /// share them and nothing is allocated per element. The callers check their arguments first, with the exceptions of
8- /// <see cref =" T:Microsoft.FSharp.Collections.ArrayModule.Parallel " />.
7+ /// <para >
8+ /// The default functions of <see cref =" T:FSharp.Collections.Immutable.FlatList " /> take and return value options and struct
9+ /// tuples, and the functions of the <see cref =" T:FSharp.Collections.Immutable.Tuple.FlatList " /> module return reference
10+ /// tuples, where the FSharp.Core functions take and return options and return reference tuples. Calling the FSharp.Core
11+ /// function and converting would allocate for every element. The algorithms here take value options and tuple constructors
12+ /// instead, so that the default modules and the modules of the <see cref =" N:FSharp.Collections.Immutable.Tuple " /> namespace
13+ /// share them and nothing is allocated per element.
14+ /// </para >
15+ /// <para >
16+ /// The callers check their arguments first, with the exceptions of
17+ /// <see cref =" T:Microsoft.FSharp.Collections.ArrayModule.Parallel " />, so the algorithms check nothing and document no
18+ /// exceptions.
19+ /// </para >
20+ /// <para >
21+ /// The summary of each function that mirrors a function of the FSharp.Core
22+ /// <see cref =" T:Microsoft.FSharp.Collections.ArrayModule.Parallel " /> module is the summary of that function word for word
23+ /// (FSharp.Core 10.1), with <c >ValueSome</c > and <c >ValueNone</c > where it says <c >Some</c > and <c >None</c >, and so are the
24+ /// descriptions of the parameters and of the result where the signatures agree. The remarks say what differs and why the
25+ /// function exists.
26+ /// </para >
927/// </remarks >
1028module internal FSharp.Collections.Immutable.ParallelArrays
1129
@@ -18,6 +36,9 @@ open System.Threading.Tasks
1836/// The chunks of a chunked parallel loop over <paramref name =" length " /> elements on <paramref name =" processors " />
1937/// processors, each as its first index and the index after its last one.
2038/// </summary >
39+ /// <param name =" processors " >The number of processors.</param >
40+ /// <param name =" length " >The number of elements.</param >
41+ /// <returns >The chunks, each as a struct tuple of its first index and the index after its last one.</returns >
2142/// <remarks >
2243/// <para >
2344/// The chunks are those of the chunked loops of <see cref =" T:Microsoft.FSharp.Collections.ArrayModule.Parallel " />: one chunk
@@ -29,6 +50,11 @@ open System.Threading.Tasks
2950/// of a chunk adds only the elements that remain to its first index, because the first index plus the full chunk length
3051/// can overflow for arrays near the maximum length on machines with more than 56 processors.
3152/// </para >
53+ /// <para >
54+ /// FSharp.Core has no such function in its public API. It is a function of its own, so that
55+ /// <see cref =" M:FSharp.Collections.Immutable.ParallelArrays.forEachChunk(System.Int32,Microsoft.FSharp.Core.FSharpFunc{System.Int32,Microsoft.FSharp.Core.FSharpFunc{System.Int32,Microsoft.FSharp.Core.Unit}}) " />
56+ /// and the tests share it, and the tests can check the arithmetic for lengths that no array can have.
57+ /// </para >
3258/// </remarks >
3359let chunks ( processors : int ) ( length : int ) : struct ( int * int ) array =
3460 let chunk =
@@ -48,9 +74,17 @@ let chunks (processors : int) (length : int) : struct (int * int) array =
4874/// <summary >
4975/// Runs an action on the chunks of the indices from 0 to <paramref name =" length " /> in parallel.
5076/// </summary >
77+ /// <param name =" length " >The number of elements.</param >
78+ /// <param name =" action " >The action, which takes the first index of its chunk and the index after its last one.</param >
5179/// <remarks >
52- /// The action takes the first index of its chunk and the index after its last one. A loop per chunk calls no delegate per
53- /// element.
80+ /// <para >
81+ /// A loop per chunk calls no delegate per element.
82+ /// </para >
83+ /// <para >
84+ /// FSharp.Core has no such function in its public API. It exists because a
85+ /// <see cref =" M:System.Threading.Tasks.Parallel.For(System.Int32,System.Int32,System.Action{System.Int32}) " /> over the
86+ /// indices calls a delegate for every element, where the action of a chunk is inlined and loops over its indices.
87+ /// </para >
5488/// </remarks >
5589let inline forEachChunk ( length : int ) ( [<InlineIfLambda>] action : int -> int -> unit ) =
5690 let bounds = chunks Environment.ProcessorCount length
@@ -65,13 +99,26 @@ let inline forEachChunk (length : int) ([<InlineIfLambda>] action : int -> int -
6599 |> ignore
66100
67101/// <summary >
68- /// The values that the chooser returns for the elements, in the order of the elements.
102+ /// Apply the given function to each element of the array. Return the array comprised of the results <c >x</c > for each
103+ /// element where the function returns <c >ValueSome x</c >.
69104/// </summary >
105+ /// <param name =" chooser " >The function to generate value options from the elements.</param >
106+ /// <param name =" array " >The input array.</param >
107+ /// <returns >The array of results.</returns >
70108/// <remarks >
71- /// The chooser runs in parallel into an array of value options, which a sequential pass compacts. Calling
109+ /// <para >
110+ /// Performs the operation in parallel using <see cref =" M:System.Threading.Tasks.Parallel.For " />. The order in which the
111+ /// given function is applied to elements of the input array is not specified. This is an O(n) operation, where n is the
112+ /// length of the array.
113+ /// </para >
114+ /// <para >
115+ /// It exists because
72116/// <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.Parallel.Choose``2(Microsoft.FSharp.Core.FSharpFunc{``0,Microsoft.FSharp.Core.FSharpOption{``1}},``0[]) " />
73- /// instead would convert every value option to an option.
117+ /// takes a chooser that returns options, and would convert every value option to an option. The chooser runs in parallel
118+ /// into an array of value options, which a sequential pass compacts.
119+ /// </para >
74120/// </remarks >
121+ /// <seealso cref =" M:FSharp.Collections.Immutable.FlatList.Parallel.Choose``2(Microsoft.FSharp.Core.FSharpFunc{``0,Microsoft.FSharp.Core.FSharpValueOption{``1}},System.Collections.Immutable.ImmutableArray{``0}) " />
75122let choose ( chooser : 'T -> 'U voption ) ( array : 'T array ) : 'U array =
76123 let chosen = Array.Parallel.map chooser array
77124 let mutable count = 0
@@ -95,6 +142,10 @@ let choose (chooser : 'T -> 'U voption) (array : 'T array) : 'U array =
95142/// <summary >
96143/// The comparer of the keys of a parallel grouping.
97144/// </summary >
145+ /// <returns >
146+ /// The comparer of F# structural equality, except that the keys of the types <see cref =" T:System.Double " /> and
147+ /// <see cref =" T:System.Single " /> compare with <see cref =" M:Microsoft.FSharp.Core.LanguagePrimitives.GenericEqualityER``1(``0,``0) " />.
148+ /// </returns >
98149/// <remarks >
99150/// <para >
100151/// Keys of type <see cref =" T:System.Double " /> and <see cref =" T:System.Single " /> compare as in
@@ -108,6 +159,11 @@ let choose (chooser : 'T -> 'U voption) (array : 'T array) : 'U array =
108159/// The function of FSharp.Core throws <see cref =" T:System.AggregateException " /> for such a key: its second pass cannot find
109160/// the key that its first pass added. That failure is not mirrored.
110161/// </para >
162+ /// <para >
163+ /// FSharp.Core has no such function in its public API. It exists because the grouping here runs over the keys with
164+ /// <see cref =" M:System.Linq.Enumerable.ToLookup``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1}) " />,
165+ /// which takes the comparer of the keys, and the comparer has to be that of FSharp.Core.
166+ /// </para >
111167/// </remarks >
112168let groupingComparer < 'Key when 'Key : equality > () : IEqualityComparer < 'Key > =
113169 if
@@ -119,18 +175,35 @@ let groupingComparer<'Key when 'Key : equality> () : IEqualityComparer<'Key> =
119175 HashIdentity.Structural< 'Key>
120176
121177/// <summary >
122- /// The keys of the projection, each with its elements; the order of both is not specified.
178+ /// Applies a key-generating function to each element of an array in parallel and yields an array of unique keys. Each
179+ /// unique key contains an array of all elements that match to this key.
123180/// </summary >
181+ /// <param name =" tuple " >The function that builds an element of the result from a key and the array of its elements.</param >
182+ /// <param name =" projection " >A function that transforms an element of the array into a comparable key.</param >
183+ /// <param name =" array " >The input array.</param >
184+ /// <returns >The result array.</returns >
124185/// <remarks >
125- /// The projection, the work of the caller, runs in parallel. The grouping then runs over the computed keys with
186+ /// <para >
187+ /// Performs the operation in parallel using <see cref =" M:System.Threading.Tasks.Parallel.For " />. The order in which the
188+ /// given function is applied to elements of the input array is not specified. The order of the keys and values in the
189+ /// result is also not specified. This is an O(n) operation, where n is the length of the array.
190+ /// </para >
191+ /// <para >
192+ /// It exists because
193+ /// <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.Parallel.GroupBy``2(Microsoft.FSharp.Core.FSharpFunc{``0,``1},``0[]) " />
194+ /// returns reference tuples. The projection, the work of the caller, runs in parallel. The grouping then runs over the
195+ /// computed keys with
126196/// <see cref =" M:System.Linq.Enumerable.ToLookup``3(System.Collections.Generic.IEnumerable{``0},System.Func{``0,``1},System.Func{``0,``2},System.Collections.Generic.IEqualityComparer{``1}) " />
127197/// and the comparer of <see cref =" M:FSharp.Collections.Immutable.ParallelArrays.groupingComparer``1 " />, so that a
128198/// <see langword =" null " /> key is a key like any other. The result has the order of
129199/// <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.GroupBy``2(Microsoft.FSharp.Core.FSharpFunc{``0,``1},``0[]) " />,
130200/// one of the orders that
131201/// <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.Parallel.GroupBy``2(Microsoft.FSharp.Core.FSharpFunc{``0,``1},``0[]) " />
132202/// allows.
203+ /// </para >
133204/// </remarks >
205+ /// <seealso cref =" M:FSharp.Collections.Immutable.FlatList.Parallel.GroupBy``2(Microsoft.FSharp.Core.FSharpFunc{``0,``1},System.Collections.Immutable.ImmutableArray{``0}) " />
206+ /// <seealso cref =" M:FSharp.Collections.Immutable.Tuple.FlatList.Parallel.GroupBy``2(Microsoft.FSharp.Core.FSharpFunc{``0,``1},System.Collections.Immutable.ImmutableArray{``0}) " />
134207let inline groupBy
135208 ( [<InlineIfLambda>] tuple : 'Key -> 'T array -> 'R )
136209 ( projection : 'T -> 'Key )
@@ -153,13 +226,26 @@ let inline groupBy
153226 result
154227
155228/// <summary >
156- /// The index of the first element that satisfies the predicate, or <c >ValueNone</c >.
229+ /// Returns the index of the first element in the array that satisfies the given predicate. Returns <c >ValueNone</c > if no
230+ /// such element exists.
157231/// </summary >
232+ /// <param name =" predicate " >The function to test the input elements.</param >
233+ /// <param name =" array " >The input array.</param >
234+ /// <returns >The index of the first element that satisfies the predicate, or <c >ValueNone</c >.</returns >
158235/// <remarks >
159- /// The predicate runs in parallel. A match breaks the loop, which then starts only the elements before it, and the lowest
160- /// index that broke the loop wins, as in
161- /// <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.Parallel.TryFindIndex``1(Microsoft.FSharp.Core.FSharpFunc{``0,System.Boolean},``0[]) " />.
236+ /// <para >
237+ /// This is an O(n) operation in the worst case, where n is the length of the array.
238+ /// </para >
239+ /// <para >
240+ /// It exists because
241+ /// <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.Parallel.TryFindIndex``1(Microsoft.FSharp.Core.FSharpFunc{``0,System.Boolean},``0[]) " />
242+ /// returns an option, where the default functions return a value option. The predicate runs in parallel. A match breaks the
243+ /// loop, which then starts only the elements before it, and the lowest index that broke the loop wins, as in the function
244+ /// of FSharp.Core.
245+ /// </para >
162246/// </remarks >
247+ /// <seealso cref =" M:FSharp.Collections.Immutable.FlatList.Parallel.TryFindIndex``1(Microsoft.FSharp.Core.FSharpFunc{``0,System.Boolean},System.Collections.Immutable.ImmutableArray{``0}) " />
248+ /// <seealso cref =" M:FSharp.Collections.Immutable.FlatList.Parallel.TryFind``1(Microsoft.FSharp.Core.FSharpFunc{``0,System.Boolean},System.Collections.Immutable.ImmutableArray{``0}) " />
163249let tryFindIndex ( predicate : 'T -> bool ) ( array : 'T array ) : int voption =
164250 let result =
165251 Parallel.For (
@@ -178,15 +264,27 @@ let tryFindIndex (predicate : 'T -> bool) (array : 'T array) : int voption =
178264 ValueNone
179265
180266/// <summary >
181- /// The value that the chooser returns for the first element with a value, or <c >ValueNone</c >.
267+ /// Applies the given function to successive elements, returning the first result where the function returns
268+ /// <c >ValueSome x</c > for some <c >x</c >. If the function never returns <c >ValueSome x</c > then <c >ValueNone</c > is
269+ /// returned.
182270/// </summary >
271+ /// <param name =" chooser " >The function to transform the array elements into value options.</param >
272+ /// <param name =" array " >The input array.</param >
273+ /// <returns >The first transformed element that is <c >ValueSome x</c >.</returns >
183274/// <remarks >
184- /// The chooser runs in parallel. A value breaks the loop, which then starts only the elements before it, and the value of
185- /// the lowest index wins. The function of FSharp.Core,
186- /// <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.Parallel.TryPick``2(Microsoft.FSharp.Core.FSharpFunc{``0,Microsoft.FSharp.Core.FSharpOption{``1}},``0[]) " />,
187- /// keeps every value in a concurrent dictionary by index; here a lock guards the value of the lowest index so far, and
188- /// only the elements that have a value take it.
275+ /// <para >
276+ /// This is an O(n) operation in the worst case, where n is the length of the array.
277+ /// </para >
278+ /// <para >
279+ /// It exists because
280+ /// <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.Parallel.TryPick``2(Microsoft.FSharp.Core.FSharpFunc{``0,Microsoft.FSharp.Core.FSharpOption{``1}},``0[]) " />
281+ /// takes a chooser that returns options, where the default functions use value options. The chooser runs in parallel. A
282+ /// value breaks the loop, which then starts only the elements before it, and the value of the lowest index wins. The
283+ /// function of FSharp.Core keeps every value in a concurrent dictionary by index; here a lock guards the value of the
284+ /// lowest index so far, and only the elements that have a value take it.
285+ /// </para >
189286/// </remarks >
287+ /// <seealso cref =" M:FSharp.Collections.Immutable.FlatList.Parallel.TryPick``2(Microsoft.FSharp.Core.FSharpFunc{``0,Microsoft.FSharp.Core.FSharpValueOption{``1}},System.Collections.Immutable.ImmutableArray{``0}) " />
190288let tryPick ( chooser : 'T -> 'U voption ) ( array : 'T array ) : 'U voption =
191289 let gate = obj ()
192290 let lowest = ref Int32.MaxValue
@@ -214,11 +312,26 @@ let tryPick (chooser : 'T -> 'U voption) (array : 'T array) : 'U voption =
214312 chosen.Value
215313
216314/// <summary >
217- /// Pairs the elements of two arrays of the same length in parallel.
315+ /// Combines the two arrays into an array of pairs. The two arrays must have equal lengths, otherwise an
316+ /// <see cref =" T:System.ArgumentException " /> is raised.
218317/// </summary >
318+ /// <param name =" tuple " >The function that builds an element of the result from the elements at the same index.</param >
319+ /// <param name =" array1 " >The first input array.</param >
320+ /// <param name =" array2 " >The second input array.</param >
321+ /// <returns >The array of tupled elements.</returns >
219322/// <remarks >
220- /// The chunks are those of <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.Parallel.Zip``2(``0[],``1[]) " />.
323+ /// <para >
324+ /// This is an O(n) operation, where n is the length of the arrays. The chunks are those of
325+ /// <see cref =" M:Microsoft.FSharp.Collections.ArrayModule.Parallel.Zip``2(``0[],``1[]) " />. The callers check the lengths first
326+ /// and raise its exception.
327+ /// </para >
328+ /// <para >
329+ /// It exists because that function returns reference tuples, which allocate for every element, where the default function
330+ /// returns struct tuples.
331+ /// </para >
221332/// </remarks >
333+ /// <seealso cref =" M:FSharp.Collections.Immutable.FlatList.Parallel.Zip``2(System.Collections.Immutable.ImmutableArray{``0},System.Collections.Immutable.ImmutableArray{``1}) " />
334+ /// <seealso cref =" M:FSharp.Collections.Immutable.Tuple.FlatList.Parallel.Zip``2(System.Collections.Immutable.ImmutableArray{``0},System.Collections.Immutable.ImmutableArray{``1}) " />
222335let inline zip ( [<InlineIfLambda>] tuple : 'T1 -> 'T2 -> 'R ) ( array1 : 'T1 array ) ( array2 : 'T2 array ) : 'R array =
223336 let result = Array.zeroCreate array1.Length
224337
0 commit comments