eval
Prototype: eval(expression, mode, options)
Return type: string
Description: Returns expression
evaluated according to mode
and options
. Currently only the math
and class
modes with
infix
option are supported for evaluating traditional math
expressions.
All the math is done with the C double
type internally. The results are returned as a string. When the mode
is math
the returned value is a floating-point value formatted to 6 decimal places as a string.
mode
and options
are optional and default to math
and infix
,
respectively.
Example:
vars:
# returns 20.000000
"result" string => eval("200/10", "math", "infix");
When the mode
is class
, the returned string is either false for 0 (!any
) or true for anything else (any
) so it can be used in a class expression under classes
. The ==
operator (see below) is very convenient for this purpose. The actual accepted values for false allow a tiny margin around 0, just like ==
.
Example:
classes:
# the class will be set
"they_are_equal" expression => eval("20 == (200/10)", "class", "infix");
The supported infix mathematical syntax, in order of precedence, is:
(
and)
parentheses for grouping expressions^
operator for exponentiation*
and/
operators for multiplication and division%
operators for modulo operation+
and-
operators for addition and subtraction==
"close enough" operator to tell if two expressions evaluate to the same number, with a tiny margin to tolerate floating point errors. It returns 1 or 0.>=
"greater or close enough" operator with a tiny margin to tolerate floating point errors. It returns 1 or 0.>
"greater than" operator. It returns 1 or 0.<=
"less than or close enough" operator with a tiny margin to tolerate floating point errors. It returns 1 or 0.<
"less than" operator. It returns 1 or 0.
The numbers can be in any format acceptable to the C scanf
function with the %lf
format specifier, followed by the k
, m
, g
, t
, or p
SI units. So e.g. -100
and 2.34m
are valid numbers.
In addition, the following constants are recognized:
e
: 2.7182818284590452354log2e
: 1.4426950408889634074log10e
: 0.43429448190325182765ln2
: 0.69314718055994530942ln10
: 2.30258509299404568402pi
: 3.14159265358979323846pi_2
: 1.57079632679489661923 (pi over 2)pi_4
: 0.78539816339744830962 (pi over 4)1_pi
: 0.31830988618379067154 (1 over pi)2_pi
: 0.63661977236758134308 (2 over pi)2_sqrtpi
: 1.12837916709551257390 (2 over square root of pi)sqrt2
: 1.41421356237309504880 (square root of 2)sqrt1_2
: 0.70710678118654752440 (square root of 1/2)
The following functions can be used, with parentheses:
ceil
andfloor
: the next highest or the previous highest integerlog10
,log2
,log
sqrt
sin
,cos
,tan
,asin
,acos
,atan
abs
: absolute valuestep
: 0 if the argument is negative, 1 otherwise
Arguments:
expression
:string
- Input string - in the range:.*
mode
: - Evaluation type - one ofmath
class
options
: - Evaluation options - one ofinfix
Example:
body common control
{
bundlesequence => { run };
}
body agent control
{
inform => "true";
}
bundle agent run
{
vars:
"values[0]" string => "x"; # bad
"values[1]" string => "+ 200"; # bad
"values[2]" string => "200 + 100";
"values[3]" string => "200 - 100";
"values[4]" string => "- - -"; # bad
"values[5]" string => "2 + 3 - 1";
"values[6]" string => ""; # 0
"values[7]" string => "3 / 0"; # inf but not an error
"values[8]" string => "3^3";
# "values[9]" string => "-1^2.1"; # 'nan' or '-nan' (on some platforms)
"values[10]" string => "sin(20)";
"values[11]" string => "cos(20)";
"values[19]" string => "20 % 3"; # remainder
"values[20]" string => "sqrt(0.2)";
"values[21]" string => "ceil(3.5)";
"values[22]" string => "floor(3.4)";
"values[23]" string => "abs(-3.4)";
"values[24]" string => "-3.4 == -3.4";
"values[25]" string => "-3.400000 == -3.400001";
"values[26]" string => "e";
"values[27]" string => "pi";
"values[28]" string => "100m"; # 100 million
"values[29]" string => "100k"; # 100 thousand
"indices" slist => sort( getindices("values"), int);
"eval[$(indices)]" string => eval("$(values[$(indices)])", "math", "infix");
reports:
"math/infix eval('$(values[$(indices)])') = '$(eval[$(indices)])'";
}
info: eval error: expression could not be parsed (input 'x')
info: eval error: expression could not be parsed (input '+ 200')
info: eval error: expression could not be parsed (input '- - -')
R: math/infix eval('x') = ''
R: math/infix eval('+ 200') = ''
R: math/infix eval('200 + 100') = '300.000000'
R: math/infix eval('200 - 100') = '100.000000'
R: math/infix eval('- - -') = ''
R: math/infix eval('2 + 3 - 1') = '4.000000'
R: math/infix eval('') = '0.000000'
R: math/infix eval('3 / 0') = 'inf'
R: math/infix eval('3^3') = '27.000000'
R: math/infix eval('sin(20)') = '0.912945'
R: math/infix eval('cos(20)') = '0.408082'
R: math/infix eval('20 % 3') = '2.000000'
R: math/infix eval('sqrt(0.2)') = '0.447214'
R: math/infix eval('ceil(3.5)') = '4.000000'
R: math/infix eval('floor(3.4)') = '3.000000'
R: math/infix eval('abs(-3.4)') = '3.400000'
R: math/infix eval('-3.4 == -3.4') = '1.000000'
R: math/infix eval('-3.400000 == -3.400001') = '0.000000'
R: math/infix eval('e') = '2.718282'
R: math/infix eval('pi') = '3.141593'
R: math/infix eval('100m') = '100000000.000000'
R: math/infix eval('100k') = '100000.000000'
info: eval error: expression could not be parsed (input 'x')
info: eval error: expression could not be parsed (input '+ 200')
info: eval error: expression could not be parsed (input '- - -')
info: eval error: expression could not be parsed (input 'x')
info: eval error: expression could not be parsed (input '+ 200')
info: eval error: expression could not be parsed (input '- - -')
This policy can be found in
/var/cfengine/share/doc/examples/eval.cf
and downloaded directly from
github.
History: