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

Last change on this file was 11754, checked in by vvoutilainen, 16 years ago

Convert using ClassCastException? to checking instanceof.
Performance tests show this approach to be faster.
Patch by Douglas R. Miles. I modified the patch to
remove tabs, so indentation may be slightly off in places.
That's something that we need to handle separately, abcl
doesn't have a clear indentation policy.

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