Free cookie consent management tool by TermsFeed Policy Generator

source: stable/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeILEmittingInterpreter.cs @ 14186

Last change on this file since 14186 was 14186, checked in by swagner, 8 years ago

#2526: Updated year of copyrights in license headers

File size: 34.5 KB
RevLine 
[6732]1#region License Information
2/* HeuristicLab
[14186]3 * Copyright (C) 2002-2016 Heuristic and Evolutionary Algorithms Laboratory (HEAL)
[6732]4 *
5 * This file is part of HeuristicLab.
6 *
7 * HeuristicLab is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * HeuristicLab is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with HeuristicLab. If not, see <http://www.gnu.org/licenses/>.
19 */
20#endregion
21
22using System;
[7615]23using System.Collections.Generic;
[6741]24using System.Linq;
[6732]25using System.Reflection;
26using System.Reflection.Emit;
27using HeuristicLab.Common;
28using HeuristicLab.Core;
[6740]29using HeuristicLab.Data;
[6732]30using HeuristicLab.Encodings.SymbolicExpressionTreeEncoding;
[6740]31using HeuristicLab.Parameters;
[6732]32using HeuristicLab.Persistence.Default.CompositeSerializers.Storable;
33
34namespace HeuristicLab.Problems.DataAnalysis.Symbolic {
35  [StorableClass]
36  [Item("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.")]
[8436]37  public sealed class SymbolicDataAnalysisExpressionTreeILEmittingInterpreter : ParameterizedNamedItem, ISymbolicDataAnalysisExpressionTreeInterpreter {
38    private static readonly Type thisType = typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter);
39    internal delegate double CompiledFunction(int sampleIndex, IList<double>[] columns);
[7842]40
[8436]41    #region method infos
42    private static MethodInfo listGetValue = typeof(IList<double>).GetProperty("Item", new Type[] { typeof(int) }).GetGetMethod();
43
[6732]44    private static MethodInfo cos = typeof(Math).GetMethod("Cos", new Type[] { typeof(double) });
45    private static MethodInfo sin = typeof(Math).GetMethod("Sin", new Type[] { typeof(double) });
46    private static MethodInfo tan = typeof(Math).GetMethod("Tan", new Type[] { typeof(double) });
47    private static MethodInfo exp = typeof(Math).GetMethod("Exp", new Type[] { typeof(double) });
48    private static MethodInfo log = typeof(Math).GetMethod("Log", new Type[] { typeof(double) });
49    private static MethodInfo power = typeof(Math).GetMethod("Pow", new Type[] { typeof(double), typeof(double) });
[6755]50    private static MethodInfo round = typeof(Math).GetMethod("Round", new Type[] { typeof(double) });
[7842]51    private static MethodInfo sqrt = typeof(Math).GetMethod("Sqrt", new Type[] { typeof(double) });
[6732]52
[7842]53    private static MethodInfo airyA = thisType.GetMethod("AiryA", new Type[] { typeof(double) });
54    private static MethodInfo airyB = thisType.GetMethod("AiryB", new Type[] { typeof(double) });
55    private static MethodInfo gamma = thisType.GetMethod("Gamma", new Type[] { typeof(double) });
56    private static MethodInfo psi = thisType.GetMethod("Psi", new Type[] { typeof(double) });
57    private static MethodInfo dawson = thisType.GetMethod("Dawson", new Type[] { typeof(double) });
58    private static MethodInfo expIntegralEi = thisType.GetMethod("ExpIntegralEi", new Type[] { typeof(double) });
59    private static MethodInfo sinIntegral = thisType.GetMethod("SinIntegral", new Type[] { typeof(double) });
60    private static MethodInfo cosIntegral = thisType.GetMethod("CosIntegral", new Type[] { typeof(double) });
61    private static MethodInfo hypSinIntegral = thisType.GetMethod("HypSinIntegral", new Type[] { typeof(double) });
62    private static MethodInfo hypCosIntegral = thisType.GetMethod("HypCosIntegral", new Type[] { typeof(double) });
63    private static MethodInfo fresnelCosIntegral = thisType.GetMethod("FresnelCosIntegral", new Type[] { typeof(double) });
64    private static MethodInfo fresnelSinIntegral = thisType.GetMethod("FresnelSinIntegral", new Type[] { typeof(double) });
65    private static MethodInfo norm = thisType.GetMethod("Norm", new Type[] { typeof(double) });
66    private static MethodInfo erf = thisType.GetMethod("Erf", new Type[] { typeof(double) });
67    private static MethodInfo bessel = thisType.GetMethod("Bessel", new Type[] { typeof(double) });
[8436]68    #endregion
[7842]69
[6732]70    private const string CheckExpressionsWithIntervalArithmeticParameterName = "CheckExpressionsWithIntervalArithmetic";
[7615]71    private const string EvaluatedSolutionsParameterName = "EvaluatedSolutions";
[7842]72
[6732]73    public override bool CanChangeName {
74      get { return false; }
75    }
[7842]76
[6732]77    public override bool CanChangeDescription {
78      get { return false; }
79    }
80
81    #region parameter properties
[7842]82
[6732]83    public IValueParameter<BoolValue> CheckExpressionsWithIntervalArithmeticParameter {
84      get { return (IValueParameter<BoolValue>)Parameters[CheckExpressionsWithIntervalArithmeticParameterName]; }
85    }
[7615]86
87    public IValueParameter<IntValue> EvaluatedSolutionsParameter {
88      get { return (IValueParameter<IntValue>)Parameters[EvaluatedSolutionsParameterName]; }
89    }
[7842]90
[6732]91    #endregion
92
93    #region properties
[7842]94
[6732]95    public BoolValue CheckExpressionsWithIntervalArithmetic {
96      get { return CheckExpressionsWithIntervalArithmeticParameter.Value; }
97      set { CheckExpressionsWithIntervalArithmeticParameter.Value = value; }
98    }
[7615]99
100    public IntValue EvaluatedSolutions {
101      get { return EvaluatedSolutionsParameter.Value; }
102      set { EvaluatedSolutionsParameter.Value = value; }
103    }
[7842]104
[6732]105    #endregion
106
107
108    [StorableConstructor]
[8436]109    private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(bool deserializing) : base(deserializing) { }
[7842]110
[8436]111    private SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter original, Cloner cloner) : base(original, cloner) { }
[6732]112    public override IDeepCloneable Clone(Cloner cloner) {
113      return new SymbolicDataAnalysisExpressionTreeILEmittingInterpreter(this, cloner);
114    }
115
116    public SymbolicDataAnalysisExpressionTreeILEmittingInterpreter()
117      : base("SymbolicDataAnalysisExpressionTreeILEmittingInterpreter", "Interpreter for symbolic expression trees.") {
[8436]118      Parameters.Add(new ValueParameter<BoolValue>(CheckExpressionsWithIntervalArithmeticParameterName, "Switch that determines if the interpreter checks the validity of expressions with interval arithmetic before evaluating the expression.", new BoolValue(false)));
119      Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
[6732]120    }
121
[7615]122    [StorableHook(HookType.AfterDeserialization)]
123    private void AfterDeserialization() {
124      if (!Parameters.ContainsKey(EvaluatedSolutionsParameterName))
[8436]125        Parameters.Add(new ValueParameter<IntValue>(EvaluatedSolutionsParameterName, "A counter for the total number of solutions the interpreter has evaluated", new IntValue(0)));
[7615]126    }
127
128    #region IStatefulItem
[7842]129
[7615]130    public void InitializeState() {
131      EvaluatedSolutions.Value = 0;
132    }
133
134    public void ClearState() {
135      EvaluatedSolutions.Value = 0;
136    }
[7842]137
[7615]138    #endregion
139
[12702]140    public IEnumerable<double> GetSymbolicExpressionTreeValues(ISymbolicExpressionTree tree, IDataset dataset, IEnumerable<int> rows) {
[6732]141      if (CheckExpressionsWithIntervalArithmetic.Value)
[8436]142        throw new NotSupportedException("Interval arithmetic is not yet supported in the symbolic data analysis interpreter.");
143
[7615]144      EvaluatedSolutions.Value++; // increment the evaluated solutions counter
[8436]145      var state = PrepareInterpreterState(tree, dataset);
[6741]146
[8436]147      Type[] methodArgs = { typeof(int), typeof(IList<double>[]) };
148      DynamicMethod testFun = new DynamicMethod("TestFun", typeof(double), methodArgs, typeof(SymbolicDataAnalysisExpressionTreeILEmittingInterpreter).Module);
[6741]149
[8436]150      ILGenerator il = testFun.GetILGenerator();
151      CompileInstructions(il, state, dataset);
152      il.Emit(System.Reflection.Emit.OpCodes.Conv_R8);
153      il.Emit(System.Reflection.Emit.OpCodes.Ret);
154      var function = (CompiledFunction)testFun.CreateDelegate(typeof(CompiledFunction));
155
156      IList<double>[] columns = dataset.DoubleVariables.Select(v => dataset.GetReadOnlyDoubleValues(v)).ToArray();
157
158      foreach (var row in rows) {
159        yield return function(row, columns);
160      }
161    }
162
[12702]163    private InterpreterState PrepareInterpreterState(ISymbolicExpressionTree tree, IDataset dataset) {
[8436]164      Instruction[] code = SymbolicExpressionTreeCompiler.Compile(tree, OpCodes.MapSymbolToOpCode);
165      Dictionary<string, int> doubleVariableNames = dataset.DoubleVariables.Select((x, i) => new { x, i }).ToDictionary(e => e.x, e => e.i);
166      int necessaryArgStackSize = 0;
167      foreach (Instruction instr in code) {
[6732]168        if (instr.opCode == OpCodes.Variable) {
[8436]169          var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
[9976]170          instr.data = doubleVariableNames[variableTreeNode.VariableName];
[6732]171        } else if (instr.opCode == OpCodes.LagVariable) {
[8436]172          var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
[9976]173          instr.data = doubleVariableNames[laggedVariableTreeNode.VariableName];
[6732]174        } else if (instr.opCode == OpCodes.VariableCondition) {
[8436]175          var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode;
[9976]176          instr.data = doubleVariableNames[variableConditionTreeNode.VariableName];
[6732]177        } else if (instr.opCode == OpCodes.Call) {
178          necessaryArgStackSize += instr.nArguments + 1;
179        }
180      }
[8436]181      return new InterpreterState(code, necessaryArgStackSize);
[6732]182    }
183
[12702]184    private void CompileInstructions(ILGenerator il, InterpreterState state, IDataset ds) {
[6732]185      Instruction currentInstr = state.NextInstruction();
186      int nArgs = currentInstr.nArguments;
187
188      switch (currentInstr.opCode) {
189        case OpCodes.Add: {
190            if (nArgs > 0) {
[6809]191              CompileInstructions(il, state, ds);
[6732]192            }
193            for (int i = 1; i < nArgs; i++) {
[6809]194              CompileInstructions(il, state, ds);
[6732]195              il.Emit(System.Reflection.Emit.OpCodes.Add);
196            }
197            return;
198          }
199        case OpCodes.Sub: {
200            if (nArgs == 1) {
[6809]201              CompileInstructions(il, state, ds);
[6732]202              il.Emit(System.Reflection.Emit.OpCodes.Neg);
203              return;
204            }
205            if (nArgs > 0) {
[6809]206              CompileInstructions(il, state, ds);
[6732]207            }
208            for (int i = 1; i < nArgs; i++) {
[6809]209              CompileInstructions(il, state, ds);
[6732]210              il.Emit(System.Reflection.Emit.OpCodes.Sub);
211            }
212            return;
213          }
214        case OpCodes.Mul: {
215            if (nArgs > 0) {
[6809]216              CompileInstructions(il, state, ds);
[6732]217            }
218            for (int i = 1; i < nArgs; i++) {
[6809]219              CompileInstructions(il, state, ds);
[6732]220              il.Emit(System.Reflection.Emit.OpCodes.Mul);
221            }
222            return;
223          }
224        case OpCodes.Div: {
225            if (nArgs == 1) {
226              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0);
[6809]227              CompileInstructions(il, state, ds);
[6732]228              il.Emit(System.Reflection.Emit.OpCodes.Div);
229              return;
230            }
231            if (nArgs > 0) {
[6809]232              CompileInstructions(il, state, ds);
[6732]233            }
234            for (int i = 1; i < nArgs; i++) {
[6809]235              CompileInstructions(il, state, ds);
[6732]236              il.Emit(System.Reflection.Emit.OpCodes.Div);
237            }
238            return;
239          }
240        case OpCodes.Average: {
[6809]241            CompileInstructions(il, state, ds);
[6732]242            for (int i = 1; i < nArgs; i++) {
[6809]243              CompileInstructions(il, state, ds);
[6732]244              il.Emit(System.Reflection.Emit.OpCodes.Add);
245            }
246            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, nArgs);
247            il.Emit(System.Reflection.Emit.OpCodes.Div);
248            return;
249          }
250        case OpCodes.Cos: {
[6809]251            CompileInstructions(il, state, ds);
[6732]252            il.Emit(System.Reflection.Emit.OpCodes.Call, cos);
253            return;
254          }
255        case OpCodes.Sin: {
[6809]256            CompileInstructions(il, state, ds);
[6732]257            il.Emit(System.Reflection.Emit.OpCodes.Call, sin);
258            return;
259          }
260        case OpCodes.Tan: {
[6809]261            CompileInstructions(il, state, ds);
[6732]262            il.Emit(System.Reflection.Emit.OpCodes.Call, tan);
263            return;
264          }
265        case OpCodes.Power: {
[6809]266            CompileInstructions(il, state, ds);
267            CompileInstructions(il, state, ds);
[6755]268            il.Emit(System.Reflection.Emit.OpCodes.Call, round);
[6732]269            il.Emit(System.Reflection.Emit.OpCodes.Call, power);
270            return;
271          }
272        case OpCodes.Root: {
[6809]273            CompileInstructions(il, state, ds);
[6755]274            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // 1 / round(...)
[6809]275            CompileInstructions(il, state, ds);
[6755]276            il.Emit(System.Reflection.Emit.OpCodes.Call, round);
277            il.Emit(System.Reflection.Emit.OpCodes.Div);
278            il.Emit(System.Reflection.Emit.OpCodes.Call, power);
279            return;
[6732]280          }
281        case OpCodes.Exp: {
[6809]282            CompileInstructions(il, state, ds);
[6732]283            il.Emit(System.Reflection.Emit.OpCodes.Call, exp);
284            return;
285          }
286        case OpCodes.Log: {
[6809]287            CompileInstructions(il, state, ds);
[6732]288            il.Emit(System.Reflection.Emit.OpCodes.Call, log);
289            return;
290          }
[7842]291        case OpCodes.Square: {
292            CompileInstructions(il, state, ds);
293            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0);
294            il.Emit(System.Reflection.Emit.OpCodes.Call, power);
295            return;
296          }
297        case OpCodes.SquareRoot: {
298            CompileInstructions(il, state, ds);
299            il.Emit(System.Reflection.Emit.OpCodes.Call, sqrt);
300            return;
301          }
302        case OpCodes.AiryA: {
303            CompileInstructions(il, state, ds);
304            il.Emit(System.Reflection.Emit.OpCodes.Call, airyA);
305            return;
306          }
307        case OpCodes.AiryB: {
308            CompileInstructions(il, state, ds);
309            il.Emit(System.Reflection.Emit.OpCodes.Call, airyB);
310            return;
311          }
312        case OpCodes.Bessel: {
313            CompileInstructions(il, state, ds);
314            il.Emit(System.Reflection.Emit.OpCodes.Call, bessel);
315            return;
316          }
317        case OpCodes.CosineIntegral: {
318            CompileInstructions(il, state, ds);
319            il.Emit(System.Reflection.Emit.OpCodes.Call, cosIntegral);
320            return;
321          }
322        case OpCodes.Dawson: {
323            CompileInstructions(il, state, ds);
324            il.Emit(System.Reflection.Emit.OpCodes.Call, dawson);
325            return;
326          }
327        case OpCodes.Erf: {
328            CompileInstructions(il, state, ds);
329            il.Emit(System.Reflection.Emit.OpCodes.Call, erf);
330            return;
331          }
332        case OpCodes.ExponentialIntegralEi: {
333            CompileInstructions(il, state, ds);
334            il.Emit(System.Reflection.Emit.OpCodes.Call, expIntegralEi);
335            return;
336          }
337        case OpCodes.FresnelCosineIntegral: {
338            CompileInstructions(il, state, ds);
339            il.Emit(System.Reflection.Emit.OpCodes.Call, fresnelCosIntegral);
340            return;
341          }
342        case OpCodes.FresnelSineIntegral: {
343            CompileInstructions(il, state, ds);
344            il.Emit(System.Reflection.Emit.OpCodes.Call, fresnelSinIntegral);
345            return;
346          }
347        case OpCodes.Gamma: {
348            CompileInstructions(il, state, ds);
349            il.Emit(System.Reflection.Emit.OpCodes.Call, gamma);
350            return;
351          }
352        case OpCodes.HyperbolicCosineIntegral: {
353            CompileInstructions(il, state, ds);
354            il.Emit(System.Reflection.Emit.OpCodes.Call, hypCosIntegral);
355            return;
356          }
357        case OpCodes.HyperbolicSineIntegral: {
358            CompileInstructions(il, state, ds);
359            il.Emit(System.Reflection.Emit.OpCodes.Call, hypSinIntegral);
360            return;
361          }
362        case OpCodes.Norm: {
363            CompileInstructions(il, state, ds);
364            il.Emit(System.Reflection.Emit.OpCodes.Call, norm);
365            return;
366          }
367        case OpCodes.Psi: {
368            CompileInstructions(il, state, ds);
369            il.Emit(System.Reflection.Emit.OpCodes.Call, psi);
370            return;
371          }
372        case OpCodes.SineIntegral: {
373            CompileInstructions(il, state, ds);
374            il.Emit(System.Reflection.Emit.OpCodes.Call, sinIntegral);
375            return;
376          }
[6732]377        case OpCodes.IfThenElse: {
378            Label end = il.DefineLabel();
379            Label c1 = il.DefineLabel();
[6809]380            CompileInstructions(il, state, ds);
[6732]381            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
382            il.Emit(System.Reflection.Emit.OpCodes.Cgt);
383            il.Emit(System.Reflection.Emit.OpCodes.Brfalse, c1);
[6809]384            CompileInstructions(il, state, ds);
[6732]385            il.Emit(System.Reflection.Emit.OpCodes.Br, end);
386            il.MarkLabel(c1);
[6809]387            CompileInstructions(il, state, ds);
[6732]388            il.MarkLabel(end);
389            return;
390          }
391        case OpCodes.AND: {
392            Label falseBranch = il.DefineLabel();
393            Label end = il.DefineLabel();
[6809]394            CompileInstructions(il, state, ds);
[6732]395            for (int i = 1; i < nArgs; i++) {
396              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
397              il.Emit(System.Reflection.Emit.OpCodes.Cgt);
398              il.Emit(System.Reflection.Emit.OpCodes.Brfalse, falseBranch);
[6809]399              CompileInstructions(il, state, ds);
[6732]400            }
401            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
402            il.Emit(System.Reflection.Emit.OpCodes.Cgt);
403            il.Emit(System.Reflection.Emit.OpCodes.Brfalse, falseBranch);
404            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // 1
405            il.Emit(System.Reflection.Emit.OpCodes.Br, end);
406            il.MarkLabel(falseBranch);
407            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // -1
408            il.Emit(System.Reflection.Emit.OpCodes.Neg);
409            il.MarkLabel(end);
410            return;
411          }
412        case OpCodes.OR: {
413            Label trueBranch = il.DefineLabel();
414            Label end = il.DefineLabel();
415            Label resultBranch = il.DefineLabel();
[6809]416            CompileInstructions(il, state, ds);
[6732]417            for (int i = 1; i < nArgs; i++) {
418              Label nextArgBranch = il.DefineLabel();
419              // complex definition because of special properties of NaN 
420              il.Emit(System.Reflection.Emit.OpCodes.Dup);
421              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // <= 0       
422              il.Emit(System.Reflection.Emit.OpCodes.Ble, nextArgBranch);
423              il.Emit(System.Reflection.Emit.OpCodes.Br, resultBranch);
424              il.MarkLabel(nextArgBranch);
425              il.Emit(System.Reflection.Emit.OpCodes.Pop);
[6809]426              CompileInstructions(il, state, ds);
[6732]427            }
428            il.MarkLabel(resultBranch);
429            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
430            il.Emit(System.Reflection.Emit.OpCodes.Cgt);
431            il.Emit(System.Reflection.Emit.OpCodes.Brtrue, trueBranch);
432            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // -1
433            il.Emit(System.Reflection.Emit.OpCodes.Neg);
434            il.Emit(System.Reflection.Emit.OpCodes.Br, end);
435            il.MarkLabel(trueBranch);
436            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // 1
437            il.MarkLabel(end);
438            return;
439          }
440        case OpCodes.NOT: {
[6809]441            CompileInstructions(il, state, ds);
[6732]442            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0); // > 0
443            il.Emit(System.Reflection.Emit.OpCodes.Cgt);
444            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
445            il.Emit(System.Reflection.Emit.OpCodes.Mul);
446            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // - 1
447            il.Emit(System.Reflection.Emit.OpCodes.Sub);
448            il.Emit(System.Reflection.Emit.OpCodes.Neg); // * -1
449            return;
450          }
[10910]451        case OpCodes.XOR: {
452            CompileInstructions(il, state, ds);
453            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
454            il.Emit(System.Reflection.Emit.OpCodes.Cgt);// > 0
455
456            for (int i = 1; i < nArgs; i++) {
457              CompileInstructions(il, state, ds);
458              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
459              il.Emit(System.Reflection.Emit.OpCodes.Cgt);// > 0
460              il.Emit(System.Reflection.Emit.OpCodes.Xor);
461            }
462            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
463            il.Emit(System.Reflection.Emit.OpCodes.Mul);
464            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // - 1
465            il.Emit(System.Reflection.Emit.OpCodes.Sub);
466            return;
467          }
[6732]468        case OpCodes.GT: {
[6809]469            CompileInstructions(il, state, ds);
470            CompileInstructions(il, state, ds);
471
[6732]472            il.Emit(System.Reflection.Emit.OpCodes.Cgt); // 1 (>) / 0 (otherwise)
473            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
474            il.Emit(System.Reflection.Emit.OpCodes.Mul);
475            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // - 1
476            il.Emit(System.Reflection.Emit.OpCodes.Sub);
477            return;
478          }
479        case OpCodes.LT: {
[6809]480            CompileInstructions(il, state, ds);
481            CompileInstructions(il, state, ds);
[6732]482            il.Emit(System.Reflection.Emit.OpCodes.Clt);
483            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // * 2
484            il.Emit(System.Reflection.Emit.OpCodes.Mul);
485            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 1.0); // - 1
486            il.Emit(System.Reflection.Emit.OpCodes.Sub);
487            return;
488          }
489        case OpCodes.TimeLag: {
[6809]490            LaggedTreeNode laggedTreeNode = (LaggedTreeNode)currentInstr.dynamicNode;
491            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row -= lag
492            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, laggedTreeNode.Lag);
493            il.Emit(System.Reflection.Emit.OpCodes.Add);
494            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
[6849]495            var prevLaggedContext = state.InLaggedContext;
496            state.InLaggedContext = true;
[6809]497            CompileInstructions(il, state, ds);
498            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row += lag
499            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, laggedTreeNode.Lag);
500            il.Emit(System.Reflection.Emit.OpCodes.Sub);
501            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
[6849]502            state.InLaggedContext = prevLaggedContext;
[6809]503            return;
[6732]504          }
505        case OpCodes.Integral: {
[6809]506            int savedPc = state.ProgramCounter;
507            LaggedTreeNode laggedTreeNode = (LaggedTreeNode)currentInstr.dynamicNode;
508            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row -= lag
509            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, laggedTreeNode.Lag);
510            il.Emit(System.Reflection.Emit.OpCodes.Add);
511            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
[6849]512            var prevLaggedContext = state.InLaggedContext;
513            state.InLaggedContext = true;
[6809]514            CompileInstructions(il, state, ds);
515            for (int l = laggedTreeNode.Lag; l < 0; l++) {
516              il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row += lag
517              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_1);
518              il.Emit(System.Reflection.Emit.OpCodes.Add);
519              il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
520              state.ProgramCounter = savedPc;
521              CompileInstructions(il, state, ds);
522              il.Emit(System.Reflection.Emit.OpCodes.Add);
523            }
[6849]524            state.InLaggedContext = prevLaggedContext;
[6809]525            return;
[6732]526          }
527
528        //mkommend: derivate calculation taken from:
529        //http://www.holoborodko.com/pavel/numerical-methods/numerical-derivative/smooth-low-noise-differentiators/
530        //one sided smooth differentiatior, N = 4
531        // y' = 1/8h (f_i + 2f_i-1, -2 f_i-3 - f_i-4)
532        case OpCodes.Derivative: {
[6809]533            int savedPc = state.ProgramCounter;
534            CompileInstructions(il, state, ds);
535            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row --
536            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_M1);
537            il.Emit(System.Reflection.Emit.OpCodes.Add);
538            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
539            state.ProgramCounter = savedPc;
[6849]540            var prevLaggedContext = state.InLaggedContext;
541            state.InLaggedContext = true;
[6809]542            CompileInstructions(il, state, ds);
543            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // f_0 + 2 * f_1
544            il.Emit(System.Reflection.Emit.OpCodes.Mul);
545            il.Emit(System.Reflection.Emit.OpCodes.Add);
546
547            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row -=2
548            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_2);
549            il.Emit(System.Reflection.Emit.OpCodes.Sub);
550            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
551            state.ProgramCounter = savedPc;
552            CompileInstructions(il, state, ds);
553            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 2.0); // f_0 + 2 * f_1 - 2 * f_3
554            il.Emit(System.Reflection.Emit.OpCodes.Mul);
555            il.Emit(System.Reflection.Emit.OpCodes.Sub);
556
557            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row --
558            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_M1);
559            il.Emit(System.Reflection.Emit.OpCodes.Add);
560            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
561            state.ProgramCounter = savedPc;
562            CompileInstructions(il, state, ds);
563            il.Emit(System.Reflection.Emit.OpCodes.Sub); // f_0 + 2 * f_1 - 2 * f_3 - f_4
564            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, 8.0); // / 8
565            il.Emit(System.Reflection.Emit.OpCodes.Div);
566
567            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // row +=4
568            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_4);
569            il.Emit(System.Reflection.Emit.OpCodes.Add);
570            il.Emit(System.Reflection.Emit.OpCodes.Starg, 0);
[6849]571            state.InLaggedContext = prevLaggedContext;
[6809]572            return;
[6732]573          }
574        case OpCodes.Call: {
[7842]575            throw new NotSupportedException(
576              "Automatically defined functions are not supported by the SymbolicDataAnalysisTreeILEmittingInterpreter. Either turn of ADFs or change the interpeter.");
[6732]577          }
578        case OpCodes.Arg: {
[7842]579            throw new NotSupportedException(
580              "Automatically defined functions are not supported by the SymbolicDataAnalysisTreeILEmittingInterpreter. Either turn of ADFs or change the interpeter.");
[6732]581          }
582        case OpCodes.Variable: {
[6741]583            VariableTreeNode varNode = (VariableTreeNode)currentInstr.dynamicNode;
[8798]584            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1); // load columns array
[9976]585            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)currentInstr.data);
[8798]586            // load correct column of the current variable
587            il.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref);
588            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // rowIndex
[6849]589            if (!state.InLaggedContext) {
590              il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
591              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.Weight); // load weight
592              il.Emit(System.Reflection.Emit.OpCodes.Mul);
593            } else {
594              var nanResult = il.DefineLabel();
595              var normalResult = il.DefineLabel();
596              il.Emit(System.Reflection.Emit.OpCodes.Dup);
597              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
598              il.Emit(System.Reflection.Emit.OpCodes.Blt, nanResult);
599              il.Emit(System.Reflection.Emit.OpCodes.Dup);
600              il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, ds.Rows);
601              il.Emit(System.Reflection.Emit.OpCodes.Bge, nanResult);
602              il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
603              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.Weight); // load weight
604              il.Emit(System.Reflection.Emit.OpCodes.Mul);
605              il.Emit(System.Reflection.Emit.OpCodes.Br, normalResult);
606              il.MarkLabel(nanResult);
607              il.Emit(System.Reflection.Emit.OpCodes.Pop); // rowIndex
[8798]608              il.Emit(System.Reflection.Emit.OpCodes.Pop); // column reference
[6849]609              il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, double.NaN);
610              il.MarkLabel(normalResult);
611            }
[6732]612            return;
613          }
614        case OpCodes.LagVariable: {
[6809]615            var nanResult = il.DefineLabel();
616            var normalResult = il.DefineLabel();
[6770]617            LaggedVariableTreeNode varNode = (LaggedVariableTreeNode)currentInstr.dynamicNode;
[8798]618            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_1); // load columns array
[9976]619            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, (int)currentInstr.data);
[8798]620            // load correct column of the current variable
621            il.Emit(System.Reflection.Emit.OpCodes.Ldelem_Ref);
[6770]622            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, varNode.Lag); // lag
[6849]623            il.Emit(System.Reflection.Emit.OpCodes.Ldarg_0); // rowIndex
624            il.Emit(System.Reflection.Emit.OpCodes.Add); // actualRowIndex = rowIndex + sampleOffset
[6809]625            il.Emit(System.Reflection.Emit.OpCodes.Dup);
626            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4_0);
627            il.Emit(System.Reflection.Emit.OpCodes.Blt, nanResult);
628            il.Emit(System.Reflection.Emit.OpCodes.Dup);
629            il.Emit(System.Reflection.Emit.OpCodes.Ldc_I4, ds.Rows);
630            il.Emit(System.Reflection.Emit.OpCodes.Bge, nanResult);
[6770]631            il.Emit(System.Reflection.Emit.OpCodes.Call, listGetValue);
632            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, varNode.Weight); // load weight
633            il.Emit(System.Reflection.Emit.OpCodes.Mul);
[6809]634            il.Emit(System.Reflection.Emit.OpCodes.Br, normalResult);
635            il.MarkLabel(nanResult);
[8798]636            il.Emit(System.Reflection.Emit.OpCodes.Pop); // sample index
637            il.Emit(System.Reflection.Emit.OpCodes.Pop); // column reference
[6809]638            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, double.NaN);
639            il.MarkLabel(normalResult);
[6770]640            return;
[6732]641          }
642        case OpCodes.Constant: {
643            ConstantTreeNode constNode = (ConstantTreeNode)currentInstr.dynamicNode;
644            il.Emit(System.Reflection.Emit.OpCodes.Ldc_R8, constNode.Value);
645            return;
646          }
647
648        //mkommend: this symbol uses the logistic function f(x) = 1 / (1 + e^(-alpha * x) )
649        //to determine the relative amounts of the true and false branch see http://en.wikipedia.org/wiki/Logistic_function
650        case OpCodes.VariableCondition: {
[7842]651            throw new NotSupportedException("Interpretation of symbol " + currentInstr.dynamicNode.Symbol.Name +
652                                            " is not supported by the SymbolicDataAnalysisTreeILEmittingInterpreter");
[6732]653          }
[7842]654        default:
655          throw new NotSupportedException("Interpretation of symbol " + currentInstr.dynamicNode.Symbol.Name +
656                                          " is not supported by the SymbolicDataAnalysisTreeILEmittingInterpreter");
[6732]657      }
658    }
659
[7842]660    public static double AiryA(double x) {
661      if (double.IsNaN(x)) return double.NaN;
662      double ai, aip, bi, bip;
663      alglib.airy(x, out ai, out aip, out bi, out bip);
664      return ai;
665    }
666
667    public static double AiryB(double x) {
668      if (double.IsNaN(x)) return double.NaN;
669      double ai, aip, bi, bip;
670      alglib.airy(x, out ai, out aip, out bi, out bip);
671      return bi;
672    }
673    public static double Dawson(double x) {
674      if (double.IsNaN(x)) return double.NaN;
675      return alglib.dawsonintegral(x);
676    }
677
678    public static double Gamma(double x) {
679      if (double.IsNaN(x)) return double.NaN;
680      return alglib.gammafunction(x);
681    }
682
683    public static double Psi(double x) {
684      if (double.IsNaN(x)) return double.NaN;
[8430]685      else if (x <= 0 && (Math.Floor(x) - x).IsAlmost(0)) return double.NaN;
[7842]686      return alglib.psi(x);
687    }
688
689    public static double ExpIntegralEi(double x) {
690      if (double.IsNaN(x)) return double.NaN;
691      return alglib.exponentialintegralei(x);
692    }
693
694    public static double SinIntegral(double x) {
695      if (double.IsNaN(x)) return double.NaN;
696      double si, ci;
697      alglib.sinecosineintegrals(x, out si, out ci);
698      return si;
699    }
700
701    public static double CosIntegral(double x) {
702      if (double.IsNaN(x)) return double.NaN;
703      double si, ci;
704      alglib.sinecosineintegrals(x, out si, out ci);
705      return ci;
706    }
707
708    public static double HypSinIntegral(double x) {
709      if (double.IsNaN(x)) return double.NaN;
710      double shi, chi;
711      alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
[8430]712      return shi;
[7842]713    }
714
715    public static double HypCosIntegral(double x) {
716      if (double.IsNaN(x)) return double.NaN;
717      double shi, chi;
718      alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
719      return chi;
720    }
721
722    public static double FresnelCosIntegral(double x) {
723      if (double.IsNaN(x)) return double.NaN;
724      double c = 0, s = 0;
725      alglib.fresnelintegral(x, ref c, ref s);
726      return c;
727    }
728
729    public static double FresnelSinIntegral(double x) {
730      if (double.IsNaN(x)) return double.NaN;
731      double c = 0, s = 0;
732      alglib.fresnelintegral(x, ref c, ref s);
733      return s;
734    }
735
736    public static double Norm(double x) {
737      if (double.IsNaN(x)) return double.NaN;
738      return alglib.normaldistribution(x);
739    }
740
741    public static double Erf(double x) {
742      if (double.IsNaN(x)) return double.NaN;
743      return alglib.errorfunction(x);
744    }
745
746    public static double Bessel(double x) {
747      if (double.IsNaN(x)) return double.NaN;
748      return alglib.besseli0(x);
749    }
[6732]750  }
751}
Note: See TracBrowser for help on using the repository browser.