public static AddAssign ( |
||
left | An |
|
right | An |
|
리턴 |
protected override object VisitAssignment(Assignment A) { LinqExpr value = target.Compile(A.Value); switch (A.Operator) { case Operator.Add: target.Add(LinqExpr.AddAssign(target.LookUp(A.Assign), value)); break; case Operator.Subtract: target.Add(LinqExpr.SubtractAssign(target.LookUp(A.Assign), value)); break; case Operator.Multiply: target.Add(LinqExpr.MultiplyAssign(target.LookUp(A.Assign), value)); break; case Operator.Divide: target.Add(LinqExpr.DivideAssign(target.LookUp(A.Assign), value)); break; case Operator.Power: target.Add(LinqExpr.PowerAssign(target.LookUp(A.Assign), value)); break; case Operator.And: target.Add(LinqExpr.AndAssign(target.LookUp(A.Assign), value)); break; case Operator.Or: target.Add(LinqExpr.OrAssign(target.LookUp(A.Assign), value)); break; case Operator.Equal: LinqExpr x = target.LookUp(A.Assign); if (x == null) { x = target.DeclInit(A.Assign, A.Value); } target.Add(LinqExpr.Assign(x, value)); break; default: throw new NotImplementedException("Operator not implemented for assignment."); } return(null); }
// Pseudocode: //string input => //{ // R result = 0; // for (int i = input.Length - 1; i >= 0; i--) // { // result <<= 6; // var m = _invMap[input[i]]; // if (m == 0xff) // return default(ConversionResult<R>); // result += m; // } // return new ConversionResult<R>(result); //} private LambdaExpression fromLambda(Type to) { var stringthis = typeof(string).GetTypeInfo().DeclaredProperties.First(p => p.GetIndexParameters().Length == 1 && p.GetIndexParameters()[0].ParameterType == typeof(int)); var input = Ex.Parameter(typeof(string), "input"); var result = Ex.Parameter(to, "result"); var i = Ex.Parameter(typeof(int), "i"); var m = Ex.Parameter(typeof(byte), "m"); var loopstart = Ex.Label("loopstart"); var end = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to), "end"); var loop = Ex.Block( Ex.Label(loopstart), Ex.IfThen(Ex.MakeBinary(ExpressionType.LessThan, i, Ex.Constant(0)), Ex.Goto(end, Result(to, result))), Ex.LeftShiftAssign(result, Ex.Constant(6)), Ex.Assign(m, Ex.ArrayIndex(Ex.Constant(_invMap), Ex.Convert(Ex.MakeIndex(input, stringthis, new[] { i }), typeof(int)))), Ex.IfThen(Ex.MakeBinary(ExpressionType.Equal, m, Ex.Constant((byte)0xff)), Ex.Goto(end, NoResult(to))), Ex.AddAssign(result, Ex.Convert(m, result.Type)), Ex.PostDecrementAssign(i), Ex.Goto(loopstart)); var block = Ex.Block(new[] { result, i, m }, Ex.Assign(result, Ex.Convert(Ex.Constant(0), to)), Ex.Assign(i, Ex.MakeBinary(ExpressionType.Subtract, Ex.Property(input, nameof(string.Length)), Ex.Constant(1))), loop, Ex.Label(end, NoResult(to))); return(Ex.Lambda(block, input)); }
private static Func <int[], int[]> GenerateCopyExpression() { var ctor = typeof(int[]).GetConstructor(new[] { typeof(int) }); var get = typeof(int[]).GetMethod("Get", new[] { typeof(int) }); var set = typeof(int[]).GetMethod("Set", new[] { typeof(int), typeof(int) }); var p1 = Exp.Parameter(typeof(int[])); var v1 = Exp.Variable(typeof(int[])); var v2 = Exp.Variable(typeof(int)); var @break = Exp.Label(); var block = Exp.Block( new[] { v1, v2 }, Exp.Assign(v1, Exp.New(ctor, Exp.Property(p1, "Length"))), Exp.Assign(v2, Exp.Constant(0)), Exp.Loop( Exp.IfThenElse( Exp.LessThan(v2, Exp.Property(p1, "Length")), Exp.Block( Exp.Call(v1, set, v2, Exp.Call(p1, get, v2)), Exp.AddAssign(v2, Exp.Constant(1)) ), Exp.Break(@break) ), @break), v1 ); return(Exp.Lambda <Func <int[], int[]> >(block, new ParameterExpression[] { p1 }).Compile()); }
private BinaryExpression BinaryExpression( ExpressionType nodeType, System.Type type, JObject obj) { var left = this.Prop(obj, "left", this.Expression); var right = this.Prop(obj, "right", this.Expression); var method = this.Prop(obj, "method", this.Method); var conversion = this.Prop(obj, "conversion", this.LambdaExpression); var liftToNull = this.Prop(obj, "liftToNull").Value <bool>(); switch (nodeType) { case ExpressionType.Add: return(Expr.Add(left, right, method)); case ExpressionType.AddAssign: return(Expr.AddAssign(left, right, method, conversion)); case ExpressionType.AddAssignChecked: return(Expr.AddAssignChecked(left, right, method, conversion)); case ExpressionType.AddChecked: return(Expr.AddChecked(left, right, method)); case ExpressionType.And: return(Expr.And(left, right, method)); case ExpressionType.AndAlso: return(Expr.AndAlso(left, right, method)); case ExpressionType.AndAssign: return(Expr.AndAssign(left, right, method, conversion)); case ExpressionType.ArrayIndex: return(Expr.ArrayIndex(left, right)); case ExpressionType.Assign: return(Expr.Assign(left, right)); case ExpressionType.Coalesce: return(Expr.Coalesce(left, right, conversion)); case ExpressionType.Divide: return(Expr.Divide(left, right, method)); case ExpressionType.DivideAssign: return(Expr.DivideAssign(left, right, method, conversion)); case ExpressionType.Equal: return(Expr.Equal(left, right, liftToNull, method)); case ExpressionType.ExclusiveOr: return(Expr.ExclusiveOr(left, right, method)); case ExpressionType.ExclusiveOrAssign: return(Expr.ExclusiveOrAssign(left, right, method, conversion)); case ExpressionType.GreaterThan: return(Expr.GreaterThan(left, right, liftToNull, method)); case ExpressionType.GreaterThanOrEqual: return(Expr.GreaterThanOrEqual(left, right, liftToNull, method)); case ExpressionType.LeftShift: return(Expr.LeftShift(left, right, method)); case ExpressionType.LeftShiftAssign: return(Expr.LeftShiftAssign(left, right, method, conversion)); case ExpressionType.LessThan: return(Expr.LessThan(left, right, liftToNull, method)); case ExpressionType.LessThanOrEqual: return(Expr.LessThanOrEqual(left, right, liftToNull, method)); case ExpressionType.Modulo: return(Expr.Modulo(left, right, method)); case ExpressionType.ModuloAssign: return(Expr.ModuloAssign(left, right, method, conversion)); case ExpressionType.Multiply: return(Expr.Multiply(left, right, method)); case ExpressionType.MultiplyAssign: return(Expr.MultiplyAssign(left, right, method, conversion)); case ExpressionType.MultiplyAssignChecked: return(Expr.MultiplyAssignChecked(left, right, method, conversion)); case ExpressionType.MultiplyChecked: return(Expr.MultiplyChecked(left, right, method)); case ExpressionType.NotEqual: return(Expr.NotEqual(left, right, liftToNull, method)); case ExpressionType.Or: return(Expr.Or(left, right, method)); case ExpressionType.OrAssign: return(Expr.OrAssign(left, right, method, conversion)); case ExpressionType.OrElse: return(Expr.OrElse(left, right, method)); case ExpressionType.Power: return(Expr.Power(left, right, method)); case ExpressionType.PowerAssign: return(Expr.PowerAssign(left, right, method, conversion)); case ExpressionType.RightShift: return(Expr.RightShift(left, right, method)); case ExpressionType.RightShiftAssign: return(Expr.RightShiftAssign(left, right, method, conversion)); case ExpressionType.Subtract: return(Expr.Subtract(left, right, method)); case ExpressionType.SubtractAssign: return(Expr.SubtractAssign(left, right, method, conversion)); case ExpressionType.SubtractAssignChecked: return(Expr.SubtractAssignChecked(left, right, method, conversion)); case ExpressionType.SubtractChecked: return(Expr.SubtractChecked(left, right, method)); default: throw new NotSupportedException(); } }
// Use homotopy method with newton's method to find a solution for F(x) = 0. private static List <Arrow> NSolve(List <Expression> F, List <Arrow> x0, double Epsilon, int MaxIterations) { int M = F.Count; int N = x0.Count; // Compute JxF, the Jacobian of F. List <Dictionary <Expression, Expression> > JxF = Jacobian(F, x0.Select(i => i.Left)).ToList(); // Define a function to evaluate JxH(x), where H = F(x) - s*F(x0). CodeGen code = new CodeGen(); ParamExpr _JxH = code.Decl <double[, ]>(Scope.Parameter, "JxH"); ParamExpr _x0 = code.Decl <double[]>(Scope.Parameter, "x0"); ParamExpr _s = code.Decl <double>(Scope.Parameter, "s"); // Load x_j from the input array and add them to the map. for (int j = 0; j < N; ++j) { code.DeclInit(x0[j].Left, LinqExpr.ArrayAccess(_x0, LinqExpr.Constant(j))); } LinqExpr error = code.Decl <double>("error"); // Compile the expressions to assign JxH for (int i = 0; i < M; ++i) { LinqExpr _i = LinqExpr.Constant(i); for (int j = 0; j < N; ++j) { code.Add(LinqExpr.Assign( LinqExpr.ArrayAccess(_JxH, _i, LinqExpr.Constant(j)), code.Compile(JxF[i][x0[j].Left]))); } // e = F(x) - s*F(x0) LinqExpr e = code.DeclInit <double>("e", LinqExpr.Subtract(code.Compile(F[i]), LinqExpr.Multiply(LinqExpr.Constant((double)F[i].Evaluate(x0)), _s))); code.Add(LinqExpr.Assign(LinqExpr.ArrayAccess(_JxH, _i, LinqExpr.Constant(N)), e)); // error += e * e code.Add(LinqExpr.AddAssign(error, LinqExpr.Multiply(e, e))); } // return error code.Return(error); Func <double[, ], double[], double, double> JxH = code.Build <Func <double[, ], double[], double, double> >().Compile(); double[] x = new double[N]; // Remember where we last succeeded/failed. double s0 = 0.0; double s1 = 1.0; do { try { // H(F, s) = F - s*F0 NewtonsMethod(M, N, JxH, s0, x, Epsilon, MaxIterations); // Success at this s! s1 = s0; for (int i = 0; i < N; ++i) { x0[i] = Arrow.New(x0[i].Left, x[i]); } // Go near the goal. s0 = Lerp(s0, 0.0, 0.9); } catch (FailedToConvergeException) { // Go near the last success. s0 = Lerp(s0, s1, 0.9); for (int i = 0; i < N; ++i) { x[i] = (double)x0[i].Right; } } } while (s0 > 0.0 && s1 >= s0 + 1e-6); // Make sure the last solution is at F itself. if (s0 != 0.0) { NewtonsMethod(M, N, JxH, 0.0, x, Epsilon, MaxIterations); for (int i = 0; i < N; ++i) { x0[i] = Arrow.New(x0[i].Left, x[i]); } } return(x0); }
// The resulting lambda processes N samples, using buffers provided for Input and Output: // void Process(int N, double t0, double T, double[] Input0 ..., double[] Output0 ...) // { ... } private Delegate DefineProcess() { // Map expressions to identifiers in the syntax tree. List <KeyValuePair <Expression, LinqExpr> > inputs = new List <KeyValuePair <Expression, LinqExpr> >(); List <KeyValuePair <Expression, LinqExpr> > outputs = new List <KeyValuePair <Expression, LinqExpr> >(); // Lambda code generator. CodeGen code = new CodeGen(); // Create parameters for the basic simulation info (N, t, Iterations). ParamExpr SampleCount = code.Decl <int>(Scope.Parameter, "SampleCount"); ParamExpr t = code.Decl(Scope.Parameter, Simulation.t); // Create buffer parameters for each input... foreach (Expression i in Input) { inputs.Add(new KeyValuePair <Expression, LinqExpr>(i, code.Decl <double[]>(Scope.Parameter, i.ToString()))); } // ... and output. foreach (Expression i in Output) { outputs.Add(new KeyValuePair <Expression, LinqExpr>(i, code.Decl <double[]>(Scope.Parameter, i.ToString()))); } // Create globals to store previous values of inputs. foreach (Expression i in Input.Distinct()) { AddGlobal(i.Evaluate(t_t0)); } // Define lambda body. // int Zero = 0 LinqExpr Zero = LinqExpr.Constant(0); // double h = T / Oversample LinqExpr h = LinqExpr.Constant(TimeStep / (double)Oversample); // Load the globals to local variables and add them to the map. foreach (KeyValuePair <Expression, GlobalExpr <double> > i in globals) { code.Add(LinqExpr.Assign(code.Decl(i.Key), i.Value)); } foreach (KeyValuePair <Expression, LinqExpr> i in inputs) { code.Add(LinqExpr.Assign(code.Decl(i.Key), code[i.Key.Evaluate(t_t0)])); } // Create arrays for linear systems. int M = Solution.Solutions.OfType <NewtonIteration>().Max(i => i.Equations.Count(), 0); int N = Solution.Solutions.OfType <NewtonIteration>().Max(i => i.UnknownDeltas.Count(), 0) + 1; LinqExpr JxF = code.DeclInit <double[][]>("JxF", LinqExpr.NewArrayBounds(typeof(double[]), LinqExpr.Constant(M))); for (int j = 0; j < M; ++j) { code.Add(LinqExpr.Assign(LinqExpr.ArrayAccess(JxF, LinqExpr.Constant(j)), LinqExpr.NewArrayBounds(typeof(double), LinqExpr.Constant(N)))); } // for (int n = 0; n < SampleCount; ++n) ParamExpr n = code.Decl <int>("n"); code.For( () => code.Add(LinqExpr.Assign(n, Zero)), LinqExpr.LessThan(n, SampleCount), () => code.Add(LinqExpr.PreIncrementAssign(n)), () => { // Prepare input samples for oversampling interpolation. Dictionary <Expression, LinqExpr> dVi = new Dictionary <Expression, LinqExpr>(); foreach (Expression i in Input.Distinct()) { LinqExpr Va = code[i]; // Sum all inputs with this key. IEnumerable <LinqExpr> Vbs = inputs.Where(j => j.Key.Equals(i)).Select(j => j.Value); LinqExpr Vb = LinqExpr.ArrayAccess(Vbs.First(), n); foreach (LinqExpr j in Vbs.Skip(1)) { Vb = LinqExpr.Add(Vb, LinqExpr.ArrayAccess(j, n)); } // dVi = (Vb - Va) / Oversample code.Add(LinqExpr.Assign( Decl <double>(code, dVi, i, "d" + i.ToString().Replace("[t]", "")), LinqExpr.Multiply(LinqExpr.Subtract(Vb, Va), LinqExpr.Constant(1.0 / (double)Oversample)))); } // Prepare output sample accumulators for low pass filtering. Dictionary <Expression, LinqExpr> Vo = new Dictionary <Expression, LinqExpr>(); foreach (Expression i in Output.Distinct()) { code.Add(LinqExpr.Assign( Decl <double>(code, Vo, i, i.ToString().Replace("[t]", "")), LinqExpr.Constant(0.0))); } // int ov = Oversample; // do { -- ov; } while(ov > 0) ParamExpr ov = code.Decl <int>("ov"); code.Add(LinqExpr.Assign(ov, LinqExpr.Constant(Oversample))); code.DoWhile(() => { // t += h code.Add(LinqExpr.AddAssign(t, h)); // Interpolate the input samples. foreach (Expression i in Input.Distinct()) { code.Add(LinqExpr.AddAssign(code[i], dVi[i])); } // Compile all of the SolutionSets in the solution. foreach (SolutionSet ss in Solution.Solutions) { if (ss is LinearSolutions) { // Linear solutions are easy. LinearSolutions S = (LinearSolutions)ss; foreach (Arrow i in S.Solutions) { code.DeclInit(i.Left, i.Right); } } else if (ss is NewtonIteration) { NewtonIteration S = (NewtonIteration)ss; // Start with the initial guesses from the solution. foreach (Arrow i in S.Guesses) { code.DeclInit(i.Left, i.Right); } // int it = iterations LinqExpr it = code.ReDeclInit <int>("it", Iterations); // do { ... --it } while(it > 0) code.DoWhile((Break) => { // Solve the un-solved system. Solve(code, JxF, S.Equations, S.UnknownDeltas); // Compile the pre-solved solutions. if (S.KnownDeltas != null) { foreach (Arrow i in S.KnownDeltas) { code.DeclInit(i.Left, i.Right); } } // bool done = true LinqExpr done = code.ReDeclInit("done", true); foreach (Expression i in S.Unknowns) { LinqExpr v = code[i]; LinqExpr dv = code[NewtonIteration.Delta(i)]; // done &= (|dv| < |v|*epsilon) code.Add(LinqExpr.AndAssign(done, LinqExpr.LessThan(LinqExpr.Multiply(Abs(dv), LinqExpr.Constant(1e4)), LinqExpr.Add(Abs(v), LinqExpr.Constant(1e-6))))); // v += dv code.Add(LinqExpr.AddAssign(v, dv)); } // if (done) break code.Add(LinqExpr.IfThen(done, Break)); // --it; code.Add(LinqExpr.PreDecrementAssign(it)); }, LinqExpr.GreaterThan(it, Zero)); //// bool failed = false //LinqExpr failed = Decl(code, code, "failed", LinqExpr.Constant(false)); //for (int i = 0; i < eqs.Length; ++i) // // failed |= |JxFi| > epsilon // code.Add(LinqExpr.OrAssign(failed, LinqExpr.GreaterThan(Abs(eqs[i].ToExpression().Compile(map)), LinqExpr.Constant(1e-3)))); //code.Add(LinqExpr.IfThen(failed, ThrowSimulationDiverged(n))); } } // Update the previous timestep variables. foreach (SolutionSet S in Solution.Solutions) { foreach (Expression i in S.Unknowns.Where(i => globals.Keys.Contains(i.Evaluate(t_t0)))) { code.Add(LinqExpr.Assign(code[i.Evaluate(t_t0)], code[i])); } } // Vo += i foreach (Expression i in Output.Distinct()) { LinqExpr Voi = LinqExpr.Constant(0.0); try { Voi = code.Compile(i); } catch (Exception Ex) { Log.WriteLine(MessageType.Warning, Ex.Message); } code.Add(LinqExpr.AddAssign(Vo[i], Voi)); } // Vi_t0 = Vi foreach (Expression i in Input.Distinct()) { code.Add(LinqExpr.Assign(code[i.Evaluate(t_t0)], code[i])); } // --ov; code.Add(LinqExpr.PreDecrementAssign(ov)); }, LinqExpr.GreaterThan(ov, Zero)); // Output[i][n] = Vo / Oversample foreach (KeyValuePair <Expression, LinqExpr> i in outputs) { code.Add(LinqExpr.Assign(LinqExpr.ArrayAccess(i.Value, n), LinqExpr.Multiply(Vo[i.Key], LinqExpr.Constant(1.0 / (double)Oversample)))); } // Every 256 samples, check for divergence. if (Vo.Any()) { code.Add(LinqExpr.IfThen(LinqExpr.Equal(LinqExpr.And(n, LinqExpr.Constant(0xFF)), Zero), LinqExpr.Block(Vo.Select(i => LinqExpr.IfThenElse(IsNotReal(i.Value), ThrowSimulationDiverged(n), LinqExpr.Assign(i.Value, RoundDenormToZero(i.Value))))))); } }); // Copy the global state variables back to the globals. foreach (KeyValuePair <Expression, GlobalExpr <double> > i in globals) { code.Add(LinqExpr.Assign(i.Value, code[i.Key])); } LinqExprs.LambdaExpression lambda = code.Build(); Delegate ret = lambda.Compile(); return(ret); }
public void BinaryExpression_AddAssign() => UnsupportedBinaryExpr(Property.Id, id => Expr.AddAssign(id, Expr.Constant(3)), ExpressionType.AddAssign);