/// <summary> /// Evaluates the node, using the variables provided in the <paramref name="Variables"/> collection. /// </summary> /// <param name="Variables">Variables collection.</param> /// <returns>Result.</returns> public override IElement Evaluate(Variables Variables) { ICommutativeRingWithIdentityElement From = this.left.Evaluate(Variables) as ICommutativeRingWithIdentityElement; if (From is null) { throw new ScriptRuntimeException("Invalid range.", this); } ICommutativeRingWithIdentityElement To = this.middle.Evaluate(Variables) as ICommutativeRingWithIdentityElement; if (To is null) { throw new ScriptRuntimeException("Invalid range.", this); } IOrderedSet S = From.AssociatedSet as IOrderedSet; if (S is null) { throw new ScriptRuntimeException("Cannot compare range.", this); } IElement Step, Last; int Direction = S.Compare(From, To); bool Done; if (!(this.middle2 is null)) { Step = this.middle2.Evaluate(Variables); if (Direction < 0) { if (S.Compare(Step, From.Zero) <= 0) { throw new ScriptRuntimeException("Invalid step size for corresponding range.", this); } } else if (Direction > 0) { if (S.Compare(Step, From.Zero) >= 0) { throw new ScriptRuntimeException("Invalid step size for corresponding range.", this); } } }
/// <summary> /// Increments a value. /// </summary> /// <param name="Value">Value to increment.</param> /// <param name="Node">Node performing the evaluation.</param> /// <returns>Incremented value.</returns> public static IElement Increment(IElement Value, ScriptNode Node) { ICommutativeRingWithIdentityElement e = Value as ICommutativeRingWithIdentityElement; if (e != null) { return(Operators.Arithmetics.Add.EvaluateAddition(Value, e.One, Node)); } else if (Value.IsScalar) { throw new ScriptRuntimeException("Unable to increment variable.", Node); } else { LinkedList <IElement> Elements = new LinkedList <IElement>(); foreach (IElement Element in Value.ChildElements) { Elements.AddLast(Increment(Element, Node)); } return(Value.Encapsulate(Elements, Node)); } }
/// <summary> /// Evaluates the node, using the variables provided in the <paramref name="Variables"/> collection. /// </summary> /// <param name="Variables">Variables collection.</param> /// <returns>Result.</returns> public override IElement Evaluate(Variables Variables) { ICommutativeRingWithIdentityElement From = this.left.Evaluate(Variables) as ICommutativeRingWithIdentityElement; if (From == null) { throw new ScriptRuntimeException("Invalid range.", this); } ICommutativeRingWithIdentityElement To = this.middle.Evaluate(Variables) as ICommutativeRingWithIdentityElement; if (To == null) { throw new ScriptRuntimeException("Invalid range.", this); } IOrderedSet S = From.AssociatedSet as IOrderedSet; if (S == null) { throw new ScriptRuntimeException("Cannot compare range.", this); } IElement Step; int Direction = S.Compare(From, To); bool Done; if (this.middle2 != null) { Step = this.middle2.Evaluate(Variables); if (Direction < 0) { if (S.Compare(Step, From.Zero) <= 0) { throw new ScriptRuntimeException("Invalid step size for corresponding range.", this); } } else if (Direction > 0) { if (S.Compare(Step, From.Zero) >= 0) { throw new ScriptRuntimeException("Invalid step size for corresponding range.", this); } } } else { if (Direction <= 0) { Step = From.One; } else { Step = From.One.Negate(); } } LinkedList <IElement> Elements = new LinkedList <IElement>(); do { Variables[this.variableName] = From; Elements.AddLast(this.right.Evaluate(Variables)); if (Direction == 0) { Done = true; } else { From = Operators.Arithmetics.Add.EvaluateAddition(From, Step, this) as ICommutativeRingWithIdentityElement; if (From == null) { throw new ScriptRuntimeException("Invalid step size.", this); } if (Direction > 0) { Done = S.Compare(From, To) < 0; } else { Done = S.Compare(From, To) > 0; } } }while (!Done); return(this.Encapsulate(Elements)); }
/// <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)); } } } }