Skip to content

Commit 7a1c462

Browse files
committed
adding Tim Freund's cmath implementation from patch #1600162
1 parent 6cde98e commit 7a1c462

3 files changed

Lines changed: 324 additions & 1 deletion

File tree

Lib/test/test_cmath.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
#! /usr/bin/env python
2+
""" Simple test script for cmathmodule.c
3+
Roger E. Masse
4+
"""
5+
import cmath
6+
import unittest
7+
from test import test_support
8+
from test.test_support import verbose
9+
10+
p = cmath.pi
11+
e = cmath.e
12+
if verbose:
13+
print 'PI = ', abs(p)
14+
print 'E = ', abs(e)
15+
16+
17+
class CmathTestCase(unittest.TestCase):
18+
def assertAlmostEqual(self, x, y, places=5, msg=None):
19+
unittest.TestCase.assertAlmostEqual(self, x.real, y.real, places, msg)
20+
unittest.TestCase.assertAlmostEqual(self, x.imag, y.imag, places, msg)
21+
22+
def test_acos(self):
23+
self.assertAlmostEqual(complex(0.936812, -2.30551),
24+
cmath.acos(complex(3, 4)))
25+
26+
def test_acosh(self):
27+
self.assertAlmostEqual(complex(2.30551, 0.93681),
28+
cmath.acosh(complex(3, 4)))
29+
30+
def test_asin(self):
31+
self.assertAlmostEqual(complex(0.633984, 2.30551),
32+
cmath.asin(complex(3, 4)))
33+
34+
def test_asinh(self):
35+
self.assertAlmostEqual(complex(2.29991, 0.917617),
36+
cmath.asinh(complex(3, 4)))
37+
38+
def test_atan(self):
39+
self.assertAlmostEqual(complex(1.44831, 0.158997),
40+
cmath.atan(complex(3, 4)))
41+
42+
def test_atanh(self):
43+
self.assertAlmostEqual(complex(0.11750, 1.40992),
44+
cmath.atanh(complex(3, 4)))
45+
46+
def test_cos(self):
47+
self.assertAlmostEqual(complex(-27.03495, -3.851153),
48+
cmath.cos(complex(3, 4)))
49+
50+
def test_cosh(self):
51+
self.assertAlmostEqual(complex(-6.58066, -7.58155),
52+
cmath.cosh(complex(3, 4)))
53+
54+
def test_exp(self):
55+
self.assertAlmostEqual(complex(-13.12878, -15.20078),
56+
cmath.exp(complex(3, 4)))
57+
58+
def test_log(self):
59+
self.assertAlmostEqual(complex(1.60944, 0.927295),
60+
cmath.log(complex(3, 4)))
61+
62+
def test_log10(self):
63+
self.assertAlmostEqual(complex(0.69897, 0.40272),
64+
cmath.log10(complex(3, 4)))
65+
66+
def test_sin(self):
67+
self.assertAlmostEqual(complex(3.853738, -27.01681),
68+
cmath.sin(complex(3, 4)))
69+
70+
def test_sinh(self):
71+
self.assertAlmostEqual(complex(-6.54812, -7.61923),
72+
cmath.sinh(complex(3, 4)))
73+
74+
def test_sqrt_real_positive(self):
75+
self.assertAlmostEqual(complex(2, 1),
76+
cmath.sqrt(complex(3, 4)))
77+
78+
def test_sqrt_real_zero(self):
79+
self.assertAlmostEqual(complex(1.41421, 1.41421),
80+
cmath.sqrt(complex(0, 4)))
81+
82+
def test_sqrt_real_negative(self):
83+
self.assertAlmostEqual(complex(1, 2),
84+
cmath.sqrt(complex(-3, 4)))
85+
86+
def test_sqrt_imaginary_zero(self):
87+
self.assertAlmostEqual(complex(0.0, 1.73205),
88+
cmath.sqrt(complex(-3, 0)))
89+
90+
def test_sqrt_imaginary_negative(self):
91+
self.assertAlmostEqual(complex(1.0, -2.0),
92+
cmath.sqrt(complex(-3, -4)))
93+
94+
def test_tan(self):
95+
self.assertAlmostEqual(complex(-0.000187346, 0.999356),
96+
cmath.tan(complex(3, 4)))
97+
98+
def test_tanh(self):
99+
self.assertAlmostEqual(complex(1.00071, 0.00490826),
100+
cmath.tanh(complex(3, 4)))
101+
102+
def test_main():
103+
test_support.run_unittest(CmathTestCase)
104+
105+
if __name__ == "__main__":
106+
test_main()
107+
108+
109+

