001/* Abstract base class for tokens that contain a 2-D matrix.
002
003 Copyright (c) 1997-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
028 */
029package ptolemy.data;
030
031import java.util.HashSet;
032import java.util.Set;
033
034import ptolemy.data.type.ArrayType;
035import ptolemy.data.type.BaseType;
036import ptolemy.data.type.FixType;
037import ptolemy.data.type.MatrixType;
038import ptolemy.data.type.Type;
039import ptolemy.data.type.TypeLattice;
040import ptolemy.graph.CPO;
041import ptolemy.kernel.util.IllegalActionException;
042import ptolemy.kernel.util.InternalErrorException;
043import ptolemy.math.Complex;
044import ptolemy.math.FixPoint;
045
046///////////////////////////////////////////////////////////////////
047//// MatrixToken
048
049/**
050 Abstract base class for tokens that contain a 2-D matrix.
051 This class defines methods for type conversion among different matrix
052 tokens. The implementation in this base class just throws an exception.
053 Derived classes should override those methods where the corresponding
054 conversion can be achieved without loss of information.
055 Derived classes should call _elementIsNil() when they encounter a nil
056 token during construction.
057
058 @author Yuhong Xiong, Steve Neuendorffer, contributor: Christopher Brooks
059 @version $Id$
060 @since Ptolemy II 0.2
061 @Pt.ProposedRating Yellow (cxh)
062 @Pt.AcceptedRating Red (cxh) nil token code
063 */
064public abstract class MatrixToken extends Token {
065    ///////////////////////////////////////////////////////////////////
066    ////                         public methods                    ////
067
068    /** Return a new token whose value is the sum of this token and
069     *  the argument. Type conversion also occurs here, so that the
070     *  operation is performed at the least type necessary to ensure
071     *  precision.  The returned type is the same as the type chosen
072     *  for the operation.  Generally, this is higher of the type of
073     *  this token and the argument type.  Subclasses should not
074     *  generally override this method, but override the protected
075     *  _add() method to ensure that type conversion is performed
076     *  consistently.
077     *  @param rightArgument The token to add to this token.
078     *  @return A new token containing the result.
079     *  @exception IllegalActionException If the argument token
080     *   and this token are of incomparable types, or the operation
081     *   does not make sense for the given types.
082     */
083    @Override
084    public Token add(Token rightArgument) throws IllegalActionException {
085        // Get the corresponding element type for this matrix type,
086        // and try a scalar operation.
087        Type elementType = getElementType();
088        int typeInfo = TypeLattice.compare(elementType, rightArgument);
089
090        if (typeInfo == CPO.SAME) {
091            Token result = _addElement(rightArgument);
092            return result;
093        } else if (typeInfo == CPO.HIGHER) {
094            Token convertedArgument = elementType.convert(rightArgument);
095
096            try {
097                Token result = _addElement(convertedArgument);
098                return result;
099            } catch (IllegalActionException ex) {
100                // If the type-specific operation fails, then create a better
101                // error message that has the types of the arguments that were
102                // passed in.
103                throw new IllegalActionException(null, ex,
104                        notSupportedMessage("add", this, rightArgument));
105            }
106        }
107
108        // If we get here, then either our element type is lower than
109        // the rightArgument or incomparable to it.
110        typeInfo = TypeLattice.compare(getType(), rightArgument);
111
112        if (typeInfo == CPO.SAME) {
113            Token result = _doAdd(rightArgument);
114            return result;
115        } else if (typeInfo == CPO.HIGHER) {
116            MatrixToken convertedArgument = (MatrixToken) getType()
117                    .convert(rightArgument);
118
119            try {
120                Token result = _doAdd(convertedArgument);
121                return result;
122            } catch (IllegalActionException ex) {
123                // If the type-specific operation fails, then create a
124                // better error message that has the types of the
125                // arguments that were passed in.
126                throw new IllegalActionException(null, ex,
127                        notSupportedMessage("add", this, rightArgument));
128            }
129        } else if (typeInfo == CPO.LOWER) {
130            Token result = rightArgument.addReverse(this);
131            return result;
132        } else {
133            // Items being added are incomparable.
134            // However, addition may still be possible because
135            // the LUB of the types might support it. E.g., [double]+complex,
136            // where the LUB is [complex].
137            Type lubType = (Type) TypeLattice.lattice()
138                    .leastUpperBound(getType(), rightArgument.getType());
139
140            // If the LUB is a new type, try it.
141            if (!lubType.equals(getType())) {
142                Token lub = lubType.convert(this);
143
144                // Caution: convert() might return this again, e.g.
145                // if lubType is general.  Only proceed if the conversion
146                // returned a new type.
147                if (!lub.getType().equals(getType())) {
148                    return lub.add(rightArgument);
149                }
150            }
151
152            throw new IllegalActionException(notSupportedIncomparableMessage(
153                    "add", this, rightArgument));
154        }
155    }
156
157    /** Return a new token whose value is the sum of this token
158     *  and the argument. Type resolution also occurs here, with
159     *  the returned token type chosen to achieve
160     *  a lossless conversion.
161     *  @param leftArgument The token to add this token to.
162     *  @return A new token containing the result.
163     *  @exception IllegalActionException If the argument token
164     *   is not of a type that can be added to this token, or
165     *   the units of this token and the argument token are not the same.
166     */
167    @Override
168    public Token addReverse(ptolemy.data.Token leftArgument)
169            throws IllegalActionException {
170        // Get the corresponding element type for this matrix type,
171        // and try a scalar operation.
172        Type elementType = getElementType();
173        int typeInfo = TypeLattice.compare(leftArgument, elementType);
174
175        if (typeInfo == CPO.LOWER) {
176            Token convertedArgument = elementType.convert(leftArgument);
177
178            try {
179                Token result = _addElement(convertedArgument);
180                return result;
181            } catch (IllegalActionException ex) {
182                // If the type-specific operation fails, then create a
183                // better error message that has the types of the
184                // arguments that were passed in.
185                throw new IllegalActionException(null, ex,
186                        notSupportedMessage("add", this, leftArgument));
187            }
188        } else if (typeInfo == CPO.SAME) {
189            Token result = _addElement(leftArgument);
190            return result;
191        }
192
193        // If we get here, then either our element type is lower than
194        // the leftArgument or incomparable to it.
195        typeInfo = TypeLattice.compare(leftArgument, getType());
196
197        // We would normally expect this to be LOWER, since this will almost
198        // always be called by subtract, so put that case first.
199        if (typeInfo == CPO.LOWER) {
200            MatrixToken convertedArgument = (MatrixToken) getType()
201                    .convert(leftArgument);
202
203            try {
204                Token result = convertedArgument._doAdd(this);
205                return result;
206            } catch (IllegalActionException ex) {
207                // If the type-specific operation fails, then create a
208                // better error message that has the types of the
209                // arguments that were passed in.
210                throw new IllegalActionException(null, ex,
211                        notSupportedMessage("addReverse", this, leftArgument));
212            }
213        } else if (typeInfo == CPO.SAME) {
214            Token result = ((MatrixToken) leftArgument)._doAdd(this);
215            return result;
216        } else if (typeInfo == CPO.HIGHER) {
217            Token result = leftArgument.add(this);
218            return result;
219        } else {
220            // Items being added are incomparable.
221            // However, addition may still be possible because
222            // the LUB of the types might support it. E.g., complex+[double],
223            // where the LUB is [complex].
224            Type lubType = (Type) TypeLattice.lattice()
225                    .leastUpperBound(getType(), leftArgument.getType());
226
227            // If the LUB is a new type, try it.
228            if (!lubType.equals(getType())) {
229                Token lub = lubType.convert(this);
230
231                // Caution: convert() might return this again, e.g.
232                // if lubType is general.  Only proceed if the conversion
233                // returned a new type.
234                if (!lub.getType().equals(getType())) {
235                    return lub.addReverse(leftArgument);
236                }
237            }
238
239            throw new IllegalActionException(notSupportedIncomparableMessage(
240                    "addReverse", this, leftArgument));
241        }
242    }
243
244    /** Create a new instance of a MatrixToken subclass with the
245     *  given number of rows and columns.  The token will contain
246     *  all of the elements of the given array.  The element type
247     *  of the matrix token will be the least upper bound of the
248     *  types of all of the tokens in the given array.  The size
249     *  of the array must be (rows*columns).
250     *  @param tokens an array of Token objects
251     *  @param rows The number of rows.
252     *  @param columns The number of columns.
253     *  @return An instance of a subclass of MatrixToken.
254     *  @exception IllegalActionException If no type exists for the
255     *   matrix token, or the array of tokens is not the right size, or
256     *   the array is null.
257     */
258    public static MatrixToken arrayToMatrix(Token[] tokens, int rows,
259            int columns) throws IllegalActionException {
260        Set<Type> typeTerms = new HashSet<Type>();
261
262        // Find the first non-nil element and get its type
263        Type baseType = BaseType.GENERAL;
264        for (int i = 0; i < tokens.length; i++) {
265            if (!tokens[i].isNil()) {
266                baseType = tokens[i].getType();
267                break;
268            }
269        }
270
271        // If a token is nil, then default to the first type that we
272        // found.
273        for (Token token : tokens) {
274            if (token.isNil()) {
275                typeTerms.add(baseType);
276            } else {
277                typeTerms.add(token.getType());
278            }
279        }
280
281        Type type = (Type) TypeLattice.lattice().leastUpperBound(typeTerms);
282
283        return arrayToMatrix(type, tokens, rows, columns);
284    }
285
286    /** Create a new instance of a MatrixToken subclass with the given
287     *  element type and number of rows and columns.  The token will
288     *  contain all of the elements of the given array.  The size of
289     *  the array must be (rows*columns).
290     *  @param type The type of the MatrixToken.
291     *  @param tokens an array of Token objects
292     *  @param rows The number of rows.
293     *  @param columns The number of columns.
294     *  @return An instance of a subclass of MatrixToken.
295     *  @exception IllegalActionException If the type is not possible,
296     *  or the array of tokens is not the right size, or the array is
297     *  null.
298     */
299    public static MatrixToken arrayToMatrix(Type type, Token[] tokens, int rows,
300            int columns) throws IllegalActionException {
301        MatrixToken token;
302
303        if (type.equals(BaseType.UNKNOWN)) {
304            throw new IllegalActionException(
305                    "Cannot resolve type for " + "matrix construction.");
306        } else if (type.equals(BaseType.BOOLEAN)) {
307            token = new BooleanMatrixToken(tokens, rows, columns);
308        } else if (type.equals(BaseType.INT)) {
309            token = new IntMatrixToken(tokens, rows, columns);
310        } else if (type.equals(BaseType.LONG)) {
311            token = new LongMatrixToken(tokens, rows, columns);
312        } else if (type.equals(BaseType.DOUBLE)) {
313            token = new DoubleMatrixToken(tokens, rows, columns);
314        } else if (type.equals(BaseType.COMPLEX)) {
315            token = new ComplexMatrixToken(tokens, rows, columns);
316        } else if (type.equals(BaseType.UNSIZED_FIX)
317                || type instanceof FixType) {
318            token = new FixMatrixToken(tokens, rows, columns);
319        } else {
320            throw new IllegalActionException(
321                    "Unrecognized type " + type + " for matrix creation.");
322        }
323
324        return token;
325    }
326
327    /** Return the (exact) return type of the arrayToMatrix function
328     *  above.  If the first argument type is an array type, then
329     *  return a matrix type of the same element type, otherwise return
330     *  BaseType.UNKNOWN.
331     *  @param type1 The type of the first argument to the
332     *  corresponding function.
333     *  @param type2 The type of the second argument to the
334     *  corresponding function.
335     *  @param type3 The type of the third argument to the
336     *  corresponding function.
337     *  @return The type of the value returned from the corresponding
338     *  function.
339     *  @exception IllegalActionException If thrown while getting the matrix
340     *  type for type1.
341     */
342    public static Type arrayToMatrixReturnType(Type type1, Type type2,
343            Type type3) throws IllegalActionException {
344        // FIXME: why are type2 and type3 isgnored here?
345        if (type1 instanceof ArrayType) {
346            Type elementType = ((ArrayType) type1).getElementType();
347            return MatrixType.getMatrixTypeForElementType(elementType);
348        } else {
349            return BaseType.UNKNOWN;
350        }
351    }
352
353    /** Return the content of this token as a 2-D boolean matrix.
354     *  In this base class, just throw an exception.
355     *  @return A 2-D boolean matrix.
356     *  @exception IllegalActionException If the token cannot be represented
357     *   as requested (always thrown in this base class).
358     */
359    public boolean[][] booleanMatrix() throws IllegalActionException {
360        throw new IllegalActionException(
361                notSupportedConversionMessage(this, "boolean matrix"));
362    }
363
364    /** Return a copy of the content of this token as a 2-D Complex matrix.
365     *  In this base class, just throw an exception.
366     *  @return A 2-D Complex matrix.
367     *  @exception IllegalActionException If the token cannot be represented
368     *   as requested (always thrown in this base class).
369     */
370    public Complex[][] complexMatrix() throws IllegalActionException {
371        throw new IllegalActionException(
372                notSupportedConversionMessage(this, "complex matrix"));
373    }
374
375    /** Create a new instance of a MatrixToken subclass with the given
376     *  number of rows and columns.  The token will contain all of the
377     *  elements of the given array.  The element type of the matrix
378     *  token will be the least upper bound of the types of all of the
379     *  tokens in the given array.  The size of the array must be
380     *  (rows*columns).
381     *  @param tokens an array of Token objects.
382     *  @param rows The number of rows.
383     *  @param columns The number of columns.
384     *  @return An instance of a subclass of MatrixToken.
385     *  @exception IllegalActionException If no type exists for the
386     *  matrix token, or the array of tokens is not the right size, or
387     *  the array is null.
388     *  @deprecated Use arrayToMatrix() instead.
389     */
390    @Deprecated
391    public static MatrixToken create(Token[] tokens, int rows, int columns)
392            throws IllegalActionException {
393        return arrayToMatrix(tokens, rows, columns);
394    }
395
396    /** Create an array of tokens of the given length.  The first
397     *  token in the sequence will have value start and each succeeding
398     *  token will have the value created by adding the given increment
399     *  to the preceding token.
400     *  @param start The value of the first element of the returned array.
401     *  @param increment The difference between elements in the array.
402     *  @param length The size of the array to create, which must not be
403     *  negative.
404     *  @return An array of tokens of the given length.
405     *  @exception IllegalActionException If the length is negative, or
406     *  tokens of the given type cannot be added together.
407     */
408    public static Token[] createSequence(Token start, Token increment,
409            int length) throws IllegalActionException {
410        Token[] result = new Token[length];
411        Token value = start;
412
413        if (length > 0) {
414            result[0] = start;
415
416            for (int i = 1; i < length; i++) {
417                value = value.add(increment);
418                result[i] = value;
419            }
420        }
421
422        return result;
423    }
424
425    /** Return the (exact) return type of the createSequence function
426     *  above.  The return type is an array type whose element type is
427     *  the least upper bound of the first two types.
428     *  @param type1 The type of the first argument to the
429     *  corresponding function.
430     *  @param type2 The type of the second argument to the
431     *  corresponding function.
432     *  @param type3 The type of the third argument to the
433     *  corresponding function.
434     *  @return The type of the value returned from the corresponding
435     *  function.
436     *  @exception IllegalActionException If thrown while creating a
437     *  new ArrayType object.
438     */
439    public static Type createSequenceReturnType(Type type1, Type type2,
440            Type type3) throws IllegalActionException {
441        return new ArrayType(TypeLattice.leastUpperBound(type1, type2));
442    }
443
444    /** Create an array of tokens of the given length.  The first
445     *  token in the sequence will have value start and each succeeding
446     *  token will have the value created by adding the given increment
447     *  to the preceding token.
448     *  @param start The value of the first element of the returned array.
449     *  @param increment The difference between elements in the array.
450     *  @param length The size of the array to create, which must not be
451     *  negative.
452     *  @return an array of tokens.
453     *  @exception IllegalActionException If the length is negative, or
454     *  tokens of the given type cannot be added together.
455     *  @deprecated Use createSequence() instead.
456     */
457    @Deprecated
458    public static Token[] createTokenSequence(Token start, Token increment,
459            int length) throws IllegalActionException {
460        return createSequence(start, increment, length);
461    }
462
463    /** Return a new matrix that is a sub-matrix of this matrix.
464     *  @param rowStart The row to start on.
465     *  @param colStart The column to start on.
466     *  @param rowSpan The number of rows to copy.
467     *  @param colSpan The number of columns to copy.
468     *  @return subclasses return a sub-matrix of this matrix.  This
469     *  base class does not return, it always throws an exception.
470     *  @exception IllegalActionException If the operation is not
471     *  supported. Always thrown in this base class.
472     */
473    public MatrixToken crop(int rowStart, int colStart, int rowSpan,
474            int colSpan) throws IllegalActionException {
475        throw new IllegalActionException(
476                "crop: Operation not supported on class " + getClass() + ".");
477    }
478
479    /** Count the number of tokens differing by the given increment
480     *  that fit in a range between the given start token and the
481     *  given end token.  This computes, type polymorphically, the
482     *  value floor(((end-start)/increment) + 1).  If the size of the
483     *  sequence cannot be determined, because the increment is zero,
484     *  or the increment is positive and end is greater than start, or
485     *  the increment is negative and start is greater than end,
486     *  then an exception will be thrown.
487     *  @param start The given start token.
488     *  @param increment The increment.
489     *  @param end The given end token
490     *  @return The size of the sequence, which will be greater than zero.
491     *  @exception IllegalActionException If the length of the
492     *  sequence cannot be determined, or the tokens provided do not
493     *  support the zero, isEqualTo, isLessThan, add, divide, or
494     *  subtract operations, or is not convertible to a double token.
495     */
496    public static int determineSequenceLength(ScalarToken start,
497            ScalarToken increment, ScalarToken end)
498            throws IllegalActionException {
499        ScalarToken zero = (ScalarToken) increment.zero();
500
501        if (increment.isEqualTo(increment.zero()).booleanValue()) {
502            throw new IllegalActionException("Sequence length cannot "
503                    + "be determined because the increment is zero.");
504        } else if (increment.isLessThan(zero).booleanValue()
505                && start.isLessThan(end).booleanValue()) {
506            throw new IllegalActionException("Sequence length cannot "
507                    + "be determined because the increment has the wrong sign.");
508        } else if (zero.isLessThan(increment).booleanValue()
509                && end.isLessThan(start).booleanValue()) {
510            throw new IllegalActionException("Sequence length cannot "
511                    + "be determined because the increment has the wrong sign.");
512        } else {
513            ScalarToken diff = (ScalarToken) end.subtract(start)
514                    .divide(increment);
515            int count;
516
517            // UGH...  I don't see how to abstract this nicely...
518            if (diff instanceof LongToken) {
519                count = (int) diff.longValue() + 1;
520            } else if (diff instanceof DoubleToken) {
521                count = (int) diff.doubleValue() + 1;
522            } else {
523                count = diff.intValue() + 1;
524            }
525
526            if (count < 1) {
527                throw new InternalErrorException(
528                        "The determined count does not make sense.");
529            }
530
531            return count;
532        }
533    }
534
535    /** Return a new token whose value is the value of this token
536     *  divided by the value of the argument token.  Division is not
537     *  supported for matrices, so this throws an exception if the
538     *  argument is a matrix. However, if it is a scalar, then division
539     *         is performed elementwise.
540     *  @param rightArgument The token that divides this token.
541     *  @return A new token containing the result.
542     *  @exception IllegalActionException If the operation
543     *   does not make sense for the given types.
544     */
545    @Override
546    public final Token divide(Token rightArgument)
547            throws IllegalActionException {
548        // Get the corresponding element type for this matrix type,
549        // and try a scalar operation.
550        Type elementType = getElementType();
551        int typeInfo = TypeLattice.compare(elementType, rightArgument);
552
553        if (typeInfo == CPO.SAME) {
554            Token result = _divideElement(rightArgument);
555            return result;
556        } else if (typeInfo == CPO.HIGHER) {
557            Token convertedArgument = elementType.convert(rightArgument);
558
559            try {
560                Token result = _divideElement(convertedArgument);
561                return result;
562            } catch (IllegalActionException ex) {
563                // If the type-specific operation fails, then create a better
564                // error message that has the types of the arguments that were
565                // passed in.
566                throw new IllegalActionException(null, ex,
567                        notSupportedMessage("divide", this, rightArgument));
568            }
569        }
570
571        // If we get here, then either our element type is lower than
572        // the rightArgument or incomparable to it.
573        typeInfo = TypeLattice.compare(getType(), rightArgument);
574
575        if (typeInfo == CPO.SAME
576                && ((MatrixToken) rightArgument).getRowCount() == 1
577                && ((MatrixToken) rightArgument).getColumnCount() == 1) {
578            // Dividing a matrix by a matrix. If the divisor has
579            // only one element, then this is OK.
580            return _divideElement(rightArgument);
581        } else if (typeInfo == CPO.HIGHER
582                && ((MatrixToken) rightArgument).getRowCount() == 1
583                && ((MatrixToken) rightArgument).getColumnCount() == 1) {
584            // Dividing a matrix by something that can be converted
585            // to a matrix, which if it has one element is OK.
586            Token convertedArgument = getType().convert(rightArgument);
587
588            try {
589                return _divideElement(convertedArgument);
590            } catch (IllegalActionException ex) {
591                // If the type-specific operation fails, then create a better
592                // error message that has the types of the arguments that were
593                // passed in.
594                throw new IllegalActionException(null, ex,
595                        notSupportedMessage("divide", this, rightArgument));
596            }
597        } else if (typeInfo == CPO.INCOMPARABLE) {
598            // Items being divided are incomparable.
599            // However, division may still be possible because
600            // the LUB of the types might support it. E.g., [double]/complex,
601            // where the LUB is [complex].
602            Type lubType = (Type) TypeLattice.lattice()
603                    .leastUpperBound(getType(), rightArgument.getType());
604
605            // If the LUB is a new type, try it.
606            if (!lubType.equals(getType())) {
607                Token lub = lubType.convert(this);
608
609                // Caution: convert() might return this again, e.g.
610                // if lubType is general.  Only proceed if the conversion
611                // returned a new type.
612                if (!lub.getType().equals(getType())) {
613                    return lub.divide(rightArgument);
614                }
615            }
616        }
617
618        throw new IllegalActionException(
619                notSupportedMessage("divide", this, rightArgument));
620    }
621
622    /** Return a new token whose value is the value of the argument
623     *  token divided by the value of this token.  Division is not
624     *  supported for matrices, so this always throws an exception.
625     *  @param leftArgument The token to be divided by the value of this token.
626     *  @return A new token containing the result.
627     *  @exception IllegalActionException If the argument token and
628     *  this token are of incomparable types, or the operation does
629     *  not make sense for the given types.
630     */
631    @Override
632    public Token divideReverse(Token leftArgument)
633            throws IllegalActionException {
634        throw new IllegalActionException(
635                notSupportedMessage("divideReverse", this, leftArgument));
636    }
637
638    /** Return the content of this token as a 2-D double matrix.
639     *  In this base class, just throw an exception.
640     *  @return A 2-D double matrix.
641     *  @exception IllegalActionException If the token cannot be represented
642     *   as requested (always thrown in this base class).
643     */
644    public double[][] doubleMatrix() throws IllegalActionException {
645        throw new IllegalActionException(
646                notSupportedConversionMessage(this, "double matrix"));
647    }
648
649    /** Return the content of this token as a 2-D fixed point matrix.
650     *  In this base class, just throw an exception.
651     *  @return A 2-D fix matrix.
652     *  @exception IllegalActionException If the token cannot be represented
653     *   as requested (always thrown in this base class).
654     */
655    public FixPoint[][] fixMatrix() throws IllegalActionException {
656        throw new IllegalActionException(
657                notSupportedConversionMessage(this, "FixPoint matrix"));
658    }
659
660    /** Return the number of columns of the matrix.
661     *  @return The number of columns of the matrix.
662     */
663    public abstract int getColumnCount();
664
665    /** Return the element of the matrix at the specified
666     *  row and column wrapped in a token.
667     *  @param row The row index of the desired element.
668     *  @param column The column index of the desired element.
669     *  @return A token containing the matrix element.
670     *  @exception ArrayIndexOutOfBoundsException If the specified
671     *   row or column number is outside the range of the matrix.
672     */
673    public abstract Token getElementAsToken(int row, int column)
674            throws ArrayIndexOutOfBoundsException;
675
676    /** Return the Type of the tokens contained in this matrix token.
677     *  @return A Type.
678     */
679    public abstract Type getElementType();
680
681    /** Return the number of rows of the matrix.
682     *  @return The number of rows of the matrix.
683     */
684    public abstract int getRowCount();
685
686    /** Return the content of this token as a 2-D integer matrix.
687     *  In this base class, just throw an exception.
688     *  @return A 2-D integer matrix.
689     *  @exception IllegalActionException If the token cannot be represented
690     *   as requested (always thrown in this base class).
691     */
692    public int[][] intMatrix() throws IllegalActionException {
693        throw new IllegalActionException(
694                notSupportedConversionMessage(this, "int matrix"));
695    }
696
697    /** Test whether the value of this Token is close to the argument
698     *  Token.  In this base class, we call isEqualTo() and the
699     *  epsilon argument is ignored.  This method should be overridden
700     *  in derived classes such as DoubleToken and ComplexToken to
701     *  provide type specific actions for equality testing using the
702     *  epsilon argument
703     *
704     *  @see #isEqualTo
705     *  @param rightArgument The token to test closeness of this token with.
706     *  @param epsilon The value that we use to determine whether two
707     *  tokens are close.  In this base class, the epsilon argument is
708     *  ignored.
709     *  @return a boolean token that contains the value true if the
710     *   value and units of this token are close to those of the argument
711     *   token.
712     *  @exception IllegalActionException If the argument token is
713     *   not of a type that can be compared with this token.
714     */
715    @Override
716    public final BooleanToken isCloseTo(Token rightArgument, double epsilon)
717            throws IllegalActionException {
718        // Note that if we had absolute(), subtraction() and islessThan()
719        // we could perhaps define this method for all tokens.  However,
720        // Precise classes like IntToken not bother doing the absolute(),
721        // subtraction(), and isLessThan() method calls and should go
722        // straight to isEqualTo().  Also, these methods might introduce
723        // exceptions because of type conversion issues.
724        int typeInfo = TypeLattice.compare(getType(), rightArgument);
725
726        if (typeInfo == CPO.SAME) {
727            return _doIsCloseTo(rightArgument, epsilon);
728        } else if (typeInfo == CPO.HIGHER) {
729            MatrixToken convertedArgument = (MatrixToken) getType()
730                    .convert(rightArgument);
731
732            try {
733                return _doIsCloseTo(convertedArgument, epsilon);
734            } catch (IllegalActionException ex) {
735                // If the type-specific operation fails, then create a better
736                // error message that has the types of the arguments that were
737                // passed in.
738                throw new IllegalActionException(null, null, ex,
739                        notSupportedMessage("isCloseTo", this, rightArgument));
740            }
741        } else if (typeInfo == CPO.LOWER) {
742            return rightArgument.isCloseTo(this, epsilon);
743        } else {
744            throw new IllegalActionException(notSupportedIncomparableMessage(
745                    "isCloseTo", this, rightArgument));
746        }
747    }
748
749    /** Test for equality of the values of this Token and the argument
750     *  Token.  The argument and this token are converted to
751     *  equivalent types, and then compared.  Generally, this is the
752     *  higher of the type of this token and the argument type.  This
753     *  method defers to the _isEqualTo method to perform a
754     *  type-specific equality check.  Derived classes should override
755     *  that method to provide type specific actions for equality
756     *  testing.
757     *
758     *  @see #isCloseTo
759     *  @param rightArgument The token with which to test equality.
760     *  @exception IllegalActionException If this method is not
761     *  supported by the derived class.
762     *  @return A BooleanToken which contains the result of the test.
763     */
764    @Override
765    public final BooleanToken isEqualTo(Token rightArgument)
766            throws IllegalActionException {
767        int typeInfo = TypeLattice.compare(getType(), rightArgument);
768
769        if (typeInfo == CPO.SAME) {
770            return _doIsEqualTo(rightArgument);
771        } else if (typeInfo == CPO.HIGHER) {
772            MatrixToken convertedArgument = (MatrixToken) getType()
773                    .convert(rightArgument);
774
775            try {
776                return _doIsEqualTo(convertedArgument);
777            } catch (IllegalActionException ex) {
778                // If the type-specific operation fails, then create a better
779                // error message that has the types of the arguments that were
780                // passed in.
781                throw new IllegalActionException(null, ex,
782                        notSupportedMessage("isEqualTo", this, rightArgument));
783            }
784        } else if (typeInfo == CPO.LOWER) {
785            return rightArgument.isEqualTo(this);
786        } else {
787            throw new IllegalActionException(notSupportedIncomparableMessage(
788                    "isEqualTo", this, rightArgument));
789        }
790    }
791
792    /** Join a matrix of matrices into a single matrix by tiling.
793     *  All matrices in the matrix must be of the same type,
794     *  the same type as this matrix. But none of them needs to
795     *  actually be this matrix. This base class simply throws
796     *  an exception. Derived classes provide the implementation.
797     *  The number of columns in the resulting matrix is the sum
798     *  of the number of columns in the first row of the argument.
799     *  The number of rows in the resulting matrix is the sum
800     *  of the number of rows in the first column of the argument.
801     *  The matrices are copied into the result starting at the
802     *  position determined by the first row or column.
803     *  If the matrices overlap, then while copying left to right,
804     *  top-to-bottom, data will be overwritten. If there are gaps,
805     *  the resulting matrix will be filled with zeros.
806     *  @param matrices A two-dimensional array of matrix tokens.
807     *  @return A new matrix token of the same type as the elements
808     *   in the input matrix of matrix tokens.
809     *  @exception IllegalActionException If the types of the matrices
810     *   in the input are not all the same, or if tiling fails due
811     *   to size incompatibilities, or if the input matrix has no
812     *   tokens, or the operation is not supported by this matrix class.
813     */
814    public MatrixToken join(MatrixToken[][] matrices)
815            throws IllegalActionException {
816        throw new IllegalActionException(
817                "join: Operation not supported on class " + getClass() + ".");
818    }
819
820    /** Return the content of this matrix as a 2-D long matrix.
821     *  In this base class, just throw an exception.
822     *  @return A 2-D long matrix.
823     *  @exception IllegalActionException If the token cannot be represented
824     *   as requested (always thrown in this base class).
825     */
826    public long[][] longMatrix() throws IllegalActionException {
827        throw new IllegalActionException(
828                notSupportedConversionMessage(this, "long matrix"));
829    }
830
831    /** Create a new instance of ArrayToken that contains the values
832     *  in the specified matrix.
833     *  @param matrix The given matrix.
834     *  @return An array.
835     */
836    public static ArrayToken matrixToArray(MatrixToken matrix) {
837        return matrix.toArray();
838    }
839
840    /** Return the (exact) return type of the toArray function above.  If the
841     *  argument is a matrix type, then return an array type of its
842     *  element type, otherwise return BaseType.UNKNOWN.
843     *  @param type The type of the argument to the corresponding function.
844     *  @return The type of the value returned from the corresponding function.
845     */
846    public static Type matrixToArrayReturnType(Type type) {
847        return toArrayReturnType(type);
848    }
849
850    /** Return a new token whose value is this token
851     *  modulo the value of the argument token.
852     *  @param rightArgument The token that performs modulo on this token.
853     *  @return A new token containing the result.
854     *  @exception IllegalActionException If the operation
855     *   does not make sense for the given types.
856     */
857    @Override
858    public final Token modulo(Token rightArgument)
859            throws IllegalActionException {
860        /*
861         // If the rightArgument is a complex token, throw an error
862         // message as modulo can't be operated.
863         if (rightArgument instanceof ComplexToken)
864         throw new IllegalActionException(
865         notSupportedMessage("modulo", this, rightArgument));
866         */
867
868        // Get the corresponding element type for this matrix type,
869        // and try a scalar operation.
870        Type elementType = getElementType();
871
872        /*
873         // If this is a complex array, throw an error message as modulo
874         // can't be performed on it
875         if (elementType == BaseType.COMPLEX)
876         throw new IllegalActionException(
877         notSupportedMessage("modulo", this, rightArgument));
878         */
879        int typeInfo = TypeLattice.compare(elementType, rightArgument);
880
881        if (typeInfo == CPO.SAME) {
882            Token result = _moduloElement(rightArgument);
883            return result;
884        } else if (typeInfo == CPO.HIGHER) {
885            Token convertedArgument = elementType.convert(rightArgument);
886
887            try {
888                Token result = _moduloElement(convertedArgument);
889                return result;
890            } catch (IllegalActionException ex) {
891                // If the type-specific operation fails, then create a better
892                // error message that has the types of the arguments that were
893                // passed in.
894                throw new IllegalActionException(null, ex,
895                        notSupportedMessage("modulo", this, rightArgument));
896            }
897        }
898
899        // If we get here, then either our element type is lower than
900        // the rightArgument or incomparable to it.
901        typeInfo = TypeLattice.compare(getType(), rightArgument);
902
903        if (typeInfo == CPO.SAME) {
904            // Dividing a matrix by a matrix. If the divisor has
905            // only one element, then this is OK.
906            return _moduloElement(rightArgument);
907        } else if (typeInfo == CPO.HIGHER) {
908            // Dividing a matrix by something that can be converted
909            // to a matrix, which if it has one element is OK.
910            Token convertedArgument = getType().convert(rightArgument);
911
912            try {
913                return _moduloElement(convertedArgument);
914            } catch (IllegalActionException ex) {
915                // If the type-specific operation fails, then create a better
916                // error message that has the types of the arguments that were
917                // passed in.
918                throw new IllegalActionException(null, ex,
919                        notSupportedMessage("modulo", this, rightArgument));
920            }
921        } else if (typeInfo == CPO.INCOMPARABLE) {
922            // Items being added are incomparable.
923            // However, division may still be possible because
924            // the LUB of the types might support it. E.g., [double]/complex,
925            // where the LUB is [complex].
926            Type lubType = (Type) TypeLattice.lattice()
927                    .leastUpperBound(getType(), rightArgument.getType());
928
929            // If the LUB is a new type, try it.
930            if (!lubType.equals(getType())) {
931                Token lub = lubType.convert(this);
932
933                // Caution: convert() might return this again, e.g.
934                // if lubType is general.  Only proceed if the conversion
935                // returned a new type.
936                if (!lub.getType().equals(getType())) {
937                    return lub.modulo(rightArgument);
938                }
939            }
940        }
941
942        throw new IllegalActionException(
943                notSupportedMessage("modulo", this, rightArgument));
944    }
945
946    /** Return a new token whose value is the value of the argument token
947     *  modulo the value of this token.  Since modulo is not
948     *  supported for matrices, this always throws an exception.
949     *  @param leftArgument The token to apply modulo to by the value
950     *  of this token.
951     *  @return A new token containing the result.
952     *  @exception IllegalActionException If the the operation does
953     *  not make sense for the given types.
954     */
955    @Override
956    public final Token moduloReverse(Token leftArgument)
957            throws IllegalActionException {
958        throw new IllegalActionException(
959                notSupportedMessage("moduloReverse", this, leftArgument));
960    }
961
962    /** Return a new token whose value is the value of this token
963     *  multiplied by the value of the argument token.  Type
964     *  conversion also occurs here, so that the operation is
965     *  performed at the least type necessary to ensure precision.
966     *  The returned type is the same as the type chosen for the
967     *  operation.  Generally, this is higher of the type of this
968     *  token and the argument type.  This class overrides the base
969     *  class to perform conversion from scalars to matrices
970     *  appropriately for matrix multiplication.  Subclasses should
971     *  not generally override this method, but override the protected
972     *  _multiply() method to ensure that type conversion is performed
973     *  consistently.
974     *  @param rightArgument The token to multiply this token by.
975     *  @return A new token containing the result.
976     *  @exception IllegalActionException If the argument token
977     *   and this token are of incomparable types, or the operation
978     *   does not make sense for the given types.
979     */
980    @Override
981    public final Token multiply(Token rightArgument)
982            throws IllegalActionException {
983        // MatrixType type = (MatrixType)getType();
984        // Get the corresponding element type for this matrix type,
985        // and try a scalar operation.
986        Type elementType = getElementType();
987        int typeInfo = TypeLattice.compare(elementType, rightArgument);
988
989        if (typeInfo == CPO.SAME) {
990            Token result = _multiplyElement(rightArgument);
991            return result;
992        } else if (typeInfo == CPO.HIGHER) {
993            Token convertedArgument = elementType.convert(rightArgument);
994
995            try {
996                Token result = _multiplyElement(convertedArgument);
997                return result;
998            } catch (IllegalActionException ex) {
999                // If the type-specific operation fails, then create a better
1000                // error message that has the types of the arguments that were
1001                // passed in.
1002                throw new IllegalActionException(null, ex,
1003                        notSupportedMessage("multiply", this, rightArgument));
1004            }
1005        }
1006
1007        // Argument must be a matrix or incomparable.
1008        typeInfo = TypeLattice.compare(getType(), rightArgument);
1009
1010        if (typeInfo == CPO.SAME) {
1011            Token result = _doMultiply(rightArgument);
1012            return result;
1013        } else if (typeInfo == CPO.HIGHER) {
1014            MatrixToken convertedArgument = (MatrixToken) getType()
1015                    .convert(rightArgument);
1016
1017            try {
1018                Token result = _doMultiply(convertedArgument);
1019                return result;
1020            } catch (IllegalActionException ex) {
1021                // If the type-specific operation fails, then create a
1022                // better error message that has the types of the
1023                // arguments that were passed in.
1024                throw new IllegalActionException(null, ex,
1025                        notSupportedMessage("multiply", this, rightArgument));
1026            }
1027        } else if (typeInfo == CPO.LOWER) {
1028            Token result = rightArgument.multiplyReverse(this);
1029            return result;
1030        } else {
1031            // Items being multiplied are incomparable.
1032            // However, multiplication may still be possible because
1033            // the LUB of the types might support it. E.g., [double]*complex,
1034            // where the LUB is [complex].
1035            Type lubType = (Type) TypeLattice.lattice()
1036                    .leastUpperBound(getType(), rightArgument.getType());
1037
1038            // If the LUB is a new type, try it.
1039            if (!lubType.equals(getType())) {
1040                Token lub = lubType.convert(this);
1041
1042                // Caution: convert() might return this again, e.g.
1043                // if lubType is general.  Only proceed if the conversion
1044                // returned a new type.
1045                if (!lub.getType().equals(getType())) {
1046                    return lub.multiply(rightArgument);
1047                }
1048            }
1049
1050            throw new IllegalActionException(notSupportedIncomparableMessage(
1051                    "multiply", this, rightArgument));
1052        }
1053    }
1054
1055    /** Return a new token whose value is the value of the argument token
1056     *  multiplied by the value of this token.
1057     *  Type resolution also occurs here, with the returned token
1058     *  type chosen to achieve a lossless conversion.
1059     *  @param leftArgument The token to be multiplied by the value of
1060     *   this token.
1061     *  @return A new token containing the result.
1062     *  @exception IllegalActionException If the argument token
1063     *   is not of a type that can be multiplied by this token.
1064     */
1065    @Override
1066    public final Token multiplyReverse(Token leftArgument)
1067            throws IllegalActionException {
1068        // Get the corresponding element type for this matrix type,
1069        // and try a scalar operation.
1070        Type elementType = getElementType();
1071        int typeInfo = TypeLattice.compare(leftArgument, elementType);
1072
1073        if (typeInfo == CPO.LOWER) {
1074            Token convertedArgument = elementType.convert(leftArgument);
1075
1076            try {
1077                Token result = _multiplyElement(convertedArgument);
1078                return result;
1079            } catch (IllegalActionException ex) {
1080                // If the type-specific operation fails, then create a
1081                // better error message that has the types of the
1082                // arguments that were passed in.
1083                throw new IllegalActionException(null, ex,
1084                        notSupportedMessage("multiply", this, leftArgument));
1085            }
1086        } else if (typeInfo == CPO.SAME) {
1087            Token result = _multiplyElement(leftArgument);
1088            return result;
1089        }
1090
1091        // Must be a matrix or incomparable.
1092        typeInfo = TypeLattice.compare(leftArgument, getType());
1093
1094        // We would normally expect this to be LOWER, since this will almost
1095        // always be called by subtract, so put that case first.
1096        if (typeInfo == CPO.LOWER) {
1097            MatrixToken convertedArgument = (MatrixToken) getType()
1098                    .convert(leftArgument);
1099
1100            try {
1101                Token result = convertedArgument._doMultiply(this);
1102                return result;
1103            } catch (IllegalActionException ex) {
1104                // If the type-specific operation fails, then create a
1105                // better error message that has the types of the
1106                // arguments that were passed in.
1107                throw new IllegalActionException(null, ex, notSupportedMessage(
1108                        "multiplyReverse", this, leftArgument));
1109            }
1110        } else if (typeInfo == CPO.SAME) {
1111            Token result = ((MatrixToken) leftArgument)._doMultiply(this);
1112            return result;
1113        } else if (typeInfo == CPO.HIGHER) {
1114            Token result = leftArgument.multiply(this);
1115            return result;
1116        } else {
1117            // Items being multiplied are incomparable.
1118            // However, multiplication may still be possible because
1119            // the LUB of the types might support it. E.g., [double]*complex,
1120            // where the LUB is [complex].
1121            Type lubType = (Type) TypeLattice.lattice()
1122                    .leastUpperBound(getType(), leftArgument.getType());
1123
1124            // If the LUB is a new type, try it.
1125            if (!lubType.equals(getType())) {
1126                Token lub = lubType.convert(this);
1127
1128                // Caution: convert() might return this again, e.g.
1129                // if lubType is general.  Only proceed if the conversion
1130                // returned a new type.
1131                if (!lub.getType().equals(getType())) {
1132                    return lub.multiplyReverse(leftArgument);
1133                }
1134            }
1135
1136            throw new IllegalActionException(notSupportedIncomparableMessage(
1137                    "multiplyReverse", leftArgument, this));
1138        }
1139    }
1140
1141    /** Return a new Token representing the right multiplicative
1142     *  identity. The returned token contains an identity matrix
1143     *  whose dimensions are the same as the number of columns of
1144     *  the matrix contained in this token.
1145     *  The implementation in this base class just throws an
1146     *  exception. This method should be overridden in the subclass
1147     *  when the right multiplicative identity exists.
1148     *  @return A new MatrixToken containing the right multiplicative
1149     *   identity.
1150     *  @exception IllegalActionException If this method is not
1151     *   supported by the derived class.
1152     */
1153    public Token oneRight() throws IllegalActionException {
1154        throw new IllegalActionException("Right multiplicative identity "
1155                + "not supported on " + getClass().getName() + " objects.");
1156    }
1157
1158    /** Split this matrix into multiple matrices. In this base
1159     *  class, this method simply throws an exception. Derived
1160     *  classes provide the implementation.
1161     *  <p>
1162     *  The matrices are produced from submatrices extracted
1163     *  left-to-right, top-to-bottom, in a raster scan pattern.
1164     *  For example, if <i>rowSplit</i> = {1, 2},
1165     *  <i>columnSplit</i> = {2, 1}, and the input matrix is
1166     *  as follows:
1167     *  <pre>
1168     *    1  2  3
1169     *    4  5  6
1170     *    7  8  9
1171     *  </pre>
1172     *  then the first matrix out is a column vector:
1173     *  <pre>
1174     *    1
1175     *    4
1176     *  </pre>
1177     *  The second matrix out is
1178     *  <pre>
1179     *    2  3
1180     *    5  6
1181     *  </pre>
1182     *  The third is
1183     *  <pre>
1184     *    7
1185     *  </pre>
1186     *  (a 1x1 matrix) and the fourth is
1187     *  <pre>
1188     *   8  9
1189     *  </pre>
1190     *  a row vector.
1191     *  If the input does not have enough elements to fill the specified
1192     *  output matrices, then zeros (of the same type as the input elements)
1193     *  are used. If the input is larger than is required to fill the specified
1194     *  output, then the additional values are discarded.
1195     *  @param rows The number of rows per submatrix.
1196     *  @param columns The number of columns per submatrix.
1197     *  @return An array of matrix tokens.
1198     *  @exception IllegalActionException If the operation is not supported.
1199     */
1200    public MatrixToken[][] split(int[] rows, int[] columns)
1201            throws IllegalActionException {
1202        throw new IllegalActionException(
1203                "split: Operation not supported on class " + getClass() + ".");
1204    }
1205
1206    /** Return a new token whose value is the value of the argument token
1207     *  subtracted from the value of this token.   Type conversion
1208     *  also occurs here, so that the operation is performed at the
1209     *  least type necessary to ensure precision.  The returned type
1210     *  is the same as the type chosen for the operation.  Generally,
1211     *  this is higher of the type of this token and the argument
1212     *  type.  Subclasses should not override this method,
1213     *  but override the protected _subtract() method to ensure that type
1214     *  conversion is performed consistently.
1215     *  @param rightArgument The token to subtract from this token.
1216     *  @return A new token containing the result.
1217     *  @exception IllegalActionException If the argument token
1218     *   and this token are of incomparable types, or the operation
1219     *   does not make sense for the given types.
1220     */
1221    @Override
1222    public final Token subtract(Token rightArgument)
1223            throws IllegalActionException {
1224        // Get the corresponding element type for this matrix type,
1225        // and try a scalar operation.
1226        Type elementType = getElementType();
1227        int typeInfo = TypeLattice.compare(elementType, rightArgument);
1228
1229        if (typeInfo == CPO.SAME) {
1230            Token result = _subtractElement(rightArgument);
1231            return result;
1232        } else if (typeInfo == CPO.HIGHER) {
1233            Token convertedArgument = elementType.convert(rightArgument);
1234
1235            try {
1236                Token result = _subtractElement(convertedArgument);
1237                return result;
1238            } catch (IllegalActionException ex) {
1239                // If the type-specific operation fails, then create a better
1240                // error message that has the types of the arguments that were
1241                // passed in.
1242                throw new IllegalActionException(null, ex,
1243                        notSupportedMessage("subtract", this, rightArgument));
1244            }
1245        }
1246
1247        // If we get here, then either our element type is lower than
1248        // the rightArgument or incomparable to it.
1249        typeInfo = TypeLattice.compare(getType(), rightArgument);
1250
1251        if (typeInfo == CPO.SAME) {
1252            Token result = _doSubtract(rightArgument);
1253            return result;
1254        } else if (typeInfo == CPO.HIGHER) {
1255            MatrixToken convertedArgument = (MatrixToken) getType()
1256                    .convert(rightArgument);
1257
1258            try {
1259                Token result = _doSubtract(convertedArgument);
1260                return result;
1261            } catch (IllegalActionException ex) {
1262                // If the type-specific operation fails, then create a
1263                // better error message that has the types of the
1264                // arguments that were passed in.
1265                throw new IllegalActionException(null, ex,
1266                        notSupportedMessage("subtract", this, rightArgument));
1267            }
1268        } else if (typeInfo == CPO.LOWER) {
1269            Token result = rightArgument.subtractReverse(this);
1270            return result;
1271        } else {
1272            // Items being subracted are incomparable.
1273            // However, subtraction may still be possible because
1274            // the LUB of the types might support it. E.g., [double]-complex,
1275            // where the LUB is [complex].
1276            Type lubType = (Type) TypeLattice.lattice()
1277                    .leastUpperBound(getType(), rightArgument.getType());
1278
1279            // If the LUB is a new type, try it.
1280            if (!lubType.equals(getType())) {
1281                Token lub = lubType.convert(this);
1282
1283                // Caution: convert() might return this again, e.g.
1284                // if lubType is general.  Only proceed if the conversion
1285                // returned a new type.
1286                if (!lub.getType().equals(getType())) {
1287                    return lub.subtract(rightArgument);
1288                }
1289            }
1290
1291            throw new IllegalActionException(notSupportedIncomparableMessage(
1292                    "subtract", this, rightArgument));
1293        }
1294    }
1295
1296    /** Return a new token whose value is the value of this token
1297     *  subtracted from the value of the argument token.
1298     *  Type resolution also occurs here, with the returned token type
1299     *  chosen to achieve a lossless conversion.
1300     *  @param leftArgument The token to subtract this token from.
1301     *  @return A new token containing the result.
1302     *  @exception IllegalActionException If the argument token is not
1303     *  of a type that can be subtracted to this token, or the units
1304     *  of this token and the argument token are not the same.
1305     */
1306    @Override
1307    public final Token subtractReverse(Token leftArgument)
1308            throws IllegalActionException {
1309        // Get the corresponding element type for this matrix type,
1310        // and try a scalar operation.
1311        Type elementType = getElementType();
1312        int typeInfo = TypeLattice.compare(leftArgument, elementType);
1313
1314        if (typeInfo == CPO.LOWER) {
1315            Token convertedArgument = elementType.convert(leftArgument);
1316
1317            try {
1318                Token result = _subtractElementReverse(convertedArgument);
1319                return result;
1320            } catch (IllegalActionException ex) {
1321                // If the type-specific operation fails, then create a
1322                // better error message that has the types of the
1323                // arguments that were passed in.
1324                throw new IllegalActionException(null, ex,
1325                        notSupportedMessage("subtract", this, leftArgument));
1326            }
1327        } else if (typeInfo == CPO.SAME) {
1328            Token result = _subtractElementReverse(leftArgument);
1329            return result;
1330        }
1331
1332        // If we get here, then either our element type is lower than
1333        // the rightArgument or incomparable to it.
1334        typeInfo = TypeLattice.compare(leftArgument, getType());
1335
1336        // We would normally expect this to be LOWER, since this will almost
1337        // always be called by subtract, so put that case first.
1338        if (typeInfo == CPO.LOWER) {
1339            MatrixToken convertedArgument = (MatrixToken) getType()
1340                    .convert(leftArgument);
1341
1342            try {
1343                Token result = convertedArgument._doSubtract(this);
1344                return result;
1345            } catch (IllegalActionException ex) {
1346                // If the type-specific operation fails, then create a
1347                // better error message that has the types of the
1348                // arguments that were passed in.
1349                throw new IllegalActionException(null, ex, notSupportedMessage(
1350                        "subtractReverse", this, leftArgument));
1351            }
1352        } else if (typeInfo == CPO.SAME) {
1353            Token result = ((MatrixToken) leftArgument)._doSubtract(this);
1354            return result;
1355        } else if (typeInfo == CPO.HIGHER) {
1356            Token result = leftArgument.subtract(this);
1357            return result;
1358        } else {
1359            // Items being subtracted are incomparable.
1360            // However, subtraction may still be possible because
1361            // the LUB of the types might support it. E.g., complex-[double],
1362            // where the LUB is [complex].
1363            Type lubType = (Type) TypeLattice.lattice()
1364                    .leastUpperBound(getType(), leftArgument.getType());
1365
1366            // If the LUB is a new type, try it.
1367            if (!lubType.equals(getType())) {
1368                Token lub = lubType.convert(this);
1369
1370                // Caution: convert() might return this again, e.g.
1371                // if lubType is general.  Only proceed if the conversion
1372                // returned a new type.
1373                if (!lub.getType().equals(getType())) {
1374                    return lub.subtractReverse(leftArgument);
1375                }
1376            }
1377
1378            throw new IllegalActionException(notSupportedIncomparableMessage(
1379                    "subtractReverse", this, leftArgument));
1380        }
1381    }
1382
1383    /** Return an ArrayToken containing the all the values of this
1384     *  matrix token.  The type of the tokens in the array is consistent
1385     *  with the type of this token.
1386     *
1387     *  @return An ArrayToken containing the elements of this matrix in
1388     *  row-scanned order.
1389     */
1390    public ArrayToken toArray() {
1391        int rowCount = getRowCount();
1392        int columnCount = getColumnCount();
1393        Token[] output = new Token[rowCount * columnCount];
1394
1395        for (int i = 0, n = 0; i < rowCount; i++) {
1396            for (int j = 0; j < columnCount; j++) {
1397                output[n++] = getElementAsToken(i, j);
1398            }
1399        }
1400
1401        ArrayToken result;
1402
1403        try {
1404            result = new ArrayToken(output);
1405        } catch (IllegalActionException illegalAction) {
1406            // Cannot happen, since the elements of MatrixToken always
1407            // have the same type.
1408            throw new InternalErrorException("MatrixToken.toArray: Cannot "
1409                    + "construct ArrayToken. " + illegalAction.getMessage());
1410        }
1411
1412        return result;
1413    }
1414
1415    /** Return an ArrayToken containing the all the values of this
1416     *  matrix token.  The type of the tokens in the array is consistent
1417     *  with the type of this token.
1418     *
1419     *  @return An ArrayToken containing the elements of this matrix in
1420     *  column-scanned order.
1421     */
1422    public ArrayToken toArrayColumnMajor() {
1423        int rowCount = getRowCount();
1424        int columnCount = getColumnCount();
1425        Token[] output = new Token[rowCount * columnCount];
1426
1427        for (int i = 0, n = 0; i < columnCount; i++) {
1428            for (int j = 0; j < rowCount; j++) {
1429                output[n++] = getElementAsToken(j, i);
1430            }
1431        }
1432
1433        ArrayToken result;
1434
1435        try {
1436            result = new ArrayToken(output);
1437        } catch (IllegalActionException illegalAction) {
1438            // Cannot happen, since the elements of MatrixToken always
1439            // have the same type.
1440            throw new InternalErrorException("MatrixToken.toArray: Cannot "
1441                    + "construct ArrayToken. " + illegalAction.getMessage());
1442        }
1443
1444        return result;
1445    }
1446
1447    /** Return the (exact) return type of the toArray function above.  If the
1448     *  argument is a matrix type, then return an array type of its
1449     *  element type, otherwise return BaseType.UNKNOWN.
1450     *  @param type The type of the argument to the corresponding function.
1451     *  @return The type of the value returned from the corresponding function.
1452     */
1453    public static Type toArrayReturnType(Type type) {
1454        if (type instanceof MatrixType) {
1455            Type elementType = ((MatrixType) type).getElementType();
1456            return new ArrayType(elementType);
1457        } else {
1458            return BaseType.UNKNOWN;
1459        }
1460    }
1461
1462    /** Return the value of this token as a string that can be parsed
1463     *  by the expression language to recover a token with the same value.
1464     *  The expression starts and ends with a square bracket.  The matrix is
1465     *  scanned starting from the upper left and proceeding across each row.
1466     *  Each element in the row is separated by a comma, and the end of a row
1467     *  is represented by a semicolon.  The value of each element is obtained
1468     *  using its toString method.
1469     *  @return A String representing a matrix similar to Matlab.
1470     */
1471    @Override
1472    public String toString() {
1473        int rowCount = getRowCount();
1474        int columnCount = getColumnCount();
1475        StringBuffer sb = new StringBuffer();
1476        sb.append("[");
1477
1478        for (int i = 0; i < rowCount; i++) {
1479            for (int j = 0; j < columnCount; j++) {
1480                // Handle nil token
1481                if (_nils != null && _nils
1482                        .contains(Integer.valueOf(i * columnCount + j))) {
1483                    sb.append("nil");
1484                } else {
1485                    sb.append(getElementAsToken(i, j).toString());
1486                }
1487
1488                if (j < columnCount - 1) {
1489                    sb.append(", ");
1490                }
1491            }
1492
1493            if (i < rowCount - 1) {
1494                sb.append("; ");
1495            }
1496        }
1497
1498        sb.append("]");
1499        return sb.toString();
1500    }
1501
1502    ///////////////////////////////////////////////////////////////////
1503    ////                      public  variables                    ////
1504
1505    /** A constant indicating to constructors that contents of an argument 2-D
1506     *  matrix should be copied. The contents of the input 2-D matrix may be
1507     *  modified after construction without violating the immutability of
1508     *  MatrixTokens.
1509     */
1510    public static final int DO_COPY = 0;
1511
1512    /** A constant indicating to constructors not to copy the contents
1513     *  of an argument 2-D matrix, but instead to just copy the
1514     *  pointer to the matrix. The contents of the input 2-D matrix
1515     *  should NOT be modified after construction of an
1516     *  instance of MatrixToken, if the property of immutability is
1517     *  to be preserved.
1518     */
1519    public static final int DO_NOT_COPY = 1;
1520
1521    ///////////////////////////////////////////////////////////////////
1522    ////                         protected methods                 ////
1523
1524    /** Return a new token whose value is the value of the argument
1525     *  Token added to the value of this Token.  It is guaranteed by
1526     *  the caller that the type of the argument is the same as the
1527     *  type of this class, and that the matrices have appropriate
1528     *  dimensions.  This method should be overridden in derived
1529     *  classes to provide type-specific operation and return a token
1530     *  of the appropriate subclass.
1531     *  @param rightArgument The token to add to this token.
1532     *  @exception IllegalActionException If this method is not
1533     *  supported by the derived class.
1534     *  @return A new Token containing the result.
1535     */
1536    protected MatrixToken _add(MatrixToken rightArgument)
1537            throws IllegalActionException {
1538        throw new IllegalActionException(
1539                notSupportedMessage("add", this, rightArgument));
1540    }
1541
1542    /** Return a new token whose value is the value of the argument
1543     *  Token added to the value of each element of this Token. It is
1544     *  guaranteed by the caller that the type of the argument
1545     *  is the same as the type of each element of this class.
1546     *  @param rightArgument The token to add to this token.
1547     *  @exception IllegalActionException If this operation is not
1548     *  supported by the derived class.
1549     *  @return A new Token containing the result.
1550     */
1551    protected MatrixToken _addElement(Token rightArgument)
1552            throws IllegalActionException {
1553        throw new IllegalActionException(
1554                notSupportedMessage("add", this, rightArgument));
1555    }
1556
1557    /** Return a new token whose elements are the result of dividing
1558     *  the elements of this token by the argument. It is
1559     *  guaranteed by the caller that the type of the argument
1560     *  is the same as the type of each element of this class.
1561     *  @param rightArgument The token that divides this token.
1562     *  @exception IllegalActionException If this operation is not
1563     *  supported by the derived class.
1564     *  @return A new Token containing the result.
1565     */
1566    protected MatrixToken _divideElement(Token rightArgument)
1567            throws IllegalActionException {
1568        throw new IllegalActionException(
1569                notSupportedMessage("divide", this, rightArgument));
1570    }
1571
1572    /** Test whether the value of this token is close to the first
1573     *  argument, where "close" means that the distance between their
1574     *  elements is less than or equal to the second argument. This
1575     *  base class delegates to the token class corresponding to the
1576     *  matrix elements, using its isCloseTo() method. If the two
1577     *  matrices do have the same dimension, then this method returns
1578     *  false.
1579     *
1580     *  @param token The matrix token to compare to this token.
1581     *  @param distance The specified distance.
1582     *  @return True if every element of the specified matrix is within
1583     *  the specified distance of the corresponding element of this matrix.
1584     *  @exception IllegalActionException If a derived class throws it.
1585     */
1586    protected BooleanToken _isCloseTo(MatrixToken token, double distance)
1587            throws IllegalActionException {
1588        int rows = getRowCount();
1589        int columns = getColumnCount();
1590
1591        if (token.getRowCount() != rows || token.getColumnCount() != columns) {
1592            return BooleanToken.FALSE;
1593        }
1594
1595        for (int i = 0; i < rows; i++) {
1596            for (int j = 0; j < columns; j++) {
1597                Token element = getElementAsToken(i, j);
1598                Token other = token.getElementAsToken(i, j);
1599
1600                if (!element.isCloseTo(other, distance).booleanValue()) {
1601                    return BooleanToken.FALSE;
1602                }
1603            }
1604        }
1605
1606        return BooleanToken.TRUE;
1607    }
1608
1609    /** Test for equality of the values of this Token and the argument
1610     *  Token.  It is guaranteed by the caller that the type and
1611     *  dimensions of the argument is the same as the type of this
1612     *  class.  This method can be overridden in derived classes to
1613     *  provide type-specific operation and return a token of the
1614     *  appropriate subclass.  In this base class, this method
1615     *         delegates to equals().
1616     *  @param rightArgument The token to compare to this token.
1617     *  @exception IllegalActionException If this method is not
1618     *   supported by a derived class.
1619     *  @return A true-valued token if the argument is equal to this
1620     *          matrix.
1621     */
1622    protected BooleanToken _isEqualTo(MatrixToken rightArgument)
1623            throws IllegalActionException {
1624        return BooleanToken.getInstance(equals(rightArgument));
1625    }
1626
1627    /** Add the element to the _nils Set.  Subclasses should call this
1628     *  when they encounter a nil token during construction.  If _nils
1629     *  is null, this method constructs _nils as a new HashSet.
1630     *  @param element The element index.  The format is rows * columnCount
1631     *  + column.
1632     */
1633    protected void _elementIsNil(int element) {
1634        if (_nils == null) {
1635            _nils = new HashSet();
1636        }
1637        _nils.add(Integer.valueOf(element));
1638    }
1639
1640    /** Return a new token whose elements are the modulo of
1641     *  the elements of this token by the argument. It is
1642     *  guaranteed by the caller that the type of the argument
1643     *  is the same as the type of each element of this class.
1644     *  @param rightArgument The token that performs modulo on this token.
1645     *  @exception IllegalActionException If this operation is not
1646     *  supported by the derived class.
1647     *  @return A new Token containing the result.
1648     */
1649    protected MatrixToken _moduloElement(Token rightArgument)
1650            throws IllegalActionException {
1651        throw new IllegalActionException(
1652                notSupportedMessage("modulo", this, rightArgument));
1653    }
1654
1655    /** Return a new token whose value is the value of this token
1656     *  multiplied by the value of the argument token.  It is
1657     *  guaranteed by the caller that the type of the argument is the
1658     *  same as the type of this class, and that the matrices have
1659     *  appropriate dimensions.  This method should be overridden in
1660     *  derived classes to provide type-specific operation and return
1661     *  a token of the appropriate subclass.
1662     *  @param rightArgument The token to multiply this token by.
1663     *  @exception IllegalActionException If this method is not
1664     *  supported by the derived class.
1665     *  @return A new Token containing the result.
1666     */
1667    protected MatrixToken _multiply(MatrixToken rightArgument)
1668            throws IllegalActionException {
1669        throw new IllegalActionException(
1670                notSupportedMessage("multiply", this, rightArgument));
1671    }
1672
1673    /** Return a new token whose value is the value of this token
1674     *  multiplied by the value of the argument scalar token.
1675     *  This method should be overridden in derived
1676     *  classes to provide type specific actions for multiply.
1677     *  @param rightArgument The token to multiply this token by.
1678     *  @exception IllegalActionException If this method is not
1679     *   supported by the derived class.
1680     *  @return A new Token containing the result that is of the same class
1681     *  as this token.
1682     */
1683    protected MatrixToken _multiplyElement(Token rightArgument)
1684            throws IllegalActionException {
1685        throw new IllegalActionException(
1686                notSupportedMessage("multiply", this, rightArgument));
1687    }
1688
1689    /** Return a new token whose value is the value of the argument
1690     *  token subtracted from the value of this token.  It is
1691     *  guaranteed by the caller that the type of the argument is the
1692     *  same as the type of this class, and that the matrices have
1693     *  appropriate dimensions.  This method should be overridden in
1694     *  derived classes to provide type-specific operation and return
1695     *  a token of the appropriate subclass.
1696     *  @param rightArgument The token to subtract from this token.
1697     *  @exception IllegalActionException If this method is not
1698     *  supported by the derived class.
1699     *  @return A new Token containing the result.
1700     */
1701    protected MatrixToken _subtract(MatrixToken rightArgument)
1702            throws IllegalActionException {
1703        throw new IllegalActionException(
1704                notSupportedMessage("subtract", this, rightArgument));
1705    }
1706
1707    /** Return a new token whose value is the value of the argument
1708     *  Token subtracted from the value of each element of this
1709     *  Token. It is guaranteed by the caller that the type of the
1710     *  argument is the same as the type of each element of this
1711     *  class.
1712     *  @param rightArgument The token to subtract from this token.
1713     *  @exception IllegalActionException If this operation is not
1714     *  supported by the derived class.
1715     *  @return A new Token containing the result.
1716     */
1717    protected MatrixToken _subtractElement(Token rightArgument)
1718            throws IllegalActionException {
1719        throw new IllegalActionException(
1720                notSupportedMessage("subtract", this, rightArgument));
1721    }
1722
1723    /** Return a new token whose value is the value of each element of
1724     *  this Token subtracted from the value the argument Token. It is
1725     *  guaranteed by the caller that the type of the argument is the
1726     *  same as the type of each element of this class.
1727     *  @param rightArgument The token to subtract this token from.
1728     *  @exception IllegalActionException If this operation is not
1729     *  supported by the derived class.
1730     *  @return A new Token containing the result.
1731     */
1732    protected MatrixToken _subtractElementReverse(Token rightArgument)
1733            throws IllegalActionException {
1734        throw new IllegalActionException(
1735                notSupportedMessage("subtract", this, rightArgument));
1736    }
1737
1738    ///////////////////////////////////////////////////////////////////
1739    ////                         protected variables               ////
1740
1741    /** HashSet of nil elements, where each element is the index of the
1742     *  element in _value[] that should be nil.
1743     */
1744    protected Set _nils;
1745
1746    ///////////////////////////////////////////////////////////////////
1747    ////                         private methods                   ////
1748
1749    /** Return a new token whose value is the value of the argument
1750     *  Token added to the value of this Token. It is guaranteed by
1751     *  the caller that the type of the argument is the same as the
1752     *  type of this class.  This method defers to the _add method
1753     *  that takes a MatrixToken.  Derived classes should override
1754     *  that method instead to provide type-specific operation.
1755     *  @param rightArgument The token to add to this token.
1756     *  @exception IllegalActionException If the matrix dimensions are
1757     *  not compatible, or this operation is not supported by the
1758     *  derived class.
1759     *  @return A new Token containing the result.
1760     */
1761    private Token _doAdd(Token rightArgument) throws IllegalActionException {
1762        MatrixToken convertedArgument = (MatrixToken) rightArgument;
1763
1764        if (convertedArgument.getRowCount() != getRowCount()
1765                || convertedArgument.getColumnCount() != getColumnCount()) {
1766            // Either this matrix or the argument might be a size one matrix
1767            // converted automatically from a scalar. Support this by
1768            // scalar addition.
1769            if (getRowCount() == 1 && getColumnCount() == 1) {
1770                // This matrix should be treated as a scalar.
1771                return convertedArgument._addElement(getElementAsToken(0, 0));
1772            } else if (convertedArgument.getRowCount() == 1
1773                    && convertedArgument.getColumnCount() == 1) {
1774                // The argument matrix should be treated as a scalar.
1775                return _addElement(convertedArgument.getElementAsToken(0, 0));
1776            } else {
1777                throw new IllegalActionException(Token
1778                        .notSupportedMessage("add", this, rightArgument)
1779                        + " because the matrices have different dimensions.");
1780            }
1781        }
1782
1783        MatrixToken result = _add(convertedArgument);
1784        return result;
1785    }
1786
1787    /** Test for closeness of the values of this Token and the
1788     *  argument Token.  It is guaranteed by the caller that the type
1789     *  of the argument is the same as the type of this class.  This
1790     *  class overrides the base class to return BooleanToken.FALSE if
1791     *  the dimensions of this token and the given token are not
1792     *  identical.  This method may defer to the _isEqualTo method
1793     *  that takes a MatrixToken.  Derived classes should override
1794     *  that method instead to provide type-specific operation.
1795     *  @param rightArgument The token with which to test equality.
1796     *  @exception IllegalActionException If this method is not
1797     *  supported by the derived class.
1798     *  @return A BooleanToken which contains the result of the test.
1799     */
1800    private BooleanToken _doIsCloseTo(Token rightArgument, double epsilon)
1801            throws IllegalActionException {
1802        MatrixToken convertedArgument = (MatrixToken) rightArgument;
1803
1804        if (convertedArgument.getRowCount() != getRowCount()
1805                || convertedArgument.getColumnCount() != getColumnCount()) {
1806            return BooleanToken.FALSE;
1807        }
1808
1809        return _isCloseTo(convertedArgument, epsilon);
1810    }
1811
1812    /** Test for equality of the values of this Token and the argument
1813     *  Token.  It is guaranteed by the caller that the type of the
1814     *  argument is the same as the type of this class.  This class
1815     *  overrides the base class to return BooleanToken.FALSE if the
1816     *  dimensions of this token and the given token are not
1817     *  identical.  This method may defer to the _isEqualTo method
1818     *  that takes a MatrixToken.  Derived classes should override
1819     *  that method instead to provide type-specific operation.
1820     *  @param rightArgument The token with which to test equality.
1821     *  @exception IllegalActionException If this method is not
1822     *  supported by the derived class.
1823     *  @return A BooleanToken which contains the result of the test.
1824     */
1825    private BooleanToken _doIsEqualTo(Token rightArgument)
1826            throws IllegalActionException {
1827        MatrixToken convertedArgument = (MatrixToken) rightArgument;
1828
1829        if (convertedArgument.getRowCount() != getRowCount()
1830                || convertedArgument.getColumnCount() != getColumnCount()) {
1831            return BooleanToken.FALSE;
1832        }
1833
1834        return _isEqualTo(convertedArgument);
1835    }
1836
1837    /** Return a new token whose value is the value of this token
1838     *  multiplied by the value of the argument token.  It is
1839     *  guaranteed by the caller that the type of the argument is the
1840     *  same as the type of this class.  This method defers to the
1841     *  _multiply method that takes a MatrixToken.  Derived classes
1842     *  should override that method instead to provide type-specific
1843     *  operation.
1844     *  @param rightArgument The token to multiply this token by.
1845     *  @exception IllegalActionException If the matrix dimensions are
1846     *  not compatible, or this operation is not supported by the
1847     *  derived class.
1848     *  @return A new Token containing the result.
1849     */
1850    private Token _doMultiply(Token rightArgument)
1851            throws IllegalActionException {
1852        MatrixToken convertedArgument = (MatrixToken) rightArgument;
1853
1854        if (convertedArgument.getRowCount() != getColumnCount()) {
1855            // Either this matrix or the argument might be a size one matrix
1856            // converted automatically from a scalar. Support this by
1857            // scalar multiplication.
1858            if (getRowCount() == 1 && getColumnCount() == 1) {
1859                // This matrix should be treated as a scalar.
1860                return convertedArgument
1861                        ._multiplyElement(getElementAsToken(0, 0));
1862            } else if (convertedArgument.getRowCount() == 1
1863                    && convertedArgument.getColumnCount() == 1) {
1864                // The argument matrix should be treated as a scalar.
1865                return _multiplyElement(
1866                        convertedArgument.getElementAsToken(0, 0));
1867            } else {
1868                throw new IllegalActionException(Token
1869                        .notSupportedMessage("multiply", this, rightArgument)
1870                        + " because the matrices have incompatible dimensions.");
1871            }
1872        }
1873        MatrixToken result = _multiply(convertedArgument);
1874        return result;
1875    }
1876
1877    /** Return a new token whose value is the value of the argument
1878     *  token subtracted from the value of this token.  It is
1879     *  guaranteed by the caller that the type of the argument is the
1880     *  same as the type of this class and has the same units as this
1881     *  token.  This method defers to the _subtract method that takes
1882     *  a MatrixToken.  Derived classes should override that method
1883     *  instead to provide type-specific operation.
1884     *  @param rightArgument The token to subtract from this token.
1885     *  @exception IllegalActionException If the matrix dimensions are
1886     *  not compatible, or this operation is not supported by the
1887     *  derived class.
1888     *  @return A new Token containing the result.
1889     */
1890    private Token _doSubtract(Token rightArgument)
1891            throws IllegalActionException {
1892        MatrixToken convertedArgument = (MatrixToken) rightArgument;
1893
1894        if (convertedArgument.getRowCount() != getRowCount()
1895                || convertedArgument.getColumnCount() != getColumnCount()) {
1896            // Either this matrix or the argument might be a size one matrix
1897            // converted automatically from a scalar. Support this by
1898            // scalar multiplication.
1899            if (getRowCount() == 1 && getColumnCount() == 1) {
1900                // This matrix should be treated as a scalar.
1901                // Need to reverse the subtraction.
1902                return convertedArgument
1903                        ._subtractElementReverse(getElementAsToken(0, 0));
1904            } else if (convertedArgument.getRowCount() == 1
1905                    && convertedArgument.getColumnCount() == 1) {
1906                // The argument matrix should be treated as a scalar.
1907                return _subtractElement(
1908                        convertedArgument.getElementAsToken(0, 0));
1909            } else {
1910                throw new IllegalActionException(Token
1911                        .notSupportedMessage("subtract", this, rightArgument)
1912                        + " because the matrices have different dimensions.");
1913            }
1914        }
1915
1916        MatrixToken result = _subtract(convertedArgument);
1917        return result;
1918    }
1919}