/*
* 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;
}
}