Merge branch 'master' of github.com:mono/mono
[mono.git] / mcs / class / System.Core / System.Linq / ParallelEnumerable.cs
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:
15 //
16 // The above copyright notice and this permission notice shall be included in
17 // all copies or substantial portions of the Software.
18 //
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.
26
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;
35
36 namespace System.Linq
37 {
38         public static class ParallelEnumerable
39         {
40                 #region Range & Repeat
41                 public static ParallelQuery<int> Range (int start, int count)
42                 {
43                         if (int.MaxValue - start < count)
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");
47
48                         return (new RangeList (start, count)).AsParallel ();
49                 }
50
51                 public static ParallelQuery<TResult> Repeat<TResult> (TResult obj, int count)
52                 {
53                         if (count < 0)
54                                 throw new ArgumentOutOfRangeException ("count", "count is less than 0");
55
56                         return (new RepeatList<TResult> (obj, count)).AsParallel ();
57                 }
58                 #endregion
59
60                 #region Empty
61                 public static ParallelQuery<TResult> Empty<TResult> ()
62                 {
63                         return Repeat<TResult> (default (TResult), 0);
64                 }
65                 #endregion
66
67                 #region AsParallel
68                 public static ParallelQuery<TSource> AsParallel<TSource> (this IEnumerable<TSource> source)
69                 {
70                         if (source == null)
71                                 throw new ArgumentNullException ("source");
72
73                         return new ParallelQuery<TSource> (new QueryStartNode<TSource> (source));
74                 }
75
76                 public static ParallelQuery<TSource> AsParallel<TSource> (this Partitioner<TSource> source)
77                 {
78                         if (source == null)
79                                 throw new ArgumentNullException ("source");
80
81                         return new ParallelQuery<TSource> (new QueryStartNode<TSource> (source));
82                 }
83
84                 public static ParallelQuery AsParallel (this IEnumerable source)
85                 {
86                         if (source == null)
87                                 throw new ArgumentNullException ("source");
88
89                         return new ParallelQuery<object> (new QueryStartNode<object> (source.Cast<object> ()));
90                 }
91
92                 public static IEnumerable<TSource> AsEnumerable<TSource> (this ParallelQuery<TSource> source)
93                 {
94                         if (source == null)
95                                 throw new ArgumentNullException ("source");
96
97                         return source.AsSequential ();
98                 }
99
100                 public static IEnumerable<TSource> AsSequential<TSource> (this ParallelQuery<TSource> source)
101                 {
102                         if (source == null)
103                                 throw new ArgumentNullException ("source");
104
105                         return source.Node.GetSequential ();
106                 }
107                 #endregion
108
109                 #region AsOrdered / AsUnordered
110                 public static ParallelQuery<TSource> AsOrdered<TSource> (this ParallelQuery<TSource> source)
111                 {
112                         if (source == null)
113                                 throw new ArgumentNullException ("source");
114
115                         return new ParallelQuery<TSource> (new QueryAsOrderedNode<TSource> (source.Node));
116                 }
117
118                 public static ParallelQuery<TSource> AsUnordered<TSource> (this ParallelQuery<TSource> source)
119                 {
120                         if (source == null)
121                                 throw new ArgumentNullException ("source");
122
123                         return new ParallelQuery<TSource> (new QueryAsUnorderedNode<TSource> (source.Node));
124                 }
125
126                 public static ParallelQuery AsOrdered (this ParallelQuery source)
127                 {
128                         if (source == null)
129                                 throw new ArgumentNullException ("source");
130
131                         return source.TypedQuery.AsOrdered ();
132                 }
133                 #endregion
134
135                 #region With*
136                 public static ParallelQuery<TSource> WithExecutionMode<TSource> (this ParallelQuery<TSource> source,
137                                                                                  ParallelExecutionMode executionMode)
138                 {
139                         if (source == null)
140                                 throw new ArgumentNullException ("source");
141
142                         return new ParallelQuery<TSource> (new ParallelExecutionModeNode<TSource> (executionMode, source.Node));
143                 }
144
145                 public static ParallelQuery<TSource> WithCancellation<TSource> (this ParallelQuery<TSource> source,
146                                                                                 CancellationToken cancellationToken)
147                 {
148                         if (source == null)
149                                 throw new ArgumentNullException ("source");
150
151                         return new ParallelQuery<TSource> (new CancellationTokenNode<TSource> (cancellationToken, source.Node));
152                 }
153
154                 public static ParallelQuery<TSource> WithMergeOptions<TSource> (this ParallelQuery<TSource> source,
155                                                                                 ParallelMergeOptions mergeOptions)
156                 {
157                         if (source == null)
158                                 throw new ArgumentNullException ("source");
159
160                         return new ParallelQuery<TSource> (new ParallelMergeOptionsNode<TSource> (mergeOptions, source.Node));
161                 }
162
163                 public static ParallelQuery<TSource> WithDegreeOfParallelism<TSource> (this ParallelQuery<TSource> source,
164                                                                                        int degreeParallelism)
165                 {
166                         if (degreeParallelism < 1 || degreeParallelism > 63)
167                                 throw new ArgumentException ("degreeOfParallelism is less than 1 or greater than 63", "degreeParallelism");
168                         if (source == null)
169                                 throw new ArgumentNullException ("source");
170
171                         return new ParallelQuery<TSource> (new DegreeOfParallelismNode<TSource> (degreeParallelism, source.Node));
172                 }
173
174                 internal static ParallelQuery<TSource> WithImplementerToken<TSource> (this ParallelQuery<TSource> source,
175                                                                                       CancellationTokenSource token)
176                 {
177                         return new ParallelQuery<TSource> (new ImplementerTokenNode<TSource> (token, source.Node));
178                 }
179                 #endregion
180
181                 #region Select
182                 public static ParallelQuery<TResult> Select<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, TResult> selector)
183                 {
184                         if (source == null)
185                                 throw new ArgumentNullException ("source");
186                         if (selector == null)
187                                 throw new ArgumentNullException ("selector");
188
189                         return new ParallelQuery<TResult> (new QuerySelectNode<TResult, TSource> (source.Node, selector));
190                 }
191
192                 public static ParallelQuery<TResult> Select<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, int, TResult> selector)
193                 {
194                         if (source == null)
195                                 throw new ArgumentNullException ("source");
196                         if (selector == null)
197                                 throw new ArgumentNullException ("selector");
198
199                         return new ParallelQuery<TResult> (new QuerySelectNode<TResult, TSource> (source.Node, selector));
200                 }
201                 #endregion
202                 
203                 #region SelectMany
204                 public static ParallelQuery<TResult> SelectMany<TSource, TResult> (this ParallelQuery<TSource> source,
205                                                                                    Func<TSource, IEnumerable<TResult>> selector)
206                 {
207                         return source.SelectMany (selector, (s, e) => e);
208                 }
209
210                 public static ParallelQuery<TResult> SelectMany<TSource, TResult> (this ParallelQuery<TSource> source,
211                                                                                    Func<TSource, int, IEnumerable<TResult>> selector)
212                 {
213                         return source.SelectMany (selector, (s, e) => e);
214                 }
215                 
216                 public static ParallelQuery<TResult> SelectMany<TSource, TCollection, TResult> (this ParallelQuery<TSource> source,
217                                                                                                 Func<TSource, IEnumerable<TCollection>> collectionSelector,
218                                                                                                 Func<TSource, TCollection, TResult> resultSelector)
219                 {
220                         return new ParallelQuery<TResult> (new QuerySelectManyNode<TSource, TCollection, TResult> (source.Node,
221                                                                                                                    collectionSelector,
222                                                                                                                    resultSelector));
223                 }
224                 
225                 public static ParallelQuery<TResult> SelectMany<TSource, TCollection, TResult> (this ParallelQuery<TSource> source,
226                                                                                                 Func<TSource, int, IEnumerable<TCollection>> collectionSelector,
227                                                                                                 Func<TSource, TCollection, TResult> resultSelector)
228                 {
229                         return new ParallelQuery<TResult> (new QuerySelectManyNode<TSource, TCollection, TResult> (source.Node,
230                                                                                                                    collectionSelector,
231                                                                                                                    resultSelector));
232                 }
233                 #endregion
234
235                 #region Where
236                 public static ParallelQuery<TSource> Where<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
237                 {
238                         if (source == null)
239                                 throw new ArgumentNullException ("source");
240                         if (predicate == null)
241                                 throw new ArgumentNullException ("predicate");
242
243                         return new ParallelQuery<TSource> (new QueryWhereNode<TSource> (source.Node, predicate));
244                 }
245
246                 public static ParallelQuery<TSource> Where<TSource> (this ParallelQuery<TSource> source, Func<TSource, int, bool> predicate)
247                 {
248                         if (source == null)
249                                 throw new ArgumentNullException ("source");
250                         if (predicate == null)
251                                 throw new ArgumentNullException ("predicate");
252
253                         return new ParallelQuery<TSource> (new QueryWhereNode<TSource> (source.Node, predicate));
254                 }
255                 #endregion
256
257                 #region Aggregate
258                 public static TSource Aggregate<TSource> (this ParallelQuery<TSource> source, Func<TSource, TSource, TSource> func)
259                 {
260                         if (source == null)
261                                 throw new ArgumentNullException ("source");
262                         if (func == null)
263                                 throw new ArgumentNullException ("func");
264
265                         return source.Aggregate<TSource, TSource, TSource> ((Func<TSource>)null,
266                                                                             func,
267                                                                             func,
268                                                                             (e) => e);
269                 }
270
271                 public static TAccumulate Aggregate<TSource, TAccumulate> (this ParallelQuery<TSource> source,
272                                                                              TAccumulate seed,
273                                                                              Func<TAccumulate, TSource, TAccumulate> func)
274                 {
275                         if (source == null)
276                                 throw new ArgumentNullException ("source");
277                         if (func == null)
278                                 throw new ArgumentNullException ("func");
279
280                         return source.Aggregate (seed, func, (e) => e);
281                 }
282
283                 public static TResult Aggregate<TSource, TAccumulate, TResult> (this ParallelQuery<TSource> source,
284                                                                                   TAccumulate seed,
285                                                                                   Func<TAccumulate, TSource, TAccumulate> func,
286                                                                                   Func<TAccumulate, TResult> resultSelector)
287                 {
288                         if (source == null)
289                                 throw new ArgumentNullException ("source");
290                         if (func == null)
291                                 throw new ArgumentNullException ("func");
292                         if (resultSelector == null)
293                                 throw new ArgumentNullException ("resultSelector");
294
295                         TAccumulate accumulator = seed;
296
297                         foreach (TSource value in source)
298                                 accumulator = func (accumulator, value);
299
300                         return resultSelector (accumulator);
301                 }
302
303                 public static TResult Aggregate<TSource, TAccumulate, TResult> (this ParallelQuery<TSource> source,
304                                                                                   TAccumulate seed,
305                                                                                   Func<TAccumulate, TSource, TAccumulate> updateAccumulatorFunc,
306                                                                                   Func<TAccumulate, TAccumulate, TAccumulate> combineAccumulatorsFunc,
307                                                                                   Func<TAccumulate, TResult> resultSelector)
308                 {
309                         if (source == null)
310                                 throw new ArgumentNullException ("source");
311                         if (updateAccumulatorFunc == null)
312                                 throw new ArgumentNullException ("updateAccumulatorFunc");
313                         if (combineAccumulatorsFunc == null)
314                                 throw new ArgumentNullException ("combineAccumulatorsFunc");
315                         if (resultSelector == null)
316                                 throw new ArgumentNullException ("resultSelector");
317
318                         return source.Aggregate (() => seed, updateAccumulatorFunc, combineAccumulatorsFunc, resultSelector);
319                 }
320
321                 public static TResult Aggregate<TSource, TAccumulate, TResult> (this ParallelQuery<TSource> source,
322                                                                                   Func<TAccumulate> seedFunc,
323                                                                                   Func<TAccumulate, TSource, TAccumulate> updateAccumulatorFunc,
324                                                                                   Func<TAccumulate, TAccumulate, TAccumulate> combineAccumulatorsFunc,
325                                                                                   Func<TAccumulate, TResult> resultSelector)
326                 {
327                         if (source == null)
328                                 throw new ArgumentNullException ("source");
329                         if (seedFunc == null)
330                                 throw new ArgumentNullException ("seedFunc");
331                         if (updateAccumulatorFunc == null)
332                                 throw new ArgumentNullException ("updateAccumulatorFunc");
333                         if (combineAccumulatorsFunc == null)
334                                 throw new ArgumentNullException ("combineAccumulatorsFunc");
335                         if (resultSelector == null)
336                                 throw new ArgumentNullException ("resultSelector");
337
338                         TAccumulate accumulator = default (TAccumulate);
339
340                         ParallelExecuter.ProcessAndAggregate<TSource, TAccumulate> (source.Node, seedFunc, updateAccumulatorFunc, (list) => {
341                                 accumulator = list [0];
342                                 for (int i = 1; i < list.Count; i++)
343                                         accumulator = combineAccumulatorsFunc (accumulator, list[i]);
344                         });
345
346                         return resultSelector (accumulator);;
347                 }
348                 #endregion
349
350                 #region ForAll
351                 public static void ForAll<TSource> (this ParallelQuery<TSource> source, Action<TSource> action)
352                 {
353                         if (source == null)
354                                 throw new ArgumentNullException ("source");
355                         if (action == null)
356                                 throw new ArgumentNullException ("action");
357
358                         ParallelExecuter.ProcessAndBlock (source.Node, (e, c) => action (e));
359                 }
360                 #endregion
361
362                 #region OrderBy
363                 public static OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey> (this ParallelQuery<TSource> source,
364                                                                                               Func<TSource, TKey> keySelector,
365                                                                                               IComparer<TKey> comparer)
366                 {
367                         if (source == null)
368                                 throw new ArgumentNullException ("source");
369                         if (keySelector == null)
370                                 throw new ArgumentNullException ("keySelector");
371                         if (comparer == null)
372                                 comparer = Comparer<TKey>.Default;
373
374                         Comparison<TSource> comparison = (e1, e2) => -comparer.Compare (keySelector (e1), keySelector (e2));
375
376                         return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
377                 }
378
379                 public static OrderedParallelQuery<TSource> OrderByDescending<TSource, TKey> (this ParallelQuery<TSource> source,
380                                                                                               Func<TSource, TKey> keySelector)
381                 {
382                         return OrderByDescending (source, keySelector, Comparer<TKey>.Default);
383                 }
384
385                 public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey> (this ParallelQuery<TSource> source,
386                                                                                     Func<TSource, TKey> keySelector)
387                 {
388                         return OrderBy (source, keySelector, Comparer<TKey>.Default);
389                 }
390
391                 public static OrderedParallelQuery<TSource> OrderBy<TSource, TKey> (this ParallelQuery<TSource> source,
392                                                                                     Func<TSource, TKey> keySelector,
393                                                                                     IComparer<TKey> comparer)
394                 {
395                         if (source == null)
396                                 throw new ArgumentNullException ("source");
397                         if (keySelector == null)
398                                 throw new ArgumentNullException ("keySelector");
399                         if (comparer == null)
400                                 comparer = Comparer<TKey>.Default;
401
402                         Comparison<TSource> comparison = (e1, e2) => comparer.Compare (keySelector (e1), keySelector (e2));
403
404                         return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
405                 }
406                 #endregion
407
408                 #region ThenBy
409                 public static OrderedParallelQuery<TSource> ThenBy<TSource, TKey> (this OrderedParallelQuery<TSource> source,
410                                                                                    Func<TSource, TKey> keySelector)
411                 {
412                         return ThenBy (source, keySelector, Comparer<TKey>.Default);
413                 }
414
415                 public static OrderedParallelQuery<TSource> ThenBy<TSource, TKey> (this OrderedParallelQuery<TSource> source,
416                                                                                    Func<TSource, TKey> keySelector,
417                                                                                    IComparer<TKey> comparer)
418                 {
419                         if (source == null)
420                                 throw new ArgumentNullException ("source");
421                         if (keySelector == null)
422                                 throw new ArgumentNullException ("keySelector");
423                         if (comparer == null)
424                                 comparer = Comparer<TKey>.Default;
425
426                         Comparison<TSource> comparison = (e1, e2) => comparer.Compare (keySelector (e1), keySelector (e2));
427
428                         return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
429                 }
430
431                 public static OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey> (this OrderedParallelQuery<TSource> source,
432                                                                                              Func<TSource, TKey> keySelector)
433                 {
434                         return ThenByDescending (source, keySelector, Comparer<TKey>.Default);
435                 }
436
437                 public static OrderedParallelQuery<TSource> ThenByDescending<TSource, TKey> (this OrderedParallelQuery<TSource> source,
438                                                                                              Func<TSource, TKey> keySelector,
439                                                                                              IComparer<TKey> comparer)
440                 {
441                         if (source == null)
442                                 throw new ArgumentNullException ("source");
443                         if (keySelector == null)
444                                 throw new ArgumentNullException ("keySelector");
445                         if (comparer == null)
446                                 comparer = Comparer<TKey>.Default;
447
448                         Comparison<TSource> comparison = (e1, e2) => -comparer.Compare (keySelector (e1), keySelector (e2));
449
450                         return new OrderedParallelQuery<TSource> (new QueryOrderByNode<TSource> (source.Node, comparison));
451                 }
452                 #endregion
453
454                 #region All
455                 public static bool All<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
456                 {
457                         if (source == null)
458                                 throw new ArgumentNullException ("source");
459                         if (predicate == null)
460                                 throw new ArgumentNullException ("predicate");
461
462                         CancellationTokenSource src = new CancellationTokenSource ();
463                         ParallelQuery<TSource> innerQuery = source.WithImplementerToken (src);
464
465                         bool result = true;
466                         try {
467                                 innerQuery.ForAll ((e) => {
468                                                 if (!predicate (e)) {
469                                                         result = false;
470                                                         src.Cancel ();
471                                                 }
472                                         });
473                         } catch (OperationCanceledException e) {
474                                 if (e.CancellationToken != src.Token)
475                                         throw e;
476                         }
477
478                         return result;
479                 }
480                 #endregion
481
482                 #region Any
483                 public static bool Any<TSource> (this ParallelQuery<TSource> source)
484                 {
485                         return Any<TSource> (source, (_) => true);
486                 }
487
488                 public static bool Any<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
489                 {
490                         if (source == null)
491                                 throw new ArgumentNullException ("source");
492                         if (predicate == null)
493                                 throw new ArgumentNullException ("predicate");
494
495                         return !source.All ((e) => !predicate (e));
496                 }
497                 #endregion
498
499                 #region Contains
500                 public static bool Contains<TSource> (this ParallelQuery<TSource> source, TSource value)
501                 {
502                         return Contains<TSource> (source, value, EqualityComparer<TSource>.Default);
503                 }
504
505                 public static bool Contains<TSource> (this ParallelQuery<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
506                 {
507                         if (source == null)
508                                 throw new ArgumentNullException ("source");
509                         if (comparer == null)
510                                 comparer = EqualityComparer<TSource>.Default;
511
512                         return Any<TSource> (source, (e) => comparer.Equals (value));
513                 }
514                 #endregion
515
516                 #region SequenceEqual
517                 public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first,
518                                                            ParallelQuery<TSource> second)
519                 {
520                         if (first == null)
521                                 throw new ArgumentNullException ("first");
522                         if (second == null)
523                                 throw new ArgumentNullException ("second");
524
525                         return first.SequenceEqual (second, EqualityComparer<TSource>.Default);
526                 }
527
528                 public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first,
529                                                            ParallelQuery<TSource> second,
530                                                            IEqualityComparer<TSource> comparer)
531                 {
532                         if (first == null)
533                                 throw new ArgumentNullException ("first");
534                         if (second == null)
535                                 throw new ArgumentNullException ("second");
536                         if (comparer == null)
537                                 comparer = EqualityComparer<TSource>.Default;
538
539                         CancellationTokenSource source = new CancellationTokenSource ();
540                         ParallelQuery<bool> innerQuery
541                                 = first.Zip (second, (e1, e2) => comparer.Equals (e1, e2)).Where ((e) => !e).WithImplementerToken (source);
542
543                         bool result = true;
544
545                         try {
546                                 innerQuery.ForAll ((value) => {
547                                                 result = false;
548                                                 source.Cancel ();
549                                         });
550                         } catch (OperationCanceledException e) {
551                                 if (e.CancellationToken != source.Token)
552                                         throw e;
553                         }
554
555                         return result;
556                 }
557
558                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
559                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
560                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
561                 public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first, IEnumerable<TSource> second)
562                 {
563                         throw new NotSupportedException ();
564                 }
565
566                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
567                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
568                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
569                 public static bool SequenceEqual<TSource> (this ParallelQuery<TSource> first,
570                                                               IEnumerable<TSource> second,
571                                                               IEqualityComparer<TSource> comparer)
572                 {
573                         throw new NotSupportedException ();
574                 }
575
576                 #endregion
577                 
578                 #region GroupBy
579                 public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this ParallelQuery<TSource> source,
580                                                                                               Func<TSource, TKey> keySelector)
581                 {
582                         return source.GroupBy (keySelector, EqualityComparer<TKey>.Default);
583                 }
584                 
585                 public static ParallelQuery<IGrouping<TKey, TSource>> GroupBy<TSource, TKey> (this ParallelQuery<TSource> source,
586                                                                                               Func<TSource, TKey> keySelector,
587                                                                                               IEqualityComparer<TKey> comparer)
588                 {
589                         return source.GroupBy (keySelector, (e) => e, comparer);
590                 }
591                 
592                 public static ParallelQuery<IGrouping<TKey, TElement>> GroupBy<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
593                                                                                                          Func<TSource, TKey> keySelector,
594                                                                                                          Func<TSource, TElement> elementSelector)
595                 {
596                         return source.GroupBy (keySelector, elementSelector, EqualityComparer<TKey>.Default);
597                 }
598                 
599                 public static ParallelQuery<TResult> GroupBy<TSource, TKey, TResult> (this ParallelQuery<TSource> source,
600                                                                                       Func<TSource, TKey> keySelector,
601                                                                                       Func<TKey, IEnumerable<TSource>, TResult> resultSelector)
602                 {
603                         return source.GroupBy (keySelector)
604                                 .Select ((g) => resultSelector (g.Key, (IEnumerable<TSource>)g));
605                 }
606                 
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,
610                                                                                                          IEqualityComparer<TKey> comparer)
611                 {
612                         if (source == null)
613                                 throw new ArgumentNullException ("source");
614                         if (keySelector == null)
615                                 throw new ArgumentNullException ("keySelector");
616                         if (elementSelector == null)
617                                 throw new ArgumentNullException ("elementSelector");
618                         if (comparer == null)
619                                 comparer = EqualityComparer<TKey>.Default;
620
621                         return new ParallelQuery<IGrouping<TKey, TElement>> (new QueryGroupByNode<TSource, TKey, TElement> (source.Node, keySelector, elementSelector, comparer));
622                 }
623                 
624                 public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult> (this ParallelQuery<TSource> source,
625                                                                                                 Func<TSource, TKey> keySelector,
626                                                                                                 Func<TSource, TElement> elementSelector,
627                                                                                                 Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
628                 {
629                         return source.GroupBy (keySelector, elementSelector)
630                                 .Select ((g) => resultSelector (g.Key, (IEnumerable<TElement>)g));
631                 }
632                 
633                 public static ParallelQuery<TResult> GroupBy<TSource, TKey, TResult> (this ParallelQuery<TSource> source,
634                                                                                       Func<TSource, TKey> keySelector,
635                                                                                       Func<TKey, IEnumerable<TSource>, TResult> resultSelector,
636                                                                                       IEqualityComparer<TKey> comparer)
637                 {
638                         return source.GroupBy (keySelector, comparer)
639                                 .Select ((g) => resultSelector (g.Key, (IEnumerable<TSource>)g));
640                 }
641                 
642                 public static ParallelQuery<TResult> GroupBy<TSource, TKey, TElement, TResult> (this ParallelQuery<TSource> source,
643                                                                                                 Func<TSource, TKey> keySelector,
644                                                                                                 Func<TSource, TElement> elementSelector,
645                                                                                                 Func<TKey, IEnumerable<TElement>, TResult> resultSelector,
646                                                                                                 IEqualityComparer<TKey> comparer)
647                 {
648                         return source.GroupBy (keySelector, elementSelector, comparer)
649                                 .Select ((g) => resultSelector (g.Key, (IEnumerable<TElement>)g));
650                 }
651                 #endregion
652
653                 #region GroupJoin
654                 public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
655                                                                                                ParallelQuery<TInner> inner,
656                                                                                                Func<TOuter, TKey> outerKeySelector,
657                                                                                                Func<TInner, TKey> innerKeySelector,
658                                                                                                Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
659                 {
660                         return outer.GroupJoin (inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
661                 }
662                 
663                 public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
664                                                                                                ParallelQuery<TInner> inner,
665                                                                                                Func<TOuter, TKey> outerKeySelector,
666                                                                                                Func<TInner, TKey> innerKeySelector,
667                                                                                                Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
668                                                                                                IEqualityComparer<TKey> comparer)
669                 {
670                         return outer.Join (inner.GroupBy (innerKeySelector, (e) => e), outerKeySelector, (e) => e.Key, (e1, e2) => resultSelector (e1, e2), comparer);
671                 }
672                 
673                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
674                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
675                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
676                 public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
677                                                                                                IEnumerable<TInner> inner,
678                                                                                                Func<TOuter, TKey> outerKeySelector,
679                                                                                                Func<TInner, TKey> innerKeySelector,
680                                                                                                Func<TOuter, IEnumerable<TInner>, TResult> resultSelector)
681                 {
682                         throw new NotSupportedException ();
683                 }
684                 
685                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
686                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
687                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
688                 public static ParallelQuery<TResult> GroupJoin<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
689                                                                                                IEnumerable<TInner> inner,
690                                                                                                Func<TOuter, TKey> outerKeySelector,
691                                                                                                Func<TInner, TKey> innerKeySelector,
692                                                                                                Func<TOuter, IEnumerable<TInner>, TResult> resultSelector,
693                                                                                                IEqualityComparer<TKey> comparer)
694                 {
695                         throw new NotSupportedException ();
696                 }
697                 #endregion
698
699                 #region ElementAt
700                 public static TSource ElementAt<TSource> (this ParallelQuery<TSource> source, int index)
701                 {
702                         if (source == null)
703                                 throw new ArgumentNullException ("source");
704                         if (index < 0)
705                                 throw new ArgumentOutOfRangeException ("index");
706                         if (index == 0) {
707                                 try {
708                                         return source.First ();
709                                 } catch (InvalidOperationException) {
710                                         throw new ArgumentOutOfRangeException ("index");
711                                 }
712                         }
713
714                         TSource result = default (TSource);
715
716                         ParallelQuery<TSource> innerQuery = source.Where ((e, i) => i == index);
717
718                         try {
719                                 result = innerQuery.First ();
720                         } catch (InvalidOperationException) {
721                                 throw new ArgumentOutOfRangeException ("index");
722                         }
723
724                         return result;
725                 }
726
727                 public static TSource ElementAtOrDefault<TSource> (this ParallelQuery<TSource> source, int index)
728                 {
729                         if (source == null)
730                                 throw new ArgumentNullException ("source");
731
732                         try {
733                                 return source.ElementAt (index);
734                         } catch (ArgumentOutOfRangeException) {
735                                 return default (TSource);
736                         }
737                 }
738                 #endregion
739
740                 #region Intersect
741                 public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first,
742                                                                          ParallelQuery<TSource> second)
743                 {
744                         return Intersect<TSource> (first, second, EqualityComparer<TSource>.Default);
745                 }
746
747                 public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first,
748                                                                          ParallelQuery<TSource> second,
749                                                                          IEqualityComparer<TSource> comparer)
750                 {
751                         if (first == null)
752                                 throw new ArgumentNullException ("first");
753                         if (second == null)
754                                 throw new ArgumentNullException ("second");
755                         if (comparer == null)
756                                 comparer = EqualityComparer<TSource>.Default;
757
758                         return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Intersect, comparer, first.Node, second.Node));
759                 }
760
761                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
762                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
763                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
764                 public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first, IEnumerable<TSource> second)
765                 {
766                         throw new NotSupportedException ();
767                 }
768
769                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
770                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
771                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
772                 public static ParallelQuery<TSource> Intersect<TSource> (this ParallelQuery<TSource> first,
773                                                                          IEnumerable<TSource> second,
774                                                                          IEqualityComparer<TSource> comparer)
775                 {
776                         throw new NotSupportedException ();
777                 }
778                 #endregion
779
780                 #region Join
781                 public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
782                                                                                           ParallelQuery<TInner> inner,
783                                                                                           Func<TOuter, TKey> outerKeySelector,
784                                                                                           Func<TInner, TKey> innerKeySelector,
785                                                                                           Func<TOuter, TInner, TResult> resultSelector)
786                 {
787                         return outer.Join (inner, outerKeySelector, innerKeySelector, resultSelector, EqualityComparer<TKey>.Default);
788                 }
789                 
790                 public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
791                                                                                           ParallelQuery<TInner> inner,
792                                                                                           Func<TOuter, TKey> outerKeySelector,
793                                                                                           Func<TInner, TKey> innerKeySelector,
794                                                                                           Func<TOuter, TInner, TResult> resultSelector,
795                                                                                           IEqualityComparer<TKey> comparer)
796                 {
797                         return new ParallelQuery<TResult> (new QueryJoinNode<TOuter, TInner, TKey, TResult> (outer.Node, inner.Node, outerKeySelector, innerKeySelector, resultSelector, comparer));
798                 }
799                 
800                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
801                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
802                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
803                 public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
804                                                                                           IEnumerable<TInner> inner,
805                                                                                           Func<TOuter, TKey> outerKeySelector,
806                                                                                           Func<TInner, TKey> innerKeySelector,
807                                                                                           Func<TOuter, TInner, TResult> resultSelector)
808                 {
809                         throw new NotSupportedException ();
810                 }
811
812                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
813                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
814                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
815                 public static ParallelQuery<TResult> Join<TOuter, TInner, TKey, TResult> (this ParallelQuery<TOuter> outer,
816                                                                                           IEnumerable<TInner> inner,
817                                                                                           Func<TOuter, TKey> outerKeySelector,
818                                                                                           Func<TInner, TKey> innerKeySelector,
819                                                                                           Func<TOuter, TInner, TResult> resultSelector,
820                                                                                           IEqualityComparer<TKey> comparer)
821                 {
822                         throw new NotSupportedException ();
823                 }
824                 #endregion
825
826                 #region Except
827                 public static ParallelQuery<TSource> Except<TSource> (this ParallelQuery<TSource> first,
828                                                                       ParallelQuery<TSource> second)
829                 {
830                         return Except<TSource> (first, second, EqualityComparer<TSource>.Default);
831                 }
832
833                 public static ParallelQuery<TSource> Except<TSource> (this ParallelQuery<TSource> first,
834                                                                       ParallelQuery<TSource> second,
835                                                                       IEqualityComparer<TSource> comparer)
836                 {
837                         if (first == null)
838                                 throw new ArgumentNullException ("first");
839                         if (second == null)
840                                 throw new ArgumentNullException ("second");
841                         if (comparer == null)
842                                 comparer = EqualityComparer<TSource>.Default;
843
844                         return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Except,
845                                                                                       comparer, first.Node, second.Node));
846                 }
847
848                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
849                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
850                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
851                 public static ParallelQuery<TSource> Except<TSource> (this ParallelQuery<TSource> first,
852                                                                       IEnumerable<TSource> second)
853                 {
854                         throw new NotSupportedException ();
855                 }
856
857                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
858                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
859                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
860                 public static ParallelQuery<TSource> Except<TSource> (this ParallelQuery<TSource> first,
861                                                                       IEnumerable<TSource> second,
862                                                                       IEqualityComparer<TSource> comparer)
863                 {
864                         throw new NotSupportedException ();
865                 }
866                 #endregion
867
868                 #region Distinct
869                 public static ParallelQuery<TSource> Distinct<TSource> (this ParallelQuery<TSource> source)
870                 {
871                         return Distinct<TSource> (source, EqualityComparer<TSource>.Default);
872                 }
873
874                 public static ParallelQuery<TSource> Distinct<TSource> (this ParallelQuery<TSource> source, IEqualityComparer<TSource> comparer)
875                 {
876                         if (source == null)
877                                 throw new ArgumentNullException ("source");
878                         if (comparer == null)
879                                 comparer = EqualityComparer<TSource>.Default;
880
881                         return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Distinct, comparer,
882                                                                                       source.Node, null));
883                 }
884                 #endregion
885
886                 #region Union
887                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
888                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
889                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
890                 public static ParallelQuery<TSource> Union<TSource> (this ParallelQuery<TSource> first,
891                                                                      IEnumerable<TSource> second)
892                 {
893                         throw new NotSupportedException ();
894                 }
895
896                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
897                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
898                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
899                 public static ParallelQuery<TSource> Union<TSource>(this ParallelQuery<TSource> first,
900                                                                     IEnumerable<TSource> second,
901                                                                     IEqualityComparer<TSource> comparer)
902                 {
903                         throw new NotSupportedException ();
904                 }
905
906                 public static ParallelQuery<TSource> Union<TSource> (this ParallelQuery<TSource> first,
907                                                                      ParallelQuery<TSource> second)
908                 {
909                         return first.Union (second, EqualityComparer<TSource>.Default);
910                 }
911
912                 public static ParallelQuery<TSource> Union<TSource> (this ParallelQuery<TSource> first,
913                                                                      ParallelQuery<TSource> second,
914                                                                      IEqualityComparer<TSource> comparer)
915                 {
916                         if (first == null)
917                                 throw new ArgumentNullException ("first");
918                         if (second == null)
919                                 throw new ArgumentNullException ("second");
920                         if (comparer == null)
921                                 comparer = EqualityComparer<TSource>.Default;
922
923                         return new ParallelQuery<TSource> (new QuerySetNode<TSource> (SetInclusionDefaults.Union, comparer, first.Node, second.Node));
924                 }
925                 #endregion
926
927                 #region Take
928                 public static ParallelQuery<TSource> Take<TSource> (this ParallelQuery<TSource> source, int count)
929                 {
930                         if (source == null)
931                                 throw new ArgumentNullException ("source");
932
933                         return new ParallelQuery<TSource> (new QueryHeadWorkerNode<TSource> (source.Node, count));
934                 }
935
936                 public static ParallelQuery<TSource> TakeWhile<TSource> (this ParallelQuery<TSource> source,
937                                                                          Func<TSource, bool> predicate)
938                 {
939                         if (source == null)
940                                 throw new ArgumentNullException ("source");
941                         if (predicate == null)
942                                 throw new ArgumentNullException ("predicate");
943
944                         return new ParallelQuery<TSource> (new QueryHeadWorkerNode<TSource> (source.Node, (e, _) => predicate (e), false));
945                 }
946
947                 public static ParallelQuery<TSource> TakeWhile<TSource> (this ParallelQuery<TSource> source,
948                                                                          Func<TSource, int, bool> predicate)
949                 {
950                         if (source == null)
951                                 throw new ArgumentNullException ("source");
952                         if (predicate == null)
953                                 throw new ArgumentNullException ("predicate");
954
955                         return new ParallelQuery<TSource> (new QueryHeadWorkerNode<TSource> (source.Node, predicate, true));
956                 }
957                 #endregion
958
959                 #region Skip
960                 public static ParallelQuery<TSource> Skip<TSource> (this ParallelQuery<TSource> source, int count)
961                 {
962                         if (source == null)
963                                 throw new ArgumentNullException ("source");
964
965                         return source.Node.IsOrdered () ?
966                                 source.Where ((e, i) => i >= count) :
967                                 source.Where ((e) => count < 0 || Interlocked.Decrement (ref count) < 0);
968
969                 }
970
971                 public static ParallelQuery<TSource> SkipWhile<TSource> (this ParallelQuery<TSource> source,
972                                                                          Func<TSource, bool> predicate)
973                 {
974                         if (source == null)
975                                 throw new ArgumentNullException ("source");
976                         if (predicate == null)
977                                 throw new ArgumentNullException ("predicate");
978
979                         return source.Node.IsOrdered () ?
980                                 source.SkipWhile ((e, i) => predicate (e)) :
981                                 source.Where ((e) => !predicate (e));
982                 }
983
984                 public static ParallelQuery<TSource> SkipWhile<TSource> (this ParallelQuery<TSource> source,
985                                                                          Func<TSource, int, bool> predicate)
986                 {
987                         if (source == null)
988                                 throw new ArgumentNullException ("source");
989                         if (predicate == null)
990                                 throw new ArgumentNullException ("predicate");
991
992                         int indexCache = int.MaxValue;
993
994                         return source.Where ((e, i) => i >= indexCache || (!predicate (e, i) && (indexCache = i) == i));
995                 }
996                 #endregion
997
998                 #region Single
999                 static TSource SingleInternal<TSource> (this ParallelQuery<TSource> source, params TSource[] init)
1000                 {
1001                         TSource result = default(TSource);
1002                         bool hasValue = false;
1003
1004                         foreach (TSource element in source) {
1005                                 if (hasValue)
1006                                         throw new InvalidOperationException ("The input sequence contains more than one element.");
1007
1008                                 result = element;
1009                                 hasValue = true;
1010                         }
1011
1012                         if (!hasValue && init.Length != 0) {
1013                                 result = init[0];
1014                                 hasValue = true;
1015                         }
1016
1017                         if (!hasValue)
1018                                 throw new InvalidOperationException ("The input sequence is empty.");
1019
1020                         return result;
1021                 }
1022
1023                 public static TSource Single<TSource> (this ParallelQuery<TSource> source)
1024                 {
1025                         if (source == null)
1026                                 throw new ArgumentNullException ("source");
1027
1028                         return SingleInternal<TSource> (source);
1029                 }
1030
1031                 public static TSource Single<TSource> (this ParallelQuery<TSource> source,
1032                                                        Func<TSource, bool> predicate)
1033                 {
1034                         if (source == null)
1035                                 throw new ArgumentNullException ("source");
1036                         if (predicate == null)
1037                                 throw new ArgumentNullException ("predicate");
1038
1039                         return source.Where (predicate).Single ();
1040                 }
1041
1042                 public static TSource SingleOrDefault<TSource> (this ParallelQuery<TSource> source)
1043                 {
1044                         if (source == null)
1045                                 throw new ArgumentNullException ("source");
1046
1047                         return SingleInternal<TSource> (source, default (TSource));
1048                 }
1049
1050                 public static TSource SingleOrDefault<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
1051                 {
1052                         if (source == null)
1053                                 throw new ArgumentNullException ("source");
1054                         if (predicate == null)
1055                                 throw new ArgumentNullException ("predicate");
1056
1057                         return source.Where (predicate).SingleOrDefault ();
1058                 }
1059                 #endregion
1060
1061                 #region Count
1062                 public static int Count<TSource> (this ParallelQuery<TSource> source)
1063                 {
1064                         if (source == null)
1065                                 throw new ArgumentNullException ("source");
1066
1067                         return source.Aggregate<TSource, int, int> (() => 0,
1068                                                                    (acc, e) => acc + 1,
1069                                                                    (acc1, acc2) => acc1 + acc2,
1070                                                                    (result) => result);
1071                 }
1072
1073                 public static int Count<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
1074                 {
1075                         if (source == null)
1076                                 throw new ArgumentNullException ("source");
1077                         if (predicate == null)
1078                                 throw new ArgumentNullException ("predicate");
1079
1080                         return source.Where (predicate).Count ();
1081                 }
1082
1083                 public static long LongCount<TSource> (this ParallelQuery<TSource> source)
1084                 {
1085                         if (source == null)
1086                                 throw new ArgumentNullException ("source");
1087
1088                         return source.Aggregate<TSource, long, long> (() => 0,
1089                                                                       (acc, e) => acc + 1,
1090                                                                       (acc1, acc2) => acc1 + acc2,
1091                                                                       (result) => result);
1092                 }
1093
1094                 public static long LongCount<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
1095                 {
1096                         if (source == null)
1097                                 throw new ArgumentNullException ("source");
1098                         if (predicate == null)
1099                                 throw new ArgumentNullException ("predicate");
1100
1101                         return source.Where (predicate).LongCount ();
1102                 }
1103                 #endregion
1104
1105                 #region Average
1106                 public static double Average (this ParallelQuery<int> source)
1107                 {
1108                         if (source == null)
1109                                 throw new ArgumentNullException ("source");
1110
1111                         return source.Aggregate (() => new int[2],
1112                                                 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1113                                                 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1114                                                 (acc) => acc[0] / ((double)acc[1]));
1115                 }
1116
1117                 public static double Average (this ParallelQuery<long> source)
1118                 {
1119                         if (source == null)
1120                                 throw new ArgumentNullException ("source");
1121
1122                         return source.Aggregate (() => new long[2],
1123                                                 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1124                                                 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1125                                                 (acc) => acc[0] / ((double)acc[1]));
1126                 }
1127
1128                 public static decimal Average (this ParallelQuery<decimal> source)
1129                 {
1130                         if (source == null)
1131                                 throw new ArgumentNullException ("source");
1132
1133                         return source.Aggregate (() => new decimal[2],
1134                                                 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1135                                                 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1136                                                 (acc) => acc[0] / acc[1]);
1137                 }
1138
1139                 public static double Average (this ParallelQuery<double> source)
1140                 {
1141                         if (source == null)
1142                                 throw new ArgumentNullException ("source");
1143
1144                         return source.Aggregate (() => new double[2],
1145                                                 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1146                                                 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1147                                                 (acc) => acc[0] / ((double)acc[1]));
1148                 }
1149
1150                 public static float Average (this ParallelQuery<float> source)
1151                 {
1152                         if (source == null)
1153                                 throw new ArgumentNullException ("source");
1154
1155                         return source.Aggregate (() => new float[2],
1156                                                 (acc, e) => { acc[0] += e; acc[1]++; return acc; },
1157                                                 (acc1, acc2) => { acc1[0] += acc2[0]; acc1[1] += acc2[1]; return acc1; },
1158                                                 (acc) => acc[0] / acc[1]);
1159                 }
1160                 #endregion
1161
1162                 #region More Average
1163                 public static double? Average (this ParallelQuery<int?> source)
1164                 {
1165                         if (source == null)
1166                                 throw new ArgumentNullException ("source");
1167
1168                         return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();;
1169                 }
1170
1171                 public static double? Average (this ParallelQuery<long?> source)
1172                 {
1173                         if (source == null)
1174                                 throw new ArgumentNullException ("source");
1175
1176                         return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
1177                 }
1178
1179                 public static decimal? Average (this ParallelQuery<decimal?> source)
1180                 {
1181                         if (source == null)
1182                                 throw new ArgumentNullException ("source");
1183
1184                         return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
1185                 }
1186
1187                 public static double? Average (this ParallelQuery<double?> source)
1188                 {
1189                         if (source == null)
1190                                 throw new ArgumentNullException ("source");
1191
1192                         return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
1193                 }
1194
1195                 public static float? Average (this ParallelQuery<float?> source)
1196                 {
1197                         if (source == null)
1198                                 throw new ArgumentNullException ("source");
1199
1200                         return source.Select ((e) => e.HasValue ? e.Value : 0).Average ();
1201                 }
1202
1203                 public static double Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> func)
1204                 {
1205                         if (source == null)
1206                                 throw new ArgumentNullException ("source");
1207                         if (func == null)
1208                                 throw new ArgumentNullException ("func");
1209
1210                         return source.Select (func).Average ();
1211                 }
1212
1213                 public static double Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> func)
1214                 {
1215                         if (source == null)
1216                                 throw new ArgumentNullException ("source");
1217                         if (func == null)
1218                                 throw new ArgumentNullException ("func");
1219
1220                         return source.Select (func).Average ();
1221                 }
1222
1223                 public static float Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> func)
1224                 {
1225                         if (source == null)
1226                                 throw new ArgumentNullException ("source");
1227                         if (func == null)
1228                                 throw new ArgumentNullException ("func");
1229
1230                         return source.Select (func).Average ();
1231                 }
1232
1233                 public static double Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> func)
1234                 {
1235                         if (source == null)
1236                                 throw new ArgumentNullException ("source");
1237                         if (func == null)
1238                                 throw new ArgumentNullException ("func");
1239
1240                         return source.Select (func).Average ();
1241                 }
1242
1243                 public static decimal Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> func)
1244                 {
1245                         if (source == null)
1246                                 throw new ArgumentNullException ("source");
1247                         if (func == null)
1248                                 throw new ArgumentNullException ("func");
1249
1250                         return source.Select (func).Average ();
1251                 }
1252
1253                 public static double? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> func)
1254                 {
1255                         if (source == null)
1256                                 throw new ArgumentNullException ("source");
1257                         if (func == null)
1258                                 throw new ArgumentNullException ("func");
1259
1260                         return source.Select (func).Average ();
1261                 }
1262
1263                 public static double? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> func)
1264                 {
1265                         if (source == null)
1266                                 throw new ArgumentNullException ("source");
1267                         if (func == null)
1268                                 throw new ArgumentNullException ("func");
1269
1270                         return source.Select (func).Average ();
1271                 }
1272
1273                 public static float? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> func)
1274                 {
1275                         if (source == null)
1276                                 throw new ArgumentNullException ("source");
1277                         if (func == null)
1278                                 throw new ArgumentNullException ("func");
1279
1280                         return source.Select (func).Average ();
1281                 }
1282
1283                 public static double? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> func)
1284                 {
1285                         if (source == null)
1286                                 throw new ArgumentNullException ("source");
1287                         if (func == null)
1288                                 throw new ArgumentNullException ("func");
1289
1290                         return source.Select (func).Average ();
1291                 }
1292
1293                 public static decimal? Average<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> func)
1294                 {
1295                         if (source == null)
1296                                 throw new ArgumentNullException ("source");
1297                         if (func == null)
1298                                 throw new ArgumentNullException ("func");
1299
1300                         return source.Select (func).Average ();
1301                 }
1302                 #endregion
1303
1304                 #region Sum
1305                 public static int Sum (this ParallelQuery<int> source)
1306                 {
1307                         if (source == null)
1308                                 throw new ArgumentNullException ("source");
1309
1310                         return source.Aggregate (0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1311                 }
1312
1313                 public static long Sum (this ParallelQuery<long> source)
1314                 {
1315                         if (source == null)
1316                                 throw new ArgumentNullException ("source");
1317
1318                         return source.Aggregate ((long)0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1319                 }
1320
1321                 public static float Sum (this ParallelQuery<float> source)
1322                 {
1323                         if (source == null)
1324                                 throw new ArgumentNullException ("source");
1325
1326                         return source.Aggregate (0.0f, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1327                 }
1328
1329                 public static double Sum (this ParallelQuery<double> source)
1330                 {
1331                         if (source == null)
1332                                 throw new ArgumentNullException ("source");
1333
1334                         return source.Aggregate (0.0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1335                 }
1336
1337                 public static decimal Sum (this ParallelQuery<decimal> source)
1338                 {
1339                         if (source == null)
1340                                 throw new ArgumentNullException ("source");
1341
1342                         return source.Aggregate ((decimal)0, (e1, e2) => e1 + e2, (sum1, sum2) => sum1 + sum2, (sum) => sum);
1343                 }
1344
1345                 public static int? Sum (this ParallelQuery<int?> source)
1346                 {
1347                         return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1348                 }
1349
1350                 public static long? Sum (this ParallelQuery<long?> source)
1351                 {
1352                         if (source == null)
1353                                 throw new ArgumentNullException ("source");
1354
1355                         return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1356                 }
1357
1358                 public static float? Sum (this ParallelQuery<float?> source)
1359                 {
1360                         if (source == null)
1361                                 throw new ArgumentNullException ("source");
1362
1363                         return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1364                 }
1365
1366                 public static double? Sum (this ParallelQuery<double?> source)
1367                 {
1368                         if (source == null)
1369                                 throw new ArgumentNullException ("source");
1370
1371                         return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1372                 }
1373
1374                 public static decimal? Sum (this ParallelQuery<decimal?> source)
1375                 {
1376                         if (source == null)
1377                                 throw new ArgumentNullException ("source");
1378
1379                         return source.Select ((e) => e.HasValue ? e.Value : 0).Sum ();
1380                 }
1381
1382                 public static int Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> func)
1383                 {
1384                         if (source == null)
1385                                 throw new ArgumentNullException ("source");
1386                         if (func == null)
1387                                 throw new ArgumentNullException ("func");
1388
1389                         return source.Select (func).Sum ();
1390                 }
1391
1392                 public static long Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> func)
1393                 {
1394                         if (source == null)
1395                                 throw new ArgumentNullException ("source");
1396                         if (func == null)
1397                                 throw new ArgumentNullException ("func");
1398
1399                         return source.Select (func).Sum ();
1400                 }
1401
1402                 public static decimal Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> func)
1403                 {
1404                         if (source == null)
1405                                 throw new ArgumentNullException ("source");
1406                         if (func == null)
1407                                 throw new ArgumentNullException ("func");
1408
1409                         return source.Select (func).Sum ();
1410                 }
1411
1412                 public static float Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> func)
1413                 {
1414                         if (source == null)
1415                                 throw new ArgumentNullException ("source");
1416                         if (func == null)
1417                                 throw new ArgumentNullException ("func");
1418
1419                         return source.Select (func).Sum ();
1420                 }
1421
1422                 public static double Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> func)
1423                 {
1424                         if (source == null)
1425                                 throw new ArgumentNullException ("source");
1426                         if (func == null)
1427                                 throw new ArgumentNullException ("func");
1428
1429                         return source.Select (func).Sum ();
1430                 }
1431
1432                 public static int? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> func)
1433                 {
1434                         if (source == null)
1435                                 throw new ArgumentNullException ("source");
1436                         if (func == null)
1437                                 throw new ArgumentNullException ("func");
1438
1439                         return source.Select (func).Sum ();
1440                 }
1441
1442                 public static long? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> func)
1443                 {
1444                         if (source == null)
1445                                 throw new ArgumentNullException ("source");
1446                         if (func == null)
1447                                 throw new ArgumentNullException ("func");
1448
1449                         return source.Select (func).Sum ();
1450                 }
1451
1452                 public static decimal? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> func)
1453                 {
1454                         if (source == null)
1455                                 throw new ArgumentNullException ("source");
1456                         if (func == null)
1457                                 throw new ArgumentNullException ("func");
1458
1459                         return source.Select (func).Sum ();
1460                 }
1461
1462                 public static float? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> func)
1463                 {
1464                         if (source == null)
1465                                 throw new ArgumentNullException ("source");
1466                         if (func == null)
1467                                 throw new ArgumentNullException ("func");
1468
1469                         return source.Select (func).Sum ();
1470                 }
1471
1472                 public static double? Sum<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> func)
1473                 {
1474                         if (source == null)
1475                                 throw new ArgumentNullException ("source");
1476                         if (func == null)
1477                                 throw new ArgumentNullException ("func");
1478
1479                         return source.Select (func).Sum ();
1480                 }
1481                 #endregion
1482
1483                 #region Min-Max
1484                 static T BestOrder<T> (ParallelQuery<T> source, Func<T, T, bool> bestSelector, T seed)
1485                 {
1486                         if (source == null)
1487                                 throw new ArgumentNullException ("source");
1488
1489                         T best = seed;
1490
1491                         best = source.Aggregate (() => seed,
1492                                                 (first, second) => (bestSelector(first, second)) ? first : second,
1493                                                 (first, second) => (bestSelector(first, second)) ? first : second,
1494                                                 (e) => e);
1495                         return best;
1496                 }
1497
1498                 public static int Min (this ParallelQuery<int> source)
1499                 {
1500                         return BestOrder (source, (first, second) => first < second, int.MaxValue);
1501                 }
1502
1503                 public static long Min (this ParallelQuery<long> source)
1504                 {
1505                         return BestOrder (source, (first, second) => first < second, long.MaxValue);
1506                 }
1507
1508                 public static float Min (this ParallelQuery<float> source)
1509                 {
1510                         return BestOrder (source, (first, second) => first < second, float.MaxValue);
1511                 }
1512
1513                 public static double Min (this ParallelQuery<double> source)
1514                 {
1515                         return BestOrder (source, (first, second) => first < second, double.MaxValue);
1516                 }
1517
1518                 public static decimal Min (this ParallelQuery<decimal> source)
1519                 {
1520                         return BestOrder (source, (first, second) => first < second, decimal.MaxValue);
1521                 }
1522
1523                 public static TSource Min<TSource> (this ParallelQuery<TSource> source)
1524                 {
1525                         IComparer<TSource> comparer = Comparer<TSource>.Default;
1526
1527                         return BestOrder (source, (first, second) => comparer.Compare (first, second) < 0, default (TSource));
1528                 }
1529
1530                 public static TResult Min<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, TResult> func)
1531                 {
1532                         if (source == null)
1533                                 throw new ArgumentNullException ("source");
1534                         if (func == null)
1535                                 throw new ArgumentNullException ("func");
1536
1537                         return source.Select (func).Min ();
1538                 }
1539
1540                 public static int? Min (this ParallelQuery<int?> source)
1541                 {
1542                         if (source == null)
1543                                 throw new ArgumentNullException ("source");
1544
1545                         return source.Select ((e) => e.HasValue ? e.Value : int.MaxValue).Min ();
1546                 }
1547
1548                 public static long? Min (this ParallelQuery<long?> source)
1549                 {
1550                         if (source == null)
1551                                 throw new ArgumentNullException ("source");
1552
1553                         return source.Select ((e) => e.HasValue ? e.Value : long.MaxValue).Min ();
1554                 }
1555
1556                 public static float? Min (this ParallelQuery<float?> source)
1557                 {
1558                         if (source == null)
1559                                 throw new ArgumentNullException ("source");
1560
1561                         return source.Select ((e) => e.HasValue ? e.Value : float.MaxValue).Min ();
1562                 }
1563
1564                 public static double? Min (this ParallelQuery<double?> source)
1565                 {
1566                         if (source == null)
1567                                 throw new ArgumentNullException ("source");
1568
1569                         return source.Select ((e) => e.HasValue ? e.Value : double.MaxValue).Min ();
1570                 }
1571
1572                 public static decimal? Min (this ParallelQuery<decimal?> source)
1573                 {
1574                         if (source == null)
1575                                 throw new ArgumentNullException ("source");
1576
1577                         return source.Select ((e) => e.HasValue ? e.Value : decimal.MaxValue).Min ();
1578                 }
1579
1580                 public static int Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> func)
1581                 {
1582                         if (source == null)
1583                                 throw new ArgumentNullException ("source");
1584                         if (func == null)
1585                                 throw new ArgumentNullException ("func");
1586
1587                         return source.Select (func).Min ();
1588                 }
1589
1590                 public static long Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> func)
1591                 {
1592                         if (source == null)
1593                                 throw new ArgumentNullException ("source");
1594                         if (func == null)
1595                                 throw new ArgumentNullException ("func");
1596
1597                         return source.Select (func).Min ();
1598                 }
1599
1600                 public static float Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> func)
1601                 {
1602                         if (source == null)
1603                                 throw new ArgumentNullException ("source");
1604                         if (func == null)
1605                                 throw new ArgumentNullException ("func");
1606
1607                         return source.Select (func).Min ();
1608                 }
1609
1610                 public static double Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> func)
1611                 {
1612                         if (source == null)
1613                                 throw new ArgumentNullException ("source");
1614                         if (func == null)
1615                                 throw new ArgumentNullException ("func");
1616
1617                         return source.Select (func).Min ();
1618                 }
1619
1620                 public static decimal Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> func)
1621                 {
1622                         if (source == null)
1623                                 throw new ArgumentNullException ("source");
1624                         if (func == null)
1625                                 throw new ArgumentNullException ("func");
1626
1627                         return source.Select (func).Min ();
1628                 }
1629
1630                 public static int? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> func)
1631                 {
1632                         if (source == null)
1633                                 throw new ArgumentNullException ("source");
1634                         if (func == null)
1635                                 throw new ArgumentNullException ("func");
1636
1637                         return source.Select (func).Min ();
1638                 }
1639
1640                 public static long? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> func)
1641                 {
1642                         if (source == null)
1643                                 throw new ArgumentNullException ("source");
1644                         if (func == null)
1645                                 throw new ArgumentNullException ("func");
1646
1647                         return source.Select (func).Min ();
1648                 }
1649
1650                 public static float? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> func)
1651                 {
1652                         if (source == null)
1653                                 throw new ArgumentNullException ("source");
1654                         if (func == null)
1655                                 throw new ArgumentNullException ("func");
1656
1657                         return source.Select (func).Min ();
1658                 }
1659
1660                 public static double? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> func)
1661                 {
1662                         if (source == null)
1663                                 throw new ArgumentNullException ("source");
1664                         if (func == null)
1665                                 throw new ArgumentNullException ("func");
1666
1667                         return source.Select (func).Min ();
1668                 }
1669
1670                 public static decimal? Min<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> func)
1671                 {
1672                         if (source == null)
1673                                 throw new ArgumentNullException ("source");
1674                         if (func == null)
1675                                 throw new ArgumentNullException ("func");
1676
1677                         return source.Select (func).Min ();
1678                 }
1679
1680                 public static int Max (this ParallelQuery<int> source)
1681                 {
1682                         return BestOrder (source, (first, second) => first > second, int.MinValue);
1683                 }
1684
1685                 public static long Max(this ParallelQuery<long> source)
1686                 {
1687                         return BestOrder(source, (first, second) => first > second, long.MinValue);
1688                 }
1689
1690                 public static float Max (this ParallelQuery<float> source)
1691                 {
1692                         return BestOrder(source, (first, second) => first > second, float.MinValue);
1693                 }
1694
1695                 public static double Max (this ParallelQuery<double> source)
1696                 {
1697                         return BestOrder(source, (first, second) => first > second, double.MinValue);
1698                 }
1699
1700                 public static decimal Max (this ParallelQuery<decimal> source)
1701                 {
1702                         return BestOrder(source, (first, second) => first > second, decimal.MinValue);
1703                 }
1704
1705                 public static TSource Max<TSource> (this ParallelQuery<TSource> source)
1706                 {
1707                         IComparer<TSource> comparer = Comparer<TSource>.Default;
1708
1709                         return BestOrder (source, (first, second) => comparer.Compare (first, second) > 0, default (TSource));
1710                 }
1711
1712                 public static TResult Max<TSource, TResult> (this ParallelQuery<TSource> source, Func<TSource, TResult> func)
1713                 {
1714                         if (source == null)
1715                                 throw new ArgumentNullException ("source");
1716                         if (func == null)
1717                                 throw new ArgumentNullException ("func");
1718
1719                         return source.Select (func).Max ();
1720                 }
1721
1722                 public static int? Max (this ParallelQuery<int?> source)
1723                 {
1724                         if (source == null)
1725                                 throw new ArgumentNullException ("source");
1726
1727                         return source.Select ((e) => e.HasValue ? e.Value : int.MinValue).Max ();
1728                 }
1729
1730                 public static long? Max (this ParallelQuery<long?> source)
1731                 {
1732                         if (source == null)
1733                                 throw new ArgumentNullException ("source");
1734
1735                         return source.Select ((e) => e.HasValue ? e.Value : long.MinValue).Max ();
1736                 }
1737
1738                 public static float? Max (this ParallelQuery<float?> source)
1739                 {
1740                         if (source == null)
1741                                 throw new ArgumentNullException ("source");
1742
1743                         return source.Select ((e) => e.HasValue ? e.Value : float.MinValue).Max ();
1744                 }
1745
1746                 public static double? Max (this ParallelQuery<double?> source)
1747                 {
1748                         if (source == null)
1749                                 throw new ArgumentNullException ("source");
1750
1751                         return source.Select ((e) => e.HasValue ? e.Value : double.MinValue).Max ();
1752                 }
1753
1754                 public static decimal? Max (this ParallelQuery<decimal?> source)
1755                 {
1756                         if (source == null)
1757                                 throw new ArgumentNullException ("source");
1758
1759                         return source.Select ((e) => e.HasValue ? e.Value : decimal.MinValue).Max ();
1760                 }
1761
1762                 public static int Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, int> func)
1763                 {
1764                         if (source == null)
1765                                 throw new ArgumentNullException ("source");
1766                         if (func == null)
1767                                 throw new ArgumentNullException ("func");
1768
1769                         return source.Select (func).Max ();
1770                 }
1771
1772                 public static long Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, long> func)
1773                 {
1774                         if (source == null)
1775                                 throw new ArgumentNullException ("source");
1776                         if (func == null)
1777                                 throw new ArgumentNullException ("func");
1778
1779                         return source.Select (func).Max ();
1780                 }
1781
1782                 public static float Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, float> func)
1783                 {
1784                         if (source == null)
1785                                 throw new ArgumentNullException ("source");
1786                         if (func == null)
1787                                 throw new ArgumentNullException ("func");
1788
1789                         return source.Select (func).Max ();
1790                 }
1791
1792                 public static double Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, double> func)
1793                 {
1794                         if (source == null)
1795                                 throw new ArgumentNullException ("source");
1796                         if (func == null)
1797                                 throw new ArgumentNullException ("func");
1798
1799                         return source.Select (func).Max ();
1800                 }
1801
1802                 public static decimal Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal> func)
1803                 {
1804                         if (source == null)
1805                                 throw new ArgumentNullException ("source");
1806                         if (func == null)
1807                                 throw new ArgumentNullException ("func");
1808
1809                         return source.Select (func).Max ();
1810                 }
1811
1812                 public static int? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, int?> func)
1813                 {
1814                         if (source == null)
1815                                 throw new ArgumentNullException ("source");
1816                         if (func == null)
1817                                 throw new ArgumentNullException ("func");
1818
1819                         return source.Select (func).Max ();
1820                 }
1821
1822                 public static long? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, long?> func)
1823                 {
1824                         if (source == null)
1825                                 throw new ArgumentNullException ("source");
1826                         if (func == null)
1827                                 throw new ArgumentNullException ("func");
1828
1829                         return source.Select (func).Max ();
1830                 }
1831
1832                 public static float? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, float?> func)
1833                 {
1834                         if (source == null)
1835                                 throw new ArgumentNullException ("source");
1836                         if (func == null)
1837                                 throw new ArgumentNullException ("func");
1838
1839                         return source.Select (func).Max ();
1840                 }
1841
1842                 public static double? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, double?> func)
1843                 {
1844                         if (source == null)
1845                                 throw new ArgumentNullException ("source");
1846                         if (func == null)
1847                                 throw new ArgumentNullException ("func");
1848
1849                         return source.Select (func).Max ();
1850                 }
1851
1852                 public static decimal? Max<TSource> (this ParallelQuery<TSource> source, Func<TSource, decimal?> func)
1853                 {
1854                         if (source == null)
1855                                 throw new ArgumentNullException ("source");
1856                         if (func == null)
1857                                 throw new ArgumentNullException ("func");
1858
1859                         return source.Select (func).Max ();
1860                 }
1861                 #endregion
1862
1863                 #region Cast / OfType
1864                 public static ParallelQuery<TResult> Cast<TResult> (this ParallelQuery source)
1865                 {
1866                         if (source == null)
1867                                 throw new ArgumentNullException ("source");
1868
1869                         return source.TypedQuery.Select ((e) => (TResult)e);
1870                 }
1871
1872                 public static ParallelQuery<TResult> OfType<TResult> (this ParallelQuery source)
1873                 {
1874                         if (source == null)
1875                                 throw new ArgumentNullException ("source");
1876
1877                         return source.TypedQuery.Where ((e) => e is TResult).Cast<TResult> ();
1878                 }
1879                 #endregion
1880
1881                 #region Reverse
1882                 public static ParallelQuery<TSource> Reverse<TSource> (this ParallelQuery<TSource> source)
1883                 {
1884                         if (source == null)
1885                                 throw new ArgumentNullException ("source");
1886
1887                         return new ParallelQuery<TSource> (new QueryReverseNode<TSource> (source));
1888                 }
1889                 #endregion
1890
1891                 #region ToArray - ToList - ToDictionary - ToLookup
1892                 public static List<TSource> ToList<TSource> (this ParallelQuery<TSource> source)
1893                 {
1894                         if (source == null)
1895                                 throw new ArgumentNullException ("source");
1896
1897                         if (source.Node.IsOrdered ())
1898                                 return ToListOrdered (source);
1899
1900                         List<TSource> temp = source.Aggregate (() => new List<TSource>(50),
1901                                                                (list, e) => { list.Add (e); return list; },
1902                                                                (list, list2) => { list.AddRange (list2); return list; },
1903                                                                (list) => list);
1904                         return temp;
1905                 }
1906
1907                 internal static List<TSource> ToListOrdered<TSource> (this ParallelQuery<TSource> source)
1908                 {
1909                         List<TSource> result = new List<TSource> ();
1910
1911                         foreach (TSource element in source)
1912                                 result.Add (element);
1913
1914                         return result;
1915                 }
1916
1917                 public static TSource[] ToArray<TSource> (this ParallelQuery<TSource> source)
1918                 {
1919                         if (source == null)
1920                                 throw new ArgumentNullException ("source");
1921
1922                         if (source.Node.IsOrdered ())
1923                                 return ToListOrdered (source).ToArray ();
1924
1925                         TSource[] result = null;
1926
1927                         Func<List<TSource>, TSource, List<TSource>> intermediate = (list, e) => {
1928                                 list.Add (e); return list;
1929                         };
1930
1931                         Action<IList<List<TSource>>> final = (list) => {
1932                                 int count = 0;
1933
1934                                 for (int i = 0; i < list.Count; i++)
1935                                   count += list[i].Count;
1936
1937                                 result = new TSource[count];
1938                                 int insertIndex = -1;
1939
1940                                 for (int i = 0; i < list.Count; i++)
1941                                   for (int j = 0; j < list[i].Count; j++)
1942                                     result [++insertIndex] = list[i][j];
1943                         };
1944
1945                         ParallelExecuter.ProcessAndAggregate<TSource, List<TSource>> (source.Node,
1946                                                                                       () => new List<TSource> (),
1947                                                                                       intermediate,
1948                                                                                       final);
1949
1950                         return result;
1951                 }
1952
1953                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this ParallelQuery<TSource> source,
1954                                                                                      Func<TSource, TKey> keySelector,
1955                                                                                      IEqualityComparer<TKey> comparer)
1956                 {
1957                         return ToDictionary<TSource, TKey, TSource> (source, keySelector, (e) => e, comparer);
1958                 }
1959
1960                 public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey> (this ParallelQuery<TSource> source,
1961                                                                                      Func<TSource, TKey> keySelector)
1962                 {
1963                         return ToDictionary<TSource, TKey, TSource> (source, keySelector, (e) => e, EqualityComparer<TKey>.Default);
1964                 }
1965
1966                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
1967                                                                                                   Func<TSource, TKey> keySelector,
1968                                                                                                   Func<TSource, TElement> elementSelector)
1969                 {
1970                         return ToDictionary<TSource, TKey, TElement> (source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
1971                 }
1972
1973                 public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
1974                                                                                                   Func<TSource, TKey> keySelector,
1975                                                                                                   Func<TSource, TElement> elementSelector,
1976                                                                                                   IEqualityComparer<TKey> comparer)
1977                 {
1978                         if (source == null)
1979                                 throw new ArgumentNullException ("source");
1980                         if (keySelector == null)
1981                                 throw new ArgumentNullException ("keySelector");
1982                         if (comparer == null)
1983                                 comparer = EqualityComparer<TKey>.Default;
1984                         if (elementSelector == null)
1985                                 throw new ArgumentNullException ("elementSelector");
1986
1987                         return source.Aggregate (() => new Dictionary<TKey, TElement> (comparer),
1988                                                   (d, e) => { d.Add (keySelector (e), elementSelector (e)); return d; },
1989                                                   (d1, d2) => { foreach (var couple in d2) d1.Add (couple.Key, couple.Value); return d1; },
1990                                                   (d) => d);
1991                 }
1992
1993                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this ParallelQuery<TSource> source,
1994                                                                               Func<TSource, TKey> keySelector)
1995                 {
1996                         return ToLookup<TSource, TKey, TSource> (source, keySelector, (e) => e, EqualityComparer<TKey>.Default);
1997                 }
1998
1999                 public static ILookup<TKey, TSource> ToLookup<TSource, TKey> (this ParallelQuery<TSource> source,
2000                                                                               Func<TSource, TKey> keySelector,
2001                                                                               IEqualityComparer<TKey> comparer)
2002                 {
2003                         return ToLookup<TSource, TKey, TSource> (source, keySelector, (e) => e, comparer);
2004                 }
2005
2006                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
2007                                                                                          Func<TSource, TKey> keySelector,
2008                                                                                          Func<TSource, TElement> elementSelector)
2009                 {
2010                         return ToLookup<TSource, TKey, TElement> (source, keySelector, elementSelector, EqualityComparer<TKey>.Default);
2011                 }
2012
2013                 public static ILookup<TKey, TElement> ToLookup<TSource, TKey, TElement> (this ParallelQuery<TSource> source,
2014                                                                                          Func<TSource, TKey> keySelector,
2015                                                                                          Func<TSource, TElement> elementSelector,
2016                                                                                          IEqualityComparer<TKey> comparer)
2017                 {
2018                         if (source == null)
2019                                 throw new ArgumentNullException ("source");
2020                         if (keySelector == null)
2021                                 throw new ArgumentNullException ("keySelector");
2022                         if (comparer == null)
2023                                 comparer = EqualityComparer<TKey>.Default;
2024                         if (elementSelector == null)
2025                                 throw new ArgumentNullException ("elementSelector");
2026
2027                         ConcurrentLookup<TKey, TElement> lookup = new ConcurrentLookup<TKey, TElement> (comparer);
2028                         source.ForAll ((e) => lookup.Add (keySelector (e), elementSelector (e)));
2029
2030                         return lookup;
2031                 }
2032                 #endregion
2033
2034                 #region Concat
2035                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather than "
2036                                    + "System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() extension method "
2037                                    + "to convert the right data source to System.Linq.ParallelQuery<T>.")]
2038                 public static ParallelQuery<TSource> Concat<TSource>(this ParallelQuery<TSource> first,
2039                                                                      IEnumerable<TSource> second)
2040                 {
2041                         throw new NotSupportedException ();
2042                 }
2043
2044                 public static ParallelQuery<TSource> Concat<TSource> (this ParallelQuery<TSource> first, ParallelQuery<TSource> second)
2045                 {
2046                         return new ParallelQuery<TSource> (new QueryConcatNode<TSource> (first.Node, second.Node));
2047                 }
2048                 #endregion
2049                 
2050                 #region DefaultIfEmpty
2051                 public static ParallelQuery<TSource> DefaultIfEmpty<TSource> (this ParallelQuery<TSource> source)
2052                 {
2053                         return source.DefaultIfEmpty (default (TSource));
2054                 }
2055                 
2056                 public static ParallelQuery<TSource> DefaultIfEmpty<TSource> (this ParallelQuery<TSource> source, TSource defaultValue)
2057                 {
2058                         return new ParallelQuery<TSource> (new QueryDefaultEmptyNode<TSource> (source.Node, defaultValue));
2059                 }
2060                 #endregion
2061                 
2062                 #region First
2063                 public static TSource First<TSource> (this ParallelQuery<TSource> source)
2064                 {
2065                         CancellationTokenSource src = new CancellationTokenSource ();
2066                         IEnumerator<TSource> enumerator = source.WithImplementerToken (src).GetEnumerator ();
2067                         
2068                         if (enumerator == null || !enumerator.MoveNext ())
2069                                 throw new InvalidOperationException ("source contains no element");
2070                         
2071                         TSource result = enumerator.Current;
2072                         src.Cancel ();
2073                         enumerator.Dispose ();
2074                         
2075                         return result;
2076                 }
2077                 
2078                 public static TSource First<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
2079                 {
2080                         return source.Where (predicate).First ();
2081                 }
2082                 
2083                 public static TSource FirstOrDefault<TSource> (this ParallelQuery<TSource> source)
2084                 {
2085                         return source.DefaultIfEmpty ().First ();
2086                 }
2087                 
2088                 public static TSource FirstOrDefault<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
2089                 {
2090                         return source.Where (predicate).FirstOrDefault ();
2091                 }
2092                 #endregion
2093                 
2094                 #region Last
2095                 public static TSource Last<TSource> (this ParallelQuery<TSource> source)
2096                 {
2097                         return source.Reverse ().First ();
2098                 }
2099                 
2100                 public static TSource Last<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
2101                 {
2102                         return source.Reverse ().First (predicate);
2103                 }
2104                 
2105                 public static TSource LastOrDefault<TSource> (this ParallelQuery<TSource> source)
2106                 {
2107                         return source.Reverse ().FirstOrDefault ();
2108                 }
2109                 
2110                 public static TSource LastOrDefault<TSource> (this ParallelQuery<TSource> source, Func<TSource, bool> predicate)
2111                 {
2112                         return source.Reverse ().FirstOrDefault (predicate);
2113                 }
2114                 #endregion
2115
2116                 #region Zip
2117                 public static ParallelQuery<TResult> Zip<TFirst, TSecond, TResult> (this ParallelQuery<TFirst> first,
2118                                                                                       ParallelQuery<TSecond> second,
2119                                                                                       Func<TFirst, TSecond, TResult> resultSelector)
2120                 {
2121                         if (first == null)
2122                                 throw new ArgumentNullException ("first");
2123                         if (second == null)
2124                                 throw new ArgumentNullException ("second");
2125                         if (resultSelector == null)
2126                                 throw new ArgumentNullException ("resultSelector");
2127
2128                         return new ParallelQuery<TResult> (new QueryZipNode<TFirst, TSecond, TResult> (resultSelector, first.Node, second.Node));
2129                 }
2130
2131                 [ObsoleteAttribute("The second data source of a binary operator must be of type System.Linq.ParallelQuery<T> rather "
2132                                    + "than System.Collections.Generic.IEnumerable<T>. To fix this problem, use the AsParallel() "
2133                                    + "extension method to convert the right data source to System.Linq.ParallelQuery<T>.")]
2134                 public static ParallelQuery<TResult> Zip<TFirst, TSecond, TResult> (this ParallelQuery<TFirst> first,
2135                                                                                       IEnumerable<TSecond> second,
2136                                                                                       Func<TFirst, TSecond, TResult> resultSelector)
2137                 {
2138                         throw new NotSupportedException ();
2139                 }
2140                 #endregion
2141         }
2142 }
2143 #endif