/// <summary> /// Tries to multiply an element to the current element, from the left. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IRingElement MultiplyLeft(IRingElement Element) { Complex[,] Values = this.Values; ComplexNumber Number = Element as ComplexNumber; ComplexMatrix Matrix; Complex[,] v; Complex n; int x, y, z; if (!(Number is null)) { n = Number.Value; v = new Complex[this.rows, this.columns]; for (y = 0; y < this.rows; y++) { for (x = 0; x < this.columns; x++) { v[y, x] = n * Values[y, x]; } } return(new ComplexMatrix(v)); }
/// <summary> /// Tries to multiply an element to the current element, from the left. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IRingElement MultiplyLeft(IRingElement Element) { double[,] Values = this.Values; DoubleNumber Number = Element as DoubleNumber; DoubleMatrix Matrix; double[,] v; double n; int x, y, z; if (!(Number is null)) { n = Number.Value; v = new double[this.rows, this.columns]; for (y = 0; y < this.rows; y++) { for (x = 0; x < this.columns; x++) { v[y, x] = n * Values[y, x]; } } return(new DoubleMatrix(v)); }
private IElement Evaluate(IElement Element) { IRingElement E = Operand as IRingElement; if (E != null) { E = E.Invert(); if (E == null) { throw new ScriptRuntimeException("Operand not invertible.", this); } else { return(E); } } else if (E.IsScalar) { throw new ScriptRuntimeException("Operand not invertible.", this); } else { LinkedList <IElement> Elements = new LinkedList <IElement>(); foreach (IElement E2 in E.ChildElements) { Elements.AddLast(this.Evaluate(E2)); } return(E.Encapsulate(Elements, this)); } }
/// <summary> /// Evaluates the operator. /// </summary> /// <param name="Operand">Operand.</param> /// <returns>Result</returns> public virtual IElement Evaluate(IElement Operand) { if (Operand is DoubleNumber DOp) { double d = DOp.Value; return(new DoubleNumber(d * d * d)); } if (Operand is IRingElement E) { IRingElement E2 = (IRingElement)Multiply.EvaluateMultiplication(E, E, this); return(Multiply.EvaluateMultiplication(E2, E, this)); } if (Operand.IsScalar) { throw new ScriptRuntimeException("Scalar operands must be double values or ring elements.", this); } LinkedList <IElement> Result = new LinkedList <IElement>(); foreach (IElement Child in Operand.ChildElements) { Result.AddLast(this.Evaluate(Child)); } return(Operand.Encapsulate(Result, this)); }
/// <summary> /// Tries to multiply an element to the current element, from the left. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IRingElement MultiplyLeft(IRingElement Element) { IElement[,] Values = this.Values; ObjectMatrix Matrix; IElement[,] v; IElement n; int x, y, z; if (Element.IsScalar) { v = new IElement[this.rows, this.columns]; for (y = 0; y < this.rows; y++) { for (x = 0; x < this.columns; x++) { v[y, x] = Operators.Arithmetics.Multiply.EvaluateMultiplication(Element, Values[y, x], null); } } return(new ObjectMatrix(v)); } else if (!((Matrix = Element as ObjectMatrix) is null)) { if (Matrix.columns != this.rows) { return(null); } IElement[,] Values2 = Matrix.Values; v = new IElement[Matrix.rows, this.columns]; for (y = 0; y < Matrix.rows; y++) { for (x = 0; x < this.columns; x++) { n = null; for (z = 0; z < this.rows; z++) { if (n is null) { n = Operators.Arithmetics.Multiply.EvaluateMultiplication(Values2[y, z], Values[z, x], null); } else { n = Operators.Arithmetics.Add.EvaluateAddition(n, Operators.Arithmetics.Multiply.EvaluateMultiplication(Values2[y, z], Values[z, x], null), null); } } v[y, x] = n; } } return(new ObjectMatrix(v)); }
/// <summary> /// Tries to multiply an element to the current element, from the left. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IRingElement MultiplyLeft(IRingElement Element) { Complex[,] Values = this.Values; ComplexNumber Number = Element as ComplexNumber; ComplexMatrix Matrix; Complex[,] v; Complex n; int x, y, z; if (Number != null) { n = Number.Value; v = new Complex[this.rows, this.columns]; for (y = 0; y < this.rows; y++) { for (x = 0; x < this.columns; x++) { v[y, x] = n * Values[y, x]; } } return(new ComplexMatrix(v)); } else if ((Matrix = Element as ComplexMatrix) != null) { if (Matrix.columns != this.rows) { return(null); } Complex[,] Values2 = Matrix.Values; v = new Complex[Matrix.rows, this.columns]; for (y = 0; y < Matrix.rows; y++) { for (x = 0; x < this.columns; x++) { n = 0; for (z = 0; z < this.rows; z++) { n += Values2[y, z] * Values[z, x]; } v[y, x] = n; } } return(new ComplexMatrix(v)); } else { return(null); } }
/// <summary> /// Tries to multiply an element to the current element, from the right. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IRingElement MultiplyRight(IRingElement Element) { double[,] Values = this.Values; DoubleNumber Number = Element as DoubleNumber; DoubleMatrix Matrix; double[,] v; double n; int x, y, z; if (Number != null) { n = Number.Value; v = new double[this.rows, this.columns]; for (y = 0; y < this.rows; y++) { for (x = 0; x < this.columns; x++) { v[y, x] = n * Values[y, x]; } } return(new DoubleMatrix(v)); } else if ((Matrix = Element as DoubleMatrix) != null) { if (this.columns != Matrix.rows) { return(null); } double[,] Values2 = Matrix.Values; v = new double[this.rows, Matrix.columns]; for (y = 0; y < this.rows; y++) { for (x = 0; x < Matrix.columns; x++) { n = 0; for (z = 0; z < this.columns; z++) { n += Values[y, z] * Values2[z, x]; } v[y, x] = n; } } return(new DoubleMatrix(v)); } else { return(null); } }
/// <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 override sealed IRingElement RightDivide(IRingElement Left, IRingElement Right) { ICommutativeRingElement L = Left as ICommutativeRingElement; ICommutativeRingElement R = Right as ICommutativeRingElement; if (L is null || R is null) { return(base.RightDivide(Left, Right)); }
/// <summary> /// Performs a scalar multiplication, if possible. /// </summary> /// <param name="Scalar">Scalar element.</param> /// <param name="ModuleElement">Module element.</param> /// <returns>Result, if understood, null otherwise.</returns> public virtual ILeftModuleElement MultiplyScalarLeft(IRingElement Scalar, ILeftModuleElement ModuleElement) { if (ModuleElement is IModuleElement E) { return(this.MultiplyScalar(Scalar, E)); } else { return(null); } }
/// <summary> /// Tries to multiply an element to the current element, from the right. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IRingElement MultiplyRight(IRingElement Element) { if (Element is ICommutativeRingElement E) { return(this.Multiply(E)); } else { return(null); } }
/// <summary> /// Tries to multiply a scalar to the current element. /// </summary> /// <param name="Scalar">Scalar to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IModuleElement MultiplyScalar(IRingElement Scalar) { if (Scalar is IFieldElement FieldElement) { return(this.MultiplyScalar(FieldElement)); } else { return(null); } }
/// <summary> /// Tries to multiply an element to the current element, from the right. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IRingElement MultiplyRight(IRingElement Element) { ICommutativeRingElement E = Element as ICommutativeRingElement; if (E == null) { return(null); } else { return(this.Multiply(E)); } }
/// <summary> /// Performs a scalar multiplication, if possible. /// </summary> /// <param name="Scalar">Scalar element.</param> /// <param name="ModuleElement">Module element.</param> /// <returns>Result, if understood, null otherwise.</returns> public virtual ILeftModuleElement MultiplyScalarLeft(IRingElement Scalar, ILeftModuleElement ModuleElement) { IModuleElement E = ModuleElement as IModuleElement; if (E == null) { return(null); } else { return(this.MultiplyScalar(Scalar, E)); } }
/// <summary> /// Tries to multiply a scalar to the current element. /// </summary> /// <param name="Scalar">Scalar to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IModuleElement MultiplyScalar(IRingElement Scalar) { IFieldElement FieldElement = Scalar as IFieldElement; if (FieldElement is null) { return(null); } else { return(this.MultiplyScalar(FieldElement)); } }
/// <summary> /// Divides the left ring element from the right one: (1/Left)*Right. /// </summary> /// <param name="Left">Left element.</param> /// <param name="Right">Right element.</param> /// <returns>Result, if understood, null otherwise.</returns> public virtual IRingElement LeftDivide(IRingElement Left, IRingElement Right) { IRingElement Inverse = Left.Invert(); if (Inverse == null) { return(null); } else { return(this.Multiply(Inverse, Right) as IRingElement); } }
/// <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 override sealed IRingElement RightDivide(IRingElement Left, IRingElement Right) { ICommutativeRingElement L = Left as ICommutativeRingElement; ICommutativeRingElement R = Right as ICommutativeRingElement; if (L == null || R == null) { return(base.RightDivide(Left, Right)); } else { return(this.Divide(L, R)); } }
/// <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> /// Evaluates the function on a vector argument. /// </summary> /// <param name="Argument">Function argument.</param> /// <param name="Variables">Variables collection.</param> /// <returns>Function result.</returns> public override IElement EvaluateVector(IVector Argument, Variables Variables) { IRingElement Result = null; IRingElement RE; IRingElement Product; foreach (IElement E in Argument.ChildElements) { RE = E as IRingElement; if (RE is null) { if (Argument.ChildElements.Count == 1) { return(E); } else { throw new ScriptRuntimeException("Elements cannot be multiplied.", this); } } if (Result is null) { Result = RE; } else { Product = Result.MultiplyRight(RE); if (Product is null) { Product = (IRingElement)Operators.Arithmetics.Multiply.EvaluateMultiplication(Result, RE, this); } Result = Product; } } if (Result is null) { return(ObjectValue.Null); } else { return(Result); } }
/// <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> /// Calculates the average of the elements of a vector. /// </summary> /// <param name="Vector">Vector</param> /// <param name="Node">Node performing evaluation.</param> /// <returns>Average of elements.</returns> public static IElement EvaluateAverage(IVector Vector, ScriptNode Node) { IElement Result = Vectors.Sum.EvaluateSum(Vector, Node); int n = Vector.Dimension; if (Result == null) { return(ObjectValue.Null); } else { IRingElement RE = Result as IRingElement; IRingElement Avg; if (RE != null && (Avg = RE.MultiplyRight(new DoubleNumber(1.0 / n))) != null) { return(Avg); } else { return(Operators.Arithmetics.Divide.EvaluateDivision(Result, new DoubleNumber(n), 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 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 override sealed IRingElement RightDivide(IRingElement Left, IRingElement Right) { if (Left is ICommutativeRingElement L && Right is ICommutativeRingElement R) { return(this.Divide(L, R)); }
/// <summary> /// Tries to multiply an element to the current element, from the right. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public override IRingElement MultiplyRight(IRingElement Element) { 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> /// Performs a scalar multiplication, if possible. /// </summary> /// <param name="Scalar">Scalar element.</param> /// <param name="ModuleElement">Module element.</param> /// <returns>Result, if understood, null otherwise.</returns> public abstract ILeftModuleElement MultiplyScalarLeft(IRingElement Scalar, ILeftModuleElement ModuleElement);
/// <summary> /// Performs a scalar multiplication, if possible. /// </summary> /// <param name="ModuleElement">Module element.</param> /// <param name="Scalar">Scalar element.</param> /// <returns>Result, if understood, null otherwise.</returns> public abstract IRightModuleElement MultiplyScalarRight(IRightModuleElement ModuleElement, IRingElement Scalar);
/// <summary> /// Performs a scalar multiplication, if possible. /// </summary> /// <param name="ModuleElement">Module element.</param> /// <param name="Scalar">Scalar element.</param> /// <returns>Result, if understood, null otherwise.</returns> public virtual IModuleElement MultiplyScalar(IRingElement Scalar, IModuleElement ModuleElement) { return(ModuleElement.MultiplyScalar(Scalar)); }
/// <summary> /// Tries to multiply an element to the current element, from the left. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public abstract IRingElement MultiplyLeft(IRingElement Element);
/// <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 DR = Right as DoubleNumber; if (Left is DoubleNumber DL && DR != null) { return(new DoubleNumber(Math.Pow(DL.Value, DR.Value))); } if (Left is IRingElement LE && 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) { if (!(LE is ICommutativeRingWithIdentityElement LE2)) { 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)); } } } }
/// <summary> /// Tries to multiply an element to the current element, from the right. /// </summary> /// <param name="Element">Element to multiply.</param> /// <returns>Result, if understood, null otherwise.</returns> public abstract IRingElement MultiplyRight(IRingElement Element);