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

Mon Jan 17 18:44:39 CET 2011

```Author: Armin Rigo <arigo at tunes.org>
Branch: cmath
Changeset: r40805:02517bdd558b
Date: 2011-01-17 18:44 +0100
http://bitbucket.org/pypy/pypy/changeset/02517bdd558b/

Log:	(lac, arigo)

rect().

diff --git a/pypy/module/cmath/__init__.py b/pypy/module/cmath/__init__.py
--- a/pypy/module/cmath/__init__.py
+++ b/pypy/module/cmath/__init__.py
@@ -21,6 +21,7 @@
'cos': "Return the cosine of x.",
'sin': "Return the sine of x.",
'tan': "Return the tangent of x.",
+    'rect': "Convert from polar coordinates to rectangular coordinates.",
}

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
@@ -123,12 +123,6 @@
#if not float.__getformat__("double").startswith("IEEE"):
#    return

-    def rect_complex(z):
-        """Wrapped version of rect that accepts a complex number instead of
-        two float arguments."""
-        xxx
-        return cmath.rect(z.real, z.imag)
-
def polar_complex(z):
"""Wrapped version of polar that returns a complex number instead of
two floats."""
@@ -138,9 +132,7 @@
for id, fn, ar, ai, er, ei, flags in parse_testfile('cmath_testcases.txt'):
arg = (ar, ai)
expected = (er, ei)
-        if fn == 'rect':
-            function = rect_complex
-        elif fn == 'polar':
+        if fn == 'polar':
function = polar_complex
else:
function = getattr(interp_cmath, 'c_' + fn)

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
@@ -19,6 +19,7 @@
from pypy.module.cmath.special_value import cosh_special_values
from pypy.module.cmath.special_value import sinh_special_values
from pypy.module.cmath.special_value import tanh_special_values
+from pypy.module.cmath.special_value import rect_special_values

def unaryfn(c_func):
@@ -449,3 +450,31 @@
# tan(z) = -i tanh(iz)
sx, sy = c_tanh(-y, x)
return sy, -sx
+
+
+ at unaryfn
+def c_rect(r, phi):
+    if not isfinite(r) or not isfinite(phi):
+        # if r is +/-infinity and phi is finite but nonzero then
+        # result is (+-INF +-INF i), but we need to compute cos(phi)
+        # and sin(phi) to figure out the signs.
+        if isinf(r) and isfinite(phi) and phi != 0.:
+            if r > 0:
+                real = copysign(INF, math.cos(phi))
+                imag = copysign(INF, math.sin(phi))
+            else:
+                real = -copysign(INF, math.cos(phi))
+                imag = -copysign(INF, math.sin(phi))
+            z = (real, imag)
+        else:
+            z = rect_special_values[special_type(r)][special_type(phi)]
+
+        # need to raise ValueError if r is a nonzero number and phi
+        # is infinite
+        if r != 0. and not isnan(r) and isinf(phi):
+            raise ValueError("math domain error")
+        return z
+
+    real = r * math.cos(phi)
+    imag = r * math.sin(phi)
+    return real, imag

diff --git a/pypy/module/cmath/special_value.py b/pypy/module/cmath/special_value.py
--- a/pypy/module/cmath/special_value.py
+++ b/pypy/module/cmath/special_value.py
@@ -155,3 +155,13 @@
(1.,0.),  (U,U), (1.,-0.),  (1.,0.),  (U,U), (1.,0.),  (1.,0.),
(N,N),    (N,N), (N,-0.),   (N,0.),   (N,N), (N,N),    (N,N),
])
+
+rect_special_values = build_table([
+    (INF,N), (U,U), (-INF,0.), (-INF,-0.), (U,U), (INF,N), (INF,N),
+    (N,N),   (U,U), (U,U),     (U,U),      (U,U), (N,N),   (N,N),
+    (0.,0.), (U,U), (-0.,0.),  (-0.,-0.),  (U,U), (0.,0.), (0.,0.),
+    (0.,0.), (U,U), (0.,-0.),  (0.,0.),    (U,U), (0.,0.), (0.,0.),
+    (N,N),   (U,U), (U,U),     (U,U),      (U,U), (N,N),   (N,N),
+    (INF,N), (U,U), (INF,-0.), (INF,0.),   (U,U), (INF,N), (INF,N),
+    (N,N),   (N,N), (N,0.),    (N,0.),     (N,N), (N,N),   (N,N),
+    ])
```