Artifact 77513f128d0038fe6a03cffcbd4fd5152ebe7bece8f9ef2ad848f88c03c4bb84:
- Executable file
r37/lisp/csl/jlisp/LispSmallInteger.java
— part of check-in
[f2fda60abd]
at
2011-09-02 18:13:33
on branch master
— Some historical releases purely for archival purposes
git-svn-id: https://svn.code.sf.net/p/reduce-algebra/code/trunk/historical@1375 2bfe0521-f11c-4a00-b80e-6202646ff360 (user: arthurcnorman@users.sourceforge.net, size: 19812) [annotate] [blame] [check-ins using] [more...]
// // This file is part of the Jlisp implementation of Standard Lisp // Copyright \u00a9 (C) Codemist Ltd, 1998-2000. // import java.math.*; import java.io.*; import java.util.*; public class LispSmallInteger extends LispInteger { public int value; // I will keep integers of up to 31 bits as "Small" integers. This means that // the criterion I will use to notice them will be that as ints they will // have their top two bits equal. For values in some (much) smaller range // I will have a pre-allocated table of values and will return one of // those when needed - thereby avoiding some heap allocation at the expense // of extra calculation and testing. static final int MIN = -100; static final int MAX = 1000; static LispSmallInteger [] preAllocated = new LispSmallInteger[MAX-MIN+1]; static void preAllocate() { for (int i=MIN; i<=MAX; i++) preAllocated[i-MIN] = new LispSmallInteger(i); } LispSmallInteger(int n) { value = n; } int intValue() { return value; } BigInteger bigIntValue() { return BigInteger.valueOf((long)value); } LispObject eval() { return this; } String printAs() { if ((currentFlags & (printBinary | printOctal | printHex)) == 0) return Integer.toString(value); else if ((currentFlags & printBinary) != 0) return Integer.toBinaryString(value); else if ((currentFlags & printOctal) != 0) return Integer.toOctalString(value); else // if ((currentFlags & printHex) != 0) return Integer.toHexString(value); } void iprint() { String s = printAs(); if ((currentFlags & noLineBreak) == 0 && currentOutput.column + s.length() > currentOutput.lineLength) currentOutput.println(); currentOutput.print(s); } void blankprint() { String s = printAs(); if ((currentFlags & noLineBreak) == 0 && currentOutput.column + s.length() >= currentOutput.lineLength) currentOutput.println(); else currentOutput.print(" "); currentOutput.print(s); } double doubleValue() { return (double)value; } public boolean lispequals(Object b) { if (!(b instanceof LispSmallInteger)) return false; return value == ((LispSmallInteger)b).value; } public boolean equals(Object b) { if (!(b instanceof LispSmallInteger)) return false; return value == ((LispSmallInteger)b).value; } public int lisphashCode() { return value*696969; } public int hashCode() { return value*696969; } void scan() { Object w = new Integer(value); if (Jlisp.objects.contains(w)) // seen before? { if (!Jlisp.repeatedObjects.containsKey(w)) { Jlisp.repeatedObjects.put( w, Jlisp.nil); // value is junk at this stage } } else Jlisp.objects.add(w); } void dump() throws IOException { Object d = new Integer(value); Object w = Jlisp.repeatedObjects.get(d); if (w != null && w instanceof Integer) putSharedRef(w); // processed before else { if (w != null) // will be used again sometime { Jlisp.repeatedObjects.put( d, new Integer(Jlisp.sharedIndex++)); Jlisp.odump.write(X_STORE); } // Note whacky coding with sign bit in bottom bit position. The intent // of this is that numbers that ar esmall in absolute value will be // packed into rather few bytes. putPrefix(value == 0x80000000 ? 1 : value < 0 ? 1 + ((-value)<<1) : value<<1, X_FIXNUM); } } public LispObject negate() throws Exception { if (value == 0xc0000000) return new LispBigInteger(-value); return valueOf(-value); } public LispObject abs() throws Exception { if (value >= 0) return this; else if (value == 0xc0000000) return new LispBigInteger(-value); else return valueOf(-value); } public LispObject add1() throws Exception { if (value == 0x3fffffff) return new LispBigInteger(0x40000000); else return valueOf(value+1); } public LispObject sub1() throws Exception { if (value == 0xc0000000) return new LispBigInteger(0xbfffffff); return valueOf(value-1); } public LispObject msd() throws Exception { int r = 0, w = value; if (w < 0) w = -(w + 1); while ((w & ~0x3f) != 0) { w = w >>> 6; r += 6; } while (w != 0) { w = w >>> 1; r += 1; } return valueOf(r); } public LispObject lsd() throws Exception { int r = 0, w = value; if (w == 0) return valueOf(-1); while ((w & 0x3f) == 0) { w = w >> 6; r += 6; } while ((w & 0x1) == 0) { w = w >> 1; r += 1; } return valueOf(r); } LispObject not() throws Exception { return valueOf(~value); } LispObject modMinus() throws Exception { if (value == 0) return this; else return valueOf(Jlisp.modulus - value); } LispObject modRecip() throws Exception { if (value == 0) return Jlisp.error("attempt to take modular recip of zero"); int a = Jlisp.modulus, b = value, s = 0, t = 1; while (b != 0) { int q = a/b; int w = a - q*b; a = b; b = w; w = s - q*t; s = t; t = w; } if (s < 0) s += Jlisp.modulus; return valueOf(s); } LispObject reduceMod() throws Exception { int r = value % Jlisp.modulus; if (r < 0) r += Jlisp.modulus; return valueOf(r); } public LispObject floor() throws Exception { return this; } public LispObject ceiling() throws Exception { return this; } public LispObject round() throws Exception { return this; } LispObject truncate() throws Exception { return this; } public LispObject ash(int n) throws Exception { if (n > 0) return valueOf(BigInteger.valueOf((long)value).shiftLeft(n)); else if (n < -31) { if (value < 0) return valueOf(-1); else return valueOf(0); } else if (n < 0) return valueOf(value >> (-n)); else return this; } public LispObject ash1(int n) throws Exception { if (n > 0) return valueOf(BigInteger.valueOf((long)value).shiftLeft(n)); else if (n < -31) return valueOf(0); else if (n < 0) { if (value >= 0) return valueOf(value >> (-n)); else return valueOf(-((-value) >> (-n))); } else return this; } public LispObject rightshift(int n) throws Exception { return valueOf(value >> n); } public LispObject evenp() throws Exception { return ((value & 1) != 0) ? Jlisp.nil : Jlisp.lispTrue; } public LispObject oddp() throws Exception { return ((value & 1) != 0) ? Jlisp.lispTrue : Jlisp.nil; } public LispObject fix() throws Exception { return this; } public LispObject fixp() throws Exception { return Jlisp.lispTrue; } public LispObject integerp() throws Exception { return Jlisp.lispTrue; } public LispObject jfloat() throws Exception { return new LispFloat((double)value); } public LispObject floatp() throws Exception { return Jlisp.nil; } public LispObject minusp() throws Exception { return value < 0 ? Jlisp.lispTrue : Jlisp.nil; } public LispObject plusp() throws Exception { return value >= 0 ? Jlisp.lispTrue : Jlisp.nil; } public LispObject zerop() throws Exception { return value == 0 ? Jlisp.lispTrue : Jlisp.nil; } public LispObject onep() throws Exception { return value == 1 ? Jlisp.lispTrue : Jlisp.nil; } public LispObject add(LispObject a) throws Exception { return a.addSmallInteger(this); } public LispObject subtract(LispObject a) throws Exception { return a.subtractSmallInteger(this); } public LispObject multiply(LispObject a) throws Exception { return a.multiplySmallInteger(this); } public LispObject expt(LispObject a) throws Exception { return a.exptSmallInteger(this); } public LispObject divide(LispObject a) throws Exception { return a.divideSmallInteger(this); } public LispObject remainder(LispObject a) throws Exception { return a.remainderSmallInteger(this); } public LispObject quotientAndRemainder(LispObject a) throws Exception { return a.quotientAndRemainderSmallInteger(this); } public LispObject mod(LispObject a) throws Exception { return a.modSmallInteger(this); } public LispObject max(LispObject a) throws Exception { return a.maxSmallInteger(this); } public LispObject min(LispObject a) throws Exception { return a.minSmallInteger(this); } public LispObject and(LispObject a) throws Exception { return a.andSmallInteger(this); } public LispObject or(LispObject a) throws Exception { return a.orSmallInteger(this); } LispObject xor(LispObject a) throws Exception { return a.xorSmallInteger(this); } LispObject gcd(LispObject a) throws Exception { return a.gcdSmallInteger(this); } LispObject modAdd(LispObject a) throws Exception { return a.modAddSmallInteger(this); } LispObject modSubtract(LispObject a) throws Exception { return a.modSubtractSmallInteger(this); } LispObject modMultiply(LispObject a) throws Exception { return a.modMultiplySmallInteger(this); } LispObject modDivide(LispObject a) throws Exception { return a.modDivideSmallInteger(this); } LispObject modExpt(int a) throws Exception { long r = 1; long w = value; while (a != 0) { if ((a & 1) != 0) r = (r*w) % Jlisp.modulus; w = (w*w) % Jlisp.modulus; a = a >>> 1; } if (r < 0) r += Jlisp.modulus; return valueOf(r); } boolean eqn(LispObject a) throws Exception { return a.eqnSmallInteger(this); } boolean neqn(LispObject a) throws Exception { return a.neqnSmallInteger(this); } boolean ge(LispObject a) throws Exception { return a.geSmallInteger(this); } boolean geq(LispObject a) throws Exception { return a.geqSmallInteger(this); } boolean le(LispObject a) throws Exception { return a.leSmallInteger(this); } boolean leq(LispObject a) throws Exception { return a.leqSmallInteger(this); } // Now versions that know they have one integer and one small integer. // I am going to accept that these will be seriously slower than the // LispSmallInteger cases and to cope with that I will suppose that // they always return small integers if they can. LispObject addInteger(LispBigInteger a) throws Exception { return valueOf(a.value.add(BigInteger.valueOf((long)value))); } LispObject subtractInteger(LispBigInteger a) throws Exception { return valueOf(a.value.subtract(BigInteger.valueOf((long)value))); } LispObject multiplyInteger(LispBigInteger a) throws Exception { return valueOf(a.value.multiply(BigInteger.valueOf((long)value))); } LispObject divideInteger(LispBigInteger a) throws Exception { if (value == 0) return Jlisp.error("attempt to divide by zero"); return valueOf(a.value.divide(BigInteger.valueOf((long)value))); } LispObject remainderInteger(LispBigInteger a) throws Exception { if (value == 0) return Jlisp.error("attempt to divide by zero"); return valueOf(a.value.remainder(BigInteger.valueOf((long)value))); } LispObject quotientAndRemainderInteger(LispBigInteger a) throws Exception { if (value == 0) return Jlisp.error("attempt to divide by zero"); BigInteger [] r = a.value.divideAndRemainder(BigInteger.valueOf((long)value)); return new Cons(valueOf(r[0]), valueOf(r[1])); } LispObject modInteger(LispBigInteger a) throws Exception { if (value == 0) return Jlisp.error("attempt to divide by zero"); return valueOf(a.value.mod(BigInteger.valueOf((long)value))); } LispObject exptInteger(LispBigInteger a) throws Exception { if (value < 0) return valueOf(0); else if (value == 0) return valueOf(1); else if (value >= 0x10000) return Jlisp.error("integer result would be too large"); else return valueOf(a.value.pow(value)); } LispObject maxInteger(LispBigInteger a) throws Exception { if (a.value.compareTo(BigInteger.valueOf((long)value)) >= 0) return a; else return this; } LispObject minInteger(LispBigInteger a) throws Exception { if (a.value.compareTo(BigInteger.valueOf((long)value)) <= 0) return a; else return this; } LispObject andInteger(LispBigInteger a) throws Exception { return valueOf(a.value.and(BigInteger.valueOf((long)value))); } LispObject orInteger(LispBigInteger a) throws Exception { return valueOf(a.value.or(BigInteger.valueOf((long)value))); } LispObject xorInteger(LispBigInteger a) throws Exception { return valueOf(a.value.xor(BigInteger.valueOf((long)value))); } LispObject gcdInteger(LispBigInteger a) throws Exception { return valueOf(a.value.gcd(BigInteger.valueOf((long)value))); } boolean eqnInteger(LispBigInteger a) throws Exception { return (a.value.compareTo(BigInteger.valueOf((long)value)) == 0); } boolean neqnInteger(LispBigInteger a) throws Exception { return (a.value.compareTo(BigInteger.valueOf((long)value)) != 0); } boolean geInteger(LispBigInteger a) throws Exception { return (a.value.compareTo(BigInteger.valueOf((long)value)) > 0); } boolean geqInteger(LispBigInteger a) throws Exception { return (a.value.compareTo(BigInteger.valueOf((long)value)) >= 0); } boolean leInteger(LispBigInteger a) throws Exception { return (a.value.compareTo(BigInteger.valueOf((long)value)) < 0); } boolean leqInteger(LispBigInteger a) throws Exception { return (a.value.compareTo(BigInteger.valueOf((long)value)) <= 0); } // Finally versions that know they have 2 small integer args. Here I need // to worry about overflow and promote to a LispBigInteger in suitable cases. LispObject addSmallInteger(LispSmallInteger a) throws Exception { return valueOf(a.value + value); } LispObject subtractSmallInteger(LispSmallInteger a) throws Exception { return valueOf(a.value - value); } LispObject multiplySmallInteger(LispSmallInteger a) throws Exception { return valueOf((long)a.value * (long)value); } LispObject divideSmallInteger(LispSmallInteger a) throws Exception { if (value == 0) return Jlisp.error("attempt to divide by zero"); return valueOf(a.value / value); } LispObject remainderSmallInteger(LispSmallInteger a) throws Exception { if (value == 0) return Jlisp.error("attempt to divide by zero"); return valueOf(a.value % value); } LispObject quotientAndRemainderSmallInteger(LispSmallInteger a) throws Exception { if (value == 0) return Jlisp.error("attempt to divide by zero"); return new Cons(valueOf(a.value / value), valueOf(a.value % value)); } LispObject modSmallInteger(LispSmallInteger a) throws Exception { if (value == 0) return Jlisp.error("attempt to divide by zero"); int r = a.value % value; if (value > 0) { if (r < 0) r += value; } else if (r > 0) r += value; return valueOf(r); } LispObject exptSmallInteger(LispSmallInteger a) throws Exception { if (value < 0) return valueOf(0); else if (value == 0) return valueOf(1); else if (value >= 0x10000) return Jlisp.error("integer result would be too large"); else return valueOf( BigInteger.valueOf((long)a.value).pow(value)); } LispObject maxSmallInteger(LispSmallInteger a) throws Exception { if (a.value >= value) return a; else return this; } LispObject minSmallInteger(LispSmallInteger a) throws Exception { if (a.value <= value) return a; else return this; } LispObject andSmallInteger(LispSmallInteger a) throws Exception { return valueOf(a.value & value); } LispObject orSmallInteger(LispSmallInteger a) throws Exception { return valueOf(a.value | value); } LispObject xorSmallInteger(LispSmallInteger a) throws Exception { return valueOf(a.value ^ value); } LispObject gcdSmallInteger(LispSmallInteger a) throws Exception { int p = a.value; int q = value; if (p < 0) p = -p; if (q < 0) q = -q; if (p == 0) return valueOf(q); if (p < q) { q = q % p; } while (q != 0) { int r = p % q; p = q; q = r; } return valueOf(p); } LispObject modAddSmallInteger(LispSmallInteger a) throws Exception { int n = a.value + value; if (n >= Jlisp.modulus) n -= Jlisp.modulus; return valueOf(n); } LispObject modSubtractSmallInteger(LispSmallInteger a) throws Exception { int n = a.value - value; if (n < 0) n += Jlisp.modulus; return valueOf(n); } LispObject modMultiplySmallInteger(LispSmallInteger a) throws Exception { long n = (long)a.value * (long)value; return valueOf(n % Jlisp.modulus); } LispObject modDivideSmallInteger(LispSmallInteger arg) throws Exception { if (value == 0) return Jlisp.error("attempt to divide by (modular) zero"); int a = Jlisp.modulus, b = value, s = 0, t = 1; while (b != 0) { int q = a/b; int w = a - q*b; a = b; b = w; w = s - q*t; s = t; t = w; } if (s < 0) s += Jlisp.modulus; return valueOf(((long)s * (long)arg.value) % Jlisp.modulus); } boolean eqnSmallInteger(LispSmallInteger a) throws Exception { return (a.value == value); } boolean neqnSmallInteger(LispSmallInteger a) throws Exception { return (a.value != value); } boolean geSmallInteger(LispSmallInteger a) throws Exception { return (a.value > value); } boolean geqSmallInteger(LispSmallInteger a) throws Exception { return (a.value >= value); } boolean leSmallInteger(LispSmallInteger a) throws Exception { return (a.value < value); } boolean leqSmallInteger(LispSmallInteger a) throws Exception { return (a.value <= value); } } // End of LispSmallInteger.java