/* * Copyright (c) Corporation for National Research Initiatives * Copyright (c) Jython Developers */ package org.python.core; import java.io.Serializable; import java.math.BigDecimal; import java.math.BigInteger; import org.python.expose.ExposedGet; import org.python.expose.ExposedMethod; import org.python.expose.ExposedNew; import org.python.expose.ExposedType; import org.python.expose.MethodType; /** * A builtin python long. This is implemented as a java.math.BigInteger. */ @ExposedType(name = "long", doc = BuiltinDocs.long_doc) public class PyLong extends PyObject { public static final PyType TYPE = PyType.fromClass(PyLong.class); public static final BigInteger MIN_LONG = BigInteger.valueOf(Long.MIN_VALUE); public static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE); public static final BigInteger MAX_ULONG = BigInteger.valueOf(1).shiftLeft(64).subtract(BigInteger.valueOf(1)); /** @deprecated Use MIN_INT instead. */ @Deprecated public static final BigInteger minLong = MIN_LONG; /** @deprecated Use MAX_INT instead. */ @Deprecated public static final BigInteger maxLong = MAX_LONG; /** @deprecated Use MAX_ULONG instead. */ @Deprecated public static final BigInteger maxULong = MAX_ULONG; private final BigInteger value; public BigInteger getValue() { return value; } public PyLong(PyType subType, BigInteger v) { super(subType); value = v; } public PyLong(BigInteger v) { this(TYPE, v); } public PyLong(double v) { this(toBigInteger(v)); } public PyLong(long v) { this(BigInteger.valueOf(v)); } public PyLong(String s) { this(new BigInteger(s)); } @ExposedNew public static PyObject long___new__(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { if (new_.for_type != subtype) { return longSubtypeNew(new_, init, subtype, args, keywords); } ArgParser ap = new ArgParser("long", args, keywords, new String[] {"x", "base"}, 0); PyObject x = ap.getPyObject(0, null); if (x != null && x.getJavaProxy() instanceof BigInteger) { return new PyLong((BigInteger) x.getJavaProxy()); } int base = ap.getInt(1, -909); if (x == null) { return new PyLong(0); } if (base == -909) { try { return x.__long__(); } catch (PyException pye) { if (!pye.match(Py.AttributeError)) { throw pye; } throw Py.TypeError(String.format("long() argument must be a string or a number, " + "not '%.200s'", x.getType().fastGetName())); } } if (!(x instanceof PyString)) { throw Py.TypeError("long: can't convert non-string with explicit base"); } return ((PyString) x).atol(base); } /** * Wimpy, slow approach to new calls for subtypes of long. * * First creates a regular long from whatever arguments we got, then allocates a * subtype instance and initializes it from the regular long. The regular long is then * thrown away. */ private static PyObject longSubtypeNew(PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { PyObject tmp = long___new__(new_, init, TYPE, args, keywords); if (tmp instanceof PyInteger) { int intValue = ((PyInteger) tmp).getValue(); return new PyLongDerived(subtype, BigInteger.valueOf(intValue)); } else { return new PyLongDerived(subtype, ((PyLong) tmp).getValue()); } } /** * Convert a double to BigInteger, raising an OverflowError if * infinite. */ private static BigInteger toBigInteger(double value) { if (Double.isInfinite(value)) { throw Py.OverflowError("cannot convert float infinity to long"); } if (Double.isNaN(value)) { return BigInteger.valueOf(0); } return new BigDecimal(value).toBigInteger(); } @ExposedGet(name = "real", doc = BuiltinDocs.long_real_doc) public PyObject getReal() { return long___long__(); } @ExposedGet(name = "imag", doc = BuiltinDocs.long_imag_doc) public PyObject getImag() { return Py.newLong(0); } @ExposedGet(name = "numerator", doc = BuiltinDocs.long_numerator_doc) public PyObject getNumerator() { return long___long__(); } @ExposedGet(name = "denominator", doc = BuiltinDocs.long_denominator_doc) public PyObject getDenominator() { return Py.newLong(1); } @Override public String toString() { return long_toString(); } @ExposedMethod(names = {"__str__", "__repr__"}, doc = BuiltinDocs.long___str___doc) final String long_toString() { return getValue().toString() + "L"; } @Override public int hashCode() { return long___hash__(); } @ExposedMethod(doc = BuiltinDocs.long___hash___doc) final int long___hash__() { return getValue().intValue(); } @Override public boolean __nonzero__() { return !getValue().equals(BigInteger.ZERO); } @ExposedMethod(doc = BuiltinDocs.long___nonzero___doc) public boolean long___nonzero__() { return __nonzero__(); } public double doubleValue() { double v = getValue().doubleValue(); if (Double.isInfinite(v)) { throw Py.OverflowError("long int too large to convert to float"); } return v; } private static final double scaledDoubleValue(BigInteger val, int[] exp) { double x = 0; int signum = val.signum(); byte[] digits; if (signum >= 0) { digits = val.toByteArray(); } else { digits = val.negate().toByteArray(); } int count = 8; int i = 0; if (digits[0] == 0) { i++; count++; } count = count <= digits.length ? count : digits.length; while (i < count) { x = x * 256 + (digits[i] & 0xff); i++; } exp[0] = digits.length - i; return signum * x; } public double scaledDoubleValue(int[] exp) { return scaledDoubleValue(getValue(),exp); } public long getLong(long min, long max) { return getLong(min, max, "long int too large to convert"); } public long getLong(long min, long max, String overflowMsg) { if (getValue().compareTo(MAX_LONG) <= 0 && getValue().compareTo(MIN_LONG) >= 0) { long v = getValue().longValue(); if (v >= min && v <= max) { return v; } } throw Py.OverflowError(overflowMsg); } @Override public long asLong(int index) { return asLong(); } @Override public int asInt(int index) { return (int) getLong(Integer.MIN_VALUE, Integer.MAX_VALUE, "long int too large to convert to int"); } @Override public int asInt() { return (int) getLong(Integer.MIN_VALUE, Integer.MAX_VALUE, "long int too large to convert to int"); } @Override public long asLong() { return getLong(Long.MIN_VALUE, Long.MAX_VALUE, "long too big to convert"); } @Override public Object __tojava__(Class<?> c) { try { if (c == Byte.TYPE || c == Byte.class) { return new Byte((byte) getLong(Byte.MIN_VALUE, Byte.MAX_VALUE)); } if (c == Short.TYPE || c == Short.class) { return new Short((short) getLong(Short.MIN_VALUE, Short.MAX_VALUE)); } if (c == Integer.TYPE || c == Integer.class) { return new Integer((int) getLong(Integer.MIN_VALUE, Integer.MAX_VALUE)); } if (c == Long.TYPE || c == Long.class) { return new Long(getLong(Long.MIN_VALUE, Long.MAX_VALUE)); } if (c == Float.TYPE || c == Double.TYPE || c == Float.class || c == Double.class) { return __float__().__tojava__(c); } if (c == BigInteger.class || c == Number.class || c == Object.class || c == Serializable.class) { return getValue(); } } catch (PyException e) { return Py.NoConversion; } return super.__tojava__(c); } @Override public int __cmp__(PyObject other) { return long___cmp__(other); } @ExposedMethod(type = MethodType.CMP, doc = BuiltinDocs.long___cmp___doc) final int long___cmp__(PyObject other) { if (!canCoerce(other)) { return -2; } return getValue().compareTo(coerce(other)); } @Override public Object __coerce_ex__(PyObject other) { return long___coerce_ex__(other); } @ExposedMethod(doc = BuiltinDocs.long___coerce___doc) final PyObject long___coerce__(PyObject other) { return adaptToCoerceTuple(long___coerce_ex__(other)); } /** * Coercion logic for long. Implemented as a final method to avoid * invocation of virtual methods from the exposed coerce. */ final Object long___coerce_ex__(PyObject other) { if (other instanceof PyLong) { return other; } else if (other instanceof PyInteger) { return Py.newLong(((PyInteger) other).getValue()); } else { return Py.None; } } private static final boolean canCoerce(PyObject other) { return other instanceof PyLong || other instanceof PyInteger; } private static final BigInteger coerce(PyObject other) { if (other instanceof PyLong) { return ((PyLong) other).getValue(); } else if (other instanceof PyInteger) { return BigInteger.valueOf(((PyInteger) other).getValue()); } else { throw Py.TypeError("xxx"); } } @Override public PyObject __add__(PyObject right) { return long___add__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___add___doc) final PyObject long___add__(PyObject right) { if (!canCoerce(right)) { return null; } return Py.newLong(getValue().add(coerce(right))); } @Override public PyObject __radd__(PyObject left) { return long___radd__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___radd___doc) final PyObject long___radd__(PyObject left) { return __add__(left); } @Override public PyObject __sub__(PyObject right) { return long___sub__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___sub___doc) final PyObject long___sub__(PyObject right) { if (!canCoerce(right)) { return null; } return Py.newLong(getValue().subtract(coerce(right))); } @Override public PyObject __rsub__(PyObject left) { return long___rsub__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rsub___doc) final PyObject long___rsub__(PyObject left) { return Py.newLong(coerce(left).subtract(getValue())); } @Override public PyObject __mul__(PyObject right) { return long___mul__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___mul___doc) final PyObject long___mul__(PyObject right) { if (right instanceof PySequence) { return ((PySequence) right).repeat(coerceInt(this)); } if (!canCoerce(right)) { return null; } return Py.newLong(getValue().multiply(coerce(right))); } @Override public PyObject __rmul__(PyObject left) { return long___rmul__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rmul___doc) final PyObject long___rmul__(PyObject left) { if (left instanceof PySequence) { return ((PySequence) left).repeat(coerceInt(this)); } if (!canCoerce(left)) { return null; } return Py.newLong(coerce(left).multiply(getValue())); } // Getting signs correct for integer division // This convention makes sense when you consider it in tandem with modulo private BigInteger divide(BigInteger x, BigInteger y) { BigInteger zero = BigInteger.valueOf(0); if (y.equals(zero)) { throw Py.ZeroDivisionError("long division or modulo"); } if (y.compareTo(zero) < 0) { if (x.compareTo(zero) > 0) { return (x.subtract(y).subtract(BigInteger.valueOf(1))).divide(y); } } else { if (x.compareTo(zero) < 0) { return (x.subtract(y).add(BigInteger.valueOf(1))).divide(y); } } return x.divide(y); } @Override public PyObject __div__(PyObject right) { return long___div__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___div___doc) final PyObject long___div__(PyObject right) { if (!canCoerce(right)) { return null; } if (Options.divisionWarning > 0) { Py.warning(Py.DeprecationWarning, "classic long division"); } return Py.newLong(divide( getValue(), coerce(right))); } @Override public PyObject __rdiv__(PyObject left) { return long___rdiv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rdiv___doc) final PyObject long___rdiv__(PyObject left) { if (!canCoerce(left)) { return null; } if (Options.divisionWarning > 0) { Py.warning(Py.DeprecationWarning, "classic long division"); } return Py.newLong(divide(coerce(left), getValue())); } @Override public PyObject __floordiv__(PyObject right) { return long___floordiv__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___floordiv___doc) final PyObject long___floordiv__(PyObject right) { if (!canCoerce(right)) { return null; } return Py.newLong(divide( getValue(), coerce(right))); } @Override public PyObject __rfloordiv__(PyObject left) { return long___rfloordiv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rfloordiv___doc) final PyObject long___rfloordiv__(PyObject left) { if (!canCoerce(left)) { return null; } return Py.newLong(divide(coerce(left), getValue())); } private static final PyFloat true_divide(BigInteger a, BigInteger b) { int[] ae = new int[1]; int[] be = new int[1]; double ad, bd; ad = scaledDoubleValue(a, ae); bd = scaledDoubleValue(b, be); if (bd == 0) { throw Py.ZeroDivisionError("long division or modulo"); } ad /= bd; int aexp = ae[0] - be[0]; if (aexp > Integer.MAX_VALUE / 8) { throw Py.OverflowError("long/long too large for a float"); } else if (aexp < -(Integer.MAX_VALUE / 8)) { return new PyFloat(0.0); } ad = ad * Math.pow(2.0, aexp * 8); if (Double.isInfinite(ad)) { throw Py.OverflowError("long/long too large for a float"); } return new PyFloat(ad); } @Override public PyObject __truediv__(PyObject right) { return long___truediv__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___truediv___doc) final PyObject long___truediv__(PyObject right) { if (!canCoerce(right)) { return null; } return true_divide( this.getValue(), coerce(right)); } @Override public PyObject __rtruediv__(PyObject left) { return long___rtruediv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rtruediv___doc) final PyObject long___rtruediv__(PyObject left) { if (!canCoerce(left)) { return null; } return true_divide(coerce(left), this.getValue()); } private BigInteger modulo(BigInteger x, BigInteger y, BigInteger xdivy) { return x.subtract(xdivy.multiply(y)); } @Override public PyObject __mod__(PyObject right) { return long___mod__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___mod___doc) final PyObject long___mod__(PyObject right) { if (!canCoerce(right)) { return null; } BigInteger rightv = coerce(right); return Py.newLong(modulo(getValue(),rightv, divide(getValue(),rightv))); } @Override public PyObject __rmod__(PyObject left) { return long___rmod__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rmod___doc) final PyObject long___rmod__(PyObject left) { if (!canCoerce(left)) { return null; } BigInteger leftv = coerce(left); return Py.newLong(modulo(leftv, getValue(), divide(leftv, getValue()))); } @Override public PyObject __divmod__(PyObject right) { return long___divmod__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___divmod___doc) final PyObject long___divmod__(PyObject right) { if (!canCoerce(right)) { return null; } BigInteger rightv = coerce(right); BigInteger xdivy = divide(getValue(),rightv); return new PyTuple(Py.newLong(xdivy), Py.newLong(modulo(getValue(),rightv, xdivy))); } @Override public PyObject __rdivmod__(PyObject left) { return long___rdivmod__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rdivmod___doc) final PyObject long___rdivmod__(PyObject left) { if (!canCoerce(left)) { return null; } BigInteger leftv = coerce(left); BigInteger xdivy = divide(leftv, getValue()); return new PyTuple(Py.newLong(xdivy), Py.newLong(modulo(leftv, getValue(), xdivy))); } @Override public PyObject __pow__(PyObject right, PyObject modulo) { return long___pow__(right, modulo); } @ExposedMethod(type = MethodType.BINARY, defaults = {"null"}, doc = BuiltinDocs.long___pow___doc) final PyObject long___pow__(PyObject right, PyObject modulo) { if (!canCoerce(right)) { return null; } if (modulo != null && !canCoerce(right)) { return null; } return _pow( getValue(), coerce(right), modulo, this, right); } @Override public PyObject __rpow__(PyObject left) { return long___rpow__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rpow___doc) final PyObject long___rpow__(PyObject left) { if (!canCoerce(left)) { return null; } return _pow(coerce(left), getValue(), null, left, this); } public static PyObject _pow(BigInteger value, BigInteger y, PyObject modulo, PyObject left, PyObject right) { if (y.compareTo(BigInteger.valueOf(0)) < 0) { if (value.compareTo(BigInteger.valueOf(0)) != 0) { return left.__float__().__pow__(right, modulo); } else { throw Py.ZeroDivisionError("zero to a negative power"); } } if (modulo == null) { return Py.newLong(value.pow(y.intValue())); } else { // This whole thing can be trivially rewritten after bugs // in modPow are fixed by SUN BigInteger z = coerce(modulo); int zi = z.intValue(); // Clear up some special cases right away if (zi == 0) { throw Py.ValueError("pow(x, y, z) with z == 0"); } if (zi == 1 || zi == -1) { return Py.newLong(0); } if (z.compareTo(BigInteger.valueOf(0)) <= 0) { // Handle negative modulo's specially /*if (z.compareTo(BigInteger.valueOf(0)) == 0) { throw Py.ValueError("pow(x, y, z) with z == 0"); }*/ y = value.modPow(y, z.negate()); if (y.compareTo(BigInteger.valueOf(0)) > 0) { return Py.newLong(z.add(y)); } else { return Py.newLong(y); } //return __pow__(right).__mod__(modulo); } else { // XXX: 1.1 no longer supported so review this. // This is buggy in SUN's jdk1.1.5 // Extra __mod__ improves things slightly return Py.newLong(value.modPow(y, z)); //return __pow__(right).__mod__(modulo); } } } private static final int coerceInt(PyObject other) { if (other instanceof PyLong) { return ((PyLong) other).asInt(); } else if (other instanceof PyInteger) { return ((PyInteger) other).getValue(); } else { throw Py.TypeError("xxx"); } } @Override public PyObject __lshift__(PyObject right) { return long___lshift__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___lshift___doc) final PyObject long___lshift__(PyObject right) { if (!canCoerce(right)) { return null; } int rightv = coerceInt(right); if (rightv < 0) { throw Py.ValueError("negative shift count"); } return Py.newLong(getValue().shiftLeft(rightv)); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rlshift___doc) final PyObject long___rlshift__(PyObject left) { if (!canCoerce(left)) { return null; } if (getValue().intValue() < 0) { throw Py.ValueError("negative shift count"); } return Py.newLong(coerce(left).shiftLeft(coerceInt(this))); } @Override public PyObject __rshift__(PyObject right) { return long___rshift__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rshift___doc) final PyObject long___rshift__(PyObject right) { if (!canCoerce(right)) { return null; } int rightv = coerceInt(right); if (rightv < 0) { throw Py.ValueError("negative shift count"); } return Py.newLong(getValue().shiftRight(rightv)); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rrshift___doc) final PyObject long___rrshift__(PyObject left) { if (!canCoerce(left)) { return null; } if (getValue().intValue() < 0) { throw Py.ValueError("negative shift count"); } return Py.newLong(coerce(left).shiftRight(coerceInt(this))); } @Override public PyObject __and__(PyObject right) { return long___and__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___and___doc) final PyObject long___and__(PyObject right) { if (!canCoerce(right)) { return null; } return Py.newLong(getValue().and(coerce(right))); } @Override public PyObject __rand__(PyObject left) { return long___rand__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rand___doc) final PyObject long___rand__(PyObject left) { if (!canCoerce(left)) { return null; } return Py.newLong(coerce(left).and(getValue())); } @Override public PyObject __xor__(PyObject right) { return long___xor__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___xor___doc) final PyObject long___xor__(PyObject right) { if (!canCoerce(right)) { return null; } return Py.newLong(getValue().xor(coerce(right))); } @Override public PyObject __rxor__(PyObject left) { return long___rxor__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___rxor___doc) final PyObject long___rxor__(PyObject left) { if (!canCoerce(left)) { return null; } return Py.newLong(coerce(left).xor(getValue())); } @Override public PyObject __or__(PyObject right) { return long___or__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___or___doc) final PyObject long___or__(PyObject right) { if (!canCoerce(right)) { return null; } return Py.newLong(getValue().or(coerce(right))); } @Override public PyObject __ror__(PyObject left) { return long___ror__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.long___ror___doc) final PyObject long___ror__(PyObject left) { if (!canCoerce(left)) { return null; } return Py.newLong(coerce(left).or(getValue())); } @Override public PyObject __neg__() { return long___neg__(); } @ExposedMethod(doc = BuiltinDocs.long___neg___doc) final PyObject long___neg__() { return Py.newLong(getValue().negate()); } @Override public PyObject __pos__() { return long___pos__(); } @ExposedMethod(doc = BuiltinDocs.long___pos___doc) final PyObject long___pos__() { return long___long__(); } @Override public PyObject __abs__() { return long___abs__(); } @ExposedMethod(doc = BuiltinDocs.long___abs___doc) final PyObject long___abs__() { if (getValue().signum() == -1) { return long___neg__(); } return long___long__(); } @Override public PyObject __invert__() { return long___invert__(); } @ExposedMethod(doc = BuiltinDocs.long___invert___doc) final PyObject long___invert__() { return Py.newLong(getValue().not()); } @Override public PyObject __int__() { return long___int__(); } @ExposedMethod(doc = BuiltinDocs.long___int___doc) final PyObject long___int__() { if (getValue().compareTo(PyInteger.MAX_INT) <= 0 && getValue().compareTo(PyInteger.MIN_INT) >= 0) { return Py.newInteger(getValue().intValue()); } return long___long__(); } @Override public PyObject __long__() { return long___long__(); } @ExposedMethod(doc = BuiltinDocs.long___long___doc) final PyObject long___long__() { return getType() == TYPE ? this : Py.newLong(getValue()); } @Override public PyFloat __float__() { return long___float__(); } @ExposedMethod(doc = BuiltinDocs.long___float___doc) final PyFloat long___float__() { return new PyFloat(doubleValue()); } @Override public PyComplex __complex__() { return long___complex__(); } final PyComplex long___complex__() { return new PyComplex(doubleValue(), 0.); } @Override public PyString __oct__() { return long___oct__(); } @ExposedMethod(doc = BuiltinDocs.long___oct___doc) final PyString long___oct__() { String s = getValue().toString(8); if (s.startsWith("-")) { return new PyString("-0" + s.substring(1, s.length()) + "L"); } else if (s.startsWith("0")) { return new PyString(s + "L"); } else { return new PyString("0" + s + "L"); } } @Override public PyString __hex__() { return long___hex__(); } @ExposedMethod(doc = BuiltinDocs.long___hex___doc) final PyString long___hex__() { String s = getValue().toString(16); if (s.startsWith("-")) { return new PyString("-0x" + s.substring(1, s.length()) + "L"); } else { return new PyString("0x" + s + "L"); } } @Override public PyString __str__() { return Py.newString(getValue().toString()); } @Override public PyUnicode __unicode__() { return new PyUnicode(getValue().toString()); } @ExposedMethod(doc = BuiltinDocs.long___getnewargs___doc) final PyTuple long___getnewargs__() { return new PyTuple(new PyLong(this.getValue())); } @Override public PyTuple __getnewargs__() { return long___getnewargs__(); } @Override public PyObject __index__() { return long___index__(); } @ExposedMethod(doc = BuiltinDocs.long___index___doc) final PyObject long___index__() { return this; } @Override public PyObject __format__(PyObject formatSpec) { return long___format__(formatSpec); } @ExposedMethod(doc = BuiltinDocs.long___format___doc) final PyObject long___format__(PyObject formatSpec) { return PyInteger.formatImpl(getValue(), formatSpec); } @Override public boolean isIndex() { return true; } @Override public int asIndex(PyObject err) { boolean tooLow = getValue().compareTo(PyInteger.MIN_INT) < 0; boolean tooHigh = getValue().compareTo(PyInteger.MAX_INT) > 0; if (tooLow || tooHigh) { if (err != null) { throw new PyException(err, "cannot fit 'long' into an index-sized integer"); } return tooLow ? Integer.MIN_VALUE : Integer.MAX_VALUE; } return (int) getValue().longValue(); } @Override public boolean isMappingType() { return false; } @Override public boolean isNumberType() { return true; } @Override public boolean isSequenceType() { return false; } }