/// <summary> /// Applies a folding function to the list of intervals. /// </summary> /// <typeparam name="T">The type of value being folded.</typeparam> /// <param name="xs">The first list of intervals.</param> /// <param name="ys">The second list of intervals.</param> /// <param name="initial">The initial value.</param> /// <param name="fold">The folding function.</param> /// <param name="final">The final fold function.</param> /// <returns>The resulting value.</returns> private static T Fold <T>(IReadOnlyList <int> xs, IReadOnlyList <int> ys, T initial, IntervalFold <T> fold, IntervalFinalFold <T> final) { #region Contract Debug.Assert(xs != null); Debug.Assert(ys != null); Debug.Assert(fold != null); Debug.Assert(final != null); #endregion T current = initial; // Neither lists has any elements, so we'll return. if (xs.Count == 0 && ys.Count == 0) { return(current); } // Indices point to the elements in the lists that are greater than or equal to `cursor`. int xi = 0; int yi = 0; // The cursor is the current position. int comparison = CompareIntervals(xs, ys, xi, yi, out int cursor); if (comparison <= 0) { xi += 1; } if (comparison >= 0) { yi += 1; } while (xi < xs.Count || yi < ys.Count) { comparison = CompareIntervals(xs, ys, xi, yi, out int nextCursor); int start = cursor; int end = nextCursor; bool hasX = (xi % 2) != 0; bool hasY = (yi % 2) != 0; current = fold(start, end, hasX, hasY, current); if (comparison <= 0) { xi += 1; } if (comparison >= 0) { yi += 1; } cursor = nextCursor; } current = final(cursor, current); return(current); }
/// <summary> /// Applies a folding function to the list of intervals. /// </summary> /// <typeparam name="T">The type of value being folded.</typeparam> /// <param name="xs">The first list of intervals.</param> /// <param name="ys">The second list of intervals.</param> /// <param name="initial">The initial value.</param> /// <param name="fold">The folding function.</param> /// <returns>The resulting value.</returns> private static T Fold <T>(IReadOnlyList <int> xs, IReadOnlyList <int> ys, T initial, IntervalFold <T> fold) => Fold(xs, ys, initial, fold, (_, v) => v);