1 21 22 package org.armedbear.lisp; 23 24 import java.math.BigInteger ; 25 26 public final class Bignum extends LispObject 27 { 28 public final BigInteger value; 29 30 public Bignum(long l) 31 { 32 value = BigInteger.valueOf(l); 33 } 34 35 public Bignum(BigInteger n) 36 { 37 value = n; 38 } 39 40 public LispObject typeOf() 41 { 42 return Symbol.BIGNUM; 43 } 44 45 public LispClass classOf() 46 { 47 return BuiltInClass.BIGNUM; 48 } 49 50 public LispObject typep(LispObject type) throws ConditionThrowable 51 { 52 if (type == Symbol.BIGNUM) 53 return T; 54 if (type == BuiltInClass.BIGNUM) 55 return T; 56 if (type == Symbol.INTEGER) 57 return T; 58 if (type == BuiltInClass.INTEGER) 59 return T; 60 if (type == Symbol.RATIONAL) 61 return T; 62 if (type == BuiltInClass.RATIONAL) 63 return T; 64 if (type == Symbol.REAL) 65 return T; 66 if (type == BuiltInClass.REAL) 67 return T; 68 if (type == Symbol.NUMBER) 69 return T; 70 if (type == BuiltInClass.NUMBER) 71 return T; 72 if (type == Symbol.SIGNED_BYTE) 73 return T; 74 if (type == Symbol.UNSIGNED_BYTE) 75 return value.signum() >= 0 ? T : NIL; 76 return super.typep(type); 77 } 78 79 public LispObject NUMBERP() 80 { 81 return T; 82 } 83 84 public boolean numberp() 85 { 86 return true; 87 } 88 89 public boolean integerp() 90 { 91 return true; 92 } 93 94 public boolean rationalp() 95 { 96 return true; 97 } 98 99 public boolean realp() 100 { 101 return true; 102 } 103 104 public boolean eql(LispObject obj) 105 { 106 if (this == obj) 107 return true; 108 if (obj instanceof Bignum) { 109 if (value.equals(((Bignum)obj).value)) 110 return true; 111 } 112 return false; 113 } 114 115 public boolean equal(LispObject obj) 116 { 117 if (this == obj) 118 return true; 119 if (obj instanceof Bignum) { 120 if (value.equals(((Bignum)obj).value)) 121 return true; 122 } 123 return false; 124 } 125 126 public boolean equalp(LispObject obj) throws ConditionThrowable 127 { 128 if (obj instanceof Bignum) 129 return value.equals(((Bignum)obj).value); 130 if (obj instanceof LispFloat) 131 return floatValue() == ((LispFloat)obj).getValue(); 132 return false; 133 } 134 135 public LispObject ABS() 136 { 137 if (value.signum() >= 0) 138 return this; 139 return new Bignum(value.negate()); 140 } 141 142 public LispObject NUMERATOR() 143 { 144 return this; 145 } 146 147 public LispObject DENOMINATOR() 148 { 149 return Fixnum.ONE; 150 } 151 152 public boolean evenp() throws ConditionThrowable 153 { 154 return !value.testBit(0); 155 } 156 157 public boolean oddp() throws ConditionThrowable 158 { 159 return value.testBit(0); 160 } 161 162 public boolean plusp() 163 { 164 return value.signum() > 0; 165 } 166 167 public boolean minusp() 168 { 169 return value.signum() < 0; 170 } 171 172 public boolean zerop() 173 { 174 return false; 175 } 176 177 public double floatValue() throws ConditionThrowable 178 { 179 double d = value.doubleValue(); 180 if (Double.isInfinite(d)) 181 signal(new TypeError(writeToString() + 182 " is too large to be converted to a float")); 183 return d; 184 } 185 186 public static BigInteger getValue(LispObject obj) throws ConditionThrowable 187 { 188 try { 189 return ((Bignum)obj).value; 190 } 191 catch (ClassCastException e) { 192 signal(new TypeError(obj, "bignum")); 193 return null; 195 } 196 } 197 198 public final BigInteger getValue() 199 { 200 return value; 201 } 202 203 public final LispObject incr() 204 { 205 return number(value.add(BigInteger.ONE)); 206 } 207 208 public final LispObject decr() 209 { 210 return number(value.subtract(BigInteger.ONE)); 211 } 212 213 public LispObject add(LispObject obj) throws ConditionThrowable 214 { 215 if (obj instanceof Fixnum) 216 return number(value.add(Fixnum.getBigInteger(obj))); 217 if (obj instanceof Bignum) 218 return number(value.add(((Bignum)obj).value)); 219 if (obj instanceof Ratio) { 220 BigInteger numerator = ((Ratio)obj).numerator(); 221 BigInteger denominator = ((Ratio)obj).denominator(); 222 return number(value.multiply(denominator).add(numerator), 223 denominator); 224 } 225 if (obj instanceof LispFloat) 226 return new LispFloat(floatValue() + ((LispFloat)obj).getValue()); 227 if (obj instanceof Complex) { 228 Complex c = (Complex) obj; 229 return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart()); 230 } 231 return signal(new TypeError(obj, Symbol.NUMBER)); 232 } 233 234 public LispObject subtract(LispObject obj) throws ConditionThrowable 235 { 236 if (obj instanceof Fixnum) 237 return number(value.subtract(Fixnum.getBigInteger(obj))); 238 if (obj instanceof Bignum) 239 return number(value.subtract(((Bignum)obj).value)); 240 if (obj instanceof Ratio) { 241 BigInteger numerator = ((Ratio)obj).numerator(); 242 BigInteger denominator = ((Ratio)obj).denominator(); 243 return number(value.multiply(denominator).subtract(numerator), 244 denominator); 245 } 246 if (obj instanceof LispFloat) 247 return new LispFloat(floatValue() - ((LispFloat)obj).getValue()); 248 if (obj instanceof Complex) { 249 Complex c = (Complex) obj; 250 return Complex.getInstance(subtract(c.getRealPart()), 251 Fixnum.ZERO.subtract(c.getImaginaryPart())); 252 } 253 return signal(new TypeError(obj, Symbol.NUMBER)); 254 } 255 256 public LispObject multiplyBy(LispObject obj) throws ConditionThrowable 257 { 258 if (obj instanceof Fixnum) { 259 int n = ((Fixnum)obj).value; 260 if (n == 0) 261 return Fixnum.ZERO; 262 if (n == 1) 263 return this; 264 return new Bignum(value.multiply(BigInteger.valueOf(n))); 265 } 266 if (obj instanceof Bignum) 267 return new Bignum(value.multiply(((Bignum)obj).value)); 268 if (obj instanceof Ratio) { 269 BigInteger n = ((Ratio)obj).numerator(); 270 return number(n.multiply(value), ((Ratio)obj).denominator()); 271 } 272 if (obj instanceof LispFloat) 273 return new LispFloat(floatValue() * ((LispFloat)obj).getValue()); 274 return signal(new TypeError(obj, Symbol.NUMBER)); 275 } 276 277 public LispObject divideBy(LispObject obj) throws ConditionThrowable 278 { 279 if (obj instanceof Fixnum) 280 return number(value, Fixnum.getBigInteger(obj)); 281 if (obj instanceof Bignum) 282 return number(value, ((Bignum)obj).value); 283 if (obj instanceof Ratio) { 284 BigInteger d = ((Ratio)obj).denominator(); 285 return number(d.multiply(value), ((Ratio)obj).numerator()); 286 } 287 if (obj instanceof LispFloat) 288 return new LispFloat(floatValue() / ((LispFloat)obj).getValue()); 289 return signal(new TypeError(obj, Symbol.NUMBER)); 290 } 291 292 public boolean isEqualTo(LispObject obj) throws ConditionThrowable 293 { 294 if (obj instanceof Bignum) 295 return value.equals(((Bignum)obj).value); 296 if (obj instanceof LispFloat) 297 return isEqualTo(((LispFloat)obj).rational()); 298 if (obj.numberp()) 299 return false; 300 signal(new TypeError(obj, Symbol.NUMBER)); 301 return false; 303 } 304 305 public boolean isNotEqualTo(LispObject obj) throws ConditionThrowable 306 { 307 if (obj instanceof Bignum) 308 return !value.equals(((Bignum)obj).value); 309 if (obj instanceof LispFloat) 310 return isNotEqualTo(((LispFloat)obj).rational()); 311 if (obj.numberp()) 312 return true; 313 signal(new TypeError(obj, Symbol.NUMBER)); 314 return false; 316 } 317 318 public boolean isLessThan(LispObject obj) throws ConditionThrowable 319 { 320 if (obj instanceof Fixnum) 321 return value.compareTo(Fixnum.getBigInteger(obj)) < 0; 322 if (obj instanceof Bignum) 323 return value.compareTo(((Bignum)obj).value) < 0; 324 if (obj instanceof Ratio) { 325 BigInteger n = value.multiply(((Ratio)obj).denominator()); 326 return n.compareTo(((Ratio)obj).numerator()) < 0; 327 } 328 if (obj instanceof LispFloat) 329 return isLessThan(((LispFloat)obj).rational()); 330 signal(new TypeError(obj, Symbol.REAL)); 331 return false; 333 } 334 335 public boolean isGreaterThan(LispObject obj) throws ConditionThrowable 336 { 337 if (obj instanceof Fixnum) 338 return value.compareTo(Fixnum.getBigInteger(obj)) > 0; 339 if (obj instanceof Bignum) 340 return value.compareTo(((Bignum)obj).value) > 0; 341 if (obj instanceof Ratio) { 342 BigInteger n = value.multiply(((Ratio)obj).denominator()); 343 return n.compareTo(((Ratio)obj).numerator()) > 0; 344 } 345 if (obj instanceof LispFloat) 346 return isGreaterThan(((LispFloat)obj).rational()); 347 signal(new TypeError(obj, Symbol.REAL)); 348 return false; 350 } 351 352 public boolean isLessThanOrEqualTo(LispObject obj) throws ConditionThrowable 353 { 354 if (obj instanceof Fixnum) 355 return value.compareTo(Fixnum.getBigInteger(obj)) <= 0; 356 if (obj instanceof Bignum) 357 return value.compareTo(((Bignum)obj).value) <= 0; 358 if (obj instanceof Ratio) { 359 BigInteger n = value.multiply(((Ratio)obj).denominator()); 360 return n.compareTo(((Ratio)obj).numerator()) <= 0; 361 } 362 if (obj instanceof LispFloat) 363 return isLessThanOrEqualTo(((LispFloat)obj).rational()); 364 signal(new TypeError(obj, Symbol.REAL)); 365 return false; 367 } 368 369 public boolean isGreaterThanOrEqualTo(LispObject obj) throws ConditionThrowable 370 { 371 if (obj instanceof Fixnum) 372 return value.compareTo(Fixnum.getBigInteger(obj)) >= 0; 373 if (obj instanceof Bignum) 374 return value.compareTo(((Bignum)obj).value) >= 0; 375 if (obj instanceof Ratio) { 376 BigInteger n = value.multiply(((Ratio)obj).denominator()); 377 return n.compareTo(((Ratio)obj).numerator()) >= 0; 378 } 379 if (obj instanceof LispFloat) 380 return isGreaterThanOrEqualTo(((LispFloat)obj).rational()); 381 signal(new TypeError(obj, Symbol.REAL)); 382 return false; 384 } 385 386 public LispObject truncate(LispObject obj) throws ConditionThrowable 387 { 388 final LispThread thread = LispThread.currentThread(); 389 LispObject value1, value2; 390 try { 391 if (obj instanceof Ratio) { 392 Ratio divisor = (Ratio) obj; 393 LispObject quotient = 394 multiplyBy(divisor.DENOMINATOR()).truncate(divisor.NUMERATOR()); 395 LispObject remainder = 396 subtract(quotient.multiplyBy(divisor)); 397 value1 = quotient; 398 value2 = remainder; 399 } else if (obj instanceof Fixnum) { 400 BigInteger divisor = ((Fixnum)obj).getBigInteger(); 401 BigInteger [] results = value.divideAndRemainder(divisor); 402 BigInteger quotient = results[0]; 403 BigInteger remainder = results[1]; 404 value1 = number(quotient); 405 value2 = (remainder.signum() == 0) ? Fixnum.ZERO : number(remainder); 406 } else if (obj instanceof Bignum) { 407 BigInteger divisor = ((Bignum)obj).value; 408 BigInteger [] results = value.divideAndRemainder(divisor); 409 BigInteger quotient = results[0]; 410 BigInteger remainder = results[1]; 411 value1 = number(quotient); 412 value2 = (remainder.signum() == 0) ? Fixnum.ZERO : number(remainder); 413 } else if (obj instanceof Ratio) { 414 Ratio divisor = (Ratio) obj; 415 LispObject quotient = 416 multiplyBy(divisor.DENOMINATOR()).truncate(divisor.NUMERATOR()); 417 LispObject remainder = 418 subtract(quotient.multiplyBy(divisor)); 419 value1 = quotient; 420 value2 = remainder; 421 } else 422 return signal(new LispError("Bignum.truncate(): not implemented: " + obj.typeOf())); 423 } 424 catch (ArithmeticException e) { 425 if (obj.zerop()) 426 return signal(new DivisionByZero()); 427 else 428 return signal(new ArithmeticError(e.getMessage())); 429 } 430 return thread.setValues(value1, value2); 431 } 432 433 public LispObject ash(LispObject obj) throws ConditionThrowable 434 { 435 BigInteger n = value; 436 if (obj instanceof Fixnum) { 437 int count = ((Fixnum)obj).value; 438 if (count == 0) 439 return this; 440 if (count == Integer.MIN_VALUE) 443 return n.signum() >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; 444 return number(n.shiftLeft(count)); 445 } 446 if (obj instanceof Bignum) { 447 BigInteger count = ((Bignum)obj).value; 448 if (count.signum() > 0) 449 return signal(new LispError("Can't represent result of left shift.")); 450 if (count.signum() < 0) 451 return n.signum() >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE; 452 Debug.bug(); } 454 return signal(new TypeError(obj, Symbol.INTEGER)); 455 } 456 457 public int hashCode() 458 { 459 return value.hashCode(); 460 } 461 462 public String writeToString() throws ConditionThrowable 463 { 464 final LispThread thread = LispThread.currentThread(); 465 final int base = Fixnum.getValue(_PRINT_BASE_.symbolValue(thread)); 466 String s = value.toString(base).toUpperCase(); 467 if (_PRINT_RADIX_.symbolValue(thread) != NIL) { 468 StringBuffer sb = new StringBuffer (); 469 switch (base) { 470 case 2: 471 sb.append("#b"); 472 sb.append(s); 473 break; 474 case 8: 475 sb.append("#o"); 476 sb.append(s); 477 break; 478 case 10: 479 sb.append(s); 480 sb.append('.'); 481 break; 482 case 16: 483 sb.append("#x"); 484 sb.append(s); 485 break; 486 default: 487 sb.append('#'); 488 sb.append(String.valueOf(base)); 489 sb.append('r'); 490 sb.append(s); 491 break; 492 } 493 s = sb.toString(); 494 } 495 return s; 496 } 497 } 498 | Popular Tags |