public CompositeRange <T> Intersect <TKey2>(CompositeRange <T, TKey2> other)
        {
            if (IsEmpty)
            {
                return(this);
            }
            if (other.IsEmpty || !ContainingRange.HasIntersection(other.ContainingRange))
            {
                return(Empty);
            }

            var intersectionResult = new List <Range <T> >(SubRanges.Count);

            var rangesToIntersect = new List <Range <T> >(SubRanges);

            foreach (var otherRange in other.GetMergedRanges())
            {
                for (var i = 0; i < rangesToIntersect.Count; i++)
                {
                    var intersectionRange = rangesToIntersect[i];
                    if (intersectionRange.StartsAfter(otherRange))
                    {
                        break;
                    }

                    intersectionRange = intersectionRange.Intersect(otherRange);
                    if (intersectionRange.IsEmpty)
                    {
                        rangesToIntersect.RemoveAt(i);
                        i--;
                    }
                    else
                    {
                        intersectionResult.Add(intersectionRange);
                    }
                }

                if (rangesToIntersect.Count == 0)
                {
                    break;
                }
            }

            CompositeRange <T> result;

            if (intersectionResult.Count == 0)
            {
                result = Empty;
            }
            else
            {
                var overload = IsMerged
                                        ? UnsafeOverload.NoEmptyRangesAlreadySortedAndMerged
                                        : UnsafeOverload.RangesAlreadySorted;

                result = new CompositeRange <T>(intersectionResult, overload);
            }

            return(result);
        }
        public bool HasIntersection <TKey2>(CompositeRange <T, TKey2> other)
        {
            if (IsEmpty && other.IsEmpty)
            {
                return(true);
            }
            if (!ContainingRange.HasIntersection(other.ContainingRange))
            {
                return(false);
            }

            var result = false;

            using (var containingRanges = GetMergedRanges().GetEnumerator())
            {
                var hasContainingRange = containingRanges.MoveNext();
                foreach (var otherRange in other.GetMergedRanges())
                {
                    while (hasContainingRange && containingRanges.Current.EndsBefore(otherRange))
                    {
                        hasContainingRange = containingRanges.MoveNext();
                    }

                    if (!hasContainingRange || containingRanges.Current.HasIntersection(otherRange))
                    {
                        result = hasContainingRange;
                        break;
                    }
                }
            }

            return(result);
        }
        public RangeIntersection <T> GetIntersection <TKey2>(Range <T, TKey2> other)
        {
            var ranges = new List <Range <T> >();

            if (!ContainingRange.HasIntersection(other))
            {
                return
                    (GetRangeIntersection(
                         other.From,
                         other.To,
                         Array <Range <T> > .Empty));
            }
            foreach (var range in SubRanges)
            {
                if (range.From > other.To)
                {
                    break;
                }
                if (range.To >= other.From)
                {
                    ranges.Add(range);
                }
            }
            return(GetRangeIntersection(other.From, other.To, ranges.ToArray()));
        }
        public CompositeRange <T> Except <TKey2>(CompositeRange <T, TKey2> other)
        {
            if (IsEmpty || other.IsEmpty || !ContainingRange.HasIntersection(other.ContainingRange))
            {
                return(this);
            }

            return(Intersect(other.GetComplementation()));
        }
        public bool HasIntersection(

            #region T4-dont-replace
            Range <T> other
            #endregion

            ) =>
        ContainingRange.HasIntersection(other) &&
        SubRanges.Any(r => r.HasIntersection(other));
        public bool Contains(

            #region T4-dont-replace
            Range <T> other
            #endregion

            ) =>
        ContainingRange.Contains(other) &&
        GetMergedRanges().Any(r => r.Contains(other));
        public CompositeRange <T> Except(

            #region T4-dont-replace
            CompositeRange <T> other
            #endregion

            )
        {
            if (IsEmpty || other.IsEmpty || !ContainingRange.HasIntersection(other.ContainingRange))
            {
                return(this);
            }

            return(Intersect(other.GetComplementation()));
        }
        public CompositeRange <T> Union(CompositeRange <T> other)
        {
            if (other.IsEmpty)
            {
                return(this);
            }
            if (IsEmpty)
            {
                return(other);
            }

            var ranges1      = SubRanges;
            var ranges2      = other.SubRanges;
            var resultRanges = new Range <T> [ranges1.Count + ranges2.Count];

            var overload = IsMerged && other.IsMerged
                                ? UnsafeOverload.NoEmptyRangesAlreadySortedAndMerged
                                : UnsafeOverload.RangesAlreadySorted;

            if (other.ContainingRange.EndsBefore(ContainingRange))
            {
                ranges2.CopyTo(resultRanges, 0);
                ranges1.CopyTo(resultRanges, ranges2.Count);
            }
            else
            {
                ranges1.CopyTo(resultRanges, 0);
                ranges2.CopyTo(resultRanges, ranges1.Count);

                if (!ContainingRange.EndsBefore(other.ContainingRange))
                {
                    overload = UnsafeOverload.NoEmptyRanges;
                }
            }
            var result = new CompositeRange <T>(resultRanges, overload);

            if (overload != UnsafeOverload.NoEmptyRangesAlreadySortedAndMerged)
            {
                result = result.Merge();
            }

            return(result);
        }
        public bool Contains(

            #region T4-dont-replace
            CompositeRange <T> other
            #endregion

            )
        {
            if (IsEmpty && other.IsEmpty)
            {
                return(true);
            }
            if (!ContainingRange.Contains(other.ContainingRange))
            {
                return(false);
            }

            var result = true;

            using (var containingRanges = GetMergedRanges().GetEnumerator())
            {
                var hasContainingRange = containingRanges.MoveNext();
                foreach (var otherRange in other.GetMergedRanges())
                {
                    while (hasContainingRange && containingRanges.Current.EndsBefore(otherRange))
                    {
                        hasContainingRange = containingRanges.MoveNext();
                    }

                    if (!hasContainingRange || !containingRanges.Current.Contains(otherRange))
                    {
                        result = false;
                        break;
                    }
                }
            }

            return(result);
        }
        public Range <T>[] GetIntersection(T value)
        {
            var ranges = new List <Range <T> >();

            if (!ContainingRange.Contains(value))
            {
                return(Array <Range <T> > .Empty);
            }

            foreach (var range in SubRanges)
            {
                if (range.StartsAfter(value))
                {
                    break;
                }
                if (range.Contains(value))
                {
                    ranges.Add(range);
                }
            }
            return(ranges.ToArray());
        }
 public bool HasIntersection <TKey2>(Range <T, TKey2> other) =>
 ContainingRange.HasIntersection(other) &&
 SubRanges.Any(r => r.HasIntersection(other));
 public bool Contains <TKey2>(Range <T, TKey2> other) =>
 ContainingRange.Contains(other) &&
 GetMergedRanges().Any(r => r.Contains(other));
 public bool Contains(RangeBoundaryTo <T> other) =>
 ContainingRange.Contains(other) &&
 SubRanges.Any(r => r.Contains(other));
 public bool Contains(T value) =>
 ContainingRange.Contains(value) &&
 SubRanges.Any(r => r.Contains(value));