Fix overflow checking in PLinq Range operator
[mono-project.git] / mcs / class / System.Core / System.Linq / ParallelEnumerable.cs
blobd85d30c24c664ec234cb3530357cc11afb94a779
1 //
2 // ParallelEnumerable.cs
3 //
4 // Author:
5 // Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
6 //
7 // Copyright (c) 2010 Jérémie "Garuma" Laval
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining a copy
10 // of this software and associated documentation files (the "Software"), to deal
11 // in the Software without restriction, including without limitation the rights
12 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 // copies of the Software, and to permit persons to whom the Software is
14 // furnished to do so, subject to the following conditions:
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25 // THE SOFTWARE.
27 #if NET_4_0
28 using System;
29 using System.Threading;
30 using System.Collections;
31 using System.Collections.Generic;
32 using System.Collections.Concurrent;
33 using System.Linq.Parallel;
34 using System.Linq.Parallel.QueryNodes;
36 namespace System.Linq
38 public static class ParallelEnumerable
40 #region Range & Repeat
41 public static ParallelQuery<int> Range (int start, int count)
43 if (int.MaxValue - start < count - 1)
44 throw new ArgumentOutOfRangeException ("count", "start + count - 1 is larger than Int32.MaxValue");
45 if (count < 0)
46 throw new ArgumentOutOfRangeException ("count", "count is less than 0");
48 return (new RangeList (start, count)).AsParallel ();
51 public static ParallelQuery<TResult> Repeat<TResult> (TResult element, int count)
53 if (count < 0)
54 throw new ArgumentOutOfRangeException ("count", "count is less than 0");
56 return (new RepeatList<TResult> (element, count)).AsParallel ();
58 #endregion
60 #region Empty
61 public static ParallelQuery<TResult> Empty<TResult> ()
63 return Repeat<TResult> (default (TResult), 0);
65 #endregion
67 #region AsParallel
68 public static ParallelQuery<TSource> AsParallel<TSource> (this IEnumerable<TSource> source)
70 if (source == null)
71 throw new ArgumentNullException ("source");
73 /* Someone might be trying to use AsParallel a bit too much, if the query was in fact
74 * already a ParallelQuery, just cast it
76 ParallelQuery<TSource> query = source as ParallelQuery<TSource>;
78 return query ?? new ParallelQuery<TSource> (new QueryStartNode<TSource> (source));
81 public static ParallelQuery<TSource> AsParallel<TSource> (this Partitioner<TSource> source)
83 if (source == null)
84 throw new ArgumentNullException ("source");
86 /* Someone might be trying to use AsParallel a bit too much, if the query was in fact
87 * already a ParallelQuery, just cast it
89 ParallelQuery<TSource> query = source as ParallelQuery<TSource>;
91 return query ?? new ParallelQuery<TSource> (new QueryStartNode<TSource> (source));
94 public static ParallelQuery AsParallel (this IEnumerable source)
96 if (source == null)
97 throw new ArgumentNullException ("source");
99 /* Someone might be trying to use AsParallel a bit too much, if the query was in fact
100 * already a ParallelQuery, just cast it
102 ParallelQuery query = source as ParallelQuery;
104 return query ?? new ParallelQuery<object> (new QueryStartNode<object> (source.Cast<object> ()));
107 public static IEnumerable<TSource> AsEnumerable<TSource> (this ParallelQuery<TSource> source)
109 if (source == null)
110 throw new ArgumentNullException ("source");
112 return source.AsSequential ();
115 public static IEnumerable<TSource> AsSequential<TSource> (this ParallelQuery<TSource> source)
117 if (source == null)
118 throw new ArgumentNullException ("source");
120 return source.Node.GetSequential ();
122 #endregion
124 #region AsOrdered / AsUnordered
125 public static ParallelQuery<TSource> AsOrdered<TSource> (this ParallelQuery<TSource> source)
127 if (source == null)
128 throw new ArgumentNullException ("source");
130 return new ParallelQuery<TSource> (new QueryAsOrderedNode<TSource> (source.Node));
133 public static ParallelQuery<TSource> AsUnordered<TSource> (this ParallelQuery<TSource> source)
135 if (source == null)
136 throw new ArgumentNullException ("source");
138 return new ParallelQuery<TSource> (new QueryAsUnorderedNode<TSource> (source.Node));
141 public static ParallelQuery AsOrdered (this ParallelQuery source)
143 if (source == null)
144 throw new ArgumentNullException ("source");
146 return source.TypedQuery.AsOrdered ();
148 #endregion
150 #region With*
151 public static ParallelQuery<TSource> WithExecutionMode<TSource> (this ParallelQuery<TSource> source,
152 ParallelExecutionMode executionMode)
154 if (source == null)
155 throw new ArgumentNullException ("source");
157 return new ParallelQuery<TSource> (new ParallelExecutionModeNode<TSource> (executionMode, source.Node));
160 public static ParallelQuery<TSource> WithCancellation<TSource> (this ParallelQuery<TSource> source,
161 CancellationToken cancellationToken)
163 if (source == null)
164 throw new ArgumentNullException ("source");
166 return new ParallelQuery<TSource> (new CancellationTokenNode<TSource> (cancellationToken, source.Node));
169 public static ParallelQuery<TSource> WithMergeOptions<TSource> (this ParallelQuery<TSource> source,
170 ParallelMergeOptions mergeOptions)
172 if (source == null)
173 throw new ArgumentNullException ("source");
175 return new ParallelQuery<TSource> (new ParallelMergeOptionsNode<TSource> (mergeOptions, source.Node));
178 public static ParallelQuery<TSource> WithDegreeOfParallelism<TSource> (this ParallelQuery<TSource> source,
179 int degreeOfParallelism)
181 if (degreeOfParallelism < 1 || degreeOfParallelism > 63)
182 throw new ArgumentException ("degreeOfParallelism is less than 1 or greater than 63", "degreeOfParallelism");
183 if (source == null)
184 throw new ArgumentNullException ("source");
186 return new ParallelQuery<TSource> (new DegreeOfParallelismNode<TSource> (degreeOfParallelism, source.Node));
189 internal static ParallelQuery<TSource> WithImplementerToken<TSource> (this ParallelQuery<TSource> source,
190 CancellationTokenSource token)
192 return new ParallelQuery<TSource> (new ImplementerTokenNode<TSource> (token, source.Node));
194 #endregion
196 #region Select
197 public static ParallelQuery<TResult> Select<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
199 if (source == null)
200 throw new ArgumentNullException ("source");
201 if (selector == null)
202 throw new ArgumentNullException ("selector");
204 return new ParallelQuery<TResult> (new QuerySelectNode<TResult, TSource> (source.Node, selector));
207 public static ParallelQuery<TResult> Select<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, int, TResult> selector)
209 if (source == null)
210 throw new ArgumentNullException ("source");
211 if (selector == null)
212 throw new ArgumentNullException ("selector");
214 return new ParallelQuery<TResult> (new QuerySelectNode<TResult, TSource> (source.Node, selector));
216 #endregion
218 #region SelectMany
219 public static ParallelQuery<TResult> SelectMany<TSource, TResult> (this ParallelQuery<TSource> source,
220 Func<TSource, IEnumerable<TResult>> selector)
222 return source.SelectMany (selector, (s, e) => e);
225 public static ParallelQuery<TResult> SelectMany<TSource, TResult> (this ParallelQuery<TSource> source,
226 Func<TSource, int, IEnumerable<TResult>> selector)
228 return source.SelectMany (selector, (s, e) => e);
231 public static ParallelQuery<TResult> SelectMany<TSource, TCollection, TResult> (this ParallelQuery<TSource> source,
232 Func<TSource, IEnumerable<TCollection>> collectionSelector,
233 Func<TSource, TCollection, TResult> resultSelector)
235 return new ParallelQuery<TResult> (new QuerySelectManyNode<TSource, TCollection, TResult> (source.Node,
236 collectionSelector,
237 resultSelector));
240 public static ParallelQuery<TResult> SelectMany<TSource, TCollection, TResult> (this ParallelQuery<TSource> source,
241 Func<TSource, int, IEnumerable<TCollection>> collectionSelector,
242 Func<TSource, TCollection, TResult> resultSelector)
244 return new ParallelQuery<TResult> (new QuerySelectManyNode<TSource, TCollection, TResult> (source.Node,
245 collectionSelector,
246 resultSelector));
248 #endregion
250 #region Where
251 public static ParallelQuery<TSource> Where<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
253 if (source == null)
254 throw new ArgumentNullException ("source");
255 if (predicate == null)
256 throw new ArgumentNullException ("predicate");
258 return new ParallelQuery<TSource> (new QueryWhereNode<TSource> (source.Node, predicate));
261 public static ParallelQuery<TSource> Where<TSource> (this ParallelQuery<TSource> source, Func<TSource, int, bool> predicate)
263 if (source == null)
264 throw new ArgumentNullException ("source");
265 if (predicate == null)
266 throw new ArgumentNullException ("predicate");
268 return new ParallelQuery<TSource> (new QueryWhereNode<TSource> (source.Node, predicate));
270 #endregion
272 #region Aggregate
273 public static TSource Aggregate<TSource> (this ParallelQuery<TSource> source, Func<TSource, TSource, TSource> func)
275 if (source == null)
276 throw new ArgumentNullException ("source");
277 if (func == null)
278 throw new ArgumentNullException ("func");
280 return source.Aggregate<TSource, TSource, TSource> ((Func<TSource>)null,
281 func,
282 func,
283 (e) => e);
286 public static TAccumulate Aggregate<TSource, TAccumulate> (this ParallelQuery<TSource> source,
287 TAccumulate seed,
288 Func<TAccumulate, TSource, TAccumulate> func)
290 if (source == null)
291 throw new ArgumentNullException ("source");
292 if (func == null)
293 throw new ArgumentNullException ("func");
295 return source.Aggregate (seed, func, (e) => e);
298 public static TResult Aggregate<TSource, TAccumulate, TResult> (this ParallelQuery<TSource> source,
299 TAccumulate seed,
300 Func<TAccumulate, TSource, TAccumulate> func,
301 Func<TAccumulate, TResult> resultSelector)
303 if (source == null)
304 throw new ArgumentNullException ("source");
305 if (func == null)
306 throw new ArgumentNullException ("func");
307 if (resultSelector == null)
308 throw new ArgumentNullException ("resultSelector");
310 TAccumulate accumulator = seed;
312 foreach (TSource value in source)
313 accumulator = func (accumulator, value);
315 return resultSelector (accumulator);
318 public static TResult Aggregate<TSource, TAccumulate, TResult> (this ParallelQuery<TSource> source,
319 TAccumulate seed,
320 Func<TAccumulate, TSource, TAccumulate> updateAccumulatorFunc,
321 Func<TAccumulate, TAccumulate, TAccumulate> combineAccumulatorsFunc,
322 Func<TAccumulate, TResult> resultSelector)
324 if (source == null)
325 throw new ArgumentNullException ("source");
326 if (updateAccumulatorFunc == null)
327 throw new ArgumentNullException ("updateAccumulatorFunc");
328 if (combineAccumulatorsFunc == null)
329 throw new ArgumentNullException ("combineAccumulatorsFunc");
330 if (resultSelector == null)
331 throw new ArgumentNullException ("resultSelector");
333 return source.Aggregate (() => seed, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector);
336 public static TResult Aggregate<TSource, TAccumulate, TResult> (this ParallelQuery<TSource> source,
337 Func<TAccumulate> seedFactory,
338 Func<TAccumulate, TSource, TAccumulate> updateAccumulatorFunc,
339 Func<TAccumulate, TAccumulate, TAccumulate> combineAccumulatorsFunc,
340 Func<TAccumulate, TResult> resultSelector)
342 if (source == null)
343 throw new ArgumentNullException ("source");
344 if (seedFactory == null)
345 throw new ArgumentNullException ("seedFactory");
346 if (updateAccumulatorFunc == null)
347 throw new ArgumentNullException ("updateAccumulatorFunc");
348 if (combineAccumulatorsFunc == null)
349 throw new ArgumentNullException ("combineAccumulatorsFunc");
350 if (resultSelector == null)
351 throw new ArgumentNullException ("resultSelector");
353 TAccumulate accumulator = default (TAccumulate);
355 ParallelExecuter.ProcessAndAggregate<TSource, TAccumulate> (source.Node, seedFactory, updateAccumulatorFunc, (list) => {
356 accumulator = list [0];
357 for (int i = 1; i < list.Count; i++)
358 accumulator = combineAccumulatorsFunc (accumulator, list[i]);
361 return resultSelector (accumulator);;
363 #endregion
365 #region ForAll
366 public static void ForAll<TSource> (this ParallelQuery<TSource> source, Action<TSource> action)
368 if (source == null)
369 throw new ArgumentNullException ("source");
370 if (action == null)
371 throw new ArgumentNullException ("action");
373 ParallelExecuter.ProcessAndBlock (source.Node, (e, c) => action (e));
375 #endregion
377 #region OrderBy
378 public static OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey> (this ParallelQuery<TSource> source,
379 Func<TSource, TKey> keySelector,
380 IComparer<TKey> comparer)
382 if (source == null)
383 throw new ArgumentNullException ("source");
384 if (keySelector == null)
385 throw new ArgumentNullException ("keySelector");
386 if (comparer == null)
387 comparer = Comparer<TKey>.Default;
389 Comparison<TSource> comparison = (e1, e2) => -comparer.Compare (keySelector (e1), keySelector (e2));
391 return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
394 public static OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey> (this ParallelQuery<TSource> source,
395 Func<TSource, TKey> keySelector)
397 return OrderByDescending (source, keySelector, Comparer<TKey>.Default);
400 public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey> (this ParallelQuery<TSource> source,
401 Func<TSource, TKey> keySelector)
403 return OrderBy (source, keySelector, Comparer<TKey>.Default);
406 public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey> (this ParallelQuery<TSource> source,
407 Func<TSource, TKey> keySelector,
408 IComparer<TKey> comparer)
410 if (source == null)
411 throw new ArgumentNullException ("source");
412 if (keySelector == null)
413 throw new ArgumentNullException ("keySelector");
414 if (comparer == null)
415 comparer = Comparer<TKey>.Default;
417 Comparison<TSource> comparison = (e1, e2) => comparer.Compare (keySelector (e1), keySelector (e2));
419 return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
421 #endregion
423 #region ThenBy
424 public static OrderedParallelQuery<TSource> ThenBy<TSource, TKey> (this OrderedParallelQuery<TSource> source,
425 Func<TSource, TKey> keySelector)
427 return ThenBy (source, keySelector, Comparer<TKey>.Default);
430 public static OrderedParallelQuery<TSource> ThenBy<TSource, TKey> (this OrderedParallelQuery<TSource> source,
431 Func<TSource, TKey> keySelector,
432 IComparer<TKey> comparer)
434 if (source == null)
435 throw new ArgumentNullException ("source");
436 if (keySelector == null)
437 throw new ArgumentNullException ("keySelector");
438 if (comparer == null)
439 comparer = Comparer<TKey>.Default;
441 Comparison<TSource> comparison = (e1, e2) => comparer.Compare (keySelector (e1), keySelector (e2));
443 return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
446 public static OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey> (this OrderedParallelQuery<TSource> source,
447 Func<TSource, TKey> keySelector)
449 return ThenByDescending (source, keySelector, Comparer<TKey>.Default);
452 public static OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey> (this OrderedParallelQuery<TSource> source,
453 Func<TSource, TKey> keySelector,
454 IComparer<TKey> comparer)
456 if (source == null)
457 throw new ArgumentNullException ("source");
458 if (keySelector == null)
459 throw new ArgumentNullException ("keySelector");
460 if (comparer == null)
461 comparer = Comparer<TKey>.Default;
463 Comparison<TSource> comparison = (e1, e2) => -comparer.Compare (keySelector (e1), keySelector (e2));
465 return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
467 #endregion
469 #region All
470 public static bool All<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
472 if (source == null)
473 throw new ArgumentNullException ("source");
474 if (predicate == null)
475 throw new ArgumentNullException ("predicate");
477 CancellationTokenSource src = new CancellationTokenSource ();
478 ParallelQuery<TSource> innerQuery = source.WithImplementerToken (src);
480 bool result = true;
481 try {
482 innerQuery.ForAll ((e) => {
483 if (!predicate (e)) {
484 result = false;
485 src.Cancel ();
488 } catch (OperationCanceledException e) {
489 if (e.CancellationToken != src.Token)
490 throw e;
493 return result;
495 #endregion
497 #region Any
498 public static bool Any<TSource> (this ParallelQuery<TSource> source)
500 return Any<TSource> (source, (_) => true);
503 public static bool Any<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
505 if (source == null)
506 throw new ArgumentNullException ("source");
507 if (predicate == null)
508 throw new ArgumentNullException ("predicate");
510 return !source.All ((e) => !predicate (e));
512 #endregion
514 #region Contains
515 public static bool Contains<TSource> (this ParallelQuery<TSource> source, TSource value)
517 return Contains<TSource> (source, value, EqualityComparer<TSource>.Default);
520 public static bool Contains<TSource> (this ParallelQuery<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
522 if (source == null)
523 throw new ArgumentNullException ("source");
524 if (comparer == null)
525 comparer = EqualityComparer<TSource>.Default;
527 return Any<TSource> (source, (e) => comparer.Equals (value));
529 #endregion
531 #region SequenceEqual
532 public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first,
533 ParallelQuery<TSource> second)
535 if (first == null)
536 throw new ArgumentNullException ("first");
537 if (second == null)
538 throw new ArgumentNullException ("second");
540 return first.SequenceEqual (second, EqualityComparer<TSource>.Default);
543 public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first,
544 ParallelQuery<TSource> second,
545 IEqualityComparer<TSource> comparer)
547 if (first == null)
548 throw new ArgumentNullException ("first");
549 if (second == null)
550 throw new ArgumentNullException ("second");
551 if (comparer == null)
552 comparer = EqualityComparer<TSource>.Default;
554 CancellationTokenSource source = new CancellationTokenSource ();
555 ParallelQuery<bool> innerQuery
556 = first.Zip (second, (e1, e2) => comparer.Equals (e1, e2)).Where ((e) => !e).WithImplementerToken (source);
558 bool result = true;
560 try {
561 innerQuery.ForAll ((value) => {
562 result = false;
563 source.Cancel ();
565 } catch (OperationCanceledException e) {
566 if (e.CancellationToken != source.Token)
567 throw e;
570 return result;
573 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
574 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
575 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
576 public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first, IEnumerable<TSource> second)
578 throw new NotSupportedException ();
581 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
582 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
583 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
584 public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first,
585 IEnumerable<TSource> second,
586 IEqualityComparer<TSource> comparer)
588 throw new NotSupportedException ();
591 #endregion
593 #region GroupBy
594 public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this ParallelQuery<TSource> source,
595 Func<TSource, TKey> keySelector)
597 return source.GroupBy (keySelector, EqualityComparer<TKey>.Default);
600 public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this ParallelQuery<TSource> source,
601 Func<TSource, TKey> keySelector,
602 IEqualityComparer<TKey> comparer)
604 return source.GroupBy (keySelector, (e) => e, comparer);
607 public static ParallelQuery<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
608 Func<TSource, TKey> keySelector,
609 Func<TSource, TElement> elementSelector)
611 return source.GroupBy (keySelector, elementSelector, EqualityComparer<TKey>.Default);
614 public static ParallelQuery<TResult> GroupBy<TSource, TKey, TResult> (this ParallelQuery<TSource> source,
615 Func<TSource, TKey> keySelector,
616 Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
618 return source.GroupBy (keySelector)
619 .Select ((g) => resultSelector (g.Key, (IEnumerable<TSource>)g));
622 public static ParallelQuery<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
623 Func<TSource, TKey> keySelector,
624 Func<TSource, TElement> elementSelector,
625 IEqualityComparer<TKey> comparer)
627 if (source == null)
628 throw new ArgumentNullException ("source");
629 if (keySelector == null)
630 throw new ArgumentNullException ("keySelector");
631 if (elementSelector == null)
632 throw new ArgumentNullException ("elementSelector");
633 if (comparer == null)
634 comparer = EqualityComparer<TKey>.Default;
636 return new ParallelQuery<IGrouping<TKey, TElement>> (new QueryGroupByNode<TSource, TKey, TElement> (source.Node, keySelector, elementSelector, comparer));
639 public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult> (this ParallelQuery<TSource> source,
640 Func<TSource, TKey> keySelector,
641 Func<TSource, TElement> elementSelector,
642 Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
644 return source.GroupBy (keySelector, elementSelector)
645 .Select ((g) => resultSelector (g.Key, (IEnumerable<TElement>)g));
648 public static ParallelQuery<TResult> GroupBy<TSource, TKey, TResult> (this ParallelQuery<TSource> source,
649 Func<TSource, TKey> keySelector,
650 Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
651 IEqualityComparer<TKey> comparer)
653 return source.GroupBy (keySelector, comparer)
654 .Select ((g) => resultSelector (g.Key, (IEnumerable<TSource>)g));
657 public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult> (this ParallelQuery<TSource> source,
658 Func<TSource, TKey> keySelector,
659 Func<TSource, TElement> elementSelector,
660 Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
661 IEqualityComparer<TKey> comparer)
663 return source.GroupBy (keySelector, elementSelector, comparer)
664 .Select ((g) => resultSelector (g.Key, (IEnumerable<TElement>)g));
666 #endregion
668 #region GroupJoin
669 public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
670 ParallelQuery<TInner> inner,
671 Func<TOuter, TKey> outerKeySelector,
672 Func<TInner, TKey> innerKeySelector,
673 Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
675 return outer.GroupJoin (inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
678 public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
679 ParallelQuery<TInner> inner,
680 Func<TOuter, TKey> outerKeySelector,
681 Func<TInner, TKey> innerKeySelector,
682 Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
683 IEqualityComparer<TKey> comparer)
685 return outer.Join (inner.GroupBy (innerKeySelector, (e) => e), outerKeySelector, (e) => e.Key, (e1, e2) => resultSelector (e1, e2), comparer);
688 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
689 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
690 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
691 public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
692 IEnumerable<TInner> inner,
693 Func<TOuter, TKey> outerKeySelector,
694 Func<TInner, TKey> innerKeySelector,
695 Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
697 throw new NotSupportedException ();
700 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
701 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
702 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
703 public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
704 IEnumerable<TInner> inner,
705 Func<TOuter, TKey> outerKeySelector,
706 Func<TInner, TKey> innerKeySelector,
707 Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
708 IEqualityComparer<TKey> comparer)
710 throw new NotSupportedException ();
712 #endregion
714 #region ElementAt
715 public static TSource ElementAt<TSource> (this ParallelQuery<TSource> source, int index)
717 if (source == null)
718 throw new ArgumentNullException ("source");
719 if (index < 0)
720 throw new ArgumentOutOfRangeException ("index");
721 if (index == 0) {
722 try {
723 return source.First ();
724 } catch (InvalidOperationException) {
725 throw new ArgumentOutOfRangeException ("index");
729 TSource result = default (TSource);
731 ParallelQuery<TSource> innerQuery = source.Where ((e, i) => i == index);
733 try {
734 result = innerQuery.First ();
735 } catch (InvalidOperationException) {
736 throw new ArgumentOutOfRangeException ("index");
739 return result;
742 public static TSource ElementAtOrDefault<TSource> (this ParallelQuery<TSource> source, int index)
744 if (source == null)
745 throw new ArgumentNullException ("source");
747 try {
748 return source.ElementAt (index);
749 } catch (ArgumentOutOfRangeException) {
750 return default (TSource);
753 #endregion
755 #region Intersect
756 public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first,
757 ParallelQuery<TSource> second)
759 return Intersect<TSource> (first, second, EqualityComparer<TSource>.Default);
762 public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first,
763 ParallelQuery<TSource> second,
764 IEqualityComparer<TSource> comparer)
766 if (first == null)
767 throw new ArgumentNullException ("first");
768 if (second == null)
769 throw new ArgumentNullException ("second");
770 if (comparer == null)
771 comparer = EqualityComparer<TSource>.Default;
773 return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Intersect, comparer, first.Node, second.Node));
776 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
777 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
778 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
779 public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first, IEnumerable<TSource> second)
781 throw new NotSupportedException ();
784 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
785 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
786 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
787 public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first,
788 IEnumerable<TSource> second,
789 IEqualityComparer<TSource> comparer)
791 throw new NotSupportedException ();
793 #endregion
795 #region Join
796 public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
797 ParallelQuery<TInner> inner,
798 Func<TOuter, TKey> outerKeySelector,
799 Func<TInner, TKey> innerKeySelector,
800 Func<TOuter, TInner, TResult> resultSelector)
802 return outer.Join (inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
805 public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
806 ParallelQuery<TInner> inner,
807 Func<TOuter, TKey> outerKeySelector,
808 Func<TInner, TKey> innerKeySelector,
809 Func<TOuter, TInner, TResult> resultSelector,
810 IEqualityComparer<TKey> comparer)
812 return new ParallelQuery<TResult> (new QueryJoinNode<TOuter, TInner, TKey, TResult> (outer.Node, inner.Node, outerKeySelector, innerKeySelector, resultSelector, comparer));
815 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
816 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
817 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
818 public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
819 IEnumerable<TInner> inner,
820 Func<TOuter, TKey> outerKeySelector,
821 Func<TInner, TKey> innerKeySelector,
822 Func<TOuter, TInner, TResult> resultSelector)
824 throw new NotSupportedException ();
827 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
828 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
829 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
830 public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
831 IEnumerable<TInner> inner,
832 Func<TOuter, TKey> outerKeySelector,
833 Func<TInner, TKey> innerKeySelector,
834 Func<TOuter, TInner, TResult> resultSelector,
835 IEqualityComparer<TKey> comparer)
837 throw new NotSupportedException ();
839 #endregion
841 #region Except
842 public static ParallelQuery<TSource> Except<TSource> (this ParallelQuery<TSource> first,
843 ParallelQuery<TSource> second)
845 return Except<TSource> (first, second, EqualityComparer<TSource>.Default);
848 public static ParallelQuery<TSource> Except<TSource> (this ParallelQuery<TSource> first,
849 ParallelQuery<TSource> second,
850 IEqualityComparer<TSource> comparer)
852 if (first == null)
853 throw new ArgumentNullException ("first");
854 if (second == null)
855 throw new ArgumentNullException ("second");
856 if (comparer == null)
857 comparer = EqualityComparer<TSource>.Default;
859 return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Except,
860 comparer, first.Node, second.Node));
863 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
864 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
865 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
866 public static ParallelQuery<TSource> Except<TSource> (this ParallelQuery<TSource> first,
867 IEnumerable<TSource> second)
869 throw new NotSupportedException ();
872 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
873 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
874 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
875 public static ParallelQuery<TSource> Except<TSource> (this ParallelQuery<TSource> first,
876 IEnumerable<TSource> second,
877 IEqualityComparer<TSource> comparer)
879 throw new NotSupportedException ();
881 #endregion
883 #region Distinct
884 public static ParallelQuery<TSource> Distinct<TSource> (this ParallelQuery<TSource> source)
886 return Distinct<TSource> (source, EqualityComparer<TSource>.Default);
889 public static ParallelQuery<TSource> Distinct<TSource> (this ParallelQuery<TSource> source, IEqualityComparer<TSource> comparer)
891 if (source == null)
892 throw new ArgumentNullException ("source");
893 if (comparer == null)
894 comparer = EqualityComparer<TSource>.Default;
896 return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Distinct, comparer,
897 source.Node, null));
899 #endregion
901 #region Union
902 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
903 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
904 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
905 public static ParallelQuery<TSource> Union<TSource> (this ParallelQuery<TSource> first,
906 IEnumerable<TSource> second)
908 throw new NotSupportedException ();
911 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
912 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
913 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
914 public static ParallelQuery<TSource> Union<TSource>(this ParallelQuery<TSource> first,
915 IEnumerable<TSource> second,
916 IEqualityComparer<TSource> comparer)
918 throw new NotSupportedException ();
921 public static ParallelQuery<TSource> Union<TSource> (this ParallelQuery<TSource> first,
922 ParallelQuery<TSource> second)
924 return first.Union (second, EqualityComparer<TSource>.Default);
927 public static ParallelQuery<TSource> Union<TSource> (this ParallelQuery<TSource> first,
928 ParallelQuery<TSource> second,
929 IEqualityComparer<TSource> comparer)
931 if (first == null)
932 throw new ArgumentNullException ("first");
933 if (second == null)
934 throw new ArgumentNullException ("second");
935 if (comparer == null)
936 comparer = EqualityComparer<TSource>.Default;
938 return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Union, comparer, first.Node, second.Node));
940 #endregion
942 #region Take
943 public static ParallelQuery<TSource> Take<TSource> (this ParallelQuery<TSource> source, int count)
945 if (source == null)
946 throw new ArgumentNullException ("source");
948 return new ParallelQuery<TSource> (new QueryHeadWorkerNode<TSource> (source.Node, count));
951 public static ParallelQuery<TSource> TakeWhile<TSource> (this ParallelQuery<TSource> source,
952 Func<TSource, bool> predicate)
954 if (source == null)
955 throw new ArgumentNullException ("source");
956 if (predicate == null)
957 throw new ArgumentNullException ("predicate");
959 return new ParallelQuery<TSource> (new QueryHeadWorkerNode<TSource> (source.Node, (e, _) => predicate (e), false));
962 public static ParallelQuery<TSource> TakeWhile<TSource> (this ParallelQuery<TSource> source,
963 Func<TSource, int, bool> predicate)
965 if (source == null)
966 throw new ArgumentNullException ("source");
967 if (predicate == null)
968 throw new ArgumentNullException ("predicate");
970 return new ParallelQuery<TSource> (new QueryHeadWorkerNode<TSource> (source.Node, predicate, true));
972 #endregion
974 #region Skip
975 public static ParallelQuery<TSource> Skip<TSource> (this ParallelQuery<TSource> source, int count)
977 if (source == null)
978 throw new ArgumentNullException ("source");
980 return source.Node.IsOrdered () ?
981 source.Where ((e, i) => i >= count) :
982 source.Where ((e) => count < 0 || Interlocked.Decrement (ref count) < 0);
986 public static ParallelQuery<TSource> SkipWhile<TSource> (this ParallelQuery<TSource> source,
987 Func<TSource, bool> predicate)
989 if (source == null)
990 throw new ArgumentNullException ("source");
991 if (predicate == null)
992 throw new ArgumentNullException ("predicate");
994 return source.Node.IsOrdered () ?
995 source.SkipWhile ((e, i) => predicate (e)) :
996 source.Where ((e) => !predicate (e));
999 public static ParallelQuery<TSource> SkipWhile<TSource> (this ParallelQuery<TSource> source,
1000 Func<TSource, int, bool> predicate)
1002 if (source == null)
1003 throw new ArgumentNullException ("source");
1004 if (predicate == null)
1005 throw new ArgumentNullException ("predicate");
1007 int indexCache = int.MaxValue;
1009 return source.Where ((e, i) => i >= indexCache || (!predicate (e, i) && (indexCache = i) == i));
1011 #endregion
1013 #region Single
1014 static TSource SingleInternal<TSource> (this ParallelQuery<TSource> source, params TSource[] init)
1016 TSource result = default(TSource);
1017 bool hasValue = false;
1019 foreach (TSource element in source) {
1020 if (hasValue)
1021 throw new InvalidOperationException ("The input sequence contains more than one element.");
1023 result = element;
1024 hasValue = true;
1027 if (!hasValue && init.Length != 0) {
1028 result = init[0];
1029 hasValue = true;
1032 if (!hasValue)
1033 throw new InvalidOperationException ("The input sequence is empty.");
1035 return result;
1038 public static TSource Single<TSource> (this ParallelQuery<TSource> source)
1040 if (source == null)
1041 throw new ArgumentNullException ("source");
1043 return SingleInternal<TSource> (source);
1046 public static TSource Single<TSource> (this ParallelQuery<TSource> source,
1047 Func<TSource, bool> predicate)
1049 if (source == null)
1050 throw new ArgumentNullException ("source");
1051 if (predicate == null)
1052 throw new ArgumentNullException ("predicate");
1054 return source.Where (predicate).Single ();
1057 public static TSource SingleOrDefault<TSource> (this ParallelQuery<TSource> source)
1059 if (source == null)
1060 throw new ArgumentNullException ("source");
1062 return SingleInternal<TSource> (source, default (TSource));
1065 public static TSource SingleOrDefault<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
1067 if (source == null)
1068 throw new ArgumentNullException ("source");
1069 if (predicate == null)
1070 throw new ArgumentNullException ("predicate");
1072 return source.Where (predicate).SingleOrDefault ();
1074 #endregion
1076 #region Count
1077 public static int Count<TSource> (this ParallelQuery<TSource> source)
1079 if (source == null)
1080 throw new ArgumentNullException ("source");
1082 return source.Aggregate<TSource, int, int> (() => 0,
1083 (acc, e) => acc + 1,
1084 (acc1, acc2) => acc1 + acc2,
1085 (result) => result);
1088 public static int Count<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
1090 if (source == null)
1091 throw new ArgumentNullException ("source");
1092 if (predicate == null)
1093 throw new ArgumentNullException ("predicate");
1095 return source.Where (predicate).Count ();
1098 public static long LongCount<TSource> (this ParallelQuery<TSource> source)
1100 if (source == null)
1101 throw new ArgumentNullException ("source");
1103 return source.Aggregate<TSource, long, long> (() => 0,
1104 (acc, e) => acc + 1,
1105 (acc1, acc2) => acc1 + acc2,
1106 (result) => result);
1109 public static long LongCount<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
1111 if (source == null)
1112 throw new ArgumentNullException ("source");
1113 if (predicate == null)
1114 throw new ArgumentNullException ("predicate");
1116 return source.Where (predicate).LongCount ();
1118 #endregion
1120 #region Average
1121 public static double Average (this ParallelQuery<int> source)
1123 if (source == null)
1124 throw new ArgumentNullException ("source");
1126 return source.Aggregate (() => new int[2],
1127 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1128 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1129 (acc) => acc[0] / ((double)acc[1]));
1132 public static double Average (this ParallelQuery<long> source)
1134 if (source == null)
1135 throw new ArgumentNullException ("source");
1137 return source.Aggregate (() => new long[2],
1138 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1139 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1140 (acc) => acc[0] / ((double)acc[1]));
1143 public static decimal Average (this ParallelQuery<decimal> source)
1145 if (source == null)
1146 throw new ArgumentNullException ("source");
1148 return source.Aggregate (() => new decimal[2],
1149 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1150 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1151 (acc) => acc[0] / acc[1]);
1154 public static double Average (this ParallelQuery<double> source)
1156 if (source == null)
1157 throw new ArgumentNullException ("source");
1159 return source.Aggregate (() => new double[2],
1160 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1161 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1162 (acc) => acc[0] / ((double)acc[1]));
1165 public static float Average (this ParallelQuery<float> source)
1167 if (source == null)
1168 throw new ArgumentNullException ("source");
1170 return source.Aggregate (() => new float[2],
1171 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1172 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1173 (acc) => acc[0] / acc[1]);
1175 #endregion
1177 #region More Average
1178 public static double? Average (this ParallelQuery<int?> source)
1180 if (source == null)
1181 throw new ArgumentNullException ("source");
1183 return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();;
1186 public static double? Average (this ParallelQuery<long?> source)
1188 if (source == null)
1189 throw new ArgumentNullException ("source");
1191 return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
1194 public static decimal? Average (this ParallelQuery<decimal?> source)
1196 if (source == null)
1197 throw new ArgumentNullException ("source");
1199 return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
1202 public static double? Average (this ParallelQuery<double?> source)
1204 if (source == null)
1205 throw new ArgumentNullException ("source");
1207 return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
1210 public static float? Average (this ParallelQuery<float?> source)
1212 if (source == null)
1213 throw new ArgumentNullException ("source");
1215 return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
1218 public static double Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> selector)
1220 if (source == null)
1221 throw new ArgumentNullException ("source");
1222 if (selector == null)
1223 throw new ArgumentNullException ("selector");
1225 return source.Select (selector).Average ();
1228 public static double Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> selector)
1230 if (source == null)
1231 throw new ArgumentNullException ("source");
1232 if (selector == null)
1233 throw new ArgumentNullException ("selector");
1235 return source.Select (selector).Average ();
1238 public static float Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> selector)
1240 if (source == null)
1241 throw new ArgumentNullException ("source");
1242 if (selector == null)
1243 throw new ArgumentNullException ("selector");
1245 return source.Select (selector).Average ();
1248 public static double Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> selector)
1250 if (source == null)
1251 throw new ArgumentNullException ("source");
1252 if (selector == null)
1253 throw new ArgumentNullException ("selector");
1255 return source.Select (selector).Average ();
1258 public static decimal Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> selector)
1260 if (source == null)
1261 throw new ArgumentNullException ("source");
1262 if (selector == null)
1263 throw new ArgumentNullException ("selector");
1265 return source.Select (selector).Average ();
1268 public static double? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> selector)
1270 if (source == null)
1271 throw new ArgumentNullException ("source");
1272 if (selector == null)
1273 throw new ArgumentNullException ("selector");
1275 return source.Select (selector).Average ();
1278 public static double? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> selector)
1280 if (source == null)
1281 throw new ArgumentNullException ("source");
1282 if (selector == null)
1283 throw new ArgumentNullException ("selector");
1285 return source.Select (selector).Average ();
1288 public static float? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> selector)
1290 if (source == null)
1291 throw new ArgumentNullException ("source");
1292 if (selector == null)
1293 throw new ArgumentNullException ("selector");
1295 return source.Select (selector).Average ();
1298 public static double? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> selector)
1300 if (source == null)
1301 throw new ArgumentNullException ("source");
1302 if (selector == null)
1303 throw new ArgumentNullException ("selector");
1305 return source.Select (selector).Average ();
1308 public static decimal? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> selector)
1310 if (source == null)
1311 throw new ArgumentNullException ("source");
1312 if (selector == null)
1313 throw new ArgumentNullException ("selector");
1315 return source.Select (selector).Average ();
1317 #endregion
1319 #region Sum
1320 public static int Sum (this ParallelQuery<int> source)
1322 if (source == null)
1323 throw new ArgumentNullException ("source");
1325 return source.Aggregate (0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1328 public static long Sum (this ParallelQuery<long> source)
1330 if (source == null)
1331 throw new ArgumentNullException ("source");
1333 return source.Aggregate ((long)0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1336 public static float Sum (this ParallelQuery<float> source)
1338 if (source == null)
1339 throw new ArgumentNullException ("source");
1341 return source.Aggregate (0.0f, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1344 public static double Sum (this ParallelQuery<double> source)
1346 if (source == null)
1347 throw new ArgumentNullException ("source");
1349 return source.Aggregate (0.0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1352 public static decimal Sum (this ParallelQuery<decimal> source)
1354 if (source == null)
1355 throw new ArgumentNullException ("source");
1357 return source.Aggregate ((decimal)0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1360 public static int? Sum (this ParallelQuery<int?> source)
1362 return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1365 public static long? Sum (this ParallelQuery<long?> source)
1367 if (source == null)
1368 throw new ArgumentNullException ("source");
1370 return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1373 public static float? Sum (this ParallelQuery<float?> source)
1375 if (source == null)
1376 throw new ArgumentNullException ("source");
1378 return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1381 public static double? Sum (this ParallelQuery<double?> source)
1383 if (source == null)
1384 throw new ArgumentNullException ("source");
1386 return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1389 public static decimal? Sum (this ParallelQuery<decimal?> source)
1391 if (source == null)
1392 throw new ArgumentNullException ("source");
1394 return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1397 public static int Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> selector)
1399 if (source == null)
1400 throw new ArgumentNullException ("source");
1401 if (selector == null)
1402 throw new ArgumentNullException ("selector");
1404 return source.Select (selector).Sum ();
1407 public static long Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> selector)
1409 if (source == null)
1410 throw new ArgumentNullException ("source");
1411 if (selector == null)
1412 throw new ArgumentNullException ("selector");
1414 return source.Select (selector).Sum ();
1417 public static decimal Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> selector)
1419 if (source == null)
1420 throw new ArgumentNullException ("source");
1421 if (selector == null)
1422 throw new ArgumentNullException ("selector");
1424 return source.Select (selector).Sum ();
1427 public static float Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> selector)
1429 if (source == null)
1430 throw new ArgumentNullException ("source");
1431 if (selector == null)
1432 throw new ArgumentNullException ("selector");
1434 return source.Select (selector).Sum ();
1437 public static double Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> selector)
1439 if (source == null)
1440 throw new ArgumentNullException ("source");
1441 if (selector == null)
1442 throw new ArgumentNullException ("selector");
1444 return source.Select (selector).Sum ();
1447 public static int? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> selector)
1449 if (source == null)
1450 throw new ArgumentNullException ("source");
1451 if (selector == null)
1452 throw new ArgumentNullException ("selector");
1454 return source.Select (selector).Sum ();
1457 public static long? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> selector)
1459 if (source == null)
1460 throw new ArgumentNullException ("source");
1461 if (selector == null)
1462 throw new ArgumentNullException ("selector");
1464 return source.Select (selector).Sum ();
1467 public static decimal? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> selector)
1469 if (source == null)
1470 throw new ArgumentNullException ("source");
1471 if (selector == null)
1472 throw new ArgumentNullException ("selector");
1474 return source.Select (selector).Sum ();
1477 public static float? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> selector)
1479 if (source == null)
1480 throw new ArgumentNullException ("source");
1481 if (selector == null)
1482 throw new ArgumentNullException ("selector");
1484 return source.Select (selector).Sum ();
1487 public static double? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> selector)
1489 if (source == null)
1490 throw new ArgumentNullException ("source");
1491 if (selector == null)
1492 throw new ArgumentNullException ("selector");
1494 return source.Select (selector).Sum ();
1496 #endregion
1498 #region Min-Max
1499 static T BestOrder<T> (ParallelQuery<T> source, Func<T, T, bool> bestSelector, T seed)
1501 if (source == null)
1502 throw new ArgumentNullException ("source");
1504 T best = seed;
1506 best = source.Aggregate (() => seed,
1507 (first, second) => (bestSelector(first, second)) ? first : second,
1508 (first, second) => (bestSelector(first, second)) ? first : second,
1509 (e) => e);
1510 return best;
1513 public static int Min (this ParallelQuery<int> source)
1515 return BestOrder (source, (first, second) => first < second, int.MaxValue);
1518 public static long Min (this ParallelQuery<long> source)
1520 return BestOrder (source, (first, second) => first < second, long.MaxValue);
1523 public static float Min (this ParallelQuery<float> source)
1525 return BestOrder (source, (first, second) => first < second, float.MaxValue);
1528 public static double Min (this ParallelQuery<double> source)
1530 return BestOrder (source, (first, second) => first < second, double.MaxValue);
1533 public static decimal Min (this ParallelQuery<decimal> source)
1535 return BestOrder (source, (first, second) => first < second, decimal.MaxValue);
1538 public static TSource Min<TSource> (this ParallelQuery<TSource> source)
1540 IComparer<TSource> comparer = Comparer<TSource>.Default;
1542 return BestOrder (source, (first, second) => comparer.Compare (first, second) < 0, default (TSource));
1545 public static TResult Min<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
1547 if (source == null)
1548 throw new ArgumentNullException ("source");
1549 if (selector == null)
1550 throw new ArgumentNullException ("selector");
1552 return source.Select (selector).Min ();
1555 public static int? Min (this ParallelQuery<int?> source)
1557 if (source == null)
1558 throw new ArgumentNullException ("source");
1560 return source.Select ((e) => e.HasValue ? e.Value : int.MaxValue).Min ();
1563 public static long? Min (this ParallelQuery<long?> source)
1565 if (source == null)
1566 throw new ArgumentNullException ("source");
1568 return source.Select ((e) => e.HasValue ? e.Value : long.MaxValue).Min ();
1571 public static float? Min (this ParallelQuery<float?> source)
1573 if (source == null)
1574 throw new ArgumentNullException ("source");
1576 return source.Select ((e) => e.HasValue ? e.Value : float.MaxValue).Min ();
1579 public static double? Min (this ParallelQuery<double?> source)
1581 if (source == null)
1582 throw new ArgumentNullException ("source");
1584 return source.Select ((e) => e.HasValue ? e.Value : double.MaxValue).Min ();
1587 public static decimal? Min (this ParallelQuery<decimal?> source)
1589 if (source == null)
1590 throw new ArgumentNullException ("source");
1592 return source.Select ((e) => e.HasValue ? e.Value : decimal.MaxValue).Min ();
1595 public static int Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> selector)
1597 if (source == null)
1598 throw new ArgumentNullException ("source");
1599 if (selector == null)
1600 throw new ArgumentNullException ("selector");
1602 return source.Select (selector).Min ();
1605 public static long Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> selector)
1607 if (source == null)
1608 throw new ArgumentNullException ("source");
1609 if (selector == null)
1610 throw new ArgumentNullException ("selector");
1612 return source.Select (selector).Min ();
1615 public static float Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> selector)
1617 if (source == null)
1618 throw new ArgumentNullException ("source");
1619 if (selector == null)
1620 throw new ArgumentNullException ("selector");
1622 return source.Select (selector).Min ();
1625 public static double Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> selector)
1627 if (source == null)
1628 throw new ArgumentNullException ("source");
1629 if (selector == null)
1630 throw new ArgumentNullException ("selector");
1632 return source.Select (selector).Min ();
1635 public static decimal Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> selector)
1637 if (source == null)
1638 throw new ArgumentNullException ("source");
1639 if (selector == null)
1640 throw new ArgumentNullException ("selector");
1642 return source.Select (selector).Min ();
1645 public static int? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> selector)
1647 if (source == null)
1648 throw new ArgumentNullException ("source");
1649 if (selector == null)
1650 throw new ArgumentNullException ("selector");
1652 return source.Select (selector).Min ();
1655 public static long? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> selector)
1657 if (source == null)
1658 throw new ArgumentNullException ("source");
1659 if (selector == null)
1660 throw new ArgumentNullException ("selector");
1662 return source.Select (selector).Min ();
1665 public static float? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> selector)
1667 if (source == null)
1668 throw new ArgumentNullException ("source");
1669 if (selector == null)
1670 throw new ArgumentNullException ("selector");
1672 return source.Select (selector).Min ();
1675 public static double? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> selector)
1677 if (source == null)
1678 throw new ArgumentNullException ("source");
1679 if (selector == null)
1680 throw new ArgumentNullException ("selector");
1682 return source.Select (selector).Min ();
1685 public static decimal? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> selector)
1687 if (source == null)
1688 throw new ArgumentNullException ("source");
1689 if (selector == null)
1690 throw new ArgumentNullException ("selector");
1692 return source.Select (selector).Min ();
1695 public static int Max (this ParallelQuery<int> source)
1697 return BestOrder (source, (first, second) => first > second, int.MinValue);
1700 public static long Max(this ParallelQuery<long> source)
1702 return BestOrder(source, (first, second) => first > second, long.MinValue);
1705 public static float Max (this ParallelQuery<float> source)
1707 return BestOrder(source, (first, second) => first > second, float.MinValue);
1710 public static double Max (this ParallelQuery<double> source)
1712 return BestOrder(source, (first, second) => first > second, double.MinValue);
1715 public static decimal Max (this ParallelQuery<decimal> source)
1717 return BestOrder(source, (first, second) => first > second, decimal.MinValue);
1720 public static TSource Max<TSource> (this ParallelQuery<TSource> source)
1722 IComparer<TSource> comparer = Comparer<TSource>.Default;
1724 return BestOrder (source, (first, second) => comparer.Compare (first, second) > 0, default (TSource));
1727 public static TResult Max<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
1729 if (source == null)
1730 throw new ArgumentNullException ("source");
1731 if (selector == null)
1732 throw new ArgumentNullException ("selector");
1734 return source.Select (selector).Max ();
1737 public static int? Max (this ParallelQuery<int?> source)
1739 if (source == null)
1740 throw new ArgumentNullException ("source");
1742 return source.Select ((e) => e.HasValue ? e.Value : int.MinValue).Max ();
1745 public static long? Max (this ParallelQuery<long?> source)
1747 if (source == null)
1748 throw new ArgumentNullException ("source");
1750 return source.Select ((e) => e.HasValue ? e.Value : long.MinValue).Max ();
1753 public static float? Max (this ParallelQuery<float?> source)
1755 if (source == null)
1756 throw new ArgumentNullException ("source");
1758 return source.Select ((e) => e.HasValue ? e.Value : float.MinValue).Max ();
1761 public static double? Max (this ParallelQuery<double?> source)
1763 if (source == null)
1764 throw new ArgumentNullException ("source");
1766 return source.Select ((e) => e.HasValue ? e.Value : double.MinValue).Max ();
1769 public static decimal? Max (this ParallelQuery<decimal?> source)
1771 if (source == null)
1772 throw new ArgumentNullException ("source");
1774 return source.Select ((e) => e.HasValue ? e.Value : decimal.MinValue).Max ();
1777 public static int Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> selector)
1779 if (source == null)
1780 throw new ArgumentNullException ("source");
1781 if (selector == null)
1782 throw new ArgumentNullException ("selector");
1784 return source.Select (selector).Max ();
1787 public static long Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> selector)
1789 if (source == null)
1790 throw new ArgumentNullException ("source");
1791 if (selector == null)
1792 throw new ArgumentNullException ("selector");
1794 return source.Select (selector).Max ();
1797 public static float Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> selector)
1799 if (source == null)
1800 throw new ArgumentNullException ("source");
1801 if (selector == null)
1802 throw new ArgumentNullException ("selector");
1804 return source.Select (selector).Max ();
1807 public static double Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> selector)
1809 if (source == null)
1810 throw new ArgumentNullException ("source");
1811 if (selector == null)
1812 throw new ArgumentNullException ("selector");
1814 return source.Select (selector).Max ();
1817 public static decimal Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> selector)
1819 if (source == null)
1820 throw new ArgumentNullException ("source");
1821 if (selector == null)
1822 throw new ArgumentNullException ("selector");
1824 return source.Select (selector).Max ();
1827 public static int? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> selector)
1829 if (source == null)
1830 throw new ArgumentNullException ("source");
1831 if (selector == null)
1832 throw new ArgumentNullException ("selector");
1834 return source.Select (selector).Max ();
1837 public static long? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> selector)
1839 if (source == null)
1840 throw new ArgumentNullException ("source");
1841 if (selector == null)
1842 throw new ArgumentNullException ("selector");
1844 return source.Select (selector).Max ();
1847 public static float? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> selector)
1849 if (source == null)
1850 throw new ArgumentNullException ("source");
1851 if (selector == null)
1852 throw new ArgumentNullException ("selector");
1854 return source.Select (selector).Max ();
1857 public static double? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> selector)
1859 if (source == null)
1860 throw new ArgumentNullException ("source");
1861 if (selector == null)
1862 throw new ArgumentNullException ("selector");
1864 return source.Select (selector).Max ();
1867 public static decimal? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> selector)
1869 if (source == null)
1870 throw new ArgumentNullException ("source");
1871 if (selector == null)
1872 throw new ArgumentNullException ("selector");
1874 return source.Select (selector).Max ();
1876 #endregion
1878 #region Cast / OfType
1879 public static ParallelQuery<TResult> Cast<TResult> (this ParallelQuery source)
1881 if (source == null)
1882 throw new ArgumentNullException ("source");
1884 return source.TypedQuery.Select ((e) => (TResult)e);
1887 public static ParallelQuery<TResult> OfType<TResult> (this ParallelQuery source)
1889 if (source == null)
1890 throw new ArgumentNullException ("source");
1892 return source.TypedQuery.Where ((e) => e is TResult).Cast<TResult> ();
1894 #endregion
1896 #region Reverse
1897 public static ParallelQuery<TSource> Reverse<TSource> (this ParallelQuery<TSource> source)
1899 if (source == null)
1900 throw new ArgumentNullException ("source");
1902 return new ParallelQuery<TSource> (new QueryReverseNode<TSource> (source));
1904 #endregion
1906 #region ToArray - ToList - ToDictionary - ToLookup
1907 public static List<TSource> ToList<TSource> (this ParallelQuery<TSource> source)
1909 if (source == null)
1910 throw new ArgumentNullException ("source");
1912 if (source.Node.IsOrdered ())
1913 return ToListOrdered (source);
1915 List<TSource> temp = source.Aggregate (() => new List<TSource>(50),
1916 (list, e) => { list.Add (e); return list; },
1917 (list, list2) => { list.AddRange (list2); return list; },
1918 (list) => list);
1919 return temp;
1922 internal static List<TSource> ToListOrdered<TSource> (this ParallelQuery<TSource> source)
1924 List<TSource> result = new List<TSource> ();
1926 foreach (TSource element in source)
1927 result.Add (element);
1929 return result;
1932 public static TSource[] ToArray<TSource> (this ParallelQuery<TSource> source)
1934 if (source == null)
1935 throw new ArgumentNullException ("source");
1937 if (source.Node.IsOrdered ())
1938 return ToListOrdered (source).ToArray ();
1940 TSource[] result = null;
1942 Func<List<TSource>, TSource, List<TSource>> intermediate = (list, e) => {
1943 list.Add (e); return list;
1946 Action<IList<List<TSource>>> final = (list) => {
1947 int count = 0;
1949 for (int i = 0; i < list.Count; i++)
1950 count += list[i].Count;
1952 result = new TSource[count];
1953 int insertIndex = -1;
1955 for (int i = 0; i < list.Count; i++)
1956 for (int j = 0; j < list[i].Count; j++)
1957 result [++insertIndex] = list[i][j];
1960 ParallelExecuter.ProcessAndAggregate<TSource, List<TSource>> (source.Node,
1961 () => new List<TSource> (),
1962 intermediate,
1963 final);
1965 return result;
1968 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this ParallelQuery<TSource> source,
1969 Func<TSource, TKey> keySelector,
1970 IEqualityComparer<TKey> comparer)
1972 return ToDictionary<TSource, TKey, TSource> (source, keySelector, (e) => e, comparer);
1975 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this ParallelQuery<TSource> source,
1976 Func<TSource, TKey> keySelector)
1978 return ToDictionary<TSource, TKey, TSource> (source, keySelector, (e) => e, EqualityComparer<TKey>.Default);
1981 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
1982 Func<TSource, TKey> keySelector,
1983 Func<TSource, TElement> elementSelector)
1985 return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
1988 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
1989 Func<TSource, TKey> keySelector,
1990 Func<TSource, TElement> elementSelector,
1991 IEqualityComparer<TKey> comparer)
1993 if (source == null)
1994 throw new ArgumentNullException ("source");
1995 if (keySelector == null)
1996 throw new ArgumentNullException ("keySelector");
1997 if (comparer == null)
1998 comparer = EqualityComparer<TKey>.Default;
1999 if (elementSelector == null)
2000 throw new ArgumentNullException ("elementSelector");
2002 return source.Aggregate (() => new Dictionary<TKey, TElement> (comparer),
2003 (d, e) => { d.Add (keySelector (e), elementSelector (e)); return d; },
2004 (d1, d2) => { foreach (var couple in d2) d1.Add (couple.Key, couple.Value); return d1; },
2005 (d) => d);
2008 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this ParallelQuery<TSource> source,
2009 Func<TSource, TKey> keySelector)
2011 return ToLookup<TSource, TKey, TSource> (source, keySelector, (e) => e, EqualityComparer<TKey>.Default);
2014 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this ParallelQuery<TSource> source,
2015 Func<TSource, TKey> keySelector,
2016 IEqualityComparer<TKey> comparer)
2018 return ToLookup<TSource, TKey, TSource> (source, keySelector, (e) => e, comparer);
2021 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
2022 Func<TSource, TKey> keySelector,
2023 Func<TSource, TElement> elementSelector)
2025 return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
2028 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
2029 Func<TSource, TKey> keySelector,
2030 Func<TSource, TElement> elementSelector,
2031 IEqualityComparer<TKey> comparer)
2033 if (source == null)
2034 throw new ArgumentNullException ("source");
2035 if (keySelector == null)
2036 throw new ArgumentNullException ("keySelector");
2037 if (comparer == null)
2038 comparer = EqualityComparer<TKey>.Default;
2039 if (elementSelector == null)
2040 throw new ArgumentNullException ("elementSelector");
2042 ConcurrentLookup<TKey, TElement> lookup = new ConcurrentLookup<TKey, TElement> (comparer);
2043 source.ForAll ((e) => lookup.Add (keySelector (e), elementSelector (e)));
2045 return lookup;
2047 #endregion
2049 #region Concat
2050 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than "
2051 + "System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method "
2052 + "to convert the right data source to System.Linq.ParallelQuery<T>.")]
2053 public static ParallelQuery<TSource> Concat<TSource>(this ParallelQuery<TSource> first,
2054 IEnumerable<TSource> second)
2056 throw new NotSupportedException ();
2059 public static ParallelQuery<TSource> Concat<TSource> (this ParallelQuery<TSource> first, ParallelQuery<TSource> second)
2061 return new ParallelQuery<TSource> (new QueryConcatNode<TSource> (first.Node, second.Node));
2063 #endregion
2065 #region DefaultIfEmpty
2066 public static ParallelQuery<TSource> DefaultIfEmpty<TSource> (this ParallelQuery<TSource> source)
2068 return source.DefaultIfEmpty (default (TSource));
2071 public static ParallelQuery<TSource> DefaultIfEmpty<TSource> (this ParallelQuery<TSource> source, TSource defaultValue)
2073 return new ParallelQuery<TSource> (new QueryDefaultEmptyNode<TSource> (source.Node, defaultValue));
2075 #endregion
2077 #region First
2078 public static TSource First<TSource> (this ParallelQuery<TSource> source)
2080 CancellationTokenSource src = new CancellationTokenSource ();
2081 IEnumerator<TSource> enumerator = source.WithImplementerToken (src).GetEnumerator ();
2083 if (enumerator == null || !enumerator.MoveNext ())
2084 throw new InvalidOperationException ("source contains no element");
2086 TSource result = enumerator.Current;
2087 src.Cancel ();
2088 enumerator.Dispose ();
2090 return result;
2093 public static TSource First<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
2095 return source.Where (predicate).First ();
2098 public static TSource FirstOrDefault<TSource> (this ParallelQuery<TSource> source)
2100 return source.DefaultIfEmpty ().First ();
2103 public static TSource FirstOrDefault<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
2105 return source.Where (predicate).FirstOrDefault ();
2107 #endregion
2109 #region Last
2110 public static TSource Last<TSource> (this ParallelQuery<TSource> source)
2112 return source.Reverse ().First ();
2115 public static TSource Last<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
2117 return source.Reverse ().First (predicate);
2120 public static TSource LastOrDefault<TSource> (this ParallelQuery<TSource> source)
2122 return source.Reverse ().FirstOrDefault ();
2125 public static TSource LastOrDefault<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
2127 return source.Reverse ().FirstOrDefault (predicate);
2129 #endregion
2131 #region Zip
2132 public static ParallelQuery<TResult> Zip<TFirst, TSecond, TResult> (this ParallelQuery<TFirst> first,
2133 ParallelQuery<TSecond> second,
2134 Func<TFirst, TSecond, TResult> resultSelector)
2136 if (first == null)
2137 throw new ArgumentNullException ("first");
2138 if (second == null)
2139 throw new ArgumentNullException ("second");
2140 if (resultSelector == null)
2141 throw new ArgumentNullException ("resultSelector");
2143 return new ParallelQuery<TResult> (new QueryZipNode<TFirst, TSecond, TResult> (resultSelector, first.Node, second.Node));
2146 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
2147 + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
2148 + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
2149 public static ParallelQuery<TResult> Zip<TFirst, TSecond, TResult> (this ParallelQuery<TFirst> first,
2150 IEnumerable<TSecond> second,
2151 Func<TFirst, TSecond, TResult> resultSelector)
2153 throw new NotSupportedException ();
2155 #endregion
2158 #endif