Free cookie consent management tool by TermsFeed Policy Generator

Changeset 9871


Ignore:
Timestamp:
08/08/13 11:48:11 (11 years ago)
Author:
bburlacu
Message:

#2021: Replaced the opcode switch block in the Evaluate() method with an if-else block, as it apparently improves performance.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/sources/HeuristicLab.Problems.DataAnalysis.Symbolic/3.4/Interpreter/SymbolicDataAnalysisExpressionTreeLinearInterpreter.cs

    r9828 r9871  
    118118      for (int i = code.Length - 1; i >= 0; --i) {
    119119        if (code[i].skip) continue;
    120         #region opcode switch
     120        #region opcode if
    121121        var instr = code[i];
    122         switch (instr.opCode) {
    123           case OpCodes.Variable: {
    124               if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
    125               var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
    126               instr.value = ((IList<double>)instr.data)[row] * variableTreeNode.Weight;
    127             }
    128             break;
    129           case OpCodes.LagVariable: {
    130               var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
    131               int actualRow = row + laggedVariableTreeNode.Lag;
    132               if (actualRow < 0 || actualRow >= dataset.Rows)
    133                 instr.value = double.NaN;
    134               else
    135                 instr.value = ((IList<double>)instr.data)[actualRow] * laggedVariableTreeNode.Weight;
    136             }
    137             break;
    138           case OpCodes.VariableCondition: {
    139               if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
    140               var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode;
    141               double variableValue = ((IList<double>)instr.data)[row];
    142               double x = variableValue - variableConditionTreeNode.Threshold;
    143               double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
    144 
    145               double trueBranch = code[instr.childIndex].value;
    146               double falseBranch = code[instr.childIndex + 1].value;
    147 
    148               instr.value = trueBranch * p + falseBranch * (1 - p);
    149             }
    150             break;
    151           case OpCodes.Add: {
    152               double s = code[instr.childIndex].value;
    153               for (int j = 1; j != instr.nArguments; ++j) {
    154                 s += code[instr.childIndex + j].value;
    155               }
    156               instr.value = s;
    157             }
    158             break;
    159           case OpCodes.Sub: {
    160               double s = code[instr.childIndex].value;
    161               for (int j = 1; j != instr.nArguments; ++j) {
    162                 s -= code[instr.childIndex + j].value;
    163               }
    164               if (instr.nArguments == 1) s = -s;
    165               instr.value = s;
    166             }
    167             break;
    168           case OpCodes.Mul: {
    169               double p = code[instr.childIndex].value;
    170               for (int j = 1; j != instr.nArguments; ++j) {
    171                 p *= code[instr.childIndex + j].value;
    172               }
    173               instr.value = p;
    174             }
    175             break;
    176           case OpCodes.Div: {
    177               double p = code[instr.childIndex].value;
    178               for (int j = 1; j != instr.nArguments; ++j) {
    179                 p /= code[instr.childIndex + j].value;
    180               }
    181               if (instr.nArguments == 1) p = 1.0 / p;
    182               instr.value = p;
    183             }
    184             break;
    185           case OpCodes.Average: {
    186               double s = code[instr.childIndex].value;
    187               for (int j = 1; j != instr.nArguments; ++j) {
    188                 s += code[instr.childIndex + j].value;
    189               }
    190               instr.value = s / instr.nArguments;
    191             }
    192             break;
    193           case OpCodes.Cos: {
    194               instr.value = Math.Cos(code[instr.childIndex].value);
    195             }
    196             break;
    197           case OpCodes.Sin: {
    198               instr.value = Math.Sin(code[instr.childIndex].value);
    199             }
    200             break;
    201           case OpCodes.Tan: {
    202               instr.value = Math.Tan(code[instr.childIndex].value);
    203             }
    204             break;
    205           case OpCodes.Square: {
    206               instr.value = Math.Pow(code[instr.childIndex].value, 2);
    207             }
    208             break;
    209           case OpCodes.Power: {
    210               double x = code[instr.childIndex].value;
    211               double y = Math.Round(code[instr.childIndex + 1].value);
    212               instr.value = Math.Pow(x, y);
    213             }
    214             break;
    215           case OpCodes.SquareRoot: {
    216               instr.value = Math.Sqrt(code[instr.childIndex].value);
    217             }
    218             break;
    219           case OpCodes.Root: {
    220               double x = code[instr.childIndex].value;
    221               double y = code[instr.childIndex + 1].value;
    222               instr.value = Math.Pow(x, 1 / y);
    223             }
    224             break;
    225           case OpCodes.Exp: {
    226               instr.value = Math.Exp(code[instr.childIndex].value);
    227             }
    228             break;
    229           case OpCodes.Log: {
    230               instr.value = Math.Log(code[instr.childIndex].value);
    231             }
    232             break;
    233           case OpCodes.Gamma: {
    234               var x = code[instr.childIndex].value;
    235               instr.value = double.IsNaN(x) ? double.NaN : alglib.gammafunction(x);
    236             }
    237             break;
    238           case OpCodes.Psi: {
    239               var x = code[instr.childIndex].value;
    240               if (double.IsNaN(x)) instr.value = double.NaN;
    241               else if (x <= 0 && (Math.Floor(x) - x).IsAlmost(0)) instr.value = double.NaN;
    242               else instr.value = alglib.psi(x);
    243             }
    244             break;
    245           case OpCodes.Dawson: {
    246               var x = code[instr.childIndex].value;
    247               instr.value = double.IsNaN(x) ? double.NaN : alglib.dawsonintegral(x);
    248             }
    249             break;
    250           case OpCodes.ExponentialIntegralEi: {
    251               var x = code[instr.childIndex].value;
    252               instr.value = double.IsNaN(x) ? double.NaN : alglib.exponentialintegralei(x);
    253             }
    254             break;
    255           case OpCodes.SineIntegral: {
    256               double si, ci;
    257               var x = code[instr.childIndex].value;
    258               if (double.IsNaN(x)) instr.value = double.NaN;
    259               else {
    260                 alglib.sinecosineintegrals(x, out si, out ci);
    261                 instr.value = si;
    262               }
    263             }
    264             break;
    265           case OpCodes.CosineIntegral: {
    266               double si, ci;
    267               var x = code[instr.childIndex].value;
    268               if (double.IsNaN(x)) instr.value = double.NaN;
    269               else {
    270                 alglib.sinecosineintegrals(x, out si, out ci);
    271                 instr.value = ci;
    272               }
    273             }
    274             break;
    275           case OpCodes.HyperbolicSineIntegral: {
    276               double shi, chi;
    277               var x = code[instr.childIndex].value;
    278               if (double.IsNaN(x)) instr.value = double.NaN;
    279               else {
    280                 alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
    281                 instr.value = shi;
    282               }
    283             }
    284             break;
    285           case OpCodes.HyperbolicCosineIntegral: {
    286               double shi, chi;
    287               var x = code[instr.childIndex].value;
    288               if (double.IsNaN(x)) instr.value = double.NaN;
    289               else {
    290                 alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
    291                 instr.value = chi;
    292               }
    293             }
    294             break;
    295           case OpCodes.FresnelCosineIntegral: {
    296               double c = 0, s = 0;
    297               var x = code[instr.childIndex].value;
    298               if (double.IsNaN(x)) instr.value = double.NaN;
    299               else {
    300                 alglib.fresnelintegral(x, ref c, ref s);
    301                 instr.value = c;
    302               }
    303             }
    304             break;
    305           case OpCodes.FresnelSineIntegral: {
    306               double c = 0, s = 0;
    307               var x = code[instr.childIndex].value;
    308               if (double.IsNaN(x)) instr.value = double.NaN;
    309               else {
    310                 alglib.fresnelintegral(x, ref c, ref s);
    311                 instr.value = s;
    312               }
    313             }
    314             break;
    315           case OpCodes.AiryA: {
    316               double ai, aip, bi, bip;
    317               var x = code[instr.childIndex].value;
    318               if (double.IsNaN(x)) instr.value = double.NaN;
    319               else {
    320                 alglib.airy(x, out ai, out aip, out bi, out bip);
    321                 instr.value = ai;
    322               }
    323             }
    324             break;
    325           case OpCodes.AiryB: {
    326               double ai, aip, bi, bip;
    327               var x = code[instr.childIndex].value;
    328               if (double.IsNaN(x)) instr.value = double.NaN;
    329               else {
    330                 alglib.airy(x, out ai, out aip, out bi, out bip);
    331                 instr.value = bi;
    332               }
    333             }
    334             break;
    335           case OpCodes.Norm: {
    336               var x = code[instr.childIndex].value;
    337               if (double.IsNaN(x)) instr.value = double.NaN;
    338               else instr.value = alglib.normaldistribution(x);
    339             }
    340             break;
    341           case OpCodes.Erf: {
    342               var x = code[instr.childIndex].value;
    343               if (double.IsNaN(x)) instr.value = double.NaN;
    344               else instr.value = alglib.errorfunction(x);
    345             }
    346             break;
    347           case OpCodes.Bessel: {
    348               var x = code[instr.childIndex].value;
    349               if (double.IsNaN(x)) instr.value = double.NaN;
    350               else instr.value = alglib.besseli0(x);
    351             }
    352             break;
    353           case OpCodes.IfThenElse: {
    354               double condition = code[instr.childIndex].value;
    355               double result;
    356               if (condition > 0.0) {
    357                 result = code[instr.childIndex + 1].value;
    358               } else {
    359                 result = code[instr.childIndex + 2].value;
    360               }
    361               instr.value = result;
    362             }
    363             break;
    364           case OpCodes.AND: {
    365               double result = code[instr.childIndex].value;
    366               for (int j = 1; j < instr.nArguments; j++) {
    367                 if (result > 0.0) result = code[instr.childIndex + j].value;
    368                 else break;
    369               }
    370               instr.value = result > 0.0 ? 1.0 : -1.0;
    371             }
    372             break;
    373           case OpCodes.OR: {
    374               double result = code[instr.childIndex].value;
    375               for (int j = 1; j < instr.nArguments; j++) {
    376                 if (result <= 0.0) result = code[instr.childIndex + j].value;
    377                 else break;
    378               }
    379               instr.value = result > 0.0 ? 1.0 : -1.0;
    380             }
    381             break;
    382           case OpCodes.NOT: {
    383               instr.value = code[instr.childIndex].value > 0.0 ? -1.0 : 1.0;
    384             }
    385             break;
    386           case OpCodes.GT: {
    387               double x = code[instr.childIndex].value;
    388               double y = code[instr.childIndex + 1].value;
    389               instr.value = x > y ? 1.0 : -1.0;
    390             }
    391             break;
    392           case OpCodes.LT: {
    393               double x = code[instr.childIndex].value;
    394               double y = code[instr.childIndex + 1].value;
    395               instr.value = x < y ? 1.0 : -1.0;
    396             }
    397             break;
    398           case OpCodes.TimeLag:
    399           case OpCodes.Integral:
    400           case OpCodes.Derivative: {
    401               var state = (InterpreterState)instr.data;
    402               state.Reset();
    403               instr.value = interpreter.Evaluate(dataset, ref row, state);
    404             }
    405             break;
    406           default:
    407             var errorText = string.Format("The {0} symbol is not supported by the linear interpreter. To support this symbol, please use the SymbolicDataAnalysisExpressionTreeInterpreter.", instr.dynamicNode.Symbol.Name);
    408             throw new NotSupportedException(errorText);
     122        if (instr.opCode == OpCodes.Variable) {
     123          if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
     124          var variableTreeNode = (VariableTreeNode)instr.dynamicNode;
     125          instr.value = ((IList<double>)instr.data)[row] * variableTreeNode.Weight;
     126        } else if (instr.opCode == OpCodes.LagVariable) {
     127          var laggedVariableTreeNode = (LaggedVariableTreeNode)instr.dynamicNode;
     128          int actualRow = row + laggedVariableTreeNode.Lag;
     129          if (actualRow < 0 || actualRow >= dataset.Rows)
     130            instr.value = double.NaN;
     131          else
     132            instr.value = ((IList<double>)instr.data)[actualRow] * laggedVariableTreeNode.Weight;
     133        } else if (instr.opCode == OpCodes.VariableCondition) {
     134          if (row < 0 || row >= dataset.Rows) instr.value = double.NaN;
     135          var variableConditionTreeNode = (VariableConditionTreeNode)instr.dynamicNode;
     136          double variableValue = ((IList<double>)instr.data)[row];
     137          double x = variableValue - variableConditionTreeNode.Threshold;
     138          double p = 1 / (1 + Math.Exp(-variableConditionTreeNode.Slope * x));
     139
     140          double trueBranch = code[instr.childIndex].value;
     141          double falseBranch = code[instr.childIndex + 1].value;
     142
     143          instr.value = trueBranch * p + falseBranch * (1 - p);
     144        } else if (instr.opCode == OpCodes.Add) {
     145          double s = code[instr.childIndex].value;
     146          for (int j = 1; j != instr.nArguments; ++j) {
     147            s += code[instr.childIndex + j].value;
     148          }
     149          instr.value = s;
     150        } else if (instr.opCode == OpCodes.Sub) {
     151          double s = code[instr.childIndex].value;
     152          for (int j = 1; j != instr.nArguments; ++j) {
     153            s -= code[instr.childIndex + j].value;
     154          }
     155          if (instr.nArguments == 1) s = -s;
     156          instr.value = s;
     157        } else if (instr.opCode == OpCodes.Mul) {
     158          double p = code[instr.childIndex].value;
     159          for (int j = 1; j != instr.nArguments; ++j) {
     160            p *= code[instr.childIndex + j].value;
     161          }
     162          instr.value = p;
     163        } else if (instr.opCode == OpCodes.Div) {
     164          double p = code[instr.childIndex].value;
     165          for (int j = 1; j != instr.nArguments; ++j) {
     166            p /= code[instr.childIndex + j].value;
     167          }
     168          if (instr.nArguments == 1) p = 1.0 / p;
     169          instr.value = p;
     170        } else if (instr.opCode == OpCodes.Average) {
     171          double s = code[instr.childIndex].value;
     172          for (int j = 1; j != instr.nArguments; ++j) {
     173            s += code[instr.childIndex + j].value;
     174          }
     175          instr.value = s / instr.nArguments;
     176        } else if (instr.opCode == OpCodes.Cos) {
     177          instr.value = Math.Cos(code[instr.childIndex].value);
     178        } else if (instr.opCode == OpCodes.Sin) {
     179          instr.value = Math.Sin(code[instr.childIndex].value);
     180        } else if (instr.opCode == OpCodes.Tan) {
     181          instr.value = Math.Tan(code[instr.childIndex].value);
     182        } else if (instr.opCode == OpCodes.Square) {
     183          instr.value = Math.Pow(code[instr.childIndex].value, 2);
     184        } else if (instr.opCode == OpCodes.Power) {
     185          double x = code[instr.childIndex].value;
     186          double y = Math.Round(code[instr.childIndex + 1].value);
     187          instr.value = Math.Pow(x, y);
     188        } else if (instr.opCode == OpCodes.SquareRoot) {
     189          instr.value = Math.Sqrt(code[instr.childIndex].value);
     190        } else if (instr.opCode == OpCodes.Root) {
     191          double x = code[instr.childIndex].value;
     192          double y = code[instr.childIndex + 1].value;
     193          instr.value = Math.Pow(x, 1 / y);
     194        } else if (instr.opCode == OpCodes.Exp) {
     195          instr.value = Math.Exp(code[instr.childIndex].value);
     196        } else if (instr.opCode == OpCodes.Log) {
     197          instr.value = Math.Log(code[instr.childIndex].value);
     198        } else if (instr.opCode == OpCodes.Gamma) {
     199          var x = code[instr.childIndex].value;
     200          instr.value = double.IsNaN(x) ? double.NaN : alglib.gammafunction(x);
     201        } else if (instr.opCode == OpCodes.Psi) {
     202          var x = code[instr.childIndex].value;
     203          if (double.IsNaN(x)) instr.value = double.NaN;
     204          else if (x <= 0 && (Math.Floor(x) - x).IsAlmost(0)) instr.value = double.NaN;
     205          else instr.value = alglib.psi(x);
     206        } else if (instr.opCode == OpCodes.Dawson) {
     207          var x = code[instr.childIndex].value;
     208          instr.value = double.IsNaN(x) ? double.NaN : alglib.dawsonintegral(x);
     209        } else if (instr.opCode == OpCodes.ExponentialIntegralEi) {
     210          var x = code[instr.childIndex].value;
     211          instr.value = double.IsNaN(x) ? double.NaN : alglib.exponentialintegralei(x);
     212        } else if (instr.opCode == OpCodes.SineIntegral) {
     213          double si, ci;
     214          var x = code[instr.childIndex].value;
     215          if (double.IsNaN(x)) instr.value = double.NaN;
     216          else {
     217            alglib.sinecosineintegrals(x, out si, out ci);
     218            instr.value = si;
     219          }
     220        } else if (instr.opCode == OpCodes.CosineIntegral) {
     221          double si, ci;
     222          var x = code[instr.childIndex].value;
     223          if (double.IsNaN(x)) instr.value = double.NaN;
     224          else {
     225            alglib.sinecosineintegrals(x, out si, out ci);
     226            instr.value = ci;
     227          }
     228        } else if (instr.opCode == OpCodes.HyperbolicSineIntegral) {
     229          double shi, chi;
     230          var x = code[instr.childIndex].value;
     231          if (double.IsNaN(x)) instr.value = double.NaN;
     232          else {
     233            alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
     234            instr.value = shi;
     235          }
     236        } else if (instr.opCode == OpCodes.HyperbolicCosineIntegral) {
     237          double shi, chi;
     238          var x = code[instr.childIndex].value;
     239          if (double.IsNaN(x)) instr.value = double.NaN;
     240          else {
     241            alglib.hyperbolicsinecosineintegrals(x, out shi, out chi);
     242            instr.value = chi;
     243          }
     244        } else if (instr.opCode == OpCodes.FresnelCosineIntegral) {
     245          double c = 0, s = 0;
     246          var x = code[instr.childIndex].value;
     247          if (double.IsNaN(x)) instr.value = double.NaN;
     248          else {
     249            alglib.fresnelintegral(x, ref c, ref s);
     250            instr.value = c;
     251          }
     252        } else if (instr.opCode == OpCodes.FresnelSineIntegral) {
     253          double c = 0, s = 0;
     254          var x = code[instr.childIndex].value;
     255          if (double.IsNaN(x)) instr.value = double.NaN;
     256          else {
     257            alglib.fresnelintegral(x, ref c, ref s);
     258            instr.value = s;
     259          }
     260        } else if (instr.opCode == OpCodes.AiryA) {
     261          double ai, aip, bi, bip;
     262          var x = code[instr.childIndex].value;
     263          if (double.IsNaN(x)) instr.value = double.NaN;
     264          else {
     265            alglib.airy(x, out ai, out aip, out bi, out bip);
     266            instr.value = ai;
     267          }
     268        } else if (instr.opCode == OpCodes.AiryB) {
     269          double ai, aip, bi, bip;
     270          var x = code[instr.childIndex].value;
     271          if (double.IsNaN(x)) instr.value = double.NaN;
     272          else {
     273            alglib.airy(x, out ai, out aip, out bi, out bip);
     274            instr.value = bi;
     275          }
     276        } else if (instr.opCode == OpCodes.Norm) {
     277          var x = code[instr.childIndex].value;
     278          if (double.IsNaN(x)) instr.value = double.NaN;
     279          else instr.value = alglib.normaldistribution(x);
     280        } else if (instr.opCode == OpCodes.Erf) {
     281          var x = code[instr.childIndex].value;
     282          if (double.IsNaN(x)) instr.value = double.NaN;
     283          else instr.value = alglib.errorfunction(x);
     284        } else if (instr.opCode == OpCodes.Bessel) {
     285          var x = code[instr.childIndex].value;
     286          if (double.IsNaN(x)) instr.value = double.NaN;
     287          else instr.value = alglib.besseli0(x);
     288        } else if (instr.opCode == OpCodes.IfThenElse) {
     289          double condition = code[instr.childIndex].value;
     290          double result;
     291          if (condition > 0.0) {
     292            result = code[instr.childIndex + 1].value;
     293          } else {
     294            result = code[instr.childIndex + 2].value;
     295          }
     296          instr.value = result;
     297        } else if (instr.opCode == OpCodes.AND) {
     298          double result = code[instr.childIndex].value;
     299          for (int j = 1; j < instr.nArguments; j++) {
     300            if (result > 0.0) result = code[instr.childIndex + j].value;
     301            else break;
     302          }
     303          instr.value = result > 0.0 ? 1.0 : -1.0;
     304        } else if (instr.opCode == OpCodes.OR) {
     305          double result = code[instr.childIndex].value;
     306          for (int j = 1; j < instr.nArguments; j++) {
     307            if (result <= 0.0) result = code[instr.childIndex + j].value;
     308            else break;
     309          }
     310          instr.value = result > 0.0 ? 1.0 : -1.0;
     311        } else if (instr.opCode == OpCodes.NOT) {
     312          instr.value = code[instr.childIndex].value > 0.0 ? -1.0 : 1.0;
     313        } else if (instr.opCode == OpCodes.GT) {
     314          double x = code[instr.childIndex].value;
     315          double y = code[instr.childIndex + 1].value;
     316          instr.value = x > y ? 1.0 : -1.0;
     317        } else if (instr.opCode == OpCodes.LT) {
     318          double x = code[instr.childIndex].value;
     319          double y = code[instr.childIndex + 1].value;
     320          instr.value = x < y ? 1.0 : -1.0;
     321        } else if (instr.opCode == OpCodes.TimeLag || instr.opCode == OpCodes.Derivative || instr.opCode == OpCodes.Integral) {
     322          var state = (InterpreterState)instr.data;
     323          state.Reset();
     324          instr.value = interpreter.Evaluate(dataset, ref row, state);
     325        } else {
     326          var errorText = string.Format("The {0} symbol is not supported by the linear interpreter. To support this symbol, please use the SymbolicDataAnalysisExpressionTreeInterpreter.", instr.dynamicNode.Symbol.Name);
     327          throw new NotSupportedException(errorText);
    409328        }
    410329        #endregion
Note: See TracChangeset for help on using the changeset viewer.