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

Last change on this file was 12254, checked in by ehuelsmann, 16 years ago

Remove 'throws ConditionThrowable?' method annotations:

it's an unchecked exception now, so no need to declare it thrown.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 25.2 KB
Line 
1/*
2 * Fixnum.java
3 *
4 * Copyright (C) 2002-2006 Peter Graves
5 * $Id: Fixnum.java 12254 2009-11-06 20:07:54Z ehuelsmann $
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)
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()
272  {
273    return (value & 0x01) == 0;
274  }
275
276  @Override
277  public boolean oddp()
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
602  {
603    return value > n;
604  }
605
606  @Override
607  public boolean isGreaterThan(LispObject obj)
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)
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)
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)
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)
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)
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)
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)
833  {
834    return Fixnum.getInstance(value & n);
835  }
836
837  @Override
838  public LispObject LOGAND(LispObject obj)
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)
861  {
862    return Fixnum.getInstance(value | n);
863  }
864
865  @Override
866  public LispObject LOGIOR(LispObject obj)
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)
881  {
882    return Fixnum.getInstance(value ^ n);
883  }
884
885  @Override
886  public LispObject LOGXOR(LispObject obj)
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)
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()
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.