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

Last change on this file was 13440, checked in by ehuelsmann, 13 years ago

Rename writeToString() to printObject() since that's what it's being used for.
Additionally, create princToString() for use in error messages, making the

required replacement where appropriate.

  • 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 13440 2011-08-05 21:25:10Z 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 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 printObject()
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.