This is Unofficial EPICS BASE Doxygen Site
calcPerform.c
Go to the documentation of this file.
1 /*************************************************************************\
2 * Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
3 * National Laboratory.
4 * Copyright (c) 2002 The Regents of the University of California, as
5 * Operator of Los Alamos National Laboratory.
6 * EPICS BASE is distributed subject to a Software License Agreement found
7 * in file LICENSE that is included with this distribution.
8 \*************************************************************************/
9 /*
10  * Author: Julie Sander and Bob Dalesio
11  * Date: 07-27-87
12  */
13 
14 #include <stdlib.h>
15 #include <stddef.h>
16 #include <stdio.h>
17 #include <string.h>
18 
19 #include "osiUnistd.h"
20 #include "dbDefs.h"
21 #include "epicsMath.h"
22 #include "epicsTypes.h"
23 #include "errlog.h"
24 #include "postfix.h"
25 #include "postfixPvt.h"
26 
27 
28 static double calcRandom(void);
29 static int cond_search(const char **ppinst, int match);
30 
31 #ifndef PI
32 #define PI 3.14159265358979323
33 #endif
34 
35 /* Turn off global optimization for 64-bit MSVC builds */
36 #if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW)
37 # pragma optimize("g", off)
38 #endif
39 
40 /* calcPerform
41  *
42  * Evalutate the postfix expression
43  */
44 LIBCOM_API long
45  calcPerform(double *parg, double *presult, const char *pinst)
46 {
47  double stack[CALCPERFORM_STACK+1]; /* zero'th entry not used */
48  double *ptop; /* stack pointer */
49  double top; /* value from top of stack */
50  epicsInt32 itop; /* integer from top of stack */
51  int op;
52  int nargs;
53 
54  /* initialize */
55  ptop = stack;
56 
57  /* RPN evaluation loop */
58  while ((op = *pinst++) != END_EXPRESSION){
59  switch (op){
60 
61  case LITERAL_DOUBLE:
62  memcpy(++ptop, pinst, sizeof(double));
63  pinst += sizeof(double);
64  break;
65 
66  case LITERAL_INT:
67  memcpy(&itop, pinst, sizeof(epicsInt32));
68  *++ptop = itop;
69  pinst += sizeof(epicsInt32);
70  break;
71 
72  case FETCH_VAL:
73  *++ptop = *presult;
74  break;
75 
76  case FETCH_A:
77  case FETCH_B:
78  case FETCH_C:
79  case FETCH_D:
80  case FETCH_E:
81  case FETCH_F:
82  case FETCH_G:
83  case FETCH_H:
84  case FETCH_I:
85  case FETCH_J:
86  case FETCH_K:
87  case FETCH_L:
88  *++ptop = parg[op - FETCH_A];
89  break;
90 
91  case STORE_A:
92  case STORE_B:
93  case STORE_C:
94  case STORE_D:
95  case STORE_E:
96  case STORE_F:
97  case STORE_G:
98  case STORE_H:
99  case STORE_I:
100  case STORE_J:
101  case STORE_K:
102  case STORE_L:
103  parg[op - STORE_A] = *ptop--;
104  break;
105 
106  case CONST_PI:
107  *++ptop = PI;
108  break;
109 
110  case CONST_D2R:
111  *++ptop = PI/180.;
112  break;
113 
114  case CONST_R2D:
115  *++ptop = 180./PI;
116  break;
117 
118  case UNARY_NEG:
119  *ptop = - *ptop;
120  break;
121 
122  case ADD:
123  top = *ptop--;
124  *ptop += top;
125  break;
126 
127  case SUB:
128  top = *ptop--;
129  *ptop -= top;
130  break;
131 
132  case MULT:
133  top = *ptop--;
134  *ptop *= top;
135  break;
136 
137  case DIV:
138  top = *ptop--;
139  *ptop /= top;
140  break;
141 
142  case MODULO:
143  itop = (epicsInt32) *ptop--;
144  if (itop)
145  *ptop = (epicsInt32) *ptop % itop;
146  else
147  *ptop = epicsNAN;
148  break;
149 
150  case POWER:
151  top = *ptop--;
152  *ptop = pow(*ptop, top);
153  break;
154 
155  case ABS_VAL:
156  *ptop = fabs(*ptop);
157  break;
158 
159  case EXP:
160  *ptop = exp(*ptop);
161  break;
162 
163  case LOG_10:
164  *ptop = log10(*ptop);
165  break;
166 
167  case LOG_E:
168  *ptop = log(*ptop);
169  break;
170 
171  case MAX:
172  nargs = *pinst++;
173  while (--nargs) {
174  top = *ptop--;
175  if (*ptop < top || isnan(top))
176  *ptop = top;
177  }
178  break;
179 
180  case MIN:
181  nargs = *pinst++;
182  while (--nargs) {
183  top = *ptop--;
184  if (*ptop > top || isnan(top))
185  *ptop = top;
186  }
187  break;
188 
189  case SQU_RT:
190  *ptop = sqrt(*ptop);
191  break;
192 
193  case ACOS:
194  *ptop = acos(*ptop);
195  break;
196 
197  case ASIN:
198  *ptop = asin(*ptop);
199  break;
200 
201  case ATAN:
202  *ptop = atan(*ptop);
203  break;
204 
205  case ATAN2:
206  top = *ptop--;
207  *ptop = atan2(top, *ptop); /* Ouch!: Args backwards! */
208  break;
209 
210  case COS:
211  *ptop = cos(*ptop);
212  break;
213 
214  case SIN:
215  *ptop = sin(*ptop);
216  break;
217 
218  case TAN:
219  *ptop = tan(*ptop);
220  break;
221 
222  case COSH:
223  *ptop = cosh(*ptop);
224  break;
225 
226  case SINH:
227  *ptop = sinh(*ptop);
228  break;
229 
230  case TANH:
231  *ptop = tanh(*ptop);
232  break;
233 
234  case CEIL:
235  *ptop = ceil(*ptop);
236  break;
237 
238  case FLOOR:
239  *ptop = floor(*ptop);
240  break;
241 
242  case FINITE:
243  nargs = *pinst++;
244  top = finite(*ptop);
245  while (--nargs) {
246  --ptop;
247  top = top && finite(*ptop);
248  }
249  *ptop = top;
250  break;
251 
252  case ISINF:
253  *ptop = isinf(*ptop);
254  break;
255 
256  case ISNAN:
257  nargs = *pinst++;
258  top = isnan(*ptop);
259  while (--nargs) {
260  --ptop;
261  top = top || isnan(*ptop);
262  }
263  *ptop = top;
264  break;
265 
266  case NINT:
267  top = *ptop;
268  *ptop = (epicsInt32) (top >= 0 ? top + 0.5 : top - 0.5);
269  break;
270 
271  case RANDOM:
272  *++ptop = calcRandom();
273  break;
274 
275  case REL_OR:
276  top = *ptop--;
277  *ptop = *ptop || top;
278  break;
279 
280  case REL_AND:
281  top = *ptop--;
282  *ptop = *ptop && top;
283  break;
284 
285  case REL_NOT:
286  *ptop = ! *ptop;
287  break;
288 
289  /* Be VERY careful converting double to int in case bit 31 is set!
290  * Out-of-range errors give very different results on different sytems.
291  * Convert negative doubles to signed and positive doubles to unsigned
292  * first to avoid overflows if bit 32 is set.
293  * The result is always signed, values with bit 31 set are negative
294  * to avoid problems when writing the value to signed integer fields
295  * like longout.VAL or ao.RVAL. However unsigned fields may give
296  * problems on some architectures. (Fewer than giving problems with
297  * signed integer. Maybe the conversion functions should handle
298  * overflows better.)
299  */
300  #define d2i(x) ((x)<0?(epicsInt32)(x):(epicsInt32)(epicsUInt32)(x))
301  #define d2ui(x) ((x)<0?(epicsUInt32)(epicsInt32)(x):(epicsUInt32)(x))
302 
303  case BIT_OR:
304  top = *ptop--;
305  *ptop = (double)(d2i(*ptop) | d2i(top));
306  break;
307 
308  case BIT_AND:
309  top = *ptop--;
310  *ptop = (double)(d2i(*ptop) & d2i(top));
311  break;
312 
313  case BIT_EXCL_OR:
314  top = *ptop--;
315  *ptop = (double)(d2i(*ptop) ^ d2i(top));
316  break;
317 
318  case BIT_NOT:
319  *ptop = (double)~d2i(*ptop);
320  break;
321 
322  /* In C the shift operators decide on an arithmetic or logical shift
323  * based on whether the integer is signed or unsigned.
324  * With signed integers, a right-shift is arithmetic and will
325  * extend the sign bit into the left-hand end of the value. When used
326  * with unsigned values a logical shift is performed. The
327  * double-casting through signed/unsigned here is important, see above.
328  */
329 
330  case RIGHT_SHIFT_ARITH:
331  top = *ptop--;
332  *ptop = (double)(d2i(*ptop) >> (d2i(top) & 31));
333  break;
334 
335  case LEFT_SHIFT_ARITH:
336  top = *ptop--;
337  *ptop = (double)(d2i(*ptop) << (d2i(top) & 31));
338  break;
339 
340  case RIGHT_SHIFT_LOGIC:
341  top = *ptop--;
342  *ptop = (double)(d2ui(*ptop) >> (d2ui(top) & 31u));
343  break;
344 
345  case NOT_EQ:
346  top = *ptop--;
347  *ptop = *ptop != top;
348  break;
349 
350  case LESS_THAN:
351  top = *ptop--;
352  *ptop = *ptop < top;
353  break;
354 
355  case LESS_OR_EQ:
356  top = *ptop--;
357  *ptop = *ptop <= top;
358  break;
359 
360  case EQUAL:
361  top = *ptop--;
362  *ptop = *ptop == top;
363  break;
364 
365  case GR_OR_EQ:
366  top = *ptop--;
367  *ptop = *ptop >= top;
368  break;
369 
370  case GR_THAN:
371  top = *ptop--;
372  *ptop = *ptop > top;
373  break;
374 
375  case COND_IF:
376  if (*ptop-- == 0.0 &&
377  cond_search(&pinst, COND_ELSE)) return -1;
378  break;
379 
380  case COND_ELSE:
381  if (cond_search(&pinst, COND_END)) return -1;
382  break;
383 
384  case COND_END:
385  break;
386 
387  default:
388  errlogPrintf("calcPerform: Bad Opcode %d at %p\n", op, pinst-1);
389  return -1;
390  }
391  }
392 
393  /* The stack should now have one item on it, the expression value */
394  if (ptop != stack + 1)
395  return -1;
396  *presult = *ptop;
397  return 0;
398 }
399 
400 #if defined(_WIN32) && defined(_M_X64) && !defined(_MINGW)
401 # pragma optimize("", on)
402 #endif
403 
404 LIBCOM_API long
405 calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
406 {
407  unsigned long inputs = 0;
408  unsigned long stores = 0;
409  char op;
410  while ((op = *pinst++) != END_EXPRESSION) {
411  switch (op) {
412 
413  case LITERAL_DOUBLE:
414  pinst += sizeof(double);
415  break;
416  case LITERAL_INT:
417  pinst += sizeof(epicsInt32);
418  break;
419  case MIN:
420  case MAX:
421  case FINITE:
422  case ISNAN:
423  pinst++;
424  break;
425 
426  case FETCH_A:
427  case FETCH_B:
428  case FETCH_C:
429  case FETCH_D:
430  case FETCH_E:
431  case FETCH_F:
432  case FETCH_G:
433  case FETCH_H:
434  case FETCH_I:
435  case FETCH_J:
436  case FETCH_K:
437  case FETCH_L:
438  /* Don't claim to use an arg we already stored to */
439  inputs |= (1 << (op - FETCH_A)) & ~stores;
440  break;
441 
442  case STORE_A:
443  case STORE_B:
444  case STORE_C:
445  case STORE_D:
446  case STORE_E:
447  case STORE_F:
448  case STORE_G:
449  case STORE_H:
450  case STORE_I:
451  case STORE_J:
452  case STORE_K:
453  case STORE_L:
454  stores |= (1 << (op - STORE_A));
455  break;
456 
457  default:
458  break;
459  }
460  }
461  if (pinputs) *pinputs = inputs;
462  if (pstores) *pstores = stores;
463  return 0;
464 }
465 
466 /* Generate a random number between 0 and 1 using the algorithm
467  * seed = (multy * seed) + addy Random Number Generator by Knuth
468  * SemiNumerical Algorithms
469  * Chapter 1
470  * randy = seed / 65535.0 To normalize the number between 0 - 1
471  */
472 static unsigned short seed = 0xa3bf;
473 static unsigned short multy = 191 * 8 + 5; /* 191 % 8 == 5 */
474 static unsigned short addy = 0x3141;
475 
476 static double calcRandom(void)
477 {
478  seed = (seed * multy) + addy;
479 
480  /* between 0 - 1 */
481  return (double) seed / 65535.0;
482 }
483 
484 /* Search the instruction stream for a matching operator, skipping any
485  * other conditional instructions found, and leave *ppinst pointing to
486  * the next instruction to be executed.
487  */
488 static int cond_search(const char **ppinst, int match)
489 {
490  const char *pinst = *ppinst;
491  int count = 1;
492  int op;
493 
494  while ((op = *pinst++) != END_EXPRESSION) {
495  if (op == match && --count == 0) {
496  *ppinst = pinst;
497  return 0;
498  }
499  switch (op) {
500  case LITERAL_DOUBLE:
501  pinst += sizeof(double);
502  break;
503  case LITERAL_INT:
504  pinst += sizeof(epicsInt32);
505  break;
506  case MIN:
507  case MAX:
508  case FINITE:
509  case ISNAN:
510  pinst++;
511  break;
512  case COND_IF:
513  count++;
514  break;
515  }
516  }
517  return 1;
518 }
Definition: postfixPvt.h:56
LIBCOM_API long calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
Find the inputs and outputs of an expression.
Definition: calcPerform.c:405
The API for the EPICS Calculation Engine.
#define isinf(x)
Definition: epicsMath.h:16
Definition: postfixPvt.h:45
Definition: postfixPvt.h:57
Miscellaneous macro definitions.
#define PI
Definition: calcPerform.c:32
LIBCOM_API long calcPerform(double *parg, double *presult, const char *pinst)
Run the calculation engine.
Definition: calcPerform.c:45
#define isnan(x)
Definition: epicsMath.h:21
#define d2ui(x)
Definition: postfixPvt.h:46
Definition: postfixPvt.h:64
int errlogPrintf(const char *pFormat,...)
Definition: errlog.c:105
float epicsNAN
Definition: epicsMath.cpp:35
Definition: postfixPvt.h:68
Definition: postfixPvt.h:48
Definition: postfixPvt.h:53
#define CALCPERFORM_STACK
Size of the internal partial result stack.
Definition: postfix.h:27
Definition: postfixPvt.h:66
ChannelPut::shared_pointer op
Definition: pvAccess.cpp:132
#define d2i(x)
#define finite(x)
Definition: epicsMath.h:16
int epicsInt32
Definition: epicsTypes.h:42