/// <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); }
/// <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)); } } } } }
/// <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)); } } } }
/// <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)); }