@ExposedType(name = "listiterator", base = PyIterator.class, isBaseType = false) public class PyListIterator extends PyIterator { public static final PyType TYPE = PyType.fromClass(PyListIterator.class); private PyList list; private boolean stopped = false; private int index = 0; public PyListIterator(PyList list) { this.list = list; } public PyObject __iternext__() { synchronized (list) { if (stopped) { // Need to prevent the iteration from restarting, even after a StopIteration, // due to the list subsequently growing. // Keeping track of this flag ensures that next(it) will throw StopIteration // exceptions on all subsequent invocations. return null; } else if (index >= list.size()) { stopped = true; return null; } else { return list.pyget(index++); } } } /* Traverseproc implementation */ @Override public int traverse(Visitproc visit, Object arg) { int retValue = super.traverse(visit, arg); if (retValue != 0) { return retValue; } return list == null ? 0 : visit.visit(list, arg); } @Override public boolean refersDirectlyTo(PyObject ob) { return ob != null && (ob == list || super.refersDirectlyTo(ob)); } }
/** A Python function. */ @ExposedType(name = "function", isBaseType = false, doc = BuiltinDocs.function_doc) public class PyFunction extends PyObject implements InvocationHandler { public static final PyType TYPE = PyType.fromClass(PyFunction.class); /** The writable name, also available via func_name. */ @ExposedGet @ExposedSet public String __name__; /** The writable doc string, also available via func_doc. */ @ExposedGet @ExposedSet public PyObject __doc__; /** The read only namespace; a dict (PyStringMap). */ @ExposedGet public PyObject func_globals; /** Default argument values for associated kwargs. Exposed as a tuple to Python. Writable. */ public PyObject[] func_defaults; /** The actual funtion's code, writable. */ @ExposedGet public PyCode func_code; /** * A function's lazily created __dict__; allows arbitrary attributes to be tacked on. Read only. */ public PyObject __dict__; /** A read only closure tuple for nested scopes. */ @ExposedGet public PyObject func_closure; /** Writable object describing what module this function belongs to. */ @ExposedGet @ExposedSet public PyObject __module__; public PyFunction( PyObject globals, PyObject[] defaults, PyCode code, PyObject doc, PyObject[] closure_cells) { super(TYPE); func_globals = globals; __name__ = code.co_name; __doc__ = doc != null ? doc : Py.None; // XXX: workaround the compiler passing Py.EmptyObjects // instead of null for defaults, whereas we want func_defaults // to be None (null) in that situation func_defaults = (defaults != null && defaults.length == 0) ? null : defaults; func_code = code; func_closure = closure_cells != null ? new PyTuple(closure_cells) : null; PyObject moduleName = globals.__finditem__("__name__"); __module__ = moduleName != null ? moduleName : Py.None; } public PyFunction(PyObject globals, PyObject[] defaults, PyCode code, PyObject doc) { this(globals, defaults, code, doc, null); } public PyFunction(PyObject globals, PyObject[] defaults, PyCode code) { this(globals, defaults, code, null, null); } public PyFunction(PyObject globals, PyObject[] defaults, PyCode code, PyObject[] closure_cells) { this(globals, defaults, code, null, closure_cells); } @ExposedNew static final PyObject function___new__( PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { ArgParser ap = new ArgParser( "function", args, keywords, new String[] {"code", "globals", "name", "argdefs", "closure"}, 0); PyObject code = ap.getPyObject(0); PyObject globals = ap.getPyObject(1); PyObject name = ap.getPyObject(2, Py.None); PyObject defaults = ap.getPyObject(3, Py.None); PyObject closure = ap.getPyObject(4, Py.None); if (!(code instanceof PyBaseCode)) { throw Py.TypeError("function() argument 1 must be code, not " + code.getType().fastGetName()); } if (name != Py.None && !Py.isInstance(name, PyString.TYPE)) { throw Py.TypeError("arg 3 (name) must be None or string"); } if (defaults != Py.None && !(defaults instanceof PyTuple)) { throw Py.TypeError("arg 4 (defaults) must be None or tuple"); } PyBaseCode tcode = (PyBaseCode) code; int nfree = tcode.co_freevars == null ? 0 : tcode.co_freevars.length; if (!(closure instanceof PyTuple)) { if (nfree > 0 && closure == Py.None) { throw Py.TypeError("arg 5 (closure) must be tuple"); } else if (closure != Py.None) { throw Py.TypeError("arg 5 (closure) must be None or tuple"); } } int nclosure = closure == Py.None ? 0 : closure.__len__(); if (nfree != nclosure) { throw Py.ValueError( String.format( "%s requires closure of length %d, not %d", tcode.co_name, nfree, nclosure)); } if (nclosure > 0) { for (PyObject o : ((PyTuple) closure).asIterable()) { if (!(o instanceof PyCell)) { throw Py.TypeError( String.format("arg 5 (closure) expected cell, found %s", o.getType().fastGetName())); } } } PyFunction function = new PyFunction( globals, defaults == Py.None ? null : ((PyTuple) defaults).getArray(), tcode, null, closure == Py.None ? null : ((PyTuple) closure).getArray()); if (name != Py.None) { function.__name__ = name.toString(); } return function; } @ExposedGet(name = "func_name") public PyString getFuncName() { return new PyString(__name__); } @ExposedSet(name = "func_name") public void setFuncName(PyString func_name) { __name__ = func_name.asString(); } @ExposedGet(name = "func_doc") public PyObject getFuncDoc() { return __doc__; } @ExposedSet(name = "func_doc") public void setFuncDoc(PyObject func_doc) { __doc__ = func_doc; } @ExposedDelete(name = "func_doc") public void delFuncDoc() { delDoc(); } @ExposedDelete(name = "__doc__") public void delDoc() { __doc__ = Py.None; } @ExposedGet(name = "func_defaults") public PyObject getFuncDefaults() { if (func_defaults == null) { return Py.None; } return new PyTuple(func_defaults); } @ExposedSet(name = "func_defaults") public void setFuncDefaults(PyObject func_defaults) { if (func_defaults != Py.None && !(func_defaults instanceof PyTuple)) { throw Py.TypeError("func_defaults must be set to a tuple object"); } this.func_defaults = func_defaults == Py.None ? null : ((PyTuple) func_defaults).getArray(); } @ExposedDelete(name = "func_defaults") public void delFuncDefaults() { func_defaults = null; } @ExposedSet(name = "func_code") public void setFuncCode(PyCode code) { if (func_code == null || !(code instanceof PyBaseCode)) { throw Py.TypeError("func_code must be set to a code object"); } PyBaseCode tcode = (PyBaseCode) code; int nfree = tcode.co_freevars == null ? 0 : tcode.co_freevars.length; int nclosure = func_closure != null ? func_closure.__len__() : 0; if (nclosure != nfree) { throw Py.ValueError( String.format( "%s() requires a code object with %d free vars," + " not %d", __name__, nclosure, nfree)); } this.func_code = code; } @ExposedDelete(name = "__module__") public void delModule() { __module__ = Py.None; } @Override public PyObject fastGetDict() { return __dict__; } @ExposedGet(name = "__dict__") public PyObject getDict() { ensureDict(); return __dict__; } @ExposedSet(name = "__dict__") public void setDict(PyObject value) { if (!(value instanceof PyDictionary) && !(value instanceof PyStringMap)) { throw Py.TypeError("setting function's dictionary to a non-dict"); } __dict__ = value; } @ExposedDelete(name = "__dict__") public void delDict() { throw Py.TypeError("function's dictionary may not be deleted"); } @ExposedGet(name = "func_dict") public PyObject getFuncDict() { return getDict(); } @ExposedSet(name = "func_dict") public void setFuncDict(PyObject value) { setDict(value); } @ExposedDelete(name = "func_dict") public void delFuncDict() { delDict(); } @ExposedSet(name = "func_globals") public void setFuncGlobals(PyObject value) { // __setattr__ would set __dict__['func_globals'] = value // without this method throw Py.TypeError("readonly attribute"); } @ExposedSet(name = "func_closure") public void setFuncClosure(PyObject value) { // same idea as setFuncGlobals throw Py.TypeError("readonly attribute"); } private void ensureDict() { if (__dict__ == null) { __dict__ = new PyStringMap(); } } @Override public void __setattr__(String name, PyObject value) { function___setattr__(name, value); } @ExposedMethod(doc = BuiltinDocs.function___setattr___doc) final void function___setattr__(String name, PyObject value) { ensureDict(); super.__setattr__(name, value); } @Override public PyObject __get__(PyObject obj, PyObject type) { return function___get__(obj, type); } @ExposedMethod(defaults = "null", doc = BuiltinDocs.function___get___doc) final PyObject function___get__(PyObject obj, PyObject type) { return new PyMethod(this, obj, type); } @Override public PyObject __call__() { return __call__(Py.getThreadState()); } @Override public PyObject __call__(ThreadState state) { return func_code.call(state, func_globals, func_defaults, func_closure); } @Override public PyObject __call__(PyObject arg) { return __call__(Py.getThreadState(), arg); } @Override public PyObject __call__(ThreadState state, PyObject arg0) { return func_code.call(state, arg0, func_globals, func_defaults, func_closure); } @Override public PyObject __call__(PyObject arg1, PyObject arg2) { return __call__(Py.getThreadState(), arg1, arg2); } @Override public PyObject __call__(ThreadState state, PyObject arg0, PyObject arg1) { return func_code.call(state, arg0, arg1, func_globals, func_defaults, func_closure); } @Override public PyObject __call__(PyObject arg1, PyObject arg2, PyObject arg3) { return __call__(Py.getThreadState(), arg1, arg2, arg3); } @Override public PyObject __call__(ThreadState state, PyObject arg0, PyObject arg1, PyObject arg2) { return func_code.call(state, arg0, arg1, arg2, func_globals, func_defaults, func_closure); } @Override public PyObject __call__(PyObject arg0, PyObject arg1, PyObject arg2, PyObject arg3) { return __call__(Py.getThreadState(), arg0, arg1, arg2, arg3); } @Override public PyObject __call__( ThreadState state, PyObject arg0, PyObject arg1, PyObject arg2, PyObject arg3) { return func_code.call(state, arg0, arg1, arg2, arg3, func_globals, func_defaults, func_closure); } @Override public PyObject __call__(PyObject[] args) { return __call__(Py.getThreadState(), args); } @Override public PyObject __call__(ThreadState state, PyObject[] args) { return __call__(state, args, Py.NoKeywords); } @Override public PyObject __call__(PyObject[] args, String[] keywords) { return __call__(Py.getThreadState(), args, keywords); } @Override public PyObject __call__(ThreadState state, PyObject[] args, String[] keywords) { return function___call__(state, args, keywords); } @ExposedMethod(doc = BuiltinDocs.function___call___doc) final PyObject function___call__(ThreadState state, PyObject[] args, String[] keywords) { return func_code.call(state, args, keywords, func_globals, func_defaults, func_closure); } @Override public PyObject __call__(PyObject arg1, PyObject[] args, String[] keywords) { return __call__(Py.getThreadState(), arg1, args, keywords); } @Override public PyObject __call__(ThreadState state, PyObject arg1, PyObject[] args, String[] keywords) { return func_code.call(state, arg1, args, keywords, func_globals, func_defaults, func_closure); } @Override public String toString() { return String.format("<function %s at %s>", __name__, Py.idstr(this)); } @Override public Object __tojava__(Class<?> c) { // Automatically coerce to single method interfaces if (c.isInstance(this) && c != InvocationHandler.class) { // for base types, conversion is simple - so don't wrap! // InvocationHandler is special, since it's a single method interface // that we implement, but if we coerce to it we want the arguments return c.cast(this); } else if (c.isInterface()) { if (c.getDeclaredMethods().length == 1 && c.getInterfaces().length == 0) { // Proper single method interface return proxy(c); } else { // Try coerce to interface with multiple overloaded versions of // the same method (name) String name = null; for (Method method : c.getMethods()) { if (method.getDeclaringClass() != Object.class) { if (name == null || name.equals(method.getName())) { name = method.getName(); } else { name = null; break; } } } if (name != null) { // single unique method name return proxy(c); } } } return super.__tojava__(c); } private Object proxy(Class<?> c) { return Proxy.newProxyInstance(c.getClassLoader(), new Class[] {c}, this); } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // Handle invocation when invoked through Proxy (as coerced to single method interface) if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } else if (args == null || args.length == 0) { return __call__().__tojava__(method.getReturnType()); } else { return __call__(Py.javas2pys(args)).__tojava__(method.getReturnType()); } } @Override public boolean isMappingType() { return false; } @Override public boolean isNumberType() { return false; } @Override public boolean isSequenceType() { return false; } }
/** A builtin python complex number */ @ExposedType(name = "complex") public class PyComplex extends PyObject { public static final PyType TYPE = PyType.fromClass(PyComplex.class); @ExposedGet public double real, imag; static PyComplex J = new PyComplex(0, 1.); @ExposedNew public static PyObject complex_new( PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { ArgParser ap = new ArgParser("complex", args, keywords, "real", "imag"); PyObject real = ap.getPyObject(0, Py.Zero); PyObject imag = ap.getPyObject(1, null); // Special-case for single argument that is already complex if (real.getType() == TYPE && new_.for_type == subtype && imag == null) { return real; } if (real instanceof PyString) { if (imag != null) { throw Py.TypeError("complex() can't take second arg if first is a string"); } return real.__complex__(); } if (imag != null && imag instanceof PyString) { throw Py.TypeError("complex() second arg can't be a string"); } try { real = real.__complex__(); } catch (PyException pye) { if (!Py.matchException(pye, Py.AttributeError)) { // __complex__ not supported throw pye; } // otherwise try other means } PyComplex complexReal; PyComplex complexImag; PyFloat toFloat = null; if (real instanceof PyComplex) { complexReal = (PyComplex) real; } else { try { toFloat = real.__float__(); } catch (PyException pye) { if (Py.matchException(pye, Py.AttributeError)) { // __float__ not supported throw Py.TypeError("complex() argument must be a string or a number"); } throw pye; } complexReal = new PyComplex(toFloat.getValue()); } if (imag == null) { complexImag = new PyComplex(0.0); } else if (imag instanceof PyComplex) { complexImag = (PyComplex) imag; } else { toFloat = null; try { toFloat = imag.__float__(); } catch (PyException pye) { if (Py.matchException(pye, Py.AttributeError)) { // __float__ not supported throw Py.TypeError("complex() argument must be a string or a number"); } throw pye; } complexImag = new PyComplex(toFloat.getValue()); } complexReal.real -= complexImag.imag; complexReal.imag += complexImag.real; if (new_.for_type != subtype) { complexReal = new PyComplexDerived(subtype, complexReal.real, complexReal.imag); } return complexReal; } public PyComplex(PyType subtype, double r, double i) { super(subtype); real = r; imag = i; } public PyComplex(double r, double i) { this(TYPE, r, i); } public PyComplex(double r) { this(r, 0.0); } public final PyFloat getReal() { return Py.newFloat(real); } public final PyFloat getImag() { return Py.newFloat(imag); } public static String toString(double value) { if (value == Math.floor(value) && value <= Long.MAX_VALUE && value >= Long.MIN_VALUE) { return Long.toString((long) value); } else { return Double.toString(value); } } public String toString() { return complex_toString(); } @ExposedMethod(names = {"__repr__", "__str__"}) final String complex_toString() { if (real == 0.) { return toString(imag) + "j"; } else { if (imag >= 0) { return "(" + toString(real) + "+" + toString(imag) + "j)"; } else { return "(" + toString(real) + "-" + toString(-imag) + "j)"; } } } public int hashCode() { return complex___hash__(); } @ExposedMethod final int complex___hash__() { if (imag == 0) { return new PyFloat(real).hashCode(); } else { long v = Double.doubleToLongBits(real) ^ Double.doubleToLongBits(imag); return (int) v ^ (int) (v >> 32); } } public boolean __nonzero__() { return complex___nonzero__(); } @ExposedMethod final boolean complex___nonzero__() { return real != 0 && imag != 0; } /*public Object __tojava__(Class c) { return super.__tojava__(c); }*/ public int __cmp__(PyObject other) { if (!canCoerce(other)) return -2; PyComplex c = coerce(other); double oreal = c.real; double oimag = c.imag; if (real == oreal && imag == oimag) return 0; if (real != oreal) { return real < oreal ? -1 : 1; } else { return imag < oimag ? -1 : 1; } } /* * @see org.python.core.PyObject#__eq__(org.python.core.PyObject) */ public PyObject __eq__(PyObject other) { return complex___eq__(other); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___eq__(PyObject other) { if (!canCoerce(other)) return null; PyComplex c = coerce(other); return Py.newBoolean(real == c.real && imag == c.imag); } /* * @see org.python.core.PyObject#__ne__(org.python.core.PyObject) */ public PyObject __ne__(PyObject other) { return complex___ne__(other); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___ne__(PyObject other) { if (!canCoerce(other)) return null; PyComplex c = coerce(other); return Py.newBoolean(real != c.real || imag != c.imag); } private PyObject unsupported_comparison(PyObject other) { if (!canCoerce(other)) return null; throw Py.TypeError("cannot compare complex numbers using <, <=, >, >="); } public PyObject __ge__(PyObject other) { return complex___ge__(other); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___ge__(PyObject other) { return unsupported_comparison(other); } public PyObject __gt__(PyObject other) { return complex___gt__(other); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___gt__(PyObject other) { return unsupported_comparison(other); } public PyObject __le__(PyObject other) { return complex___le__(other); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___le__(PyObject other) { return unsupported_comparison(other); } public PyObject __lt__(PyObject other) { return complex___lt__(other); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___lt__(PyObject other) { return unsupported_comparison(other); } public Object __coerce_ex__(PyObject other) { return complex___coerce_ex__(other); } @ExposedMethod final PyObject complex___coerce__(PyObject other) { return adaptToCoerceTuple(complex___coerce_ex__(other)); } /** * Coercion logic for complex. Implemented as a final method to avoid invocation of virtual * methods from the exposed coerce. */ final PyObject complex___coerce_ex__(PyObject other) { if (other instanceof PyComplex) return other; if (other instanceof PyFloat) return new PyComplex(((PyFloat) other).getValue(), 0); if (other instanceof PyInteger) return new PyComplex(((PyInteger) other).getValue(), 0); if (other instanceof PyLong) return new PyComplex(((PyLong) other).doubleValue(), 0); return Py.None; } private final boolean canCoerce(PyObject other) { return other instanceof PyComplex || other instanceof PyFloat || other instanceof PyInteger || other instanceof PyLong; } private final PyComplex coerce(PyObject other) { if (other instanceof PyComplex) return (PyComplex) other; if (other instanceof PyFloat) return new PyComplex(((PyFloat) other).getValue(), 0); if (other instanceof PyInteger) return new PyComplex(((PyInteger) other).getValue(), 0); if (other instanceof PyLong) return new PyComplex(((PyLong) other).doubleValue(), 0); throw Py.TypeError("xxx"); } public PyObject __add__(PyObject right) { return complex___add__(right); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___add__(PyObject right) { if (!canCoerce(right)) return null; PyComplex c = coerce(right); return new PyComplex(real + c.real, imag + c.imag); } public PyObject __radd__(PyObject left) { return complex___radd__(left); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___radd__(PyObject left) { return __add__(left); } private static final PyObject _sub(PyComplex o1, PyComplex o2) { return new PyComplex(o1.real - o2.real, o1.imag - o2.imag); } public PyObject __sub__(PyObject right) { return complex___sub__(right); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___sub__(PyObject right) { if (!canCoerce(right)) return null; return _sub(this, coerce(right)); } public PyObject __rsub__(PyObject left) { return complex___rsub__(left); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___rsub__(PyObject left) { if (!canCoerce(left)) return null; return _sub(coerce(left), this); } private static final PyObject _mul(PyComplex o1, PyComplex o2) { return new PyComplex( o1.real * o2.real - o1.imag * o2.imag, o1.real * o2.imag + o1.imag * o2.real); } public PyObject __mul__(PyObject right) { return complex___mul__(right); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___mul__(PyObject right) { if (!canCoerce(right)) return null; return _mul(this, coerce(right)); } public PyObject __rmul__(PyObject left) { return complex___rmul__(left); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___rmul__(PyObject left) { if (!canCoerce(left)) return null; return _mul(coerce(left), this); } private static final PyObject _div(PyComplex a, PyComplex b) { double abs_breal = b.real < 0 ? -b.real : b.real; double abs_bimag = b.imag < 0 ? -b.imag : b.imag; if (abs_breal >= abs_bimag) { // Divide tops and bottom by b.real if (abs_breal == 0.0) { throw Py.ZeroDivisionError("complex division"); } double ratio = b.imag / b.real; double denom = b.real + b.imag * ratio; return new PyComplex((a.real + a.imag * ratio) / denom, (a.imag - a.real * ratio) / denom); } else { /* divide tops and bottom by b.imag */ double ratio = b.real / b.imag; double denom = b.real * ratio + b.imag; return new PyComplex((a.real * ratio + a.imag) / denom, (a.imag * ratio - a.real) / denom); } } public PyObject __div__(PyObject right) { return complex___div__(right); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___div__(PyObject right) { if (!canCoerce(right)) return null; if (Options.divisionWarning >= 2) Py.warning(Py.DeprecationWarning, "classic complex division"); return _div(this, coerce(right)); } public PyObject __rdiv__(PyObject left) { return complex___rdiv__(left); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___rdiv__(PyObject left) { if (!canCoerce(left)) return null; if (Options.divisionWarning >= 2) Py.warning(Py.DeprecationWarning, "classic complex division"); return _div(coerce(left), this); } public PyObject __floordiv__(PyObject right) { return complex___floordiv__(right); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___floordiv__(PyObject right) { if (!canCoerce(right)) return null; return _divmod(this, coerce(right)).__finditem__(0); } public PyObject __rfloordiv__(PyObject left) { return complex___rfloordiv__(left); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___rfloordiv__(PyObject left) { if (!canCoerce(left)) return null; return _divmod(coerce(left), this).__finditem__(0); } public PyObject __truediv__(PyObject right) { return complex___truediv__(right); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___truediv__(PyObject right) { if (!canCoerce(right)) return null; return _div(this, coerce(right)); } public PyObject __rtruediv__(PyObject left) { return complex___rtruediv__(left); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___rtruediv__(PyObject left) { if (!canCoerce(left)) return null; return _div(coerce(left), this); } public PyObject __mod__(PyObject right) { return complex___mod__(right); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___mod__(PyObject right) { if (!canCoerce(right)) return null; return _mod(this, coerce(right)); } public PyObject __rmod__(PyObject left) { return complex___rmod__(left); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___rmod__(PyObject left) { if (!canCoerce(left)) return null; return _mod(coerce(left), this); } private static PyObject _mod(PyComplex value, PyComplex right) { Py.warning(Py.DeprecationWarning, "complex divmod(), // and % are deprecated"); PyComplex z = (PyComplex) _div(value, right); z.real = Math.floor(z.real); z.imag = 0.0; return value.__sub__(z.__mul__(right)); } public PyObject __divmod__(PyObject right) { return complex___divmod__(right); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___divmod__(PyObject right) { if (!canCoerce(right)) return null; return _divmod(this, coerce(right)); } public PyObject __rdivmod__(PyObject left) { return complex___rdivmod__(left); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___rdivmod__(PyObject left) { if (!canCoerce(left)) return null; return _divmod(coerce(left), this); } private static PyObject _divmod(PyComplex value, PyComplex right) { Py.warning(Py.DeprecationWarning, "complex divmod(), // and % are deprecated"); PyComplex z = (PyComplex) _div(value, right); z.real = Math.floor(z.real); z.imag = 0.0; return new PyTuple(z, value.__sub__(z.__mul__(right))); } private static PyObject ipow(PyComplex value, int iexp) { int pow = iexp; if (pow < 0) pow = -pow; double xr = value.real; double xi = value.imag; double zr = 1; double zi = 0; double tmp; while (pow > 0) { if ((pow & 0x1) != 0) { tmp = zr * xr - zi * xi; zi = zi * xr + zr * xi; zr = tmp; } pow >>= 1; if (pow == 0) break; tmp = xr * xr - xi * xi; xi = xr * xi * 2; xr = tmp; } PyComplex ret = new PyComplex(zr, zi); if (iexp < 0) return new PyComplex(1, 0).__div__(ret); return ret; } public PyObject __pow__(PyObject right, PyObject modulo) { return complex___pow__(right, modulo); } @ExposedMethod(type = MethodType.BINARY, defaults = "null") final PyObject complex___pow__(PyObject right, PyObject modulo) { if (modulo != null) { throw Py.ValueError("complex modulo"); } if (!canCoerce(right)) return null; return _pow(this, coerce(right)); } public PyObject __rpow__(PyObject left) { return complex___rpow__(left); } @ExposedMethod(type = MethodType.BINARY) final PyObject complex___rpow__(PyObject left) { if (!canCoerce(left)) return null; return _pow(coerce(left), this); } public static PyObject _pow(PyComplex value, PyComplex right) { double xr = value.real; double xi = value.imag; double yr = right.real; double yi = right.imag; if (yr == 0 && yi == 0) { return new PyComplex(1, 0); } if (xr == 0 && xi == 0) { if (yi != 0 || yr < 0) { throw Py.ZeroDivisionError("0.0 to a negative or complex power"); } } // Check for integral powers int iexp = (int) yr; if (yi == 0 && yr == iexp && iexp >= -128 && iexp <= 128) { return ipow(value, iexp); } double abs = Math.hypot(xr, xi); double len = Math.pow(abs, yr); double at = Math.atan2(xi, xr); double phase = at * yr; if (yi != 0) { len /= Math.exp(at * yi); phase += yi * Math.log(abs); } return new PyComplex(len * Math.cos(phase), len * Math.sin(phase)); } public PyObject __neg__() { return complex___neg__(); } @ExposedMethod final PyObject complex___neg__() { return new PyComplex(-real, -imag); } public PyObject __pos__() { return complex___pos__(); } @ExposedMethod final PyObject complex___pos__() { return new PyComplex(real, imag); } public PyObject __invert__() { throw Py.TypeError("bad operand type for unary ~"); } public PyObject __abs__() { return complex___abs__(); } @ExposedMethod final PyObject complex___abs__() { return new PyFloat(Math.hypot(real, imag)); } public PyObject __int__() { return complex___int__(); } @ExposedMethod final PyInteger complex___int__() { throw Py.TypeError("can't convert complex to int; use e.g. int(abs(z))"); } public PyObject __long__() { return complex___long__(); } @ExposedMethod final PyObject complex___long__() { throw Py.TypeError("can't convert complex to long; use e.g. long(abs(z))"); } public PyFloat __float__() { return complex___float__(); } @ExposedMethod final PyFloat complex___float__() { throw Py.TypeError("can't convert complex to float; use e.g. abs(z)"); } public PyComplex __complex__() { return new PyComplex(real, imag); } public PyComplex conjugate() { return complex_conjugate(); } @ExposedMethod final PyComplex complex_conjugate() { return new PyComplex(real, -imag); } @ExposedMethod final PyTuple complex___getnewargs__() { return new PyTuple(new PyComplex(real, imag)); } public PyTuple __getnewargs__() { return complex___getnewargs__(); } public boolean isMappingType() { return false; } public boolean isSequenceType() { return false; } }
@ExposedType(name = "list", base = PyObject.class) public class PyList extends PySequenceList implements List { public static final PyType TYPE = PyType.fromClass(PyList.class); private final List<PyObject> list; public volatile int gListAllocatedStatus = -1; public PyList() { this(TYPE); } public PyList(PyType type) { super(type); list = Generic.list(); } private PyList(List list, boolean convert) { super(TYPE); if (!convert) { this.list = list; } else { this.list = Generic.list(); for (Object o : list) { add(o); } } } public PyList(PyType type, PyObject[] elements) { super(type); list = new ArrayList<PyObject>(Arrays.asList(elements)); } public PyList(PyType type, Collection c) { super(type); list = new ArrayList<PyObject>(c.size()); for (Object o : c) { add(o); } } public PyList(PyObject[] elements) { this(TYPE, elements); } public PyList(Collection c) { this(TYPE, c); } public PyList(PyObject o) { this(TYPE); for (PyObject item : o.asIterable()) { list.add(item); } } public static PyList fromList(List<PyObject> list) { return new PyList(list, false); } List<PyObject> getList() { return Collections.unmodifiableList(list); } private static List<PyObject> listify(Iterator<PyObject> iter) { List<PyObject> list = Generic.list(); while (iter.hasNext()) { list.add(iter.next()); } return list; } public PyList(Iterator<PyObject> iter) { this(TYPE, listify(iter)); } @ExposedNew @ExposedMethod(doc = BuiltinDocs.list___init___doc) final void list___init__(PyObject[] args, String[] kwds) { ArgParser ap = new ArgParser("list", args, kwds, new String[] {"sequence"}, 0); PyObject seq = ap.getPyObject(0, null); clear(); if (seq == null) { return; } if (seq instanceof PyList) { list.addAll(((PyList) seq).list); // don't convert } else if (seq instanceof PyTuple) { list.addAll(((PyTuple) seq).getList()); } else { for (PyObject item : seq.asIterable()) { append(item); } } } @Override public int __len__() { return list___len__(); } @ExposedMethod(doc = BuiltinDocs.list___len___doc) final synchronized int list___len__() { return size(); } @Override protected void del(int i) { remove(i); } @Override protected void delRange(int start, int stop) { remove(start, stop); } @Override protected void setslice(int start, int stop, int step, PyObject value) { if (stop < start) { stop = start; } if (value instanceof PyList) { if (value == this) { // copy value = new PyList((PySequence) value); } setslicePyList(start, stop, step, (PyList) value); } else if (value instanceof PySequence) { setsliceIterator(start, stop, step, value.asIterable().iterator()); } else if (value != null && !(value instanceof List)) { value = new PyList(value); setsliceIterator(start, stop, step, value.asIterable().iterator()); } else { List valueList = (List) value.__tojava__(List.class); if (valueList != null && valueList != Py.NoConversion) { setsliceList(start, stop, step, valueList); } } } private final void setsliceList(int start, int stop, int step, List value) { int n = sliceLength(start, stop, step); if (list instanceof ArrayList) { ((ArrayList) list).ensureCapacity(start + n); } ListIterator src = value.listIterator(); for (int j = start; src.hasNext(); j += step) { set(j, src.next()); } } private final void setsliceIterator(int start, int stop, int step, Iterator<PyObject> iter) { if (step == 1) { List<PyObject> insertion = new ArrayList<PyObject>(); if (iter != null) { while (iter.hasNext()) { insertion.add(iter.next()); } } list.subList(start, stop).clear(); list.addAll(start, insertion); } else { int size = list.size(); for (int j = start; iter.hasNext(); j += step) { PyObject item = iter.next(); if (j >= size) { list.add(item); } else { list.set(j, item); } } } } private final void setslicePyList(int start, int stop, int step, PyList other) { if (step == 1) { list.subList(start, stop).clear(); list.addAll(start, other.list); } else { int size = list.size(); Iterator<PyObject> iter = other.list.listIterator(); for (int j = start; iter.hasNext(); j += step) { PyObject item = iter.next(); if (j >= size) { list.add(item); } else { list.set(j, item); } } } } @Override protected synchronized PyObject repeat(int count) { if (count < 0) { count = 0; } int size = size(); int newSize = size * count; if (count != 0 && newSize / count != size) { throw Py.MemoryError(""); } PyObject[] elements = list.toArray(new PyObject[size]); PyObject[] newList = new PyObject[newSize]; for (int i = 0; i < count; i++) { System.arraycopy(elements, 0, newList, i * size, size); } return new PyList(newList); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___ne___doc) final synchronized PyObject list___ne__(PyObject o) { return seq___ne__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___eq___doc) final synchronized PyObject list___eq__(PyObject o) { return seq___eq__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___lt___doc) final synchronized PyObject list___lt__(PyObject o) { return seq___lt__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___le___doc) final synchronized PyObject list___le__(PyObject o) { return seq___le__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___gt___doc) final synchronized PyObject list___gt__(PyObject o) { return seq___gt__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___ge___doc) final synchronized PyObject list___ge__(PyObject o) { return seq___ge__(o); } @Override public PyObject __imul__(PyObject o) { return list___imul__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___imul___doc) final synchronized PyObject list___imul__(PyObject o) { if (!o.isIndex()) { return null; } int count = o.asIndex(Py.OverflowError); int size = size(); if (size == 0 || count == 1) { return this; } if (count < 1) { clear(); return this; } if (size > Integer.MAX_VALUE / count) { throw Py.MemoryError(""); } int newSize = size * count; if (list instanceof ArrayList) { ((ArrayList) list).ensureCapacity(newSize); } List<PyObject> oldList = new ArrayList<PyObject>(list); for (int i = 1; i < count; i++) { list.addAll(oldList); } gListAllocatedStatus = __len__(); // now omit? return this; } @Override public PyObject __mul__(PyObject o) { return list___mul__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___mul___doc) final synchronized PyObject list___mul__(PyObject o) { if (!o.isIndex()) { return null; } return repeat(o.asIndex(Py.OverflowError)); } @Override public PyObject __rmul__(PyObject o) { return list___rmul__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___rmul___doc) final synchronized PyObject list___rmul__(PyObject o) { if (!o.isIndex()) { return null; } return repeat(o.asIndex(Py.OverflowError)); } @Override public PyObject __add__(PyObject o) { return list___add__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___add___doc) final synchronized PyObject list___add__(PyObject o) { PyList sum = null; if (o instanceof PySequenceList && !(o instanceof PyTuple)) { if (o instanceof PyList) { List oList = ((PyList) o).list; List newList = new ArrayList(list.size() + oList.size()); newList.addAll(list); newList.addAll(oList); sum = fromList(newList); } } else if (!(o instanceof PySequenceList)) { // also support adding java lists (but not PyTuple!) Object oList = o.__tojava__(List.class); if (oList != Py.NoConversion && oList != null) { List otherList = (List) oList; sum = new PyList(); sum.list_extend(this); for (Iterator i = otherList.iterator(); i.hasNext(); ) { sum.add(i.next()); } } } return sum; } @Override public PyObject __radd__(PyObject o) { return list___radd__(o); } // XXX: needs __doc__ @ExposedMethod(type = MethodType.BINARY) final synchronized PyObject list___radd__(PyObject o) { // Support adding java.util.List, but prevent adding PyTuple. // 'o' should never be a PyNewList since __add__ is defined. PyList sum = null; if (o instanceof PySequence) { return null; } Object oList = o.__tojava__(List.class); if (oList != Py.NoConversion && oList != null) { sum = new PyList(); sum.addAll((List) oList); sum.extend(this); } return sum; } @ExposedMethod(doc = BuiltinDocs.list___contains___doc) final synchronized boolean list___contains__(PyObject o) { return object___contains__(o); } @ExposedMethod(doc = BuiltinDocs.list___delitem___doc) final synchronized void list___delitem__(PyObject index) { seq___delitem__(index); } @ExposedMethod(doc = BuiltinDocs.list___setitem___doc) final synchronized void list___setitem__(PyObject o, PyObject def) { seq___setitem__(o, def); } @ExposedMethod(doc = BuiltinDocs.list___getitem___doc) final synchronized PyObject list___getitem__(PyObject o) { PyObject ret = seq___finditem__(o); if (ret == null) { throw Py.IndexError("index out of range: " + o); } return ret; } @Override public PyObject __iter__() { return list___iter__(); } @ExposedMethod(doc = BuiltinDocs.list___iter___doc) public synchronized PyObject list___iter__() { return new PyFastSequenceIter(this); } @ExposedMethod(defaults = "null", doc = BuiltinDocs.list___getslice___doc) final synchronized PyObject list___getslice__(PyObject start, PyObject stop, PyObject step) { return seq___getslice__(start, stop, step); } @ExposedMethod(defaults = "null", doc = BuiltinDocs.list___setslice___doc) final synchronized void list___setslice__( PyObject start, PyObject stop, PyObject step, PyObject value) { seq___setslice__(start, stop, step, value); } @ExposedMethod(defaults = "null", doc = BuiltinDocs.list___delslice___doc) final synchronized void list___delslice__(PyObject start, PyObject stop, PyObject step) { seq___delslice__(start, stop, step); } @Override protected String unsupportedopMessage(String op, PyObject o2) { if (op.equals("+")) { return "can only concatenate list (not \"{2}\") to list"; } return super.unsupportedopMessage(op, o2); } public String toString() { return list_toString(); } // XXX: needs __doc__ @ExposedMethod(names = "__repr__") final synchronized String list_toString() { ThreadState ts = Py.getThreadState(); if (!ts.enterRepr(this)) { return "[...]"; } StringBuilder buf = new StringBuilder("["); int length = size(); int i = 0; for (PyObject item : list) { buf.append(item.__repr__().toString()); if (i < length - 1) { buf.append(", "); } i++; } buf.append("]"); ts.exitRepr(this); return buf.toString(); } /** * Add a single element to the end of list. * * @param o the element to add. */ public void append(PyObject o) { list_append(o); } @ExposedMethod(doc = BuiltinDocs.list_append_doc) final synchronized void list_append(PyObject o) { pyadd(o); gListAllocatedStatus = __len__(); } /** * Return the number elements in the list that equals the argument. * * @param o the argument to test for. Testing is done with the <code>==</code> operator. */ public int count(PyObject o) { return list_count(o); } @ExposedMethod(doc = BuiltinDocs.list_count_doc) final synchronized int list_count(PyObject o) { int count = 0; for (PyObject item : list) { if (item.equals(o)) { count++; } } return count; } /** * return smallest index where an element in the list equals the argument. * * @param o the argument to test for. Testing is done with the <code>==</code> operator. */ public int index(PyObject o) { return index(o, 0); } public int index(PyObject o, int start) { return list_index(o, start, size()); } public int index(PyObject o, int start, int stop) { return list_index(o, start, stop); } @ExposedMethod( defaults = {"null", "null"}, doc = BuiltinDocs.list_index_doc) final synchronized int list_index(PyObject o, PyObject start, PyObject stop) { int startInt = start == null ? 0 : PySlice.calculateSliceIndex(start); int stopInt = stop == null ? size() : PySlice.calculateSliceIndex(stop); return list_index(o, startInt, stopInt); } final synchronized int list_index(PyObject o, int start, int stop) { return _index(o, "list.index(x): x not in list", start, stop); } final synchronized int list_index(PyObject o, int start) { return _index(o, "list.index(x): x not in list", start, size()); } final synchronized int list_index(PyObject o) { return _index(o, "list.index(x): x not in list", 0, size()); } private int _index(PyObject o, String message, int start, int stop) { // Follow Python 2.3+ behavior int validStop = boundToSequence(stop); int validStart = boundToSequence(start); int i = validStart; if (validStart <= validStop) { try { for (PyObject item : list.subList(validStart, validStop)) { if (item.equals(o)) { return i; } i++; } } catch (ConcurrentModificationException ex) { throw Py.ValueError(message); } } throw Py.ValueError(message); } /** * Insert the argument element into the list at the specified index. <br> * Same as <code>s[index:index] = [o] if index >= 0</code>. * * @param index the position where the element will be inserted. * @param o the element to insert. */ public void insert(int index, PyObject o) { list_insert(index, o); } @ExposedMethod(doc = BuiltinDocs.list_insert_doc) final synchronized void list_insert(int index, PyObject o) { if (index < 0) { index = Math.max(0, size() + index); } if (index > size()) { index = size(); } pyadd(index, o); gListAllocatedStatus = __len__(); } /** * Remove the first occurence of the argument from the list. The elements arecompared with the * <code>==</code> operator. <br> * Same as <code>del s[s.index(x)]</code> * * @param o the element to search for and remove. */ public void remove(PyObject o) { list_remove(o); } @ExposedMethod(doc = BuiltinDocs.list_remove_doc) final synchronized void list_remove(PyObject o) { del(_index(o, "list.remove(x): x not in list", 0, size())); gListAllocatedStatus = __len__(); } /** * Reverses the items of s in place. The reverse() methods modify the list in place for economy of * space when reversing a large list. It doesn't return the reversed list to remind you of this * side effect. */ public void reverse() { list_reverse(); } @ExposedMethod(doc = BuiltinDocs.list_reverse_doc) final synchronized void list_reverse() { Collections.reverse(list); gListAllocatedStatus = __len__(); } /** Removes and return the last element in the list. */ public PyObject pop() { return pop(-1); } /** * Removes and return the <code>n</code> indexed element in the list. * * @param n the index of the element to remove and return. */ public PyObject pop(int n) { return list_pop(n); } @ExposedMethod(defaults = "-1", doc = BuiltinDocs.list_pop_doc) final synchronized PyObject list_pop(int n) { int length = size(); if (length == 0) { throw Py.IndexError("pop from empty list"); } if (n < 0) { n += length; } if (n < 0 || n >= length) { throw Py.IndexError("pop index out of range"); } PyObject v = list.remove(n); return v; } /** * Append the elements in the argument sequence to the end of the list. <br> * Same as <code>s[len(s):len(s)] = o</code>. * * @param o the sequence of items to append to the list. */ public void extend(PyObject o) { list_extend(o); } @ExposedMethod(doc = BuiltinDocs.list_extend_doc) final synchronized void list_extend(PyObject o) { if (o instanceof PyList) { list.addAll(((PyList) o).list); } else { for (PyObject item : o.asIterable()) { list.add(item); } } gListAllocatedStatus = __len__(); } @Override public PyObject __iadd__(PyObject o) { return list___iadd__(o); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.list___iadd___doc) final synchronized PyObject list___iadd__(PyObject o) { PyType oType = o.getType(); if (oType == TYPE || oType == PyTuple.TYPE || this == o) { extend(fastSequence(o, "argument must be iterable")); return this; } PyObject it; try { it = o.__iter__(); } catch (PyException pye) { if (!pye.match(Py.TypeError)) { throw pye; } return null; } extend(it); return this; } /** * Sort the items of the list in place. The compare argument is a function of two arguments (list * items) which should return -1, 0 or 1 depending on whether the first argument is considered * smaller than, equal to, or larger than the second argument. Note that this slows the sorting * process down considerably; e.g. to sort a list in reverse order it is much faster to use calls * to the methods sort() and reverse() than to use the built-in function sort() with a comparison * function that reverses the ordering of the elements. * * @param compare the comparison function. */ /** * Sort the items of the list in place. Items is compared with the normal relative comparison * operators. */ @ExposedMethod(doc = BuiltinDocs.list_sort_doc) final synchronized void list_sort(PyObject[] args, String[] kwds) { ArgParser ap = new ArgParser("list", args, kwds, new String[] {"cmp", "key", "reverse"}, 0); PyObject cmp = ap.getPyObject(0, Py.None); PyObject key = ap.getPyObject(1, Py.None); PyObject reverse = ap.getPyObject(2, Py.False); sort(cmp, key, reverse); } public void sort(PyObject cmp, PyObject key, PyObject reverse) { boolean bReverse = reverse.__nonzero__(); if (key == Py.None || key == null) { if (cmp == Py.None || cmp == null) { sort(bReverse); } else { sort(cmp, bReverse); } } else { sort(cmp, key, bReverse); } } // a bunch of optimized paths for sort to avoid unnecessary work, such as DSU or checking compare // functions for null public void sort() { sort(false); } private synchronized void sort(boolean reverse) { gListAllocatedStatus = -1; if (reverse) { Collections.reverse(list); // maintain stability of sort by reversing first } Collections.sort(list, new PyObjectDefaultComparator(this)); if (reverse) { Collections.reverse(list); // maintain stability of sort by reversing first } gListAllocatedStatus = __len__(); } private static class PyObjectDefaultComparator implements Comparator<PyObject> { private final PyList list; PyObjectDefaultComparator(PyList list) { this.list = list; } public int compare(PyObject o1, PyObject o2) { int result = o1._cmp(o2); if (this.list.gListAllocatedStatus >= 0) { throw Py.ValueError("list modified during sort"); } return result; } public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof PyObjectDefaultComparator) { return true; } return false; } } public void sort(PyObject compare) { sort(compare, false); } private synchronized void sort(PyObject compare, boolean reverse) { gListAllocatedStatus = -1; if (reverse) { Collections.reverse(list); // maintain stability of sort by reversing first } PyObjectComparator c = new PyObjectComparator(this, compare); Collections.sort(list, c); if (reverse) { Collections.reverse(list); } gListAllocatedStatus = __len__(); } private static class PyObjectComparator implements Comparator<PyObject> { private final PyList list; private final PyObject cmp; PyObjectComparator(PyList list, PyObject cmp) { this.list = list; this.cmp = cmp; } public int compare(PyObject o1, PyObject o2) { int result = cmp.__call__(o1, o2).asInt(); if (this.list.gListAllocatedStatus >= 0) { throw Py.ValueError("list modified during sort"); } return result; } public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof PyObjectComparator) { return cmp.equals(((PyObjectComparator) o).cmp); } return false; } } private static class KV { private final PyObject key; private final PyObject value; KV(PyObject key, PyObject value) { this.key = key; this.value = value; } } private static class KVComparator implements Comparator<KV> { private final PyList list; private final PyObject cmp; KVComparator(PyList list, PyObject cmp) { this.list = list; this.cmp = cmp; } public int compare(KV o1, KV o2) { int result; if (cmp != null && cmp != Py.None) { result = cmp.__call__(o1.key, o2.key).asInt(); } else { result = o1.key._cmp(o2.key); } if (this.list.gListAllocatedStatus >= 0) { throw Py.ValueError("list modified during sort"); } return result; } public boolean equals(Object o) { if (o == this) { return true; } if (o instanceof KVComparator) { return cmp.equals(((KVComparator) o).cmp); } return false; } } private synchronized void sort(PyObject cmp, PyObject key, boolean reverse) { gListAllocatedStatus = -1; int size = list.size(); final ArrayList<KV> decorated = new ArrayList<KV>(size); for (PyObject value : list) { decorated.add(new KV(key.__call__(value), value)); } list.clear(); KVComparator c = new KVComparator(this, cmp); if (reverse) { Collections.reverse(decorated); // maintain stability of sort by reversing first } Collections.sort(decorated, c); if (reverse) { Collections.reverse(decorated); } if (list instanceof ArrayList) { ((ArrayList) list).ensureCapacity(size); } for (KV kv : decorated) { list.add(kv.value); } gListAllocatedStatus = __len__(); } public int hashCode() { return list___hash__(); } @ExposedMethod(doc = BuiltinDocs.list___hash___doc) final synchronized int list___hash__() { throw Py.TypeError(String.format("unhashable type: '%.200s'", getType().fastGetName())); } @Override public PyTuple __getnewargs__() { return new PyTuple(new PyTuple(getArray())); } @Override public void add(int index, Object element) { pyadd(index, Py.java2py(element)); } @Override public boolean add(Object o) { pyadd(Py.java2py(o)); return true; } @Override public synchronized boolean addAll(int index, Collection c) { PyList elements = new PyList(c); return list.addAll(index, elements.list); } @Override public boolean addAll(Collection c) { return addAll(0, c); } @Override public synchronized void clear() { list.clear(); } @Override public synchronized boolean contains(Object o) { return list.contains(Py.java2py(o)); } @Override public synchronized boolean containsAll(Collection c) { if (c instanceof PyList) { return list.containsAll(((PyList) c).list); } else if (c instanceof PyTuple) { return list.containsAll(((PyTuple) c).getList()); } else { return list.containsAll(new PyList(c)); } } @Override public boolean equals(Object other) { if (this == other) { return true; } if (other instanceof PyObject) { synchronized (this) { return _eq((PyObject) other).__nonzero__(); } } if (other instanceof List) { synchronized (this) { return list.equals(other); } } return false; } @Override public synchronized Object get(int index) { return list.get(index).__tojava__(Object.class); } @Override public synchronized PyObject[] getArray() { PyObject a[] = null; return list.toArray(a); } @Override public synchronized int indexOf(Object o) { return list.indexOf(Py.java2py(o)); } @Override public synchronized boolean isEmpty() { return list.isEmpty(); } @Override public Iterator iterator() { return new Iterator() { private final Iterator<PyObject> iter = list.iterator(); public boolean hasNext() { return iter.hasNext(); } public Object next() { return iter.next().__tojava__(Object.class); } public void remove() { iter.remove(); } }; } @Override public synchronized int lastIndexOf(Object o) { return list.lastIndexOf(Py.java2py(o)); } @Override public ListIterator listIterator() { return listIterator(0); } @Override public ListIterator listIterator(final int index) { return new ListIterator() { private final ListIterator<PyObject> iter = list.listIterator(index); public boolean hasNext() { return iter.hasNext(); } public Object next() { return iter.next().__tojava__(Object.class); } public boolean hasPrevious() { return iter.hasPrevious(); } public Object previous() { return iter.previous().__tojava__(Object.class); } public int nextIndex() { return iter.nextIndex(); } public int previousIndex() { return iter.previousIndex(); } public void remove() { iter.remove(); } public void set(Object o) { iter.set(Py.java2py(o)); } public void add(Object o) { iter.add(Py.java2py(o)); } }; } @Override public synchronized void pyadd(int index, PyObject element) { list.add(index, element); } @Override public synchronized boolean pyadd(PyObject o) { list.add(o); return true; } @Override public synchronized PyObject pyget(int index) { return list.get(index); } public synchronized void pyset(int index, PyObject element) { list.set(index, element); } @Override public synchronized Object remove(int index) { return list.remove(index); } @Override public synchronized void remove(int start, int stop) { list.subList(start, stop).clear(); } @Override public synchronized boolean removeAll(Collection c) { if (c instanceof PySequenceList) { return list.removeAll(c); } else { return list.removeAll(new PyList(c)); } } @Override public synchronized boolean retainAll(Collection c) { if (c instanceof PySequenceList) { return list.retainAll(c); } else { return list.retainAll(new PyList(c)); } } @Override public synchronized Object set(int index, Object element) { return list.set(index, Py.java2py(element)).__tojava__(Object.class); } @Override public synchronized int size() { return list.size(); } @Override public synchronized List subList(int fromIndex, int toIndex) { return fromList(list.subList(fromIndex, toIndex)); } @Override public synchronized Object[] toArray() { Object copy[] = list.toArray(); for (int i = 0; i < copy.length; i++) { copy[i] = ((PyObject) copy[i]).__tojava__(Object.class); } return copy; } @Override public synchronized Object[] toArray(Object[] a) { int size = size(); Class<?> type = a.getClass().getComponentType(); if (a.length < size) { a = (Object[]) Array.newInstance(type, size); } for (int i = 0; i < size; i++) { a[i] = list.get(i).__tojava__(type); } if (a.length > size) { for (int i = size; i < a.length; i++) { a[i] = null; } } return a; } protected PyObject getslice(int start, int stop, int step) { if (step > 0 && stop < start) { stop = start; } int n = sliceLength(start, stop, step); List<PyObject> newList; if (step == 1) { newList = new ArrayList<PyObject>(list.subList(start, stop)); } else { newList = new ArrayList<PyObject>(n); for (int i = start, j = 0; j < n; i += step, j++) { newList.add(list.get(i)); } } return fromList(newList); } @Override public synchronized boolean remove(Object o) { return list.remove(Py.java2py(o)); } }
/** A builtin python float. */ @ExposedType(name = "float", doc = BuiltinDocs.float_doc) public class PyFloat extends PyObject { public static final PyType TYPE = PyType.fromClass(PyFloat.class); /** Precisions used by repr() and str(), respectively. */ private static final int PREC_REPR = 17; private static final int PREC_STR = 12; private final double value; public double getValue() { return value; } public PyFloat(PyType subtype, double v) { super(subtype); value = v; } public PyFloat(double v) { this(TYPE, v); } public PyFloat(float v) { this((double) v); } @ExposedNew public static PyObject float_new( PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { ArgParser ap = new ArgParser("float", args, keywords, new String[] {"x"}, 0); PyObject x = ap.getPyObject(0, null); if (x == null) { if (new_.for_type == subtype) { return new PyFloat(0.0); } else { return new PyFloatDerived(subtype, 0.0); } } else { PyFloat floatObject = null; try { floatObject = x.__float__(); } catch (PyException e) { if (e.match(Py.AttributeError)) { // Translate AttributeError to TypeError // XXX: We are using the same message as CPython, even if // it is not strictly correct (instances of types // that implement the __float__ method are also // valid arguments) throw Py.TypeError("float() argument must be a string or a number"); } throw e; } if (new_.for_type == subtype) { return floatObject; } else { return new PyFloatDerived(subtype, floatObject.getValue()); } } } @ExposedGet(name = "real", doc = BuiltinDocs.float_real_doc) public PyObject getReal() { return float___float__(); } @ExposedGet(name = "imag", doc = BuiltinDocs.float_imag_doc) public PyObject getImag() { return Py.newFloat(0.0); } /** Determine if this float is not infinity, nor NaN. */ public boolean isFinite() { return !Double.isInfinite(getValue()) && !Double.isNaN(getValue()); } @Override public String toString() { return __str__().toString(); } @Override public PyString __str__() { return float___str__(); } @ExposedMethod(doc = BuiltinDocs.float___str___doc) final PyString float___str__() { return Py.newString(formatDouble(PREC_STR)); } @Override public PyString __repr__() { return float___repr__(); } @ExposedMethod(doc = BuiltinDocs.float___repr___doc) final PyString float___repr__() { return Py.newString(formatDouble(PREC_REPR)); } private String formatDouble(int precision) { if (Double.isNaN(getValue())) { return "nan"; } String result = String.format("%%.%dg", precision); result = Py.newString(result).__mod__(this).toString(); int i = 0; if (result.startsWith("-")) { i++; } for (; i < result.length(); i++) { if (!Character.isDigit(result.charAt(i))) { break; } } if (i == result.length()) { result += ".0"; } return result; } @Override public int hashCode() { return float___hash__(); } @ExposedMethod(doc = BuiltinDocs.float___hash___doc) final int float___hash__() { double intPart = Math.floor(getValue()); double fractPart = getValue() - intPart; if (fractPart == 0) { if (intPart <= Integer.MAX_VALUE && intPart >= Integer.MIN_VALUE) { return (int) getValue(); } else { return __long__().hashCode(); } } else { long v = Double.doubleToLongBits(getValue()); return (int) v ^ (int) (v >> 32); } } @Override public boolean __nonzero__() { return float___nonzero__(); } @ExposedMethod(doc = BuiltinDocs.float___nonzero___doc) final boolean float___nonzero__() { return getValue() != 0; } @Override public Object __tojava__(Class<?> c) { if (c == Double.TYPE || c == Number.class || c == Double.class || c == Object.class || c == Serializable.class) { return new Double(getValue()); } if (c == Float.TYPE || c == Float.class) { return new Float(getValue()); } return super.__tojava__(c); } @Override public PyObject __eq__(PyObject other) { // preclude _cmp_unsafe's this == other shortcut because NaN != anything, even // itself if (Double.isNaN(getValue())) { return Py.False; } return null; } @Override public PyObject __ne__(PyObject other) { if (Double.isNaN(getValue())) { return Py.True; } return null; } @Override public int __cmp__(PyObject other) { return float___cmp__(other); } // XXX: needs __doc__ @ExposedMethod(type = MethodType.CMP) final int float___cmp__(PyObject other) { double i = getValue(); double j; if (other instanceof PyFloat) { j = ((PyFloat) other).getValue(); } else if (!isFinite()) { // we're infinity: our magnitude exceeds any finite // integer, so it doesn't matter which int we compare i // with. If NaN, similarly. if (other instanceof PyInteger || other instanceof PyLong) { j = 0.0; } else { return -2; } } else if (other instanceof PyInteger) { j = ((PyInteger) other).getValue(); } else if (other instanceof PyLong) { BigDecimal v = new BigDecimal(getValue()); BigDecimal w = new BigDecimal(((PyLong) other).getValue()); return v.compareTo(w); } else { return -2; } if (i < j) { return -1; } else if (i > j) { return 1; } else if (i == j) { return 0; } else { // at least one side is NaN return Double.isNaN(i) ? (Double.isNaN(j) ? 1 : -1) : 1; } } @Override public Object __coerce_ex__(PyObject other) { return float___coerce_ex__(other); } @ExposedMethod(doc = BuiltinDocs.float___coerce___doc) final PyObject float___coerce__(PyObject other) { return adaptToCoerceTuple(float___coerce_ex__(other)); } /** * Coercion logic for float. Implemented as a final method to avoid invocation of virtual methods * from the exposed coerce. */ final Object float___coerce_ex__(PyObject other) { if (other instanceof PyFloat) { return other; } else { if (other instanceof PyInteger) { return new PyFloat((double) ((PyInteger) other).getValue()); } if (other instanceof PyLong) { return new PyFloat(((PyLong) other).doubleValue()); } else { return Py.None; } } } private static boolean canCoerce(PyObject other) { return other instanceof PyFloat || other instanceof PyInteger || other instanceof PyLong; } private static double coerce(PyObject other) { if (other instanceof PyFloat) { return ((PyFloat) other).getValue(); } else if (other instanceof PyInteger) { return ((PyInteger) other).getValue(); } else if (other instanceof PyLong) { return ((PyLong) other).doubleValue(); } else { throw Py.TypeError("xxx"); } } @Override public PyObject __add__(PyObject right) { return float___add__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___add___doc) final PyObject float___add__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); return new PyFloat(getValue() + rightv); } @Override public PyObject __radd__(PyObject left) { return float___radd__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___radd___doc) final PyObject float___radd__(PyObject left) { return __add__(left); } @Override public PyObject __sub__(PyObject right) { return float___sub__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___sub___doc) final PyObject float___sub__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); return new PyFloat(getValue() - rightv); } @Override public PyObject __rsub__(PyObject left) { return float___rsub__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rsub___doc) final PyObject float___rsub__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); return new PyFloat(leftv - getValue()); } @Override public PyObject __mul__(PyObject right) { return float___mul__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___mul___doc) final PyObject float___mul__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); return new PyFloat(getValue() * rightv); } @Override public PyObject __rmul__(PyObject left) { return float___rmul__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rmul___doc) final PyObject float___rmul__(PyObject left) { return __mul__(left); } @Override public PyObject __div__(PyObject right) { return float___div__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___div___doc) final PyObject float___div__(PyObject right) { if (!canCoerce(right)) { return null; } if (Options.divisionWarning >= 2) { Py.warning(Py.DeprecationWarning, "classic float division"); } double rightv = coerce(right); if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(getValue() / rightv); } @Override public PyObject __rdiv__(PyObject left) { return float___rdiv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rdiv___doc) final PyObject float___rdiv__(PyObject left) { if (!canCoerce(left)) { return null; } if (Options.divisionWarning >= 2) { Py.warning(Py.DeprecationWarning, "classic float division"); } double leftv = coerce(left); if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(leftv / getValue()); } @Override public PyObject __floordiv__(PyObject right) { return float___floordiv__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___floordiv___doc) final PyObject float___floordiv__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(Math.floor(getValue() / rightv)); } @Override public PyObject __rfloordiv__(PyObject left) { return float___rfloordiv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rfloordiv___doc) final PyObject float___rfloordiv__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(Math.floor(leftv / getValue())); } @Override public PyObject __truediv__(PyObject right) { return float___truediv__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___truediv___doc) final PyObject float___truediv__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(getValue() / rightv); } @Override public PyObject __rtruediv__(PyObject left) { return float___rtruediv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rtruediv___doc) final PyObject float___rtruediv__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(leftv / getValue()); } private static double modulo(double x, double y) { if (y == 0) { throw Py.ZeroDivisionError("float modulo"); } double z = Math.IEEEremainder(x, y); if (z * y < 0) { z += y; } return z; } @Override public PyObject __mod__(PyObject right) { return float___mod__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___mod___doc) final PyObject float___mod__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); return new PyFloat(modulo(getValue(), rightv)); } @Override public PyObject __rmod__(PyObject left) { return float___rmod__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rmod___doc) final PyObject float___rmod__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); return new PyFloat(modulo(leftv, getValue())); } @Override public PyObject __divmod__(PyObject right) { return float___divmod__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___divmod___doc) final PyObject float___divmod__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } double z = Math.floor(getValue() / rightv); return new PyTuple(new PyFloat(z), new PyFloat(getValue() - z * rightv)); } @Override public PyObject __rdivmod__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } double z = Math.floor(leftv / getValue()); return new PyTuple(new PyFloat(z), new PyFloat(leftv - z * getValue())); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rdivmod___doc) final PyObject float___rdivmod__(PyObject left) { return __rdivmod__(left); } @Override public PyObject __pow__(PyObject right, PyObject modulo) { return float___pow__(right, modulo); } @ExposedMethod(type = MethodType.BINARY, defaults = "null", doc = BuiltinDocs.float___pow___doc) final PyObject float___pow__(PyObject right, PyObject modulo) { if (!canCoerce(right)) { return null; } if (modulo != null) { throw Py.TypeError("pow() 3rd argument not allowed unless all arguments are integers"); } return _pow(getValue(), coerce(right), modulo); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rpow___doc) final PyObject float___rpow__(PyObject left) { return __rpow__(left); } @Override public PyObject __rpow__(PyObject left) { if (!canCoerce(left)) { return null; } return _pow(coerce(left), getValue(), null); } private static PyFloat _pow(double value, double iw, PyObject modulo) { // Rely completely on Java's pow function if (iw == 0) { if (modulo != null) { return new PyFloat(modulo(1.0, coerce(modulo))); } return new PyFloat(1.0); } if (value == 0.0) { if (iw < 0.0) { throw Py.ZeroDivisionError("0.0 cannot be raised to a negative power"); } return new PyFloat(0); } if (value < 0 && iw != Math.floor(iw)) { throw Py.ValueError("negative number cannot be raised to a fractional power"); } double ret = Math.pow(value, iw); return new PyFloat(modulo == null ? ret : modulo(ret, coerce(modulo))); } @Override public PyObject __neg__() { return float___neg__(); } @ExposedMethod(doc = BuiltinDocs.float___neg___doc) final PyObject float___neg__() { return new PyFloat(-getValue()); } @Override public PyObject __pos__() { return float___pos__(); } @ExposedMethod(doc = BuiltinDocs.float___pos___doc) final PyObject float___pos__() { return float___float__(); } @Override public PyObject __invert__() { throw Py.TypeError("bad operand type for unary ~"); } @Override public PyObject __abs__() { return float___abs__(); } @ExposedMethod(doc = BuiltinDocs.float___abs___doc) final PyObject float___abs__() { if (getValue() < 0) { return float___neg__(); } return float___float__(); } @Override public PyObject __int__() { return float___int__(); } @ExposedMethod(doc = BuiltinDocs.float___int___doc) final PyObject float___int__() { if (getValue() <= Integer.MAX_VALUE && getValue() >= Integer.MIN_VALUE) { return new PyInteger((int) getValue()); } return __long__(); } @Override public PyObject __long__() { return float___long__(); } @ExposedMethod(doc = BuiltinDocs.float___long___doc) final PyObject float___long__() { return new PyLong(getValue()); } @Override public PyFloat __float__() { return float___float__(); } @ExposedMethod(doc = BuiltinDocs.float___float___doc) final PyFloat float___float__() { return getType() == TYPE ? this : Py.newFloat(getValue()); } @Override public PyComplex __complex__() { return new PyComplex(getValue(), 0.); } @ExposedMethod(doc = BuiltinDocs.float___getnewargs___doc) final PyTuple float___getnewargs__() { return new PyTuple(new PyObject[] {new PyFloat(getValue())}); } @Override public PyTuple __getnewargs__() { return float___getnewargs__(); } @Override public double asDouble() { return getValue(); } @Override public boolean isNumberType() { return true; } // standard singleton issues apply here to __getformat__/__setformat__, // but this is what Python demands public enum Format { UNKNOWN("unknown"), BE("IEEE, big-endian"), LE("IEEE, little-endian"); private final String format; Format(String format) { this.format = format; } public String format() { return format; } } // subset of IEEE-754, the JVM is big-endian public static volatile Format double_format = Format.BE; public static volatile Format float_format = Format.BE; @ExposedClassMethod(doc = BuiltinDocs.float___getformat___doc) public static String float___getformat__(PyType type, String typestr) { if ("double".equals(typestr)) { return double_format.format(); } else if ("float".equals(typestr)) { return float_format.format(); } else { throw Py.ValueError("__getformat__() argument 1 must be 'double' or 'float'"); } } @ExposedClassMethod(doc = BuiltinDocs.float___setformat___doc) public static void float___setformat__(PyType type, String typestr, String format) { Format new_format = null; if (!"double".equals(typestr) && !"float".equals(typestr)) { throw Py.ValueError("__setformat__() argument 1 must be 'double' or 'float'"); } if (Format.LE.format().equals(format)) { throw Py.ValueError( String.format( "can only set %s format to 'unknown' or the " + "detected platform value", typestr)); } else if (Format.BE.format().equals(format)) { new_format = Format.BE; } else if (Format.UNKNOWN.format().equals(format)) { new_format = Format.UNKNOWN; } else { throw Py.ValueError( "__setformat__() argument 2 must be 'unknown', " + "'IEEE, little-endian' or 'IEEE, big-endian'"); } if (new_format != null) { if ("double".equals(typestr)) { double_format = new_format; } else { float_format = new_format; } } } }
/** A builtin python float. */ @Untraversable @ExposedType(name = "float", doc = BuiltinDocs.float_doc) public class PyFloat extends PyObject { public static final PyType TYPE = PyType.fromClass(PyFloat.class); /** Format specification used by repr(). */ static final Spec SPEC_REPR = InternalFormat.fromText(" >r"); /** Format specification used by str(). */ static final Spec SPEC_STR = Spec.NUMERIC; /** Constant float(0). */ static final PyFloat ZERO = new PyFloat(0.0); /** Constant float(1). */ static final PyFloat ONE = new PyFloat(1.0); /** Constant float("nan"). */ static final PyFloat NAN = new PyFloat(Double.NaN); private final double value; public double getValue() { return value; } public PyFloat(PyType subtype, double v) { super(subtype); value = v; } public PyFloat(double v) { this(TYPE, v); } public PyFloat(float v) { this((double) v); } @ExposedNew public static PyObject float_new( PyNewWrapper new_, boolean init, PyType subtype, PyObject[] args, String[] keywords) { ArgParser ap = new ArgParser("float", args, keywords, new String[] {"x"}, 0); PyObject x = ap.getPyObject(0, null); if (x == null) { if (new_.for_type == subtype) { return ZERO; } else { return new PyFloatDerived(subtype, 0.0); } } else { PyFloat floatObject = null; try { floatObject = x.__float__(); } catch (PyException e) { if (e.match(Py.AttributeError)) { // Translate AttributeError to TypeError // XXX: We are using the same message as CPython, even if // it is not strictly correct (instances of types // that implement the __float__ method are also // valid arguments) throw Py.TypeError("float() argument must be a string or a number"); } throw e; } if (new_.for_type == subtype) { return floatObject; } else { return new PyFloatDerived(subtype, floatObject.getValue()); } } } @ExposedGet(name = "real", doc = BuiltinDocs.float_real_doc) public PyObject getReal() { return float___float__(); } @ExposedGet(name = "imag", doc = BuiltinDocs.float_imag_doc) public PyObject getImag() { return ZERO; } @ExposedClassMethod(doc = BuiltinDocs.float_fromhex_doc) public static PyObject float_fromhex(PyType type, PyObject o) { // XXX: I'm sure this could be shortened/simplified, but Double.parseDouble() takes // non-hex strings and requires the form 0xNUMBERpNUMBER for hex input which // causes extra complexity here. String message = "invalid hexadecimal floating-point string"; boolean negative = false; PyString s = o.__str__(); String value = s.getString().trim().toLowerCase(); if (value.length() == 0) { throw Py.ValueError(message); } else if (value.equals("nan") || value.equals("-nan") || value.equals("+nan")) { return NAN; } else if (value.equals("inf") || value.equals("infinity") || value.equals("+inf") || value.equals("+infinity")) { return new PyFloat(Double.POSITIVE_INFINITY); } else if (value.equals("-inf") || value.equals("-infinity")) { return new PyFloat(Double.NEGATIVE_INFINITY); } // Strip and record + or - if (value.charAt(0) == '-') { value = value.substring(1); negative = true; } else if (value.charAt(0) == '+') { value = value.substring(1); } if (value.length() == 0) { throw Py.ValueError(message); } // Append 0x if not present. if (!value.startsWith("0x") && !value.startsWith("0X")) { value = "0x" + value; } // reattach - if needed. if (negative) { value = "-" + value; } // Append p if not present. if (value.indexOf('p') == -1) { value = value + "p0"; } try { double d = Double.parseDouble(value); if (Double.isInfinite(d)) { throw Py.OverflowError("hexadecimal value too large to represent as a float"); } return new PyFloat(d); } catch (NumberFormatException n) { throw Py.ValueError(message); } } // @ExposedClassMethod(doc = BuiltinDocs.float_hex_doc) // public static PyObject float_hex(PyType type, double value) { // return new PyString(Double.toHexString(value)); // } private String pyHexString(Double f) { // Simply rewrite Java hex repr to expected Python values; not // the most efficient, but we don't expect this to be a hot // spot in our code either String java_hex = Double.toHexString(getValue()); if (java_hex.equals("Infinity")) { return "inf"; } else if (java_hex.equals("-Infinity")) { return "-inf"; } else if (java_hex.equals("NaN")) { return "nan"; } else if (java_hex.equals("0x0.0p0")) { return "0x0.0p+0"; } else if (java_hex.equals("-0x0.0p0")) { return "-0x0.0p+0"; } // replace hex rep of MpE to conform with Python such that // 1. M is padded to 16 digits (ignoring a leading -) // 2. Mp+E if E>=0 // example: result of 42.0.hex() is translated from // 0x1.5p5 to 0x1.5000000000000p+5 int len = java_hex.length(); boolean start_exponent = false; StringBuilder py_hex = new StringBuilder(len + 1); int padding = f > 0 ? 17 : 18; for (int i = 0; i < len; i++) { char c = java_hex.charAt(i); if (c == 'p') { for (int pad = i; pad < padding; pad++) { py_hex.append('0'); } start_exponent = true; } else if (start_exponent) { if (c != '-') { py_hex.append('+'); } start_exponent = false; } py_hex.append(c); } return py_hex.toString(); } @ExposedMethod(doc = BuiltinDocs.float_hex_doc) public PyObject float_hex() { return new PyString(pyHexString(getValue())); } /** Determine if this float is not infinity, nor NaN. */ public boolean isFinite() { return !Double.isInfinite(getValue()) && !Double.isNaN(getValue()); } @Override public String toString() { return __str__().toString(); } @Override public PyString __str__() { return float___str__(); } @ExposedMethod(doc = BuiltinDocs.float___str___doc) final PyString float___str__() { return Py.newString(formatDouble(SPEC_STR)); } @Override public PyString __repr__() { return float___repr__(); } @ExposedMethod(doc = BuiltinDocs.float___repr___doc) final PyString float___repr__() { return Py.newString(formatDouble(SPEC_REPR)); } /** * Format this float according to the specification passed in. Supports <code>__str__</code> and * <code>__repr__</code>. * * @param spec parsed format specification string * @return formatted value */ private String formatDouble(Spec spec) { FloatFormatter f = new FloatFormatter(spec); return f.format(value).getResult(); } @Override public int hashCode() { return float___hash__(); } @ExposedMethod(doc = BuiltinDocs.float___hash___doc) final int float___hash__() { double value = getValue(); if (Double.isInfinite(value)) { return value < 0 ? -271828 : 314159; } else if (Double.isNaN(value)) { return 0; } double intPart = Math.floor(value); double fractPart = value - intPart; if (fractPart == 0) { if (intPart <= Integer.MAX_VALUE && intPart >= Integer.MIN_VALUE) { return (int) value; } else { return __long__().hashCode(); } } else { long v = Double.doubleToLongBits(getValue()); return (int) v ^ (int) (v >> 32); } } @Override public boolean __nonzero__() { return float___nonzero__(); } @ExposedMethod(doc = BuiltinDocs.float___nonzero___doc) final boolean float___nonzero__() { return getValue() != 0; } @Override public Object __tojava__(Class<?> c) { if (c == Double.TYPE || c == Number.class || c == Double.class || c == Object.class || c == Serializable.class) { return new Double(getValue()); } else if (c == Float.TYPE || c == Float.class) { return new Float(getValue()); } return super.__tojava__(c); } @Override public PyObject __eq__(PyObject other) { // preclude _cmp_unsafe's this == other shortcut because NaN != anything, even // itself if (Double.isNaN(getValue())) { return Py.False; } return null; } @Override public PyObject __ne__(PyObject other) { if (Double.isNaN(getValue())) { return Py.True; } return null; } @Override public PyObject __gt__(PyObject other) { // NaN > anything is always false. if (Double.isNaN(getValue())) { return Py.False; } return null; } @Override public PyObject __ge__(PyObject other) { // NaN >= anything is always false. if (Double.isNaN(getValue())) { return Py.False; } return null; } @Override public PyObject __lt__(PyObject other) { // NaN < anything is always false. if (Double.isNaN(getValue())) { return Py.False; } return null; } @Override public PyObject __le__(PyObject other) { // NaN >= anything is always false. if (Double.isNaN(getValue())) { return Py.False; } return null; } @Override public int __cmp__(PyObject other) { return float___cmp__(other); } // XXX: needs __doc__ @ExposedMethod(type = MethodType.CMP) final int float___cmp__(PyObject other) { double i = getValue(); double j; if (other instanceof PyFloat) { j = ((PyFloat) other).getValue(); } else if (!isFinite()) { // we're infinity: our magnitude exceeds any finite // integer, so it doesn't matter which int we compare i // with. If NaN, similarly. if (other instanceof PyInteger || other instanceof PyLong) { j = 0.0; } else { return -2; } } else if (other instanceof PyInteger) { j = ((PyInteger) other).getValue(); } else if (other instanceof PyLong) { BigDecimal v = new BigDecimal(getValue()); BigDecimal w = new BigDecimal(((PyLong) other).getValue()); return v.compareTo(w); } else { return -2; } if (i < j) { return -1; } else if (i > j) { return 1; } else if (i == j) { return 0; } else { // at least one side is NaN return Double.isNaN(i) ? (Double.isNaN(j) ? 1 : -1) : 1; } } @Override public Object __coerce_ex__(PyObject other) { return float___coerce_ex__(other); } @ExposedMethod(doc = BuiltinDocs.float___coerce___doc) final PyObject float___coerce__(PyObject other) { return adaptToCoerceTuple(float___coerce_ex__(other)); } /** * Coercion logic for float. Implemented as a final method to avoid invocation of virtual methods * from the exposed coerce. */ final Object float___coerce_ex__(PyObject other) { if (other instanceof PyFloat) { return other; } else if (other instanceof PyInteger) { return new PyFloat((double) ((PyInteger) other).getValue()); } else if (other instanceof PyLong) { return new PyFloat(((PyLong) other).doubleValue()); } else { return Py.None; } } private static boolean canCoerce(PyObject other) { return other instanceof PyFloat || other instanceof PyInteger || other instanceof PyLong; } private static double coerce(PyObject other) { if (other instanceof PyFloat) { return ((PyFloat) other).getValue(); } else if (other instanceof PyInteger) { return ((PyInteger) other).getValue(); } else if (other instanceof PyLong) { return ((PyLong) other).doubleValue(); } else { throw Py.TypeError("xxx"); } } @Override public PyObject __add__(PyObject right) { return float___add__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___add___doc) final PyObject float___add__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); return new PyFloat(getValue() + rightv); } @Override public PyObject __radd__(PyObject left) { return float___radd__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___radd___doc) final PyObject float___radd__(PyObject left) { return __add__(left); } @Override public PyObject __sub__(PyObject right) { return float___sub__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___sub___doc) final PyObject float___sub__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); return new PyFloat(getValue() - rightv); } @Override public PyObject __rsub__(PyObject left) { return float___rsub__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rsub___doc) final PyObject float___rsub__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); return new PyFloat(leftv - getValue()); } @Override public PyObject __mul__(PyObject right) { return float___mul__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___mul___doc) final PyObject float___mul__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); return new PyFloat(getValue() * rightv); } @Override public PyObject __rmul__(PyObject left) { return float___rmul__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rmul___doc) final PyObject float___rmul__(PyObject left) { return __mul__(left); } @Override public PyObject __div__(PyObject right) { return float___div__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___div___doc) final PyObject float___div__(PyObject right) { if (!canCoerce(right)) { return null; } else if (Options.division_warning >= 2) { Py.warning(Py.DeprecationWarning, "classic float division"); } double rightv = coerce(right); if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(getValue() / rightv); } @Override public PyObject __rdiv__(PyObject left) { return float___rdiv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rdiv___doc) final PyObject float___rdiv__(PyObject left) { if (!canCoerce(left)) { return null; } else if (Options.division_warning >= 2) { Py.warning(Py.DeprecationWarning, "classic float division"); } double leftv = coerce(left); if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(leftv / getValue()); } @Override public PyObject __floordiv__(PyObject right) { return float___floordiv__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___floordiv___doc) final PyObject float___floordiv__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(Math.floor(getValue() / rightv)); } @Override public PyObject __rfloordiv__(PyObject left) { return float___rfloordiv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rfloordiv___doc) final PyObject float___rfloordiv__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(Math.floor(leftv / getValue())); } @Override public PyObject __truediv__(PyObject right) { return float___truediv__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___truediv___doc) final PyObject float___truediv__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(getValue() / rightv); } @Override public PyObject __rtruediv__(PyObject left) { return float___rtruediv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rtruediv___doc) final PyObject float___rtruediv__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } return new PyFloat(leftv / getValue()); } /** * Python % operator: y = n*x + z. The modulo operator always yields a result with the same sign * as its second operand (or zero). (Compare <code>java.Math.IEEEremainder</code>) * * @param x dividend * @param y divisor * @return <code>x % y</code> */ private static double modulo(double x, double y) { if (y == 0.0) { throw Py.ZeroDivisionError("float modulo"); } else { double z = x % y; if (z == 0.0) { // Has to be same sign as y (even when zero). return Math.copySign(z, y); } else if ((z > 0.0) == (y > 0.0)) { // z has same sign as y, as it must. return z; } else { // Note abs(z) < abs(y) and opposite sign. return z + y; } } } @Override public PyObject __mod__(PyObject right) { return float___mod__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___mod___doc) final PyObject float___mod__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); return new PyFloat(modulo(getValue(), rightv)); } @Override public PyObject __rmod__(PyObject left) { return float___rmod__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rmod___doc) final PyObject float___rmod__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); return new PyFloat(modulo(leftv, getValue())); } @Override public PyObject __divmod__(PyObject right) { return float___divmod__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___divmod___doc) final PyObject float___divmod__(PyObject right) { if (!canCoerce(right)) { return null; } double rightv = coerce(right); if (rightv == 0) { throw Py.ZeroDivisionError("float division"); } double z = Math.floor(getValue() / rightv); return new PyTuple(new PyFloat(z), new PyFloat(getValue() - z * rightv)); } @Override public PyObject __rdivmod__(PyObject left) { if (!canCoerce(left)) { return null; } double leftv = coerce(left); if (getValue() == 0) { throw Py.ZeroDivisionError("float division"); } double z = Math.floor(leftv / getValue()); return new PyTuple(new PyFloat(z), new PyFloat(leftv - z * getValue())); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rdivmod___doc) final PyObject float___rdivmod__(PyObject left) { return __rdivmod__(left); } @Override public PyObject __pow__(PyObject right, PyObject modulo) { return float___pow__(right, modulo); } @ExposedMethod( type = MethodType.BINARY, defaults = "null", // doc = BuiltinDocs.float___pow___doc) final PyObject float___pow__(PyObject right, PyObject modulo) { if (!canCoerce(right)) { return null; } modulo = (modulo == Py.None) ? null : modulo; if (modulo != null) { throw Py.TypeError("pow() 3rd argument not allowed unless all arguments are integers"); } else { return _pow(getValue(), coerce(right)); } } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.float___rpow___doc) final PyObject float___rpow__(PyObject left) { return __rpow__(left); } @Override public PyObject __rpow__(PyObject left) { if (!canCoerce(left)) { return null; } else { return _pow(coerce(left), getValue()); } } private static PyFloat _pow(double v, double w) { /* * This code was translated from the CPython implementation at v2.7.8 by progressively * removing cases that could be delegated to Java. Jython differs from CPython in that where * C pow() overflows, Java pow() returns inf (observed on Windows). This is not subject to * regression tests, so we take it as an allowable platform dependency. All other * differences in Java Math.pow() are trapped below and Python behaviour is enforced. */ if (w == 0) { // v**0 is 1, even 0**0 return ONE; } else if (Double.isNaN(v)) { // nan**w = nan, unless w == 0 return NAN; } else if (Double.isNaN(w)) { // v**nan = nan, unless v == 1; 1**nan = 1 if (v == 1.0) { return ONE; } else { return NAN; } } else if (Double.isInfinite(w)) { /* * In Java Math pow(1,inf) = pow(-1,inf) = pow(1,-inf) = pow(-1,-inf) = nan, but in * Python they are all 1. */ if (v == 1.0 || v == -1.0) { return ONE; } } else if (v == 0.0) { // 0**w is an error if w is negative. if (w < 0.0) { throw Py.ZeroDivisionError("0.0 cannot be raised to a negative power"); } } else if (!Double.isInfinite(v) && v < 0.0) { if (w != Math.floor(w)) { throw Py.ValueError("negative number cannot be raised to a fractional power"); } } // In all cases not caught above we can entrust the calculation to Java return new PyFloat(Math.pow(v, w)); } @Override public PyObject __neg__() { return float___neg__(); } @ExposedMethod(doc = BuiltinDocs.float___neg___doc) final PyObject float___neg__() { return new PyFloat(-getValue()); } @Override public PyObject __pos__() { return float___pos__(); } @ExposedMethod(doc = BuiltinDocs.float___pos___doc) final PyObject float___pos__() { return float___float__(); } @Override public PyObject __invert__() { throw Py.TypeError("bad operand type for unary ~"); } @Override public PyObject __abs__() { return float___abs__(); } @ExposedMethod(doc = BuiltinDocs.float___abs___doc) final PyObject float___abs__() { return new PyFloat(Math.abs(getValue())); } @Override public PyObject __int__() { return float___int__(); } /** Smallest value that cannot be represented as an int */ private static double INT_LONG_BOUNDARY = -(double) Integer.MIN_VALUE; // 2^31 @ExposedMethod(doc = BuiltinDocs.float___int___doc) final PyObject float___int__() { double v = getValue(); if (v < INT_LONG_BOUNDARY && v > -(INT_LONG_BOUNDARY + 1.0)) { // v will fit into an int (when rounded towards zero). return new PyInteger((int) v); } else { return __long__(); } } @Override public PyObject __long__() { return float___long__(); } @ExposedMethod(doc = BuiltinDocs.float___long___doc) final PyObject float___long__() { return new PyLong(getValue()); } @Override public PyFloat __float__() { return float___float__(); } @ExposedMethod(doc = BuiltinDocs.float___float___doc) final PyFloat float___float__() { return getType() == TYPE ? this : Py.newFloat(getValue()); } @Override public PyObject __trunc__() { return float___trunc__(); } @ExposedMethod(doc = BuiltinDocs.float___trunc___doc) final PyObject float___trunc__() { if (Double.isNaN(value)) { throw Py.ValueError("cannot convert float NaN to integer"); } if (Double.isInfinite(value)) { throw Py.OverflowError("cannot convert float infinity to integer"); } if (value < Integer.MAX_VALUE) { return new PyInteger((int) value); } else if (value < Long.MAX_VALUE) { return new PyLong((long) value); } BigDecimal d = new BigDecimal(value); return new PyLong(d.toBigInteger()); } @Override public PyObject conjugate() { return float_conjugate(); } @ExposedMethod(doc = BuiltinDocs.float_conjugate_doc) final PyObject float_conjugate() { return this; } public boolean is_integer() { return float_is_integer(); } @ExposedMethod(doc = BuiltinDocs.float_is_integer_doc) final boolean float_is_integer() { if (Double.isInfinite(value)) { return false; } return Math.floor(value) == value; } @Override public PyComplex __complex__() { return new PyComplex(getValue(), 0.); } @ExposedMethod(doc = BuiltinDocs.float___getnewargs___doc) final PyTuple float___getnewargs__() { return new PyTuple(new PyObject[] {new PyFloat(getValue())}); } @Override public PyTuple __getnewargs__() { return float___getnewargs__(); } @Override public PyObject __format__(PyObject formatSpec) { return float___format__(formatSpec); } @ExposedMethod(doc = BuiltinDocs.float___format___doc) final PyObject float___format__(PyObject formatSpec) { // Parse the specification Spec spec = InternalFormat.fromText(formatSpec, "__format__"); // Get a formatter for the specification FloatFormatter f = prepareFormatter(spec); if (f != null) { // Bytes mode if formatSpec argument is not unicode. f.setBytes(!(formatSpec instanceof PyUnicode)); // Convert as per specification. f.format(value); // Return a result that has the same type (str or unicode) as the formatSpec argument. return f.pad().getPyResult(); } else { // The type code was not recognised in prepareFormatter throw Formatter.unknownFormat(spec.type, "float"); } } /** * Common code for PyFloat, {@link PyInteger} and {@link PyLong} to prepare a {@link * FloatFormatter} from a parsed specification. The object returned has format method {@link * FloatFormatter#format(double)}. * * @param spec a parsed PEP-3101 format specification. * @return a formatter ready to use, or null if the type is not a floating point format type. * @throws PyException(ValueError) if the specification is faulty. */ @SuppressWarnings("fallthrough") static FloatFormatter prepareFormatter(Spec spec) { // Slight differences between format types switch (spec.type) { case 'n': if (spec.grouping) { throw Formatter.notAllowed("Grouping", "float", spec.type); } // Fall through case Spec.NONE: case 'e': case 'f': case 'g': case 'E': case 'F': case 'G': case '%': // Check for disallowed parts of the specification if (spec.alternate) { throw FloatFormatter.alternateFormNotAllowed("float"); } // spec may be incomplete. The defaults are those commonly used for numeric formats. spec = spec.withDefaults(Spec.NUMERIC); return new FloatFormatter(spec); default: return null; } } @ExposedMethod(doc = BuiltinDocs.float_as_integer_ratio_doc) public PyTuple as_integer_ratio() { if (Double.isInfinite(value)) { throw Py.OverflowError("Cannot pass infinity to float.as_integer_ratio."); } if (Double.isNaN(value)) { throw Py.ValueError("Cannot pass NaN to float.as_integer_ratio."); } PyTuple frexp = math.frexp(value); double float_part = ((Double) frexp.get(0)).doubleValue(); int exponent = ((Integer) frexp.get(1)).intValue(); for (int i = 0; i < 300 && float_part != Math.floor(float_part); i++) { float_part *= 2.0; exponent--; } /* * self == float_part * 2**exponent exactly and float_part is integral. If FLT_RADIX != 2, * the 300 steps may leave a tiny fractional part to be truncated by PyLong_FromDouble(). */ PyLong numerator = new PyLong(float_part); PyLong denominator = new PyLong(1); PyLong py_exponent = new PyLong(Math.abs(exponent)); py_exponent = (PyLong) denominator.__lshift__(py_exponent); if (exponent > 0) { numerator = new PyLong(numerator.getValue().multiply(py_exponent.getValue())); } else { denominator = py_exponent; } return new PyTuple(numerator, denominator); } @Override public double asDouble() { return getValue(); } @Override public boolean isNumberType() { return true; } // standard singleton issues apply here to __getformat__/__setformat__, // but this is what Python demands public enum Format { UNKNOWN("unknown"), BE("IEEE, big-endian"), LE("IEEE, little-endian"); private final String format; Format(String format) { this.format = format; } public String format() { return format; } } // subset of IEEE-754, the JVM is big-endian public static volatile Format double_format = Format.BE; public static volatile Format float_format = Format.BE; @ExposedClassMethod(doc = BuiltinDocs.float___getformat___doc) public static String float___getformat__(PyType type, String typestr) { if ("double".equals(typestr)) { return double_format.format(); } else if ("float".equals(typestr)) { return float_format.format(); } else { throw Py.ValueError("__getformat__() argument 1 must be 'double' or 'float'"); } } @ExposedClassMethod(doc = BuiltinDocs.float___setformat___doc) public static void float___setformat__(PyType type, String typestr, String format) { Format new_format = null; if (!"double".equals(typestr) && !"float".equals(typestr)) { throw Py.ValueError("__setformat__() argument 1 must be 'double' or 'float'"); } if (Format.LE.format().equals(format)) { throw Py.ValueError( String.format( "can only set %s format to 'unknown' or the " + "detected platform value", typestr)); } else if (Format.BE.format().equals(format)) { new_format = Format.BE; } else if (Format.UNKNOWN.format().equals(format)) { new_format = Format.UNKNOWN; } else { throw Py.ValueError( "__setformat__() argument 2 must be 'unknown', " + "'IEEE, little-endian' or 'IEEE, big-endian'"); } if (new_format != null) { if ("double".equals(typestr)) { double_format = new_format; } else { float_format = new_format; } } } }