EPICS Base  7.0.6.1
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Macros | Functions
postfix.h File Reference

The API for the EPICS Calculation Engine. More...

#include "libComAPI.h"
Include dependency graph for postfix.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define CALCPERFORM_NARGS   12
 Number of input arguments to a calc expression (A-L)
 
#define CALCPERFORM_STACK   80
 Size of the internal partial result stack.
 
Postfix and Infix Buffer Sizes
#define INFIX_TO_POSTFIX_SIZE(n)   ((n)*21/6)
 Calculate required size of postfix buffer from infix. More...
 
#define MAX_INFIX_SIZE   100
 Size of a "standard" infix string. More...
 
#define MAX_POSTFIX_SIZE   INFIX_TO_POSTFIX_SIZE(MAX_INFIX_SIZE)
 Size of a "standard" postfix buffer. More...
 
Calc Engine Error Codes
Note
Changes in these errors must also be made in calcErrorStr().
#define CALC_ERR_NONE   0
 No error.
 
#define CALC_ERR_TOOMANY   1
 Too many results returned.
 
#define CALC_ERR_BAD_LITERAL   2
 Bad numeric literal.
 
#define CALC_ERR_BAD_ASSIGNMENT   3
 Bad assignment target.
 
#define CALC_ERR_BAD_SEPERATOR   4
 Comma without parentheses.
 
#define CALC_ERR_PAREN_NOT_OPEN   5
 Close parenthesis without open.
 
#define CALC_ERR_PAREN_OPEN   6
 Open parenthesis at end of expression.
 
#define CALC_ERR_CONDITIONAL   7
 Unbalanced conditional ?: operators.
 
#define CALC_ERR_INCOMPLETE   8
 Incomplete expression, operand missing.
 
#define CALC_ERR_UNDERFLOW   9
 Runtime stack would underflow.
 
#define CALC_ERR_OVERFLOW   10
 Runtime stack would overflow.
 
#define CALC_ERR_SYNTAX   11
 Syntax error.
 
#define CALC_ERR_NULL_ARG   12
 NULL or empty input argument.
 
#define CALC_ERR_INTERNAL   13
 Internal error, bad element type.
 

Functions

LIBCOM_API long postfix (const char *pinfix, char *ppostfix, short *perror)
 Compile an infix expression into postfix byte-code. More...
 
LIBCOM_API long calcPerform (double *parg, double *presult, const char *ppostfix)
 Run the calculation engine. More...
 
LIBCOM_API long calcArgUsage (const char *ppostfix, unsigned long *pinputs, unsigned long *pstores)
 Find the inputs and outputs of an expression. More...
 
LIBCOM_API const char * calcErrorStr (short error)
 Convert an error code to a string. More...
 
LIBCOM_API void calcExprDump (const char *pinst)
 Disassemble a postfix expression. More...
 

Detailed Description

Author
Bob Dalesio, Andrew Johnson

Defines macros and the routines provided by the calculation engine for subsystems that need to evaluate mathematical expressions.

Definition in file postfix.h.

Macro Definition Documentation

#define INFIX_TO_POSTFIX_SIZE (   n)    ((n)*21/6)

This macro calculates the maximum size of postfix buffer needed for an infix expression buffer of a given size. The argument n must count the trailing nil byte in the input expression string. The actual size needed is never larger than this value, although it is actually a few bytes smaller for some sizes.

The maximum expansion from infix to postfix is for the sub-expression

.1?.1:

which is 6 characters long and results in 21 bytes of postfix:

.1 => LITERAL_DOUBLE + 8 byte value
? => COND_IF
.1 => LITERAL_DOUBLE + 8 byte value
: => COND_ELSE
...
=> COND_END

For other short expressions the factor 21/6 always gives a big enough postfix buffer (proven by hand, look at '1+' and '.1+' as well).

Definition at line 59 of file postfix.h.

#define MAX_INFIX_SIZE   100

This is not a hard limit, just the default size for the database

Definition at line 66 of file postfix.h.

#define MAX_POSTFIX_SIZE   INFIX_TO_POSTFIX_SIZE(MAX_INFIX_SIZE)

This is not a hard limit, just the default size for the database

Definition at line 72 of file postfix.h.

Function Documentation

