TOC PREV NEXT

3.7 Built-In Functions

The expression language includes a set of functions, such as sin(), cos(), etc. The functions that are built in include all static methods of the classes shown in Table 2 on page 115, which together provide a rich set1. The functions currently available are shown in the tables in the appendix, which also show the argument types and return types.

In most cases, a function that operates on scalar arguments can also operate on arrays and matrices. Thus, for example, you can fill a row vector with a sine wave using an expression like

 
sin([0.0:PI/100:1.0]) 

Or you can construct an array as follows,
 
sin({0.0, 0.1, 0.2, 0.3}) 
 
Functions that operate on type double will also generally operate on int or unsignedByte, because these can be losslessly converted to double, but not generally on long or complex.

Tables of available functions are shown in the appendix. For example, Table 4 on page 124 shows trigonometric functions. Note that these operate on double or complex, and hence on int and unsignedByte, which can be losslessly converted to double. The result will always be double. For example,

 
>> cos(0) 
1.0 
 
These functions will also operate on matrices and arrays, in addition to the scalar types shown in the table, as illustrated above. The result will be a matrix or array of the same size as the argument, but always containing elements of type double

Table 5 on page 125 shows other arithmetic functions beyond the trigonometric functions. As with the trigonometric functions, those that indicate that they operate on double will also work on int and unsignedByte, and unless they indicate otherwise, they will return whatever they return when the argument is double. Those functions in the table that take scalar arguments will also operate on matrices and arrays. For example, since the table indicates that the max() function can take int, int as arguments, then by implication, it can also take {int}, {int}. For example,

 
>> max({1, 2}, {2, 1}) 
{2, 2} 
 
Notice that the table also indicates that max() can take {int} as an argument. E.g.
 
>> max({1, 2, 3}) 
3 
 
In the former case, the function is applied pointwise to the two arguments. In the latter case, the returned value is the maximum over all the contents of the single argument.

Table 6 shows functions that only work with matrices, arrays, or records (that is, there is no corresponding scalar operation). Recall that most functions that operate on scalars will also operate on arrays and matricesTable 7 shows utility functions for evaluating expressions given as strings or representing numbers as strings. Of these, the eval() function is the most flexible (see page 117).

A few of the functions have sufficiently subtle properties that they require further explanation. That explanation is here.
eval() and traceEvaluation()

The built-in function eval() will evaluate a string as an expression in the expression language. For example,

 
eval("[1.0, 2.0; 3.0, 4.0]") 
 
will return a matrix of doubles. The following combination can be used to read parameters from a file:
 
eval(readFile("filename")) 
 
where the filename can be relative to the current working directory (where Ptolemy II was started, as reported by the property user.dir), the user's home directory (as reported by the property user.home), or the classpath, which includes the directory tree in which Ptolemy II is installed.

Note that if eval() is used in an Expression actor, then it will be impossible for the type system to infer any more specific output type than general. If you need the output type to be more specific, then you will need to cast the result of eval(). For example, to force it to type double:

 
>> cast(double, eval("pi/2")) 
1.5707963267949 
 
The traceEvaluation() function evaluates an expression given as a string, much like eval(), but instead of reporting the result, reports exactly how the expression was evaluated. This can be used to debug expressions, particularly when the expression language is extended by users.
random(), gaussian()

The functions random() and gaussian() shown in Table 5 on page 125 return one or more random numbers. With the minimum number of arguments (zero or two, respectively), they return a single number. With one additional argument, they return an array of the specified length. With a second additional argument, they return a matrix with the specified number of rows and columns.

There is a key subtlety when using these functions in Ptolemy II. In particular, they are evaluated only when the expression within which they appear is evaluated. The result of the expression may be used repeatedly without re-evaluating the expression. Thus, for example, if the value parameter of the Const actor is set to "random()", then its output will be a random constant, i.e., it will not change on each firing. The output will change, however, on successive runs of the model. In contrast, if this is used in an Expression actor, then each firing triggers an evaluation of the expression, and consequently will result in a new random number.

property()

The property() function accesses system properties by name. Some possibly useful system properties are:

ptolemy.ptII.dir: The directory in which Ptolemy II is installed.
ptolemy.ptII.dirAsURL: The directory in which Ptolemy II is installed, but represented as a URL.
user.dir: The current working directory, which is usually the directory in which the current executable was started.
remainder()
This function computes the remainder operation on two arguments as prescribed by the IEEE 754 standard, which is not the same as the modulo operation computed by the % operator. The result of remainder(x, y) is , where is the integer closest to the exact value of . If two integers are equally close, then is the integer that is even. This yields results that may be surprising, as indicated by the following examples:
 
>> remainder(1,2) 
1.0 
>> remainder(3,2) 
-1.0 
 
Compare this to
 
>> 3%2 
1 
which is different in two ways. The result numerically different and is of type int, whereas remainder() always yields a result of type double. The remainder() function is implemented by the java.lang.Math class, which calls it IEEEremainder(). The documentation for that class gives the following special cases:
If either argument is NaN, or the first argument is infinite, or the second argument is positive zero or negative zero, then the result is NaN.
If the first argument is finite and the second argument is infinite, then the result is the same as the first argument.
DCT() and IDCT()

The DCT function can take one, two, or three arguments. In all three cases, the first argument is an array of length and the DCT returns an

(4)
for from 0 to , where is the size of the specified array and is the size of the DCT. If only one argument is given, then is set to equal the next power of two larger than . If a second argument is given, then its value is the order of the DCT, and the size of the DCT is . If a third argument is given, then it specifies the scaling factors according to the following table:
TABLE 3: Normalization options for the DCT function
Name Third argument Normalization
Normalized
0
Unnormalized
1
Orthonormal
2

The default, if a third argument is not given, is "Normalized."

The IDCT function is similar, and can also take one, two, or three arguments. The formula in this case is

(5) .
1 Moreover, the set of available can easily be extended if you are writing Java code by registering another class that includes static methods (see the PtParser class in the ptolemy.data.expr package).

TOC PREV NEXT