All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.python.core.PyComplex Maven / Gradle / Ivy

Go to download

Jython is an implementation of the high-level, dynamic, object-oriented language Python written in 100% Pure Java, and seamlessly integrated with the Java platform. It thus allows you to run Python on any Java platform.

There is a newer version: 2.7.4
Show newest version
// Copyright (c) Corporation for National Research Initiatives
// Copyright (c) Jython Developers
package org.python.core;

import org.python.core.stringlib.FloatFormatter;
import org.python.core.stringlib.InternalFormat;
import org.python.core.stringlib.InternalFormat.Formatter;
import org.python.core.stringlib.InternalFormat.Spec;
import org.python.expose.ExposedGet;
import org.python.expose.ExposedMethod;
import org.python.expose.ExposedNew;
import org.python.expose.ExposedType;
import org.python.expose.MethodType;

/**
 * A builtin python complex number
 */
@Untraversable
@ExposedType(name = "complex", doc = BuiltinDocs.complex_doc)
public class PyComplex extends PyObject {

    public static final PyType TYPE = PyType.fromClass(PyComplex.class);

    /** Format specification used by repr(). */
    static final Spec SPEC_REPR = InternalFormat.fromText(" >r"); // but also minFracDigits=0
    /** Format specification used by str() and none-format. (As CPython, but is that right?) */
    static final Spec SPEC_STR = InternalFormat.fromText(" >.12g");

    static PyComplex J = new PyComplex(0, 1.);

    public static final PyComplex Inf = new PyComplex(Double.POSITIVE_INFINITY,
            Double.POSITIVE_INFINITY);
    public static final PyComplex NaN = new PyComplex(Double.NaN, Double.NaN);

    @ExposedGet(doc = BuiltinDocs.complex_real_doc)
    public double real;

