public void ArrayAccess() { var expected = LinqExpression.ArrayAccess( LinqExpression.Parameter( typeof(int[])), LinqExpression.Parameter( typeof(int))); using var g = new GraphEngine.Graph(); g.LoadFromString(@" @prefix : <http://example.com/> . :s :arrayAccessArray [ :parameterType [ :typeName ""System.Int32[]"" ; ] ; ] ; :arrayAccessIndexes ( [ :parameterType [ :typeName ""System.Int32"" ; ] ; ] ) ; . "); var s = g.GetUriNode(":s"); var actual = Expression.Parse(s).LinqExpression; Console.WriteLine(actual.GetDebugView()); actual.Should().Be(expected); }
public LambdaExpression CreateLambda(Type from, Type to) { var toParameters = to.GetTypeInfo().GenericTypeArguments; var tupa = toParameters.Length; var input = Ex.Parameter(from, "input"); var converters = toParameters.Select(p => Ref.GetLambda(typeof(string), p)).ToArray(); var res = toParameters.Select(p => Ex.Parameter(typeof(ConversionResult <>).MakeGenericType(p))).ToArray(); var end = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to), "end"); var indexer = typeof(string[]).GetTypeInfo().GetDeclaredProperty("Item"); var split = Ex.Parameter(typeof(string[]), "split"); var conversion = Ex.Block(converters.Select((c, i) => Ex.Block( Ex.Assign(res[i], c.ApplyTo(Ex.MakeIndex(split, indexer, new[] { Ex.MakeBinary(Et.Add, Ex.Constant(i), Ex.MakeBinary(Et.Subtract, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa))) }))), Ex.IfThen(Ex.Not(Ex.Property(res[i], nameof(IConversionResult.IsSuccessful))), Ex.Goto(end, NoResult(to)))))); var block = Ex.Block(new[] { split }, Ex.Assign(split, Ex.Call(input, nameof(string.Split), Type.EmptyTypes, _separator)), Ex.Condition(Ex.MakeBinary(Et.LessThan, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa)), NoResult(to), Ex.Block(res, Ex.IfThen(Ex.MakeBinary(Et.GreaterThan, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa)), Ex.Assign(Ex.ArrayAccess(split, Ex.MakeBinary(Et.Subtract, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa))), Ex.Call(typeof(string), nameof(string.Join), Type.EmptyTypes, _separatorString, Ex.Call(typeof(Enumerable), nameof(Enumerable.Take), new[] { typeof(string) }, split, Ex.MakeBinary(Et.Add, Ex.Constant(1), Ex.MakeBinary(Et.Subtract, Ex.Property(split, nameof(Array.Length)), Ex.Constant(tupa))))))), conversion, Ex.Label(end, Result(to, Ex.Call(Creator(to), res.Select(r => Ex.Property(r, nameof(IConversionResult.Result))))))))); var lambda = Ex.Lambda(block, input); return(lambda); }
static Expression GetArgument(Expression Expression, int n) { if (Expression.Type == typeof(LuaArguments)) return Expression.Property(Expression, "Item", Expression.Constant(n)); else return Expression.ArrayAccess(Expression, Expression.Constant(n)); }
// Define a function for running the simulation of a population system S with timestep // dt. The number of timesteps and the data buffer are parameters of the defined function. static Func <int, double[, ], int> DefineSimulate(double dt, PopulationSystem S) { CodeGen code = new CodeGen(); // Define a parameter for the current population x, and define mappings to the // expressions defined above. LinqExpr N = code.Decl <int>(Scope.Parameter, "N"); LinqExpr Data = code.Decl <double[, ]>(Scope.Parameter, "Data"); // Loop over the sample range requested. Note that this loop is a 'runtime' loop, // while the rest of the loops nested in the body of this loop are 'compile time' loops. LinqExpr n = code.DeclInit <int>("n", 1); code.For( () => { }, LinqExpr.LessThan(n, N), () => code.Add(LinqExpr.PostIncrementAssign(n)), () => { // Define expressions representing the population of each species. List <Expression> x = new List <Expression>(); for (int i = 0; i < S.N; ++i) { // Define a variable xi. Expression xi = "x" + i.ToString(); x.Add(xi); // xi = Data[n, i]. code.DeclInit(xi, LinqExpr.ArrayAccess(Data, LinqExpr.Subtract(n, LinqExpr.Constant(1)), LinqExpr.Constant(i))); } for (int i = 0; i < S.N; ++i) { // This list is the elements of the sum representing the i'th // row of f, i.e. r_i + (A*x)_i. Expression dx_dt = 1; for (int j = 0; j < S.N; ++j) { dx_dt -= S.A[i, j] * x[j]; } // Define dx_i/dt = x_i * f_i(x), as per the Lotka-Volterra equations. dx_dt *= x[i] * S.r[i]; // Euler's method for x(t) is: x(t) = x(t - h) + h * x'(t - h). Expression integral = x[i] + dt * dx_dt; // Data[n, i] = Data[n - 1, i] + dt * dx_dt; code.Add(LinqExpr.Assign( LinqExpr.ArrayAccess(Data, n, LinqExpr.Constant(i)), code.Compile(integral))); } }); code.Return(N); // Compile the generated code. LinqExprs.Expression <Func <int, double[, ], int> > expr = code.Build <Func <int, double[, ], int> >(); return(expr.Compile()); }
Exp Call(Exp obj, string name, Exp arg0) { return(Exp.Call(obj, Callvirt, Exp.Constant(name), Exp.Block ( Exp.Assign(Exp.Field(arg1, "self"), obj), Exp.Assign(Exp.ArrayAccess(Exp.Field(arg1, "Input"), Exp.Constant(0)), arg0), arg1 ))); }
public void ArrayAccess() { var expression = LinqExpression.ArrayAccess( LinqExpression.Parameter( typeof(int[])), LinqExpression.Parameter( typeof(int))); ShouldRoundrip(expression); }
// Solve a system of linear equations private static void Solve(CodeGen code, LinqExpr Ab, IEnumerable <LinearCombination> Equations, IEnumerable <Expression> Unknowns) { LinearCombination[] eqs = Equations.ToArray(); Expression[] deltas = Unknowns.ToArray(); int M = eqs.Length; int N = deltas.Length; // Initialize the matrix. for (int i = 0; i < M; ++i) { LinqExpr Abi = code.ReDeclInit <double[]>("Abi", LinqExpr.ArrayAccess(Ab, LinqExpr.Constant(i))); for (int x = 0; x < N; ++x) { code.Add(LinqExpr.Assign( LinqExpr.ArrayAccess(Abi, LinqExpr.Constant(x)), code.Compile(eqs[i][deltas[x]]))); } code.Add(LinqExpr.Assign( LinqExpr.ArrayAccess(Abi, LinqExpr.Constant(N)), code.Compile(eqs[i][1]))); } // Gaussian elimination on this turd. //RowReduce(code, Ab, M, N); code.Add(LinqExpr.Call( GetMethod <Simulation>("RowReduce", Ab.Type, typeof(int), typeof(int)), Ab, LinqExpr.Constant(M), LinqExpr.Constant(N))); // Ab is now upper triangular, solve it. for (int j = N - 1; j >= 0; --j) { LinqExpr _j = LinqExpr.Constant(j); LinqExpr Abj = code.ReDeclInit <double[]>("Abj", LinqExpr.ArrayAccess(Ab, _j)); LinqExpr r = LinqExpr.ArrayAccess(Abj, LinqExpr.Constant(N)); for (int ji = j + 1; ji < N; ++ji) { r = LinqExpr.Add(r, LinqExpr.Multiply(LinqExpr.ArrayAccess(Abj, LinqExpr.Constant(ji)), code[deltas[ji]])); } code.DeclInit(deltas[j], LinqExpr.Divide(LinqExpr.Negate(r), LinqExpr.ArrayAccess(Abj, _j))); } }
// Pseudocode: //I input => //{ // var i = (UI)input; // var result = new char[base64sizeof(UI)]; // for (int j = 0; j == 0 || i > 0; j++) // { // result[j] = _mapChar[i & 0x3f]; // i >>= 6; // } //} private LambdaExpression toLambda(Type from) { var input = Ex.Parameter(from, "input"); var result = Ex.Parameter(typeof(char[]), "result"); var i = workingType(from) == from ? input : Ex.Parameter(workingType(from), "i"); var j = Ex.Parameter(typeof(int), "j"); var loopstart = Ex.Label("loopstart"); var loopend = Ex.Label("loopend"); var loop = Ex.Block( Ex.Label(loopstart), Ex.IfThen(Ex.MakeBinary(ExpressionType.AndAlso, Ex.MakeBinary(ExpressionType.GreaterThan, j, Ex.Constant(0)), i.Type == typeof(BigInteger) ? (Ex)Ex.Call(i, nameof(BigInteger.Equals), Type.EmptyTypes, Ex.Constant(BigInteger.Zero)) : Ex.MakeBinary(ExpressionType.Equal, i, Ex.Convert(Ex.Constant(0), i.Type))), Ex.Goto(loopend)), Ex.Assign( Ex.ArrayAccess(result, j), Ex.ArrayIndex(Ex.Constant(_mapChars), Ex.Convert(Ex.MakeBinary(ExpressionType.And, i, Ex.Convert(Ex.Constant(0x3f), i.Type)), typeof(int)))), Ex.RightShiftAssign(i, Ex.Constant(6)), Ex.PostIncrementAssign(j), Ex.Goto(loopstart)); var ret = Result(typeof(string), Ex.New(typeof(string).GetTypeInfo().DeclaredConstructors .Select(c => new { c, p = c.GetParameters() }) .First(c => c.p.Length == 3 && c.p[0].ParameterType == typeof(char[]) && c.p[1].ParameterType == typeof(int) && c.p[2].ParameterType == typeof(int)).c, result, Ex.Constant(0), j)); var block = Ex.Block(Ex.Assign(j, Ex.Constant(0)), Ex.Assign(result, Ex.NewArrayBounds(typeof(char), Ex.Constant(charbound(from)))), loop, Ex.Label(loopend), ret); block = input == i ? Ex.Block(new[] { j, result }, block) : Ex.Block(new[] { i, j, result }, Ex.Assign(i, Ex.Convert(input, i.Type)), block); return(Ex.Lambda(block, input)); }
public LambdaExpression CreateLambda(Type from, Type to) { var input = Ex.Parameter(from, "input"); var eType = to.GetElementType(); var res = Ex.Parameter(typeof(ConversionResult <>).MakeGenericType(eType).MakeArrayType(), "res"); var end = Ex.Label(typeof(ConversionResult <>).MakeGenericType(to), "end"); var fromParameters = from.GetTypeInfo().GenericTypeArguments; var converters = fromParameters.Select(t => new { Lambda = Ref.GetLambda(t, eType), Input = t }).ToArray(); var block = Ex.Block(new[] { res }, Ex.Assign(res, Ex.NewArrayBounds(typeof(ConversionResult <>).MakeGenericType(eType), Ex.Constant(fromParameters.Length))), Ex.Block(converters.Select((con, i) => Ex.Block( Ex.Assign(Ex.ArrayAccess(res, Ex.Constant(i)), con.Lambda.ApplyTo(Ex.PropertyOrField(input, $"Item{i + 1}"))), Ex.IfThen(Ex.Not(Ex.Property(Ex.ArrayIndex(res, Ex.Constant(i)), nameof(IConversionResult.IsSuccessful))), Ex.Goto(end, NoResult(to)))))), Ex.Label(end, Result(to, Ex.NewArrayInit(eType, Enumerable.Range(0, fromParameters.Length) .Select(idx => Ex.Property(Ex.ArrayIndex(res, Ex.Constant(idx)), nameof(IConversionResult.Result))))))); var lambda = Ex.Lambda(block, input); return(lambda); }
public static Ex Index(this Ex me, Ex index) => Ex.ArrayAccess(me, index);
private static LinqExpression[] CompileGroup(ExpressionGroup group, CompilationData data) { switch (group) { case Persist p: foreach (var s in p.State) { if (!(s.InitialValue is Constant)) { throw new Exception("Persist initial value is not constant"); } data.StateValues.Add(((Constant)s.InitialValue).Value); } var assigns = new List <LinqExpression>(); // TODO: Resolve parent scopes data.ResolveState = s => LinqExpression.ArrayAccess(data.StateArray, LinqExpression.Constant(s.Id)); for (var i = 0; i < p.NewValue.Count; i++) { var newValueExpr = Compile(p.NewValue[i], data); assigns.Add(LinqExpression.Assign( LinqExpression.ArrayAccess(data.StateArray, LinqExpression.Constant(i)), newValueExpr)); } data.Statements.AddRange(assigns); return(Enumerable.Range(0, p.Size) .Select(i => LinqExpression.ArrayAccess(data.StateArray, LinqExpression.Constant(i))) .ToArray()); case Loop l: var stateList = new List <ParameterExpression>(); foreach (var s in l.State) { var initial = Compile(s.InitialValue, data); var variable = LinqExpression.Variable(initial.Type); data.Statements.Add(LinqExpression.Assign(variable, initial)); data.Variables.Add(variable); stateList.Add(variable); } // TODO: Resolve parent scopes data.ResolveState = s => stateList[s.Id]; var parentStatements = data.Statements; // Make a new cache that copies in the old one, but won't leak State expressions data.Cache = new Dictionary <CachedExpression, ParameterExpression>(data.Cache); // Create a new statements list to put in the loop body var s1 = data.Statements = new List <LinqExpression>(); var condition = Compile(l.Condition, data); var s2 = data.Statements = new List <LinqExpression>(); var newState = l.Body.Select(e => Compile(e, data)).ToArray(); // Ensure that the entire state is only set at the end of the loop for (var i = 0; i < newState.Length; i++) { var s = newState[i]; if (!(s is ParameterExpression)) { var tmpVar = LinqExpression.Variable(s.Type); data.Variables.Add(tmpVar); s2.Add(LinqExpression.Assign(tmpVar, s)); newState[i] = tmpVar; } } var breakLabel = LinqExpression.Label(); var body = LinqExpression.Block(s1 .Concat(new[] { LinqExpression.IfThen( LinqExpression.LessThan(condition, LinqExpression.Constant(1f)), LinqExpression.Break(breakLabel)) }) .Concat(s2) .Concat(newState.Select((e, i) => LinqExpression.Assign(stateList[i], e)))); parentStatements.Add(LinqExpression.Loop(body, breakLabel)); return(stateList.ToArray()); 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); }
// Generate code to perform row reduction. private static void RowReduce(CodeGen code, LinqExpr Ab, int M, int N) { // For each variable in the system... for (int j = 0; j + 1 < N; ++j) { LinqExpr _j = LinqExpr.Constant(j); LinqExpr Abj = code.ReDeclInit <double[]>("Abj", LinqExpr.ArrayAccess(Ab, _j)); // int pi = j LinqExpr pi = code.ReDeclInit <int>("pi", _j); // double max = |Ab[j][j]| LinqExpr max = code.ReDeclInit <double>("max", Abs(LinqExpr.ArrayAccess(Abj, _j))); // Find a pivot row for this variable. //code.For(j + 1, M, _i => //{ for (int i = j + 1; i < M; ++i) { LinqExpr _i = LinqExpr.Constant(i); // if(|Ab[i][j]| > max) { pi = i, max = |Ab[i][j]| } LinqExpr maxj = code.ReDeclInit <double>("maxj", Abs(LinqExpr.ArrayAccess(LinqExpr.ArrayAccess(Ab, _i), _j))); code.Add(LinqExpr.IfThen( LinqExpr.GreaterThan(maxj, max), LinqExpr.Block( LinqExpr.Assign(pi, _i), LinqExpr.Assign(max, maxj)))); } // (Maybe) swap the pivot row with the current row. LinqExpr Abpi = code.ReDecl <double[]>("Abpi"); code.Add(LinqExpr.IfThen( LinqExpr.NotEqual(_j, pi), LinqExpr.Block( new[] { LinqExpr.Assign(Abpi, LinqExpr.ArrayAccess(Ab, pi)) }.Concat( Enumerable.Range(j, N + 1 - j).Select(x => Swap( LinqExpr.ArrayAccess(Abj, LinqExpr.Constant(x)), LinqExpr.ArrayAccess(Abpi, LinqExpr.Constant(x)), code.ReDecl <double>("swap"))))))); //// It's hard to believe this swap isn't faster than the above... //code.Add(LinqExpr.IfThen(LinqExpr.NotEqual(_j, pi), LinqExpr.Block( // Swap(LinqExpr.ArrayAccess(Ab, _j), LinqExpr.ArrayAccess(Ab, pi), Redeclare<double[]>(code, "temp")), // LinqExpr.Assign(Abj, LinqExpr.ArrayAccess(Ab, _j))))); // Eliminate the rows after the pivot. LinqExpr p = code.ReDeclInit <double>("p", LinqExpr.ArrayAccess(Abj, _j)); //code.For(j + 1, M, _i => //{ for (int i = j + 1; i < M; ++i) { LinqExpr _i = LinqExpr.Constant(i); LinqExpr Abi = code.ReDeclInit <double[]>("Abi", LinqExpr.ArrayAccess(Ab, _i)); // s = Ab[i][j] / p LinqExpr s = code.ReDeclInit <double>("scale", LinqExpr.Divide(LinqExpr.ArrayAccess(Abi, _j), p)); // Ab[i] -= Ab[j] * s for (int ji = j + 1; ji < N + 1; ++ji) { code.Add(LinqExpr.SubtractAssign( LinqExpr.ArrayAccess(Abi, LinqExpr.Constant(ji)), LinqExpr.Multiply(LinqExpr.ArrayAccess(Abj, LinqExpr.Constant(ji)), s))); } } } }
// 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 Expr ToExpression() => Expr.ArrayAccess(Array.ToExpression(), Index.ToExpression());
public override TreeNode TryUnroll() { if (!MustUnroll) { return(this); } // Reduce begins now var bodyExpression = new TreeNode() { TypeToken = Array.TypeToken.GetElementTypeToken(), MemberToken = Array.MemberToken, AccessExpression = Array.AccessExpression }; // Array initializer added now and only now bodyExpression.ReadExpression.Add(bodyExpression.TypeToken.NewArrayBounds(Expr.Constant(IterationCount - InitialValue))); // Create N blocks of body for (var i = 0; i < IterationCount - InitialValue; ++i) { var invocationNode = new TreeNode() { // Can't reuse this.AccessExpression because it's bound on the iterator. AccessExpression = Expr.ArrayAccess(Array.AccessExpression, Expr.Constant(i)), MemberToken = Array.MemberToken, TypeToken = Array.TypeToken.GetElementTypeToken() }; // Insert ctor if class if (invocationNode.TypeToken.IsClass) { invocationNode.ReadExpression.Add(invocationNode.TypeToken.NewExpression()); } // Insert all children foreach (var childNode in Children) { var newChildNode = new TreeNode() { AccessExpression = Expr.MakeMemberAccess(invocationNode.AccessExpression, childNode.MemberToken.MemberInfo), MemberToken = childNode.MemberToken, TypeToken = childNode.TypeToken }; // Now that we created a new block we must try to unroll it if it needs to foreach (var subChildNode in childNode.Children) { newChildNode.AddChild(subChildNode.TryUnroll()); } // If deserialization calls were found select the one corresponding to the currently unrolling iteration. if (childNode.ReadExpression.Count > 0) { newChildNode.ReadExpression.Add(childNode.ReadExpression[i]); } invocationNode.AddChild(newChildNode); } bodyExpression.AddChild(invocationNode); } return(bodyExpression); }