001/* The base type of matrix token classes. 002 003 Copyright (c) 2006-2018 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.data.type; 029 030import ptolemy.data.BooleanMatrixToken; 031import ptolemy.data.ComplexMatrixToken; 032import ptolemy.data.ComplexToken; 033import ptolemy.data.DoubleMatrixToken; 034import ptolemy.data.DoubleToken; 035import ptolemy.data.FixMatrixToken; 036import ptolemy.data.FixToken; 037import ptolemy.data.IntMatrixToken; 038import ptolemy.data.IntToken; 039import ptolemy.data.LongMatrixToken; 040import ptolemy.data.LongToken; 041import ptolemy.data.MatrixToken; 042import ptolemy.data.Token; 043import ptolemy.graph.CPO; 044import ptolemy.kernel.util.IllegalActionException; 045import ptolemy.kernel.util.InternalErrorException; 046import ptolemy.math.Complex; 047import ptolemy.math.FixPoint; 048 049/////////////////////////////////////////////////////////////////// 050//// MatrixType 051 052/** 053 The base type of matrix token classes. This type functions as a union 054 of the various matrix types. It allows for the creation of arrays 055 that consist of diverse matrix types, because the array type will 056 be {matrix}. 057 058 @author Steve Neuendorffer and Edward A. Lee 059 @version $Id$ 060 @since Ptolemy II 5.2 061 @Pt.ProposedRating Red (yuhong) 062 @Pt.AcceptedRating Red 063 */ 064public class MatrixType extends StructuredType implements Cloneable { 065 066 /** Construct a new matrix type that represents matrix tokens of the 067 * given class with the given number of rows and columns. 068 * @param c The token class. 069 * @param type The element type. 070 * @param name The name. 071 */ 072 public MatrixType(Class c, Type type, String name) { 073 _tokenClass = c; 074 _elementType = type; 075 _name = name; 076 BaseType._addType(this, name, c); 077 } 078 079 /////////////////////////////////////////////////////////////////// 080 //// public methods //// 081 082 /** Return this, that is, return the reference to this object. 083 * @return A MatrixType. 084 */ 085 @Override 086 public Object clone() { 087 return this; 088 } 089 090 /** If the argument is an instance of this class or a subclass, 091 * then return the token. Otherwise, throw an exception. 092 * @param token A token. 093 * @return An instance of this class. 094 * @exception IllegalActionException If the argument is not 095 * an instance of this class. 096 */ 097 @Override 098 public Token convert(Token token) throws IllegalActionException { 099 if (token instanceof MatrixToken) { 100 return token; 101 } 102 throw new IllegalActionException(Token 103 .notSupportedIncomparableConversionMessage(token, "matrix")); 104 } 105 106 /** Determine if the argument represents the same MatrixType as this 107 * object. 108 * @param object A Type. 109 * @return True if the argument type is a matrix type representing the 110 * same class, with the same number of rows and columns. 111 */ 112 @Override 113 public boolean equals(Object object) { 114 if (!(object instanceof MatrixType)) { 115 return false; 116 } 117 118 MatrixType matrixType = (MatrixType) object; 119 120 if (matrixType.getTokenClass() != _tokenClass) { 121 return false; 122 } 123 124 return true; 125 } 126 127 /** Return the type of the elements contained in an instance of 128 * this matrix type. Tokens of the type returned by this method 129 * will be returned by the getElementAsToken of matrices that 130 * have this type. If this is an instance of this base class 131 * rather than the specific matrix types, then return null. 132 * @return The type of the elements. 133 */ 134 public Type getElementType() { 135 return _elementType; 136 } 137 138 /** Return a matrix type whose element type is the given element 139 * type. 140 * @param elementType The type of the element. 141 * @return The matrix type. 142 * @exception IllegalActionException If the elementType is not a 143 * type that has a corresponding matrix type. 144 */ 145 public static MatrixType getMatrixTypeForElementType(Type elementType) 146 throws IllegalActionException { 147 MatrixType matrixType; 148 149 if (elementType.equals(BaseType.UNKNOWN)) { 150 throw new IllegalActionException( 151 "Cannot resolve type for " + "matrix construction."); 152 } else if (elementType.equals(BaseType.BOOLEAN)) { 153 matrixType = BaseType.BOOLEAN_MATRIX; 154 } else if (elementType.equals(BaseType.INT)) { 155 matrixType = BaseType.INT_MATRIX; 156 } else if (elementType.equals(BaseType.LONG)) { 157 matrixType = BaseType.LONG_MATRIX; 158 } else if (elementType.equals(BaseType.DOUBLE)) { 159 matrixType = BaseType.DOUBLE_MATRIX; 160 } else if (elementType.equals(BaseType.COMPLEX)) { 161 matrixType = BaseType.COMPLEX_MATRIX; 162 } else if (elementType instanceof FixType) { 163 matrixType = BaseType.FIX_MATRIX; 164 } else if (elementType.equals(BaseType.UNSIZED_FIX)) { 165 matrixType = BaseType.FIX_MATRIX; 166 } else { 167 throw new IllegalActionException("Type " + elementType 168 + " does not have a corresponding matrix type."); 169 } 170 171 return matrixType; 172 } 173 174 /** Return the class for tokens that this type represents. 175 * @return A class that represents a matrix token. 176 */ 177 @Override 178 public Class getTokenClass() { 179 return _tokenClass; 180 } 181 182 /** Return a hash code value for this object. 183 * @return The hash code for the token class of this type. 184 */ 185 @Override 186 public int hashCode() { 187 return getTokenClass().hashCode(); 188 } 189 190 /** Set the elements that have declared type BaseType.UNKNOWN to the 191 * specified type. 192 * @param type A Type. 193 */ 194 @Override 195 public void initialize(Type type) { 196 // Ignore... This type has no components that are unknown. 197 } 198 199 /** Return true if the element type is abstract. 200 * @return True. 201 */ 202 @Override 203 public boolean isAbstract() { 204 return _elementType.isAbstract(); 205 } 206 207 /** Test if the argument type is compatible with this type. The method 208 * returns true if this type is UNKNOWN, since any type is a substitution 209 * instance of it. If this type is not UNKNOWN, this method returns true 210 * if the argument type is less than or equal to this type in the type 211 * lattice, and false otherwise. 212 * @param type An instance of Type. 213 * @return True if the argument is compatible with this type. 214 */ 215 @Override 216 public boolean isCompatible(Type type) { 217 int typeInfo = TypeLattice.compare(this, type); 218 return typeInfo == CPO.SAME || typeInfo == CPO.HIGHER; 219 } 220 221 /** Test if this Type is a constant. A Type is a constant if it 222 * does not contain BaseType.UNKNOWN in any level within it. 223 * @return False. 224 */ 225 @Override 226 public boolean isConstant() { 227 return true; 228 } 229 230 /** Return true, indicating that instances of this type can 231 * exist. 232 * @return True. 233 */ 234 @Override 235 public boolean isInstantiable() { 236 return _elementType.isInstantiable(); 237 } 238 239 /** Test if the argument is a substitution instance of this type. 240 * @param type A Type. 241 * @return False. 242 */ 243 @Override 244 public boolean isSubstitutionInstance(Type type) { 245 if (type instanceof StructuredType) { 246 return ((StructuredType) type) 247 ._getRepresentative() == _getRepresentative(); 248 } else { 249 return false; 250 } 251 } 252 253 /** Return the string representation of this type. 254 * @return A String. 255 */ 256 @Override 257 public String toString() { 258 return _name; 259 } 260 261 /** Update this StructuredType to the specified Structured Type. 262 ** The specified type must have the same structure as this type. 263 * This method will only update the component type that is 264 * BaseType.UNKNOWN, and leave the constant part of this type intact. 265 * @param newType A StructuredType. 266 * @exception IllegalActionException If the specified type has a 267 * different structure. 268 */ 269 @Override 270 public void updateType(StructuredType newType) 271 throws IllegalActionException { 272 if (newType._getRepresentative() != _getRepresentative()) { 273 throw new InternalErrorException("MatrixType.updateType: Cannot " 274 + "updateType the element type to " + newType + "."); 275 } 276 } 277 278 /** The boolean matrix data type. */ 279 public static class BooleanMatrixType extends MatrixType { 280 public BooleanMatrixType() { 281 super(BooleanMatrixToken.class, BaseType.BOOLEAN, "[boolean]"); 282 } 283 284 @Override 285 public Token convert(Token token) throws IllegalActionException { 286 if (token instanceof MatrixToken) { 287 return BooleanMatrixToken.convert(token); 288 } else { 289 // NOTE: No point in converting to a boolean matrix, 290 // since you can't do anything with it. 291 throw new IllegalActionException( 292 Token.notSupportedConversionMessage(token, toString())); 293 } 294 } 295 } 296 297 /** The complex matrix data type. */ 298 public static class ComplexMatrixType extends MatrixType { 299 public ComplexMatrixType() { 300 super(ComplexMatrixToken.class, BaseType.COMPLEX, "[complex]"); 301 } 302 303 @Override 304 public Token convert(Token token) throws IllegalActionException { 305 if (token instanceof MatrixToken) { 306 return ComplexMatrixToken.convert(token); 307 } else { 308 if (token.isNil()) { 309 throw new IllegalActionException(Token 310 .notSupportedConversionMessage(token, toString())); 311 } 312 // Try to create a new [complex] type with just one member. 313 // The following conversion will fail if the member cannot 314 // be converted to an int. 315 ComplexToken singleMember = ComplexToken.convert(token); 316 Complex[][] matrix = new Complex[1][1]; 317 matrix[0][0] = singleMember.complexValue(); 318 return new ComplexMatrixToken(matrix); 319 } 320 321 } 322 } 323 324 /** The double matrix data type. */ 325 public static class DoubleMatrixType extends MatrixType { 326 public DoubleMatrixType() { 327 super(DoubleMatrixToken.class, BaseType.DOUBLE, "[double]"); 328 } 329 330 @Override 331 public Token convert(Token token) throws IllegalActionException { 332 if (token instanceof MatrixToken) { 333 return DoubleMatrixToken.convert(token); 334 } else { 335 if (token.isNil()) { 336 // MatrixTokens do not support nil because there is no 337 // way to represent a nil double as a Java.lang.Double. 338 // Double.NaN is a possibility, but NaN is a value, whereas 339 // nil is the absent value. Other types, like int do 340 // not have NaN, so we catch this problem here. 341 // Note that this code is called by the "cast" expression 342 // language method from data.expr.UtilityFunctions 343 throw new IllegalActionException(Token 344 .notSupportedConversionMessage(token, toString())); 345 } 346 // Try to create a new [double] type with just one member. 347 // The following conversion will fail if the member cannot 348 // be converted to an int. 349 DoubleToken singleMember = DoubleToken.convert(token); 350 double[] matrix = new double[1]; 351 matrix[0] = singleMember.doubleValue(); 352 return new DoubleMatrixToken(matrix, 1, 1); 353 } 354 } 355 } 356 357 /** The integer matrix data type. */ 358 public static class IntMatrixType extends MatrixType { 359 public IntMatrixType() { 360 super(IntMatrixToken.class, BaseType.INT, "[int]"); 361 } 362 363 @Override 364 public Token convert(Token token) throws IllegalActionException { 365 if (token instanceof MatrixToken) { 366 return IntMatrixToken.convert(token); 367 } else { 368 if (token.isNil()) { 369 throw new IllegalActionException(Token 370 .notSupportedConversionMessage(token, toString())); 371 } 372 373 // Try to create a new [int] type with just one member. 374 // The following conversion will fail if the member cannot 375 // be converted to an int. 376 IntToken singleMember = IntToken.convert(token); 377 int[] matrix = new int[1]; 378 matrix[0] = singleMember.intValue(); 379 return new IntMatrixToken(matrix, 1, 1); 380 } 381 } 382 } 383 384 /** The fix matrix data type. */ 385 public static class FixMatrixType extends MatrixType { 386 public FixMatrixType() { 387 super(FixMatrixToken.class, BaseType.UNSIZED_FIX, "[fixedpoint]"); 388 } 389 390 @Override 391 public Token convert(Token token) throws IllegalActionException { 392 if (token instanceof MatrixToken) { 393 return FixMatrixToken.convert(token); 394 } else { 395 if (token.isNil()) { 396 throw new IllegalActionException(Token 397 .notSupportedConversionMessage(token, toString())); 398 } 399 // Try to create a new [fix] type with just one member. 400 // The following conversion will fail if the member cannot 401 // be converted to an int. 402 FixToken singleMember = FixToken.convert(token); 403 FixPoint[][] matrix = new FixPoint[1][1]; 404 matrix[0][0] = singleMember.fixValue(); 405 return new FixMatrixToken(matrix); 406 } 407 } 408 } 409 410 /** The long matrix data type. */ 411 public static class LongMatrixType extends MatrixType { 412 public LongMatrixType() { 413 super(LongMatrixToken.class, BaseType.LONG, "[long]"); 414 } 415 416 @Override 417 public Token convert(Token token) throws IllegalActionException { 418 if (token instanceof MatrixToken) { 419 return LongMatrixToken.convert(token); 420 } else { 421 if (token.isNil()) { 422 throw new IllegalActionException(Token 423 .notSupportedConversionMessage(token, toString())); 424 } 425 // Try to create a new [long] type with just one member. 426 // The following conversion will fail if the member cannot 427 // be converted to an int. 428 LongToken singleMember = LongToken.convert(token); 429 long[] matrix = new long[1]; 430 matrix[0] = singleMember.longValue(); 431 return new LongMatrixToken(matrix, 1, 1); 432 } 433 } 434 } 435 436 /////////////////////////////////////////////////////////////////// 437 //// protected methods //// 438 439 /** Compare this type with the specified type. The specified type 440 * must be of the same structured type, otherwise an exception will 441 * be thrown. 442 * This method returns one of ptolemy.graph.CPO.LOWER, 443 * ptolemy.graph.CPO.SAME, ptolemy.graph.CPO.HIGHER, 444 * ptolemy.graph.CPO.INCOMPARABLE, indicating this type is lower 445 * than, equal to, higher than, or incomparable with the 446 * specified type in the type hierarchy, respectively. 447 * @param type a StructuredType. 448 * @return An integer. 449 * @exception IllegalArgumentException If the specified type is 450 * not the same structured type as this one. 451 */ 452 @Override 453 protected int _compare(StructuredType type) { 454 return CPO.SAME; 455 456 // if (equals(type)) { 457 // return CPO.SAME; 458 // } else { 459 // return CPO.LOWER; 460 // } 461 } 462 463 /** Return a static instance of this structured type. The return 464 * value is used by TypeLattice to represent this type. 465 * @return a StructuredType. 466 */ 467 @Override 468 protected StructuredType _getRepresentative() { 469 return this; 470 } 471 472 /** Return the greatest lower bound of this type with the specified 473 * type. The specified type must be of the same structured type, 474 * otherwise an exception will be thrown. 475 * @param type a StructuredType. 476 * @return a StructuredType. 477 * @exception IllegalArgumentException If the specified type is 478 * not the same structured type as this one. 479 */ 480 @Override 481 protected StructuredType _greatestLowerBound(StructuredType type) { 482 return this; 483 } 484 485 /** Return the least upper bound of this type with the specified 486 * type. The specified type must be of the same structured type, 487 * otherwise an exception will be thrown. 488 * @param type a StructuredType. 489 * @return a StructuredType. 490 * @exception IllegalArgumentException If the specified type is 491 * not the same structured type as this one. 492 */ 493 @Override 494 protected StructuredType _leastUpperBound(StructuredType type) { 495 return this; 496 497 // if (equals(type)) { 498 // return this; 499 // } else { 500 // return type; 501 // } 502 } 503 504 /////////////////////////////////////////////////////////////////// 505 //// private variables //// 506 507 /** The type of MatrixToken that this class represents. */ 508 private Class _tokenClass; 509 510 /** The type of the elements of the matrix, or ScalarType for this base class. */ 511 private Type _elementType; 512 513 /** The name of this instance. */ 514 private String _name; 515}