ArrayAccess() public static method

Creates an IndexExpression to access an array.
The expression representing the array can be obtained by using the MakeMemberAccess method, or through NewArrayBounds or NewArrayInit.
public static ArrayAccess ( Expression array ) : IndexExpression
array Expression An expression representing the array to index.
return IndexExpression
コード例 #1
0
        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);
        }
コード例 #2
0
        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);
        }
コード例 #3
0
ファイル: LuaCompiler.cs プロジェクト: chenzuo/NetLua
 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));
 }
コード例 #4
0
ファイル: Program.cs プロジェクト: wiselynx/ComputerAlgebra
        // 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());
        }
コード例 #5
0
ファイル: Py.cs プロジェクト: alexphaus/py
 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
                     )));
 }
コード例 #6
0
        public void ArrayAccess()
        {
            var expression =
                LinqExpression.ArrayAccess(
                    LinqExpression.Parameter(
                        typeof(int[])),
                    LinqExpression.Parameter(
                        typeof(int)));

            ShouldRoundrip(expression);
        }
コード例 #7
0
        // 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)));
            }
        }
コード例 #8
0
        // 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));
        }
コード例 #9
0
        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);
        }
コード例 #10
0
 public static Ex Index(this Ex me, Ex index) => Ex.ArrayAccess(me, index);
コード例 #11
0
        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();
            }
        }
コード例 #12
0
        // 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);
        }
コード例 #13
0
        // 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)));
                    }
                }
            }
        }
コード例 #14
0
        // 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);
        }
コード例 #15
0
 public Expr ToExpression() => Expr.ArrayAccess(Array.ToExpression(), Index.ToExpression());
コード例 #16
0
ファイル: TreeNode.cs プロジェクト: Warpten/DBClientFiles.NET
        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);
        }