source: trunk/abcl/src/org/armedbear/lisp/Fixnum.java

Last change on this file was 15548, checked in by Mark Evenson, 2 years ago

Proposal to fix Github issue #177

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