1 25 package org.jrobin.graph; 26 27 import java.util.ArrayList ; 28 29 import org.jrobin.core.Util; 30 import org.jrobin.core.RrdException; 31 32 38 class RpnCalculator 39 { 40 public static final byte TKN_CONSTANT = 0; 45 public static final byte TKN_DATASOURCE = 1; 46 public static final byte TKN_PLUS = 2; 47 public static final byte TKN_MINUS = 3; 48 public static final byte TKN_MULTIPLY = 4; 49 public static final byte TKN_DIVIDE = 5; 50 public static final byte TKN_MOD = 6; 51 public static final byte TKN_SIN = 7; 52 public static final byte TKN_COS = 8; 53 public static final byte TKN_LOG = 9; 54 public static final byte TKN_EXP = 10; 55 public static final byte TKN_FLOOR = 11; 56 public static final byte TKN_CEIL = 12; 57 public static final byte TKN_ROUND = 13; 58 public static final byte TKN_POW = 14; 59 public static final byte TKN_ABS = 15; 60 public static final byte TKN_SQRT = 16; 61 public static final byte TKN_RANDOM = 17; 62 public static final byte TKN_LT = 18; 63 public static final byte TKN_LE = 19; 64 public static final byte TKN_GT = 20; 65 public static final byte TKN_GE = 21; 66 public static final byte TKN_EQ = 22; 67 public static final byte TKN_IF = 23; 68 public static final byte TKN_MIN = 24; 69 public static final byte TKN_MAX = 25; 70 public static final byte TKN_LIMIT = 26; 71 public static final byte TKN_DUP = 27; 72 public static final byte TKN_EXC = 28; 73 public static final byte TKN_POP = 29; 74 public static final byte TKN_UN = 30; 75 public static final byte TKN_UNKN = 31; 76 public static final byte TKN_NOW = 32; 77 public static final byte TKN_TIME = 33; 78 public static final byte TKN_PI = 34; 79 public static final byte TKN_E = 35; 80 public static final byte TKN_AND = 36; 81 public static final byte TKN_OR = 37; 82 public static final byte TKN_XOR = 38; 83 public static final byte TKN_SAMPLES = 39; 84 public static final byte TKN_STEP = 40; 85 86 private double step; 87 private Source[] sources; 88 private ArrayList stack = new ArrayList (); 89 90 91 99 RpnCalculator( Source[] sources, double step ) 100 { 101 this.sources = sources; 102 this.step = step; 103 } 104 105 106 117 public double evaluate( Cdef cdef, int row, long timestamp ) throws RrdException 118 { 119 stack.clear(); 120 121 byte[] tokens = cdef.getTokens(); 122 int[] dsIndices = cdef.getDsIndices(); 123 double[] constants = cdef.getConstants(); 124 125 double x1, x2, x3; 126 127 for ( int i = 0; i < tokens.length; i++ ) 128 { 129 switch ( tokens[i] ) 130 { 131 case TKN_CONSTANT: 132 push( constants[i] ); 133 break; 134 135 case TKN_DATASOURCE: 136 push( sources[ dsIndices[i] ].get(row) ); 137 break; 138 139 case TKN_PLUS: 140 push(pop() + pop()); 141 break; 142 143 case TKN_MINUS: 144 x2 = pop(); 145 x1 = pop(); 146 push(x1 - x2); 147 break; 148 149 case TKN_MULTIPLY: 150 push(pop() * pop()); 151 break; 152 153 case TKN_DIVIDE: 154 x2 = pop(); 155 x1 = pop(); 156 push(x1 / x2); 157 break; 158 159 case TKN_MOD: 160 x2 = pop(); 161 x1 = pop(); 162 push(x1 % x2); 163 break; 164 165 case TKN_SIN: 166 push(Math.sin(pop())); 167 break; 168 169 case TKN_COS: 170 push(Math.cos(pop())); 171 break; 172 173 case TKN_LOG: 174 push(Math.log(pop())); 175 break; 176 177 case TKN_EXP: 178 push(Math.exp(pop())); 179 break; 180 181 case TKN_FLOOR: 182 push(Math.floor(pop())); 183 break; 184 185 case TKN_CEIL: 186 push(Math.ceil(pop())); 187 break; 188 189 case TKN_ROUND: 190 push(Math.round(pop())); 191 break; 192 193 case TKN_POW: 194 x2 = pop(); 195 x1 = pop(); 196 push(Math.pow(x1, x2)); 197 break; 198 199 case TKN_ABS: 200 push(Math.abs(pop())); 201 break; 202 203 case TKN_SQRT: 204 push(Math.sqrt(pop())); 205 break; 206 207 case TKN_RANDOM: 208 push(Math.random()); 209 break; 210 211 case TKN_LT: 212 x2 = pop(); 213 x1 = pop(); 214 push(x1 < x2? 1: 0); 215 break; 216 217 case TKN_LE: 218 x2 = pop(); 219 x1 = pop(); 220 push(x1 <= x2? 1: 0); 221 break; 222 223 case TKN_GT: 224 x2 = pop(); 225 x1 = pop(); 226 push(x1 > x2? 1: 0); 227 break; 228 229 case TKN_GE: 230 x2 = pop(); 231 x1 = pop(); 232 push(x1 >= x2? 1: 0); 233 break; 234 235 case TKN_EQ: 236 x2 = pop(); 237 x1 = pop(); 238 push(x1 == x2? 1: 0); 239 break; 240 241 case TKN_IF: 242 x3 = pop(); 243 x2 = pop(); 244 x1 = pop(); 245 push(x1 != 0 ? x2: x3); 246 break; 247 248 case TKN_MIN: 249 push(Math.min(pop(), pop())); 250 break; 251 252 case TKN_MAX: 253 push(Math.max(pop(), pop())); 254 break; 255 256 case TKN_LIMIT: 257 double high = pop(), low = pop(), value = pop(); 258 push(value < low || value > high? Double.NaN: value); 259 break; 260 261 case TKN_DUP: 262 double x = pop(); 263 push(x); 264 push(x); 265 break; 266 267 case TKN_EXC: 268 x2 = pop(); 269 x1 = pop(); 270 push(x2); 271 push(x1); 272 break; 273 274 case TKN_POP: 275 pop(); 276 break; 277 278 case TKN_UN: 279 push(Double.isNaN(pop())? 1: 0); 280 break; 281 282 case TKN_UNKN: 283 push(Double.NaN); 284 break; 285 286 case TKN_NOW: 287 push(Util.getTime()); 288 break; 289 290 case TKN_TIME: 291 push(timestamp); 292 break; 293 294 case TKN_PI: 295 push(Math.PI); 296 break; 297 298 case TKN_E: 299 push(Math.E); 300 break; 301 302 case TKN_AND: 303 x2 = pop(); 304 x1 = pop(); 305 push((x1 != 0 && x2 != 0)? 1: 0); 306 break; 307 308 case TKN_OR: 309 x2 = pop(); 310 x1 = pop(); 311 push((x1 != 0 || x2 != 0)? 1: 0); 312 break; 313 314 case TKN_XOR: 315 x2 = pop(); 316 x1 = pop(); 317 push(((x1 != 0 && x2 == 0) || (x1 == 0 && x2 != 0))? 1: 0); 318 break; 319 320 case TKN_SAMPLES: 321 push( cdef.getSampleCount() ); 322 break; 323 324 case TKN_STEP: 325 push( step ); 326 break; 327 } 328 } 329 330 if (stack.size() != 1) 331 throw new RrdException("RPN error, invalid stack length"); 332 333 return pop(); 334 } 335 336 337 344 private void push( double value ) 345 { 346 stack.add( new Double (value) ); 347 } 348 349 354 private double pop() throws RrdException 355 { 356 int last = stack.size() - 1; 357 if ( last < 0 ) 358 throw new RrdException("POP failed, stack empty"); 359 360 Double lastValue = (Double ) stack.remove(last); 361 362 return lastValue.doubleValue(); 363 } 364 365 } 366 | Popular Tags |