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