override public bool LessEqual(IAbstractDomain /*!*/ a)
        {
            bool result;

            if (AbstractDomainsHelper.TryTrivialLess(this, a, out result))
            {
                return(result);
            }

            ProductIntervalsWeakUpperBounds <Expression> r = a as ProductIntervalsWeakUpperBounds <Expression>;

            bool b1 = this.Left.LessEqual(r.Left);
            bool b2 = this.Right.LessEqual(r.Right);

            return(b1 & b2);
        }
        /// <summary>
        /// The pairwise widening
        /// </summary>
        public override IAbstractDomain Widening(IAbstractDomain prev)
        {
            if (this.IsBottom)
            {
                return(prev);
            }
            if (prev.IsBottom)
            {
                return(this);
            }

            Debug.Assert(prev is ProductIntervalsWeakUpperBounds <Expression>, "Wrong type of the domain for the widening...");

            ProductIntervalsWeakUpperBounds <Expression> asIntWSUB = (ProductIntervalsWeakUpperBounds <Expression>)prev;

            IntervalEnvironment <Rational, Expression> widenLeft  = (IntervalEnvironment <Rational, Expression>) this.Left.Widening(asIntWSUB.Left);
            WeakUpperBounds <Expression, Rational>     widenRight = (WeakUpperBounds <Expression, Rational>) this.Right.Widening(asIntWSUB.Right);

            ProductIntervalsWeakUpperBounds <Expression> result = (ProductIntervalsWeakUpperBounds <Expression>) this.Factory(widenLeft, widenRight);

            return(result);
        }
        /// <summary>
        /// This is a version of the join which causes a partial propagation of the information from Intervals to Symbolic upper bounds
        /// </summary>
        /// <param name="a">The other element</param>
        public override IAbstractDomain Join(IAbstractDomain a)
        {
            if (this.IsBottom)
            {
                return(a);
            }
            if (a.IsBottom)
            {
                return(this);
            }
            if (this.IsTop)
            {
                return(this);
            }
            if (a.IsTop)
            {
                return(a);
            }

            //^ assert a is ReducedCartesianAbstractDomain<LeftDomain, RightDomain>;

            ProductIntervalsWeakUpperBounds <Expression> r = a as ProductIntervalsWeakUpperBounds <Expression>;

            if (a == null)
            {
                Debug.Assert(false, "Error cannot compare a cartesian abstract element with a " + a.GetType());
            }

            IntervalEnvironment <Rational, Expression> joinLeftPart;
            WeakUpperBounds <Expression, Rational>     joinRightPart;

            joinLeftPart  = (IntervalEnvironment <Rational, Expression>) this.Left.Join(r.Left);
            joinRightPart = (WeakUpperBounds <Expression, Rational>) this.right.Join(r.Right);

            return(this.Factory(joinLeftPart, joinRightPart));
        }