internal double Evaluate( Cdef cdef, int row, long timestamp ) { stack.Clear(); byte[] tokens = cdef.Tokens; int[] dsIndices = cdef.DsIndices; double[] constants = cdef.Constants; Random autoRand = new Random(); double x1, x2, x3; for ( int i = 0; i < tokens.Length; i++ ) { switch ( tokens[i] ) { case TKN_CONSTANT: Push( constants[i] ); break; case TKN_DATASOURCE: Push( sources[ dsIndices[i] ].Get(row) ); break; case TKN_PLUS: Push(Pop() + Pop()); break; case TKN_MINUS: x2 = Pop(); x1 = Pop(); Push(x1 - x2); break; case TKN_MULTIPLY: Push(Pop() * Pop()); break; case TKN_DIVIDE: x2 = Pop(); x1 = Pop(); Push(x1 / x2); break; case TKN_MOD: x2 = Pop(); x1 = Pop(); Push(x1 % x2); break; case TKN_SIN: Push(Math.Sin(Pop())); break; case TKN_COS: Push(Math.Cos(Pop())); break; case TKN_LOG: Push(Math.Log(Pop())); break; case TKN_EXP: Push(Math.Exp(Pop())); break; case TKN_FLOOR: Push(Math.Floor(Pop())); break; case TKN_CEIL: Push(Math.Ceiling(Pop())); break; case TKN_ROUND: Push(Math.Round(Pop(), MidpointRounding.AwayFromZero)); break; case TKN_POW: x2 = Pop(); x1 = Pop(); Push(Math.Pow(x1, x2)); break; case TKN_ABS: Push(Math.Abs(Pop())); break; case TKN_SQRT: Push(Math.Sqrt(Pop())); break; case TKN_RANDOM: Push(autoRand.Next()); break; case TKN_LT: x2 = Pop(); x1 = Pop(); Push(x1 < x2? 1: 0); break; case TKN_LE: x2 = Pop(); x1 = Pop(); Push(x1 <= x2? 1: 0); break; case TKN_GT: x2 = Pop(); x1 = Pop(); Push(x1 > x2? 1: 0); break; case TKN_GE: x2 = Pop(); x1 = Pop(); Push(x1 >= x2? 1: 0); break; case TKN_EQ: x2 = Pop(); x1 = Pop(); Push(x1 == x2? 1: 0); break; case TKN_IF: x3 = Pop(); x2 = Pop(); x1 = Pop(); Push(x1 != 0 ? x2: x3); break; case TKN_MIN: Push(Math.Min(Pop(), Pop())); break; case TKN_MAX: Push(Math.Max(Pop(), Pop())); break; case TKN_LIMIT: double high = Pop(), low = Pop(), val = Pop(); Push(val < low || val > high? Double.NaN: val); break; case TKN_DUP: double x = Pop(); Push(x); Push(x); break; case TKN_EXC: x2 = Pop(); x1 = Pop(); Push(x2); Push(x1); break; case TKN_POP: Pop(); break; case TKN_UN: Push(Double.IsNaN(Pop())? 1: 0); break; case TKN_UNKN: Push(Double.NaN); break; case TKN_NOW: Push(Util.Time); break; case TKN_TIME: Push(timestamp); break; case TKN_PI: Push(Math.PI); break; case TKN_E: Push(Math.E); break; case TKN_AND: x2 = Pop(); x1 = Pop(); Push((x1 != 0 && x2 != 0)? 1: 0); break; case TKN_OR: x2 = Pop(); x1 = Pop(); Push((x1 != 0 || x2 != 0)? 1: 0); break; case TKN_XOR: x2 = Pop(); x1 = Pop(); Push(((x1 != 0 && x2 == 0) || (x1 == 0 && x2 != 0))? 1: 0); break; case TKN_SAMPLES: Push (cdef.SampleCount); break; case TKN_STEP: Push( step ); break; } } if (stack.Count != 1) throw new RrdException("RPN error, invalid stack length"); return Pop(); }
internal double Evaluate( Cdef cdef, int row, long timestamp ) { stack.Clear(); byte[] tokens = cdef.Tokens; int[] dsIndices = cdef.DsIndices; double[] constants = cdef.Constants; Random autoRand = new Random(); double x1, x2, x3; for ( int i = 0; i < tokens.Length; i++ ) { switch ( tokens[i] ) { case TKN_CONSTANT: Push( constants[i] ); break; case TKN_DATASOURCE: Push( sources[ dsIndices[i] ].Get(row) ); break; case TKN_PLUS: Push(Pop() + Pop()); break; case TKN_MINUS: x2 = Pop(); x1 = Pop(); Push(x1 - x2); break; case TKN_MULTIPLY: Push(Pop() * Pop()); break; case TKN_DIVIDE: x2 = Pop(); x1 = Pop(); Push(x1 / x2); break; case TKN_MOD: x2 = Pop(); x1 = Pop(); Push(x1 % x2); break; case TKN_SIN: Push(Math.Sin(Pop())); break; case TKN_COS: Push(Math.Cos(Pop())); break; case TKN_LOG: Push(Math.Log(Pop())); break; case TKN_EXP: Push(Math.Exp(Pop())); break; case TKN_FLOOR: Push(Math.Floor(Pop())); break; case TKN_CEIL: Push(Math.Ceiling(Pop())); break; case TKN_ROUND: Push(Math.Round(Pop(), MidpointRounding.AwayFromZero)); break; case TKN_POW: x2 = Pop(); x1 = Pop(); Push(Math.Pow(x1, x2)); break; case TKN_ABS: Push(Math.Abs(Pop())); break; case TKN_SQRT: Push(Math.Sqrt(Pop())); break; case TKN_RANDOM: Push(autoRand.Next()); break; case TKN_LT: x2 = Pop(); x1 = Pop(); Push(x1 < x2? 1: 0); break; case TKN_LE: x2 = Pop(); x1 = Pop(); Push(x1 <= x2? 1: 0); break; case TKN_GT: x2 = Pop(); x1 = Pop(); Push(x1 > x2? 1: 0); break; case TKN_GE: x2 = Pop(); x1 = Pop(); Push(x1 >= x2? 1: 0); break; case TKN_EQ: x2 = Pop(); x1 = Pop(); Push(x1 == x2? 1: 0); break; case TKN_IF: x3 = Pop(); x2 = Pop(); x1 = Pop(); Push(x1 != 0 ? x2: x3); break; case TKN_MIN: Push(Math.Min(Pop(), Pop())); break; case TKN_MAX: Push(Math.Max(Pop(), Pop())); break; case TKN_LIMIT: double high = Pop(), low = Pop(), val = Pop(); Push(val < low || val > high? Double.NaN: val); break; case TKN_DUP: double x = Pop(); Push(x); Push(x); break; case TKN_EXC: x2 = Pop(); x1 = Pop(); Push(x2); Push(x1); break; case TKN_POP: Pop(); break; case TKN_UN: Push(Double.IsNaN(Pop())? 1: 0); break; case TKN_UNKN: Push(Double.NaN); break; case TKN_NOW: Push(Util.Time); break; case TKN_TIME: Push(timestamp); break; case TKN_PI: Push(Math.PI); break; case TKN_E: Push(Math.E); break; case TKN_AND: x2 = Pop(); x1 = Pop(); Push((x1 != 0 && x2 != 0)? 1: 0); break; case TKN_OR: x2 = Pop(); x1 = Pop(); Push((x1 != 0 || x2 != 0)? 1: 0); break; case TKN_XOR: x2 = Pop(); x1 = Pop(); Push(((x1 != 0 && x2 == 0) || (x1 == 0 && x2 != 0))? 1: 0); break; case TKN_SAMPLES: Push (cdef.SampleCount); break; case TKN_STEP: Push( step ); break; case TKN_TREND: double seconds = Pop(); double value = Pop(); double trend = Double.NaN; // Is this the first value? if (this.TrendWindowStart == 0) this.TrendWindowStart = timestamp; // Add new value this.TrendValues.Add(value); // To we have a full window? if (timestamp >= this.TrendWindowStart + seconds) { //this.TrendWindowStart = timestamp; double sum = 0; // Sum up all values for (int v = 0; v < this.TrendValues.Count; v++) { sum += this.TrendValues[v]; } // Calc average, i.e. trend trend = sum / this.TrendValues.Count; // Remove oldest value this.TrendValues.RemoveAt(0); } // Return the calculated point Push(trend); break; } } if (stack.Count != 1) throw new RrdException("RPN error, invalid stack length"); return Pop(); }