/// <summary> /// Divides the right ring element from the left one: Left*(1/Right) /// </summary> /// <param name="Left">Left element.</param> /// <param name="Right">Right element.</param> /// <returns>Result, if understood, null otherwise.</returns> public virtual IRingElement RightDivide(IRingElement Left, IRingElement Right) { IRingElement Inverse = Right.Invert(); if (Inverse is null) { return(null); } else { return(this.Multiply(Left, Inverse) as IRingElement); } }
/// <summary> /// Evaluates the function. /// </summary> /// <param name="Argument">Function argument.</param> /// <param name="Variables">Variables collection.</param> /// <returns>Function result.</returns> public override IElement Evaluate(IElement Argument, Variables Variables) { IRingElement E = Argument as IRingElement; if (E != null) { E = E.Invert(); if (E != null) { return(E); } } return(base.Evaluate(Argument, Variables)); }
/// <summary> /// Divides the right operand from the left 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 != null) { Temp = RE.Invert(); if (Temp != null) { Result = LE.MultiplyRight(Temp); if (Result != null) { return(Result); } Result = Temp.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) { Temp = RE.Invert(); if (Temp != null) { Result = LE.MultiplyRight(Temp); if (Result != null) { return(Result); } Result = Temp.MultiplyLeft(LE); 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 { 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> /// Calculates Left ^ Right. /// </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 EvaluatePower(IElement Left, IElement Right, ScriptNode Node) { DoubleNumber DL = Left as DoubleNumber; DoubleNumber DR = Right as DoubleNumber; if (DL != null && DR != null) { return(new DoubleNumber(Math.Pow(DL.Value, DR.Value))); } IRingElement LE = Left as IRingElement; if (LE != null && DR != null) { double d = DR.Value; if (d >= long.MinValue && d <= long.MaxValue && Math.Truncate(d) == d) { long n = (long)d; if (n < 0) { LE = LE.Invert(); if (LE == null) { throw new ScriptRuntimeException("Base element not invertible.", Node); } n = -n; } else if (n == 0) { ICommutativeRingWithIdentityElement LE2 = LE as ICommutativeRingWithIdentityElement; if (LE2 == null) { throw new ScriptRuntimeException("Base element ring does not have unity.", Node); } return(LE2.One); } IRingElement Result = null; while (n > 0) { if ((n & 1) == 1) { if (Result == null) { Result = LE; } else { Result = (IRingElement)Multiply.EvaluateMultiplication(Result, LE, Node); } } n >>= 1; if (n > 0) { LE = (IRingElement)Multiply.EvaluateMultiplication(LE, LE, Node); } } return(Result); } else { throw new ScriptRuntimeException("Exponent too large.", Node); } } if (Left.IsScalar) { if (Right.IsScalar) { throw new ScriptRuntimeException("Power operation could not be computed.", Node); } else { LinkedList <IElement> Elements = new LinkedList <IElement>(); foreach (IElement RightChild in Right.ChildElements) { Elements.AddLast(EvaluatePower(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(EvaluatePower(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(EvaluatePower(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(EvaluatePower(LeftChild, RightChild, Node)); } LeftResult.AddLast(Right.Encapsulate(RightResult, Node)); } return(Left.Encapsulate(LeftResult, Node)); } } } }