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:
ceilandfloor: the next highest or the previous highest integerlog10,log2,logsqrtsin,cos,tan,asin,acos,atanabs: absolute valuestep: 0 if the argument is negative, 1 otherwise
Arguments:
expression:string, in the range:.*mode: one ofmathclass
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: