public SingleSelectWrapper(IArray2d <T> source, Kernel <T, R> kernel) { _source = source ?? throw new ArgumentNullException(nameof(source)); _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel)); _h = source.GetLength(0); _w = source.GetLength(1); _km = KernelMeasure.Measure(kernel); if (source is IRelQueryableArray2d <T> rqa) { if (rqa.BoundOptions[BoundsDirection.Top] != Bounds.Skip) { _km.xmin = 0; } if (rqa.BoundOptions[BoundsDirection.Bottom] != Bounds.Skip) { _km.xmax = 0; } if (rqa.BoundOptions[BoundsDirection.Left] != Bounds.Skip) { _km.ymin = 0; } if (rqa.BoundOptions[BoundsDirection.Right] != Bounds.Skip) { _km.ymax = 0; } } }
public static KernelMeasure Measure(LambdaExpression kernel, KernelMeasure m = null) { m = m ?? new KernelMeasure(); // TODO: perform the analysis of the kernel lambda to see what's going on new KernelMeasureVisitor(kernel, m).Visit(kernel); return(m); }
public static Expression <Filter <T, R> > GenerateExprFilter <T, R>(Expression <Kernel <T, R> > kernelExpr) where R : unmanaged { var km = KernelMeasure.Measure(kernelExpr.Compile()); var data_arg = Parameter(typeof(T[, ]), "data"); var result_var = Variable(typeof(R[, ]), "result"); var i_var = Variable(typeof(int), "i"); var j_var = Variable(typeof(int), "j"); var h_var = Variable(typeof(int), "h"); var w_var = Variable(typeof(int), "w"); var inlinedKernel = new CellAccessInliner <T>(kernelExpr.Parameters[0], data_arg, i_var, j_var).Visit(kernelExpr.Body); var fe = Block(typeof(R[, ]), new[] { data_arg, h_var, w_var, result_var }, new[] { Assign(h_var, Call(data_arg, typeof(T[, ]).GetMethod("GetLength", new [] { typeof(int) }), Constant(0))), Assign(w_var, Call(data_arg, typeof(T[, ]).GetMethod("GetLength", new [] { typeof(int) }), Constant(1))), Assign(result_var, New(typeof(R[, ]).GetConstructor(new[] { typeof(int), typeof(int) }), h_var, w_var)), ExpressionHelper.For(i_var, Constant(-km.xmin), LessThan(i_var, Subtract(h_var, Constant(km.xmax))), AddAssign(i_var, Constant(1)), ExpressionHelper.For(j_var, Constant(-km.ymin), LessThan(j_var, Subtract(h_var, Constant(km.xmax))), AddAssign(j_var, Constant(1)), Assign(MakeIndex(result_var, typeof(R[, ]).GetProperty("Item", new Type[] { typeof(int), typeof(int) }), new[] { i_var, j_var }), inlinedKernel)) ), result_var } ); var nne = Lambda <Filter <T, R> >(fe, data_arg); return(nne); }
public static KernelMeasure Measure <T, R>(Kernel <T, R> kernel, KernelMeasure m = null) { m = m ?? new KernelMeasure(); var km = new KernelMeasure <T>(m); kernel(km); return(m); }
public DualSelectWrapper(IArray2d <T> left, IArray2d <A> right, Expression <Func <ICell <T>, ICell <A>, R> > kernel) { _left = left ?? throw new ArgumentNullException(nameof(left)); _right = right ?? throw new ArgumentNullException(nameof(right)); _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel)); _compiledKernel = _kernel.Compile(); _h = Min(left.GetLength(0), right.GetLength(0)); _w = Min(left.GetLength(1), right.GetLength(1)); _km = new KernelMeasure(); var km1 = new KernelMeasure <T>(_km); var km2 = new KernelMeasure <A>(_km); _compiledKernel(km1, km2); }
public RecurrentSelectWrapper(IArray2d <T> source, Func <ICell <T>, ICell <R>, R> kernel) { _source = source ?? throw new ArgumentNullException(nameof(source)); _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel)); _h = source.GetLength(0); _w = source.GetLength(1); var m = new KernelMeasure(); var km1 = new KernelMeasure <T>(m); var km2 = new KernelMeasure <R>(m); kernel(km1, km2); _xmin = m.xmin; _xmax = m.xmax; _ymin = m.ymin; _ymax = m.ymax; }
public DualSelectWrapper(IArray2d <T> left, IArray2d <A> right, Func <ICell <T>, ICell <A>, R> kernel) { _left = left ?? throw new ArgumentNullException(nameof(left)); _right = right ?? throw new ArgumentNullException(nameof(right)); _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel)); _h = Math.Min(left.GetLength(0), right.GetLength(0)); _w = Math.Min(left.GetLength(1), right.GetLength(1)); var m = new KernelMeasure(); var km1 = new KernelMeasure <T>(m); var km2 = new KernelMeasure <A>(m); kernel(km1, km2); _xmin = m.xmin; _xmax = m.xmax; _ymin = m.ymin; _ymax = m.ymax; }
private unsafe static R[,] FilterParallel <T, R>(Kernel <T, R> kernel, T[,] source) where T : unmanaged where R : unmanaged { var h = source.GetLength(0); var w = source.GetLength(1); var result = new R[h, w]; var km = KernelMeasure.Measure(kernel); h -= km.xmax; // decrease to use as the cycle limit var factory = GetStripeHandlerFactory(kernel); var linesCount = h + km.xmin; var taskCount = Min(linesCount, Environment.ProcessorCount); fixed(T *psource = &source[-km.xmin, -km.ymin]) fixed(R * presult = &result[-km.xmin, -km.ymin]) { var tasks = new Task[taskCount - 1]; long delta = 0; for (var taskNum = 0; taskNum < taskCount; taskNum++) { int startInclusive = taskNum * linesCount / taskCount; int endExclusive = (taskNum + 1) * linesCount / taskCount; var psourcetmp = psource + startInclusive * w; delta = (long)presult - (long)psource + startInclusive * w * (sizeof(R) - sizeof(T)); var stripeHandler = factory(psourcetmp, endExclusive - startInclusive, delta, w, kernel.Target); if (taskNum + 1 == taskCount) // the last task { stripeHandler(); // is executed in the main thread } else // the others { tasks[taskNum] = Task.Run(stripeHandler); // are executed in the worker threads } } Task.WaitAll(tasks); } return(result); }
public static R[,] Select <T, R>(this IRelQueryableArray2d <T> source, Kernel <T, R> kernel) { var h = source.GetLength(0); var w = source.GetLength(1); var result = new R[h, w]; var km = KernelMeasure.Measure(kernel); var cell = new Cell <T>(source); for (cell._x = -km.xmin; cell._x < h - km.xmax; cell._x++) { for (cell._y = -km.ymin; cell._y < w - km.ymax; cell._y++) { result[cell._x, cell._y] = kernel(cell); } } return(result); }
public unsafe static R[,] FilterParallel <T, R>(Expression <Kernel <T, R> > kernel, T[,] source) where T : unmanaged where R : unmanaged { var h = source.GetLength(0); var w = source.GetLength(1); var result = new R[h, w]; var km = KernelMeasure.Measure(kernel.Compile()); //h -= km.xmax; // decrease to use as the cycle limit var factory = GenerateStripeHandlerFactory(kernel); var linesCount = h + km.xmin - km.xmax; var taskCount = Min(linesCount, Environment.ProcessorCount); using (var sourceRef = new UnsafeArray2d <T>(source)) using (var resultRef = new UnsafeArray2d <R>(result)) { var tasks = new Task[taskCount - 1]; for (var taskNum = 0; taskNum < taskCount; taskNum++) { int xmin = -km.xmin + taskNum * linesCount / taskCount; int xmax = -km.xmin + (taskNum + 1) * linesCount / taskCount; var stripeHandler = factory(xmin, xmax, -km.ymin, w - km.ymax, sourceRef, resultRef); if (taskNum + 1 == taskCount) // the last task { stripeHandler(); // is executed in the main thread } else // the others { tasks[taskNum] = Task.Run(stripeHandler); // are executed in the worker threads } } Task.WaitAll(tasks); } return(result); }
internal KernelMeasureVisitor(LambdaExpression kernel, KernelMeasure m) { _kernel = kernel ?? throw new ArgumentNullException(nameof(kernel)); _m = m ?? throw new ArgumentNullException(nameof(m)); }
private static MethodBuilder BuildRunMethod <T, R>(Expression <Kernel <T, R> > kernel, TypeBuilder tb, FieldInfo xmin, FieldInfo xmax, FieldInfo ymin, FieldInfo ymax, FieldInfo source, FieldInfo target) where T : unmanaged where R : unmanaged { var km = KernelMeasure.Measure(kernel.Compile()); //TODO: perform an expression-only measure var staticRun = tb.DefineMethod("RunStatic", MethodAttributes.HideBySig | MethodAttributes.Private | MethodAttributes.Static, null, new[] { typeof(int), typeof(int), typeof(int), typeof(int), typeof(int), typeof(UnsafeArray2dPtr <T>), UnsafeArray2d.GetRefType <R>() }); var xmin_arg = Parameter(typeof(int), "xmin"); var xmax_arg = Parameter(typeof(int), "xmax"); var ymin_arg = Parameter(typeof(int), "ymin"); var ymax_arg = Parameter(typeof(int), "ymax"); var height_arg = Parameter(typeof(int), "height"); var sourcePtr_arg = Parameter(typeof(UnsafeArray2dPtr <T>), "sourcePtr"); var targetPtr_arg = Parameter(UnsafeArray2d.GetRefType <R>(), "targetPtr"); var i_var = Variable(typeof(int), "i"); var j_var = Variable(typeof(int), "j"); var w_var = Variable(typeof(int), "w"); var inlinedKernel = new CellAccessUnsafeInliner(kernel.Parameters[0], sourcePtr_arg, i_var, j_var, height_arg, w_var).Visit(kernel.Body); BlockExpression fe = null; if (typeof(T) == typeof(R)) // slight optimization { var l = Label(); var d_var = Variable(typeof(int), "d"); var lineEnd_var = Variable(typeof(UnsafeArray2dPtr <T>), "lineEnd"); fe = Block( new[] { w_var, d_var, lineEnd_var }, Assign(w_var, Property(sourcePtr_arg, typeof(UnsafeArray2dPtr <T>).GetProperty(nameof(UnsafeArray2dPtr <T> .Stride)))), Assign(d_var, Subtract(targetPtr_arg, sourcePtr_arg)), For(i_var, xmin_arg, LessThan(i_var, xmax_arg), Constant(1), Block( Assign(lineEnd_var, Subtract(Add(sourcePtr_arg, ymax_arg), ymin_arg)), Loop( IfThenElse( LessThan(sourcePtr_arg, lineEnd_var), Block( Assign( MakeIndex( sourcePtr_arg, typeof(UnsafeArray2dPtr <T>).GetProperty("Item", new[] { typeof(int) }), new[] { d_var } ), inlinedKernel ), AddAssign(sourcePtr_arg, Constant(1)) // skip to the next element ), Break(l) ), l ), AddAssign(sourcePtr_arg, Constant(km.ymax - km.ymin)) // skip to the next row ) ) ); } else { fe = Block( new[] { w_var }, Assign(w_var, Property(sourcePtr_arg, typeof(UnsafeArray2dPtr <T>).GetProperty(nameof(UnsafeArray2dPtr <T> .Stride)))), For(i_var, xmin_arg, LessThan(i_var, xmax_arg), Constant(1), Block( For( j_var, ymin_arg, LessThan(j_var, ymax_arg), Constant(1), Block( Assign( MakeIndex( targetPtr_arg, UnsafeArray2d.GetRefType <R>().GetProperty("Item", new[] { typeof(int) }), new[] { Constant(0) } ), inlinedKernel ), AddAssign(sourcePtr_arg, Constant(1)), // skip to the next element AddAssign(targetPtr_arg, Constant(1)) ) ), AddAssign(sourcePtr_arg, Constant(km.ymax - km.ymin)), // skip to the next row AddAssign(targetPtr_arg, Constant(km.ymax - km.ymin)) ) ) ); } LambdaExpression staticRunLambda = Lambda(fe, xmin_arg, xmax_arg, ymin_arg, ymax_arg, height_arg, sourcePtr_arg, targetPtr_arg); staticRunLambda.CompileToMethod(staticRun); return(BuildInstanceRun <T, R>(tb, xmin, xmax, ymin, ymax, source, target, staticRun)); }
private static MethodBuilder BuildRunMethod <R>(LambdaExpression kernel, TypeBuilder tb, FieldInfo xmin, FieldInfo xmax, FieldInfo ymin, FieldInfo ymax, IEnumerable <FieldInfo> sources, FieldInfo target, bool recurrent) { var km = KernelMeasure.Measure(kernel); //TODO: perform an expression-only measure var sourceTypes = (from s in sources let elemType = s.FieldType.GetGenericArguments()[0] select typeof(UnsafeArray2dPtr <>).MakeGenericType(elemType)).ToArray(); var paramTypes = Enumerable.Repeat(typeof(int), 5) .Concat(sourceTypes) .Append(UnsafeArray2d.GetRefType <R>()).ToArray(); var staticRun = tb.DefineMethod("RunStatic", MethodAttributes.HideBySig | MethodAttributes.Private | MethodAttributes.Static, null, paramTypes); var xmin_arg = Parameter(typeof(int), "xmin"); var xmax_arg = Parameter(typeof(int), "xmax"); var ymin_arg = Parameter(typeof(int), "ymin"); var ymax_arg = Parameter(typeof(int), "ymax"); var height_arg = Parameter(typeof(int), "height"); var sourceArgs = new List <ParameterExpression>(); var i = 0; foreach (var s in sources) { sourceArgs.Add(Parameter(sourceTypes[i++], s.Name.Substring(1) + "Ptr")); } var targetPtr_arg = Parameter(UnsafeArray2d.GetRefType <R>(), "targetPtr"); var paramMap = new Dictionary <ParameterExpression, ParameterExpression>(); for (i = 0; i < sourceArgs.Count; i++) { //if(kernel.Parameters[i].Type.IsConstructedGenericType && kernel.Parameters[i].Type.GetGenericTypeDefinition() == typeof(ICell<>)) paramMap.Add(kernel.Parameters[i], sourceArgs[i]); } if (recurrent) { paramMap.Add(kernel.Parameters[i], targetPtr_arg); } var i_var = Variable(typeof(int), "i"); var j_var = Variable(typeof(int), "j"); var w_var = Variable(typeof(int), "w"); var inlinedKernelBody = new CellAccessUnsafeInliner(paramMap, i_var, j_var, height_arg, w_var).Visit(kernel.Body); BlockExpression fe = null; { fe = Block( new[] { w_var }, Assign(w_var, Property(targetPtr_arg, UnsafeArray2d.GetRefType <R>().GetProperty("Stride"))), For(i_var, xmin_arg, LessThan(i_var, xmax_arg), Constant(1), Block( For( j_var, ymin_arg, LessThan(j_var, ymax_arg), Constant(1), Block( Assign( MakeIndex( targetPtr_arg, UnsafeArray2d.GetRefType <R>().GetProperty("Item", new[] { typeof(int) }), new[] { Constant(0) } ), inlinedKernelBody ), Block(from s in sourceArgs select AddAssign(s, Constant(1))), // skip to the next element AddAssign(targetPtr_arg, Constant(1)) ) ), Block(from s in sourceArgs select AddAssign(s, Constant(km.ymax - km.ymin))), // skip to the next row AddAssign(targetPtr_arg, Constant(km.ymax - km.ymin)) ) ) ); } LambdaExpression staticRunLambda = Lambda(fe, (new[] { xmin_arg, xmax_arg, ymin_arg, ymax_arg, height_arg }).Concat(sourceArgs).Append(targetPtr_arg)); staticRunLambda.CompileToMethod(staticRun); return(BuildInstanceRun <R>(tb, xmin, xmax, ymin, ymax, sources, target, staticRun)); }
public static Filter <T, R> GenerateFilter <T, R>(Kernel <T, R> kernel) { var km = KernelMeasure.Measure(kernel); DynamicMethod dm = new DynamicMethod("Filter" + kernel.Method.Name, typeof(IArray2d <R>), new[] { typeof(object), typeof(IArray2d <T>) }); var ilg = dm.GetILGenerator(); var h_var = ilg.DeclareLocal(typeof(int)); var w_var = ilg.DeclareLocal(typeof(int)); var result_var = ilg.DeclareLocal(typeof(R[, ])); var i_var = ilg.DeclareLocal(typeof(int)); var j_var = ilg.DeclareLocal(typeof(int)); ilg.Emit(OpCodes.Ldarg_1); // source ilg.Emit(OpCodes.Ldc_I4_0); // 0 MethodInfo getLength = typeof(IArray2d).GetMethod(nameof(IArray2d.GetLength), new [] { typeof(int) }); ilg.Emit(OpCodes.Callvirt, getLength); ilg.Emit(OpCodes.Stloc, h_var); ilg.Emit(OpCodes.Ldarg_1); // source ilg.Emit(OpCodes.Ldc_I4_1); // 0 ilg.Emit(OpCodes.Callvirt, getLength); ilg.Emit(OpCodes.Stloc, w_var); ilg.Emit(OpCodes.Ldloc, h_var); ilg.Emit(OpCodes.Ldloc, w_var); ilg.Emit(OpCodes.Newobj, typeof(R[, ]).GetConstructor(new[] { typeof(int), typeof(int) })); ilg.Emit(OpCodes.Stloc, result_var); ilg.EmitIncrease(h_var, -km.ymax); ilg.EmitIncrease(w_var, -km.xmax); ilg.EmitFor(i_var, 0 - km.xmin, h_var, () => { ilg.EmitFor(j_var, 0 - km.ymin, w_var, () => { ilg.Emit(OpCodes.Ldloc, result_var); ilg.Emit(OpCodes.Ldloc, i_var); ilg.Emit(OpCodes.Ldloc, j_var); // call the kernel - begin var ki = new SafeInliningILInstructionVisitor <T>(ilg, i_var, j_var); new ILReader(kernel.Method).Accept(ki); // call the kernel - end ilg.Emit(OpCodes.Call, typeof(R[, ]).GetMethod("Set", new [] { typeof(int), typeof(int), typeof(R) })); }); }); ilg.Emit(OpCodes.Ldloc, result_var); ilg.Emit(OpCodes.Newobj, typeof(ArrayWrapper <R>).GetConstructor(new[] { typeof(R[, ]) })); ilg.Emit(OpCodes.Box, typeof(ArrayWrapper <R>)); ilg.Emit(OpCodes.Ret); var inlined = (Func <object, IArray2d <T>, IArray2d <R> >)dm.CreateDelegate(typeof(Func <object, IArray2d <T>, IArray2d <R> >)); //Print(inlined.Method); return(data => inlined(kernel.Target, data)); }
private unsafe static Filter <T, R> GenerateUnsafeFilter <T, R>(Kernel <T, R> kernel) where T : unmanaged where R : unmanaged { var km = KernelMeasure.Measure(kernel); var dm = new DynamicMethod <Func <object, T[, ], R[, ]> >("Filter." + kernel.Method.Name, typeof(Array2D).Module); var ilg = dm.GetILGenerator(); var h = ilg.DeclareLocal(typeof(int)); var w = ilg.DeclareLocal(typeof(int)); var psource = ilg.DeclareLocal(typeof(T *)); var sourcePin = ilg.DeclareLocal(typeof(T[, ]), true); // a replica of the arg1, to force the GC pinning var targetPin = ilg.DeclareLocal(typeof(R[, ]), true); // a target structure var i = ilg.DeclareLocal(typeof(int)); var j = ilg.DeclareLocal(typeof(int)); var W = ilg.DeclareLocal(typeof(int)); var delta = ilg.DeclareLocal(typeof(int)); ilg.Emit(OpCodes.Ldarg_1); // source ilg.Emit(OpCodes.Ldc_I4_0); // 0 var getLength = typeof(T[, ]).GetMethod(nameof(Array.GetLength), new [] { typeof(int) }); ilg.Emit(OpCodes.Call, getLength); ilg.Emit(OpCodes.Stloc, h); ilg.Emit(OpCodes.Ldarg_1); // source ilg.Emit(OpCodes.Ldc_I4_1); // 1 ilg.Emit(OpCodes.Call, getLength); ilg.Emit(OpCodes.Stloc, w); ilg.Emit(OpCodes.Ldloc, h); ilg.Emit(OpCodes.Ldloc, w); ilg.Emit(OpCodes.Newobj, typeof(R[, ]).GetConstructor(new[] { typeof(int), typeof(int) })); ilg.Emit(OpCodes.Stloc, targetPin); // pinning the target ilg.Emit(OpCodes.Ldarg_1); // source ilg.Emit(OpCodes.Stloc, sourcePin); // pinning the source ilg.Emit(OpCodes.Ldloc, sourcePin); ilg.Emit(OpCodes.Ldc_I4, -km.xmin); // -km.xmin, source ilg.Emit(OpCodes.Ldc_I4, -km.ymin); // -km.ymin, -km.xmin, source MethodInfo arrayofTAddressGetter = typeof(T[, ]).GetMethod("Address", new[] { typeof(int), typeof(int) }); ilg.Emit(OpCodes.Call, arrayofTAddressGetter);// &source[1,1]; ilg.Emit(OpCodes.Conv_U); ilg.Emit(OpCodes.Stloc, psource); ilg.Emit(OpCodes.Ldloc, targetPin); // load result ilg.Emit(OpCodes.Ldc_I4, -km.xmin); // -km.xmin, target ilg.Emit(OpCodes.Ldc_I4, -km.ymin); // -km.ymin, -km.xmin, target ilg.Emit(OpCodes.Call, arrayofTAddressGetter); // &target[1,1]; ilg.Emit(OpCodes.Conv_U); ilg.Emit(OpCodes.Ldloc, psource); ilg.Emit(OpCodes.Sub); ilg.Emit(OpCodes.Stloc, delta); ilg.Emit(OpCodes.Ldloc, w); ilg.Emit(OpCodes.Stloc, W); ilg.EmitIncrease(h, -km.ymax); ilg.EmitIncrease(w, -km.xmax); ilg.EmitFor(i, 0 - km.xmin, h, () => { ilg.EmitFor(j, 0 - km.ymin, w, () => { ilg.Emit(OpCodes.Ldloc, psource); ilg.Emit(OpCodes.Ldloc, delta); ilg.Emit(OpCodes.Add); // source+delta = target; var usilv = new UnsafeInliningILInstructionVisitor <T>(ilg, i, j, W, psource); //new ILReader(kernel.Method).Accept(usilv); ilg.Emit(OpCodes.Stind_I4); ilg.EmitIncrease(psource, sizeof(T)); // psource ++ ilg.EmitIncrease(delta, sizeof(R) - sizeof(T)); // delta += sizediff; zero in case of same-type; }); ilg.EmitIncrease(psource, sizeof(T) * (km.ymax - km.ymin)); }); ilg.Emit(OpCodes.Ldloc, targetPin); ilg.Emit(OpCodes.Ret); var inlined = dm.CreateDelegate(); R[,] filter(T[,] data) => inlined(kernel.Target, data); return(filter); }
private static unsafe MethodBuilder BuildRunMethod <T, R>(Kernel <T, R> kernel, TypeBuilder tb, FieldInfo length, FieldInfo sourcePtr, FieldInfo delta, FieldInfo width, FieldInfo target) where T : unmanaged where R : unmanaged { var km = KernelMeasure.Measure(kernel); var hs = tb.DefineMethod("Run", MethodAttributes.HideBySig | MethodAttributes.Public, null, new Type[0]); //var hs = new DynamicMethod("HandleStripe." + kernel.Method.Name, null, new[] { typeof(object), typeof(T*), typeof(int), typeof(int), typeof(long), typeof(int) }, typeof(Array2D).Module); var ilg = hs.GetILGenerator(); var tempw = ilg.DeclareLocal(typeof(int)); var tempW = ilg.DeclareLocal(typeof(int)); var tempI = ilg.DeclareLocal(typeof(int)); var tempJ = ilg.DeclareLocal(typeof(int)); var lengthVar = ilg.DeclareLocal(typeof(int)); var deltaVar = ilg.DeclareLocal(typeof(long)); var srcPtr = ilg.DeclareLocal(typeof(T *)); ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Ldfld, width); ilg.Emit(OpCodes.Dup); ilg.Emit(OpCodes.Stloc, tempW); // W = width; ilg.Emit(OpCodes.Ldc_I4, km.ymax); ilg.Emit(OpCodes.Sub); ilg.Emit(OpCodes.Stloc, tempw); // w = width-1; ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Ldfld, sourcePtr); ilg.Emit(OpCodes.Stloc, srcPtr); // srcPtr = sourcePtr; ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Ldfld, delta); ilg.Emit(OpCodes.Stloc, deltaVar); // delta = delta; ilg.Emit(OpCodes.Ldarg_0); // this ilg.Emit(OpCodes.Ldfld, length); ilg.Emit(OpCodes.Stloc, lengthVar); ilg.EmitFor(tempI, 0, lengthVar, () => { ilg.EmitFor(tempJ, -km.ymin, tempw, () => { ilg.Emit(OpCodes.Ldloc, srcPtr); ilg.Emit(OpCodes.Ldloc, deltaVar); ilg.Emit(OpCodes.Conv_I); // (int) delta; ilg.Emit(OpCodes.Add); // srcPtr+delta = target; var usilv = new UnsafeParallelInliningILInstructionVisitor <T>(ilg, tempI, tempJ, tempW, srcPtr, target); new ILReader(kernel.Method).Accept(usilv); ilg.Emit(OpCodes.Stind_I4); //todo: work with different types ilg.EmitIncrease(srcPtr, sizeof(T)); // srcPtr++; ilg.EmitIncrease(deltaVar, sizeof(R) - sizeof(T)); }); ilg.EmitIncrease(srcPtr, sizeof(T) * (km.ymax - km.ymin)); ilg.EmitIncrease(deltaVar, ((km.ymax - km.ymin)) * (sizeof(R) - sizeof(T))); }); ilg.Emit(OpCodes.Ret); return(hs); }