LIBCOM_API long postfix ( const char *  pinfix,
char *  ppostfix,
short *  perror 
)

Converts an expression from an infix string to postfix byte-code

Parameters
pinfixPointer to the infix string
ppostfixPointer to the postfix buffer
perrorPlace to return an error code
Returns
Non-zero value in event of error

It is the caller's responsibility to ensure that ppostfix points to sufficient storage to hold the postfix expression. The macro INFIX_TO_POSTFIX_SIZE(n) can be used to calculate an appropriate postfix buffer size from the length of the infix buffer.

Note
"n" must count the terminating nil byte too.
  1. The infix expressions that can be used are very similar to the C expression syntax, but with some additions and subtle differences in operator meaning and precedence. The string may contain a series of expressions separated by a semi-colon character ';' any one of which may actually provide the calculation result; however all of the other expressions included must assign their result to a variable. All alphabetic elements described below are case independent, so upper and lower case letters may be used and mixed in the variable and function names as desired. Spaces may be used anywhere within an expression except between the characters that make up a single expression element.
  2. ***Numeric Literals*** The simplest expression element is a numeric literal, any (positive) number expressed using the standard floating point syntax that can be stored as a double precision value. This now includes the values Infinity and NaN (not a number). Note that negative numbers will be encoded as a positive literal to which the unary negate operator is applied.
    • Examples:
      • 1
      • 2.718281828459
      • Inf
  3. ***Constants*** There are three trigonometric constants available to any expression which return a value:
    • pi returns the value of the mathematical constant pi.
    • D2R evaluates to pi/180 which, when used as a multiplier, converts an angle from degrees to radians.
    • R2D evaluates to 180/pi which as a multiplier converts an angle from radians to degrees.
  4. ***Variables*** Variables are used to provide inputs to an expression, and are named using the single letters A through L inclusive or the keyword VAL which refers to the previous result of this calculation. The software that makes use of the expression evaluation code should document how the individual variables are given values; for the calc record type the input links INPA through INPL can be used to obtain these from other record fields, and VAL refers to the the VAL field (which can be overwritten from outside the record via Channel Access or a database link).
  5. ***Variable Assignment Operator*** Recently added is the ability to assign the result of a sub-expression to any of the single letter variables, which can then be used in another sub-expression. The variable assignment operator is the character pair := and must immediately follow the name of the variable to receive the expression value. Since the infix string must return exactly one value, every expression string must have exactly one sub-expression that is not an assignment, which can appear anywhere in the string. Sub-expressions within the string are separated by a semi-colon character.
    • Examples:
      • B; B:=A
      • i:=i+1; a*sin(i*D2R)
  6. ***Arithmetic Operators*** The usual binary arithmetic operators are provided: + - * and / with their usual relative precedence and left-to-right associativity, and - may also be used as a unary negate operator where it has a higher precedence and associates from right to left. There is no unary plus operator, so numeric literals cannot begin with a + sign.

    • Examples:
      • a*b + c
      • a/-4 - b

    Three other binary operators are also provided: % is the integer modulo operator, while the synonymous operators ** and ^ raise their left operand to the power of the right operand. % has the same precedence and associativity as * and /, while the power operators associate left-to-right and have a precedence in between * and unary minus.

    • Examples:
      • e:=a%10;
      • d:=a/10%10;
      • c:=a/100%10;
      • b:=a/1000%10;
      • b*4096+c*256+d*16+e
      • sqrt(a**2 + b**2)
  7. ***Algebraic Functions*** Various algebraic functions are available which take parameters inside parentheses. The parameter separator is a comma.
    • Absolute value: abs(a)
    • Exponential ea: exp(a)
    • Logarithm, base 10: log(a)
    • Natural logarithm (base e): ln(a) or loge(a)
    • n parameter maximum value: max(a, b, ...)
    • n parameter minimum value: min(a, b, ...)
    • Square root: sqr(a) or sqrt(a)
  8. ***Trigonometric Functions*** Standard circular trigonometric functions, with angles expressed in radians:
    • Sine: sin(a)
    • Cosine: cos(a)
    • Tangent: tan(a)
    • Arcsine: asin(a)
    • Arccosine: acos(a)
    • Arctangent: atan(a)
    • 2 parameter arctangent: atan2(a, b)
      Note
      Note that these arguments are the reverse of the ANSI C function, so while C would return arctan(a/b) the calc expression engine returns arctan(b/a)
  9. ***Hyperbolic Trigonometry*** The basic hyperbolic functions are provided, but no inverse functions (which are not provided by the ANSI C math library either).
    • Hyperbolic sine: sinh(a)
    • Hyperbolic cosine: cosh(a)
    • Hyperbolic tangent: tanh(a)
  10. ***Numeric Functions*** The numeric functions perform operations related to the floating point numeric representation and truncation or rounding.
    • Round up to next integer: ceil(a)
    • Round down to next integer: floor(a)
    • Round to nearest integer: nint(a)
    • Test for infinite result: isinf(a)
    • Test for any non-numeric values: isnan(a, ...)
    • Test for all finite, numeric values: finite(a, ...)
    • Random number between 0 and 1: rndm
  11. ***Boolean Operators*** These operators regard their arguments as true or false, where 0.0 is false and any other value is true.
    • Boolean and: a && b
    • Boolean or: a || b
    • Boolean not: !a
  12. ***Bitwise Operators*** The bitwise operators convert their arguments to an integer (by truncation), perform the appropriate bitwise operation and convert back to a floating point value. Unlike in C though, ^ is not a bitwise exclusive-or operator.
    • Bitwise and: a & b or a and b
    • Bitwise or: a | b or a or b
    • Bitwise exclusive or: a xor b
    • Bitwise not (ones complement): ~a or not a
    • Bitwise left shift: a << b
    • Bitwise right shift: a >> b
  13. ***Relational Operators*** Standard numeric comparisons between two values:
    • Less than: a < b
    • Less than or equal to: a <= b
    • Equal to: a = b or a == b
    • Greater than or equal to: a >= b
    • Greater than: a > b
    • Not equal to: a != b or a # b
  14. ***Conditional Operator*** Expressions can use the C conditional operator, which has a lower precedence than all of the other operators except for the assignment operator.
    • condition ? true result : false result
      • Example:
        • a < 360 ? a+1 : 0
  15. ***Parentheses*** Sub-expressions can be placed within parentheses to override operator presence rules. Parentheses can be nested to any depth, but the intermediate value stack used by the expression evaluation engine is limited to 80 results (which require an expression at least 321 characters long to reach).
