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

Last change on this file was 14757, checked in by Mark Evenson, 10 years ago

Futher fix for EQUALP on numeric tower

This fixes the following case

(let ((h1 (make-hash-table :test 'equalp))

(h2 (make-hash-table :test 'equalp))
(h (make-hash-table :test 'equalp)))

(setf (gethash 1 h1) 2

(gethash 2 h2) 1
(gethash h1 h) h2
(gethash h2 h) h1)

h)

See <https://mailman.common-lisp.net/pipermail/armedbear-devel/2015-April/003452.html>.
See <http://abcl.org/trac/ticket/388>.

Thanks to Massimiliano Ghilardi.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 24.9 KB
Line 
1/*
2 * Fixnum.java
3 *
4 * Copyright (C) 2002-2006 Peter Graves
5 * $Id: Fixnum.java 14757 2015-04-11 07:44:42Z 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 != null && obj.numberp())
232      return isEqualTo(obj);
233    return false;
234  }
235
236  @Override
237  public LispObject ABS()
238  {
239    if (value >= 0)
240      return this;
241    return LispInteger.getInstance(-(long)value);
242  }
243
244  @Override
245  public LispObject NUMERATOR()
246  {
247    return this;
248  }
249
250  @Override
251  public LispObject DENOMINATOR()
252  {
253    return ONE;
254  }
255
256  @Override
257  public boolean evenp()
258  {
259    return (value & 0x01) == 0;
260  }
261
262  @Override
263  public boolean oddp()
264  {
265    return (value & 0x01) != 0;
266  }
267
268  @Override
269  public boolean plusp()
270  {
271    return value > 0;
272  }
273
274  @Override
275  public boolean minusp()
276  {
277    return value < 0;
278  }
279
280  @Override
281  public boolean zerop()
282  {
283    return value == 0;
284  }
285
286  public static int getValue(LispObject obj)
287  {
288          if (obj instanceof Fixnum) return ((Fixnum)obj).value;
289          type_error(obj, Symbol.FIXNUM);
290      // Not reached.
291          return 0;
292  }
293
294  @Override
295  public float floatValue() {
296    return (float)value;
297  }
298
299  @Override
300  public double doubleValue() {
301    return (double)value;
302  }
303
304  public static int getInt(LispObject obj)
305  {
306          if (obj instanceof Fixnum) return ((Fixnum)obj).value;
307          type_error(obj, Symbol.FIXNUM);
308      // Not reached.
309          return 0;
310  }
311
312  public static BigInteger getBigInteger(LispObject obj)
313  {
314          if (obj instanceof Fixnum) return BigInteger.valueOf(((Fixnum)obj).value);
315          type_error(obj, Symbol.FIXNUM);
316      // Not reached.
317          return null;
318  }
319
320  @Override
321  public int intValue()
322  {
323    return value;
324  }
325
326  @Override
327  public long longValue()
328  {
329    return (long) value;
330  }
331
332  public final BigInteger getBigInteger()
333  {
334    return BigInteger.valueOf(value);
335  }
336
337  @Override
338  public final LispObject incr()
339  {
340    return LispInteger.getInstance(1 + (long)value);
341  }
342
343  @Override
344  public final LispObject decr()
345  {
346    return LispInteger.getInstance(-1 + (long)value);
347  }
348
349  @Override
350  public LispObject negate()
351  {
352    return LispInteger.getInstance((-(long)value));
353  }
354
355  @Override
356  public LispObject add(int n)
357  {
358    return LispInteger.getInstance((long) value + n);
359  }
360
361  @Override
362  public LispObject add(LispObject obj)
363  {
364    if (obj instanceof Fixnum)
365      {
366        long result = (long) value + ((Fixnum)obj).value;
367        return LispInteger.getInstance(result);
368      }
369    if (obj instanceof Bignum)
370      return number(getBigInteger().add(((Bignum)obj).value));
371    if (obj instanceof Ratio)
372      {
373        BigInteger numerator = ((Ratio)obj).numerator();
374        BigInteger denominator = ((Ratio)obj).denominator();
375        return number(getBigInteger().multiply(denominator).add(numerator),
376                      denominator);
377      }
378    if (obj instanceof SingleFloat)
379      return new SingleFloat(value + ((SingleFloat)obj).value);
380    if (obj instanceof DoubleFloat)
381      return new DoubleFloat(value + ((DoubleFloat)obj).value);
382    if (obj instanceof Complex)
383      {
384        Complex c = (Complex) obj;
385        return Complex.getInstance(add(c.getRealPart()), c.getImaginaryPart());
386      }
387    return type_error(obj, Symbol.NUMBER);
388  }
389
390  @Override
391  public LispObject subtract(int n)
392  {
393    return LispInteger.getInstance((long)value - n);
394  }
395
396  @Override
397  public LispObject subtract(LispObject obj)
398  {
399    if (obj instanceof Fixnum)
400      return number((long) value - ((Fixnum)obj).value);
401    if (obj instanceof Bignum)
402      return number(getBigInteger().subtract(Bignum.getValue(obj)));
403    if (obj instanceof Ratio)
404      {
405        BigInteger numerator = ((Ratio)obj).numerator();
406        BigInteger denominator = ((Ratio)obj).denominator();
407        return number(
408          getBigInteger().multiply(denominator).subtract(numerator),
409          denominator);
410      }
411    if (obj instanceof SingleFloat)
412      return new SingleFloat(value - ((SingleFloat)obj).value);
413    if (obj instanceof DoubleFloat)
414      return new DoubleFloat(value - ((DoubleFloat)obj).value);
415    if (obj instanceof Complex)
416      {
417        Complex c = (Complex) obj;
418        return Complex.getInstance(subtract(c.getRealPart()),
419                                   ZERO.subtract(c.getImaginaryPart()));
420      }
421    return type_error(obj, Symbol.NUMBER);
422  }
423
424  @Override
425  public LispObject multiplyBy(int n)
426  {
427    long result = (long) value * n;
428    return LispInteger.getInstance(result);
429  }
430
431  @Override
432  public LispObject multiplyBy(LispObject obj)
433  {
434    if (obj instanceof Fixnum)
435      {
436        long result = (long) value * ((Fixnum)obj).value;
437        return LispInteger.getInstance(result);
438      }
439    if (obj instanceof Bignum)
440      return number(getBigInteger().multiply(((Bignum)obj).value));
441    if (obj instanceof Ratio)
442      {
443        BigInteger numerator = ((Ratio)obj).numerator();
444        BigInteger denominator = ((Ratio)obj).denominator();
445        return number(
446          getBigInteger().multiply(numerator),
447          denominator);
448      }
449    if (obj instanceof SingleFloat)
450      return new SingleFloat(value * ((SingleFloat)obj).value);
451    if (obj instanceof DoubleFloat)
452      return new DoubleFloat(value * ((DoubleFloat)obj).value);
453    if (obj instanceof Complex)
454      {
455        Complex c = (Complex) obj;
456        return Complex.getInstance(multiplyBy(c.getRealPart()),
457                                   multiplyBy(c.getImaginaryPart()));
458      }
459    return type_error(obj, Symbol.NUMBER);
460  }
461
462  @Override
463  public LispObject divideBy(LispObject obj)
464  {
465    try
466      {
467        if (obj instanceof Fixnum)
468          {
469            final int divisor = ((Fixnum)obj).value;
470            // (/ MOST-NEGATIVE-FIXNUM -1) is a bignum.
471            if (value > Integer.MIN_VALUE)
472              if (value % divisor == 0)
473                return Fixnum.getInstance(value / divisor);
474            return number(BigInteger.valueOf(value),
475                          BigInteger.valueOf(divisor));
476          }
477        if (obj instanceof Bignum)
478          return number(getBigInteger(), ((Bignum)obj).value);
479        if (obj instanceof Ratio)
480          {
481            BigInteger numerator = ((Ratio)obj).numerator();
482            BigInteger denominator = ((Ratio)obj).denominator();
483            return number(getBigInteger().multiply(denominator),
484                          numerator);
485          }
486        if (obj instanceof SingleFloat)
487          return new SingleFloat(value / ((SingleFloat)obj).value);
488        if (obj instanceof DoubleFloat)
489          return new DoubleFloat(value / ((DoubleFloat)obj).value);
490        if (obj instanceof Complex)
491          {
492            Complex c = (Complex) obj;
493            LispObject realPart = c.getRealPart();
494            LispObject imagPart = c.getImaginaryPart();
495            LispObject denominator =
496              realPart.multiplyBy(realPart).add(imagPart.multiplyBy(imagPart));
497            return Complex.getInstance(multiplyBy(realPart).divideBy(denominator),
498                                       Fixnum.ZERO.subtract(multiplyBy(imagPart).divideBy(denominator)));
499          }
500        return type_error(obj, Symbol.NUMBER);
501      }
502    catch (ArithmeticException e)
503      {
504        if (obj.zerop())
505          return error(new DivisionByZero());
506        return error(new ArithmeticError(e.getMessage()));
507      }
508  }
509
510  @Override
511  public boolean isEqualTo(int n)
512  {
513    return value == n;
514  }
515
516  @Override
517  public boolean isEqualTo(LispObject obj)
518  {
519    if (obj instanceof Fixnum)
520      return value == ((Fixnum)obj).value;
521    if (obj instanceof SingleFloat)
522      return isEqualTo(((SingleFloat)obj).rational());
523    if (obj instanceof DoubleFloat)
524      return value == ((DoubleFloat)obj).value;
525    if (obj instanceof Complex)
526      return obj.isEqualTo(this);
527    if (obj.numberp())
528      return false;
529    type_error(obj, Symbol.NUMBER);
530    // Not reached.
531    return false;
532  }
533
534  @Override
535  public boolean isNotEqualTo(int n)
536  {
537    return value != n;
538  }
539
540  @Override
541  public boolean isNotEqualTo(LispObject obj)
542  {
543    if (obj instanceof Fixnum)
544      return value != ((Fixnum)obj).value;
545    // obj is not a fixnum.
546    if (obj instanceof SingleFloat)
547      return isNotEqualTo(((SingleFloat)obj).rational());
548    if (obj instanceof DoubleFloat)
549      return value != ((DoubleFloat)obj).value;
550    if (obj instanceof Complex)
551      return obj.isNotEqualTo(this);
552    if (obj.numberp())
553      return true;
554    type_error(obj, Symbol.NUMBER);
555    // Not reached.
556    return false;
557  }
558
559  @Override
560  public boolean isLessThan(int n)
561  {
562    return value < n;
563  }
564
565  @Override
566  public boolean isLessThan(LispObject obj)
567  {
568    if (obj instanceof Fixnum)
569      return value < ((Fixnum)obj).value;
570    if (obj instanceof Bignum)
571      return getBigInteger().compareTo(Bignum.getValue(obj)) < 0;
572    if (obj instanceof Ratio)
573      {
574        BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator());
575        return n.compareTo(((Ratio)obj).numerator()) < 0;
576      }
577    if (obj instanceof SingleFloat)
578      return isLessThan(((SingleFloat)obj).rational());
579    if (obj instanceof DoubleFloat)
580      return isLessThan(((DoubleFloat)obj).rational());
581    type_error(obj, Symbol.REAL);
582    // Not reached.
583    return false;
584  }
585
586  @Override
587  public boolean isGreaterThan(int n)
588  {
589    return value > n;
590  }
591
592  @Override
593  public boolean isGreaterThan(LispObject obj)
594  {
595    if (obj instanceof Fixnum)
596      return value > ((Fixnum)obj).value;
597    if (obj instanceof Bignum)
598      return getBigInteger().compareTo(Bignum.getValue(obj)) > 0;
599    if (obj instanceof Ratio)
600      {
601        BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator());
602        return n.compareTo(((Ratio)obj).numerator()) > 0;
603      }
604    if (obj instanceof SingleFloat)
605      return isGreaterThan(((SingleFloat)obj).rational());
606    if (obj instanceof DoubleFloat)
607      return isGreaterThan(((DoubleFloat)obj).rational());
608    type_error(obj, Symbol.REAL);
609    // Not reached.
610    return false;
611  }
612
613  @Override
614  public boolean isLessThanOrEqualTo(int n)
615  {
616    return value <= n;
617  }
618
619  @Override
620  public boolean isLessThanOrEqualTo(LispObject obj)
621  {
622    if (obj instanceof Fixnum)
623      return value <= ((Fixnum)obj).value;
624    if (obj instanceof Bignum)
625      return getBigInteger().compareTo(Bignum.getValue(obj)) <= 0;
626    if (obj instanceof Ratio)
627      {
628        BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator());
629        return n.compareTo(((Ratio)obj).numerator()) <= 0;
630      }
631    if (obj instanceof SingleFloat)
632      return isLessThanOrEqualTo(((SingleFloat)obj).rational());
633    if (obj instanceof DoubleFloat)
634      return isLessThanOrEqualTo(((DoubleFloat)obj).rational());
635    type_error(obj, Symbol.REAL);
636    // Not reached.
637    return false;
638  }
639
640  @Override
641  public boolean isGreaterThanOrEqualTo(int n)
642  {
643    return value >= n;
644  }
645
646  @Override
647  public boolean isGreaterThanOrEqualTo(LispObject obj)
648  {
649    if (obj instanceof Fixnum)
650      return value >= ((Fixnum)obj).value;
651    if (obj instanceof Bignum)
652      return getBigInteger().compareTo(Bignum.getValue(obj)) >= 0;
653    if (obj instanceof Ratio)
654      {
655        BigInteger n = getBigInteger().multiply(((Ratio)obj).denominator());
656        return n.compareTo(((Ratio)obj).numerator()) >= 0;
657      }
658    if (obj instanceof SingleFloat)
659      return isGreaterThanOrEqualTo(((SingleFloat)obj).rational());
660    if (obj instanceof DoubleFloat)
661      return isGreaterThanOrEqualTo(((DoubleFloat)obj).rational());
662    type_error(obj, Symbol.REAL);
663    // Not reached.
664    return false;
665  }
666
667  @Override
668  public LispObject truncate(LispObject obj)
669  {
670    final LispThread thread = LispThread.currentThread();
671    final LispObject value1, value2;
672    try
673      {
674        if (obj instanceof Fixnum)
675          {
676            int divisor = ((Fixnum)obj).value;
677            int quotient = value / divisor;
678            int remainder = value % divisor;
679            value1 = Fixnum.getInstance(quotient);
680            value2 = remainder == 0 ? Fixnum.ZERO : Fixnum.getInstance(remainder);
681          }
682        else if (obj instanceof Bignum)
683          {
684            BigInteger val = getBigInteger();
685            BigInteger divisor = ((Bignum)obj).value;
686            BigInteger[] results = val.divideAndRemainder(divisor);
687            BigInteger quotient = results[0];
688            BigInteger remainder = results[1];
689            value1 = number(quotient);
690            value2 = (remainder.signum() == 0) ? Fixnum.ZERO : number(remainder);
691          }
692        else if (obj instanceof Ratio)
693          {
694            Ratio divisor = (Ratio) obj;
695            LispObject quotient =
696              multiplyBy(divisor.DENOMINATOR()).truncate(divisor.NUMERATOR());
697            LispObject remainder =
698              subtract(quotient.multiplyBy(divisor));
699            value1 = quotient;
700            value2 = remainder;
701          }
702        else if (obj instanceof SingleFloat)
703          {
704            // "When rationals and floats are combined by a numerical function,
705            // the rational is first converted to a float of the same format."
706            // 12.1.4.1
707            return new SingleFloat(value).truncate(obj);
708          }
709        else if (obj instanceof DoubleFloat)
710          {
711            // "When rationals and floats are combined by a numerical function,
712            // the rational is first converted to a float of the same format."
713            // 12.1.4.1
714            return new DoubleFloat(value).truncate(obj);
715          }
716        else
717          return type_error(obj, Symbol.REAL);
718      }
719    catch (ArithmeticException e)
720      {
721        if (obj.zerop())
722          return error(new DivisionByZero());
723        else
724          return error(new ArithmeticError(e.getMessage()));
725      }
726    return thread.setValues(value1, value2);
727  }
728
729  @Override
730  public LispObject MOD(LispObject divisor)
731  {
732    if (divisor instanceof Fixnum)
733      return MOD(((Fixnum)divisor).value);
734    return super.MOD(divisor);
735  }
736
737  @Override
738  public LispObject MOD(int divisor)
739  {
740    final int r;
741    try
742      {
743        r = value % divisor;
744      }
745    catch (ArithmeticException e)
746      {
747        return error(new ArithmeticError("Division by zero."));
748      }
749    if (r == 0)
750      return Fixnum.ZERO;
751    if (divisor < 0)
752      {
753        if (value > 0)
754          return Fixnum.getInstance(r + divisor);
755      }
756    else
757      {
758        if (value < 0)
759          return Fixnum.getInstance(r + divisor);
760      }
761    return Fixnum.getInstance(r);
762  }
763
764  @Override
765  public LispObject ash(int shift)
766  {
767    if (value == 0)
768      return this;
769    if (shift == 0)
770      return this;
771    long n = value;
772    if (shift <= -32)
773      {
774        // Right shift.
775        return n >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE;
776      }
777    if (shift < 0)
778      return Fixnum.getInstance((int)(n >> -shift));
779    if (shift <= 32)
780      {
781        n = n << shift;
782        return LispInteger.getInstance(n);
783      }
784    // BigInteger.shiftLeft() succumbs to a stack overflow if shift
785    // is Integer.MIN_VALUE, so...
786    if (shift == Integer.MIN_VALUE)
787      return n >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE;
788    return number(BigInteger.valueOf(value).shiftLeft(shift));
789  }
790
791  @Override
792  public LispObject ash(LispObject obj)
793  {
794    if (obj instanceof Fixnum)
795      return ash(((Fixnum)obj).value);
796    if (obj instanceof Bignum)
797      {
798        if (value == 0)
799          return this;
800        BigInteger n = BigInteger.valueOf(value);
801        BigInteger shift = ((Bignum)obj).value;
802        if (shift.signum() > 0)
803          return error(new LispError("Can't represent result of left shift."));
804        if (shift.signum() < 0)
805          return n.signum() >= 0 ? Fixnum.ZERO : Fixnum.MINUS_ONE;
806        Debug.bug(); // Shouldn't happen.
807      }
808    return type_error(obj, Symbol.INTEGER);
809  }
810
811  @Override
812  public LispObject LOGNOT()
813  {
814    return Fixnum.getInstance(~value);
815  }
816
817  @Override
818  public LispObject LOGAND(int n)
819  {
820    return Fixnum.getInstance(value & n);
821  }
822
823  @Override
824  public LispObject LOGAND(LispObject obj)
825  {
826    if (obj instanceof Fixnum)
827      return Fixnum.getInstance(value & ((Fixnum)obj).value);
828    if (obj instanceof Bignum)
829      {
830        if (value >= 0)
831          {
832            int n2 = (((Bignum)obj).value).intValue();
833            return Fixnum.getInstance(value & n2);
834          }
835        else
836          {
837            BigInteger n1 = getBigInteger();
838            BigInteger n2 = ((Bignum)obj).value;
839            return number(n1.and(n2));
840          }
841      }
842    return type_error(obj, Symbol.INTEGER);
843  }
844
845  @Override
846  public LispObject LOGIOR(int n)
847  {
848    return Fixnum.getInstance(value | n);
849  }
850
851  @Override
852  public LispObject LOGIOR(LispObject obj)
853  {
854    if (obj instanceof Fixnum)
855      return Fixnum.getInstance(value | ((Fixnum)obj).value);
856    if (obj instanceof Bignum)
857      {
858        BigInteger n1 = getBigInteger();
859        BigInteger n2 = ((Bignum)obj).value;
860        return number(n1.or(n2));
861      }
862    return type_error(obj, Symbol.INTEGER);
863  }
864
865  @Override
866  public LispObject LOGXOR(int n)
867  {
868    return Fixnum.getInstance(value ^ n);
869  }
870
871  @Override
872  public LispObject LOGXOR(LispObject obj)
873  {
874    if (obj instanceof Fixnum)
875      return Fixnum.getInstance(value ^ ((Fixnum)obj).value);
876    if (obj instanceof Bignum)
877      {
878        BigInteger n1 = getBigInteger();
879        BigInteger n2 = ((Bignum)obj).value;
880        return number(n1.xor(n2));
881      }
882    return type_error(obj, Symbol.INTEGER);
883  }
884
885  @Override
886  public LispObject LDB(int size, int position)
887  {
888    long n = (long) value >> position;
889    long mask = (1L << size) - 1;
890    return number(n & mask);
891  }
892
893  final static BigInteger BIGINTEGER_TWO = new BigInteger ("2");
894
895  /** Computes fixnum^bignum, returning a fixnum or a bignum.
896    */
897  public LispObject pow(LispObject obj)
898  {
899    BigInteger y = Bignum.getValue(obj);
900
901    if (y.compareTo (BigInteger.ZERO) < 0)
902      return (Fixnum.getInstance(1)).divideBy(this.pow(Bignum.getInstance(y.negate())));
903
904    if (y.compareTo(BigInteger.ZERO) == 0)
905      // No need to test base here; CLHS says 0^0 == 1.
906      return Fixnum.getInstance(1);
907     
908    int x = this.value;
909
910    if (x == 0)
911      return Fixnum.getInstance(0);
912
913    if (x == 1)
914      return Fixnum.getInstance(1);
915
916    BigInteger xy = BigInteger.ONE;
917    BigInteger term = BigInteger.valueOf((long) x);
918
919    while (! y.equals(BigInteger.ZERO))
920    {
921      if (y.testBit(0))
922        xy = xy.multiply(term);
923
924      term = term.multiply(term);
925      y = y.shiftLeft(1);
926    }
927
928    return Bignum.getInstance(xy);
929  }
930
931  @Override
932  public int hashCode()
933  {
934    return value;
935  }
936
937  @Override
938  public String printObject()
939  {
940    final LispThread thread = LispThread.currentThread();
941    int base = Fixnum.getValue(Symbol.PRINT_BASE.symbolValue(thread));
942    String s = Integer.toString(value, base).toUpperCase();
943    if (Symbol.PRINT_RADIX.symbolValue(thread) != NIL)
944      {
945        StringBuilder sb = new StringBuilder();
946        switch (base)
947          {
948          case 2:
949            sb.append("#b");
950            sb.append(s);
951            break;
952          case 8:
953            sb.append("#o");
954            sb.append(s);
955            break;
956          case 10:
957            sb.append(s);
958            sb.append('.');
959            break;
960          case 16:
961            sb.append("#x");
962            sb.append(s);
963            break;
964          default:
965            sb.append('#');
966            sb.append(String.valueOf(base));
967            sb.append('r');
968            sb.append(s);
969            break;
970          }
971        s = sb.toString();
972      }
973    return s;
974  }
975}
Note: See TracBrowser for help on using the repository browser.