001/* A token that contains a 2-D Complex matrix.
002
003 Copyright (c) 1998-2014 The Regents of the University of California.
004 All rights reserved.
005 Permission is hereby granted, without written agreement and without
006 license or royalty fees, to use, copy, modify, and distribute this
007 software and its documentation for any purpose, provided that the above
008 copyright notice and the following two paragraphs appear in all copies
009 of this software.
010
011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
015 SUCH DAMAGE.
016
017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
022 ENHANCEMENTS, OR MODIFICATIONS.
023
024 PT_COPYRIGHT_VERSION_2
025 COPYRIGHTENDKEY
026
027 */
028package ptolemy.data;
029
030import ptolemy.data.expr.ASTPtRootNode;
031import ptolemy.data.expr.ParseTreeEvaluator;
032import ptolemy.data.expr.PtParser;
033import ptolemy.data.type.BaseType;
034import ptolemy.data.type.Type;
035import ptolemy.data.type.TypeLattice;
036import ptolemy.graph.CPO;
037import ptolemy.kernel.util.IllegalActionException;
038import ptolemy.kernel.util.InternalErrorException;
039import ptolemy.math.Complex;
040import ptolemy.math.ComplexMatrixMath;
041
042///////////////////////////////////////////////////////////////////
043//// ComplexMatrixToken
044
045/**
046 A token that contains a 2-D Complex matrix.
047
048 @see ptolemy.math.Complex
049 @author Yuhong Xiong, Christopher Hylands, Steve Neuendorffer
050 @version $Id$
051 @since Ptolemy II 0.2
052 @Pt.ProposedRating Green (neuendor)
053 @Pt.AcceptedRating Yellow (cxh)
054 */
055public class ComplexMatrixToken extends MatrixToken {
056    /** Construct an ComplexMatrixToken with a one by one matrix. The
057     *  only element in the matrix has value 0.0
058     */
059    public ComplexMatrixToken() {
060        _rowCount = 1;
061        _columnCount = 1;
062        _value = new Complex[1][1];
063        _value[0][0] = Complex.ZERO;
064    }
065
066    /** Construct a ComplexMatrixToken with the specified 2-D matrix.
067     *  Make a copy of the matrix and store the copy,
068     *  so that changes on the specified matrix after this token is
069     *  constructed will not affect the content of this token.
070     *  This constructor also ensures that the matrix is initialized
071     *  with zeros if any of the specifies values is null.
072     *  @param value The 2-D Complex matrix.
073     *  @exception IllegalActionException If the specified matrix
074     *   is null.
075     */
076    public ComplexMatrixToken(final Complex[][] value)
077            throws IllegalActionException {
078        if (value == null) {
079            throw new IllegalActionException(
080                    "ComplexMatrixToken: The " + "specified matrix is null.");
081        }
082
083        _initialize(value, DO_COPY);
084    }
085
086    /** Construct a ComplexMatrixToken with the specified 2-D matrix.
087     *  If copy is DO_COPY, make a copy of the matrix and store the copy,
088     *  so that changes on the specified matrix after this token is
089     *  constructed will not affect the content of this token.
090     *  If copy is DO_NOT_COPY, just reference the matrix (do not copy
091     *  its contents). This saves some time and memory.
092     *  The argument matrix should NOT be modified after this constructor
093     *  is called to preserve immutability.
094     *  <p>
095     *  Since the DO_NOT_COPY option requires some care, this constructor
096     *  is protected.
097     *  @param value The 2-D Complex matrix.
098     *  @param copy If {@link ptolemy.data.MatrixToken#DO_COPY}, the the
099     *  value matrix is copied, If {@link
100     *  ptolemy.data.MatrixToken#DO_NOT_COPY}, then the value matrix
101     *  is not copied.
102     *  @exception IllegalActionException If the specified matrix
103     *   is null.
104     */
105    public ComplexMatrixToken(final Complex[][] value, int copy)
106            throws IllegalActionException {
107        if (value == null) {
108            throw new IllegalActionException(
109                    "ComplexMatrixToken: The " + "specified matrix is null.");
110        }
111
112        _initialize(value, copy);
113    }
114
115    /** Construct an ComplexMatrixToken from the specified string.
116     *  @param init A string expression of a 2-D complex matrix.
117     *  @exception IllegalActionException If the string does
118     *   not contain a parsable 2-D complex matrix.
119     */
120    public ComplexMatrixToken(String init) throws IllegalActionException {
121        PtParser parser = new PtParser();
122        ASTPtRootNode tree = parser.generateParseTree(init);
123        Token token = new ParseTreeEvaluator().evaluateParseTree(tree);
124
125        if (token instanceof ComplexMatrixToken) {
126            Complex[][] value = ((ComplexMatrixToken) token).complexMatrix();
127            _initialize(value, DO_COPY);
128        } else {
129            throw new IllegalActionException("A ComplexMatrixToken cannot be"
130                    + " created from the expression '" + init + "'");
131        }
132    }
133
134    /** Construct an ComplexMatrixToken from the specified array of
135     *  tokens.  The tokens in the array must be scalar tokens
136     *  convertible into complex numbers.
137     *  @param tokens The array of tokens, which must contains
138     *  rows*columns ScalarTokens.
139     *  @param rows The number of rows in the matrix to be created.
140     *  @param columns The number of columns in the matrix to be
141     *  created.
142     *  @exception IllegalActionException If the array of tokens is
143     *  null, or the length of the array is not correct, or if one of
144     *  the elements of the array is null, or if one of the elements
145     *  of the array cannot be losslessly converted to an integer.
146     */
147    public ComplexMatrixToken(Token[] tokens, int rows, int columns)
148            throws IllegalActionException {
149        if (tokens == null) {
150            throw new IllegalActionException(
151                    "ComplexMatrixToken: The specified" + " array is null.");
152        }
153
154        if (tokens.length != rows * columns) {
155            throw new IllegalActionException("ComplexMatrixToken: The specified"
156                    + " array is not of the correct length");
157        }
158
159        _rowCount = rows;
160        _columnCount = columns;
161        _value = new Complex[rows][columns];
162
163        for (int i = 0; i < tokens.length; i++) {
164            Token token = tokens[i];
165
166            if (token instanceof ScalarToken) {
167                _value[i / columns][i % columns] = ((ScalarToken) token)
168                        .complexValue();
169            } else if (token == null) {
170                _value[i / columns][i % columns] = Complex.ZERO;
171            } else {
172                throw new IllegalActionException("ComplexMatrixToken: Element "
173                        + i + " in the array with value " + token
174                        + " is not a ScalarToken");
175            }
176        }
177    }
178
179    ///////////////////////////////////////////////////////////////////
180    ////                         public methods                    ////
181
182    /** Return the content of this token as a new 2-D Complex matrix.
183     *  @return A 2-D Complex matrix
184     */
185    @Override
186    public Complex[][] complexMatrix() {
187        return ComplexMatrixMath.allocCopy(_value);
188    }
189
190    /** Convert the specified token into an instance of ComplexMatrixToken.
191     *  This method does lossless conversion.
192     *  If the argument is already an instance of ComplexMatrixToken,
193     *  it is returned without any change. Otherwise, if the argument
194     *  is below ComplexMatrixToken in the type hierarchy, it is converted to
195     *  an instance of ComplexMatrixToken or one of the subclasses of
196     *  ComplexMatrixToken and returned. If none of the above condition is
197     *  met, an exception is thrown.
198     *  @param token The token to be converted to a ComplexMatrixToken.
199     *  @return A ComplexMatrixToken
200     *  @exception IllegalActionException If the conversion cannot
201     *   be carried out.
202     */
203    public static ComplexMatrixToken convert(Token token)
204            throws IllegalActionException {
205        if (token instanceof ComplexMatrixToken) {
206            return (ComplexMatrixToken) token;
207        }
208
209        int compare = TypeLattice.compare(BaseType.COMPLEX_MATRIX, token);
210
211        if (compare == CPO.LOWER || compare == CPO.INCOMPARABLE) {
212            throw new IllegalActionException(
213                    notSupportedIncomparableConversionMessage(token,
214                            "[complex]"));
215        }
216
217        // try Complex
218        //  compare = TypeLattice.compare(BaseType.COMPLEX, token);
219        //         if (compare == CPO.SAME || compare == CPO.HIGHER) {
220        //             Complex[][] result = new Complex[1][1];
221        //             ComplexToken tem = ComplexToken.convert(token);
222        //             result[0][0] = tem.complexValue();
223        //             return new ComplexMatrixToken(result);
224        //         }
225        // try DoubleMatrix
226        compare = TypeLattice.compare(BaseType.DOUBLE_MATRIX, token);
227
228        if (compare == CPO.SAME || compare == CPO.HIGHER) {
229            DoubleMatrixToken tem = DoubleMatrixToken.convert(token);
230            return new ComplexMatrixToken(tem.complexMatrix());
231        }
232
233        // The argument is below ComplexMatrixToken in the type hierarchy,
234        // but I don't recognize it.
235        throw new IllegalActionException(
236                notSupportedConversionMessage(token, "[complex]"));
237    }
238
239    /** Return a new matrix that is a sub-matrix of this matrix.
240     *  @param rowStart The row to start on.
241     *  @param colStart The column to start on.
242     *  @param rowSpan The number of rows to copy.
243     *  @param colSpan The number of columns to copy.
244     *  @return a sub-matrix of this matrix.
245     *  @exception IllegalActionException If the returned matrix is empty or if the specified
246     *   parameters result in out of bounds accesses.
247     */
248    @Override
249    public MatrixToken crop(int rowStart, int colStart, int rowSpan,
250            int colSpan) throws IllegalActionException {
251        Complex[][] value = this.complexMatrix();
252        try {
253            Complex[][] result = new Complex[rowSpan][colSpan];
254            for (int i = 0; i < rowSpan; i++) {
255                System.arraycopy(value[rowStart + i], colStart, result[i], 0,
256                        colSpan);
257            }
258            return new ComplexMatrixToken(result);
259        } catch (ArrayIndexOutOfBoundsException ex) {
260            throw new IllegalActionException(
261                    "Matrix crop indices out of bounds (rowStart = " + rowStart
262                            + ", colStart = " + colStart + ", rowSpan = "
263                            + rowSpan + ", colSpan = " + colSpan + ").");
264        }
265    }
266
267    /** Return true if the argument is an instance of ComplexMatrixToken
268     *  of the same dimensions and the corresponding elements of the matrices
269     *  are equal.
270     *  @param object An instance of Object.
271     *  @return True if the argument is an instance of ComplexMatrixToken
272     *   of the same dimensions and the corresponding elements of the
273     *   matrices are equal.
274     */
275    @Override
276    public boolean equals(Object object) {
277        if (object == null) {
278            return false;
279        }
280        // This test rules out instances of a subclass.
281        if (object.getClass() != getClass()) {
282            return false;
283        }
284
285        ComplexMatrixToken matrixArgument = (ComplexMatrixToken) object;
286
287        if (_rowCount != matrixArgument.getRowCount()) {
288            return false;
289        }
290
291        if (_columnCount != matrixArgument.getColumnCount()) {
292            return false;
293        }
294
295        Complex[][] matrix = matrixArgument.complexMatrix();
296
297        for (int i = 0; i < _rowCount; i++) {
298            for (int j = 0; j < _columnCount; j++) {
299                if (!_value[i][j].equals(matrix[i][j])) {
300                    return false;
301                }
302            }
303        }
304
305        return true;
306    }
307
308    /** Return the number of columns in the matrix.
309     *  @return The number of columns in the matrix.
310     */
311    @Override
312    public int getColumnCount() {
313        return _columnCount;
314    }
315
316    /** Return the element of the matrix at the specified
317     *  row and column in a ComplexToken.
318     *  @param row The row index of the desired element.
319     *  @param column The column index of the desired element.
320     *  @return A ComplexToken containing the matrix element.
321     *  @exception ArrayIndexOutOfBoundsException If the specified
322     *   row or column number is outside the range of the matrix.
323     */
324    @Override
325    public Token getElementAsToken(final int row, final int column)
326            throws ArrayIndexOutOfBoundsException {
327        return new ComplexToken(_value[row][column]);
328    }
329
330    /** Return the element of the contained matrix at the specified
331     *  row and column.
332     *  @param row The row index of the desired element.
333     *  @param column The column index of the desired element.
334     *  @return The Complex at the specified matrix entry.
335     *  @exception ArrayIndexOutOfBoundsException If the specified
336     *   row or column number is outside the range of the matrix.
337     */
338    public Complex getElementAt(final int row, final int column) {
339        return _value[row][column];
340    }
341
342    /** Return the Type of the tokens contained in this matrix token.
343     *  This must be a type representing a scalar token.
344     *  @return BaseType.COMPLEX.
345     */
346    @Override
347    public Type getElementType() {
348        return BaseType.COMPLEX;
349    }
350
351    /** Return the number of rows in the matrix.
352     *  @return The number of rows in the matrix.
353     */
354    @Override
355    public int getRowCount() {
356        return _rowCount;
357    }
358
359    /** Return the type of this token.
360     *  @return BaseType.COMPLEX_MATRIX
361     */
362    @Override
363    public Type getType() {
364        return BaseType.COMPLEX_MATRIX;
365    }
366
367    /** Return a hash code value for this token. This method returns the
368     *  integer portion of the magnitude of the sum of the elements.
369     *  @return A hash code value for this token.
370     */
371    @Override
372    public int hashCode() {
373        Complex sum = new Complex(0);
374
375        for (int i = 0; i < _rowCount; i++) {
376            for (int j = 0; j < _columnCount; j++) {
377                sum = sum.add(_value[i][j]);
378            }
379        }
380
381        return (int) sum.magnitude();
382    }
383
384    /** Join a matrix of matrices into a single matrix by tiling.
385     *  All matrices in the matrix must be of the same type,
386     *  the same type as this matrix. But none of them needs to
387     *  actually be this matrix. This base class simply throws
388     *  an exception. Derived classes provide the implementation.
389     *  The number of columns in the resulting matrix is the sum
390     *  of the number of columns in the first row of the argument.
391     *  The number of rows in the resulting matrix is the sum
392     *  of the number of rows in the first column of the argument.
393     *  The matrices are copied into the result starting at the
394     *  position determined by the first row or column.
395     *  If the matrices overlap, then while copying left to right,
396     *  top-to-bottom, data will be overwritten. If there are gaps,
397     *  the resulting matrix will be filled with zeros.
398     *  @param matrices A two-dimensional array of matrix tokens.
399     *  @return A new matrix token of the same type as the elements
400     *   in the input matrix of matrix tokens.
401     *  @exception IllegalActionException If the types of the matrices
402     *   in the input are not all the same, or if tiling fails due
403     *   to size incompatibilities, or if the input matrix has no
404     *   tokens.
405     */
406    @Override
407    public MatrixToken join(MatrixToken[][] matrices)
408            throws IllegalActionException {
409        if (matrices == null || matrices.length == 0
410                || matrices[0].length == 0) {
411            throw new IllegalActionException("matrixJoin: No input matrices.");
412        }
413        // Calculate the size of the result.
414        // This assumes the matrices tile.
415        int rows = 0;
416        int columns = 0;
417        for (MatrixToken[] matrice : matrices) {
418            rows += matrice[0].getRowCount();
419        }
420        for (int j = 0; j < matrices[0].length; j++) {
421            columns += matrices[0][j].getColumnCount();
422        }
423        Complex[][] tiled = new Complex[rows][columns];
424        int row = 0;
425        for (int i = 0; i < matrices.length; i++) {
426            int column = 0;
427            for (int j = 0; j < matrices[i].length; j++) {
428                if (!(matrices[i][j] instanceof ComplexMatrixToken)) {
429                    throw new IllegalActionException(
430                            "matrixJoin: matrices not all of the same type.");
431                }
432                int rowCount = matrices[i][j].getRowCount();
433                if (row + rowCount > rows) {
434                    rowCount = rows - row;
435                }
436                int columnCount = matrices[i][j].getColumnCount();
437                if (column + columnCount > columns) {
438                    columnCount = columns - column;
439                }
440                ComplexMatrixMath.matrixCopy(matrices[i][j].complexMatrix(), 0,
441                        0, tiled, row, column, rowCount, columnCount);
442                // Starting position for the next column.
443                column += matrices[0][j].getColumnCount();
444            }
445            // Starting position for the next column.
446            row += matrices[i][0].getRowCount();
447        }
448        return new ComplexMatrixToken(tiled);
449    }
450
451    /** Split this matrix into multiple matrices. See the base
452     *  class for documentation.
453     *  @param rows The number of rows per submatrix.
454     *  @param columns The number of columns per submatrix.
455     *  @return An array of matrix tokens.
456     */
457    @Override
458    public MatrixToken[][] split(int[] rows, int[] columns) {
459        MatrixToken[][] result = new MatrixToken[rows.length][columns.length];
460        Complex[][] source = complexMatrix();
461        int row = 0;
462        for (int i = 0; i < rows.length; i++) {
463            int column = 0;
464            for (int j = 0; j < columns.length; j++) {
465                Complex[][] contents = new Complex[rows[i]][columns[j]];
466                int rowspan = rows[i];
467                if (row + rowspan > source.length) {
468                    rowspan = source.length - row;
469                }
470                int columnspan = columns[j];
471                if (column + columnspan > source[0].length) {
472                    columnspan = source[0].length - column;
473                }
474                if (columnspan > 0 && rowspan > 0) {
475                    ComplexMatrixMath.matrixCopy(source, row, column, contents,
476                            0, 0, rowspan, columnspan);
477                }
478                column += columns[j];
479                try {
480                    // Use the copy constructor to ensure zero fill.
481                    result[i][j] = new ComplexMatrixToken(contents);
482                } catch (IllegalActionException e) {
483                    throw new InternalErrorException(e);
484                }
485            }
486            row += rows[i];
487        }
488        return result;
489    }
490
491    /** Return a new Token representing the left multiplicative
492     *  identity. The returned token contains an identity matrix
493     *  whose dimensions are the same as the number of rows of
494     *  the matrix contained in this token.
495     *  @return A new ComplexMatrixToken containing the left multiplicative
496     *   identity.
497     */
498    @Override
499    public Token one() {
500        try {
501            return new ComplexMatrixToken(ComplexMatrixMath.identity(_rowCount),
502                    DO_NOT_COPY);
503        } catch (IllegalActionException illegalAction) {
504            // should not happen
505            throw new InternalErrorException("ComplexMatrixToken.one: "
506                    + "Cannot create identity matrix.");
507        }
508    }
509
510    /** Return a new Token representing the right multiplicative
511     *  identity. The returned token contains an identity matrix
512     *  whose dimensions are the same as the number of columns of
513     *  the matrix contained in this token.
514     *  @return A new ComplexMatrixToken containing the right
515     *   multiplicative identity.
516     */
517    @Override
518    public Token oneRight() {
519        try {
520            return new ComplexMatrixToken(
521                    ComplexMatrixMath.identity(_columnCount), DO_NOT_COPY);
522        } catch (IllegalActionException illegalAction) {
523            // should not happen
524            throw new InternalErrorException("ComplexMatrixToken.oneRight: "
525                    + "Cannot create identity matrix.");
526        }
527    }
528
529    /** Return a new Token representing the additive identity.
530     *  The returned token contains a matrix whose elements are
531     *  all zero, and the size of the matrix is the same as the
532     *  matrix contained in this token.
533     *  @return A new ComplexMatrixToken containing the additive identity.
534     */
535    @Override
536    public Token zero() {
537        try {
538            return new ComplexMatrixToken(
539                    ComplexMatrixMath.zero(_rowCount, _columnCount),
540                    DO_NOT_COPY);
541        } catch (IllegalActionException illegalAction) {
542            // should not happen
543            throw new InternalErrorException(
544                    "ComplexMatrixToken.zero: " + "Cannot create zero matrix.");
545        }
546    }
547
548    ///////////////////////////////////////////////////////////////////
549    ////                         protected methods                 ////
550
551    /** Return a new token whose value is the value of the argument
552     *  Token added to the value of this Token.  It is assumed that
553     *  the type of the argument is ComplexMatrixToken.
554     *  @param rightArgument The token to add to this token.
555     *  @exception IllegalActionException If the units are not
556     *  compatible, or this operation is not supported by the derived
557     *  class.
558     *  @return A new ComplexMatrixToken containing the result.
559     */
560    @Override
561    protected MatrixToken _add(MatrixToken rightArgument)
562            throws IllegalActionException {
563        ComplexMatrixToken convertedArgument = (ComplexMatrixToken) rightArgument;
564        Complex[][] result = ComplexMatrixMath.add(_value,
565                convertedArgument._getInternalComplexMatrix());
566        return new ComplexMatrixToken(result);
567    }
568
569    /** Return a new token whose value is the value of the argument
570     *  Token added to the value of each element of this Token. It is
571     *  assumed that the type of the argument is the same as the type
572     *  of each element of this class or is a matrix with one element.
573     *  @param rightArgument The token to add to this token.
574     *  @exception IllegalActionException If this operation is not
575     *  supported by the derived class.
576     *  @return A new ComplexMatrixToken containing the result.
577     */
578    @Override
579    protected MatrixToken _addElement(Token rightArgument)
580            throws IllegalActionException {
581        Complex scalar;
582        if (rightArgument instanceof ComplexMatrixToken) {
583            if (((ComplexMatrixToken) rightArgument).getRowCount() != 1
584                    || ((ComplexMatrixToken) rightArgument)
585                            .getColumnCount() != 1) {
586                // Throw an exception.
587                return super._moduloElement(rightArgument);
588            }
589            scalar = ((ComplexMatrixToken) rightArgument).getElementAt(0, 0);
590        } else {
591            scalar = ((ComplexToken) rightArgument).complexValue();
592        }
593        Complex[][] result = ComplexMatrixMath.add(_value, scalar);
594        return new ComplexMatrixToken(result);
595    }
596
597    /** Return a new token whose elements are the result of dividing
598     *  the elements of this token by the argument. It is
599     *  assumed that the type of the argument is the same as the type
600     *  of each element of this class or is a matrix with one element.
601     *  @param rightArgument The token that divides this token.
602     *  @exception IllegalActionException If this operation is not
603     *  supported by the derived class.
604     *  @return A new Token containing the result.
605     */
606    @Override
607    protected MatrixToken _divideElement(Token rightArgument)
608            throws IllegalActionException {
609        Complex scalar;
610        if (rightArgument instanceof ComplexMatrixToken) {
611            if (((ComplexMatrixToken) rightArgument).getRowCount() != 1
612                    || ((ComplexMatrixToken) rightArgument)
613                            .getColumnCount() != 1) {
614                // Throw an exception.
615                return super._moduloElement(rightArgument);
616            }
617            scalar = ((ComplexMatrixToken) rightArgument).getElementAt(0, 0);
618        } else {
619            scalar = ((ComplexToken) rightArgument).complexValue();
620        }
621        Complex[][] result = ComplexMatrixMath.divide(_value, scalar);
622        return new ComplexMatrixToken(result);
623    }
624
625    /** Return a reference to the internal 2-D matrix of complex
626     *  numbers that represents this Token. Because no copying is
627     *  done, the contents must NOT be modified to preserve the
628     *  immutability of Token.
629     *  @return A 2-D complex Java matrix.
630     */
631    protected Complex[][] _getInternalComplexMatrix() {
632        return _value;
633    }
634
635    /** Return a new token whose value is the value of the argument
636     *  Token multiplied to the value of this Token.  It is assumed that
637     *  the type of the argument is ComplexMatrixToken.
638     *  @param rightArgument The token to multiply this token by.
639     *  @exception IllegalActionException If the units are not
640     *  compatible, or this operation is not supported by the derived
641     *  class.
642     *  @return A new ComplexMatrixToken containing the result.
643     */
644    @Override
645    protected MatrixToken _multiply(MatrixToken rightArgument)
646            throws IllegalActionException {
647        ComplexMatrixToken convertedArgument = (ComplexMatrixToken) rightArgument;
648        Complex[][] result = ComplexMatrixMath.multiply(_value,
649                convertedArgument._getInternalComplexMatrix());
650        return new ComplexMatrixToken(result);
651    }
652
653    /** Return a new token whose value is the value of this token
654     *  multiplied by the value of the argument token.
655     *  @param rightArgument The token to multiply this token by.
656     *  @exception IllegalActionException If this method is not
657     *   supported by the derived class.
658     *  @return A new ComplexMatrixToken containing the result.
659     */
660    @Override
661    protected MatrixToken _multiplyElement(Token rightArgument)
662            throws IllegalActionException {
663        Complex scalar;
664        if (rightArgument instanceof ComplexMatrixToken) {
665            if (((ComplexMatrixToken) rightArgument).getRowCount() != 1
666                    || ((ComplexMatrixToken) rightArgument)
667                            .getColumnCount() != 1) {
668                // Throw an exception.
669                return super._moduloElement(rightArgument);
670            }
671            scalar = ((ComplexMatrixToken) rightArgument).getElementAt(0, 0);
672        } else {
673            scalar = ((ComplexToken) rightArgument).complexValue();
674        }
675        Complex[][] result = ComplexMatrixMath.multiply(_value, scalar);
676        return new ComplexMatrixToken(result);
677    }
678
679    /** Return a new token whose value is the value of the argument
680     *  Token subtracted to the value of this Token.  It is assumed that
681     *  the type of the argument is ComplexMatrixToken.
682     *  @param rightArgument The token to subtract to this token.
683     *  @exception IllegalActionException If the units are not
684     *  compatible, or this operation is not supported by the derived
685     *  class.
686     *  @return A new ComplexMatrixToken containing the result.
687     */
688    @Override
689    protected MatrixToken _subtract(MatrixToken rightArgument)
690            throws IllegalActionException {
691        ComplexMatrixToken convertedArgument = (ComplexMatrixToken) rightArgument;
692        Complex[][] result = ComplexMatrixMath.subtract(_value,
693                convertedArgument._getInternalComplexMatrix());
694        return new ComplexMatrixToken(result);
695    }
696
697    /** Return a new token whose value is the value of the argument
698     *  Token subtracted from the value of each element of this Token. It is
699     *  assumed that the type of the argument is the same as the type
700     *  of each element of this class or is a matrix with one element.
701     *  @param rightArgument The token to subtract from this token.
702     *  @exception IllegalActionException If this operation is not
703     *  supported by the derived class.
704     *  @return A new Token containing the result.
705     */
706    @Override
707    protected MatrixToken _subtractElement(Token rightArgument)
708            throws IllegalActionException {
709        Complex scalar;
710        if (rightArgument instanceof ComplexMatrixToken) {
711            if (((ComplexMatrixToken) rightArgument).getRowCount() != 1
712                    || ((ComplexMatrixToken) rightArgument)
713                            .getColumnCount() != 1) {
714                // Throw an exception.
715                return super._moduloElement(rightArgument);
716            }
717            scalar = ((ComplexMatrixToken) rightArgument).getElementAt(0, 0);
718        } else {
719            scalar = ((ComplexToken) rightArgument).complexValue();
720        }
721        Complex[][] result = ComplexMatrixMath.add(_value, scalar.negate());
722        return new ComplexMatrixToken(result);
723    }
724
725    /** Return a new token whose value is the value of the argument
726     *  Token subtracted from the value of each element of this Token. It is
727     *  assumed that the type of the argument is the same as the type
728     *  of each element of this class or is a matrix with one element.
729     *  @param rightArgument The token to subtract from this token.
730     *  @exception IllegalActionException If this operation is not
731     *  supported by the derived class.
732     *  @return A new Token containing the result.
733     */
734    @Override
735    protected MatrixToken _subtractElementReverse(Token rightArgument)
736            throws IllegalActionException {
737        Complex scalar;
738        if (rightArgument instanceof ComplexMatrixToken) {
739            if (((ComplexMatrixToken) rightArgument).getRowCount() != 1
740                    || ((ComplexMatrixToken) rightArgument)
741                            .getColumnCount() != 1) {
742                // Throw an exception.
743                return super._moduloElement(rightArgument);
744            }
745            scalar = ((ComplexMatrixToken) rightArgument).getElementAt(0, 0);
746        } else {
747            scalar = ((ComplexToken) rightArgument).complexValue();
748        }
749        Complex[][] result = ComplexMatrixMath
750                .negative(ComplexMatrixMath.add(_value, scalar.negate()));
751        return new ComplexMatrixToken(result);
752    }
753
754    ///////////////////////////////////////////////////////////////////
755    ////                         private methods                   ////
756    // initialize the row and column count and copy the specified
757    // matrix. This method is used by the constructors.
758    private void _initialize(Complex[][] value, int copy) {
759        _rowCount = value.length;
760        _columnCount = value[0].length;
761
762        if (copy == DO_NOT_COPY) {
763            _value = value;
764        } else {
765            // Can't use System.arraycopy() because we have
766            // to ensure that nulls are replaced with zero.
767            _value = new Complex[value.length][value[0].length];
768            for (int i = 0; i < value.length; i++) {
769                for (int j = 0; j < value[0].length; j++) {
770                    if (value[i][j] != null) {
771                        _value[i][j] = value[i][j];
772                    } else {
773                        _value[i][j] = Complex.ZERO;
774                    }
775                }
776            }
777        }
778    }
779
780    ///////////////////////////////////////////////////////////////////
781    ////                         private variables                 ////
782    private Complex[][] _value = null;
783
784    private int _rowCount = 0;
785
786    private int _columnCount = 0;
787}