Ejemplo n.º 1
0
@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));
  }
}
Ejemplo n.º 2
0
/** 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;
  }
}
Ejemplo n.º 3
0
/** 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 &gt;= 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));
  }
}
Ejemplo n.º 5
0
/** 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;
      }
    }
  }
}
Ejemplo n.º 6
0
/** 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;
      }
    }
  }
}