diff options
author | Pim van den Berg | 2013-05-10 21:36:54 +0200 |
---|---|---|
committer | Pim van den Berg | 2013-05-10 21:36:54 +0200 |
commit | 0163faefef02207ad0ea3330af688103633293ff (patch) | |
tree | c407fca93a3418af59c4c7133327f5bc1630fba5 /js/RrdRpn.js | |
parent | Merge pull request #5 from mce35/nut (diff) | |
download | apt-panopticon_cgp-0163faefef02207ad0ea3330af688103633293ff.zip apt-panopticon_cgp-0163faefef02207ad0ea3330af688103633293ff.tar.gz apt-panopticon_cgp-0163faefef02207ad0ea3330af688103633293ff.tar.bz2 apt-panopticon_cgp-0163faefef02207ad0ea3330af688103633293ff.tar.xz |
import js directory from jsrrdgraph for client side graph rendering
Source: https://github.com/manuelluis/jsrrdgraph@276b880
Diffstat (limited to 'js/RrdRpn.js')
-rw-r--r-- | js/RrdRpn.js | 616 |
1 files changed, 616 insertions, 0 deletions
diff --git a/js/RrdRpn.js b/js/RrdRpn.js new file mode 100644 index 0000000..cbb5e8f --- /dev/null +++ b/js/RrdRpn.js | |||
@@ -0,0 +1,616 @@ | |||
1 | /** | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the Free | ||
5 | * Software Foundation; either version 2 of the License, or (at your option) | ||
6 | * any later version. | ||
7 | * | ||
8 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | |||
13 | * You should have received a copy of the GNU General Public License along | ||
14 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA | ||
16 | |||
17 | * RRDtool 1.4.5 Copyright by Tobi Oetiker, 1997-2010 | ||
18 | * | ||
19 | * Convert to javascript: Manuel Sanmartin <manuel.luis at gmail.com> | ||
20 | **/ | ||
21 | |||
22 | "use strict"; | ||
23 | |||
24 | /** | ||
25 | * RrdRpnError | ||
26 | * @constructor | ||
27 | */ | ||
28 | var RrdRpnError = function (message) | ||
29 | { | ||
30 | this.prototype = Error.prototype; | ||
31 | this.name = "RrdRpnError"; | ||
32 | this.message = (message) ? message : "RPN stack underflow"; | ||
33 | }; | ||
34 | |||
35 | /** | ||
36 | * RrdRpn | ||
37 | * @constructor | ||
38 | */ | ||
39 | var RrdRpn = function (str_expr, gdes) /* parser */ | ||
40 | { | ||
41 | var steps = -1; | ||
42 | var expr; | ||
43 | var exprs = str_expr.split(','); | ||
44 | |||
45 | this.rpnexpr = str_expr; | ||
46 | this.rpnp = []; | ||
47 | this.rpnstack = null; | ||
48 | |||
49 | for(var i=0, len=exprs.length; i < len; i++) { | ||
50 | expr=exprs[i].toUpperCase(); | ||
51 | |||
52 | steps++; | ||
53 | this.rpnp[steps] = {}; | ||
54 | |||
55 | if (!isNaN(expr)) { | ||
56 | this.rpnp[steps].op = RrdRpn.OP_NUMBER; | ||
57 | this.rpnp[steps].val = parseFloat(expr); | ||
58 | } | ||
59 | else if (expr === '+') this.rpnp[steps].op = RrdRpn.OP_ADD; | ||
60 | else if (expr === '-') this.rpnp[steps].op = RrdRpn.OP_SUB; | ||
61 | else if (expr === '*') this.rpnp[steps].op = RrdRpn.OP_MUL; | ||
62 | else if (expr === '/') this.rpnp[steps].op = RrdRpn.OP_DIV; | ||
63 | else if (expr === '%') this.rpnp[steps].op = RrdRpn.OP_MOD; | ||
64 | else if (expr === 'SIN') this.rpnp[steps].op = RrdRpn.OP_SIN; | ||
65 | else if (expr === 'COS') this.rpnp[steps].op = RrdRpn.OP_COS; | ||
66 | else if (expr === 'LOG') this.rpnp[steps].op = RrdRpn.OP_LOG; | ||
67 | else if (expr === 'FLOOR') this.rpnp[steps].op = RrdRpn.OP_FLOOR; | ||
68 | else if (expr === 'CEIL') this.rpnp[steps].op = RrdRpn.OP_CEIL; | ||
69 | else if (expr === 'EXP') this.rpnp[steps].op = RrdRpn.OP_EXP; | ||
70 | else if (expr === 'DUP') this.rpnp[steps].op = RrdRpn.OP_DUP; | ||
71 | else if (expr === 'EXC') this.rpnp[steps].op = RrdRpn.OP_EXC; | ||
72 | else if (expr === 'POP') this.rpnp[steps].op = RrdRpn.OP_POP; | ||
73 | else if (expr === 'LTIME') this.rpnp[steps].op = RrdRpn.OP_LTIME; | ||
74 | else if (expr === 'LT') this.rpnp[steps].op = RrdRpn.OP_LT; | ||
75 | else if (expr === 'LE') this.rpnp[steps].op = RrdRpn.OP_LE; | ||
76 | else if (expr === 'GT') this.rpnp[steps].op = RrdRpn.OP_GT; | ||
77 | else if (expr === 'GE') this.rpnp[steps].op = RrdRpn.OP_GE; | ||
78 | else if (expr === 'EQ') this.rpnp[steps].op = RrdRpn.OP_EQ; | ||
79 | else if (expr === 'IF') this.rpnp[steps].op = RrdRpn.OP_IF; | ||
80 | else if (expr === 'MIN') this.rpnp[steps].op = RrdRpn.OP_MIN; | ||
81 | else if (expr === 'MAX') this.rpnp[steps].op = RrdRpn.OP_MAX; | ||
82 | else if (expr === 'LIMIT') this.rpnp[steps].op = RrdRpn.OP_LIMIT; | ||
83 | else if (expr === 'UNKN') this.rpnp[steps].op = RrdRpn.OP_UNKN; | ||
84 | else if (expr === 'UN') this.rpnp[steps].op = RrdRpn.OP_UN; | ||
85 | else if (expr === 'NEGINF') this.rpnp[steps].op = RrdRpn.OP_NEGINF; | ||
86 | else if (expr === 'NE') this.rpnp[steps].op = RrdRpn.OP_NE; | ||
87 | else if (expr === 'COUNT') this.rpnp[steps].op = RrdRpn.OP_COUNT; | ||
88 | else if (/PREV\([-_A-Za-z0-9]+\)/.test(expr)) { | ||
89 | var match = exprs[i].match(/PREV\(([-_A-Za-z0-9]+)\)/i); | ||
90 | if (match.length == 2) { | ||
91 | this.rpnp[steps].op = RrdRpn.OP_PREV_OTHER; | ||
92 | this.rpnp[steps].ptr = this.find_var(gdes, match[1]); // FIXME if -1 | ||
93 | } | ||
94 | } | ||
95 | else if (expr === 'PREV') this.rpnp[steps].op = RrdRpn.OP_PREV; | ||
96 | else if (expr === 'INF') this.rpnp[steps].op = RrdRpn.OP_INF; | ||
97 | else if (expr === 'ISINF') this.rpnp[steps].op = RrdRpn.OP_ISINF; | ||
98 | else if (expr === 'NOW') this.rpnp[steps].op = RrdRpn.OP_NOW; | ||
99 | else if (expr === 'TIME') this.rpnp[steps].op = RrdRpn.OP_TIME; | ||
100 | else if (expr === 'ATAN2') this.rpnp[steps].op = RrdRpn.OP_ATAN2; | ||
101 | else if (expr === 'ATAN') this.rpnp[steps].op = RrdRpn.OP_ATAN; | ||
102 | else if (expr === 'SQRT') this.rpnp[steps].op = RrdRpn.OP_SQRT; | ||
103 | else if (expr === 'SORT') this.rpnp[steps].op = RrdRpn.OP_SORT; | ||
104 | else if (expr === 'REV') this.rpnp[steps].op = RrdRpn.OP_REV; | ||
105 | else if (expr === 'TREND') this.rpnp[steps].op = RrdRpn.OP_TREND; | ||
106 | else if (expr === 'TRENDNAN') this.rpnp[steps].op = RrdRpn.OP_TRENDNAN; | ||
107 | else if (expr === 'PREDICT') this.rpnp[steps].op = RrdRpn.OP_PREDICT; | ||
108 | else if (expr === 'PREDICTSIGMA') this.rpnp[steps].op = RrdRpn.OP_PREDICTSIGMA; | ||
109 | else if (expr === 'RAD2DEG') this.rpnp[steps].op = RrdRpn.OP_RAD2DEG; | ||
110 | else if (expr === 'DEG2RAD') this.rpnp[steps].op = RrdRpn.OP_DEG2RAD; | ||
111 | else if (expr === 'AVG') this.rpnp[steps].op = RrdRpn.OP_AVG; | ||
112 | else if (expr === 'ABS') this.rpnp[steps].op = RrdRpn.OP_ABS; | ||
113 | else if (expr === 'ADDNAN') this.rpnp[steps].op = RrdRpn.OP_ADDNAN; | ||
114 | else if (/[-_A-Za-z0-9]+/.test(expr)) { | ||
115 | this.rpnp[steps].ptr = this.find_var(gdes, exprs[i]); // FIXME if -1 | ||
116 | this.rpnp[steps].op = RrdRpn.OP_VARIABLE; | ||
117 | } else { | ||
118 | return; | ||
119 | } | ||
120 | } | ||
121 | this.rpnp[steps + 1] = {}; | ||
122 | this.rpnp[steps + 1].op = RrdRpn.OP_END; | ||
123 | }; | ||
124 | |||
125 | RrdRpn.OP_NUMBER= 0; | ||
126 | RrdRpn.OP_VARIABLE = 1; | ||
127 | RrdRpn.OP_INF = 2; | ||
128 | RrdRpn.OP_PREV = 3; | ||
129 | RrdRpn.OP_NEGINF = 4; | ||
130 | RrdRpn.OP_UNKN = 5; | ||
131 | RrdRpn.OP_NOW = 6; | ||
132 | RrdRpn.OP_TIME = 7; | ||
133 | RrdRpn.OP_ADD = 8; | ||
134 | RrdRpn.OP_MOD = 9; | ||
135 | RrdRpn.OP_SUB = 10; | ||
136 | RrdRpn.OP_MUL = 11; | ||
137 | RrdRpn.OP_DIV = 12; | ||
138 | RrdRpn.OP_SIN = 13; | ||
139 | RrdRpn.OP_DUP = 14; | ||
140 | RrdRpn.OP_EXC = 15; | ||
141 | RrdRpn.OP_POP = 16; | ||
142 | RrdRpn.OP_COS = 17; | ||
143 | RrdRpn.OP_LOG = 18; | ||
144 | RrdRpn.OP_EXP = 19; | ||
145 | RrdRpn.OP_LT = 20; | ||
146 | RrdRpn.OP_LE = 21; | ||
147 | RrdRpn.OP_GT = 22; | ||
148 | RrdRpn.OP_GE = 23; | ||
149 | RrdRpn.OP_EQ = 24; | ||
150 | RrdRpn.OP_IF = 25; | ||
151 | RrdRpn.OP_MIN = 26; | ||
152 | RrdRpn.OP_MAX = 27; | ||
153 | RrdRpn.OP_LIMIT = 28; | ||
154 | RrdRpn.OP_FLOOR = 29; | ||
155 | RrdRpn.OP_CEIL = 30; | ||
156 | RrdRpn.OP_UN = 31; | ||
157 | RrdRpn.OP_END = 32; | ||
158 | RrdRpn.OP_LTIME = 33; | ||
159 | RrdRpn.OP_NE = 34; | ||
160 | RrdRpn.OP_ISINF = 35; | ||
161 | RrdRpn.OP_PREV_OTHER = 36; | ||
162 | RrdRpn.OP_COUNT = 37; | ||
163 | RrdRpn.OP_ATAN = 38; | ||
164 | RrdRpn.OP_SQRT = 39; | ||
165 | RrdRpn.OP_SORT = 40; | ||
166 | RrdRpn.OP_REV = 41; | ||
167 | RrdRpn.OP_TREND = 42; | ||
168 | RrdRpn.OP_TRENDNAN = 43; | ||
169 | RrdRpn.OP_ATAN2 = 44; | ||
170 | RrdRpn.OP_RAD2DEG = 45; | ||
171 | RrdRpn.OP_DEG2RAD = 46; | ||
172 | RrdRpn.OP_PREDICT = 47; | ||
173 | RrdRpn.OP_PREDICTSIGMA = 48; | ||
174 | RrdRpn.OP_AVG = 49; | ||
175 | RrdRpn.OP_ABS = 50; | ||
176 | RrdRpn.OP_ADDNAN = 51 ; | ||
177 | |||
178 | RrdRpn.prototype.find_var = function(gdes, key) | ||
179 | { | ||
180 | for (var ii = 0, gdes_c = gdes.length; ii < gdes_c; ii++) { | ||
181 | if ((gdes[ii].gf == RrdGraphDesc.GF_DEF || | ||
182 | gdes[ii].gf == RrdGraphDesc.GF_VDEF || | ||
183 | gdes[ii].gf == RrdGraphDesc.GF_CDEF) | ||
184 | && gdes[ii].vname == key) { | ||
185 | return ii; | ||
186 | } | ||
187 | } | ||
188 | return -1; | ||
189 | }; | ||
190 | |||
191 | RrdRpn.prototype.compare_double = function(x, y) | ||
192 | { | ||
193 | var diff = x - y; | ||
194 | return (diff < 0) ? -1 : (diff > 0) ? 1 : 0; | ||
195 | }; | ||
196 | |||
197 | RrdRpn.prototype.fmod = function (x, y) | ||
198 | { | ||
199 | // http://kevin.vanzonneveld.net | ||
200 | // + original by: Onno Marsman | ||
201 | // + input by: Brett Zamir (http://brett-zamir.me) | ||
202 | // + bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) | ||
203 | // * example 1: fmod(5.7, 1.3); | ||
204 | // * returns 1: 0.5 | ||
205 | var tmp, tmp2, p = 0, | ||
206 | pY = 0, | ||
207 | l = 0.0, | ||
208 | l2 = 0.0; | ||
209 | |||
210 | tmp = x.toExponential().match(/^.\.?(.*)e(.+)$/); | ||
211 | p = parseInt(tmp[2], 10) - (tmp[1] + '').length; | ||
212 | tmp = y.toExponential().match(/^.\.?(.*)e(.+)$/); | ||
213 | pY = parseInt(tmp[2], 10) - (tmp[1] + '').length; | ||
214 | |||
215 | if (pY > p) p = pY; | ||
216 | |||
217 | tmp2 = (x % y); | ||
218 | |||
219 | if (p < -100 || p > 20) { | ||
220 | l = Math.round(Math.log(tmp2) / Math.log(10)); | ||
221 | l2 = Math.pow(10, l); | ||
222 | return (tmp2 / l2).toFixed(l - p) * l2; | ||
223 | } else { | ||
224 | return parseFloat(tmp2.toFixed(-p)); | ||
225 | } | ||
226 | }; | ||
227 | |||
228 | RrdRpn.prototype.calc = function (data_idx, output, output_idx) | ||
229 | { | ||
230 | var stptr = -1; | ||
231 | |||
232 | this.rpnstack = []; | ||
233 | |||
234 | for (var rpi = 0; this.rpnp[rpi].op != RrdRpn.OP_END; rpi++) { | ||
235 | switch (this.rpnp[rpi].op) { | ||
236 | case RrdRpn.OP_NUMBER: | ||
237 | this.rpnstack[++stptr] = this.rpnp[rpi].val; | ||
238 | break; | ||
239 | case RrdRpn.OP_VARIABLE: | ||
240 | case RrdRpn.OP_PREV_OTHER: | ||
241 | if (this.rpnp[rpi].ds_cnt == 0) { | ||
242 | throw new RrdRpnError("VDEF made it into rpn_calc... aborting"); | ||
243 | } else { | ||
244 | if (this.rpnp[rpi].op == RrdRpn.OP_VARIABLE) { | ||
245 | this.rpnstack[++stptr] = this.rpnp[rpi].data[this.rpnp[rpi].pdata]; | ||
246 | } else { | ||
247 | if ((output_idx) <= 0) this.rpnstack[++stptr] = Number.NaN; | ||
248 | else this.rpnstack[++stptr] = this.rpnp[rpi].data[this.rpnp[rpi].pdata - this.rpnp[rpi].ds_cnt]; | ||
249 | } | ||
250 | if (data_idx % this.rpnp[rpi].step == 0) { | ||
251 | this.rpnp[rpi].pdata += this.rpnp[rpi].ds_cnt; | ||
252 | } | ||
253 | } | ||
254 | break; | ||
255 | case RrdRpn.OP_COUNT: | ||
256 | this.rpnstack[++stptr] = (output_idx + 1); /* Note: Counter starts at 1 */ | ||
257 | break; | ||
258 | case RrdRpn.OP_PREV: | ||
259 | if ((output_idx) <= 0) this.rpnstack[++stptr] = Number.NaN; | ||
260 | else this.rpnstack[++stptr] = output[output_idx - 1]; | ||
261 | break; | ||
262 | case RrdRpn.OP_UNKN: | ||
263 | this.rpnstack[++stptr] = Number.NaN; | ||
264 | break; | ||
265 | case RrdRpn.OP_INF: | ||
266 | this.rpnstack[++stptr] = Infinity; | ||
267 | break; | ||
268 | case RrdRpn.OP_NEGINF: | ||
269 | this.rpnstack[++stptr] = -Infinity; | ||
270 | break; | ||
271 | case RrdRpn.OP_NOW: | ||
272 | this.rpnstack[++stptr] = Math.round((new Date()).getTime() / 1000); | ||
273 | break; | ||
274 | case RrdRpn.OP_TIME: | ||
275 | this.rpnstack[++stptr] = data_idx; | ||
276 | break; | ||
277 | case RrdRpn.OP_LTIME: | ||
278 | var date = new Date(data_idx*1000); // FIXME XXX | ||
279 | this.rpnstack[++stptr] = date.getTimezoneOffset() * 60 + data_idx; | ||
280 | break; | ||
281 | case RrdRpn.OP_ADD: | ||
282 | if(stptr < 1) throw new RrdRpnError(); | ||
283 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] + this.rpnstack[stptr]; | ||
284 | stptr--; | ||
285 | break; | ||
286 | case RrdRpn.OP_ADDNAN: | ||
287 | if(stptr < 1) throw new RrdRpnError(); | ||
288 | if (isNaN(this.rpnstack[stptr - 1])) { | ||
289 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
290 | } else if (isNaN(this.rpnstack[stptr])) { | ||
291 | /* NOOP */ | ||
292 | /* this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1]; */ | ||
293 | } else { | ||
294 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] + this.rpnstack[stptr]; | ||
295 | } | ||
296 | stptr--; | ||
297 | break; | ||
298 | case RrdRpn.OP_SUB: | ||
299 | if(stptr < 1) throw new RrdRpnError(); | ||
300 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] - this.rpnstack[stptr]; | ||
301 | stptr--; | ||
302 | break; | ||
303 | case RrdRpn.OP_MUL: | ||
304 | if(stptr < 1) throw new RrdRpnError(); | ||
305 | this.rpnstack[stptr - 1] = (this.rpnstack[stptr - 1]) * (this.rpnstack[stptr]); | ||
306 | stptr--; | ||
307 | break; | ||
308 | case RrdRpn.OP_DIV: | ||
309 | if(stptr < 1) throw new RrdRpnError(); | ||
310 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] / this.rpnstack[stptr]; | ||
311 | stptr--; | ||
312 | break; | ||
313 | case RrdRpn.OP_MOD: | ||
314 | if(stptr < 1) throw new RrdRpnError(); | ||
315 | this.rpnstack[stptr - 1] = this.fmod(this.rpnstack[stptr - 1] , this.rpnstack[stptr]); | ||
316 | stptr--; | ||
317 | break; | ||
318 | case RrdRpn.OP_SIN: | ||
319 | if(stptr < 0) throw new RrdRpnError(); | ||
320 | this.rpnstack[stptr] = Math.sin(this.rpnstack[stptr]); | ||
321 | break; | ||
322 | case RrdRpn.OP_ATAN: | ||
323 | if(stptr < 0) throw new RrdRpnError(); | ||
324 | this.rpnstack[stptr] = Math.atan(this.rpnstack[stptr]); | ||
325 | break; | ||
326 | case RrdRpn.OP_RAD2DEG: | ||
327 | if(stptr < 0) throw new RrdRpnError(); | ||
328 | this.rpnstack[stptr] = 57.29577951 * this.rpnstack[stptr]; | ||
329 | break; | ||
330 | case RrdRpn.OP_DEG2RAD: | ||
331 | if(stptr < 0) throw new RrdRpnError(); | ||
332 | this.rpnstack[stptr] = 0.0174532952 * this.rpnstack[stptr]; | ||
333 | break; | ||
334 | case RrdRpn.OP_ATAN2: | ||
335 | if(stptr < 1) throw new RrdRpnError(); | ||
336 | this.rpnstack[stptr - 1] = Math.atan2(this.rpnstack[stptr - 1], this.rpnstack[stptr]); | ||
337 | stptr--; | ||
338 | break; | ||
339 | case RrdRpn.OP_COS: | ||
340 | if(stptr < 0) throw new RrdRpnError(); | ||
341 | this.rpnstack[stptr] = Math.cos(this.rpnstack[stptr]); | ||
342 | break; | ||
343 | case RrdRpn.OP_CEIL: | ||
344 | if(stptr < 0) throw new RrdRpnError(); | ||
345 | this.rpnstack[stptr] = Math.ceil(this.rpnstack[stptr]); | ||
346 | break; | ||
347 | case RrdRpn.OP_FLOOR: | ||
348 | if(stptr < 0) throw new RrdRpnError(); | ||
349 | this.rpnstack[stptr] = Math.floor(this.rpnstack[stptr]); | ||
350 | break; | ||
351 | case RrdRpn.OP_LOG: | ||
352 | if(stptr < 0) throw new RrdRpnError(); | ||
353 | this.rpnstack[stptr] = Math.log(this.rpnstack[stptr]); | ||
354 | break; | ||
355 | case RrdRpn.OP_DUP: | ||
356 | if(stptr < 0) throw new RrdRpnError(); | ||
357 | this.rpnstack[stptr + 1] = this.rpnstack[stptr]; | ||
358 | stptr++; | ||
359 | break; | ||
360 | case RrdRpn.OP_POP: | ||
361 | if(stptr < 0) throw new RrdRpnError(); | ||
362 | stptr--; | ||
363 | break; | ||
364 | case RrdRpn.OP_EXC: | ||
365 | if(stptr < 1) throw new RrdRpnError(); { | ||
366 | var dummy = this.rpnstack[stptr]; | ||
367 | this.rpnstack[stptr] = this.rpnstack[stptr - 1]; | ||
368 | this.rpnstack[stptr - 1] = dummy; | ||
369 | } | ||
370 | break; | ||
371 | case RrdRpn.OP_EXP: | ||
372 | if(stptr < 0) throw new RrdRpnError(); | ||
373 | this.rpnstack[stptr] = Math.exp(this.rpnstack[stptr]); | ||
374 | break; | ||
375 | case RrdRpn.OP_LT: | ||
376 | if(stptr < 1) throw new RrdRpnError(); | ||
377 | if (isNaN(this.rpnstack[stptr - 1])) { | ||
378 | } else if (isNaN(this.rpnstack[stptr])) { | ||
379 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
380 | } else { | ||
381 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] < this.rpnstack[stptr] ? 1.0 : 0.0; | ||
382 | } | ||
383 | stptr--; | ||
384 | break; | ||
385 | case RrdRpn.OP_LE: | ||
386 | if(stptr < 1) throw new RrdRpnError(); | ||
387 | if (isNaN(this.rpnstack[stptr - 1])) { | ||
388 | } else if (isNaN(this.rpnstack[stptr])) { | ||
389 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
390 | } else { | ||
391 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] <= this.rpnstack[stptr] ? 1.0 : 0.0; | ||
392 | } | ||
393 | stptr--; | ||
394 | break; | ||
395 | case RrdRpn.OP_GT: | ||
396 | if(stptr < 1) throw new RrdRpnError(); | ||
397 | if (isNaN(this.rpnstack[stptr - 1])) { | ||
398 | } else if (isNaN(this.rpnstack[stptr])) { | ||
399 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
400 | } else { | ||
401 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] > this.rpnstack[stptr] ? 1.0 : 0.0; | ||
402 | } | ||
403 | stptr--; | ||
404 | break; | ||
405 | case RrdRpn.OP_GE: | ||
406 | if(stptr < 1) throw new RrdRpnError(); | ||
407 | if (isNaN(this.rpnstack[stptr - 1])) { | ||
408 | } else if (isNaN(this.rpnstack[stptr])) { | ||
409 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
410 | } else { | ||
411 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] >= this.rpnstack[stptr] ? 1.0 : 0.0; | ||
412 | } | ||
413 | stptr--; | ||
414 | break; | ||
415 | case RrdRpn.OP_NE: | ||
416 | if(stptr < 1) throw new RrdRpnError(); | ||
417 | if (isNaN(this.rpnstack[stptr - 1])) { | ||
418 | } else if (isNaN(this.rpnstack[stptr])) { | ||
419 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
420 | } else { | ||
421 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] == this.rpnstack[stptr] ? 0.0 : 1.0; | ||
422 | } | ||
423 | stptr--; | ||
424 | break; | ||
425 | case RrdRpn.OP_EQ: | ||
426 | if(stptr < 1) throw new RrdRpnError(); | ||
427 | if (isNaN(this.rpnstack[stptr - 1])) { | ||
428 | } else if (isNaN(this.rpnstack[stptr])) { | ||
429 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
430 | } else { | ||
431 | this.rpnstack[stptr - 1] = this.rpnstack[stptr - 1] == this.rpnstack[stptr] ? 1.0 : 0.0; | ||
432 | } | ||
433 | stptr--; | ||
434 | break; | ||
435 | case RrdRpn.OP_IF: | ||
436 | if(stptr < 2) throw new RrdRpnError(); | ||
437 | this.rpnstack[stptr - 2] = (isNaN(this.rpnstack[stptr - 2]) || this.rpnstack[stptr - 2] == 0.0) ? this.rpnstack[stptr] : this.rpnstack[stptr - 1]; | ||
438 | stptr--; | ||
439 | stptr--; | ||
440 | break; | ||
441 | case RrdRpn.OP_MIN: | ||
442 | if(stptr < 1) throw new RrdRpnError(); | ||
443 | if (isNaN(this.rpnstack[stptr - 1])) { | ||
444 | } else if (isNaN(this.rpnstack[stptr])) { | ||
445 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
446 | } else if (this.rpnstack[stptr - 1] > this.rpnstack[stptr]) { | ||
447 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
448 | } | ||
449 | stptr--; | ||
450 | break; | ||
451 | case RrdRpn.OP_MAX: | ||
452 | if(stptr < 1) throw new RrdRpnError(); | ||
453 | if (isNaN(this.rpnstack[stptr - 1])) { | ||
454 | } else if (isNaN(this.rpnstack[stptr])) { | ||
455 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
456 | } else if (this.rpnstack[stptr - 1] < this.rpnstack[stptr]) { | ||
457 | this.rpnstack[stptr - 1] = this.rpnstack[stptr]; | ||
458 | } | ||
459 | stptr--; | ||
460 | break; | ||
461 | case RrdRpn.OP_LIMIT: | ||
462 | if(stptr < 2) throw new RrdRpnError(); | ||
463 | if (isNaN(this.rpnstack[stptr - 2])) { | ||
464 | } else if (isNaN(this.rpnstack[stptr - 1])) { | ||
465 | this.rpnstack[stptr - 2] = this.rpnstack[stptr - 1]; | ||
466 | } else if (isNaN(this.rpnstack[stptr])) { | ||
467 | this.rpnstack[stptr - 2] = this.rpnstack[stptr]; | ||
468 | } else if (this.rpnstack[stptr - 2] < this.rpnstack[stptr - 1]) { | ||
469 | this.rpnstack[stptr - 2] = Number.NaN; | ||
470 | } else if (this.rpnstack[stptr - 2] > this.rpnstack[stptr]) { | ||
471 | this.rpnstack[stptr - 2] = Number.NaN; | ||
472 | } | ||
473 | stptr -= 2; | ||
474 | break; | ||
475 | case RrdRpn.OP_UN: | ||
476 | if(stptr < 0) throw new RrdRpnError(); | ||
477 | this.rpnstack[stptr] = isNaN(this.rpnstack[stptr]) ? 1.0 : 0.0; | ||
478 | break; | ||
479 | case RrdRpn.OP_ISINF: | ||
480 | if(stptr < 0) throw new RrdRpnError(); | ||
481 | this.rpnstack[stptr] = isInfinite(this.rpnstack[stptr]) ? 1.0 : 0.0; | ||
482 | break; | ||
483 | case RrdRpn.OP_SQRT: | ||
484 | if(stptr < 0) throw new RrdRpnError(); | ||
485 | this.rpnstack[stptr] = Math.sqrt(this.rpnstack[stptr]); | ||
486 | break; | ||
487 | case RrdRpn.OP_SORT: | ||
488 | if(stptr < 0) throw new RrdRpnError(); | ||
489 | var spn = this.rpnstack[stptr--]; | ||
490 | if(stptr < spn - 1) throw new RrdRpnError(); | ||
491 | var array = this.rpnstack.slice(stptr - spn + 1, stptr +1); | ||
492 | array.sort(this.compare_double); | ||
493 | for (var i=stptr - spn + 1, ii=0; i < (stptr +1) ; i++, ii++) | ||
494 | this.rpnstack[i] = array[ii]; | ||
495 | // qsort(this.rpnstack + stptr - spn + 1, spn, sizeof(double), rpn_compare_double); | ||
496 | break; | ||
497 | case RrdRpn.OP_REV: | ||
498 | if(stptr < 0) throw new RrdRpnError(); | ||
499 | var spn = this.rpnstack[stptr--]; | ||
500 | if(stptr < spn - 1) throw new RrdRpnError(); | ||
501 | var array = this.rpnstack.slice(stptr - spn + 1, stptr +1); | ||
502 | array.reverse(); | ||
503 | for (var i=stptr - spn + 1, ii=0; i < (stptr +1) ; i++, ii++) | ||
504 | this.rpnstack[i] = array[ii]; | ||
505 | break; | ||
506 | case RrdRpn.OP_PREDICT: | ||
507 | case RrdRpn.OP_PREDICTSIGMA: | ||
508 | if(stptr < 2) throw new RrdRpnError(); | ||
509 | var locstepsize = this.rpnstack[--stptr]; | ||
510 | var shifts = this.rpnstack[--stptr]; | ||
511 | if(stptr < shifts) throw new RrdRpnError(); | ||
512 | if (shifts<0) stptr--; | ||
513 | else stptr-=shifts; | ||
514 | var val=Number.NaN; | ||
515 | var dsstep = this.rpnp[rpi - 1].step; | ||
516 | var dscount = this.rpnp[rpi - 1].ds_cnt; | ||
517 | var locstep = Math.ceil(locstepsize/dsstep); | ||
518 | var sum = 0; | ||
519 | var sum2 = 0; | ||
520 | var count = 0; | ||
521 | /* now loop for each position */ | ||
522 | var doshifts=shifts; | ||
523 | if (shifts<0) doshifts=-shifts; | ||
524 | for(var loop=0;loop<doshifts;loop++) { | ||
525 | var shiftstep=1; | ||
526 | if (shifts<0) shiftstep = loop*this.rpnstack[stptr]; | ||
527 | else shiftstep = this.rpnstack[stptr+loop]; | ||
528 | if(shiftstep <0) { | ||
529 | throw new RrdRpnError("negative shift step not allowed: "+shiftstep); | ||
530 | } | ||
531 | shiftstep=Math.ceil(shiftstep/dsstep); | ||
532 | for(var i=0;i<=locstep;i++) { | ||
533 | var offset=shiftstep+i; | ||
534 | if ((offset>=0)&&(offset<output_idx)) { | ||
535 | val = this.rpnp[rpi - 1].data[-dscount * offset]; | ||
536 | if (! isNaN(val)) { | ||
537 | sum+=val; | ||
538 | sum2+=val*val; | ||
539 | count++; | ||
540 | } | ||
541 | } | ||
542 | } | ||
543 | } | ||
544 | val=Number.NaN; | ||
545 | if (this.rpnp[rpi].op == RrdRpn.OP_PREDICT) { | ||
546 | if (count>0) val = sum/count; | ||
547 | } else { | ||
548 | if (count>1) { | ||
549 | val=count*sum2-sum*sum; | ||
550 | if (val<0) { | ||
551 | val=Number.NaN; | ||
552 | } else { | ||
553 | val=Math.sqrt(val/(count*(count-1.0))); | ||
554 | } | ||
555 | } | ||
556 | } | ||
557 | this.rpnstack[stptr] = val; | ||
558 | break; | ||
559 | case RrdRpn.OP_TREND: | ||
560 | case RrdRpn.OP_TRENDNAN: | ||
561 | if(stptr < 1) throw new RrdRpnError(); | ||
562 | if ((rpi < 2) || (this.rpnp[rpi - 2].op != RrdRpn.OP_VARIABLE)) { | ||
563 | throw new RrdRpnError("malformed trend arguments"); | ||
564 | } else { | ||
565 | var dur = this.rpnstack[stptr]; | ||
566 | var step = this.rpnp[rpi - 2].step; | ||
567 | |||
568 | if (output_idx + 1 >= Math.ceil(dur / step)) { | ||
569 | var ignorenan = (this.rpnp[rpi].op == RrdRpn.OP_TREND); | ||
570 | var accum = 0.0; | ||
571 | var i = 0; | ||
572 | var count = 0; | ||
573 | |||
574 | do { | ||
575 | var val = this.rpnp[rpi - 2].data[this.rpnp[rpi - 2].ds_cnt * i--]; | ||
576 | if (ignorenan || !isNaN(val)) { | ||
577 | accum += val; | ||
578 | ++count; | ||
579 | } | ||
580 | dur -= step; | ||
581 | } while (dur > 0); | ||
582 | |||
583 | this.rpnstack[--stptr] = (count == 0) ? Number.NaN : (accum / count); | ||
584 | } else this.rpnstack[--stptr] = Number.NaN; | ||
585 | } | ||
586 | break; | ||
587 | case RrdRpn.OP_AVG: | ||
588 | if(stptr < 0) throw new RrdRpnError(); | ||
589 | var i = this.rpnstack[stptr--]; | ||
590 | var sum = 0; | ||
591 | var count = 0; | ||
592 | |||
593 | if(stptr < i - 1) throw new RrdRpnError(); | ||
594 | while (i > 0) { | ||
595 | var val = this.rpnstack[stptr--]; | ||
596 | i--; | ||
597 | if (isNaN(val)) continue; | ||
598 | count++; | ||
599 | sum += val; | ||
600 | } | ||
601 | if (count > 0) this.rpnstack[++stptr] = sum / count; | ||
602 | else this.rpnstack[++stptr] = Number.NaN; | ||
603 | break; | ||
604 | case RrdRpn.OP_ABS: | ||
605 | if(stptr < 0) throw new RrdRpnError(); | ||
606 | this.rpnstack[stptr] = fabs(this.rpnstack[stptr]); | ||
607 | break; | ||
608 | case RrdRpn.OP_END: | ||
609 | break; | ||
610 | } | ||
611 | } | ||
612 | if (stptr != 0) throw new RrdRpnError("RPN final stack size != 1"); | ||
613 | output[output_idx] = this.rpnstack[0]; | ||
614 | return 0; | ||
615 | }; | ||
616 | |||