Expressions
This help topic describes the common syntax of expressions that you can use in string maths, field maths, block maths, DTM maths, and in macro expressions. The variables you can use in a specific maths function are explained in the help topic for that function.
Note: In an expression, quantities are converted between numbers, strings, and booleans automatically. If Surpac cannot convert a quantity, it reports an error. When a real number is converted to a string only the significant digits are displayed and stored in the string variable.
An expression is composed of a single operand or a number of operands joined by operators. A primary operand can be:
- A variable reference (a name starting with a letter or underscore followed by a series of letters, underscores, or digits) - eg. this_is_a_variable_reference
- An array/table reference. An identifier followed by an expression enclosed in square brackets is treated as an array reference. The array index is evaluated as a string so that it is possible to index arrays using arbitrary strings as well as integers. - e.g. a[1], a["abc"], ab[xyz + 1]
- A function call - eg. POW(10, twenty)
- A parenthesised expression - eg. (var_1 + var_2)
- A constant number - eg. 1, 10.2, 5E25, 2.3456E-10
- A constant string. A string is delimited by single quotes (' ') or double quotes (" ") where the closing delimiter must be the same as the opening delimiter. To insert the delimiter character or special characters into strings escape sequences can be used.
- A special identifier. Attribute names containing characters which are
not normally allowed in identifiers can be contained within square brackets
to force Surpac to interpret them correctly.
For a block model this could consist of any printable characters (excluding [ or ]).
e.g. result_attr = [-attr__1.6 b] - 0.1234For a database field, this would include any field name containing - or % characters which would otherwise be confused with operators.
e.g. result_field = [field-1] - field_2
View specific help, in this help topic, for:
More help for, and examples of, variables are provided in String maths, Block maths, Field maths, and DTM maths.
Escape characters
The recognised escape sequence characters are:
| \\ | backslash. Must always be escaped. |
| \' | single quote character. Single quotes do not need to be escaped if the string delimiters are double quotes. |
| \" | double quote character. Double quotes do not need to be escaped if the string delimiters are single quotes. |
| \a | ASCII bell |
| \b | ASCII backspace |
| \e | ASCII escape |
| \f | ASCII form feed |
| \n | ASCII new line |
| \r | ASCII carriage return |
| \t | ASCII horizontal tab |
| \v | ASCII vertical tab |
| \xh | hexadecimal character code where h is a sequence of hexadecimal digits. |
| \o | octal character code where o is a sequence of 1 to 3 octal digits. |
String constants
Examples of string constants are:
``This is a string with a single quote (`) ''
`This is a string with a single quote (\') and a double quote (``) '
`This is a multi-line string. \n With this as the second line.'
Operators
Operators are a shorthand notation for invoking particular functions. As well as MUL(a, b) you can also use a*b for the same result. Care must be taken when using operators to ensure that the association and precedence match your expectations. For example, a**b**c is the same as a**(b**c) since ** groups from the right, whereas a*b*c is the same as (a*b)*c since * groups from the left. Similarly a . b*c + d will be interpreted as (a . (b*c)) + d while a + b*c . d will be interpreted as (a + (b*c)) . d since + and . have the same precedence and group from the left while * has a higher precedence. Keyword operators, such as AND, must be separated from adjoining variables by at least one space.
The operators understood in expressions are detailed in the following table:
| Class (in order of priority) | Associativity | Operator | Example | Equivalence |
|---|---|---|---|---|
| unary | right | + - ~ ! * |
+ a - a ~ a ! a * a |
REAL(a) NEGATE(a) BITNOT(a) NOT(a) VAR(a)- see note below |
| exponential | right | ** | a ** b | POW(a, b) |
| multiplication | left | * / % |
a * b a / b a % b |
MUL(a, b) DIV(a, b) MOD(a, b) |
| addition | left | + - . cat |
a + b a - b a . b a cat b |
ADD(a, b) SUB(a, b) STRCAT(a, b) STRCAT(a, b) |
| shift | left | << >> |
a << b a >> b |
SHIFTL(a, b) SHIFTR(a, b) |
| relational | none | <= < >= > le lt ge gt |
a <= b a < b a >= b a > b a le b a lt b a ge b a gt b |
LE(a, b) LT(a, b) GE(a, b) GT(a, b) STRLE(a, b) STRLT(a, b) STRGE(a, b) STRGT(a, b) |
| equality | none | == != <=> eq ne cmp |
a == b a != b a <=> b a eq b a ne b a cmp b |
EQ(a, b) NE(a, b) CMP(a, b) STREQ(a, b) STRNE(a, b) STRCMP(a, b) |
| bitwise and | left | & | a & b | BITAND(a, b) |
| bitwise or | left | | ^ |
a | b a ^ b |
BITOR(a, b) BITXOR(a, b) |
| logical and | left | && and |
a && b a and b |
AND(a, b) AND(a, b) |
| logical or | left | || or |
a || b a or b |
OR(a, b) OR(a, b) |
| conditional | right | ? : | a ? b : c | IFEXPR(a, b, c) |
Note: Use of the unary * operator can
be confused with the exponential operation when it immediately follows
the binary * operator. To avoid confusion always place a space between
a binary * operator and an immediately following unary * operator.
For example, you wanted to multiply the value contained in variable var
by 2. If you used the expression :-
you would get an error. The following expression must be used instead :-
Safest yet would be to use :-
Functions
The functions available to expressions can be grouped as follows:
- boolean functions
- bitwise functions
- algebraic functions
- string functions
- numeric comparison functions
- string comparison functions
- radian trigonometric functions
- degree trigonometric functions
- angle unit conversion functions
- exponential functions
- conversion functions
- numeric constant functions
- random number generation functions
- datetime functions
- miscellaneous functions
- application specific functions
Boolean Functions
| function | description |
|---|---|
| NOT(a) | evaluate a as a boolean and complement it |
| AND(a, b) | evaluate a and b as booleans and calculate the boolean and of a and b |
| OR(a, b) | evaluate a and b as booleans and calculate the boolean or of a and b |
| XOR(a, b) | evaluate a and b as booleans and calculate the boolean xor of a and b |
| IFEXPR(a, b, c) | evaluate a as a boolean and if a is true then the result of the function is b otherwise it is c |
| IIF(a, b, c) | same as IFEXPR |
Bitwise Functions
| function | description |
|---|---|
| BITNOT(a) | evaluate a as an integer and take the ones-complement |
| BITAND(a, b) | evaluate a and b as integers and calculate the bitwise and |
| BITOR(a, b) | evaluate a and b as integers and calculate the bitwise inclusive or |
| BITXOR(a, b) | evaluate a and b as integers and calculate the bitwise exclusive or |
| SHIFTL(a, b) | evaluate a and b as integers and calculate a shifted left b binary places |
| SHIFTR(a, b) | evaluate a and b as integers and calculate a shifted right b binary places |
Algebraic Functions
| function | description |
|---|---|
| ABS(a) | evaluate a as a real and return the absolute value of a |
| NEGATE(a) | evaluate a as a real and negate it |
| POW(a, b) | evaluate a and b as reals and calculate a raised to the power b |
| MUL(a, b, ...) | evaluate the arguments as reals and multiply them together |
| DIV(a, b) | evaluate a and b as reals and calculate a/b |
| MOD(a, b) | evaluate a and b as reals and calculate a - i*b for some integer i where the result has the same sign as a and magnitude less than the magnitude of b (i.e. the real remainder of a/b) |
| ADD(a, b, ...) | evaluate the arguments as reals and add them together |
| SUB(a, b) | evaluate a and b as reals and calculate a - b |
| SQRT(a) | evaluate a as a real and calculate the square root of a |
String Functions
| function | description |
|---|---|
| STRCAT(a, b, ...) | evaluate the arguments as strings and concatenate them together |
| STRLEN(a) | evaluate a as a string and return its length |
| INDEX(a, b) | evaluate a and b as strings and calculate the offset of the first occurrence of b in a. -1 is returned if b is not in a |
| RINDEX(a, b) | evaluate a and b as strings and calculate the offset of the last occurrence of b in a. -1 is returned if b is not in a |
| SUBSTR(a, b, c) | evaluate a as a string and b and c as integers and calculate the substring of a starting at offset b of length c |
| TRIM(a) | evaluate a as a string and trim leading and trailing spaces from a. e.g. TRIM(" a b c ") = "a b c" |
| TRIML(a) | evaluate a as a string and trim leading spaces from a. e.g. TRIML(" a b c ") = "a b c " |
| TRIMR(a) | evaluate a as a string and trim trailing spaces from a. e.g. TRIMR(" a b c ") = " a b c" |
| SCAN(a, b) | evaluate a and b as strings and return the offset of the first character in a which is also in b. -1 is returned if a and b have no characters in common. e.g. SCAN("abc", "xyz") = -1, SCAN("abc", "dcb") = 1 |
| PARSE(a, b, c) | evaluate a as a string, b as a single
character string and c as an integer then return the c-th field of a using
the character b as a field separator. If c is negative then the fields
are counted from the end of a. e.g. PARSE("a,b,c", ",", 0) == "a", PARSE("a,b,c", ",", 1) == "b", PARSE("a,b,c", ",", 2) == "c", PARSE("a,b,c", ",", 3) == "", PARSE("a,b,c", ",", -1) == "c", PARSE("a,b,c", ",", -2) == "b", PARSE("a,b,c", ",", -3) == "a" |
Numeric Comparison Functions
| function | description |
|---|---|
| LT(a, b) | evaluate a and b as reals and return true if a is less than b |
| GT(a, b) | evaluate a and b as reals and return true if a is greater than b |
| LE(a, b) | evaluate a and b as reals and return true if a is less than or equal to b |
| GE(a, b) | evaluate a and b as reals and return true if a is greater than or equal to b |
| EQ(a, b) | evaluate a and b as reals and return true if a is equal to b |
| NE(a, b) | evaluate a and b as reals and return true if a is not equal to b |
| CMP(a, b) | evaluate a and b as reals and return -1 if a < b, 0 if a = b, and 1 if a > b |
String Comparison Functions
| function | description |
|---|---|
| STRLT(a, b) | evaluate a and b as strings and return true if a is less than b |
| STRGT(a, b) | evaluate a and b as strings and return true if a is greater than b |
| STRLE(a, b) | evaluate a and b as strings and return true if a is less than or equal to b |
| STRGE(a, b) | evaluate a and b as strings and return true if a is greater than or equal to b |
| STREQ(a, b) | evaluate a and b as strings and return true if a is equal to b |
| STRNE(a, b) | evaluate a and b as strings and return true if a is not equal to b |
| STRCMP(a, b) | evaluate a and b as strings and return -1 if a<b, 0 if a=b, and 1 if a>b |
| STRCMP_NC(a, b) | evaluate a and b as strings and return -1 if a<b, 0 if a=b, and 1 if a>b ignoring case |
Radian Trigonometric Functions (all angles in radians)
| function | description |
|---|---|
| SIN(a) | a is evaluated as a real and returns sin(a) |
| COS(a) | a is evaluated as a real and returns cos(a) |
| TAN(a) | a is evaluated as a real and returns tan(a) |
| ASIN(a) | a is evaluated as a real and returns asin(a) in the range [-pi/2, pi/2] |
| ACOS(a) | a is evaluated as a real and returns acos(a) in the range [0.0, pi] |
| ATAN(a) | a is evaluated as a real and returns atan(a) in the range [-pi/2, pi/2] |
| ATAN2(a, b) | a and b are evaluated as reals and returns ATAN(a/b) modified using the signs of a and b to determine the quadrant of the result |
Degree Trigonometric Functions (all angles in degrees)
| function | description |
|---|---|
| SIND(a) | a is evaluated as a real and returns sin(a) |
| COSD(a) | a is evaluated as a real and returns cos(a) |
| TAND(a) | a is evaluated as a real and returns tan(a) |
| ASIND(a) | a is evaluated as a real and returns asin(a) in the range [-90.0, 90.0] |
| ACOSD(a) | a is evaluated as a real and returns acos(a) in the range [0.0, 180.0] |
| ATAND(a) | a is evaluated as a real and returns atan(a) in the range [-90.0, 90.0] |
| ATAN2D(a) | a and b are evaluated as reals and returns ATAND(a/b) modified using the signs of a and b to determine the quadrant of the result |
Angle Unit Conversion Functions
| function | description |
|---|---|
| RTOD(a) | evaluate a as a real and convert from radians to degrees |
| RTOG(a) | evaluate a as a real and convert from radians to grads |
| DTOG(a) | evaluate a as a real and convert from degrees to grads |
| DTOR(a) | evaluate a as a real and convert from degrees to radians |
| GTOR(a) | evaluate a as a real and convert from grads to radians |
| GTOD(a) | evaluate a as a real and convert from grads to degrees |
| DEGTODMS(a) | evaluate a as a real and convert from decimal degrees to a ddd.mmss angle |
| DMSTODEG(a) | evaluate a as a real and convert from a ddd.mmss angle to decimal degrees |
Exponential Functions
| function | description |
|---|---|
| EXP(a) | evaluate a as a real and calculate e raised to the power a |
| EXP2(a) | evaluate a as a real and calculate 2 raised to the power a |
| EXP10(a) | evaluate a as a real and calculate 10 raised to the power a |
| LOG(a) | evaluate a as a real and calculate the natural logarithm of a (ie. the logarithm to the base e) |
| LOG2(a) | evaluate a as a real and calculate the base 2 logarithm of a |
| LOG10(a) | evaluate a as a real and calculate the base 10 logarithm of a |
Conversion Functions
Numeric Constant Functions
| function | description |
|---|---|
| PI() | return pi |
| E() | return e (the base of the natural logarithm) |
Random Number Generation Functions
| function | description |
|---|---|
| FRANDOM() | return a random number uniformly distributed between 0 and 1 |
| SRANDOM(a) | evaluate a as an integer and use it to seed the random number generator and then return a random number as for FRANDOM() |
Datetime Functions
| function | description |
|---|---|
| JULIAN_TO_DATE(a) | evaluate a as an integer and convert it from a Julian date to a character date in the form "DD-MMM-YYYY". The Julian date is defined as the number of days which have elapsed since 1 January 4713 BC. |
| DATE_TO_JULIAN(a) | evaluate a as a string and convert it from a date in the form "DD-MMM-YYYY" to a integral Julian date |
| CPUTIME() | return the CPU time used by this process |
| ELAPSEDTIME() | return the elapsed time since the first call to ELAPSEDTIME() |
| TIME() | return the current date and time in the form "Sun Sep 16 01:03:52 1973" |
Miscellaneous Functions
| function | description |
|---|---|
| STRFILENAME(a, b, c) | evaluate a and c as strings and b as a real and format the result to be a string file name with a as the location, b as the id, and c as the file extension |
| SYSTEM(a) | evaluate a as a string and execute it as an OS command. The result is the return status from the command. |
| CUT(a, b, c) | evaluate a, b, and c as reals and return: b if a < b, c if a > c, otherwise a |
| CUTLO(a, b) | evaluate a and b as reals and return: b if a < b, otherwise a |
| CUTHI(a, b) | evaluate a and b as reals and return: b if a > b, otherwise a |
| SCALE(a, b, c) | evaluate a, b, and c as reals and return: (a - b)*c + b. ie. scale a by c around b |
| MIN(a, b, ...) | evaluate the arguments as reals and return the minimum argument value |
| MAX(a, b, ...) | evaluate the arguments as reals and return the maximum argument value |
| SIGN(a, b) | evaluate a and b as reals and return a number with the magnitude of a and the sign of b. e.g. SIGN(5, 3) = 5, SIGN(-5, 3) = 5, SIGN(5, -3) = -5, SIGN(-5, -3) = -5 |
| VAR(a) | evaluate the argument as a string and return the value of the variable with that name |