libCom/calc: Added integer literals, which use less space in Postfix.
Renamed LITERAL to LITERAL_DOUBLE and added LITERAL_INT. postfix() only uses LITERAL_INT if the results are identical. Adjusted INFIX_TO_POSTFIX_SIZE() macro to match. Cleaned up some other internal issues.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
@@ -43,21 +43,26 @@ epicsShareFunc long
|
||||
double stack[CALCPERFORM_STACK+1]; /* zero'th entry not used */
|
||||
double *ptop; /* stack pointer */
|
||||
double top; /* value from top of stack */
|
||||
long itop; /* integer from top of stack */
|
||||
int itop; /* integer from top of stack */
|
||||
int op;
|
||||
int nargs;
|
||||
|
||||
/* initialize */
|
||||
ptop = stack;
|
||||
|
||||
/* RPN evaluation loop */
|
||||
while (*pinst != END_EXPRESSION){
|
||||
switch (*pinst){
|
||||
while ((op = *pinst++) != END_EXPRESSION){
|
||||
switch (op){
|
||||
|
||||
case LITERAL:
|
||||
++ptop;
|
||||
++pinst;
|
||||
memcpy((void *)ptop, pinst, sizeof(double));
|
||||
pinst += sizeof(double) - 1;
|
||||
case LITERAL_DOUBLE:
|
||||
memcpy((void *)++ptop, pinst, sizeof(double));
|
||||
pinst += sizeof(double);
|
||||
break;
|
||||
|
||||
case LITERAL_INT:
|
||||
memcpy(&itop, pinst, sizeof(int));
|
||||
*++ptop = itop;
|
||||
pinst += sizeof(int);
|
||||
break;
|
||||
|
||||
case FETCH_VAL:
|
||||
@@ -76,7 +81,7 @@ epicsShareFunc long
|
||||
case FETCH_J:
|
||||
case FETCH_K:
|
||||
case FETCH_L:
|
||||
*++ptop = parg[*pinst - FETCH_A];
|
||||
*++ptop = parg[op - FETCH_A];
|
||||
break;
|
||||
|
||||
case STORE_A:
|
||||
@@ -91,7 +96,7 @@ epicsShareFunc long
|
||||
case STORE_J:
|
||||
case STORE_K:
|
||||
case STORE_L:
|
||||
parg[*pinst - STORE_A] = *ptop--;
|
||||
parg[op - STORE_A] = *ptop--;
|
||||
break;
|
||||
|
||||
case CONST_PI:
|
||||
@@ -160,7 +165,7 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case MAX:
|
||||
nargs = *++pinst;
|
||||
nargs = *pinst++;
|
||||
while (--nargs) {
|
||||
top = *ptop--;
|
||||
if (*ptop < top || isnan(top))
|
||||
@@ -169,7 +174,7 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case MIN:
|
||||
nargs = *++pinst;
|
||||
nargs = *pinst++;
|
||||
while (--nargs) {
|
||||
top = *ptop--;
|
||||
if (*ptop > top || isnan(top))
|
||||
@@ -231,7 +236,7 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case FINITE:
|
||||
nargs = *++pinst;
|
||||
nargs = *pinst++;
|
||||
top = finite(*ptop);
|
||||
while (--nargs) {
|
||||
--ptop;
|
||||
@@ -245,7 +250,7 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case ISNAN:
|
||||
nargs = *++pinst;
|
||||
nargs = *pinst++;
|
||||
top = isnan(*ptop);
|
||||
while (--nargs) {
|
||||
--ptop;
|
||||
@@ -350,12 +355,9 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
default:
|
||||
errlogPrintf("calcPerform: Bad Opcode %d at %p\n",*pinst, pinst);
|
||||
errlogPrintf("calcPerform: Bad Opcode %d at %p\n", op, pinst-1);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Advance to next opcode */
|
||||
++pinst;
|
||||
}
|
||||
|
||||
/* The stack should now have one item on it, the expression value */
|
||||
@@ -372,12 +374,21 @@ calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
|
||||
unsigned long inputs = 0;
|
||||
unsigned long stores = 0;
|
||||
char op;
|
||||
while ((op = *pinst) != END_EXPRESSION) {
|
||||
while ((op = *pinst++) != END_EXPRESSION) {
|
||||
switch (op) {
|
||||
|
||||
case LITERAL:
|
||||
case LITERAL_DOUBLE:
|
||||
pinst += sizeof(double);
|
||||
break;
|
||||
case LITERAL_INT:
|
||||
pinst += sizeof(int);
|
||||
break;
|
||||
case MIN:
|
||||
case MAX:
|
||||
case FINITE:
|
||||
case ISNAN:
|
||||
pinst++;
|
||||
break;
|
||||
|
||||
case FETCH_A:
|
||||
case FETCH_B:
|
||||
@@ -413,7 +424,6 @@ calcArgUsage(const char *pinst, unsigned long *pinputs, unsigned long *pstores)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pinst++;
|
||||
}
|
||||
if (pinputs) *pinputs = inputs;
|
||||
if (pstores) *pstores = stores;
|
||||
@@ -439,24 +449,37 @@ static double calcRandom(void)
|
||||
}
|
||||
|
||||
/* Search the instruction stream for a matching operator, skipping any
|
||||
* other conditional instructions found
|
||||
* other conditional instructions found, and leave *ppinst pointing to
|
||||
* the next instruction to be executed.
|
||||
*/
|
||||
static int cond_search(const char **ppinst, int match)
|
||||
{
|
||||
const char *pinst = *ppinst + 1;
|
||||
const char *pinst = *ppinst;
|
||||
int count = 1;
|
||||
int op;
|
||||
|
||||
while ((op = *pinst) != END_EXPRESSION) {
|
||||
while ((op = *pinst++) != END_EXPRESSION) {
|
||||
if (op == match && --count == 0) {
|
||||
*ppinst = pinst;
|
||||
return 0;
|
||||
} else if (op == COND_IF)
|
||||
count++;
|
||||
else if (op == LITERAL)
|
||||
}
|
||||
switch (op) {
|
||||
case LITERAL_DOUBLE:
|
||||
pinst += sizeof(double);
|
||||
pinst++;
|
||||
break;
|
||||
case LITERAL_INT:
|
||||
pinst += sizeof(int);
|
||||
break;
|
||||
case MIN:
|
||||
case MAX:
|
||||
case FINITE:
|
||||
case ISNAN:
|
||||
pinst++;
|
||||
break;
|
||||
case COND_IF:
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
@@ -10,7 +10,7 @@
|
||||
*
|
||||
* Subroutines used to convert an infix expression to a postfix expression
|
||||
*
|
||||
* Author: Bob Dalesio
|
||||
* Original Author: Bob Dalesio
|
||||
* Date: 12-12-86
|
||||
*/
|
||||
|
||||
@@ -69,17 +69,17 @@ static const ELEMENT operands[] = {
|
||||
{"!", 7, 8, 0, UNARY_OPERATOR, REL_NOT},
|
||||
{"(", 0, 8, 0, UNARY_OPERATOR, NOT_GENERATED},
|
||||
{"-", 7, 8, 0, UNARY_OPERATOR, UNARY_NEG},
|
||||
{".", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"0", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"1", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"2", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"3", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"4", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"5", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"6", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"7", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"8", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"9", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{".", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"0", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"1", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"2", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"3", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"4", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"5", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"6", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"7", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"8", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"9", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"A", 0, 0, 1, OPERAND, FETCH_A},
|
||||
{"ABS", 7, 8, 0, UNARY_OPERATOR, ABS_VAL},
|
||||
{"ACOS", 7, 8, 0, UNARY_OPERATOR, ACOS},
|
||||
@@ -101,7 +101,7 @@ static const ELEMENT operands[] = {
|
||||
{"G", 0, 0, 1, OPERAND, FETCH_G},
|
||||
{"H", 0, 0, 1, OPERAND, FETCH_H},
|
||||
{"I", 0, 0, 1, OPERAND, FETCH_I},
|
||||
{"INF", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"INF", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"ISINF", 7, 8, 0, UNARY_OPERATOR, ISINF},
|
||||
{"ISNAN", 7, 8, 0, VARARG_OPERATOR,ISNAN},
|
||||
{"J", 0, 0, 1, OPERAND, FETCH_J},
|
||||
@@ -113,7 +113,7 @@ static const ELEMENT operands[] = {
|
||||
{"MAX", 7, 8, 0, VARARG_OPERATOR,MAX},
|
||||
{"MIN", 7, 8, 0, VARARG_OPERATOR,MIN},
|
||||
{"NINT", 7, 8, 0, UNARY_OPERATOR, NINT},
|
||||
{"NAN", 0, 0, 1, LITERAL_OPERAND,LITERAL},
|
||||
{"NAN", 0, 0, 1, LITERAL_OPERAND,LITERAL_DOUBLE},
|
||||
{"NOT", 7, 8, 0, UNARY_OPERATOR, BIT_NOT},
|
||||
{"PI", 0, 0, 1, OPERAND, CONST_PI},
|
||||
{"R2D", 0, 0, 1, OPERAND, CONST_R2D},
|
||||
@@ -214,7 +214,8 @@ epicsShareFunc long
|
||||
int cond_count = 0;
|
||||
char *pout = ppostfix;
|
||||
char *pnext;
|
||||
double constant;
|
||||
double lit_d;
|
||||
int lit_i;
|
||||
|
||||
if (psrc == NULL || *psrc == '\0' ||
|
||||
pout == NULL || perror == NULL) {
|
||||
@@ -237,18 +238,25 @@ epicsShareFunc long
|
||||
break;
|
||||
|
||||
case LITERAL_OPERAND:
|
||||
*pout++ = pel->code;
|
||||
runtime_depth += pel->runtime_effect;
|
||||
|
||||
psrc -= strlen(pel->name);
|
||||
constant = epicsStrtod(psrc, &pnext);
|
||||
lit_d = epicsStrtod(psrc, &pnext);
|
||||
if (pnext == psrc) {
|
||||
*perror = CALC_ERR_BAD_LITERAL;
|
||||
goto bad;
|
||||
}
|
||||
psrc = pnext;
|
||||
memcpy(pout, (void *)&constant, sizeof(double));
|
||||
pout += sizeof(double);
|
||||
lit_i = lit_d;
|
||||
if (lit_d != (double) lit_i) {
|
||||
*pout++ = pel->code;
|
||||
memcpy(pout, (void *)&lit_d, sizeof(double));
|
||||
pout += sizeof(double);
|
||||
} else {
|
||||
*pout++ = LITERAL_INT;
|
||||
memcpy(pout, (void *)&lit_i, sizeof(int));
|
||||
pout += sizeof(int);
|
||||
}
|
||||
|
||||
operand_needed = FALSE;
|
||||
break;
|
||||
@@ -500,7 +508,7 @@ epicsShareFunc void
|
||||
static const char *opcodes[] = {
|
||||
"End Expression",
|
||||
/* Operands */
|
||||
"LITERAL", "VAL",
|
||||
"LITERAL_DOUBLE", "LITERAL_INT", "VAL",
|
||||
"FETCH_A", "FETCH_B", "FETCH_C", "FETCH_D", "FETCH_E", "FETCH_F",
|
||||
"FETCH_G", "FETCH_H", "FETCH_I", "FETCH_J", "FETCH_K", "FETCH_L",
|
||||
/* Assignment */
|
||||
@@ -571,15 +579,21 @@ epicsShareFunc void
|
||||
"NOT_GENERATED"
|
||||
};
|
||||
char op;
|
||||
double lit;
|
||||
double lit_d;
|
||||
int lit_i;
|
||||
|
||||
while ((op = *pinst) != END_EXPRESSION) {
|
||||
switch (op) {
|
||||
case LITERAL:
|
||||
memcpy((void *)&lit, ++pinst, sizeof(double));
|
||||
printf("\tLiteral: %g\n", lit);
|
||||
case LITERAL_DOUBLE:
|
||||
memcpy((void *)&lit_d, ++pinst, sizeof(double));
|
||||
printf("\tDouble %g\n", lit_d);
|
||||
pinst += sizeof(double);
|
||||
break;
|
||||
case LITERAL_INT:
|
||||
memcpy((void *)&lit_i, ++pinst, sizeof(int));
|
||||
printf("\tInteger %d\n", lit_i);
|
||||
pinst += sizeof(int);
|
||||
break;
|
||||
case MIN:
|
||||
case MAX:
|
||||
case FINITE:
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* postfix.h
|
||||
* Author: Bob Dalesio
|
||||
* Original Author: Bob Dalesio
|
||||
* Date: 9-21-88
|
||||
*/
|
||||
|
||||
@@ -20,14 +19,11 @@
|
||||
#define CALCPERFORM_NARGS 12
|
||||
#define CALCPERFORM_STACK 80
|
||||
|
||||
#define INFIX_TO_POSTFIX_SIZE(n) (((n-2)>>2)*21 + ((n-2)&2)*5 + 10)
|
||||
/* The above is calculated from the following expression fragments:
|
||||
* 1?1: 4 chars expand to 21 chars
|
||||
* 1+ 2 chars expand to 10 chars
|
||||
* 1 1 char expands to 9 chars
|
||||
* All other infix operators convert by a factor of 1:1 or less.
|
||||
* Allow 1 char each for the infix and postfix terminators,
|
||||
* and the infix must be a complete expression
|
||||
#define INFIX_TO_POSTFIX_SIZE(n) (n*21/6)
|
||||
/* The above expression is an estimate of the maximum postfix buffer
|
||||
* size needed for a given infix expression buffer. The actual size
|
||||
* needed is never larger than this value, although it is actually a
|
||||
* few bytes smaller for some sizes.
|
||||
*/
|
||||
|
||||
/* These are not hard limits, just default sizes for the database */
|
||||
|
||||
@@ -1,23 +1,25 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2010 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* postfixPvt.h
|
||||
* Author: Bob Dalesio
|
||||
* Original Author: Bob Dalesio
|
||||
* Date: 9-21-88
|
||||
*/
|
||||
|
||||
/* Notes:
|
||||
* 1. The FETCH_A through FETCH_L and STORE_A through STORE_L opcodes must
|
||||
* be contiguous.
|
||||
* 2. The LITERAL opcode is followed by its double value.
|
||||
* 3. You can't quite use strlen() on an RPN buffer, since the literal
|
||||
* double value can contain nil bytes.
|
||||
* 2. The LITERAL opcodes are followed by a binary representation of their
|
||||
* values, but these are not aligned properly.
|
||||
* 3. The var-arg functions MIN, MAX, FINITE and ISNAN are followed by
|
||||
* a byte giving the number of arguments to process.
|
||||
* 4. You can't use strlen() on an RPN buffer since the literal values
|
||||
* can contain zero bytes.
|
||||
*/
|
||||
|
||||
#ifndef INCpostfixPvth
|
||||
@@ -28,7 +30,7 @@
|
||||
typedef enum {
|
||||
END_EXPRESSION = 0,
|
||||
/* Operands */
|
||||
LITERAL, FETCH_VAL,
|
||||
LITERAL_DOUBLE, LITERAL_INT, FETCH_VAL,
|
||||
FETCH_A, FETCH_B, FETCH_C, FETCH_D, FETCH_E, FETCH_F,
|
||||
FETCH_G, FETCH_H, FETCH_I, FETCH_J, FETCH_K, FETCH_L,
|
||||
/* Assignment */
|
||||
|
||||
Reference in New Issue
Block a user