This section presents different examples of programming in the discrete-event domain. There are no pre-defined stars that work with matrices in the discrete-event domain. We will give several examples of DE stars that work with matrices.

This section develops a star in the DE domain that will create an identity matrix. Instead of creating a source star which must schedule itself, we will create a star that fires whenever it receives an new input value. For example, a clock or some other source can be attached to the star to set its firing pattern.

defstar {

name { Identity_M }

domain { DE }

desc { Output a floating-point identity matrix.}

author { Brian L. Evans }

input {

name { input }

type { anytype }

}

output {

name { output }

type { FLOAT_MATRIX_ENV }

}

defstate {

name { rowsCols }

type { int }

default { 2 }

desc {

Number of rows and columns of the output square matrix. }

}

ccinclude { "Matrix.h" }

go {

// Functional Star: pass timestamp without change

completionTime = arrivalTime;

// For messages, you must pass dynamically allocated data

FloatMatrix& result =

*(new FloatMatrix(int(rowsCols),int(rowsCols)));

// Set the contents of the matrix to an identity matrix

result.identity();

// Send the matrix result to the output port

output.put(completionTime) << result;

}

}

This is a functional star because the time stamp on the input particle is not altered. The output is a matrix message. The matrix is a square matrix. In order for the matrix to remain defined after the go method finishes, the matrix result cannot be allocated from local memory. Instead, it must be allocated from global dynamic memory via the new operator. In the syntax for the new operator, the int cast in int(rowsCols) extracts the value from rowsCols which is an instance of the State data structure. The dynamic memory allocated for the matrix will be automatically deleted by the Message class. Then, the matrix is reset to be an identity matrix. Finally, the matrix is sent to the output port with the same time stamp as that of the input data. Note that the syntax to output data in the discrete-event domain differs from the syntax of the synchronous dataflow domain due to the time stamp. In the SDF domain, the output code would be

output%0 << result

In the next example, we will compute the matrix transpose.

defstar {

name { Transpose_M }

domain { DE }

desc { Transpose a floating-point matrix.}

author { Brian L. Evans }

input {

name { input }

type { FLOAT_MATRIX_ENV }

}

output {

name { output }

type { FLOAT_MATRIX_ENV }

}

ccinclude { "Matrix.h" }

go {

// Functional Star: pass timestamp without change

completionTime = arrivalTime;

// Extract the matrix on the input port

Envelope Xpkt;

input.get().getMessage(Xpkt);

const FloatMatrix& Xmatrix =

*(const FloatMatrix *)Xpkt.myData();

// Create a copy of the input matrix

FloatMatrix& xtrans = *(new FloatMatrix(Xmatrix));

// Transpose the matrix

xtrans.transpose();

// Send the matrix result to the output port

output.put(completionTime) << xtrans;

}

}

The key difference between creating an identity matrix and taking a matrix transpose in the DE domain is the conversion of the input data to a matrix. The input data comes in the form of an envelope which is essentially an instance of a class embedded in a message particle. To extract the contents of the message, we first extract the message from the input envelope. Then, we extract the data field from the message and cast it to be a FloatMatrix. Just as in the previous example, we need to allocate dynamic memory to hold the value of the matrix to be output. In this case, we do not have to code the transpose operation since it is already built into the matrix classes.

*Copyright © 1990-1997, University of California. All rights
reserved.*