public static IEnumerable <IInterval <uint> > Subtract([NotNull] this IInterval <uint> source, [NotNull, ItemNotNull] IEnumerable <IInterval <uint> > others) { // need to order the intervals so using an intervaltree for this others = (others as IIntervalTree <uint, IInterval <uint> > ?? others.ToIntervalTree <uint, IInterval <uint> >()).Search(source); var returnFinalTarget = true; foreach (var other in others) { var overlap = source.TryGetOverlap(other).GetOrDefault(); if (overlap == null) // sanity check, but since we search a tree, this should never happen. { continue; } IInterval <uint> firstOne = null, secondOne = null; // subtraction only gives a result of 0, 1, or 2 returns, everything else is impossible. foreach (var leftover in source.SubtractOverlap(overlap)) { if (firstOne == null) // means first time in loop { firstOne = leftover; } else { secondOne = leftover; } } if (firstOne == null) // means there was no leftovers { // if this is the last one, then we should not release the final one. returnFinalTarget = false; continue; } // some leftover stuff, so should release those. returnFinalTarget = true; if (secondOne == null) // means only one leftover, we just continue subtracting. { source = firstOne; } else // means 2 leftover, which means we yield the first one and then continue subtracting from the second one. { yield return(firstOne); source = secondOne; } } if (returnFinalTarget) { yield return(source); // return last one or only one if no loops } }