Пример #1
0
        private static IntervalCollection <T> LowUnionOf <T>(Interval <T> a, Interval <T> b)
        {
            if (Interval.IsNullOrEmpty(a))
            {
                return(new IntervalCollection <T>(b));
            }

            if (Interval.IsNullOrEmpty(b))
            {
                return(new IntervalCollection <T>(a));
            }

            var result = new List <Interval <T> >(3);

            result.AddRange(a.DifferenceWith(b));
            result.AddRange(b.DifferenceWith(a));

            var intersection = default(Interval <T>);

            if (TryIntersectionOf(a, b, out intersection))
            {
                result.Add(intersection);
            }

            result.Sort();

            return(new IntervalCollection <T>(result));
        }
Пример #2
0
        /// <summary>
        /// Determines the complement of an <see cref="Interval&lt;T&gt;"/>.
        /// </summary>
        /// <typeparam name="T">The value type of the interval.</typeparam>
        /// <param name="value">An <see cref="Interval&lt;T&gt;"/> reference.</param>
        /// <returns>An <see cref="IntervalCollection&lt;T&gt;"/> that contains elements not in the specified interval.</returns>
        /// <seealso href="http://en.wikipedia.org/wiki/Complement_(set_theory)">Complement (set theory)</seealso>
        public static IntervalCollection <T> ComplementOf <T>(Interval <T> value)
        {
            if (Interval.IsNullOrEmpty(value))
            {
                return(new IntervalCollection <T>
                       (
                           new Interval <T>(Bound <T> .LowestBound, Bound <T> .UpmostBound)
                       ));
            }

            var lowerBound = value.LowerBound;
            var upperBound = value.UpperBound;
            var result     = new List <Interval <T> >(2);

            if (object.Equals(lowerBound, Bound <T> .LowestBound) && object.Equals(upperBound, Bound <T> .UpmostBound))
            {
            }
            else if (object.Equals(lowerBound, Bound <T> .LowestBound))
            {
                result.Add(new Interval <T>
                               (new Bound <T>(BoundType.Lower, Bound.Reverse(upperBound.Direction), upperBound.Value)
                               , Bound <T> .UpmostBound));
            }
            else if (object.Equals(upperBound, Bound <T> .UpmostBound))
            {
                result.Add(new Interval <T>
                               (Bound <T> .LowestBound
                               , new Bound <T>(BoundType.Upper, Bound.Reverse(lowerBound.Direction), lowerBound.Value)));
            }
            else
            {
                var iLower = Bound <T> .LowestBound;
                var iUpper = new Bound <T>(BoundType.Upper, Bound.Reverse(lowerBound.Direction), lowerBound.Value);

                var jLower = new Bound <T>(BoundType.Lower, Bound.Reverse(upperBound.Direction), upperBound.Value);
                var jUpper = Bound <T> .UpmostBound;

                Interval <T> i;
                if (Interval.TryParse(iLower, iUpper, out i))
                {
                    result.Add(i);
                }

                Interval <T> j;
                if (Interval.TryParse(jLower, jUpper, out j))
                {
                    result.Add(j);
                }
            }

            return(new IntervalCollection <T>(result));
        }
Пример #3
0
        /// <summary>
        /// Determines the difference of two intervals.
        /// </summary>
        /// <typeparam name="T">The value type of the interval.</typeparam>
        /// <param name="a">The first interval.</param>
        /// <param name="b">The second interval.</param>
        /// <returns>An <see cref="IntervalCollection&lt;T&gt;"/> that contains elements in <paramref name="a"/> but not in <paramref name="b"/>.</returns>
        /// <seealso href="http://en.wikipedia.org/wiki/Complement_(set_theory)">Relative complement (set theory)</seealso>
        public static IntervalCollection <T> DifferenceOf <T>(Interval <T> a, Interval <T> b)
        {
            if (Interval.IsNullOrEmpty(a))
            {
                return(new IntervalCollection <T>(a));
            }

            if (Interval.IsNullOrEmpty(b))
            {
                return(new IntervalCollection <T>(a));
            }

            // A - B = A ∩ Bc
            if (object.Equals(a, b))
            {
                return(new IntervalCollection <T>());
            }

            var c    = b.Complement;
            var args = new Interval <T> [c.Count + 1];

            args[0] = a;
            c.CopyTo(args, 1);

            var result = new List <Interval <T> >(2);

            foreach (var i in c)
            {
                var value = a.IntersectionWith(i);
                if (!Interval.IsNullOrEmpty(value))
                {
                    result.Add(value);
                }
            }

            return(new IntervalCollection <T>(result));
        }