src/org/python/modules/Setup.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ public class Setup
5353
"errno",
5454
"array:org.python.modules.ArrayModule",
5555
"sets:org.python.modules.sets.Sets",
56-
"_random:org.python.modules.random.RandomModule"
56+
"_random:org.python.modules.random.RandomModule",
57+
"cmath"
5758
};
5859
}

src/org/python/modules/cmath.java

Lines changed: 213 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,213 @@
1+
package org.python.modules;
2+
3+
import org.python.core.Py;
4+
import org.python.core.PyComplex;
5+
import org.python.core.PyException;
6+
import org.python.core.PyFloat;
7+
import org.python.core.PyObject;
8+
import org.python.modules.math;
9+
10+
public class cmath {
11+
public static PyFloat pi = new PyFloat(Math.PI);
12+
public static PyFloat e = new PyFloat(Math.E);
13+
14+
private static PyComplex one = new PyComplex(1.0, 0.0);
15+
private static PyComplex half = new PyComplex(0.5, 0.0);
16+
private static PyComplex i = new PyComplex(0.0, 1.0);
17+
private static PyComplex half_i = new PyComplex(0.0, 0.5);
18+
19+
private static PyComplex c_prodi(PyComplex x) {
20+
return (new PyComplex(-x.imag, x.real));
21+
}
22+
23+
private static double hypot(double x, double y) {
24+
return (Math.sqrt(x * x + y * y));
25+
}
26+
27+
private static PyComplex complexFromPyObject(PyObject in) {
28+
try{
29+
return(in.__complex__());
30+
} catch(PyException e){
31+
if(e.type == Py.AttributeError) {
32+
throw Py.TypeError("a float is required");
33+
}
34+
throw e;
35+
}
36+
}
37+
38+
public static PyObject acos(PyObject in) {
39+
PyComplex x = complexFromPyObject(in);
40+
return (c_prodi(log(x.__add__(i
41+
.__mul__(sqrt(one.__sub__(x.__mul__(x))))))).__neg__());
42+
}
43+
44+
public static PyComplex acosh(PyObject in) {
45+
PyComplex x = complexFromPyObject(in);
46+
PyComplex r = null;
47+
48+
PyComplex a = sqrt(x.__sub__(one));
49+
PyComplex b = sqrt(x.__add__(one));
50+
PyComplex c = sqrt(half);
51+
r = log(c.__mul__(b.__add__(a)));
52+
53+
return ((PyComplex) r.__add__(r));
54+
}
55+
56+
public static PyComplex asin(PyObject in) {
57+
PyComplex x = complexFromPyObject(in);
58+
PyComplex r = null;
59+
60+
PyComplex squared = (PyComplex) x.__mul__(x);
61+
PyComplex sq1_minus_xsq = sqrt(one.__sub__(squared));
62+
63+
r = (PyComplex) c_prodi(log(sq1_minus_xsq.__add__(c_prodi(x))))
64+
.__neg__();
65+
return (r);
66+
}
67+
68+
public static PyComplex asinh(PyObject in) {
69+
PyComplex x = complexFromPyObject(in);
70+
PyComplex r = null;
71+
72+
PyComplex a = sqrt(x.__add__(i));
73+
PyComplex b = sqrt(x.__sub__(i));
74+
PyComplex z = sqrt(half);
75+
r = log(z.__mul__(a.__add__(b)));
76+
77+
return ((PyComplex) r.__add__(r));
78+
}
79+
80+
public static PyComplex atan(PyObject in) {
81+
PyComplex x = complexFromPyObject(in);
82+
PyComplex r = (PyComplex) half_i.__mul__(log(i.__add__(x).__div__(
83+
i.__sub__(x))));
84+
85+
return (r);
86+
}
87+
88+
public static PyComplex atanh(PyObject in) {
89+
PyComplex x = complexFromPyObject(in);
90+
PyComplex r = (PyComplex) half.__mul__(log(one.__add__(x).__div__(
91+
one.__sub__(x))));
92+
return (r);
93+
}
94+
95+
public static PyComplex cos(PyObject in) {
96+
PyComplex x = complexFromPyObject(in);
97+
PyComplex r = new PyComplex(Math.cos(x.real) * math.cosh(x.imag), -Math
98+
.sin(x.real)
99+
* math.sinh(x.imag));
100+
return (r);
101+
}
102+
103+
public static PyComplex cosh(PyObject in) {
104+
PyComplex x = complexFromPyObject(in);
105+
PyComplex r = new PyComplex(Math.cos(x.imag) * math.cosh(x.real), Math
106+
.sin(x.imag)
107+
* math.sinh(x.real));
108+
return (r);
109+
}
110+
111+
public static PyComplex exp(PyObject in) {
112+
PyComplex x = complexFromPyObject(in);
113+
PyComplex r = new PyComplex(0.0, 0.0);
114+
double l = Math.exp(x.real);
115+
r.real = l * Math.cos(x.imag);
116+
r.imag = l * Math.sin(x.imag);
117+
return (r);
118+
}
119+
120+
public static PyComplex log(PyObject in) {
121+
PyComplex r = new PyComplex(0.0, 0.0);
122+
PyComplex x = complexFromPyObject(in);
123+
r.imag = Math.atan2(x.imag, x.real);
124+
r.real = Math.log(hypot(x.real, x.imag));
125+
return (r);
126+
}
127+
128+
public static PyComplex log10(PyObject in) {
129+
PyComplex r = new PyComplex(0.0, 0.0);
130+
PyComplex x = complexFromPyObject(in);
131+
double l = hypot(x.real, x.imag);
132+
r.imag = Math.atan2(x.imag, x.real) / Math.log(10.0);
133+
r.real = math.log10(new PyFloat(l));
134+
return (r);
135+
}
136+
137+
public static PyComplex sin(PyObject in) {
138+
PyComplex r = new PyComplex(0.0, 0.0);
139+
PyComplex x = complexFromPyObject(in);
140+
r.real = Math.sin(x.real) * math.cosh(x.imag);
141+
r.imag = Math.cos(x.real) * math.sinh(x.imag);
142+
return (r);
143+
}
144+
145+
public static PyComplex sinh(PyObject in) {
146+
PyComplex r = new PyComplex(0.0, 0.0);
147+
PyComplex x = complexFromPyObject(in);
148+
r.real = Math.cos(x.imag) * math.sinh(x.real);
149+
r.imag = Math.sin(x.imag) * math.cosh(x.real);
150+
return (r);
151+
}
152+
153+
public static PyComplex sqrt(PyObject in) {
154+
PyComplex x = complexFromPyObject(in);
155+
PyComplex r = new PyComplex(0.0, 0.0);
156+
157+
if ((x.real != 0.0) || (x.imag != 0.0)) {
158+
double s = Math
159+
.sqrt(0.5 * (Math.abs(x.real) + hypot(x.real, x.imag)));
160+
double d = 0.5 * x.imag / s;
161+
162+
if (x.real > 0) {
163+
r.real = s;
164+
r.imag = d;
165+
} else if (x.imag >= 0) {
166+
r.real = d;
167+
r.imag = s;
168+
} else {
169+
r.real = -d;
170+
r.imag = -s;
171+
}
172+
}
173+
return (r);
174+
}
175+
176+
public static PyComplex tan(PyObject in) {
177+
PyComplex x = complexFromPyObject(in);
178+
PyComplex r = new PyComplex(0.0, 0.0);
179+
180+
double sr = Math.sin(x.real);
181+
double cr = Math.cos(x.real);
182+
double shi = math.sinh(x.imag);
183+
double chi = math.cosh(x.imag);
184+
double rs = sr * chi;
185+
double is = cr * shi;
186+
double rc = cr * chi;
187+
double ic = -sr * shi;
188+
double d = rc * rc + ic * ic;
189+
r.real = ((rs * rc) + (is * ic)) / d;
190+
r.imag = ((is * rc) - (rs * ic)) / d;
191+
192+
return (r);
193+
}
194+
195+
public static PyComplex tanh(PyObject in) {
196+
PyComplex x = complexFromPyObject(in);
197+
PyComplex r = new PyComplex(0.0, 0.0);
198+
199+
double si = Math.sin(x.imag);
200+
double ci = Math.cos(x.imag);
201+
double shr = math.sinh(x.real);
202+
double chr = math.cosh(x.real);
203+
double rs = ci * shr;
204+
double is = si * chr;
205+
double rc = ci * chr;
206+
double ic = si * shr;
207+
double d = rc * rc + ic * ic;
208+
r.real = ((rs * rc) + (is * ic)) / d;
209+
r.imag = ((is * rc) - (rs * ic)) / d;
210+
211+
return (r);
212+
}
213+
}

0 commit comments

Comments
 (0)