internal static IEnumerable <T> PNN <T>(IEnumerable <T> source, int from, int to, int step) { to = -to; step = -step; int count; var buffer = new DynamicRotativeBuffer <T>(); using (var enumerator = source.GetEnumerator()) { var fromCount = from + 1; var toCount = to - 1; var minToBuffer = Math.Min(fromCount, toCount); buffer.BufferUpToCount(enumerator, minToBuffer); if (buffer.length == 0) { yield break; } var reachedEnd = buffer.length < minToBuffer; if (!reachedEnd) { if (fromCount > toCount) { var toSkip = fromCount - toCount; reachedEnd = toSkip != buffer.RotateUpToCount(enumerator, toSkip); } else if (toCount > fromCount) { count = toCount - fromCount; while (count > 0 && enumerator.MoveNext()) { --count; } reachedEnd = count > 0; } } count = buffer.length; if (!reachedEnd) { count -= enumerator.Skip(count); } } if (count <= 0) { yield break; } var head = (buffer.head - 1 + buffer.length) % buffer.length; while (count > 0) { count -= step; yield return(buffer.items[head]); head = (head - step + buffer.length) % buffer.length; } }
internal static IEnumerable <T> NPP <T>(IEnumerable <T> source, int from, int?to, int step) { from = -from; var buffer = new DynamicRotativeBuffer <T>(); int count; var offset = 0; if (to.HasValue) { var toValue = to.Value; if (from >= toValue) { using (var enumerator = source.GetEnumerator()) { buffer.BufferUpToCount(enumerator, toValue); if (buffer.length != toValue) { offset = 0; count = buffer.length; } else { var toSkip = from - toValue; if (toSkip != enumerator.Skip(toSkip)) { offset = 0; count = buffer.length; } else { offset = enumerator.Skip(toValue); count = toValue - offset; } } } } else { using (var enumerator = source.GetEnumerator()) { buffer.BufferUpToCount(enumerator, from); count = buffer.length; if (count != from) { offset = 0; } else { var toSkip = toValue - from; if (toSkip != buffer.RotateUpToCount(enumerator, toSkip)) { offset = 0; count = buffer.length; } else { offset = enumerator.Skip(from); count = from - offset; } } } } } else { using (var enumerator = source.GetEnumerator()) { buffer.BufferUpToCount(enumerator, from); if (buffer.length == from) { buffer.RotateUntilEndWithCount(enumerator); } } count = buffer.length; } if (count <= 0) { yield break; } count = (count + step - 1) / step; buffer.head += offset; while (count-- > 0) { yield return(buffer.items[buffer.head % buffer.length]); buffer.head += step; } }