/// <summary> /// Combines two graphs using the operator of this binary expression /// </summary> /// <param name="leftGraph"></param> /// <param name="rightGraph"></param> /// <returns></returns> private Functions.Graph combineGraph(Functions.Graph leftGraph, Functions.Graph rightGraph) { Functions.Graph retVal = null; switch (Operation) { case BinaryExpression.OPERATOR.ADD: retVal = leftGraph.AddGraph(rightGraph); break; case BinaryExpression.OPERATOR.SUB: retVal = leftGraph.SubstractGraph(rightGraph); break; case BinaryExpression.OPERATOR.MULT: retVal = leftGraph.MultGraph(rightGraph); break; case BinaryExpression.OPERATOR.DIV: retVal = leftGraph.DivGraph(rightGraph); break; } return(retVal); }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public override Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); if (Term != null) { retVal = Functions.Graph.createGraph(GetValue(context), parameter); } else if (Expression != null) { if (UnaryOp == null) { retVal = Expression.createGraph(context, parameter); } else if (UnaryOp == MINUS) { retVal = Expression.createGraph(context, parameter); retVal.Negate(); } else { throw new Exception("Cannot create graph where NOT operator is defined"); } } return(retVal); }
/// <summary> /// Creates the result as a surface /// </summary> /// <param name="context"></param> /// <param name="leftFunction"></param> /// <param name="unboundLeft"></param> /// <param name="rightFunction"></param> /// <param name="unboundRight"></param> /// <returns></returns> private ICallable createGraphResult(InterpretationContext context, Functions.Function leftFunction, List <Parameter> unboundLeft, Functions.Function rightFunction, List <Parameter> unboundRight) { ICallable retVal = null; Functions.Graph leftGraph = createGraphForUnbound(context, Left, leftFunction, unboundLeft); if (leftGraph != null) { Functions.Graph rightGraph = createGraphForUnbound(context, Right, rightFunction, unboundRight); if (rightGraph != null) { retVal = combineGraph(leftGraph, rightGraph).Function; } else { AddError("Cannot create graph for " + Right); } } else { AddError("Cannot create graph for " + Left); } return(retVal); }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public override Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); Functions.PredefinedFunctions.Cast cast = Called.Ref as Functions.PredefinedFunctions.Cast; if (cast != null) { // In case of cast, just take the graph of the enclosed expression Parameter param = (Parameter)cast.FormalParameters[0]; retVal = cast.createGraphForParameter(context, param); } Function calledFunction = Called.Ref as Function; Dictionary <Parameter, Expression> parameterAssociation = null; if (calledFunction == null) { calledFunction = Called.GetValue(context) as Function; parameterAssociation = createParameterAssociation(calledFunction); } else { parameterAssociation = ParameterAssociation; } Parameter Xaxis = null; foreach (KeyValuePair <Parameter, Expression> pair in parameterAssociation) { if (pair.Value.Ref == parameter) { if (Xaxis == null) { Xaxis = pair.Key; } else { Root.AddError("Cannot evaluate graph for function call " + ToString() + " which has more than 1 parameter used as X axis"); Xaxis = null; break; } } } int token = context.LocalScope.PushContext(); calledFunction.AssignParameters(context, AssignParameterValues(context, calledFunction, false)); if (Xaxis != null) { retVal = calledFunction.createGraphForParameter(context, Xaxis); } else { retVal = Function.createGraphForValue(GetValue(context)); } context.LocalScope.PopContext(token); return(retVal); }
/// <summary> /// Provides the graph of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the graph</param> /// <returns></returns> public override Functions.Graph createGraph(Interpreter.InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); retVal = Functions.Graph.createGraph(GetValue(context), parameter); return(retVal); }
/// <summary> /// Creates a graph for a single constant value /// </summary> /// <param name="retVal"></param> /// <param name="value"></param> /// <returns></returns> public static Graph createGraph(double value, Parameter parameter = null) { Graph retVal = new Functions.Graph(); Functions.Graph.Segment segment = new Functions.Graph.Segment(0, double.MaxValue, new Segment.Curve()); segment.Expression.v0 = value; retVal.addSegment(segment); return(retVal); }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public override Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); retVal = Functions.Graph.createGraph(GetValue(context), parameter); if (retVal == null) { throw new Exception("Cannot create graph for " + ToString()); } return(retVal); }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public override Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); if (parameter == Parameters[0] || parameter == Parameters[1]) { retVal = Expression.createGraph(context, parameter); } else { throw new Exception("Cannot create graph for parameter " + parameter.Name); } return(retVal); }
/// <summary> /// Provides the callable that is called by this expression /// </summary> /// <param name="namable"></param> /// <returns></returns> public override ICallable getCalled(InterpretationContext context) { ICallable retVal = null; Functions.Function function = InitialValue.Ref as Functions.Function; if (function == null) { function = InitialValue.getCalled(context) as Functions.Function; } if (function != null) { if (function.FormalParameters.Count == 1) { int token = context.LocalScope.PushContext(); context.LocalScope.setGraphParameter((Parameter)function.FormalParameters[0]); Functions.Graph graph = createGraph(context, (Parameter)function.FormalParameters[0]); context.LocalScope.PopContext(token); if (graph != null) { retVal = graph.Function; } } else if (function.FormalParameters.Count == 2) { int token = context.LocalScope.PushContext(); context.LocalScope.setSurfaceParameters((Parameter)function.FormalParameters[0], (Parameter)function.FormalParameters[1]); Functions.Surface surface = createSurface(context, (Parameter)function.FormalParameters[0], (Parameter)function.FormalParameters[1]); context.LocalScope.PopContext(token); if (surface != null) { retVal = surface.Function; } } else { AddError("Cannot evaluate REDUCE expression to a function"); } } else { AddError("Cannot evaluate REDUCE expression to a function"); } return(retVal); }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public override Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); Graph leftGraph = Left.createGraph(context, parameter); if (leftGraph != null) { Graph rightGraph = Right.createGraph(context, parameter); if (rightGraph != null) { retVal = combineGraph(leftGraph, rightGraph); } } return(retVal); }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public override Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = base.createGraph(context, parameter); Functions.Graph graph = InitialValue.createGraph(context, parameter); if (graph != null) { Values.ListValue value = ListExpression.GetValue(context) as Values.ListValue; if (value != null) { int token = PrepareIteration(context); AccumulatorVariable.Value = graph.Function; foreach (Values.IValue v in value.Val) { if (v != EFSSystem.EmptyValue) { IteratorVariable.Value = v; if (conditionSatisfied(context)) { AccumulatorVariable.Value = IteratorExpression.GetValue(context); } } NextIteration(); } Functions.Function function = AccumulatorVariable.Value as Functions.Function; if (function != null) { retVal = function.Graph; } else { retVal = Functions.Function.createGraphForValue(AccumulatorVariable.Value); } EndIteration(context, token); } } else { throw new Exception("Cannot create graph for initial value " + InitialValue.ToString()); } return(retVal); }
/// <summary> /// Provides the double value from the IValue provided /// </summary> /// <param name="val"></param> /// <returns></returns> private double getValue(Values.IValue val) { double retVal = 0; Constants.EnumValue enumValue = val as Constants.EnumValue; if (enumValue != null) { val = enumValue.Value; } Values.DoubleValue vd = val as Values.DoubleValue; if (vd != null) { retVal = vd.Val; } else { Values.IntValue vi = val as Values.IntValue; if (vi != null) { retVal = (double)vi.Val; } else { Functions.Function function = val as Functions.Function; if (function != null) { Functions.Graph graph = function.Graph; if (graph != null) { if (graph.Segments.Count == 1) { retVal = graph.Val(0); } } } } } return(retVal); }
/// <summary> /// Provides the value associated to this Expression /// </summary> /// <param name="context">The context on which the value must be found</param> /// <returns></returns> public override Values.IValue GetValue(InterpretationContext context) { Values.IValue retVal = null; try { if (Parameters.Count == 1) { int token = context.LocalScope.PushContext(); context.LocalScope.setGraphParameter(Parameters[0]); Functions.Graph graph = createGraph(context, Parameters[0]); context.LocalScope.PopContext(token); if (graph != null) { retVal = graph.Function; } } else if (Parameters.Count == 2) { int token = context.LocalScope.PushContext(); context.LocalScope.setSurfaceParameters(Parameters[0], Parameters[1]); Functions.Surface surface = createSurface(context, Parameters[0], Parameters[1]); context.LocalScope.PopContext(token); if (surface != null) { retVal = surface.Function; } } } catch (Exception) { /// TODO Ugly hack, because functions & function types are merged. /// This provides an empty function as the type of this retVal = GetExpressionType() as Values.IValue; } return(retVal); }
/// <summary> /// Creates the graph associated to this expression, when the given parameter ranges over the X axis /// </summary> /// <param name="context">The interpretation context</param> /// <param name="parameter">The parameters of *the enclosing function* for which the graph should be created</param> /// <returns></returns> public virtual Functions.Graph createGraph(InterpretationContext context, Parameter parameter) { Functions.Graph retVal = null; return(retVal); }
/// <summary> /// Performs the arithmetic operation based on the type of the result /// </summary> /// <param name="context">The context used to perform this operation</param> /// <param name="left"></param> /// <param name="Operation"></param> /// <param name="right"></param> /// <returns></returns> public virtual Values.IValue PerformArithmericOperation(Interpreter.InterpretationContext context, Values.IValue left, BinaryExpression.OPERATOR Operation, Values.IValue right) // left +/-/*/div/exp right { Values.IValue retVal = null; Functions.Function leftFunction = left as Functions.Function; Functions.Function rigthFunction = right as Functions.Function; if (rigthFunction == null) { if (leftFunction.Graph != null) { Functions.Graph graph = Functions.Graph.createGraph(Functions.Function.getDoubleValue(right)); rigthFunction = graph.Function; } else { Functions.Surface surface = Functions.Surface.createSurface(Functions.Function.getDoubleValue(right), leftFunction.Surface.XParameter, leftFunction.Surface.YParameter); rigthFunction = surface.Function; } } if (leftFunction.Graph != null) { Functions.Graph tmp = null; switch (Operation) { case BinaryExpression.OPERATOR.ADD: tmp = leftFunction.Graph.AddGraph(rigthFunction.Graph); break; case BinaryExpression.OPERATOR.SUB: tmp = leftFunction.Graph.SubstractGraph(rigthFunction.Graph); break; case BinaryExpression.OPERATOR.MULT: tmp = leftFunction.Graph.MultGraph(rigthFunction.Graph); break; case BinaryExpression.OPERATOR.DIV: tmp = leftFunction.Graph.DivGraph(rigthFunction.Graph); break; } retVal = tmp.Function; } else { Functions.Surface rightSurface = rigthFunction.getSurface(leftFunction.Surface.XParameter, leftFunction.Surface.YParameter); Functions.Surface tmp = null; switch (Operation) { case BinaryExpression.OPERATOR.ADD: tmp = leftFunction.Surface.AddSurface(rightSurface); break; case BinaryExpression.OPERATOR.SUB: tmp = leftFunction.Surface.SubstractSurface(rightSurface); break; case BinaryExpression.OPERATOR.MULT: tmp = leftFunction.Surface.MultiplySurface(rightSurface); break; case BinaryExpression.OPERATOR.DIV: tmp = leftFunction.Surface.DivideSurface(rightSurface); break; } retVal = tmp.Function; } return(retVal); }
/// <summary> /// Provides the surface of this function if it has been statically defined /// </summary> /// <param name="context">the context used to create the graph</param> /// <param name="Xparameter">The parameter used for the X axis</param> /// <param name="Yparameter">The parameter used for the Y axis</param> /// <returns></returns> public virtual Surface createSurfaceForParameters(Interpreter.InterpretationContext context, Parameter Xparameter, Parameter Yparameter) { Surface retVal = Surface; if (retVal == null) { if (Xparameter != null) { if (Yparameter != null) { if (Cases.Count > 0) { retVal = new Surface(Xparameter, Yparameter); foreach (Case cas in Cases) { if (PreconditionSatisfied(context, cas, Xparameter, Yparameter)) { Surface surface = cas.Expression.createSurface(context, Xparameter, Yparameter); if (surface != null) { Parameter parameter = null; surface = ReduceSurface(context, cas, surface, out parameter); if (parameter == null || parameter == surface.XParameter) { retVal.MergeX(surface); } else { retVal = Surface.MergeY(retVal, surface); } } else { AddError("Cannot create surface for expression " + cas.ExpressionText); retVal = null; break; } } } } else if (Graph != null) { // The function is defined by a graph // Extend it to a surface // TODO: Check the right parameter retVal = Graph.ToSurfaceX(); retVal.XParameter = Xparameter; retVal.YParameter = Yparameter; } else { AddError("cannot create surface for function " + Name + " with given parameters"); } } else { // Function with 1 parameter that ranges over the Xaxis retVal = new Surface(Xparameter, Yparameter); Functions.Graph graph = createGraphForParameter(context, Xparameter); foreach (Graph.Segment segment in graph.Segments) { Graph newGraph = Graph.createGraph(segment.Expression.v0); Surface.Segment newSegment = new Surface.Segment(segment.Start, segment.End, newGraph); retVal.AddSegment(newSegment); } } } else if (Yparameter != null) { // TODO : Remove check code if ((Yparameter.Enclosing != this)) { System.Diagnostics.Debugger.Break(); } // Function with 1 parameter that ranges over the Yaxis retVal = new Surface(Xparameter, Yparameter); Graph graph = createGraphForParameter(context, Yparameter); Surface.Segment segment = new Functions.Surface.Segment(0, double.MaxValue, graph); retVal.AddSegment(segment); } else { AddError("Invalid parameters for surface creation"); } } retVal.XParameter = Xparameter; retVal.YParameter = Yparameter; return(retVal); }
/// <summary> /// Provides the value associated to this Expression /// </summary> /// <param name="context">The context on which the value must be found</param> /// <returns></returns> public override Values.IValue GetValue(InterpretationContext context) { Values.IValue retVal = null; ExplanationPart previous = SetupExplanation(); Functions.Function function = getFunction(context); if (function != null) { long start = System.Environment.TickCount; Dictionary <Variables.Actual, Values.IValue> parameterValues = AssignParameterValues(context, function, true); List <Parameter> parameters = GetPlaceHolders(function, parameterValues); if (parameters == null) { retVal = function.Evaluate(context, parameterValues); if (retVal == null) { AddError("Call " + function.Name + " ( " + ParameterValues(parameterValues) + " ) returned nothing"); } } else if (parameters.Count == 1) // graph { int token = context.LocalScope.PushContext(); context.LocalScope.setGraphParameter(parameters[0]); Functions.Graph graph = function.createGraphForParameter(context, parameters[0]); context.LocalScope.PopContext(token); if (graph != null) { retVal = graph.Function; } else { AddError("Cannot create graph on Call " + function.Name + " ( " + ParameterValues(parameterValues) + " )"); } } else // surface { Functions.Surface surface = function.createSurfaceForParameters(context, parameters[0], parameters[1]); if (surface != null) { retVal = surface.Function; } else { AddError("Cannot create surface on Call " + function.Name + " ( " + ParameterValues(parameterValues) + " )"); } } long stop = System.Environment.TickCount; long span = (stop - start); function.ExecutionTimeInMilli += span; function.ExecutionCount += 1; if (explain) { CompleteExplanation(previous, function.Name + " ( " + ParameterValues(parameterValues) + " ) returned " + explainNamable(retVal) + "\n"); } } else { AddError("Cannot find function " + ToString()); } return(retVal); }