## Formulas in moodss

### Contents:

- 1. About this document
- 2. Expressions
  - 2.1. Operands
  - 2.2. Operators
  - 2.3. Functions
  - 2.4. Error handling
- 3. Formatting
- 4. Advanced usage

### 1. About this document

This document contains general and reference information to help the user create formulas from data cells coming from modules loaded in the moodss application. Once created, the formulas are displayed in formulas tables, described in the general moodss documentation.
This document particularly covers the mathematical expressions that can be used in formulas, including their syntax and the various available operators and functions.

### 2. Expressions

In moodss and moomps, a formula consists of a user defined name, comments and a mathematical expression made of data cells, mathematical operators and functions. The expression is the core of the formula.

An expression consists of a combination of operands (data cells, numbers, mathematical functions, ...), operators (+, -, ...), and parentheses. White space may be used between the operands and operators and parentheses; it is ignored when the result of the formula is internally calculated.

For example, the screen shot below shows the expression used to calculate the memory usage of a computer in percent, obtained by dividing the used memory by the available memory and multiplying the result by 100.

You may notice that something is wrong with this expression, since its result seems to be 0, unexpected since there is some actual memory used. What is happening is that the internal calculation engine (called the calculator in this document), when possible, interprets the operands as integer values.
What we want in this case is to force floating-point numbers calculations, which can be achieved by using a math function to convert one of the memory operands to floating-point, as shown below.

We will now cover in more details all the available features of expressions.

#### 2.1. Operands

Where possible, operands are interpreted as integer values (such as 123), else treated as floating-point numbers (such as 12.345) if that is possible.
An operand may be directly input as a constant value by the user (such as the 100 multiplier in the screen shots above), or dropped from any source of data cells (such as used memory and available memory).

Conversion among internal representations for integer and floating-point operands is done automatically as needed. For arithmetic computations, integers are used until some floating-point number is introduced, after which floating-point is used. For example, the result of 5/4 is 1, while 5/4.0 gives 1.25.
Floating-point results are always displayed and used with a . (dot) or an e so that they will not look like integer values. For example, the result of 20.0/5.0 is 4.0, not 4.

An operand may also be a mathematical function whose arguments have any of the above forms for operands, such as double(127544) (see the functions section).

#### 2.2. Operators

The valid operators are listed below, grouped in decreasing order of precedence:

- - + ~ ! Unary minus, unary plus, bit-wise NOT, logical NOT. Bit-wise NOT may be applied only to integers.
- * / % Multiply, divide, remainder. Remainder may be applied only to integers. The remainder will always have the same sign as the divisor and an absolute value smaller than the divisor.
- + - Add and subtract.
- << >> Left and right shift. Valid for integer operands only. A right shift always propagates the sign bit.
- < > <= >= Boolean less, greater, less than or equal, and greater than or equal. Each operator produces 1 if the condition is true, 0 otherwise.
- == != Boolean equal and not equal. Each operator produces a zero/one result.
- & Bit-wise AND. Valid for integer operands only.
- ^ Bit-wise exclusive OR. Valid for integer operands only.
- | Bit-wise OR. Valid for integer operands only.
- && Logical AND. Produces a 1 result if both operands are non-zero, 0 otherwise. Valid for boolean and numeric (integers or floating-point) operands only.
- || Logical OR. Produces a 0 result if both operands are zero, 1 otherwise. Valid for boolean and numeric (integers or floating-point) operands only.

#### 2.3. Functions

The following specific functions take strictly one data cell (dragged and dropped in moodss formulas interface) as sole argument. They internally use the value of the data cell at the last update of the formula, which means that they return an undefined value the first time they are invoked, since, obviously, there was no previous value for the data cell.

- delta(cell) Returns the difference between the current value of a data cell and its last value, in 64 bit integer form. Equivalent to:
  wide(cell - last(cell)).
  Note: handles 64 bit counters that always grow and wrap around:
  wide(1 - 18446744073709551615) = 2
- delta32(cell) Returns the difference between the current value of a data cell and its last value, in 32 bit integer (always positive) form. Equivalent to:
  (cell - last(cell)) & 0xFFFFFFFF.
  Note: handles 32 bit counters that always grow and wrap around:
  (1 - 4294967295) & 0xFFFFFFFF = 2, (1 - 2) & 0xFFFFFFFF = 4294967295
- diff(cell) Returns the difference between the current value of a data cell and its last value, in floating point form, with maximum precision. Equivalent to: double(cell - last(cell)).
- last(cell) Returns the value of a data cell at the last update time.

Notes:

