1 21 22 package org.armedbear.lisp; 23 24 import java.math.BigInteger ; 25 26 public final class Fixnum extends LispObject 27 { 28 public static final Fixnum ZERO = new Fixnum(0); 29 public static final Fixnum ONE = new Fixnum(1); 30 public static final Fixnum TWO = new Fixnum(2); 31 public static final Fixnum MINUS_ONE = new Fixnum(-1); 32 33 public final int value; 34 35 public Fixnum(int value) 36 { 37 this.value = value; 38 } 39 40 public Object javaInstance() 41 { 42 return new Integer (value); 43 } 44 45 public Object javaInstance(Class c) 46 { 47 String cn = c.getName(); 48 if (cn.equals("java.lang.Byte") || cn.equals("byte")) 49 return new Byte (((Integer )javaInstance()).byteValue()); 50 if (cn.equals("java.lang.Short") || cn.equals("short")) 51 return new Short (((Integer )javaInstance()).shortValue()); 52 if (cn.equals("java.lang.Long") || cn.equals("long")) 53 return new Long (((Integer )javaInstance()).longValue()); 54 return javaInstance(); 55 } 56 57 public static Fixnum getInstance(int value) 58 { 59 return new Fixnum(value); 60 } 61 62 public LispObject typeOf() 63 { 64 if (value == 0 || value == 1) 65 return Symbol.BIT; 66 else 67 return Symbol.FIXNUM; 68 } 69 70 public LispClass classOf() 71 { 72 return BuiltInClass.FIXNUM; 73 } 74 75 public LispObject getDescription() 76 { 77 StringBuffer sb = new StringBuffer ("The fixnum "); 78 sb.append(value); 79 return new SimpleString(sb); 80 } 81 82 public LispObject typep(LispObject type) throws ConditionThrowable 83 { 84 if (type == Symbol.FIXNUM) 85 return T; 86 if (type == BuiltInClass.FIXNUM) 87 return T; 88 if (type == Symbol.INTEGER) 89 return T; 90 if (type == BuiltInClass.INTEGER) 91 return T; 92 if (type == Symbol.RATIONAL) 93 return T; 94 if (type == BuiltInClass.RATIONAL) 95 return T; 96 if (type == Symbol.REAL) 97 return T; 98 if (type == BuiltInClass.REAL) 99 return T; 100 if (type == Symbol.NUMBER) 101 return T; 102 if (type == BuiltInClass.NUMBER) 103 return T; 104 if (type == Symbol.SIGNED_BYTE) 105 return T; 106 if (type == Symbol.UNSIGNED_BYTE) 107 return value >= 0 ? T : NIL; 108 if (type == Symbol.BIT) 109 return (value == 0 || value == 1) ? T : NIL; 110 return super.typep(type); 111 } 112 113 public LispObject NUMBERP() 114 { 115 return T; 116 } 117 118 public boolean numberp() 119 { 120 return true; 121 } 122 123 public boolean integerp() 124 { 125 return true; 126 } 127 128 public boolean rationalp() 129 { 130 return true; 131 } 132 133 public boolean realp() 134 { 135 return true; 136 } 137 138 public boolean eql(LispObject obj) 139 { 140 if (this == obj) 141 return true; 142 if (obj instanceof Fixnum) { 143 if (value == ((Fixnum)obj).value) 144 return true; 145 } 146 return false; 147 } 148 149 public boolean equal(LispObject obj) 150 { 151 if (this == obj) 152 return true; 153 if (obj instanceof Fixnum) { 154 if (value == ((Fixnum)obj).value) 155 return true; 156 } 157 return false; 158 } 159 160 public boolean equalp(LispObject obj) 161 { 162 if (obj instanceof Fixnum) 163 return value == ((Fixnum)obj).value; 164 if (obj instanceof LispFloat) 165 return (float) value == ((LispFloat)obj).getValue(); 166 return false; 167 } 168 169 public LispObject ABS() 170 { 171 if (value >= 0) 172 return this; 173 return number(-((long)value)); 174 } 175 176 public LispObject NUMERATOR() 177 { 178 return this; 179 } 180 181 public LispObject DENOMINATOR() 182 { 183 return ONE; 184 } 185 186 public boolean evenp() throws ConditionThrowable 187 { 188 return (value & 0x01) == 0; 189 } 190 191 public boolean oddp() throws ConditionThrowable 192 { 193 return (value & 0x01) != 0; 194 } 195 196 public boolean plusp() 197 { 198 return value > 0; 199 } 200 201 public boolean minusp() 202 { 203 return value < 0; 204 } 205 206 public boolean zerop() 207 { 208 return value == 0; 209 } 210 211 public static int getValue(LispObject obj) throws ConditionThrowable 212 { 213 try { 214 return ((Fixnum)obj).value; 215 } 216 catch (ClassCastException e) { 217 signal(new TypeError(obj, Symbol.FIXNUM)); 218 return 0; 220 } 221 } 222 223 public static int getInt(LispObject obj) throws ConditionThrowable 224 { 225 try { 226 return (int) ((Fixnum)obj).value; 227 } 228 catch (ClassCastException e) { 229 signal(new TypeError(obj, Symbol.FIXNUM)); 230 return 0; 232 } 233 } 234 235 public static BigInteger getBigInteger(LispObject obj) throws ConditionThrowable 236 { 237 try { 238 return BigInteger.valueOf(((Fixnum)obj).value); 239 } 240 catch (ClassCastException e) { 241 signal(new TypeError(obj, Symbol.FIXNUM)); 242 return null; 244 } 245 } 246 247 public static float getFloat(LispObject obj) throws ConditionThrowable 248 { 249 try { 250 return (float) ((Fixnum)obj).value; 251 } 252 catch (ClassCastException e) { 253 signal(new TypeError(obj, Symbol.FIXNUM)); 254 return 0; 255 } 256 } 257 258 public final int getValue() 259 { 260 return value; 261 } 262 263 public final BigInteger getBigInteger() 264 { 265 return BigInteger.valueOf(value); 266 } 267 268 public final LispObject incr() 269 { 270 if (value < Integer.MAX_VALUE) 271 return new Fixnum(value + 1); 272 return new Bignum((long) value + 1); 273 } 274 275 public final LispObject decr() 276 { 277 if (value > Integer.MIN_VALUE) 278 return new Fixnum(value - 1); 279 return new Bignum((long) value - 1); 280 } 281 282 public LispObject add(LispObject obj) throws ConditionThrowable 283 { 284 if (obj instanceof Fixnum) 285 return number((long) value + ((Fixnum)obj).value); 286 if (obj instanceof Bignum) 287 return number(getBigInteger().add(Bignum.getValue(obj))); 288 if (obj instanceof Ratio) { 289 BigInteger numerator = ((Ratio)obj).numerator(); 290 BigInteger denominator = ((Ratio)obj).denominator(); 291 return number( 292 getBigInteger().multiply(denominator).add(numerator), 293 denominator); 294 } 295 if (obj instanceof LispFloat) 296 return new LispFloat(value + LispFloat.getValue(obj)); 297 if (obj instanceof Complex) { 298 Complex c = (Complex) obj; 299 return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart()); 300 } 301 return signal(new TypeError(obj, "number")); 302 } 303 304 public LispObject subtract(LispObject obj) throws ConditionThrowable 305 { 306 if (obj instanceof Fixnum) 307 return number((long) value - ((Fixnum)obj).value); 308 if (obj instanceof Bignum) 309 return number(getBigInteger().subtract(Bignum.getValue(obj))); 310 if (obj instanceof Ratio) { 311 BigInteger numerator = ((Ratio)obj).numerator(); 312 BigInteger denominator = ((Ratio)obj).denominator(); 313 return number( 314 getBigInteger().multiply(denominator).subtract(numerator), 315 denominator); 316 } 317 if (obj instanceof LispFloat) 318 return new LispFloat(value - LispFloat.getValue(obj)); 319 if (obj instanceof Complex) { 320 Complex c = (Complex) obj; 321 return Complex.getInstance(subtract(c.getRealPart()), 322 ZERO.subtract(c.getImaginaryPart())); 323 } 324 return signal(new TypeError(obj, "number")); 325 } 326 327 public LispObject multiplyBy(LispObject obj) throws ConditionThrowable 328 { 329 if (obj instanceof Fixnum) 330 return number((long) value * ((Fixnum)obj).value); 331 if (obj instanceof Bignum) 332 return number(getBigInteger().multiply(((Bignum)obj).value)); 333 if (obj instanceof Ratio) { 334 BigInteger numerator = ((Ratio)obj).numerator(); 335 BigInteger denominator = ((Ratio)obj).denominator(); 336 return number( 337 getBigInteger().multiply(numerator), 338 denominator); 339 } 340 if (obj instanceof LispFloat) 341 return new LispFloat(value * LispFloat.getValue(obj)); 342 if (obj instanceof Complex) { 343 Complex c = (Complex) obj; 344 return Complex.getInstance(multiplyBy(c.getRealPart()), 345 multiplyBy(c.getImaginaryPart())); 346 } 347 return signal(new TypeError(obj, "number")); 348 } 349 350 public LispObject divideBy(LispObject obj) throws ConditionThrowable 351 { 352 try { 353 if (obj instanceof Fixnum) { 354 final int divisor = ((Fixnum)obj).value; 355 if (value % divisor == 0) 356 return new Fixnum(value / divisor); 357 return number(BigInteger.valueOf(value), 358 BigInteger.valueOf(divisor)); 359 } 360 if (obj instanceof Bignum) 361 return number(getBigInteger(), ((Bignum)obj).getValue()); 362 if (obj instanceof Ratio) { 363 BigInteger numerator = ((Ratio)obj).numerator(); 364 BigInteger denominator = ((Ratio)obj).denominator(); 365 return number(getBigInteger().multiply(denominator), 366 numerator); 367 } 368 if (obj instanceof LispFloat) 369 return new LispFloat(value / LispFloat.getValue(obj)); 370 if (obj instanceof Complex) { 371 Complex c = (Complex) obj; 372 LispObject realPart = c.getRealPart(); 373 LispObject imagPart = c.getImaginaryPart(); 374 LispObject denominator = 375 realPart.multiplyBy(realPart).add(imagPart.multiplyBy(imagPart)); 376 return Complex.getInstance(multiplyBy(realPart).divideBy(denominator), 377 Fixnum.ZERO.subtract(multiplyBy(imagPart).divideBy(denominator))); 378 } 379 return signal(new TypeError(obj, "number")); 380 } 381 catch (ArithmeticException e) { 382 if (obj.zerop()) 383 return signal(new DivisionByZero()); 384 return signal(new ArithmeticError(e.getMessage())); 385 } 386 } 387 388 public boolean isEqualTo(LispObject obj) throws ConditionThrowable 389 { 390 if (obj instanceof Fixnum) 391 return value == ((Fixnum)obj).value; 392 if (obj instanceof LispFloat) 393 return (float) value == LispFloat.getValue(obj); 394 if (obj instanceof Complex) 395 return obj.isEqualTo(this); 396 if (obj.numberp()) 397 return false; 398 signal(new TypeError(obj, "number")); 399 return false; 401 } 402 403 public boolean isNotEqualTo(LispObject obj) throws ConditionThrowable 404 { 405 if (obj instanceof Fixnum) 406 return value != ((Fixnum)obj).value; 407 if (obj instanceof LispFloat) 409 return (float) value != LispFloat.getValue(obj); 410 if (obj instanceof Complex) 411 return obj.isNotEqualTo(this); 412 if (obj.numberp()) 413 return true; 414 signal(new TypeError(obj, "number")); 415 return false; 417 } 418 419 public boolean isLessThan(LispObject obj) throws ConditionThrowable 420 { 421 if (obj instanceof Fixnum) 422 return value < ((Fixnum)obj).value; 423 if (obj instanceof Bignum) 424 return getBigInteger().compareTo(Bignum.getValue(obj)) < 0; 425 if (obj instanceof Ratio) { 426 BigInteger n = 427 getBigInteger().multiply(((Ratio)obj).denominator()); 428 return n.compareTo(((Ratio)obj).numerator()) < 0; 429 } 430 if (obj instanceof LispFloat) 431 return isLessThan(((LispFloat)obj).rational()); 432 signal(new TypeError(obj, "number")); 433 return false; 435 } 436 437 public boolean isGreaterThan(LispObject obj) throws ConditionThrowable 438 { 439 if (obj instanceof Fixnum) 440 return value > ((Fixnum)obj).value; 441 if (obj instanceof Bignum) 442 return getBigInteger().compareTo(Bignum.getValue(obj)) > 0; 443 if (obj instanceof Ratio) { 444 BigInteger n = 445 getBigInteger().multiply(((Ratio)obj).denominator()); 446 return n.compareTo(((Ratio)obj).numerator()) > 0; 447 } 448 if (obj instanceof LispFloat) 449 return isGreaterThan(((LispFloat)obj).rational()); 450 signal(new TypeError(obj, "number")); 451 return false; 453 } 454 455 public boolean isLessThanOrEqualTo(LispObject obj) throws ConditionThrowable 456 { 457 if (obj instanceof Fixnum) 458 return value <= ((Fixnum)obj).value; 459 if (obj instanceof Bignum) 460 return getBigInteger().compareTo(Bignum.getValue(obj)) <= 0; 461 if (obj instanceof Ratio) { 462 BigInteger n = 463 getBigInteger().multiply(((Ratio)obj).denominator()); 464 return n.compareTo(((Ratio)obj).numerator()) <= 0; 465 } 466 if (obj instanceof LispFloat) 467 return isLessThanOrEqualTo(((LispFloat)obj).rational()); 468 signal(new TypeError(obj, "number")); 469 return false; 471 } 472 473 public boolean isGreaterThanOrEqualTo(LispObject obj) throws ConditionThrowable 474 { 475 if (obj instanceof Fixnum) 476 return value >= ((Fixnum)obj).value; 477 if (obj instanceof Bignum) 478 return getBigInteger().compareTo(Bignum.getValue(obj)) >= 0; 479 if (obj instanceof Ratio) { 480 BigInteger n = 481 getBigInteger().multiply(((Ratio)obj).denominator()); 482 return n.compareTo(((Ratio)obj).numerator()) >= 0; 483 } 484 if (obj instanceof LispFloat) 485 return isGreaterThanOrEqualTo(((LispFloat)obj).rational()); 486 signal(new TypeError(obj, "number")); 487 return false; 489 } 490 491 public LispObject truncate(LispObject obj) throws ConditionThrowable 492 { 493 final LispThread thread = LispThread.currentThread(); 494 final LispObject value1, value2; 495 try { 496 if (obj instanceof Fixnum) { 497 long divisor = ((Fixnum)obj).value; 498 long quotient = value / divisor; 499 long remainder = value % divisor; 500 value1 = number(quotient); 501 value2 = remainder == 0 ? Fixnum.ZERO : number(remainder); 502 } else if (obj instanceof Bignum) { 503 BigInteger value = getBigInteger(); 504 BigInteger divisor = ((Bignum)obj).getValue(); 505 BigInteger [] results = value.divideAndRemainder(divisor); 506 BigInteger quotient = results[0]; 507 BigInteger remainder = results[1]; 508 value1 = number(quotient); 509 value2 = (remainder.signum() == 0) ? Fixnum.ZERO : number(remainder); 510 } else if (obj instanceof Ratio) { 511 Ratio divisor = (Ratio) obj; 512 LispObject quotient = 513 multiplyBy(divisor.DENOMINATOR()).truncate(divisor.NUMERATOR()); 514 LispObject remainder = 515 subtract(quotient.multiplyBy(divisor)); 516 value1 = quotient; 517 value2 = remainder; 518 } else 519 return signal(new LispError("Fixnum.truncate(): not implemented: " + obj.typeOf())); 520 } 521 catch (ArithmeticException e) { 522 if (obj.zerop()) 523 return signal(new DivisionByZero()); 524 else 525 return signal(new ArithmeticError(e.getMessage())); 526 } 527 return thread.setValues(value1, value2); 528 } 529 530 public LispObject MOD(LispObject divisor) throws ConditionThrowable 531 { 532 if (divisor instanceof Fixnum) { 533 final int d = ((Fixnum)divisor).value; 534 final int r; 535 try { 536 r = value % d; 537 } 538 catch (ArithmeticException e) { 539 return signal(new ArithmeticError("Division by zero.")); 540 } 541 if (r == 0) 542 return Fixnum.ZERO; 543 if (d < 0) { 544 if (value > 0) 545 return new Fixnum(r + d); 546 } else { 547 if (value < 0) 548 return new Fixnum(r + d); 549 } 550 return new Fixnum(r); 551 } 552 return super.MOD(divisor); 553 } 554 555 public LispObject ash(LispObject obj) throws ConditionThrowable 556 { 557 if (obj instanceof Fixnum) { 558 if (value == 0) 559 return this; 560 int shift = ((Fixnum)obj).value; 561 if (shift == 0) 562 return this; 563 long n = value; 564 if (shift <= -32) { 565 return n >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; 567 } 568 if (shift < 0) 569 return new Fixnum((int)(n >> -shift)); 570 if (shift <= 32) 571 return number(n << shift); 572 if (shift == Integer.MIN_VALUE) 575 return n >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; 576 return number(BigInteger.valueOf(value).shiftLeft(shift)); 577 } 578 if (obj instanceof Bignum) { 579 if (value == 0) 580 return this; 581 BigInteger n = BigInteger.valueOf(value); 582 BigInteger shift = ((Bignum)obj).value; 583 if (shift.signum() > 0) 584 return signal(new LispError("Can't represent result of left shift.")); 585 if (shift.signum() < 0) 586 return n.signum() >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; 587 Debug.bug(); } 589 return signal(new TypeError(obj, Symbol.INTEGER)); 590 } 591 592 public int hashCode() 593 { 594 return value; 595 } 596 597 public String writeToString() throws ConditionThrowable 598 { 599 final LispThread thread = LispThread.currentThread(); 600 int base = Fixnum.getValue(_PRINT_BASE_.symbolValue(thread)); 601 String s = Integer.toString(value, base).toUpperCase(); 602 if (_PRINT_RADIX_.symbolValue(thread) != NIL) { 603 StringBuffer sb = new StringBuffer (); 604 switch (base) { 605 case 2: 606 sb.append("#b"); 607 sb.append(s); 608 break; 609 case 8: 610 sb.append("#o"); 611 sb.append(s); 612 break; 613 case 10: 614 sb.append(s); 615 sb.append('.'); 616 break; 617 case 16: 618 sb.append("#x"); 619 sb.append(s); 620 break; 621 default: 622 sb.append('#'); 623 sb.append(String.valueOf(base)); 624 sb.append('r'); 625 sb.append(s); 626 break; 627 } 628 s = sb.toString(); 629 } 630 return s; 631 } 632 } 633 | Popular Tags |