/* Copyright (c) Microsoft Corporation All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 THIS CODE IS PROVIDED *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABLITY OR NON-INFRINGEMENT. See the Apache Version 2.0 License for specific language governing permissions and limitations under the License. */ using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Globalization; using System.Reflection; using System.Linq; using Microsoft.Research.DryadLinq.Internal; #pragma warning disable 1591 namespace Microsoft.Research.DryadLinq.Internal { /// /// This class provides the IEnumerable implementation of the operators /// we introduced in DryadLINQ. This is needed to implement LocalDebug. /// /// A DryadLINQ user should not need to use this class directly. public static class DryadLinqEnumerable { // Operator: HashPartition public static IEnumerable HashPartition(this IEnumerable source, Func keySelector, IEqualityComparer comparer, int count) { return source; } public static IEnumerable HashPartition(this IEnumerable source, Func keySelector, int count) { return source; } public static IEnumerable HashPartition(this IEnumerable source, Func keySelector) { return source; } public static IEnumerable HashPartition(this IEnumerable source, Func keySelector, IEqualityComparer comparer) { return source; } public static IEnumerable HashPartition(this IEnumerable source, Func keySelector, Func resultSelector) { foreach (TSource x in source) { yield return resultSelector(x); } } public static IEnumerable HashPartition(this IEnumerable source, Func keySelector, IEqualityComparer comparer, Func resultSelector) { foreach (TSource x in source) { yield return resultSelector(x); } } // Operator: RangePartition public static IEnumerable RangePartition(this IEnumerable source, Func keySelector, bool isDescending) { return source; } public static IEnumerable RangePartition(this IEnumerable source, Func keySelector, IComparer comparer, bool isDescending) { return source; } public static IEnumerable RangePartition(this IEnumerable source, Func keySelector, TKey[] rangeSeparators) { return source; } public static IEnumerable RangePartition(this IEnumerable source, Func keySelector, TKey[] rangeSeparators, IComparer comparer) { return source; } // Operator: Apply public static IEnumerable Apply(this IEnumerable source, Func, IEnumerable> procFunc) { return procFunc(source); } public static IEnumerable Apply(this IEnumerable source1, IEnumerable source2, Func, IEnumerable, IEnumerable> procFunc) { return procFunc(source1, source2); } public static IEnumerable Apply(this IEnumerable source, IEnumerable[] otherSources, Func[], IEnumerable> procFunc) { IEnumerable[] allSources = new IEnumerable[otherSources.Length + 1]; allSources[0] = source; for (int i = 0; i < otherSources.Length; i++) { allSources[i+1] = otherSources[i]; } return procFunc(allSources); } public static IEnumerable Apply(this IEnumerable source, IEnumerable[] otherSources, Func, IEnumerable[], IEnumerable> procFunc) { return procFunc(source, otherSources); } // Operator: DoWhile public static IEnumerable DoWhile(this IEnumerable source, Func, IQueryable> body, Func, IQueryable, IQueryable> cond) { IEnumerable before = source; while (true) { IEnumerable after = before; after = body(after.AsQueryable()); var more = cond(before.AsQueryable(), after.AsQueryable()).Single(); if (!more) return after; before = after; } } // Operator: SlidingWindow public static IEnumerable SlidingWindow(this IEnumerable source, Func, T2> procFunc, Int32 windowSize) { Window window = new Window(windowSize); using (IEnumerator sourceEnum = source.GetEnumerator()) { while (window.Count() < windowSize) { if (!sourceEnum.MoveNext()) break; window.Add(sourceEnum.Current); } if (window.Count() == windowSize) { yield return procFunc(window); while (sourceEnum.MoveNext()) { window.Add(sourceEnum.Current); yield return procFunc(window); } } } } // Operator: ApplyWithPartitionIndex public static IEnumerable ApplyWithPartitionIndex(this IEnumerable source, Func, int, IEnumerable> procFunc) { return procFunc(source, 0); } public static IEnumerable AnyAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Any()); } public static IEnumerable AnyAsQuery(this IEnumerable source, Func predicate) { return DryadLinqVertex.AsEnumerable(source.Any(predicate)); } public static IEnumerable AllAsQuery(this IEnumerable source, Func predicate) { return DryadLinqVertex.AsEnumerable(source.All(predicate)); } public static IEnumerable CountAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Count()); } public static IEnumerable CountAsQuery(this IEnumerable source, Func predicate) { return DryadLinqVertex.AsEnumerable(source.Count(predicate)); } public static IEnumerable LongCountAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.LongCount()); } public static IEnumerable LongCountAsQuery(this IEnumerable source, Func predicate) { return DryadLinqVertex.AsEnumerable(source.LongCount(predicate)); } public static IEnumerable ContainsAsQuery(this IEnumerable source, TSource value) { return DryadLinqVertex.AsEnumerable(source.Contains(value)); } public static IEnumerable ContainsAsQuery(this IEnumerable source, TSource value, IEqualityComparer comparer) { return DryadLinqVertex.AsEnumerable(source.Contains(value, comparer)); } public static IEnumerable SequenceEqualAsQuery(this IEnumerable first, IEnumerable second) { return DryadLinqVertex.AsEnumerable(first.SequenceEqual(second)); } public static IEnumerable SequenceEqualAsQuery(this IEnumerable first, IEnumerable second, IEqualityComparer comparer) { return DryadLinqVertex.AsEnumerable(first.SequenceEqual(second, comparer)); } public static IEnumerable FirstAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.First()); } public static IEnumerable FirstAsQuery(this IEnumerable source, Func predicate) { return DryadLinqVertex.AsEnumerable(source.First(predicate)); } public static IEnumerable LastAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Last()); } public static IEnumerable LastAsQuery(this IEnumerable source, Func predicate) { return DryadLinqVertex.AsEnumerable(source.Last(predicate)); } public static IEnumerable SingleAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Single()); } public static IEnumerable SingleAsQuery(this IEnumerable source, Func predicate) { return DryadLinqVertex.AsEnumerable(source.Single(predicate)); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Sum()); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable SumAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Sum(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Min()); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MinAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Min(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Max()); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable MaxAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Max(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source) { return DryadLinqVertex.AsEnumerable(source.Average()); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } public static IEnumerable AverageAsQuery(this IEnumerable source, Func selector) { return DryadLinqVertex.AsEnumerable(source.Average(selector)); } // Aggregate operator public static TAccumulate Aggregate(this IEnumerable source, Func seedFunc, Func func) { return source.Aggregate(seedFunc(), func); } public static TResult Aggregate(this IEnumerable source, Func seedFunc, Func func, Func resultSelector) { return resultSelector(source.Aggregate(seedFunc, func)); } public static IEnumerable AggregateAsQuery(this IEnumerable source, Func func) { return DryadLinqVertex.AsEnumerable(source.Aggregate(func)); } public static IEnumerable AggregateAsQuery(this IEnumerable source, TAccumulate seed, Func func) { return DryadLinqVertex.AsEnumerable(source.Aggregate(seed, func)); } public static IEnumerable AggregateAsQuery(this IEnumerable source, TAccumulate seed, Func func, Func resultSelector) { return DryadLinqVertex.AsEnumerable(source.Aggregate(seed, func, resultSelector)); } public static IEnumerable AggregateAsQuery(this IEnumerable source, Func seedFunc, Func func) { return DryadLinqVertex.AsEnumerable(source.Aggregate(seedFunc(), func)); } public static IEnumerable AggregateAsQuery(this IEnumerable source, Func seedFunc, Func func, Func resultSelector) { return DryadLinqVertex.AsEnumerable(source.Aggregate(seedFunc, func, resultSelector)); } public static IEnumerable AssumeHashPartition(this IEnumerable source, Func keySelector) { return source; } // Operator: AssumeHashPartition public static IEnumerable AssumeHashPartition(this IEnumerable source, Func keySelector, IEqualityComparer comparer) { return source; } public static IEnumerable AssumeRangePartition(this IEnumerable source, Func keySelector, bool isDescending) { return source; } // Operator: AssumeRangePartition public static IEnumerable AssumeRangePartition(this IEnumerable source, Func keySelector, IComparer comparer, bool isDescending) { return source; } public static IEnumerable AssumeRangePartition(this IEnumerable source, Func keySelector, TKey[] rangeSeparators) { return source; } public static IEnumerable AssumeRangePartition(this IEnumerable source, Func keySelector, TKey[] rangeSeparators, IComparer comparer) { return source; } // Operator: AssumeOrderBy public static IEnumerable AssumeOrderBy(this IEnumerable source, Func keySelector, bool isDescending) { return source; } public static IEnumerable AssumeOrderBy(this IEnumerable source, Func keySelector, IComparer comparer, bool isDescending) { return source; } public static IMultiEnumerable Fork(this IEnumerable source, Func, IEnumerable>> mapper) { List resX = new List(); List resY = new List(); IEnumerable> result = mapper(source); foreach (ForkTuple item in result) { if (item.HasFirst) resX.Add(item.First); if (item.HasSecond) resY.Add(item.Second); } return new MultiEnumerable(resX, resY); } public static IMultiEnumerable Fork(this IEnumerable source, Func, IEnumerable>> mapper) { List resX = new List(); List resY = new List(); List resZ = new List(); IEnumerable> result = mapper(source); foreach (ForkTuple item in result) { if (item.HasFirst) resX.Add(item.First); if (item.HasSecond) resY.Add(item.Second); if (item.HasThird) resZ.Add(item.Third); } return new MultiEnumerable(resX, resY, resZ); } public static IMultiEnumerable Fork(this IEnumerable source, Func> mapper) { List resX = new List(); List resY = new List(); foreach (TSource elem in source) { ForkTuple item = mapper(elem); if (item.HasFirst) resX.Add(item.First); if (item.HasSecond) resY.Add(item.Second); } return new MultiEnumerable(resX, resY); } public static IMultiEnumerable Fork(this IEnumerable source, Func> mapper) { List resX = new List(); List resY = new List(); List resZ = new List(); foreach (TSource elem in source) { ForkTuple item = mapper(elem); if (item.HasFirst) resX.Add(item.First); if (item.HasSecond) resY.Add(item.Second); if (item.HasThird) resZ.Add(item.Third); } return new MultiEnumerable(resX, resY, resZ); } public static IMultiEnumerable Fork(this IEnumerable source, Func keySelector, TKey[] keys) { List[] enumList = new List[keys.Length]; Dictionary keyMap = new Dictionary(keys.Length); for (int i = 0; i < keys.Length; i++) { enumList[i] = new List(); keyMap.Add(keys[i], i); } foreach (TSource item in source) { int index; if (keyMap.TryGetValue(keySelector(item), out index)) { enumList[index].Add(item); } } return new MultiEnumerable(enumList); } public static IEnumerable LongTakeWhile(this IEnumerable source, Func predicate) { long index = 0; foreach (TSource element in source) { if (!predicate(element, index)) { yield break; } yield return element; checked { index++; } } } public static IEnumerable LongSkipWhile(this IEnumerable source, Func predicate) { long index = -1; bool yielding = false; using (IEnumerator sourceEnum = source.GetEnumerator()) { while (sourceEnum.MoveNext()) { checked { index++; } if (!predicate(sourceEnum.Current, index)) { yielding = true; break; } } if (yielding) { do { yield return sourceEnum.Current; } while (sourceEnum.MoveNext()); } } } public static IEnumerable FlattenGroups(IEnumerable> groups) { foreach (var g in groups) { foreach (var x in g) { yield return x; } } } [FieldMapping("key", "Key")] public static IGrouping MakeDryadLinqGroup(K key, IEnumerable> groups) { return new DryadLinqGrouping(key, FlattenGroups(groups)); } public static IEnumerable Flatten(IEnumerable> groups) { foreach (var g in groups) { foreach (var x in g) { yield return x; } } } public static IEnumerable FlattenDistinct(IEnumerable> groups, IEqualityComparer comparer) { return Flatten(groups).Distinct(comparer).ToArray(); } public static IEnumerable> Offsets(IEnumerable counts, bool isLong) { int index = 0; long offset = 0; foreach (long count in counts) { yield return new IndexedValue(index, offset); index++; checked { offset += count; } } if (!isLong && (offset > Int32.MaxValue)) { throw new OverflowException(SR.IndexTooSmall); } } public static IEnumerable WhereWithStartIndex(IEnumerable source, IEnumerable> startIndex, Func predicate) { int index = (int)startIndex.Single().Value; foreach (TSource element in source) { if (predicate(element, index)) { yield return element; } checked { index++; } } } public static IEnumerable LongWhere(this IEnumerable source, Func predicate) { long index = 0; foreach (TSource element in source) { if (predicate(element, index)) { yield return element; } checked { index++; } } } public static IEnumerable LongWhereWithStartIndex(IEnumerable source, IEnumerable> startIndex, Func predicate) { long index = startIndex.Single().Value; foreach (TSource element in source) { if (predicate(element, index)) { yield return element; } checked { index++; } } } public static IEnumerable SelectWithStartIndex(IEnumerable source, IEnumerable> startIndex, Func selector) { int index = (int)startIndex.Single().Value; foreach (TSource element in source) { yield return selector(element, index); checked { index++; } } } public static IEnumerable LongSelect(this IEnumerable source, Func selector) { long index = 0; foreach (TSource element in source) { yield return selector(element, index); checked { index++; } } } public static IEnumerable LongSelectWithStartIndex(IEnumerable source, IEnumerable> startIndex, Func selector) { long index = startIndex.Single().Value; foreach (TSource element in source) { yield return selector(element, index); checked { index++; } } } public static IEnumerable SelectManyWithStartIndex(IEnumerable source, IEnumerable> startIndex, Func> selector) { int index = (int)startIndex.Single().Value; foreach (TSource element in source) { foreach (TResult result in selector(element, index)) { yield return result; } checked { index++; } } } public static IEnumerable LongSelectManyWithStartIndex( IEnumerable source, IEnumerable> startIndex, Func> selector) { long index = startIndex.Single().Value; foreach (TSource element in source) { foreach (TResult result in selector(element, index)) { yield return result; } checked { index++; } } } public static IEnumerable SelectManyResultWithStartIndex( IEnumerable source, IEnumerable> startIndex, Func> collectionSelector, Func resultSelector) { int index = (int)startIndex.Single().Value; foreach (TSource element in source) { foreach (TCollection result in collectionSelector(element, index)) { yield return resultSelector(element, result); } checked { index++; } } } public static IEnumerable LongSelectMany( this IEnumerable source, Func> selector) { long index = 0; foreach (TSource element in source) { foreach (TResult result in selector(element, index)) { yield return result; } checked { index++; } } } public static IEnumerable LongSelectMany( this IEnumerable source, Func> selector, Func resultSelector) { long index = 0; foreach (TSource element in source) { foreach (TCollection result in selector(element, index)) { yield return resultSelector(element, result); } checked { index++; } } } public static IEnumerable LongSelectManyResultWithStartIndex( IEnumerable source, IEnumerable> startIndex, Func> collectionSelector, Func resultSelector) { long index = startIndex.Single().Value; foreach (TSource element in source) { foreach (TCollection result in collectionSelector(element, index)) { yield return resultSelector(element, result); } checked { index++; } } } private const int GroupSize = 1000; public static IEnumerable, bool>> GroupTakeWhile(IEnumerable source, Func pred) { List group = new List(GroupSize); foreach (T elem in source) { if (pred(elem)) { if (group.Count == GroupSize) { yield return new Pair, bool>(group, true); group = new List(GroupSize); } group.Add(elem); } else { yield return new Pair, bool>(group, false); yield break; } } yield return new Pair, bool>(group, true); } public static IEnumerable, bool>> GroupIndexedTakeWhile(IEnumerable source, IEnumerable> startIndex, Func pred) { int currIdx = (int)startIndex.Single().Value; List group = new List(GroupSize); foreach (T elem in source) { if (pred(elem, currIdx)) { if (group.Count == GroupSize) { yield return new Pair, bool>(group, true); group = new List(GroupSize); } group.Add(elem); checked { currIdx++; } } else { yield return new Pair, bool>(group, false); yield break; } } yield return new Pair, bool>(group, true); } public static IEnumerable, bool>> GroupIndexedLongTakeWhile(IEnumerable source, IEnumerable> startIndex, Func pred) { long currIdx = startIndex.Single().Value; List group = new List(GroupSize); foreach (T elem in source) { if (pred(elem, currIdx)) { if (group.Count == GroupSize) { yield return new Pair, bool>(group, true); group = new List(GroupSize); } group.Add(elem); currIdx++; } else { yield return new Pair, bool>(group, false); yield break; } } yield return new Pair, bool>(group, true); } public static IEnumerable ToStore(IEnumerable source) { return source; } } }