KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jrobin > graph > RpnCalculator


1 /* ============================================================
2  * JRobin : Pure java implementation of RRDTool's functionality
3  * ============================================================
4  *
5  * Project Info: http://www.jrobin.org
6  * Project Lead: Sasa Markovic (saxon@jrobin.org)
7  *
8  * Developers: Sasa Markovic (saxon@jrobin.org)
9  * Arne Vandamme (cobralord@jrobin.org)
10  *
11  * (C) Copyright 2003, by Sasa Markovic.
12  *
13  * This library is free software; you can redistribute it and/or modify it under the terms
14  * of the GNU Lesser General Public License as published by the Free Software Foundation;
15  * either version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
18  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
19  * See the GNU Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public License along with this
22  * library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
23  * Boston, MA 02111-1307, USA.
24  */

25 package org.jrobin.graph;
26
27 import java.util.ArrayList JavaDoc;
28
29 import org.jrobin.core.Util;
30 import org.jrobin.core.RrdException;
31
32 /**
33  * <p>Used to calculate result of an RPN expression.</p>
34  *
35  * @author Arne Vandamme (cobralord@jrobin.org)
36  * @author Sasa Markovic (saxon@jrobin.org)
37  */

38 class RpnCalculator
39 {
40     // ================================================================
41
// -- Members
42
// ================================================================
43
// Token definitions
44
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 JavaDoc stack = new ArrayList JavaDoc();
89     
90     
91     // ================================================================
92
// -- Constructors
93
// ================================================================
94
/**
95      * Constructs a RPN calculator object by providing the source array to use for value lookups.
96      * @param sources Table containing all retrieved datasources of the graph definition.
97      * @param step Time in seconds that one sample represents.
98      */

99     RpnCalculator( Source[] sources, double step )
100     {
101         this.sources = sources;
102         this.step = step;
103     }
104     
105     
106     // ================================================================
107
// -- Public methods
108
// ================================================================
109
/**
110      * Evaluates a Cdef RPN expression into a single value.
111      * @param cdef Cdef object representing the parsed RPN expression.
112      * @param row Row index in the source table to retrieve all necessary values.
113      * @param timestamp Timestamp of the datapoint for which the value should be calculated.
114      * @return Calculated double value of the requested datapoint.
115      * @throws RrdException Thrown in case of a JRobin specific error.
116      */

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     // ================================================================
338
// -- Private methods
339
// ================================================================
340
/**
341      * Pushes as a double value on the internal stack.
342      * @param value Value to push on the stack.
343      */

344     private void push( double value )
345     {
346         stack.add( new Double JavaDoc(value) );
347     }
348
349     /**
350      * Pops a double value off the internal stack.
351      * @return Value popped off the stack.
352      * @throws RrdException Thrown in case of a JRobin specific error.
353      */

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 JavaDoc lastValue = (Double JavaDoc) stack.remove(last);
361     
362         return lastValue.doubleValue();
363     }
364
365 }
366
Popular Tags