    @ExposedGet(doc = BuiltinDocs.complex_imag_doc)
    public double imag;

    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);
    }

    @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;
        } else if (real instanceof PyString) {
            if (imag != null) {
                throw Py.TypeError("complex() can't take second arg if first is a string");
            }
            return real.__complex__();
        } else 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 (!pye.match(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 (pye.match(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 (pye.match(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;
        if (complexReal.imag == 0.0) {
            // necessary if complexImag is -0.0, given that adding 0.0 + -0.0 is 0.0
            complexReal.imag = complexImag.real;
        } else {
            complexReal.imag += complexImag.real;
        }
        if (new_.for_type != subtype) {
            complexReal = new PyComplexDerived(subtype, complexReal.real, complexReal.imag);
        }
        return complexReal;
    }

    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);
        }
    }

    @Override
    public String toString() {
        return __str__().toString();
    }

    @Override
    public PyString __str__() {
        return complex___str__();
    }

    @ExposedMethod(doc = BuiltinDocs.complex___str___doc)
    final PyString complex___str__() {
        return Py.newString(formatComplex(SPEC_STR));
    }

    @Override
    public PyString __repr__() {
        return complex___repr__();
    }

    @ExposedMethod(doc = BuiltinDocs.complex___repr___doc)
    final PyString complex___repr__() {
        return Py.newString(formatComplex(SPEC_REPR));
    }

    /**
     * Format this complex according to the specification passed in. Supports __str__
     * and __repr__, and none-format.
     * 

* In general, the output is surrounded in parentheses, like "(12.34+24.68j)". * However, if the real part is zero (but not negative zero), only the imaginary part is * printed, and without parentheses like "24.68j". The number format specification * passed in is used for the real and imaginary parts individually, with padding to width * afterwards (if the specification requires it). * * @param spec parsed format specification string * @return formatted value */ private String formatComplex(Spec spec) { int size = 2 * FloatFormatter.size(spec) + 3; // 2 floats + "(j)" FloatFormatter f = new FloatFormatter(new StringBuilder(size), spec); f.setBytes(true); // Even in r-format, complex strips *all* the trailing zeros. f.setMinFracDigits(0); if (Double.doubleToLongBits(real) == 0L) { // Real part is truly zero: show no real part. f.format(imag).append('j'); } else { f.append('(').format(real).format(imag, "+").append("j)"); } return f.pad().getResult(); } @Override public int hashCode() { return complex___hash__(); } @ExposedMethod(doc = BuiltinDocs.complex___hash___doc) 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); } } @Override public boolean __nonzero__() { return complex___nonzero__(); } @ExposedMethod(doc = BuiltinDocs.complex___nonzero___doc) final boolean complex___nonzero__() { return real != 0 || imag != 0; } @Override 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; } } @Override public PyObject __eq__(PyObject other) { return complex___eq__(other); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___eq___doc) final PyObject complex___eq__(PyObject other) { switch (eq_helper(other)) { case 0: return Py.False; case 1: return Py.True; default: return null; } } /** * Helper for {@link #complex___eq__(PyObject)} and {@link #complex___ne__(PyObject)}. * * @param other to compare for equality with this * @return 0 = false, 1 = true, 2 = don't know (ask the other object) */ private int eq_helper(PyObject other) { // We only deal with primitive types here. All others delegate upwards (return 2). boolean equal; if (other instanceof PyComplex) { PyComplex c = ((PyComplex)other); equal = (this.real == c.real && this.imag == c.imag); } else if (other instanceof PyFloat) { PyFloat f = ((PyFloat)other); equal = (this.imag == 0.0 && this.real == f.getValue()); } else if (other instanceof PyInteger || other instanceof PyLong) { if (this.imag == 0.0) { // The imaginary part is zero: other object primitive might equal the real part. double r = this.real; if (Double.isInfinite(r) || Double.isNaN(r)) { // No integer primitive type can be infinite, and NaN never equals anything. equal = false; } else { // Delegate the logic to PyFloat PyFloat f = new PyFloat(r); equal = (f.float___cmp__(other) == 0); } } else { // No other primitive can have an imaginary part. equal = false; } } else { // other is not one of the types we know how to deal with. return 2; } // Only "known" cases end here: translate to return code return equal ? 1 : 0; } @Override public PyObject __ne__(PyObject other) { return complex___ne__(other); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___ne___doc) final PyObject complex___ne__(PyObject other) { switch (eq_helper(other)) { case 0: return Py.True; case 1: return Py.False; default: return null; } } private PyObject unsupported_comparison(PyObject other) { if (!canCoerce(other)) { return null; } throw Py.TypeError("cannot compare complex numbers using <, <=, >, >="); } @Override public PyObject __ge__(PyObject other) { return complex___ge__(other); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___ge___doc) final PyObject complex___ge__(PyObject other) { return unsupported_comparison(other); } @Override public PyObject __gt__(PyObject other) { return complex___gt__(other); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___gt___doc) final PyObject complex___gt__(PyObject other) { return unsupported_comparison(other); } @Override public PyObject __le__(PyObject other) { return complex___le__(other); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___le___doc) final PyObject complex___le__(PyObject other) { return unsupported_comparison(other); } @Override public PyObject __lt__(PyObject other) { return complex___lt__(other); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___lt___doc) final PyObject complex___lt__(PyObject other) { return unsupported_comparison(other); } @Override public Object __coerce_ex__(PyObject other) { return complex___coerce_ex__(other); } @ExposedMethod(doc = BuiltinDocs.complex___coerce___doc) 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; } else if (other instanceof PyFloat) { return new PyComplex(((PyFloat)other).getValue(), 0); } else if (other instanceof PyInteger) { return new PyComplex(((PyInteger)other).getValue(), 0); } else 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; } else if (other instanceof PyFloat) { return new PyComplex(((PyFloat)other).getValue(), 0); } else if (other instanceof PyInteger) { return new PyComplex(((PyInteger)other).getValue(), 0); } else if (other instanceof PyLong) { return new PyComplex(((PyLong)other).doubleValue(), 0); } throw Py.TypeError("xxx"); } @Override public PyObject __add__(PyObject right) { return complex___add__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___add___doc) final PyObject complex___add__(PyObject right) { if (!canCoerce(right)) { return null; } PyComplex c = coerce(right); return new PyComplex(real + c.real, imag + c.imag); } @Override public PyObject __radd__(PyObject left) { return complex___radd__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___radd___doc) final PyObject complex___radd__(PyObject left) { return __add__(left); } private final static PyObject _sub(PyComplex o1, PyComplex o2) { return new PyComplex(o1.real - o2.real, o1.imag - o2.imag); } @Override public PyObject __sub__(PyObject right) { return complex___sub__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___sub___doc) final PyObject complex___sub__(PyObject right) { if (!canCoerce(right)) { return null; } return _sub(this, coerce(right)); } @Override public PyObject __rsub__(PyObject left) { return complex___rsub__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___rsub___doc) final PyObject complex___rsub__(PyObject left) { if (!canCoerce(left)) { return null; } return _sub(coerce(left), this); } private final static 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); } @Override public PyObject __mul__(PyObject right) { return complex___mul__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___mul___doc) final PyObject complex___mul__(PyObject right) { if (!canCoerce(right)) { return null; } return _mul(this, coerce(right)); } @Override public PyObject __rmul__(PyObject left) { return complex___rmul__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___rmul___doc) final PyObject complex___rmul__(PyObject left) { if (!canCoerce(left)) { return null; } return _mul(coerce(left), this); } private final static 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); } } @Override public PyObject __div__(PyObject right) { return complex___div__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___div___doc) final PyObject complex___div__(PyObject right) { if (!canCoerce(right)) { return null; } else if (Options.division_warning >= 2) { Py.warning(Py.DeprecationWarning, "classic complex division"); } return _div(this, coerce(right)); } @Override public PyObject __rdiv__(PyObject left) { return complex___rdiv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___rdiv___doc) final PyObject complex___rdiv__(PyObject left) { if (!canCoerce(left)) { return null; } else if (Options.division_warning >= 2) { Py.warning(Py.DeprecationWarning, "classic complex division"); } return _div(coerce(left), this); } @Override public PyObject __floordiv__(PyObject right) { return complex___floordiv__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___floordiv___doc) final PyObject complex___floordiv__(PyObject right) { if (!canCoerce(right)) { return null; } return _divmod(this, coerce(right)).__finditem__(0); } @Override public PyObject __rfloordiv__(PyObject left) { return complex___rfloordiv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___rfloordiv___doc) final PyObject complex___rfloordiv__(PyObject left) { if (!canCoerce(left)) { return null; } return _divmod(coerce(left), this).__finditem__(0); } // Special case __tojava__ for bug 1605, since we broke it with our support for faux floats. @Override public Object __tojava__(Class c) { if (c.isInstance(this)) { return this; } return Py.NoConversion; } @Override public PyObject __truediv__(PyObject right) { return complex___truediv__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___truediv___doc) final PyObject complex___truediv__(PyObject right) { if (!canCoerce(right)) { return null; } return _div(this, coerce(right)); } @Override public PyObject __rtruediv__(PyObject left) { return complex___rtruediv__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___rtruediv___doc) final PyObject complex___rtruediv__(PyObject left) { if (!canCoerce(left)) { return null; } return _div(coerce(left), this); } @Override public PyObject __mod__(PyObject right) { return complex___mod__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___mod___doc) final PyObject complex___mod__(PyObject right) { if (!canCoerce(right)) { return null; } return _mod(this, coerce(right)); } @Override public PyObject __rmod__(PyObject left) { return complex___rmod__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___rmod___doc) 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)); } @Override public PyObject __divmod__(PyObject right) { return complex___divmod__(right); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___divmod___doc) final PyObject complex___divmod__(PyObject right) { if (!canCoerce(right)) { return null; } return _divmod(this, coerce(right)); } @Override public PyObject __rdivmod__(PyObject left) { return complex___rdivmod__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___rdivmod___doc) 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; } @Override public PyObject __pow__(PyObject right, PyObject modulo) { return complex___pow__(right, modulo); } @ExposedMethod(type = MethodType.BINARY, defaults = "null", doc = BuiltinDocs.complex___pow___doc) final PyObject complex___pow__(PyObject right, PyObject modulo) { if (modulo != null) { throw Py.ValueError("complex modulo"); } else if (!canCoerce(right)) { return null; } return _pow(this, coerce(right)); } @Override public PyObject __rpow__(PyObject left) { return complex___rpow__(left); } @ExposedMethod(type = MethodType.BINARY, doc = BuiltinDocs.complex___rpow___doc) 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)); } @Override public PyObject __neg__() { return complex___neg__(); } @ExposedMethod(doc = BuiltinDocs.complex___neg___doc) final PyObject complex___neg__() { return new PyComplex(-real, -imag); } @Override public PyObject __pos__() { return complex___pos__(); } @ExposedMethod(doc = BuiltinDocs.complex___pos___doc) final PyObject complex___pos__() { return getType() == TYPE ? this : new PyComplex(real, imag); } @Override public PyObject __invert__() { throw Py.TypeError("bad operand type for unary ~"); } @Override public PyObject __abs__() { return complex___abs__(); } @ExposedMethod(doc = BuiltinDocs.complex___abs___doc) final PyObject complex___abs__() { double mag = Math.hypot(real, imag); if (Double.isInfinite(mag) && !(Double.isInfinite(real) || Double.isInfinite(imag))) { // In these circumstances Math.hypot quietly returns inf, but Python should raise. throw Py.OverflowError("absolute value too large"); } return new PyFloat(mag); } @Override public PyObject __int__() { return complex___int__(); } @ExposedMethod(doc = BuiltinDocs.complex___int___doc) final PyInteger complex___int__() { throw Py.TypeError("can't convert complex to int; use e.g. int(abs(z))"); } @Override public PyObject __long__() { return complex___long__(); } @ExposedMethod(doc = BuiltinDocs.complex___long___doc) final PyObject complex___long__() { throw Py.TypeError("can't convert complex to long; use e.g. long(abs(z))"); } @Override public PyFloat __float__() { return complex___float__(); } @ExposedMethod(doc = BuiltinDocs.complex___float___doc) final PyFloat complex___float__() { throw Py.TypeError("can't convert complex to float; use e.g. abs(z)"); } @Override public PyComplex __complex__() { return new PyComplex(real, imag); } @Override public PyComplex conjugate() { return complex_conjugate(); } @ExposedMethod(doc = BuiltinDocs.complex_conjugate_doc) final PyComplex complex_conjugate() { return new PyComplex(real, -imag); } @ExposedMethod(doc = BuiltinDocs.complex___getnewargs___doc) final PyTuple complex___getnewargs__() { return new PyTuple(new PyFloat(real), new PyFloat(imag)); } @Override public PyTuple __getnewargs__() { return complex___getnewargs__(); } @Override public PyObject __format__(PyObject formatSpec) { return complex___format__(formatSpec); } @ExposedMethod(doc = BuiltinDocs.complex___format___doc) final PyObject complex___format__(PyObject formatSpec) { // Parse the specification Spec spec = InternalFormat.fromText(formatSpec, "__format__"); // fromText will have thrown if formatSpecStr is not a PyString (including PyUnicode) PyString formatSpecStr = (PyString)formatSpec; String result; // Validate the specification and detect the special case for none-format switch (checkSpecification(spec)) { case 0: // None-format // In none-format, we take the default type and precision from __str__. spec = spec.withDefaults(SPEC_STR); // And then we use the __str__ mechanism to get parentheses or real 0 elision. result = formatComplex(spec); break; case 1: // Floating-point formats // In any other format, defaults are those commonly used for numeric formats. spec = spec.withDefaults(Spec.NUMERIC); int size = 2 * FloatFormatter.size(spec) + 1; // 2 floats + "j" FloatFormatter f = new FloatFormatter(new StringBuilder(size), spec); f.setBytes(!(formatSpecStr instanceof PyUnicode)); // Convert both parts as per specification f.format(real).format(imag, "+").append('j'); result = f.pad().getResult(); break; default: // The type code was not recognised throw Formatter.unknownFormat(spec.type, "complex"); } // Wrap the result in the same type as the format string return formatSpecStr.createInstance(result); } /** * Validate a parsed specification, for PyComplex, returning 0 if it is a valid * none-format specification, 1 if it is a valid float specification, and some other value if it * not a valid type. If it has any other faults (e.g. alternate form was specified) the method * raises a descriptive exception. * * @param spec a parsed PEP-3101 format specification. * @return 0, 1, or other value for none-format, a float format, or incorrect type. * @throws PyException {@code ValueError} if the specification is faulty. */ @SuppressWarnings("fallthrough") private static int checkSpecification(Spec spec) { // Slight differences between format types switch (spec.type) { case 'n': if (spec.grouping) { throw Formatter.notAllowed("Grouping", "complex", spec.type); } // Fall through case Spec.NONE: case 'e': case 'f': case 'g': case 'E': case 'F': case 'G': // Check for disallowed parts of the specification if (spec.alternate) { throw FloatFormatter.alternateFormNotAllowed("complex"); } else if (spec.fill == '0') { throw FloatFormatter.zeroPaddingNotAllowed("complex"); } else if (spec.align == '=') { throw FloatFormatter.alignmentNotAllowed('=', "complex"); } else { return (spec.type == Spec.NONE) ? 0 : 1; } default: // spec.type is invalid for complex return 2; } } @Override public boolean isNumberType() { return true; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy