public IntDomain2 Intersect(IntDomain2 domain) { if (ReferenceEquals(domain, this)) { return(this); } if (domain.IsEmpty()) { return(m_Empty); } if (domain.IsSimple()) { return(Intersect(domain.m_Interval)); } // 1, 6 if (!IntersectsWith(domain)) { return(m_Empty); } // If the target is contained, then the result would be equal to the domain, hence we return the domain. if (IsSimple()) { if (domain.Contains(m_Interval)) { return(this); } if (m_Interval.Contains(domain.m_Interval)) { return(domain); } } // Need to be a bit smart, put our interval in a list, in case it gets chopped up. List <IntInterval> intervalList; if (IsSimple()) { intervalList = new List <IntInterval>(1); intervalList.Add(m_Interval); } else { intervalList = m_IntervalList; } IntDomain2 result = new IntDomain2(); result.m_IntervalList = new List <IntInterval>(intervalList.Count + domain.m_IntervalList.Count); int idx = 0; int domIdx = 0; bool equal = true; while (idx < intervalList.Count || domIdx < domain.m_IntervalList.Count) { // 6 if (idx == intervalList.Count) { domIdx = domain.m_IntervalList.Count; } // 1 else if (domIdx == domain.m_IntervalList.Count) { idx = intervalList.Count; equal = false; } else { IntInterval intv = intervalList[idx]; IntInterval domIntv = domain.m_IntervalList[domIdx]; // 1 : completely before if (domIntv.Max < intv.Min - 1) { ++domIdx; } // 6 : completely after else if (domIntv.Min > intv.Max + 1) { ++idx; equal = false; } // 3 else if (domIntv.Min <= intv.Min && domIntv.Max >= intv.Max) { result.m_IntervalList.Add(intv); ++idx; } // ~4 : divide into two intervals... else if (domIntv.Min > intv.Min && domIntv.Max < intv.Max) { result.m_IntervalList.Add(domIntv); ++domIdx; equal = false; } // 2 else if (domIntv.Min <= intv.Min && domIntv.Max < intv.Max) { result.m_IntervalList.Add(intv.Intersect(domIntv)); ++domIdx; equal = false; } // 5 else if (domIntv.Min > intv.Min && domIntv.Max >= intv.Max) { result.m_IntervalList.Add(intv.Intersect(domIntv)); ++idx; equal = false; } } } if (equal) { return(this); } result.UpdateInterval(); return(result); }
public IntDomain2 Difference(IntDomain2 domain) { if (ReferenceEquals(domain, this)) { return(m_Empty); } if (domain.IsEmpty()) { return(this); } if (domain.IsSimple()) { return(Difference(domain.m_Interval)); } //1, 6 if (!IntersectsWith(domain.m_Interval)) { return(this); } // Need to be a bit smart, put our interval in a list, in case it gets chopped up. List <IntInterval> intervalList; if (IsSimple()) { intervalList = new List <IntInterval>(1); intervalList.Add(m_Interval); } else { intervalList = m_IntervalList; } IntDomain2 result = new IntDomain2(); result.m_IntervalList = new List <IntInterval>(intervalList.Count + domain.m_IntervalList.Count); int idx = 0; int domIdx = 0; while (idx < intervalList.Count || domIdx < domain.m_IntervalList.Count) { // 6 if (idx == intervalList.Count) { domIdx = domain.m_IntervalList.Count; } // 1 else if (domIdx == domain.m_IntervalList.Count) { idx = intervalList.Count; } else { IntInterval intv = intervalList[idx]; IntInterval domIntv = domain.m_IntervalList[domIdx]; // 1 : completely before if (domIntv.Max < intv.Min - 1) { ++domIdx; } // 6 : completely after else if (domIntv.Min > intv.Max + 1) { result.m_IntervalList.Add(intv); ++idx; } // 3 else if (domIntv.Min < intv.Min && domIntv.Max > intv.Max) { ++idx; } // 4 : divide into two intervals... else if (domIntv.Min > intv.Min && domIntv.Max < intv.Max) { while (domIdx < domain.m_IntervalList.Count && domIntv.Min > intv.Min && domIntv.Max < intv.Max) { result.m_IntervalList.Add(new IntInterval(intv.Min, domIntv.Min - 1)); intv = new IntInterval(domIntv.Max + 1, intv.Max); ++domIdx; if (domIdx < domain.m_IntervalList.Count) { domIntv = domain.m_IntervalList[domIdx]; } } result.m_IntervalList.Add(intv); } // 2 else if (domIntv.Min <= intv.Min && domIntv.Max < intv.Max) { result.m_IntervalList.Add(intv.Difference(domIntv)); ++domIdx; } // 5 else if (domIntv.Min > intv.Min && domIntv.Max >= intv.Max) { result.m_IntervalList.Add(intv.Difference(domIntv)); ++idx; } } } result.UpdateInterval(); return(result); }