[Jython-checkins] jython: Fix str.__complex__() to accept all valid inputs.
jeff.allen
jython-checkins at python.org
Wed Dec 31 02:41:06 CET 2014
https://hg.python.org/jython/rev/5409ad3e93f4
changeset: 7482:5409ad3e93f4
user: Jeff Allen <ja.py at farowl.co.uk>
date: Sat Dec 20 09:51:58 2014 +0000
summary:
Fix str.__complex__() to accept all valid inputs.
Fixes a number of test failures in test_complex.
files:
Lib/test/test_complex.py | 220 -------------
src/org/python/core/PyString.java | 302 ++++++++---------
2 files changed, 149 insertions(+), 373 deletions(-)
diff --git a/Lib/test/test_complex.py b/Lib/test/test_complex.py
--- a/Lib/test/test_complex.py
+++ b/Lib/test/test_complex.py
@@ -220,7 +220,6 @@
def test_conjugate(self):
self.assertClose(complex(5.3, 9.8).conjugate(), 5.3-9.8j)
- @unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
def test_constructor(self):
class OS:
def __init__(self, value): self.value = value
@@ -264,24 +263,16 @@
self.assertAlmostEqual(complex(), 0)
self.assertAlmostEqual(complex("-1"), -1)
self.assertAlmostEqual(complex("+1"), +1)
- #FIXME: these are not working in Jython.
self.assertAlmostEqual(complex("(1+2j)"), 1+2j)
self.assertAlmostEqual(complex("(1.3+2.2j)"), 1.3+2.2j)
- # ]
self.assertAlmostEqual(complex("3.14+1J"), 3.14+1j)
- #FIXME: these are not working in Jython.
self.assertAlmostEqual(complex(" ( +3.14-6J )"), 3.14-6j)
self.assertAlmostEqual(complex(" ( +3.14-J )"), 3.14-1j)
self.assertAlmostEqual(complex(" ( +3.14+j )"), 3.14+1j)
- # ]
self.assertAlmostEqual(complex("J"), 1j)
- #FIXME: this is not working in Jython.
self.assertAlmostEqual(complex("( j )"), 1j)
- # ]
self.assertAlmostEqual(complex("+J"), 1j)
- #FIXME: this is not working in Jython.
self.assertAlmostEqual(complex("( -j)"), -1j)
- # ]
self.assertAlmostEqual(complex('1e-500'), 0.0 + 0.0j)
self.assertAlmostEqual(complex('-1e-500j'), 0.0 - 0.0j)
self.assertAlmostEqual(complex('-1e-500+1e-500j'), -0.0 + 0.0j)
@@ -301,9 +292,7 @@
return atan2(x, -1.)
self.assertEqual(split_zeros(complex(1., 0.).imag), split_zeros(0.))
- #FIXME: this is not working in Jython.
self.assertEqual(split_zeros(complex(1., -0.).imag), split_zeros(-0.))
- # ]
self.assertEqual(split_zeros(complex(0., 1.).real), split_zeros(0.))
self.assertEqual(split_zeros(complex(-0., 1.).real), split_zeros(-0.))
@@ -340,199 +329,19 @@
self.assertRaises(ValueError, complex, "(1+2j)123")
if test_support.have_unicode:
self.assertRaises(ValueError, complex, unicode("x"))
- #FIXME: these are raising wrong errors in Jython.
self.assertRaises(ValueError, complex, "1j+2")
self.assertRaises(ValueError, complex, "1e1ej")
self.assertRaises(ValueError, complex, "1e++1ej")
self.assertRaises(ValueError, complex, ")1+2j(")
- # ]
# the following three are accepted by Python 2.6
- #FIXME: these are raising wrong errors in Jython.
self.assertRaises(ValueError, complex, "1..1j")
self.assertRaises(ValueError, complex, "1.11.1j")
self.assertRaises(ValueError, complex, "1e1.1j")
- # ]
- #FIXME: not working in Jython.
if test_support.have_unicode:
# check that complex accepts long unicode strings
self.assertEqual(type(complex(unicode("1"*500))), complex)
- # ]
-
- class EvilExc(Exception):
- pass
-
- class evilcomplex:
- def __complex__(self):
- raise EvilExc
-
- self.assertRaises(EvilExc, complex, evilcomplex())
-
- class float2:
- def __init__(self, value):
- self.value = value
- def __float__(self):
- return self.value
-
- self.assertAlmostEqual(complex(float2(42.)), 42)
- self.assertAlmostEqual(complex(real=float2(17.), imag=float2(23.)), 17+23j)
- self.assertRaises(TypeError, complex, float2(None))
-
- class complex0(complex):
- """Test usage of __complex__() when inheriting from 'complex'"""
- def __complex__(self):
- return 42j
-
- class complex1(complex):
- """Test usage of __complex__() with a __new__() method"""
- def __new__(self, value=0j):
- return complex.__new__(self, 2*value)
- def __complex__(self):
- return self
-
- class complex2(complex):
- """Make sure that __complex__() calls fail if anything other than a
- complex is returned"""
- def __complex__(self):
- return None
-
- self.assertAlmostEqual(complex(complex0(1j)), 42j)
- self.assertAlmostEqual(complex(complex1(1j)), 2j)
- self.assertRaises(TypeError, complex, complex2(1j))
-
- def test_constructor_jy(self):
- # These are the parts of test_constructor that work in Jython.
- # Delete this test when test_constructor skip is removed.
- class OS:
- def __init__(self, value): self.value = value
- def __complex__(self): return self.value
- class NS(object):
- def __init__(self, value): self.value = value
- def __complex__(self): return self.value
- self.assertEqual(complex(OS(1+10j)), 1+10j)
- self.assertEqual(complex(NS(1+10j)), 1+10j)
- self.assertRaises(TypeError, complex, OS(None))
- self.assertRaises(TypeError, complex, NS(None))
-
- self.assertAlmostEqual(complex("1+10j"), 1+10j)
- self.assertAlmostEqual(complex(10), 10+0j)
- self.assertAlmostEqual(complex(10.0), 10+0j)
- self.assertAlmostEqual(complex(10L), 10+0j)
- self.assertAlmostEqual(complex(10+0j), 10+0j)
- self.assertAlmostEqual(complex(1,10), 1+10j)
- self.assertAlmostEqual(complex(1,10L), 1+10j)
- self.assertAlmostEqual(complex(1,10.0), 1+10j)
- self.assertAlmostEqual(complex(1L,10), 1+10j)
- self.assertAlmostEqual(complex(1L,10L), 1+10j)
- self.assertAlmostEqual(complex(1L,10.0), 1+10j)
- self.assertAlmostEqual(complex(1.0,10), 1+10j)
- self.assertAlmostEqual(complex(1.0,10L), 1+10j)
- self.assertAlmostEqual(complex(1.0,10.0), 1+10j)
- self.assertAlmostEqual(complex(3.14+0j), 3.14+0j)
- self.assertAlmostEqual(complex(3.14), 3.14+0j)
- self.assertAlmostEqual(complex(314), 314.0+0j)
- self.assertAlmostEqual(complex(314L), 314.0+0j)
- self.assertAlmostEqual(complex(3.14+0j, 0j), 3.14+0j)
- self.assertAlmostEqual(complex(3.14, 0.0), 3.14+0j)
- self.assertAlmostEqual(complex(314, 0), 314.0+0j)
- self.assertAlmostEqual(complex(314L, 0L), 314.0+0j)
- self.assertAlmostEqual(complex(0j, 3.14j), -3.14+0j)
- self.assertAlmostEqual(complex(0.0, 3.14j), -3.14+0j)
- self.assertAlmostEqual(complex(0j, 3.14), 3.14j)
- self.assertAlmostEqual(complex(0.0, 3.14), 3.14j)
- self.assertAlmostEqual(complex("1"), 1+0j)
- self.assertAlmostEqual(complex("1j"), 1j)
- self.assertAlmostEqual(complex(), 0)
- self.assertAlmostEqual(complex("-1"), -1)
- self.assertAlmostEqual(complex("+1"), +1)
- #FIXME: these are not working in Jython.
- #self.assertAlmostEqual(complex("(1+2j)"), 1+2j)
- #self.assertAlmostEqual(complex("(1.3+2.2j)"), 1.3+2.2j)
- self.assertAlmostEqual(complex("3.14+1J"), 3.14+1j)
- #FIXME: these are not working in Jython.
- #self.assertAlmostEqual(complex(" ( +3.14-6J )"), 3.14-6j)
- #self.assertAlmostEqual(complex(" ( +3.14-J )"), 3.14-1j)
- #self.assertAlmostEqual(complex(" ( +3.14+j )"), 3.14+1j)
- self.assertAlmostEqual(complex("J"), 1j)
- #FIXME: this is not working in Jython.
- #self.assertAlmostEqual(complex("( j )"), 1j)
- self.assertAlmostEqual(complex("+J"), 1j)
- #FIXME: this is not working in Jython.
- #self.assertAlmostEqual(complex("( -j)"), -1j)
- self.assertAlmostEqual(complex('1e-500'), 0.0 + 0.0j)
- self.assertAlmostEqual(complex('-1e-500j'), 0.0 - 0.0j)
- self.assertAlmostEqual(complex('-1e-500+1e-500j'), -0.0 + 0.0j)
-
- class complex2(complex): pass
- self.assertAlmostEqual(complex(complex2(1+1j)), 1+1j)
- self.assertAlmostEqual(complex(real=17, imag=23), 17+23j)
- self.assertAlmostEqual(complex(real=17+23j), 17+23j)
- self.assertAlmostEqual(complex(real=17+23j, imag=23), 17+46j)
- self.assertAlmostEqual(complex(real=1+2j, imag=3+4j), -3+5j)
-
- # check that the sign of a zero in the real or imaginary part
- # is preserved when constructing from two floats. (These checks
- # are harmless on systems without support for signed zeros.)
- def split_zeros(x):
- """Function that produces different results for 0. and -0."""
- return atan2(x, -1.)
-
- self.assertEqual(split_zeros(complex(1., 0.).imag), split_zeros(0.))
- #FIXME: this is not working in Jython.
- #self.assertEqual(split_zeros(complex(1., -0.).imag), split_zeros(-0.))
- self.assertEqual(split_zeros(complex(0., 1.).real), split_zeros(0.))
- self.assertEqual(split_zeros(complex(-0., 1.).real), split_zeros(-0.))
-
- c = 3.14 + 1j
- self.assertTrue(complex(c) is c)
- del c
-
- self.assertRaises(TypeError, complex, "1", "1")
- self.assertRaises(TypeError, complex, 1, "1")
-
- if test_support.have_unicode:
- self.assertEqual(complex(unicode(" 3.14+J ")), 3.14+1j)
-
- # SF bug 543840: complex(string) accepts strings with \0
- # Fixed in 2.3.
- self.assertRaises(ValueError, complex, '1+1j\0j')
-
- self.assertRaises(TypeError, int, 5+3j)
- self.assertRaises(TypeError, long, 5+3j)
- self.assertRaises(TypeError, float, 5+3j)
- self.assertRaises(ValueError, complex, "")
- self.assertRaises(TypeError, complex, None)
- self.assertRaises(ValueError, complex, "\0")
- self.assertRaises(ValueError, complex, "3\09")
- self.assertRaises(TypeError, complex, "1", "2")
- self.assertRaises(TypeError, complex, "1", 42)
- self.assertRaises(TypeError, complex, 1, "2")
- self.assertRaises(ValueError, complex, "1+")
- self.assertRaises(ValueError, complex, "1+1j+1j")
- self.assertRaises(ValueError, complex, "--")
- self.assertRaises(ValueError, complex, "(1+2j")
- self.assertRaises(ValueError, complex, "1+2j)")
- self.assertRaises(ValueError, complex, "1+(2j)")
- self.assertRaises(ValueError, complex, "(1+2j)123")
- if test_support.have_unicode:
- self.assertRaises(ValueError, complex, unicode("x"))
- #FIXME: these are raising wrong errors in Jython.
- #self.assertRaises(ValueError, complex, "1j+2")
- #self.assertRaises(ValueError, complex, "1e1ej")
- #self.assertRaises(ValueError, complex, "1e++1ej")
- #self.assertRaises(ValueError, complex, ")1+2j(")
-
- # the following three are accepted by Python 2.6
- #FIXME: these are raising wrong errors in Jython.
- #self.assertRaises(ValueError, complex, "1..1j")
- #self.assertRaises(ValueError, complex, "1.11.1j")
- #self.assertRaises(ValueError, complex, "1e1.1j")
-
- #FIXME: not working in Jython.
- #if test_support.have_unicode:
- # # check that complex accepts long unicode strings
- # self.assertEqual(type(complex(unicode("1"*500))), complex)
class EvilExc(Exception):
pass
@@ -641,7 +450,6 @@
for num in nums:
self.assertAlmostEqual((num.real**2 + num.imag**2) ** 0.5, abs(num))
- @unittest.skipIf(test_support.is_jython, "FIXME: str.__complex__ not working in Jython")
def test_repr(self):
self.assertEqual(repr(1+6j), '(1+6j)')
self.assertEqual(repr(1-6j), '(1-6j)')
@@ -665,32 +473,6 @@
self.assertEqual(repr(complex(0, -INF)), "-infj")
self.assertEqual(repr(complex(0, NAN)), "nanj")
- def test_repr_jy(self):
- # These are just the cases that Jython can do from test_repr
- # Delete this test when test_repr passes
- self.assertEqual(repr(1+6j), '(1+6j)')
- self.assertEqual(repr(1-6j), '(1-6j)')
-
- self.assertNotEqual(repr(-(1+0j)), '(-1+-0j)')
-
- # Fails to round-trip:
-# self.assertEqual(1-6j,complex(repr(1-6j)))
-# self.assertEqual(1+6j,complex(repr(1+6j)))
-# self.assertEqual(-6j,complex(repr(-6j)))
-# self.assertEqual(6j,complex(repr(6j)))
-
- self.assertEqual(repr(complex(1., INF)), "(1+infj)")
- self.assertEqual(repr(complex(1., -INF)), "(1-infj)")
- self.assertEqual(repr(complex(INF, 1)), "(inf+1j)")
- self.assertEqual(repr(complex(-INF, INF)), "(-inf+infj)")
- self.assertEqual(repr(complex(NAN, 1)), "(nan+1j)")
- self.assertEqual(repr(complex(1, NAN)), "(1+nanj)")
- self.assertEqual(repr(complex(NAN, NAN)), "(nan+nanj)")
-
- self.assertEqual(repr(complex(0, INF)), "infj")
- self.assertEqual(repr(complex(0, -INF)), "-infj")
- self.assertEqual(repr(complex(0, NAN)), "nanj")
-
def test_neg(self):
self.assertEqual(-(1+6j), -1-6j)
@@ -729,7 +511,6 @@
@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
"test requires IEEE 754 doubles")
- @unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
def test_overflow(self):
self.assertEqual(complex("1e500"), complex(INF, 0.0))
self.assertEqual(complex("-1e500j"), complex(0.0, -INF))
@@ -737,7 +518,6 @@
@unittest.skipUnless(float.__getformat__("double").startswith("IEEE"),
"test requires IEEE 754 doubles")
- @unittest.skipIf(test_support.is_jython, "FIXME: not working in Jython")
def test_repr_roundtrip(self):
vals = [0.0, 1e-500, 1e-315, 1e-200, 0.0123, 3.1415, 1e50, INF, NAN]
vals += [-v for v in vals]
diff --git a/src/org/python/core/PyString.java b/src/org/python/core/PyString.java
--- a/src/org/python/core/PyString.java
+++ b/src/org/python/core/PyString.java
@@ -1021,141 +1021,9 @@
throw Py.TypeError("bad operand type for unary ~");
}
- @SuppressWarnings("fallthrough")
@Override
public PyComplex __complex__() {
- boolean got_re = false;
- boolean got_im = false;
- boolean done = false;
- boolean sw_error = false;
-
- int s = 0;
- int n = getString().length();
- while (s < n && Character.isSpaceChar(getString().charAt(s))) {
- s++;
- }
-
- if (s == n) {
- throw Py.ValueError("empty string for complex()");
- }
-
- double z = -1.0;
- double x = 0.0;
- double y = 0.0;
-
- int sign = 1;
- do {
- char c = getString().charAt(s);
- switch (c) {
- case '-':
- sign = -1;
- /* Fallthrough */
- case '+':
- if (done || s + 1 == n) {
- sw_error = true;
- break;
- }
- // a character is guaranteed, but it better be a digit
- // or J or j
- c = getString().charAt(++s); // eat the sign character
- // and check the next
- if (!Character.isDigit(c) && c != 'J' && c != 'j') {
- sw_error = true;
- }
- break;
-
- case 'J':
- case 'j':
- if (got_im || done) {
- sw_error = true;
- break;
- }
- if (z < 0.0) {
- y = sign;
- } else {
- y = sign * z;
- }
- got_im = true;
- done = got_re;
- sign = 1;
- s++; // eat the J or j
- break;
-
- case ' ':
- while (s < n && Character.isSpaceChar(getString().charAt(s))) {
- s++;
- }
- if (s != n) {
- sw_error = true;
- }
- break;
-
- default:
- boolean digit_or_dot = (c == '.' || Character.isDigit(c));
- if (!digit_or_dot) {
- sw_error = true;
- break;
- }
- int end = endDouble(getString(), s);
- z = Double.valueOf(getString().substring(s, end)).doubleValue();
- if (z == Double.POSITIVE_INFINITY) {
- throw Py.ValueError(String.format("float() out of range: %.150s",
- getString()));
- }
-
- s = end;
- if (s < n) {
- c = getString().charAt(s);
- if (c == 'J' || c == 'j') {
- break;
- }
- }
- if (got_re) {
- sw_error = true;
- break;
- }
-
- /* accept a real part */
- x = sign * z;
- got_re = true;
- done = got_im;
- z = -1.0;
- sign = 1;
- break;
-
- } /* end of switch */
-
- } while (s < n && !sw_error);
-
- if (sw_error) {
- throw Py.ValueError("malformed string for complex() " + getString().substring(s));
- }
-
- return new PyComplex(x, y);
- }
-
- private int endDouble(String string, int s) {
- int n = string.length();
- while (s < n) {
- char c = string.charAt(s++);
- if (Character.isDigit(c)) {
- continue;
- }
- if (c == '.') {
- continue;
- }
- if (c == 'e' || c == 'E') {
- if (s < n) {
- c = string.charAt(s);
- if (c == '+' || c == '-') {
- s++;
- }
- continue;
- }
- }
- return s - 1;
- }
- return s;
+ return atocx();
}
// Add in methods from string module
@@ -2718,45 +2586,80 @@
* @return the value
*/
public double atof() {
- String bogus = null;
double x = 0.0;
- Matcher m = atofPattern.matcher(getString());
-
- if (m.matches()) {
- // Might be a valid float
+ Matcher m = getFloatPattern().matcher(getString());
+ boolean valid = m.matches();
+
+ if (valid) {
+ // Might be a valid float: trimmed of white space in group 1.
+ String number = m.group(1);
try {
- if (m.group(3) == null) {
- // No numeric part was found: it's something like "-Inf" or "hOrsE"
+ char lastChar = number.charAt(number.length() - 1);
+ if (Character.isLetter(lastChar)) {
+ // It's something like "nan", "-Inf" or "+nifty"
x = atofSpecials(m.group(1));
} else {
// A numeric part was present, try to convert the whole
x = Double.parseDouble(m.group(1));
}
} catch (NumberFormatException e) {
- bogus = m.group(1);
+ valid = false;
}
- } else {
- // This doesn't match the pattern for a float value
- bogus = getString().trim();
}
- // At this point, bogus will have been set to the trimmed string if there was a problem.
- if (bogus == null) {
+ // At this point, valid will have been cleared if there was a problem.
+ if (valid) {
return x;
} else {
- String fmt = "could not convert string to float: %s";
- throw Py.ValueError(String.format(fmt, bogus));
+ String fmt = "invalid literal for float: %s";
+ throw Py.ValueError(String.format(fmt, getString().trim()));
}
}
/**
- * Regular expression that includes all valid a Python float() arguments, in which group 1
- * captures the whole, stripped of white space, and group 3 will be present only if the form is
- * numeric. Invalid non numerics are accepted ("+hOrsE" as "-inf").
+ * Regular expression for an unsigned Python float, accepting also any sequence of the letters
+ * that belong to "NaN" or "Infinity" in whatever case. This is used within the regular
+ * expression patterns that define a priori acceptable strings in the float and complex
+ * constructors. The expression contributes no capture groups.
*/
- private static Pattern atofPattern = Pattern
- .compile("\\s*([+-]?(((\\d+(\\.\\d*)?|\\.\\d+)([eE][+-]?\\d+)?)|\\p{Alpha}+))\\s*");
+ private static final String UF_RE =
+ "(?:(?:(?:\\d+\\.?|\\.\\d)\\d*(?:[eE][+-]?\\d+)?)|[infatyINFATY]+)";
+
+ /**
+ * Return the (lazily) compiled regular expression that matches all valid a Python float()
+ * arguments, in which Group 1 captures the number, stripped of white space. Various invalid
+ * non-numerics are provisionally accepted (e.g. "+inanity" or "-faint").
+ */
+ private static synchronized Pattern getFloatPattern() {
+ if (floatPattern == null) {
+ floatPattern = Pattern.compile("\\s*([+-]?" + UF_RE + ")\\s*");
+ }
+ return floatPattern;
+ }
+
+ /** Access only through {@link #getFloatPattern()}. */
+ private static Pattern floatPattern = null;
+
+ /**
+ * Return the (lazily) compiled regular expression for a Python complex number. This is used
+ * within the regular expression patterns that define a priori acceptable strings in the complex
+ * constructors. The expression contributes five named capture groups a, b, x, y and j. x and y
+ * are the two floats encountered, and if j is present, one of them is the imaginary part.
+ * a and b are the optional parentheses. They must either both be present or both omitted.
+ */
+ private static synchronized Pattern getComplexPattern() {
+ if (complexPattern == null) {
+ complexPattern = Pattern.compile("\\s*(?<a>\\(\\s*)?" // Parenthesis <a>
+ + "(?<x>[+-]?" + UF_RE + "?)" // <x>
+ + "(?<y>[+-]" + UF_RE + "?)?(?<j>[jJ])?" // + <y> <j>
+ + "\\s*(?<b>\\)\\s*)?"); // Parenthesis <b>
+ }
+ return complexPattern;
+ }
+
+ /** Access only through {@link #getComplexPattern()} */
+ private static Pattern complexPattern = null;
/**
* Conversion for non-numeric floats, accepting signed or unsigned "inf" and "nan", in any case.
@@ -2784,6 +2687,99 @@
}
}
+ /**
+ * Convert this PyString to a complex value according to Python rules.
+ *
+ * @return the value
+ */
+ private PyComplex atocx() {
+ double x = 0.0, y = 0.0;
+ Matcher m = getComplexPattern().matcher(getString());
+ boolean valid = m.matches();
+
+ if (valid) {
+ // Passes a priori, but we have some checks to make. Brackets: both or neither.
+ if ((m.group("a") != null) != (m.group("b") != null)) {
+ valid = false;
+
+ } else {
+ try {
+ // Pick up the two numbers [+-]? <x> [+-] <y> j?
+ String xs = m.group("x"), ys = m.group("y");
+
+ if (m.group("j") != null) {
+ // There is a 'j', so there is an imaginary part.
+ if (ys != null) {
+ // There were two numbers, so the second is the imaginary part.
+ y = toComplexPart(ys);
+ // And the first is the real part
+ x = toComplexPart(xs);
+ } else if (xs != null) {
+ // There was only one number (and a 'j')so it is the imaginary part.
+ y = toComplexPart(xs);
+ // x = 0.0;
+ } else {
+ // There were no numbers, just the 'j'. (Impossible return?)
+ y = 1.0;
+ // x = 0.0;
+ }
+
+ } else {
+ // There is no 'j' so can only be one number, the real part.
+ x = Double.parseDouble(xs);
+ if (ys != null) {
+ // Something like "123 +" or "123 + 456" but no 'j'.
+ throw new NumberFormatException();
+ }
+ }
+
+ } catch (NumberFormatException e) {
+ valid = false;
+ }
+ }
+ }
+
+ // At this point, valid will have been cleared if there was a problem.
+ if (valid) {
+ return new PyComplex(x, y);
+ } else {
+ String fmt = "complex() arg is a malformed string: %s";
+ throw Py.ValueError(String.format(fmt, getString().trim()));
+ }
+
+ }
+
+ /**
+ * Helper for interpreting each part (real and imaginary) of a complex number expressed as a
+ * string in {@link #atocx(String)}. It deals with numbers, inf, nan and their variants, and
+ * with the "implied one" in +j or 10-j.
+ *
+ * @param s to interpret
+ * @return value of s
+ * @throws NumberFormatException if the number is invalid
+ */
+ private static double toComplexPart(String s) throws NumberFormatException {
+ if (s.length() == 0) {
+ // Empty string (occurs only as 'j')
+ return 1.0;
+ } else {
+ char lastChar = s.charAt(s.length() - 1);
+ if (Character.isLetter(lastChar)) {
+ // Possibly a sign, then letters that ought to be "nan" or "inf[inity]"
+ return atofSpecials(s);
+ } else if (lastChar == '+') {
+ // Occurs only as "+j"
+ return 1.0;
+ } else if (lastChar == '-') {
+ // Occurs only as "-j"
+ return -1.0;
+ } else {
+ // Possibly a sign then an unsigned float
+ return Double.parseDouble(s);
+ }
+ }
+ }
+
private BigInteger asciiToBigInteger(int base, boolean isLong) {
String str = getString();
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list