Matrix outputs

To put a matrix into an output porthole, the syntax is:

FloatMatrix& tOutMatrix = *(new FloatMatrix(int(numRows),int(numCols)));
// ... do some operations on the outMatrix
Output%0 << tOutMatrix;

The last line is similar to outputting a scalar value. This is because the << operator has been overloaded for MatrixEnvParticle to support PtMatrix class inputs. The standard use of the MessageParticle class requires the programmer to put his message into an envelope first and then use << on the envelope (see Use of the Envelope Class), but this has been specialized so that the extra operation of creating an envelope first is not explicit.

Here is an example of a complete primitive definition with input and output matrices:

defprimitive
{
  name        { SimpleMpy_M }
  domain      { SDF }
  desc
  {
    Does a matrix multiplication of two input Float
matrices A and B to produce matrix C.
Matrix A has dimensions (numRows,X).
Matrix B has dimensions (X,numCols).
Matrix C has dimensions (numRows,numCols).
the programmer need only specify numRows and numCols.
An error will be generated automatically if the
number of columns in A does not match the number of
columns in B.
  }

  input
  {
    name { A_Input }
    type { float_matrix_env }
  }

  input
  {
    name { B_Input }
    type { float_matrix_env }
  }

  output
  {
    name { Output }
    type { float_matrix_env }
  }

  defparameter
  {
    name        { numRows }
    type        { int }
    default     { "2" }
  }

  defparameter
  {
    name        { numCols }
    type        { int }
    default     { "2" }
  }

  ccinclude { "kernel/Matrix.h" }

  go
  {
    // get inputs
    Envelope tAPkt;
    Envelope tBPkt;
    (A_Input%0).getMessage(tAPkt);
    (B_Input%0).getMessage(tBPkt);
    const FloatMatrix& tAMatrix = *(const FloatMatrix*)tAPkt.myData();
    const FloatMatrix& tBMatrix = *(const FloatMatrix*)tBPkt.myData();

    // check for "null" matrix inputs, which could be
    // caused by delays on the input line
    if (tAPkt.empty() || tBPkt.empty())
    {
      // if either input is empty, return a zero
      // matrix with the state dimensions
      FloatMatrix& tResult = *(new FloatMatrix(int(numRows),int(numCols)));
      tResult = 0.0;
      Output%0 << tResult;
    }
    else
    {
      // AMatrix and BMatrix are both valid
      if ((tAMatrix.numRows() != int(numRows)) ||
          (tBMatrix.numCols() != int(numCols)))
      {
        Error::abortRun(*this, "Dimension size of FloatMatrix",
                        " inputs do not match the given ",
                        " state parameters.");
        return;
      }
      //do matrix multiplication
      FloatMatrix& tResult = *(new FloatMatrix(int(numRows),int(numCols)));
      // we could write
      //   tResult = tAMatrix * tBMatrix;
      // but the following is faster
      multiply(tAMatrix,tBMatrix,tResult);
      Output%0 << tResult;
    }
  }
}