public override PrimitiveExpression Simplified(Grimoire grimoire, CalcTimer timer) { timer.ThrowIfTimedOut(); CalcFunction func; if (!grimoire.Functions.TryGetValue(FunctionName, out func)) { throw new SimplificationException( $"Unknown function '{FunctionName}'.", this ); } if (func.ArgumentCount != Arguments.Count) { string expectedArgCountString = (func.ArgumentCount == 1) ? $"{func.ArgumentCount} argument" : $"{func.ArgumentCount} arguments" ; throw new SimplificationException( $"Function '{FunctionName}' expects {expectedArgCountString}, got {Arguments.Count}.", this ); } ImmutableList <PrimitiveExpression> simplifiedArgs = Arguments .ConvertAll(arg => arg.Simplified(grimoire, timer)); timer.ThrowIfTimedOut(); PrimitiveExpression result; try { result = func.Call.Invoke(simplifiedArgs); } catch (OverflowException ex) { throw new SimplificationException(this, ex); } catch (DivideByZeroException ex) { throw new SimplificationException(this, ex); } catch (FunctionDomainException ex) { throw new SimplificationException(this, ex); } catch (TimeoutException ex) { throw new SimplificationException(this, ex); } return(result.Repositioned(Index, Length)); }
public CreateRegularGridProgressForm(CancellationTokenSource cancellationTokenSource, Progress helper = null) { this.cancellationTokenSource = cancellationTokenSource; InitializeComponent(); if (helper != null) { CalcProgressBar.Maximum = helper.MaxValue; CalcProgressBar.Style = ProgressBarStyle.Continuous; helper.ProgressChanged += SetProgress; } start = DateTimeOffset.Now; CalcTimer.Start(); }
public override PrimitiveExpression Simplified(Grimoire grimoire, CalcTimer timer) { timer.ThrowIfTimedOut(); PrimitiveExpression ret; if (!grimoire.Constants.TryGetValue(Name, out ret)) { throw new SimplificationException( $"Unknown constant '{Name}'.", this ); } return(ret.Repositioned(Index, Length)); }
public abstract PrimitiveExpression Simplified(Grimoire grimoire, CalcTimer timer);
public override PrimitiveExpression Simplified(Grimoire grimoire, CalcTimer timer) { // nothing to simplify return(this); }
public override PrimitiveExpression Simplified(Grimoire grimoire, CalcTimer timer) { timer.ThrowIfTimedOut(); PrimitiveExpression primLeft = LeftSide.Simplified(grimoire, timer); timer.ThrowIfTimedOut(); PrimitiveExpression primRight = RightSide.Simplified(grimoire, timer); timer.ThrowIfTimedOut(); // type check switch (Operation) { case Operation.BinaryAnd: case Operation.BinaryOr: case Operation.BinaryXor: if (primLeft.Type == PrimitiveType.Decimal || primRight.Type == PrimitiveType.Decimal) { throw new SimplificationException( "Cannot perform a bitwise operation on a floating-point number.", this ); } break; default: break; } try { // mixed types? coerce if (primLeft.Type == PrimitiveType.IntegerLong) { if (primRight.Type == PrimitiveType.IntegerBig) { // IntegerLong < IntegerBig primLeft = new PrimitiveExpression(primLeft.Index, primLeft.Length, new BigInteger(primLeft.LongValue)); } else if (primRight.Type == PrimitiveType.Decimal) { // IntegerLong < Decimal primLeft = new PrimitiveExpression(primLeft.Index, primLeft.Length, (decimal)primLeft.LongValue); } } else if (primLeft.Type == PrimitiveType.IntegerBig) { if (primRight.Type == PrimitiveType.IntegerLong) { // IntegerBig > IntegerLong primRight = new PrimitiveExpression(primRight.Index, primRight.Length, new BigInteger(primRight.LongValue)); } else if (primRight.Type == PrimitiveType.Decimal) { // IntegerBig < Decimal primLeft = new PrimitiveExpression(primLeft.Index, primLeft.Length, (decimal)primLeft.BigIntegerValue); } } else if (primLeft.Type == PrimitiveType.Decimal) { if (primRight.Type == PrimitiveType.IntegerLong) { // Decimal > IntegerLong primRight = new PrimitiveExpression(primRight.Index, primRight.Length, (decimal)primRight.LongValue); } else if (primRight.Type == PrimitiveType.IntegerBig) { // Decimal > IntegerBig primRight = new PrimitiveExpression(primRight.Index, primRight.Length, (decimal)primRight.BigIntegerValue); } } } catch (OverflowException ex) { throw new SimplificationException(this, ex); } catch (DivideByZeroException ex) { throw new SimplificationException(this, ex); } catch (FunctionDomainException ex) { throw new SimplificationException(this, ex); } catch (TimeoutException ex) { throw new SimplificationException(this, ex); } timer.ThrowIfTimedOut(); Debug.Assert(primLeft.Type == primRight.Type); int newIndex = primLeft.Index; int newLength = primRight.Index + primRight.Length - primLeft.Index; try { switch (Operation) { case Operation.Add: return(BinaryOp( newIndex, newLength, primLeft, primRight, (a, b) => checked (a + b), (a, b) => checked (a + b), (a, b) => checked (a + b) )); case Operation.Divide: return(new PrimitiveExpression( newIndex, newLength, checked (primLeft.ToDecimal() / primRight.ToDecimal()) )); case Operation.IntegralDivide: return(BinaryOp( newIndex, newLength, primLeft, primRight, (a, b) => checked (a / b), (a, b) => checked (a / b), (a, b) => Math.Truncate(checked (a / b)) )); case Operation.Multiply: return(BinaryOp( newIndex, newLength, primLeft, primRight, (a, b) => checked (a * b), (a, b) => checked (a * b), (a, b) => checked (a * b) )); case Operation.Power: if (primLeft.Type == PrimitiveType.IntegerLong) { return(Pow(newIndex, newLength, primLeft.LongValue, primRight.LongValue, timer)); } else if (primLeft.Type == PrimitiveType.IntegerBig) { return(Pow(newIndex, newLength, primLeft.BigIntegerValue, primRight.BigIntegerValue, timer)); } else if (primLeft.Type == PrimitiveType.Decimal) { return(Pow(newIndex, newLength, primLeft.DecimalValue, primRight.DecimalValue, timer)); } break; case Operation.Remainder: return(BinaryOp( newIndex, newLength, primLeft, primRight, (a, b) => checked (a % b), (a, b) => checked (a % b), (a, b) => checked (a % b) )); case Operation.Subtract: return(BinaryOp( newIndex, newLength, primLeft, primRight, (a, b) => checked (a - b), (a, b) => checked (a - b), (a, b) => checked (a - b) )); case Operation.BinaryAnd: return(BinaryOp( newIndex, newLength, primLeft, primRight, (a, b) => checked (a & b), (a, b) => checked (a & b), null )); case Operation.BinaryOr: return(BinaryOp( newIndex, newLength, primLeft, primRight, (a, b) => checked (a | b), (a, b) => checked (a | b), null )); case Operation.BinaryXor: return(BinaryOp( newIndex, newLength, primLeft, primRight, (a, b) => checked (a ^ b), (a, b) => checked (a ^ b), null )); } } catch (OverflowException ex) { throw new SimplificationException(this, ex); } catch (DivideByZeroException ex) { throw new SimplificationException(this, ex); } catch (FunctionDomainException ex) { throw new SimplificationException(this, ex); } catch (TimeoutException ex) { throw new SimplificationException(this, ex); } throw new SimplificationException($"Cannot handle binary operator {Operation}.", this); }
public PrimitiveExpression Pow(int index, int length, BigInteger baseBig, BigInteger exponentBig, CalcTimer timer) { if (baseBig.IsZero) { if (exponentBig.IsZero) { throw new SimplificationException("0**0 is undefined.", this); } else if (exponentBig < BigInteger.Zero) { throw new DivideByZeroException(); } } if (baseBig.IsOne) { return(new PrimitiveExpression(index, length, BigInteger.One)); } if (exponentBig.IsOne) { return(new PrimitiveExpression(index, length, baseBig)); } timer.ThrowIfTimedOut(); BigInteger actualExponent = BigInteger.Abs(exponentBig); BigInteger product = BigInteger.One; for (long i = 1; i < actualExponent; ++i) { timer.ThrowIfTimedOut(); checked { product *= baseBig; } } if (exponentBig.Sign < 0) { return(new PrimitiveExpression(index, length, 1.0m / ((decimal)product))); } return(new PrimitiveExpression(index, length, product)); }
public PrimitiveExpression Pow(int index, int length, long baseLong, long exponentLong, CalcTimer timer) { PrimitiveExpression pex = Pow(index, length, (BigInteger)baseLong, (BigInteger)exponentLong, timer); if ( pex.Type == PrimitiveType.IntegerBig && pex.BigIntegerValue >= long.MinValue && pex.BigIntegerValue <= long.MaxValue ) { // don't promote where unnecessary return(new PrimitiveExpression(index, length, (long)pex.BigIntegerValue)); } return(pex); }
public static PrimitiveExpression Pow(int index, int length, decimal baseDec, decimal exponentDec, CalcTimer timer) { // FIXME: find a smarter way? return(new PrimitiveExpression(index, length, (decimal)Math.Pow((double)baseDec, (double)exponentDec))); }
public override PrimitiveExpression Simplified(Grimoire grimoire, CalcTimer timer) { timer.ThrowIfTimedOut(); PrimitiveExpression primOperand = Operand.Simplified(grimoire, timer); try { switch (Operation) { case Operation.Negate: if (primOperand.Type == PrimitiveType.IntegerLong) { return(new PrimitiveExpression(Index, Length, -primOperand.LongValue)); } else if (primOperand.Type == PrimitiveType.IntegerBig) { return(new PrimitiveExpression(Index, Length, -primOperand.BigIntegerValue)); } else if (primOperand.Type == PrimitiveType.Decimal) { return(new PrimitiveExpression(Index, Length, -primOperand.DecimalValue)); } break; case Operation.Factorial: if (primOperand.Type == PrimitiveType.IntegerLong) { return(new PrimitiveExpression(Index, Length, MathFuncs.Factorial(primOperand.LongValue, timer))); } else if (primOperand.Type == PrimitiveType.IntegerBig) { return(new PrimitiveExpression(Index, Length, MathFuncs.Factorial(primOperand.BigIntegerValue, timer))); } else if (primOperand.Type == PrimitiveType.Decimal) { throw new FunctionDomainException("Factorials are not defined on fractional numbers."); } break; default: break; } } catch (OverflowException ex) { throw new SimplificationException(this, ex); } catch (DivideByZeroException ex) { throw new SimplificationException(this, ex); } catch (FunctionDomainException ex) { throw new SimplificationException(this, ex); } catch (TimeoutException ex) { throw new SimplificationException(this, ex); } throw new SimplificationException($"Cannot handle unary operator {Operation}.", this); }