Пример #4
0
        private static IntervalCollection <T> HighUnionOf <T>(Interval <T> a, Interval <T> b)
        {
            if (Interval.IsNullOrEmpty(a))
            {
                return(new IntervalCollection <T>(b));
            }

            if (Interval.IsNullOrEmpty(b))
            {
                return(new IntervalCollection <T>(a));
            }

            var lowestBound = Bound.Min(a.LowerBound, b.LowerBound);
            var upmostValue = Bound.Max(a.UpperBound, b.UpperBound);

            var lowerBound = default(Bound <T>);
            var upperBound = default(Bound <T>);

            //      a
            //-------------
            //      b
            //  ---------
            if (object.Equals(lowestBound, a.LowerBound) &&
                object.Equals(upmostValue, a.UpperBound))
            {
                lowerBound = new Bound <T>(BoundType.Lower
                                           , object.Equals(a.LowerBound.Value, b.LowerBound.Value)
                        ? Bound.Max(a.LowerBound.Direction, b.LowerBound.Direction)
                        : a.LowerBound.Direction
                                           , a.LowerBound.Value);
                upperBound = new Bound <T>(BoundType.Upper
                                           , object.Equals(a.UpperBound.Value, b.UpperBound.Value)
                        ? Bound.Max(a.UpperBound.Direction, b.UpperBound.Direction)
                        : a.UpperBound.Direction
                                           , a.UpperBound.Value);
            }

            //      a
            //  ---------
            //      b
            //-------------
            else if (object.Equals(lowestBound, b.LowerBound) &&
                     object.Equals(upmostValue, b.UpperBound))
            {
                lowerBound = new Bound <T>(BoundType.Lower
                                           , object.Equals(a.LowerBound.Value, b.LowerBound.Value)
                        ? Bound.Max(a.LowerBound.Direction, b.LowerBound.Direction)
                        : b.LowerBound.Direction
                                           , b.LowerBound.Value);
                upperBound = new Bound <T>(BoundType.Upper
                                           , object.Equals(a.UpperBound.Value, b.UpperBound.Value)
                        ? Bound.Max(a.UpperBound.Direction, b.UpperBound.Direction)
                        : b.UpperBound.Direction
                                           , b.UpperBound.Value);
            }

            //    a
            //---------
            //        b
            //  -------------
            else if (object.Equals(lowestBound, a.LowerBound) &&
                     object.Equals(upmostValue, b.UpperBound) &&
                     a.UpperBound.UnionCompareTo(b.LowerBound) >= 0)
            {
                lowerBound = new Bound <T>(BoundType.Lower
                                           , object.Equals(a.LowerBound.Value, b.LowerBound.Value)
                        ? Bound.Max(a.LowerBound.Direction, b.LowerBound.Direction)
                        : a.LowerBound.Direction
                                           , a.LowerBound.Value);

                upperBound = new Bound <T>(BoundType.Upper
                                           , object.Equals(a.UpperBound.Value, b.UpperBound.Value)
                        ? Bound.Max(a.UpperBound.Direction, b.UpperBound.Direction)
                        : b.UpperBound.Direction
                                           , b.UpperBound.Value);
            }

            //        a
            //  -------------
            //    b
            //---------
            else if (object.Equals(lowestBound, b.LowerBound) &&
                     object.Equals(upmostValue, a.UpperBound) &&
                     b.UpperBound.UnionCompareTo(a.LowerBound) >= 0)
            {
                lowerBound = new Bound <T>(BoundType.Lower
                                           , object.Equals(a.LowerBound.Value, b.LowerBound.Value)
                        ? Bound.Max(a.LowerBound.Direction, b.LowerBound.Direction)
                        : b.LowerBound.Direction
                                           , b.LowerBound.Value);

                upperBound = new Bound <T>(BoundType.Upper
                                           , object.Equals(a.UpperBound.Value, b.UpperBound.Value)
                        ? Bound.Max(a.UpperBound.Direction, b.UpperBound.Direction)
                        : a.UpperBound.Direction
                                           , a.UpperBound.Value);
            }
            else
            {
                return(new IntervalCollection <T>(a, b));
            }

            Interval <T> result;

            return(TryParse(lowerBound, upperBound, out result)
                ? new IntervalCollection <T>(result)
                : new IntervalCollection <T>(a, b));
        }
