source: branches/0.22.x/abcl/src/org/armedbear/lisp/Fixnum.java

Last change on this file was 12431, checked in by Mark Evenson, 15 years ago

Replace FastStringBuffer? with java.lang.StringBuilder?.

Phil Hudson suggested in Feburary 2009 that "[FastStringBuffer?] should
be removed with all references to it replaced with
java.lang.StringBuilder? once enough confidence in this change has been
gained." After almost a year of using FastStringBuffer? as a delagate
for StringBuilder?, that confidence has indeed been gained.

One subtlety for use of StringBuilder?: there is no

StringBuilder?(char)

constructor, so use

StringBuilder?(String.valueOf(c))

to construct a new StringBuilder? containing a single char. Otherwise
that char will get promoted to an int, and you will invoke

StringBuilder?(int capacity)

which will "swallow" the first character that you thought you were adding.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.1 KB
Line 
1/*
2 * Fixnum.java
3 *
4 * Copyright (C) 2002-2006 Peter Graves
5 * $Id: Fixnum.java 12431 2010-02-08 08:05:15Z mevenson $
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 *
21 * As a special exception, the copyright holders of this library give you
22 * permission to link this library with independent modules to produce an
23 * executable, regardless of the license terms of these independent
24 * modules, and to copy and distribute the resulting executable under
25 * terms of your choice, provided that you also meet, for each linked
26 * independent module, the terms and conditions of the license of that
27 * module.  An independent module is a module which is not derived from
28 * or based on this library.  If you modify this library, you may extend
29 * this exception to your version of the library, but you are not
30 * obligated to do so.  If you do not wish to do so, delete this
31 * exception statement from your version.
32 */
33
34package org.armedbear.lisp;
35
36import static org.armedbear.lisp.Lisp.*;
37
38import java.math.BigInteger;
39
40public final class Fixnum extends LispInteger
41{
42  public static final int MAX_POS_CACHE = 256;//just like before - however never set this to less than 256
43  public static final Fixnum[] constants = new Fixnum[MAX_POS_CACHE];
44  static
45  {
46    for (int i = 0; i < MAX_POS_CACHE; i++)
47      constants[i] = new Fixnum(i);
48  }
49
50  public static final Fixnum ZERO      = constants[0];
51  public static final Fixnum ONE       = constants[1];
52  public static final Fixnum TWO       = constants[2];
53  public static final Fixnum THREE     = constants[3];
54
55  public static final Fixnum MINUS_ONE = Fixnum.getInstance(-1);
56
57  public static Fixnum getInstance(int n)
58  {
59    return (n >= 0 && n < MAX_POS_CACHE) ? constants[n] : new Fixnum(n);
60  }
61
62  public final int value;
63
64  // set to private to hunt down sneaky creators
65  private Fixnum(int value)
66  {
67    this.value = value;
68  }
69
70  @Override
71  public Object javaInstance()
72  {
73    return Integer.valueOf(value);
74  }
75
76  @Override
77  public Object javaInstance(Class c)
78  {
79    String cn = c.getName();
80    if (cn.equals("java.lang.Byte") || cn.equals("byte"))
81      return Byte.valueOf((byte)value);
82    if (cn.equals("java.lang.Short") || cn.equals("short"))
83      return Short.valueOf((short)value);
84    if (cn.equals("java.lang.Long") || cn.equals("long"))
85      return Long.valueOf((long)value);
86    return javaInstance();
87  }
88
89  @Override
90  public LispObject typeOf()
91  {
92    if (value == 0 || value == 1)
93      return Symbol.BIT;
94    if (value > 1)
95      return list(Symbol.INTEGER, ZERO, Fixnum.getInstance(Integer.MAX_VALUE));
96    return Symbol.FIXNUM;
97  }
98
99  @Override
100  public LispObject classOf()
101  {
102    return BuiltInClass.FIXNUM;
103  }
104
105  @Override
106  public LispObject getDescription()
107  {
108    StringBuffer sb = new StringBuffer("The fixnum ");
109    sb.append(value);
110    return new SimpleString(sb);
111  }
112
113  @Override
114  public LispObject typep(LispObject type)
115  {
116    if (type instanceof Symbol)
117      {
118        if (type == Symbol.FIXNUM)
119          return T;
120        if (type == Symbol.INTEGER)
121          return T;
122        if (type == Symbol.RATIONAL)
123          return T;
124        if (type == Symbol.REAL)
125          return T;
126        if (type == Symbol.NUMBER)
127          return T;
128        if (type == Symbol.SIGNED_BYTE)
129          return T;
130        if (type == Symbol.UNSIGNED_BYTE)
131          return value >= 0 ? T : NIL;
132        if (type == Symbol.BIT)
133          return (value == 0 || value == 1) ? T : NIL;
134      }
135    else if (type instanceof LispClass)
136      {
137        if (type == BuiltInClass.FIXNUM)
138          return T;
139        if (type == BuiltInClass.INTEGER)
140          return T;
141        if (type == BuiltInClass.RATIONAL)
142          return T;
143        if (type == BuiltInClass.REAL)
144          return T;
145        if (type == BuiltInClass.NUMBER)
146          return T;
147      }
148    else if (type instanceof Cons)
149      {
150        if (type.equal(UNSIGNED_BYTE_8))
151          return (value >= 0 && value <= 255) ? T : NIL;
152        if (type.equal(UNSIGNED_BYTE_16))
153          return (value >= 0 && value <= 65535) ? T : NIL;
154        if (type.equal(UNSIGNED_BYTE_32))
155          return value >= 0 ? T : NIL;
156      }
157    return super.typep(type);
158  }
159
160  @Override
161  public boolean numberp()
162  {
163    return true;
164  }
165
166  @Override
167  public boolean integerp()
168  {
169    return true;
170  }
171
172  @Override
173  public boolean rationalp()
174  {
175    return true;
176  }
177
178  @Override
179  public boolean realp()
180  {
181    return true;
182  }
183
184  @Override
185  public boolean eql(int n)
186  {
187    return value == n;
188  }
189
190  @Override
191  public boolean eql(LispObject obj)
192  {
193    if (this == obj)
194      return true;
195    if (obj instanceof Fixnum)
196      {
197        if (value == ((Fixnum)obj).value)
198          return true;
199      }
200    return false;
201  }
202
203  @Override
204  public boolean equal(int n)
205  {
206    return value == n;
207  }
208
209  @Override
210  public boolean equal(LispObject obj)
211  {
212    if (this == obj)
213      return true;
214    if (obj instanceof Fixnum)
215      {
216        if (value == ((Fixnum)obj).value)
217          return true;
218      }
219    return false;
220  }
221
222  @Override
223  public boolean equalp(int n)
224  {
225    return value == n;
226  }
227
228  @Override
229  public boolean equalp(LispObject obj)
230  {
231    if (obj instanceof Fixnum)
232      return value == ((Fixnum)obj).value;
233    if (obj instanceof SingleFloat)
234      return value == ((SingleFloat)obj).value;
235    if (obj instanceof DoubleFloat)
236      return value == ((DoubleFloat)obj).value;
237    return false;
238  }
239
240  @Override
241  public LispObject ABS()
242  {
243    if (value >= 0)
244      return this;
245    return LispInteger.getInstance(-(long)value);
246  }
247
248  @Override
249  public LispObject NUMERATOR()
250  {
251    return this;
252  }
253
254  @Override
255  public LispObject DENOMINATOR()
256  {
257    return ONE;
258  }
259
260  @Override
261  public boolean evenp()
262  {
263    return (value & 0x01) == 0;
264  }
265
266  @Override
267  public boolean oddp()
268  {
269    return (value & 0x01) != 0;
270  }
271
272  @Override
273  public boolean plusp()
274  {
275    return value > 0;
276  }
277
278  @Override
279  public boolean minusp()
280  {
281    return value < 0;
282  }
283
284  @Override
285  public boolean zerop()
286  {
287    return value == 0;
288  }
289
290  public static int getValue(LispObject obj)
291  {
292          if (obj instanceof Fixnum) return ((Fixnum)obj).value;
293          type_error(obj, Symbol.FIXNUM);
294      // Not reached.
295          return 0;
296  }
297
298  @Override
299  public float floatValue() {
300    return (float)value;
301  }
302
303  @Override
304  public double doubleValue() {
305    return (double)value;
306  }
307
308  public static int getInt(LispObject obj)
309  {
310          if (obj instanceof Fixnum) return ((Fixnum)obj).value;
311          type_error(obj, Symbol.FIXNUM);
312      // Not reached.
313          return 0;
314  }
315
316  public static BigInteger getBigInteger(LispObject obj)
317  {
318          if (obj instanceof Fixnum) return BigInteger.valueOf(((Fixnum)obj).value);
319          type_error(obj, Symbol.FIXNUM);
320      // Not reached.
321          return null;
322  }
323
324  @Override
325  public int intValue()
326  {
327    return value;
328  }
329
330  @Override
331  public long longValue()
332  {
333    return (long) value;
334  }
335
336  public final BigInteger getBigInteger()
337  {
338    return BigInteger.valueOf(value);
339  }
340
341  @Override
342  public final LispObject incr()
343  {
344    return LispInteger.getInstance(1 + (long)value);
345  }
346
347  @Override
348  public final LispObject decr()
349  {
350    return LispInteger.getInstance(-1 + (long)value);
351  }
352
353  @Override
354  public LispObject negate()
355  {
356    return LispInteger.getInstance((-(long)value));
357  }
358
359  @Override
360  public LispObject add(int n)
361  {
362    return LispInteger.getInstance((long) value + n);
363  }
364
365  @Override
366  public LispObject add(LispObject obj)
367  {
368    if (obj instanceof Fixnum)
369      {
370        long result = (long) value + ((Fixnum)obj).value;
371        return LispInteger.getInstance(result);
372      }
373    if (obj instanceof Bignum)
374      return number(getBigInteger().add(((Bignum)obj).value));
375    if (obj instanceof Ratio)
376      {
377        BigInteger numerator = ((Ratio)obj).numerator();
378        BigInteger denominator = ((Ratio)obj).denominator();
379        return number(getBigInteger().multiply(denominator).add(numerator),
380                      denominator);
381      }
382    if (obj instanceof SingleFloat)
383      return new SingleFloat(value + ((SingleFloat)obj).value);
384    if (obj instanceof DoubleFloat)
385      return new DoubleFloat(value + ((DoubleFloat)obj).value);
386    if (obj instanceof Complex)
387      {
388        Complex c = (Complex) obj;
389        return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart());
390      }
391    return type_error(obj, Symbol.NUMBER);
392  }
393
394  @Override
395  public LispObject subtract(int n)
396  {
397    return LispInteger.getInstance((long)value - n);
398  }
399
400  @Override
401  public LispObject subtract(LispObject obj)
402  {
403    if (obj instanceof Fixnum)
404      return number((long) value - ((Fixnum)obj).value);
405    if (obj instanceof Bignum)
406      return number(getBigInteger().subtract(Bignum.getValue(obj)));
407    if (obj instanceof Ratio)
408      {
409        BigInteger numerator = ((Ratio)obj).numerator();
410        BigInteger denominator = ((Ratio)obj).denominator();
411        return number(
412          getBigInteger().multiply(denominator).subtract(numerator),
413          denominator);
414      }
415    if (obj instanceof SingleFloat)
416      return new SingleFloat(value - ((SingleFloat)obj).value);
417    if (obj instanceof DoubleFloat)
418      return new DoubleFloat(value - ((DoubleFloat)obj).value);
419    if (obj instanceof Complex)
420      {
421        Complex c = (Complex) obj;
422        return Complex.getInstance(subtract(c.getRealPart()),
423                                   ZERO.subtract(c.getImaginaryPart()));
424      }
425    return type_error(obj, Symbol.NUMBER);
426  }
427
428  @Override
429  public LispObject multiplyBy(int n)
430  {
431    long result = (long) value * n;
432    return LispInteger.getInstance(result);
433  }
434
435  @Override
436  public LispObject multiplyBy(LispObject obj)
437  {
438    if (obj instanceof Fixnum)
439      {
440        long result = (long) value * ((Fixnum)obj).value;
441        return LispInteger.getInstance(result);
442      }
443    if (obj instanceof Bignum)
444      return number(getBigInteger().multiply(((Bignum)obj).value));
445    if (obj instanceof Ratio)
446      {
447        BigInteger numerator = ((Ratio)obj).numerator();
448        BigInteger denominator = ((Ratio)obj).denominator();
449        return number(
450          getBigInteger().multiply(numerator),
451          denominator);
452      }
453    if (obj instanceof SingleFloat)
454      return new SingleFloat(value * ((SingleFloat)obj).value);
455    if (obj instanceof DoubleFloat)
456      return new DoubleFloat(value * ((DoubleFloat)obj).value);
457    if (obj instanceof Complex)
458      {
459        Complex c = (Complex) obj;
460        return Complex.getInstance(multiplyBy(c.getRealPart()),
461                                   multiplyBy(c.getImaginaryPart()));
462      }
463    return type_error(obj, Symbol.NUMBER);
464  }
465
466  @Override
467  public LispObject divideBy(LispObject obj)
468  {
469    try
470      {
471        if (obj instanceof Fixnum)
472          {
473            final int divisor = ((Fixnum)obj).value;
474            // (/ MOST-NEGATIVE-FIXNUM -1) is a bignum.
475            if (value > Integer.MIN_VALUE)
476              if (value % divisor == 0)
477                return Fixnum.getInstance(value / divisor);
478            return number(BigInteger.valueOf(value),
479                          BigInteger.valueOf(divisor));
480          }
481        if (obj instanceof Bignum)
482          return number(getBigInteger(), ((Bignum)obj).value);
483        if (obj instanceof Ratio)
484          {
485            BigInteger numerator = ((Ratio)obj).numerator();
486            BigInteger denominator = ((Ratio)obj).denominator();
487            return number(getBigInteger().multiply(denominator),
488                          numerator);
489          }
490        if (obj instanceof SingleFloat)
491          return new SingleFloat(value / ((SingleFloat)obj).value);
492        if (obj instanceof DoubleFloat)
493          return new DoubleFloat(value / ((DoubleFloat)obj).value);
494        if (obj instanceof Complex)
495          {
496            Complex c = (Complex) obj;
497            LispObject realPart = c.getRealPart();
498            LispObject imagPart = c.getImaginaryPart();
499            LispObject denominator =
500              realPart.multiplyBy(realPart).add(imagPart.multiplyBy(imagPart));
501            return Complex.getInstance(multiplyBy(realPart).divideBy(denominator),
502                                       Fixnum.ZERO.subtract(multiplyBy(imagPart).divideBy(denominator)));
503          }
504        return type_error(obj, Symbol.NUMBER);
505      }
506    catch (ArithmeticException e)
507      {
508        if (obj.zerop())
509          return error(new DivisionByZero());
510        return error(new ArithmeticError(e.getMessage()));
511      }
512  }
513
514  @Override
515  public boolean isEqualTo(int n)
516  {
517    return value == n;
518  }
519
520  @Override
521  public boolean isEqualTo(LispObject obj)
522  {
523    if (obj instanceof Fixnum)
524      return value == ((Fixnum)obj).value;
525    if (obj instanceof SingleFloat)
526      return isEqualTo(((SingleFloat)obj).rational());
527    if (obj instanceof DoubleFloat)
528      return value == ((DoubleFloat)obj).value;
529    if (obj instanceof Complex)
530      return obj.isEqualTo(this);
531    if (obj.numberp())
532      return false;
533    type_error(obj, Symbol.NUMBER);
534    // Not reached.
535    return false;
536  }
537
538  @Override
539  public boolean isNotEqualTo(int n)
540  {
541    return value != n;
542  }
543
544  @Override
545  public boolean isNotEqualTo(LispObject obj)
546  {
547    if (obj instanceof Fixnum)
548      return value != ((Fixnum)obj).value;
549    // obj is not a fixnum.
550    if (obj instanceof SingleFloat)
551      return isNotEqualTo(((SingleFloat)obj).rational());
552    if (obj instanceof DoubleFloat)
553      return value != ((DoubleFloat)obj).value;
554    if (obj instanceof Complex)
555      return obj.isNotEqualTo(this);
556    if (obj.numberp())
557      return true;
558    type_error(obj, Symbol.NUMBER);
559    // Not reached.
560    return false;
561  }
562
563  @Override
564  public boolean isLessThan(int n)
565  {
566    return value < n;
567  }
568
569  @Override
570  public boolean isLessThan(LispObject obj)
571  {
572    if (obj instanceof Fixnum)
573      return value < ((Fixnum)obj).value;
574    if (obj instanceof Bignum)
575      return getBigInteger().compareTo(Bignum.getValue(obj)) < 0;
576    if (obj instanceof Ratio)
577      {
578        BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator());
579        return n.compareTo(((Ratio)obj).numerator()) < 0;
580      }
581    if (obj instanceof SingleFloat)
582      return isLessThan(((SingleFloat)obj).rational());
583    if (obj instanceof DoubleFloat)
584      return isLessThan(((DoubleFloat)obj).rational());
585    type_error(obj, Symbol.REAL);
586    // Not reached.
587    return false;
588  }
589
590  @Override
591  public boolean isGreaterThan(int n)
592  {
593    return value > n;
594  }
595
596  @Override
597  public boolean isGreaterThan(LispObject obj)
598  {
599    if (obj instanceof Fixnum)
600      return value > ((Fixnum)obj).value;
601    if (obj instanceof Bignum)
602      return getBigInteger().compareTo(Bignum.getValue(obj)) > 0;
603    if (obj instanceof Ratio)
604      {
605        BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator());
606        return n.compareTo(((Ratio)obj).numerator()) > 0;
607      }
608    if (obj instanceof SingleFloat)
609      return isGreaterThan(((SingleFloat)obj).rational());
610    if (obj instanceof DoubleFloat)
611      return isGreaterThan(((DoubleFloat)obj).rational());
612    type_error(obj, Symbol.REAL);
613    // Not reached.
614    return false;
615  }
616
617  @Override
618  public boolean isLessThanOrEqualTo(int n)
619  {
620    return value <= n;
621  }
622
623  @Override
624  public boolean isLessThanOrEqualTo(LispObject obj)
625  {
626    if (obj instanceof Fixnum)
627      return value <= ((Fixnum)obj).value;
628    if (obj instanceof Bignum)
629      return getBigInteger().compareTo(Bignum.getValue(obj)) <= 0;
630    if (obj instanceof Ratio)
631      {
632        BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator());
633        return n.compareTo(((Ratio)obj).numerator()) <= 0;
634      }
635    if (obj instanceof SingleFloat)
636      return isLessThanOrEqualTo(((SingleFloat)obj).rational());
637    if (obj instanceof DoubleFloat)
638      return isLessThanOrEqualTo(((DoubleFloat)obj).rational());
639    type_error(obj, Symbol.REAL);
640    // Not reached.
641    return false;
642  }
643
644  @Override
645  public boolean isGreaterThanOrEqualTo(int n)
646  {
647    return value >= n;
648  }
649
650  @Override
651  public boolean isGreaterThanOrEqualTo(LispObject obj)
652  {
653    if (obj instanceof Fixnum)
654      return value >= ((Fixnum)obj).value;
655    if (obj instanceof Bignum)
656      return getBigInteger().compareTo(Bignum.getValue(obj)) >= 0;
657    if (obj instanceof Ratio)
658      {
659        BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator());
660        return n.compareTo(((Ratio)obj).numerator()) >= 0;
661      }
662    if (obj instanceof SingleFloat)
663      return isGreaterThanOrEqualTo(((SingleFloat)obj).rational());
664    if (obj instanceof DoubleFloat)
665      return isGreaterThanOrEqualTo(((DoubleFloat)obj).rational());
666    type_error(obj, Symbol.REAL);
667    // Not reached.
668    return false;
669  }
670
671  @Override
672  public LispObject truncate(LispObject obj)
673  {
674    final LispThread thread = LispThread.currentThread();
675    final LispObject value1, value2;
676    try
677      {
678        if (obj instanceof Fixnum)
679          {
680            int divisor = ((Fixnum)obj).value;
681            int quotient = value / divisor;
682            int remainder = value % divisor;
683            value1 = Fixnum.getInstance(quotient);
684            value2 = remainder == 0 ? Fixnum.ZERO : Fixnum.getInstance(remainder);
685          }
686        else if (obj instanceof Bignum)
687          {
688            BigInteger val = getBigInteger();
689            BigInteger divisor = ((Bignum)obj).value;
690            BigInteger[] results = val.divideAndRemainder(divisor);
691            BigInteger quotient = results[0];
692            BigInteger remainder = results[1];
693            value1 = number(quotient);
694            value2 = (remainder.signum() == 0) ? Fixnum.ZERO : number(remainder);
695          }
696        else if (obj instanceof Ratio)
697          {
698            Ratio divisor = (Ratio) obj;
699            LispObject quotient =
700              multiplyBy(divisor.DENOMINATOR()).truncate(divisor.NUMERATOR());
701            LispObject remainder =
702              subtract(quotient.multiplyBy(divisor));
703            value1 = quotient;
704            value2 = remainder;
705          }
706        else if (obj instanceof SingleFloat)
707          {
708            // "When rationals and floats are combined by a numerical function,
709            // the rational is first converted to a float of the same format."
710            // 12.1.4.1
711            return new SingleFloat(value).truncate(obj);
712          }
713        else if (obj instanceof DoubleFloat)
714          {
715            // "When rationals and floats are combined by a numerical function,
716            // the rational is first converted to a float of the same format."
717            // 12.1.4.1
718            return new DoubleFloat(value).truncate(obj);
719          }
720        else
721          return type_error(obj, Symbol.REAL);
722      }
723    catch (ArithmeticException e)
724      {
725        if (obj.zerop())
726          return error(new DivisionByZero());
727        else
728          return error(new ArithmeticError(e.getMessage()));
729      }
730    return thread.setValues(value1, value2);
731  }
732
733  @Override
734  public LispObject MOD(LispObject divisor)
735  {
736    if (divisor instanceof Fixnum)
737      return MOD(((Fixnum)divisor).value);
738    return super.MOD(divisor);
739  }
740
741  @Override
742  public LispObject MOD(int divisor)
743  {
744    final int r;
745    try
746      {
747        r = value % divisor;
748      }
749    catch (ArithmeticException e)
750      {
751        return error(new ArithmeticError("Division by zero."));
752      }
753    if (r == 0)
754      return Fixnum.ZERO;
755    if (divisor < 0)
756      {
757        if (value > 0)
758          return Fixnum.getInstance(r + divisor);
759      }
760    else
761      {
762        if (value < 0)
763          return Fixnum.getInstance(r + divisor);
764      }
765    return Fixnum.getInstance(r);
766  }
767
768  @Override
769  public LispObject ash(int shift)
770  {
771    if (value == 0)
772      return this;
773    if (shift == 0)
774      return this;
775    long n = value;
776    if (shift <= -32)
777      {
778        // Right shift.
779        return n >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE;
780      }
781    if (shift < 0)
782      return Fixnum.getInstance((int)(n >> -shift));
783    if (shift <= 32)
784      {
785        n = n << shift;
786        return LispInteger.getInstance(n);
787      }
788    // BigInteger.shiftLeft() succumbs to a stack overflow if shift
789    // is Integer.MIN_VALUE, so...
790    if (shift == Integer.MIN_VALUE)
791      return n >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE;
792    return number(BigInteger.valueOf(value).shiftLeft(shift));
793  }
794
795  @Override
796  public LispObject ash(LispObject obj)
797  {
798    if (obj instanceof Fixnum)
799      return ash(((Fixnum)obj).value);
800    if (obj instanceof Bignum)
801      {
802        if (value == 0)
803          return this;
804        BigInteger n = BigInteger.valueOf(value);
805        BigInteger shift = ((Bignum)obj).value;
806        if (shift.signum() > 0)
807          return error(new LispError("Can't represent result of left shift."));
808        if (shift.signum() < 0)
809          return n.signum() >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE;
810        Debug.bug(); // Shouldn't happen.
811      }
812    return type_error(obj, Symbol.INTEGER);
813  }
814
815  @Override
816  public LispObject LOGNOT()
817  {
818    return Fixnum.getInstance(~value);
819  }
820
821  @Override
822  public LispObject LOGAND(int n)
823  {
824    return Fixnum.getInstance(value & n);
825  }
826
827  @Override
828  public LispObject LOGAND(LispObject obj)
829  {
830    if (obj instanceof Fixnum)
831      return Fixnum.getInstance(value & ((Fixnum)obj).value);
832    if (obj instanceof Bignum)
833      {
834        if (value >= 0)
835          {
836            int n2 = (((Bignum)obj).value).intValue();
837            return Fixnum.getInstance(value & n2);
838          }
839        else
840          {
841            BigInteger n1 = getBigInteger();
842            BigInteger n2 = ((Bignum)obj).value;
843            return number(n1.and(n2));
844          }
845      }
846    return type_error(obj, Symbol.INTEGER);
847  }
848
849  @Override
850  public LispObject LOGIOR(int n)
851  {
852    return Fixnum.getInstance(value | n);
853  }
854
855  @Override
856  public LispObject LOGIOR(LispObject obj)
857  {
858    if (obj instanceof Fixnum)
859      return Fixnum.getInstance(value | ((Fixnum)obj).value);
860    if (obj instanceof Bignum)
861      {
862        BigInteger n1 = getBigInteger();
863        BigInteger n2 = ((Bignum)obj).value;
864        return number(n1.or(n2));
865      }
866    return type_error(obj, Symbol.INTEGER);
867  }
868
869  @Override
870  public LispObject LOGXOR(int n)
871  {
872    return Fixnum.getInstance(value ^ n);
873  }
874
875  @Override
876  public LispObject LOGXOR(LispObject obj)
877  {
878    if (obj instanceof Fixnum)
879      return Fixnum.getInstance(value ^ ((Fixnum)obj).value);
880    if (obj instanceof Bignum)
881      {
882        BigInteger n1 = getBigInteger();
883        BigInteger n2 = ((Bignum)obj).value;
884        return number(n1.xor(n2));
885      }
886    return type_error(obj, Symbol.INTEGER);
887  }
888
889  @Override
890  public LispObject LDB(int size, int position)
891  {
892    long n = (long) value >> position;
893    long mask = (1L << size) - 1;
894    return number(n & mask);
895  }
896
897  final static BigInteger BIGINTEGER_TWO = new BigInteger ("2");
898
899  /** Computes fixnum^bignum, returning a fixnum or a bignum.
900    */
901  public LispObject pow(LispObject obj)
902  {
903    BigInteger y = Bignum.getValue(obj);
904
905    if (y.compareTo (BigInteger.ZERO) < 0)
906      return (Fixnum.getInstance(1)).divideBy(this.pow(Bignum.getInstance(y.negate())));
907
908    if (y.compareTo(BigInteger.ZERO) == 0)
909      // No need to test base here; CLHS says 0^0 == 1.
910      return Fixnum.getInstance(1);
911     
912    int x = this.value;
913
914    if (x == 0)
915      return Fixnum.getInstance(0);
916
917    if (x == 1)
918      return Fixnum.getInstance(1);
919
920    BigInteger xy = BigInteger.ONE;
921    BigInteger term = BigInteger.valueOf((long) x);
922
923    while (! y.equals(BigInteger.ZERO))
924    {
925      if (y.testBit(0))
926        xy = xy.multiply(term);
927
928      term = term.multiply(term);
929      y = y.shiftLeft(1);
930    }
931
932    return Bignum.getInstance(xy);
933  }
934
935  @Override
936  public int hashCode()
937  {
938    return value;
939  }
940
941  @Override
942  public String writeToString()
943  {
944    final LispThread thread = LispThread.currentThread();
945    int base = Fixnum.getValue(Symbol.PRINT_BASE.symbolValue(thread));
946    String s = Integer.toString(value, base).toUpperCase();
947    if (Symbol.PRINT_RADIX.symbolValue(thread) != NIL)
948      {
949        StringBuilder sb = new StringBuilder();
950        switch (base)
951          {
952          case 2:
953            sb.append("#b");
954            sb.append(s);
955            break;
956          case 8:
957            sb.append("#o");
958            sb.append(s);
959            break;
960          case 10:
961            sb.append(s);
962            sb.append('.');
963            break;
964          case 16:
965            sb.append("#x");
966            sb.append(s);
967            break;
968          default:
969            sb.append('#');
970            sb.append(String.valueOf(base));
971            sb.append('r');
972            sb.append(s);
973            break;
974          }
975        s = sb.toString();
976      }
977    return s;
978  }
979}
Note: See TracBrowser for help on using the repository browser.