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