Пример #5
0
        /// <summary>
        /// Determines the intersection of two intervals.
        /// </summary>
        /// <typeparam name="T">The value type of the intervals.</typeparam>
        /// <param name="a">The first interval.</param>
        /// <param name="b">The second interval.</param>
        /// <returns>An <see cref="Interval&lt;T&gt;"/> that contains all elements of <paramref name="a"/>
        /// that also belong to <paramref name="b"/> (or equivalently, all elements of <paramref name="b"/>
        /// that also belong to <paramref name="a"/>), but no other elements.</returns>
        /// <seealso href="http://en.wikipedia.org/wiki/Intersection_(set_theory)">Intersection (set theory)</seealso>
        private static Interval <T> IntersectionOf <T>(Interval <T> a, Interval <T> b)
        {
            if (Interval.IsNullOrEmpty(a))
            {
                return(a);
            }
            if (Interval.IsNullOrEmpty(b))
            {
                return(b);
            }

            var lowestBound = Bound.Min(a.LowerBound, b.LowerBound);
            var upmostValue = Bound.Max(a.UpperBound, b.UpperBound);

            var lowerBound = default(Bound <T>);
            var upperBound = default(Bound <T>);

            //      a
            //-------------
            //      b
            //  ---------
            if (object.Equals(lowestBound, a.LowerBound) &&
                object.Equals(upmostValue, a.UpperBound))
            {
                lowerBound = new Bound <T>(BoundType.Lower
                                           , object.Equals(a.LowerBound.Value, b.LowerBound.Value)
                        ? Bound.Min(a.LowerBound.Direction, b.LowerBound.Direction)
                        : b.LowerBound.Direction
                                           , b.LowerBound.Value);
                upperBound = new Bound <T>(BoundType.Upper
                                           , object.Equals(a.UpperBound.Value, b.UpperBound.Value)
                        ? Bound.Min(a.UpperBound.Direction, b.UpperBound.Direction)
                        : b.UpperBound.Direction
                                           , b.UpperBound.Value);
            }

            //      a
            //  ---------
            //      b
            //-------------
            else if (object.Equals(lowestBound, b.LowerBound) &&
                     object.Equals(upmostValue, b.UpperBound))
            {
                lowerBound = new Bound <T>(BoundType.Lower
                                           , object.Equals(a.LowerBound.Value, b.LowerBound.Value)
                        ? Bound.Min(a.LowerBound.Direction, b.LowerBound.Direction)
                        : a.LowerBound.Direction
                                           , a.LowerBound.Value);
                upperBound = new Bound <T>(BoundType.Upper
                                           , object.Equals(a.UpperBound.Value, b.UpperBound.Value)
                        ? Bound.Min(a.UpperBound.Direction, b.UpperBound.Direction)
                        : a.UpperBound.Direction
                                           , a.UpperBound.Value);
            }

            //    a
            //---------
            //        b
            //  -------------
            else if (object.Equals(lowestBound, a.LowerBound) &&
                     object.Equals(upmostValue, b.UpperBound))
            {
                lowerBound = new Bound <T>(BoundType.Lower
                                           , object.Equals(a.LowerBound.Value, b.LowerBound.Value)
                        ? Bound.Min(a.LowerBound.Direction, b.LowerBound.Direction)
                        : b.LowerBound.Direction
                                           , b.LowerBound.Value);

                upperBound = new Bound <T>(BoundType.Upper
                                           , object.Equals(a.UpperBound.Value, b.UpperBound.Value)
                        ? Bound.Min(a.UpperBound.Direction, b.UpperBound.Direction)
                        : a.UpperBound.Direction
                                           , a.UpperBound.Value);
            }

            //        a
            //  -------------
            //    b
            //---------
            else if (object.Equals(lowestBound, b.LowerBound) &&
                     object.Equals(upmostValue, a.UpperBound))
            {
                lowerBound = new Bound <T>(BoundType.Lower
                                           , object.Equals(a.LowerBound.Value, b.LowerBound.Value)
                        ? Bound.Min(a.LowerBound.Direction, b.LowerBound.Direction)
                        : a.LowerBound.Direction
                                           , a.LowerBound.Value);

                upperBound = new Bound <T>(BoundType.Upper
                                           , object.Equals(a.UpperBound.Value, b.UpperBound.Value)
                        ? Bound.Min(a.UpperBound.Direction, b.UpperBound.Direction)
                        : b.UpperBound.Direction
                                           , b.UpperBound.Value);
            }
            else
            {
                return(Interval.Empty <T>());
            }

            Interval <T> result;

            return(TryParse(lowerBound, upperBound, out result)
                ? result
                : Interval.Empty <T>());
        }