[pypy-svn] pypy cmath: (lac, arigo)

Mon Jan 17 15:45:45 CET 2011

```Author: Armin Rigo <arigo at tunes.org>
Branch: cmath
Changeset: r40769:0e06e114ac1a
Date: 2011-01-17 15:45 +0100
http://bitbucket.org/pypy/pypy/changeset/0e06e114ac1a/

Log:	(lac, arigo)

Finish the implementation of c_sqrt(). Yay!

diff --git a/pypy/module/cmath/test/test_cmath.py b/pypy/module/cmath/test/test_cmath.py
--- a/pypy/module/cmath/test/test_cmath.py
+++ b/pypy/module/cmath/test/test_cmath.py
@@ -1,8 +1,19 @@
from __future__ import with_statement
from pypy.conftest import gettestobjspace
+from pypy.rlib.rarithmetic import copysign
import os

+def test_special_values():
+    from pypy.module.cmath.special_value import sqrt_special_values
+    assert len(sqrt_special_values) == 7
+    assert len(sqrt_special_values[4]) == 7
+    assert isinstance(sqrt_special_values[5][1], tuple)
+    assert sqrt_special_values[5][1][0] == 1e200 * 1e200
+    assert sqrt_special_values[5][1][1] == -0.
+    assert copysign(1., sqrt_special_values[5][1][1]) == -1.
+
+
class AppTestCMath:
def setup_class(cls):
cls.space = gettestobjspace(usemodules=['cmath'])
@@ -23,6 +34,9 @@
z = cmath.sqrt((dbl_min * 0.00000000000001) + 0j)
assert abs(z.real - 1.49107189843e-161) < 1e-170
assert z.imag == 0.0
+        z = cmath.sqrt(1e200*1e200 - 10j)
+        assert math.isinf(z.real) and z.real > 0.0
+        assert z.imag == 0.0 and math.copysign(1., z.imag) == -1.

def test_acos(self):
import cmath

diff --git a/pypy/module/cmath/interp_cmath.py b/pypy/module/cmath/interp_cmath.py
--- a/pypy/module/cmath/interp_cmath.py
+++ b/pypy/module/cmath/interp_cmath.py
@@ -3,6 +3,8 @@
from pypy.interpreter.gateway import ObjSpace, W_Root
from pypy.module.cmath import Module
from pypy.module.cmath.constant import DBL_MIN, CM_SCALE_UP, CM_SCALE_DOWN
+from pypy.module.cmath.special_value import isfinite, special_type
+from pypy.module.cmath.special_value import sqrt_special_values

def unaryfn(name):
@@ -44,7 +46,8 @@
# x and y by a sufficiently large power of 2 to ensure that x and y
# are normal.

-    #XXX SPECIAL_VALUE
+    if not isfinite(x) or not isfinite(y):
+        return sqrt_special_values[special_type(x)][special_type(y)]

if x == 0. and y == 0.:
return (0., y)

diff --git a/pypy/module/cmath/special_value.py b/pypy/module/cmath/special_value.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cmath/special_value.py
@@ -0,0 +1,77 @@
+import math
+from pypy.rlib.rarithmetic import isnan, isinf, copysign
+
+# code to deal with special values (infinities, NaNs, ...)
+#
+# The special types can be:
+ST_NINF    = 0         # negative infinity
+ST_NEG     = 1         # negative finite number (nonzero)
+ST_NZERO   = 2         # -0.
+ST_PZERO   = 3         # +0.
+ST_POS     = 4         # positive finite number (nonzero)
+ST_PINF    = 5         # positive infinity
+ST_NAN     = 6         # Not a Number
+
+def special_type(d):
+    if isnan(d):
+        return ST_NAN
+    elif isinf(d):
+        if d > 0.0:
+            return ST_PINF
+        else:
+            return ST_NINF
+    else:
+        if d != 0.0:
+            if d > 0.0:
+                return ST_POS
+            else:
+                return ST_NEG
+        else:
+            if copysign(1., d) == 1.:
+                return ST_PZERO
+            else:
+                return ST_NZERO
+
+def isfinite(d):
+    return not isinf(d) and not isnan(d)
+
+
+P   = math.pi
+P14 = 0.25 * math.pi
+P12 = 0.5 * math.pi
+P34 = 0.75 * math.pi
+INF = 1e200 * 1e200
+N   = INF / INF
+U   = -9.5426319407711027e33   # unlikely value, used as placeholder
+
+def build_table(lst):
+    table = []
+    assert len(lst) == 49
+    it = iter(lst)
+    for j in range(7):
+        row = []
+        for i in range(7):
+            (x, y) = it.next()
+            row.append((x, y))
+        table.append(row)
+    return table
+
+##acos_special_values = build_table([
+## C(P34,INF),C(P,INF), C(P,INF), C(P,-INF), C(P,-INF), C(P34,-INF),C(N,INF),
+## C(P12,INF),C(U,U),   C(U,U),   C(U,U),    C(U,U),    C(P12,-INF),C(N,N),
+## C(P12,INF),C(U,U),   C(P12,0.),C(P12,-0.),C(U,U),    C(P12,-INF),C(P12,N),
+## C(P12,INF),C(U,U),   C(P12,0.),C(P12,-0.),C(U,U),    C(P12,-INF),C(P12,N),
+## C(P12,INF),C(U,U),   C(U,U),   C(U,U),    C(U,U),    C(P12,-INF),C(N,N),
+## C(P14,INF),C(0.,INF),C(0.,INF),C(0.,-INF),C(0.,-INF),C(P14,-INF),C(N,INF),
+## C(N,INF),  C(N,N),   C(N,N),   C(N,N),    C(N,N),    C(N,-INF),  C(N,N)
+## ])
+
+sqrt_special_values = build_table([
+    (INF,-INF), (0.,-INF), (0.,-INF), (0.,INF), (0.,INF), (INF,INF), (N,INF),
+    (INF,-INF), (U,U),     (U,U),     (U,U),    (U,U),    (INF,INF), (N,N),
+    (INF,-INF), (U,U),     (0.,-0.),  (0.,0.),  (U,U),    (INF,INF), (N,N),
+    (INF,-INF), (U,U),     (0.,-0.),  (0.,0.),  (U,U),    (INF,INF), (N,N),
+    (INF,-INF), (U,U),     (U,U),     (U,U),    (U,U),    (INF,INF), (N,N),
+    (INF,-INF), (INF,-0.), (INF,-0.), (INF,0.), (INF,0.), (INF,INF), (INF,N),
+    (INF,-INF), (N,N),     (N,N),     (N,N),    (N,N),    (INF,INF), (N,N),
+    ])
```