- Before moodss 21.2 and moomps 5.6, delta() behaved differently on 32 and 64 bit platforms: this has been solved by using either delta() or delta32() based on the handled data and expected behavior.
- A formula is usually updated by the core (moodss or moomps), at the time the dashboard is refreshed, as defined by its poll time. A formula update means the result of the formula is evaluated, using the values of the embedded data cells at the current time, and possibly the values of some of the cells at the time of the last update of the formula (if diff(), delta(), delta32() or last() functions are used). If the formula contains any data cell belonging to an asynchronous module instance, then the formula is updated (or evaluated) at any time the value of a composing asynchronous data cell changes, independently of the dashboard refresh rate (poll time). The value of the last update time (see diff(time)) is updated every time the formula is evaluated.

There is also a special specific function which returns the time difference between updates:

- diff(time) Returns the difference in seconds between the current time and its value at the last update, in floating point form. For example, the formula "diff(cell) / diff(time)" gives the growth rate of a data cell.

The following mathematical functions are also supported in expressions. They work solely with floating-point numbers unless otherwise noted:

- abs(number) Returns the absolute value of number. Number may be either integer or floating-point, and the result is returned in the same form.
- acos(number) Returns the arc cosine of number, in the range [0,PI] radians. Number should be in the range [-1,1].
- asin(number) Returns the arc sine of number, in the range [-PI/2,PI/2] radians. Number should be in the range [-1,1].
- atan(number) Returns the arc tangent of number, in the range [-PI/2,PI/2] radians.
- atan2(y,x) Returns the arc tangent of y/x, in the range [-PI,PI] radians. x and y cannot both be 0. If x is greater than 0, this is equivalent to atan(y/x).
- ceil(number) Returns the smallest integral floating-point value (i.e. with a zero fractional part) not less than number.
- cos(number) Returns the cosine of number, measured in radians.
- cosh(number) Returns the hyperbolic cosine of number. If the result would cause an overflow, an error is returned.
- double(number) If number is a floating-point value, returns number, otherwise converts number to floating-point and returns the converted value.
- exp(number) Returns the exponential of number, defined as e to the power of number. If the result would cause an overflow, an error is returned.
- floor(number) Returns the largest integral floating-point value (i.e. with a zero fractional part) not greater than number.
- fmod(x,y) Returns the floating-point remainder of the division of x by y. If y is 0, an error is returned.
- hypot(x,y) Computes the length of the hypotenuse of a right-angled triangle sqrt(x*x+y*y).
- int(number) If number is an integer value of the same width as the machine word, returns number, otherwise converts number to an integer (of the same size as a machine word, i.e. 32-bits on 32-bit systems, and 64-bits on 64-bit systems) by truncation and returns the converted value.
- log(number) Returns the natural logarithm of number. Number must be a positive value.
- log10(number) Returns the base 10 logarithm of number. Number must be a positive value.
- pow(x,y) Computes the value of x raised to the power y. If x is negative, y must be an integer value.
- round(number) If number is an integer value, returns number, otherwise converts number to integer by rounding and returns the converted value.
- sin(number) Returns the sine of number, measured in radians.
- sinh(number) Returns the hyperbolic sine of number. If the result would cause an overflow, an error is returned.
- sqrt(number) Returns the square root of number. Number must be non-negative.
- tan(number) Returns the tangent of number, measured in radians.
- tanh(number) Returns the hyperbolic tangent of number.
- wide(number) Converts number to an integer value at least 64-bits wide (by sign-extension if number is a 32-bit number) if it is not one already.

#### 2.4. Error handling

Error handling is handled by the internal calculator, and most messages are easy to understand, but careful reading and thorough thinking is always useful...
Note: for experts, it is actually the expr command in a safe Tcl interpreter that reports errors.

Some typical error messaged are explained here (please request new entries as you see fit):

- syntax error in expression "...": variable references require preceding $: means that probably some stray alphabet characters or an invalid mathematical function were left in the expression.
- syntax error in expression "...": premature end of expression: a closing parentheses may be missing.

### 3. Formatting

(to be implemented)

### 4. Advanced usage

Operands integer values may be specified in decimal (the normal case), in octal (if the first character of the operand is 0), or in hexadecimal (if the first two characters of the operand are 0x).

Floating-point numbers may be specified in any of the ways accepted by an ANSI-compliant C compiler (except that the f, F, l, and L suffixes are not permitted). For example, all of the following are valid floating-point numbers: 2.1, 3., 6e4, 7.91e+16. If no numeric interpretation is possible, then it is an error and the result of the expression is ?.

The following operator is also valid:

- x?y:z if-then-else, as in C. If x evaluates to non-zero, then the result is the value of y. Otherwise the result is the value of z.

The following random functions are also supported in expressions:

- rand() Returns a pseudo-random floating-point value in the range [0,1]. Each result from rand completely determines all future results from subsequent calls to rand. The seed of the generator is initialized from the internal clock of the machine or may be set with the srand function.
- srand(number) The number, which must be an integer, is used to reset the seed for the random number generator of rand. Returns the first random number (see rand) from that seed.

Finally, for users fluent in the Tcl language, you may use all the features of the expr command, including strings as operands, as the formula text is directly passed to the expr command, after filling the values of the data cells of course.