예제 #1
0
파일: Ring.cs 프로젝트: xiaguoli/IoTGateway
        /// <summary>
        /// Multiplies two ring elements, if possible.
        /// </summary>
        /// <param name="Left">Left element.</param>
        /// <param name="Right">Right element.</param>
        /// <returns>Result, if understood, null otherwise.</returns>
        public virtual IRingElement Multiply(IRingElement Left, IRingElement Right)
        {
            IRingElement Result;

            Result = Left.MultiplyRight(Right);
            if (Result != null)
            {
                return(Result);
            }

            Result = Right.MultiplyLeft(Left);
            if (Result != null)
            {
                return(Result);
            }

            return(null);
        }
예제 #2
0
        /// <summary>
        /// Divides the left operand from the right one.
        /// </summary>
        /// <param name="Left">Left operand.</param>
        /// <param name="Right">Right operand.</param>
        /// <param name="Node">Node performing the operation.</param>
        /// <returns>Result</returns>
        public static IElement EvaluateDivision(IElement Left, IElement Right, ScriptNode Node)
        {
            IRingElement LE = Left as IRingElement;
            IRingElement RE = Right as IRingElement;
            IElement     Result;
            IRingElement Temp;

            if (LE != null && RE != null)
            {
                // TODO: Optimize in case of matrices. It's more efficient to employ a solve algorithm than to compute the inverse and the multiply.

                Temp = LE.Invert();
                if (Temp != null)
                {
                    Result = RE.MultiplyLeft(Temp);
                    if (Result != null)
                    {
                        return(Result);
                    }

                    Result = Temp.MultiplyRight(RE);
                    if (Result != null)
                    {
                        return(Result);
                    }
                }
            }

            if (Left.IsScalar)
            {
                if (Right.IsScalar)
                {
                    ISet LeftSet  = Left.AssociatedSet;
                    ISet RightSet = Right.AssociatedSet;

                    if (!LeftSet.Equals(RightSet))
                    {
                        if (!Expression.Upgrade(ref Left, ref LeftSet, ref Right, ref RightSet, Node))
                        {
                            throw new ScriptRuntimeException("Incompatible operands.", Node);
                        }

                        LE = Left as IRingElement;
                        RE = Right as IRingElement;
                        if (LE != null && RE != null)
                        {
                            Temp = LE.Invert();
                            if (Temp != null)
                            {
                                Result = RE.MultiplyLeft(Temp);
                                if (Result != null)
                                {
                                    return(Result);
                                }

                                Result = Temp.MultiplyRight(RE);
                                if (Result != null)
                                {
                                    return(Result);
                                }
                            }
                        }
                    }

                    throw new ScriptRuntimeException("Operands cannot be divided.", Node);
                }
                else
                {
                    LinkedList <IElement> Elements = new LinkedList <IElement>();

                    foreach (IElement RightChild in Right.ChildElements)
                    {
                        Elements.AddLast(EvaluateDivision(Left, RightChild, Node));
                    }

                    return(Right.Encapsulate(Elements, Node));
                }
            }
            else
            {
                if (Right.IsScalar)
                {
                    LinkedList <IElement> Elements = new LinkedList <IElement>();

                    foreach (IElement LeftChild in Left.ChildElements)
                    {
                        Elements.AddLast(EvaluateDivision(LeftChild, Right, Node));
                    }

                    return(Left.Encapsulate(Elements, Node));
                }
                else
                {
                    ISet Set1 = Left as ISet;
                    ISet Set2 = Right as ISet;

                    if (Set1 != null && Set2 != null)
                    {
                        return(new SetDifference(Set1, Set2));
                    }
                    else
                    {
                        ICollection <IElement> LeftChildren  = Left.ChildElements;
                        ICollection <IElement> RightChildren = Right.ChildElements;

                        if (LeftChildren.Count == RightChildren.Count)
                        {
                            LinkedList <IElement>  Elements = new LinkedList <IElement>();
                            IEnumerator <IElement> eLeft    = LeftChildren.GetEnumerator();
                            IEnumerator <IElement> eRight   = RightChildren.GetEnumerator();

                            try
                            {
                                while (eLeft.MoveNext() && eRight.MoveNext())
                                {
                                    Elements.AddLast(EvaluateDivision(eLeft.Current, eRight.Current, Node));
                                }
                            }
                            finally
                            {
                                eLeft.Dispose();
                                eRight.Dispose();
                            }

                            return(Left.Encapsulate(Elements, Node));
                        }
                        else
                        {
                            LinkedList <IElement> LeftResult = new LinkedList <IElement>();

                            foreach (IElement LeftChild in LeftChildren)
                            {
                                LinkedList <IElement> RightResult = new LinkedList <IElement>();

                                foreach (IElement RightChild in RightChildren)
                                {
                                    RightResult.AddLast(EvaluateDivision(LeftChild, RightChild, Node));
                                }

                                LeftResult.AddLast(Right.Encapsulate(RightResult, Node));
                            }

                            return(Left.Encapsulate(LeftResult, Node));
                        }
                    }
                }
            }
        }
예제 #3
0
        /// <summary>
        /// Multiplies two operands.
        /// </summary>
        /// <param name="Left">Left operand.</param>
        /// <param name="Right">Right operand.</param>
        /// <param name="Node">Node performing the operation.</param>
        /// <returns>Result</returns>
        public static IElement EvaluateMultiplication(IElement Left, IElement Right, ScriptNode Node)
        {
            IRingElement LE = Left as IRingElement;
            IRingElement RE = Right as IRingElement;
            IElement     Result;

            if (LE != null && RE != null)
            {
                Result = LE.MultiplyRight(RE);
                if (Result != null)
                {
                    return(Result);
                }

                Result = RE.MultiplyLeft(LE);
                if (Result != null)
                {
                    return(Result);
                }
            }

            if (Left.IsScalar)
            {
                if (Right.IsScalar)
                {
                    ISet LeftSet  = Left.AssociatedSet;
                    ISet RightSet = Right.AssociatedSet;

                    if (!LeftSet.Equals(RightSet))
                    {
                        if (!Expression.Upgrade(ref Left, ref LeftSet, ref Right, ref RightSet, Node))
                        {
                            throw new ScriptRuntimeException("Incompatible operands.", Node);
                        }

                        LE = Left as IRingElement;
                        RE = Right as IRingElement;
                        if (LE != null && RE != null)
                        {
                            Result = LE.MultiplyRight(RE);
                            if (Result != null)
                            {
                                return(Result);
                            }

                            Result = RE.MultiplyLeft(LE);
                            if (Result != null)
                            {
                                return(Result);
                            }
                        }
                    }

                    throw new ScriptRuntimeException("Operands cannot be multiplied.", Node);
                }
                else
                {
                    LinkedList <IElement> Elements = new LinkedList <IElement>();

                    foreach (IElement RightChild in Right.ChildElements)
                    {
                        Elements.AddLast(EvaluateMultiplication(Left, RightChild, Node));
                    }

                    return(Right.Encapsulate(Elements, Node));
                }
            }
            else
            {
                if (Right.IsScalar)
                {
                    LinkedList <IElement> Elements = new LinkedList <IElement>();

                    foreach (IElement LeftChild in Left.ChildElements)
                    {
                        Elements.AddLast(EvaluateMultiplication(LeftChild, Right, Node));
                    }

                    return(Left.Encapsulate(Elements, Node));
                }
                else
                {
                    ICollection <IElement> LeftChildren  = Left.ChildElements;
                    ICollection <IElement> RightChildren = Right.ChildElements;

                    if (LeftChildren.Count == RightChildren.Count)
                    {
                        LinkedList <IElement>  Elements = new LinkedList <IElement>();
                        IEnumerator <IElement> eLeft    = LeftChildren.GetEnumerator();
                        IEnumerator <IElement> eRight   = RightChildren.GetEnumerator();

                        try
                        {
                            while (eLeft.MoveNext() && eRight.MoveNext())
                            {
                                Elements.AddLast(EvaluateMultiplication(eLeft.Current, eRight.Current, Node));
                            }
                        }
                        finally
                        {
                            eLeft.Dispose();
                            eRight.Dispose();
                        }

                        return(Left.Encapsulate(Elements, Node));
                    }
                    else
                    {
                        LinkedList <IElement> LeftResult = new LinkedList <IElement>();

                        foreach (IElement LeftChild in LeftChildren)
                        {
                            LinkedList <IElement> RightResult = new LinkedList <IElement>();

                            foreach (IElement RightChild in RightChildren)
                            {
                                RightResult.AddLast(EvaluateMultiplication(LeftChild, RightChild, Node));
                            }

                            LeftResult.AddLast(Right.Encapsulate(RightResult, Node));
                        }

                        return(Left.Encapsulate(LeftResult, Node));
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Divides the left operand from the right one.
        /// </summary>
        /// <param name="Left">Left operand.</param>
        /// <param name="Right">Right operand.</param>
        /// <param name="Node">Node performing the operation.</param>
        /// <returns>Result</returns>
        public static IElement EvaluateDivision(IElement Left, IElement Right, ScriptNode Node)
        {
            IRingElement RE = Right as IRingElement;
            IElement     Result;
            IRingElement Temp;

            if (Left is IRingElement LE && !(RE is null))
            {
                // TODO: Optimize in case of matrices. It's more efficient to employ a solve algorithm than to compute the inverse and the multiply.

                Temp = LE.Invert();
                if (!(Temp is null))
                {
                    Result = RE.MultiplyLeft(Temp);
                    if (!(Result is null))
                    {
                        return(Result);
                    }

                    Result = Temp.MultiplyRight(RE);
                    if (!(Result is null))
                    {
                        return(Result);
                    }
                }
            }

            if (Left.IsScalar)
            {
                if (Right.IsScalar)
                {
                    ISet LeftSet  = Left.AssociatedSet;
                    ISet RightSet = Right.AssociatedSet;

                    if (!LeftSet.Equals(RightSet))
                    {
                        if (!Expression.UpgradeField(ref Left, ref LeftSet, ref Right, ref RightSet, Node))
                        {
                            throw new ScriptRuntimeException("Incompatible operands.", Node);
                        }

                        LE = Left as IRingElement;
                        RE = Right as IRingElement;
                        if (!(LE is null) && !(RE is null))
                        {
                            Temp = LE.Invert();
                            if (!(Temp is null))
                            {
                                Result = RE.MultiplyLeft(Temp);
                                if (!(Result is null))
                                {
                                    return(Result);
                                }

                                Result = Temp.MultiplyRight(RE);
                                if (!(Result is null))
                                {
                                    return(Result);
                                }
                            }
                        }
                    }

                    throw new ScriptRuntimeException("Operands cannot be divided.", Node);
                }
                else
                {
                    LinkedList <IElement> Elements = new LinkedList <IElement>();

                    foreach (IElement RightChild in Right.ChildElements)
                    {
                        Elements.AddLast(EvaluateDivision(Left, RightChild, Node));
                    }

                    return(Right.Encapsulate(Elements, Node));
                }
            }
            else
            {
                if (Right.IsScalar)
                {
                    LinkedList <IElement> Elements = new LinkedList <IElement>();

                    foreach (IElement LeftChild in Left.ChildElements)
                    {
                        Elements.AddLast(EvaluateDivision(LeftChild, Right, Node));
                    }

                    return(Left.Encapsulate(Elements, Node));
                }
                else
                {
                    ISet Set2 = Right as ISet;

                    if (Left is ISet Set1 && !(Set2 is null))
                    {
                        return(new SetDifference(Set1, Set2));
                    }