001/* A token that contains a short (16 bit integer) 002 003 Copyright (c) 2007-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 ptolemy.data.type.BaseType; 032import ptolemy.data.type.Type; 033import ptolemy.data.type.TypeLattice; 034import ptolemy.data.unit.UnitUtilities; 035import ptolemy.graph.CPO; 036import ptolemy.kernel.util.IllegalActionException; 037import ptolemy.math.Complex; 038import ptolemy.math.FixPoint; 039 040/////////////////////////////////////////////////////////////////// 041//// ShortToken 042 043/** 044 A token that contains a signed 16-bit integer number. Generally, this 045 class handles overflow the same way that overflow Java native types 046 are handled. In other words, overflow just past java.lang.Short.MAX_VALUE 047 results in negative values close to java.lang.Short.MIN_VALUE. 048 049 @author Isaac Liu, based on IntToken by Neil Smyth, Yuhong Xiong, Steve Neuendorffer, contributor: Christopher Brooks 050 @version $Id$ 051 @since Ptolemy II 6.1 052 @Pt.ProposedRating Red (iliu) 053 @Pt.AcceptedRating Red (iliu) 054 */ 055public class ShortToken extends ScalarToken { 056 /** Construct a token with short 0. 057 */ 058 public ShortToken() { 059 _value = 0; 060 } 061 062 /** Construct a token with the specified value. 063 * @param value The specified value. 064 */ 065 public ShortToken(final short value) { 066 _value = value; 067 } 068 069 /** Construct a ShortToken with the specified integer value. 070 * This method's cast to (byte) keeps only the low 071 * order 16 bits of the integer. 072 * @param value The specified value. 073 */ 074 public ShortToken(int value) { 075 _value = (short) value; 076 } 077 078 /** Construct an ShortToken from the specified string. 079 * @param init The specified string. 080 * @exception IllegalActionException If the token could not 081 * be created with the given String. 082 */ 083 public ShortToken(String init) throws IllegalActionException { 084 if (init == null || init.equals("nil")) { 085 throw new IllegalActionException( 086 notSupportedNullNilStringMessage("ShortToken", init)); 087 } 088 try { 089 _value = Short.parseShort(init); 090 } catch (NumberFormatException e) { 091 throw new IllegalActionException(null, e, 092 "Failed to parse \"" + init + "\" as a number."); 093 } 094 } 095 096 /////////////////////////////////////////////////////////////////// 097 //// public methods //// 098 099 /** Return the value of this token as a Complex. The real part 100 * of the Complex is the value of this token, the imaginary part 101 * is set to 0. 102 * @return A Complex. 103 */ 104 @Override 105 public Complex complexValue() { 106 return new Complex(_value); 107 } 108 109 /** Convert the specified token into an instance of ShortToken. 110 * This method does lossless conversion. The units of the 111 * returned token will be the same as the units of the given 112 * token. If the argument is already an instance of ShortToken, it 113 * is returned without any change. If the argument is a 114 * nil token, then {@link #NIL} is returned. 115 * Otherwise, if the argument is below ShortToken in the type 116 * hierarchy, it is converted to an instance of ShortToken or one 117 * of the subclasses of ShortToken and returned. If none of the 118 * above condition is met, an exception is thrown. 119 * 120 * @param token The token to be converted to a ShortToken. 121 * @return A ShortToken. 122 * @exception IllegalActionException If the conversion 123 * cannot be carried out. 124 */ 125 public static ShortToken convert(Token token) 126 throws IllegalActionException { 127 if (token instanceof ShortToken) { 128 return (ShortToken) token; 129 } 130 if (token.isNil()) { 131 return ShortToken.NIL; 132 } 133 134 int compare = TypeLattice.compare(BaseType.SHORT, token); 135 136 if (compare == CPO.LOWER || compare == CPO.INCOMPARABLE) { 137 throw new IllegalActionException( 138 notSupportedIncomparableConversionMessage(token, "short")); 139 } 140 141 compare = TypeLattice.compare(BaseType.UNSIGNED_BYTE, token); 142 143 if (compare == CPO.SAME || compare == CPO.HIGHER) { 144 UnsignedByteToken unsignedByteToken = UnsignedByteToken 145 .convert(token); 146 ShortToken result = new ShortToken(unsignedByteToken.shortValue()); 147 if (unsignedByteToken._unitCategoryExponents != null 148 && !UnitUtilities.isUnitless( 149 unsignedByteToken._unitCategoryExponents)) { 150 result._unitCategoryExponents = unsignedByteToken 151 ._copyOfCategoryExponents(); 152 } 153 return result; 154 } 155 156 // The argument is below UnsignedByteToken in the type hierarchy, 157 // but I don't recognize it. 158 throw new IllegalActionException( 159 notSupportedConversionMessage(token, "short")); 160 } 161 162 /** Return the value in the token as a double. 163 * @return The value contained in this token as a double. 164 */ 165 @Override 166 public double doubleValue() { 167 return _value; 168 } 169 170 /** Return true if the argument's class is ShortToken and it has the 171 * same values as this token. 172 * @param object An instance of Object. 173 * @return True if the argument is an ShortToken with the same 174 * value. If either this object or the argument is a nil Token, return 175 * false. 176 */ 177 @Override 178 public boolean equals(Object object) { 179 if (object == null) { 180 return false; 181 } 182 // This test rules out subclasses. 183 if (object.getClass() != getClass()) { 184 return false; 185 } 186 187 if (this.isNil() || ((ShortToken) object).isNil()) { 188 return false; 189 } 190 191 if (((ShortToken) object).shortValue() == _value) { 192 return true; 193 } 194 195 return false; 196 } 197 198 /** Return the value in the token as a fixpoint. 199 * @return The value contained in this token as a fixpoint. 200 */ 201 @Override 202 public FixPoint fixValue() { 203 // FIXME: Does FixPoint need to specially handle Short? 204 return new FixPoint(_value); 205 } 206 207 /** Return the value in the token as a float. 208 * @return The value contained in this token as a float. 209 */ 210 @Override 211 public float floatValue() { 212 return _value; 213 } 214 215 /** Return the type of this token. 216 * @return BaseType.SHORT 217 */ 218 @Override 219 public Type getType() { 220 return BaseType.SHORT; 221 } 222 223 /** Return a hash code value for this token. This method just returns the 224 * contained short casted to integer. 225 * @return A hash code value for this token. 226 */ 227 @Override 228 public int hashCode() { 229 return _value; 230 } 231 232 /** Return the value in the token as an int. 233 * @return The int value contained in this token. 234 */ 235 @Override 236 public int intValue() { 237 return _value; 238 } 239 240 /** Return true if the token is nil, (aka null or missing). 241 * Nil or missing tokens occur when a data source is sparsely populated. 242 * @return True if the token is the {@link #NIL} token. 243 */ 244 @Override 245 public boolean isNil() { 246 // We use a method here so that we can easily change how 247 // we determine if a token is nil without modify lots of classes. 248 // Can't use equals() here, or we'll go into an infinite loop. 249 return this == ShortToken.NIL; 250 } 251 252 /** Returns a token representing the result of shifting the bits 253 * of this token towards the most significant bit, filling the 254 * least significant bits with zeros. 255 * @param bits The number of bits to shift. 256 * @return The left shift. 257 * If this token is nil, then {@link #NIL} is returned. 258 */ 259 @Override 260 public ScalarToken leftShift(int bits) { 261 if (isNil()) { 262 return ShortToken.NIL; 263 } 264 return new ShortToken(_value << bits); 265 } 266 267 /** Returns a token representing the result of shifting the bits 268 * of this token towards the least significant bit, filling the 269 * most significant bits with zeros. This treats the value as an 270 * unsigned number, which may have the effect of destroying the 271 * sign of the value. 272 * @param bits The number of bits to shift. 273 * @return The logical right shift. 274 * If this token is nil, then {@link #NIL} is returned. 275 */ 276 @Override 277 public ScalarToken logicalRightShift(int bits) { 278 if (isNil()) { 279 return ShortToken.NIL; 280 } 281 short returnValue = (short) (_value >>> bits); 282 returnValue = (short) (returnValue & 0x7FFF); 283 return new ShortToken(returnValue); 284 } 285 286 /** Return the value in the token as a long. 287 * @return The short value contained in this token as a long. 288 */ 289 @Override 290 public long longValue() { 291 return _value; 292 } 293 294 /** Returns an ShortToken with value 1. 295 * @return An ShortToken with value 1. 296 */ 297 @Override 298 public Token one() { 299 return ONE; 300 } 301 302 /** Returns a token representing the result of shifting the bits 303 * of this token towards the least significant bit, filling the 304 * most significant bits with the sign of the value. This preserves 305 * the sign of the result. 306 * @param bits The number of bits to shift. 307 * @return The right shift. 308 * If this token is nil, then {@link #NIL} is returned. 309 */ 310 @Override 311 public ScalarToken rightShift(int bits) { 312 if (isNil()) { 313 return ShortToken.NIL; 314 } 315 return new ShortToken(_value >> bits); 316 } 317 318 /** Return the value in the token as a short. 319 * @return The value contained in this token as a short. 320 */ 321 @Override 322 public short shortValue() { 323 return _value; 324 } 325 326 /** Return the value of this token as a string that can be parsed 327 * by the expression language to recover a token with the same value. 328 * If this token has a unit, the return string also includes a unit 329 * string produced by the unitsString() method in the super class. 330 * @return A String representing the int value and the units (if 331 * any) of this token. 332 * @see ptolemy.data.ScalarToken#unitsString 333 */ 334 @Override 335 public String toString() { 336 String unitString = ""; 337 338 if (!_isUnitless()) { 339 unitString = " * " + unitsString(); 340 } 341 342 if (isNil()) { 343 // FIXME: what about units? 344 return super.toString(); 345 } 346 return Short.toString(_value) + "s" + unitString; 347 } 348 349 /** Returns an ShortToken with value 0. 350 * @return An ShortToken with value 0. 351 */ 352 @Override 353 public Token zero() { 354 return ZERO; 355 } 356 357 /////////////////////////////////////////////////////////////////// 358 //// public variables //// 359 360 /** A token that represents a missing value. 361 * Null or missing tokens are common in analytical systems 362 * like R and SAS where they are used to handle sparsely populated data 363 * sources. In database parlance, missing tokens are sometimes called 364 * null tokens. Since null is a Java keyword, we use the term "nil". 365 * The toString() method on a nil token returns the string "nil". 366 */ 367 public static final ShortToken NIL = new ShortToken(Short.MAX_VALUE); 368 369 /** A ShortToken with the value 1.0. */ 370 public static final ShortToken ONE = new ShortToken(1); 371 372 /** A ShortToken with the value 0.0. */ 373 public static final ShortToken ZERO = new ShortToken(0); 374 375 /////////////////////////////////////////////////////////////////// 376 //// protected methods //// 377 378 /** Return a ScalarToken containing the absolute value of the 379 * value of this token. If this token contains a non-negative 380 * number, it is returned directly; otherwise, a new token is 381 * returned. Note that it is explicitly allowable to return this 382 * token, since the units are the same. 383 * @return An ShortToken. 384 */ 385 @Override 386 protected ScalarToken _absolute() { 387 ShortToken result; 388 389 if (_value >= 0) { 390 result = this; 391 } else { 392 result = new ShortToken(-_value); 393 } 394 395 return result; 396 } 397 398 /** Return a new token whose value is the value of the 399 * argument Token added to the value of this Token. It is assumed 400 * that the type of the argument is an ShortToken. 401 * @param rightArgument The token to add to this token. 402 * @return A new ShortToken containing the result. 403 */ 404 @Override 405 protected ScalarToken _add(ScalarToken rightArgument) { 406 short sum = (short) (_value 407 + ((ShortToken) rightArgument).shortValue()); 408 return new ShortToken(sum); 409 } 410 411 /** Returns a token representing the bitwise AND of this token and 412 * the given token. It is assumed that the type of the argument 413 * is an ShortToken. 414 * @param rightArgument The ShortToken to bitwise AND with this one. 415 * @return The bitwise AND. 416 */ 417 @Override 418 protected ScalarToken _bitwiseAnd(ScalarToken rightArgument) { 419 short sum = (short) (_value 420 & ((ShortToken) rightArgument).shortValue()); 421 return new ShortToken(sum); 422 } 423 424 /** Returns a token representing the bitwise NOT of this token. 425 * @return The bitwise NOT of this token. 426 */ 427 @Override 428 protected ScalarToken _bitwiseNot() { 429 ShortToken result = new ShortToken(~_value); 430 return result; 431 } 432 433 /** Returns a token representing the bitwise OR of this token and 434 * the given token. It is assumed that 435 * the type of the argument is an ShortToken. 436 * @param rightArgument The ShortToken to bitwise OR with this one. 437 * @return The bitwise OR. 438 */ 439 @Override 440 protected ScalarToken _bitwiseOr(ScalarToken rightArgument) { 441 short sum = (short) (_value 442 | ((ShortToken) rightArgument).shortValue()); 443 return new ShortToken(sum); 444 } 445 446 /** Returns a token representing the bitwise XOR of this token and 447 * the given token. It is assumed that 448 * the type of the argument is an ShortToken. 449 * @param rightArgument The ShortToken to bitwise XOR with this one. 450 * @return The bitwise XOR. 451 */ 452 @Override 453 protected ScalarToken _bitwiseXor(ScalarToken rightArgument) { 454 short sum = (short) (_value 455 ^ ((ShortToken) rightArgument).shortValue()); 456 return new ShortToken(sum); 457 } 458 459 /** Return a new token whose value is the value of this token 460 * divided by the value of the argument token. It is assumed that 461 * the type of the argument is an ShortToken. 462 * @param rightArgument The token to divide this token by. 463 * @return A new ShortToken containing the result. 464 */ 465 @Override 466 protected ScalarToken _divide(ScalarToken rightArgument) { 467 short quotient = (short) (_value 468 / ((ShortToken) rightArgument).shortValue()); 469 return new ShortToken(quotient); 470 } 471 472 /** Test whether the value of this token is close to the first 473 * argument, where "close" means that the distance between their 474 * values is less than or equal to the second argument. It is 475 * assumed that the type of the first argument is ShortToken. 476 * @param rightArgument The token to compare to this token. 477 * @param epsilon The distance. 478 * @return A token containing true if the value of the first 479 * argument is close to the value of this token. 480 */ 481 @Override 482 protected BooleanToken _isCloseTo(ScalarToken rightArgument, 483 double epsilon) { 484 // NOTE: This code is duplicated in 485 // ptolemy.math.IntegerMatrixMath.within(); if this 486 // implementation changes, also change the corresponding 487 // implementation there. 488 double right = ((ShortToken) rightArgument).doubleValue(); 489 double left = doubleValue(); 490 491 if (right > left + epsilon || right < left - epsilon) { 492 return BooleanToken.FALSE; 493 } else { 494 return BooleanToken.TRUE; 495 } 496 } 497 498 /** Test for ordering of the values of this Token and the argument 499 * Token. It is assumed that the type of the argument is ShortToken. 500 * @param rightArgument The token to add to this token. 501 * @exception IllegalActionException If this method is not 502 * supported by the derived class. 503 * @return A new Token containing the result. 504 */ 505 @Override 506 protected BooleanToken _isLessThan(ScalarToken rightArgument) 507 throws IllegalActionException { 508 ShortToken convertedArgument = (ShortToken) rightArgument; 509 return BooleanToken 510 .getInstance(_value < convertedArgument.shortValue()); 511 } 512 513 /** Return a new token whose value is the value of this token 514 * modulo the value of the argument token. It is assumed that 515 * the type of the argument is an ShortToken. 516 * @param rightArgument The token to modulo this token by. 517 * @return A new ShortToken containing the result. 518 */ 519 @Override 520 protected ScalarToken _modulo(ScalarToken rightArgument) { 521 short remainder = (short) (_value 522 % ((ShortToken) rightArgument).shortValue()); 523 return new ShortToken(remainder); 524 } 525 526 /** Return a new token whose value is the value of this token 527 * multiplied by the value of the argument token. It is assumed that 528 * the type of the argument is an ShortToken. 529 * @param rightArgument The token to multiply this token by. 530 * @return A new ShortToken containing the result. 531 */ 532 @Override 533 protected ScalarToken _multiply(ScalarToken rightArgument) { 534 short product = (short) (_value 535 * ((ShortToken) rightArgument).shortValue()); 536 return new ShortToken(product); 537 } 538 539 /** Return a new token whose value is the value of the argument token 540 * subtracted from the value of this token. It is assumed that 541 * the type of the argument is an ShortToken. 542 * @param rightArgument The token to subtract from this token. 543 * @return A new ShortToken containing the result. 544 */ 545 @Override 546 protected ScalarToken _subtract(ScalarToken rightArgument) { 547 short difference = (short) (_value 548 - ((ShortToken) rightArgument).shortValue()); 549 return new ShortToken(difference); 550 } 551 552 /////////////////////////////////////////////////////////////////// 553 //// private variables //// 554 private final short _value; 555}