This is Unofficial EPICS BASE Doxygen Site
Main Page
Related Pages
Modules
Namespaces
Classes
Files
File List
File Members
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
}
COSH
Definition:
postfixPvt.h:65
BIT_AND
Definition:
postfixPvt.h:84
STORE_D
Definition:
postfixPvt.h:37
POWER
Definition:
postfixPvt.h:50
postfixPvt.h
LEFT_SHIFT_ARITH
Definition:
postfixPvt.h:88
FETCH_J
Definition:
postfixPvt.h:35
FETCH_A
Definition:
postfixPvt.h:34
MAX
Definition:
postfixPvt.h:56
FETCH_C
Definition:
postfixPvt.h:34
GR_THAN
Definition:
postfixPvt.h:96
BIT_OR
Definition:
postfixPvt.h:83
UNARY_NEG
Definition:
postfixPvt.h:44
calcArgUsage
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
REL_AND
Definition:
postfixPvt.h:80
RIGHT_SHIFT_ARITH
Definition:
postfixPvt.h:87
LESS_THAN
Definition:
postfixPvt.h:92
SINH
Definition:
postfixPvt.h:67
LITERAL_INT
Definition:
postfixPvt.h:33
postfix.h
The API for the EPICS Calculation Engine.
errlog.h
NINT
Definition:
postfixPvt.h:76
SQU_RT
Definition:
postfixPvt.h:58
MODULO
Definition:
postfixPvt.h:49
isinf
#define isinf(x)
Definition:
epicsMath.h:16
ADD
Definition:
postfixPvt.h:45
MULT
Definition:
postfixPvt.h:47
CONST_R2D
Definition:
postfixPvt.h:42
LESS_OR_EQ
Definition:
postfixPvt.h:93
FETCH_D
Definition:
postfixPvt.h:34
COND_IF
Definition:
postfixPvt.h:98
LITERAL_DOUBLE
Definition:
postfixPvt.h:33
FETCH_I
Definition:
postfixPvt.h:35
MIN
Definition:
postfixPvt.h:57
dbDefs.h
Miscellaneous macro definitions.
STORE_L
Definition:
postfixPvt.h:38
STORE_E
Definition:
postfixPvt.h:37
FETCH_B
Definition:
postfixPvt.h:34
STORE_C
Definition:
postfixPvt.h:37
FETCH_K
Definition:
postfixPvt.h:35
STORE_F
Definition:
postfixPvt.h:37
PI
#define PI
Definition:
calcPerform.c:32
calcPerform
LIBCOM_API long calcPerform(double *parg, double *presult, const char *pinst)
Run the calculation engine.
Definition:
calcPerform.c:45
STORE_I
Definition:
postfixPvt.h:38
ASIN
Definition:
postfixPvt.h:61
CEIL
Definition:
postfixPvt.h:71
STORE_B
Definition:
postfixPvt.h:37
GR_OR_EQ
Definition:
postfixPvt.h:95
CONST_PI
Definition:
postfixPvt.h:40
ISNAN
Definition:
postfixPvt.h:75
isnan
#define isnan(x)
Definition:
epicsMath.h:21
FETCH_G
Definition:
postfixPvt.h:35
ATAN2
Definition:
postfixPvt.h:63
STORE_H
Definition:
postfixPvt.h:38
epicsTypes.h
FETCH_F
Definition:
postfixPvt.h:34
STORE_G
Definition:
postfixPvt.h:38
ACOS
Definition:
postfixPvt.h:60
d2ui
#define d2ui(x)
COND_END
Definition:
postfixPvt.h:100
SUB
Definition:
postfixPvt.h:46
COS
Definition:
postfixPvt.h:64
CONST_D2R
Definition:
postfixPvt.h:41
RANDOM
Definition:
postfixPvt.h:77
STORE_A
Definition:
postfixPvt.h:37
FETCH_VAL
Definition:
postfixPvt.h:33
LOG_E
Definition:
postfixPvt.h:55
ABS_VAL
Definition:
postfixPvt.h:52
errlogPrintf
int errlogPrintf(const char *pFormat,...)
Definition:
errlog.c:105
LOG_10
Definition:
postfixPvt.h:54
epicsNAN
float epicsNAN
Definition:
epicsMath.cpp:35
TAN
Definition:
postfixPvt.h:68
FLOOR
Definition:
postfixPvt.h:72
TANH
Definition:
postfixPvt.h:69
RIGHT_SHIFT_LOGIC
Definition:
postfixPvt.h:89
COND_ELSE
Definition:
postfixPvt.h:99
FETCH_L
Definition:
postfixPvt.h:35
DIV
Definition:
postfixPvt.h:48
REL_NOT
Definition:
postfixPvt.h:81
FETCH_H
Definition:
postfixPvt.h:35
EXP
Definition:
postfixPvt.h:53
END_EXPRESSION
Definition:
postfixPvt.h:31
CALCPERFORM_STACK
#define CALCPERFORM_STACK
Size of the internal partial result stack.
Definition:
postfix.h:27
BIT_EXCL_OR
Definition:
postfixPvt.h:85
FETCH_E
Definition:
postfixPvt.h:34
STORE_J
Definition:
postfixPvt.h:38
FINITE
Definition:
postfixPvt.h:73
BIT_NOT
Definition:
postfixPvt.h:86
SIN
Definition:
postfixPvt.h:66
op
ChannelPut::shared_pointer op
Definition:
pvAccess.cpp:132
d2i
#define d2i(x)
finite
#define finite(x)
Definition:
epicsMath.h:16
STORE_K
Definition:
postfixPvt.h:38
EQUAL
Definition:
postfixPvt.h:94
NOT_EQ
Definition:
postfixPvt.h:91
REL_OR
Definition:
postfixPvt.h:79
epicsInt32
int epicsInt32
Definition:
epicsTypes.h:42
ATAN
Definition:
postfixPvt.h:62
ISINF
Definition:
postfixPvt.h:74
modules
libcom
src
calc
calcPerform.c
Generated by
1.8.11