LIBCOM_API long calcPerform ( double *  parg,
double *  presult,
const char *  ppostfix 
)

Evaluates the postfix expression against a set ot input values.

Parameters
pargPointer to an array of double values for the arguments A-L that can appear in the expression. Note that the argument values may be modified if the expression uses the assignment operator.
presultWhere to put the calculated result, which may be a NaN or Infinity.
ppostfixThe postfix expression created by postfix().
Returns
Status value 0 for OK, or non-zero if an error is discovered during the evaluation process.
LIBCOM_API long calcArgUsage ( const char *  ppostfix,
unsigned long *  pinputs,
unsigned long *  pstores 
)

Software using the calc subsystem may need to know what expression arguments are used and/or modified by a particular expression. It can discover this from the postfix string by calling calcArgUsage(), which takes two pointers pinputs and pstores to a pair of unsigned long bitmaps which return that information to the caller. Passing a NULL value for either of these pointers is legal if only the other is needed.

The least significant bit (bit 0) of the bitmap at *pinputs will be set if the expression depends on the argument A, and so on through bit 11 for the argument L. An argument that is not used until after a value has been assigned to it will not be set in the pinputs bitmap, thus the bits can be used to determine whether a value needs to be supplied for their associated argument or not for the purposes of evaluating the expression.

Bit 0 of the bitmap at *pstores will be set if the expression assigns a value to the argument A, bit 1 for argument B etc.

Parameters
ppostfixA postfix expression created by postfix().
pinputsBitmap pointer.
pstoresBitmap pointer.
Returns
The return value will be non-zero if the ppostfix expression was illegal, otherwise 0.
LIBCOM_API const char* calcErrorStr ( short  error)

Gives out a printable version of an individual error code. The error codes are macros defined here with names starting CALC_ERR_

Parameters
errorError code
Returns
A string representation of the error code
LIBCOM_API void calcExprDump ( const char *  pinst)

Convert the byte-code stream to text and print to stdout.

Parameters
pinstpostfix instructions