Skip to content

Commit 2e65120

Browse files
committed
Applied patch 1717358 for radians and degrees from LaserGuidedBunnyRabbit (lgbr).
Also added the two argument log function, and updated to the CPython release25-maint test_math.py.
1 parent 9a3f616 commit 2e65120

File tree

2 files changed

+133
-45
lines changed

2 files changed

+133
-45
lines changed

Lib/test/test_math.py

Lines changed: 96 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,153 +1,209 @@
1+
# XXX Taken from CPython's release25-maint revision 56608
12
# Python test set -- math module
3+
# XXXX Should not do tests around zero only
24

3-
from test_support import *
5+
from test.test_support import TestFailed, verbose
46

57
seps='1e-05'
68
eps = eval(seps)
7-
print_test('math (test_math.py)', 1) # 'math module, testing with eps', seps
9+
print 'math module, testing with eps', seps
810
import math
911

1012
def testit(name, value, expected):
11-
if abs(value-expected) > eps:
12-
raise TestFailed, '%s returned %f, expected %f'%\
13-
(name, value, expected)
13+
if abs(value-expected) > eps:
14+
raise TestFailed, '%s returned %f, expected %f'%\
15+
(name, value, expected)
1416

15-
print_test('constants: e, pi', 2)
16-
assert abs(math.pi-3.1415926) < eps
17-
assert abs(math.e-2.7182818) < eps
17+
print 'constants'
18+
testit('pi', math.pi, 3.1415926)
19+
testit('e', math.e, 2.7182818)
1820

19-
print_test('acos')
20-
testit('acos', math.acos(-1), math.pi)
21-
testit('acos', math.acos(0), math.pi/2)
22-
testit('acos', math.acos(1), 0)
21+
print 'acos'
22+
testit('acos(-1)', math.acos(-1), math.pi)
23+
testit('acos(0)', math.acos(0), math.pi/2)
24+
testit('acos(1)', math.acos(1), 0)
2325

24-
print_test('asin')
26+
print 'asin'
2527
testit('asin(-1)', math.asin(-1), -math.pi/2)
2628
testit('asin(0)', math.asin(0), 0)
2729
testit('asin(1)', math.asin(1), math.pi/2)
2830

29-
print_test('atan')
31+
print 'atan'
3032
testit('atan(-1)', math.atan(-1), -math.pi/4)
3133
testit('atan(0)', math.atan(0), 0)
3234
testit('atan(1)', math.atan(1), math.pi/4)
3335

34-
print_test('atan2')
36+
print 'atan2'
3537
testit('atan2(-1, 0)', math.atan2(-1, 0), -math.pi/2)
3638
testit('atan2(-1, 1)', math.atan2(-1, 1), -math.pi/4)
3739
testit('atan2(0, 1)', math.atan2(0, 1), 0)
3840
testit('atan2(1, 1)', math.atan2(1, 1), math.pi/4)
3941
testit('atan2(1, 0)', math.atan2(1, 0), math.pi/2)
4042

41-
print_test('ceil')
43+
print 'ceil'
4244
testit('ceil(0.5)', math.ceil(0.5), 1)
4345
testit('ceil(1.0)', math.ceil(1.0), 1)
4446
testit('ceil(1.5)', math.ceil(1.5), 2)
4547
testit('ceil(-0.5)', math.ceil(-0.5), 0)
4648
testit('ceil(-1.0)', math.ceil(-1.0), -1)
4749
testit('ceil(-1.5)', math.ceil(-1.5), -1)
4850

49-
print_test('cos')
51+
print 'cos'
5052
testit('cos(-pi/2)', math.cos(-math.pi/2), 0)
5153
testit('cos(0)', math.cos(0), 1)
5254
testit('cos(pi/2)', math.cos(math.pi/2), 0)
5355
testit('cos(pi)', math.cos(math.pi), -1)
5456

55-
print_test('cosh')
57+
print 'cosh'
5658
testit('cosh(0)', math.cosh(0), 1)
5759
testit('cosh(2)-2*cosh(1)**2', math.cosh(2)-2*math.cosh(1)**2, -1) # Thanks to Lambert
5860

59-
print_test('exp')
61+
print 'degrees'
62+
testit('degrees(pi)', math.degrees(math.pi), 180.0)
63+
testit('degrees(pi/2)', math.degrees(math.pi/2), 90.0)
64+
testit('degrees(-pi/4)', math.degrees(-math.pi/4), -45.0)
65+
66+
print 'exp'
6067
testit('exp(-1)', math.exp(-1), 1/math.e)
6168
testit('exp(0)', math.exp(0), 1)
6269
testit('exp(1)', math.exp(1), math.e)
6370

64-
print_test('fabs')
71+
print 'fabs'
6572
testit('fabs(-1)', math.fabs(-1), 1)
6673
testit('fabs(0)', math.fabs(0), 0)
6774
testit('fabs(1)', math.fabs(1), 1)
6875

69-
print_test('floor')
76+
print 'floor'
7077
testit('floor(0.5)', math.floor(0.5), 0)
7178
testit('floor(1.0)', math.floor(1.0), 1)
7279
testit('floor(1.5)', math.floor(1.5), 1)
7380
testit('floor(-0.5)', math.floor(-0.5), -1)
7481
testit('floor(-1.0)', math.floor(-1.0), -1)
7582
testit('floor(-1.5)', math.floor(-1.5), -2)
7683

77-
print_test('fmod')
84+
print 'fmod'
7885
testit('fmod(10,1)', math.fmod(10,1), 0)
7986
testit('fmod(10,0.5)', math.fmod(10,0.5), 0)
8087
testit('fmod(10,1.5)', math.fmod(10,1.5), 1)
8188
testit('fmod(-10,1)', math.fmod(-10,1), 0)
8289
testit('fmod(-10,0.5)', math.fmod(-10,0.5), 0)
8390
testit('fmod(-10,1.5)', math.fmod(-10,1.5), -1)
8491

85-
print_test('frexp')
92+
print 'frexp'
8693
def testfrexp(name, (mant, exp), (emant, eexp)):
87-
if abs(mant-emant) > eps or exp <> eexp:
88-
raise TestFailed, '%s returned %s, expected %s'%\
89-
(name, `mant, exp`, `emant,eexp`)
94+
if abs(mant-emant) > eps or exp != eexp:
95+
raise TestFailed, '%s returned %r, expected %r'%\
96+
(name, (mant, exp), (emant,eexp))
9097

9198
testfrexp('frexp(-1)', math.frexp(-1), (-0.5, 1))
9299
testfrexp('frexp(0)', math.frexp(0), (0, 0))
93100
testfrexp('frexp(1)', math.frexp(1), (0.5, 1))
94101
testfrexp('frexp(2)', math.frexp(2), (0.5, 2))
95102

96-
print_test('hypot')
103+
print 'hypot'
97104
testit('hypot(0,0)', math.hypot(0,0), 0)
98105
testit('hypot(3,4)', math.hypot(3,4), 5)
99106

100-
print_test('ldexp')
107+
print 'ldexp'
101108
testit('ldexp(0,1)', math.ldexp(0,1), 0)
102109
testit('ldexp(1,1)', math.ldexp(1,1), 2)
103110
testit('ldexp(1,-1)', math.ldexp(1,-1), 0.5)
104111
testit('ldexp(-1,1)', math.ldexp(-1,1), -2)
105112

106-
print_test('log')
113+
print 'log'
107114
testit('log(1/e)', math.log(1/math.e), -1)
108115
testit('log(1)', math.log(1), 0)
109116
testit('log(e)', math.log(math.e), 1)
117+
testit('log(32,2)', math.log(32,2), 5)
118+
testit('log(10**40, 10)', math.log(10**40, 10), 40)
119+
testit('log(10**40, 10**20)', math.log(10**40, 10**20), 2)
110120

111-
print_test('log10')
121+
print 'log10'
112122
testit('log10(0.1)', math.log10(0.1), -1)
113123
testit('log10(1)', math.log10(1), 0)
114124
testit('log10(10)', math.log10(10), 1)
115125

116-
print_test('modf')
126+
print 'modf'
117127
def testmodf(name, (v1, v2), (e1, e2)):
118-
if abs(v1-e1) > eps or abs(v2-e2):
119-
raise TestFailed, '%s returned %s, expected %s'%\
120-
(name, `v1,v2`, `e1,e2`)
128+
if abs(v1-e1) > eps or abs(v2-e2):
129+
raise TestFailed, '%s returned %r, expected %r'%\
130+
(name, (v1,v2), (e1,e2))
121131

122132
testmodf('modf(1.5)', math.modf(1.5), (0.5, 1.0))
123133
testmodf('modf(-1.5)', math.modf(-1.5), (-0.5, -1.0))
124134

125-
print_test('pow')
135+
print 'pow'
126136
testit('pow(0,1)', math.pow(0,1), 0)
127137
testit('pow(1,0)', math.pow(1,0), 1)
128138
testit('pow(2,1)', math.pow(2,1), 2)
129139
testit('pow(2,-1)', math.pow(2,-1), 0.5)
130140

131-
print_test('sin')
141+
print 'radians'
142+
testit('radians(180)', math.radians(180), math.pi)
143+
testit('radians(90)', math.radians(90), math.pi/2)
144+
testit('radians(-45)', math.radians(-45), -math.pi/4)
145+
146+
print 'sin'
132147
testit('sin(0)', math.sin(0), 0)
133148
testit('sin(pi/2)', math.sin(math.pi/2), 1)
134149
testit('sin(-pi/2)', math.sin(-math.pi/2), -1)
135150

136-
print_test('sinh')
151+
print 'sinh'
137152
testit('sinh(0)', math.sinh(0), 0)
138153
testit('sinh(1)**2-cosh(1)**2', math.sinh(1)**2-math.cosh(1)**2, -1)
139154
testit('sinh(1)+sinh(-1)', math.sinh(1)+math.sinh(-1), 0)
140155

141-
print_test('sqrt')
156+
print 'sqrt'
142157
testit('sqrt(0)', math.sqrt(0), 0)
143158
testit('sqrt(1)', math.sqrt(1), 1)
144159
testit('sqrt(4)', math.sqrt(4), 2)
145160

146-
print_test('tan')
161+
print 'tan'
147162
testit('tan(0)', math.tan(0), 0)
148163
testit('tan(pi/4)', math.tan(math.pi/4), 1)
149164
testit('tan(-pi/4)', math.tan(-math.pi/4), -1)
150165

151-
print_test('tanh')
166+
print 'tanh'
152167
testit('tanh(0)', math.tanh(0), 0)
153168
testit('tanh(1)+tanh(-1)', math.tanh(1)+math.tanh(-1), 0)
169+
170+
# RED_FLAG 16-Oct-2000 Tim
171+
# While 2.0 is more consistent about exceptions than previous releases, it
172+
# still fails this part of the test on some platforms. For now, we only
173+
# *run* test_exceptions() in verbose mode, so that this isn't normally
174+
# tested.
175+
176+
def test_exceptions():
177+
print 'exceptions'
178+
try:
179+
x = math.exp(-1000000000)
180+
except:
181+
# mathmodule.c is failing to weed out underflows from libm, or
182+
# we've got an fp format with huge dynamic range
183+
raise TestFailed("underflowing exp() should not have raised "
184+
"an exception")
185+
if x != 0:
186+
raise TestFailed("underflowing exp() should have returned 0")
187+
188+
# If this fails, probably using a strict IEEE-754 conforming libm, and x
189+
# is +Inf afterwards. But Python wants overflows detected by default.
190+
try:
191+
x = math.exp(1000000000)
192+
except OverflowError:
193+
pass
194+
else:
195+
raise TestFailed("overflowing exp() didn't trigger OverflowError")
196+
197+
# If this fails, it could be a puzzle. One odd possibility is that
198+
# mathmodule.c's macros are getting confused while comparing
199+
# Inf (HUGE_VAL) to a NaN, and artificially setting errno to ERANGE
200+
# as a result (and so raising OverflowError instead).
201+
try:
202+
x = math.sqrt(-1.0)
203+
except ValueError:
204+
pass
205+
else:
206+
raise TestFailed("sqrt(-1) didn't raise ValueError")
207+
208+
if verbose:
209+
test_exceptions()

src/org/python/modules/math.java

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -56,13 +56,37 @@ public static double floor(double v) {
5656
}
5757

5858
public static double log(PyObject v) {
59+
return log(v, null);
60+
}
61+
62+
public static double log(PyObject v, PyObject base) {
63+
double doubleValue;
5964
if (v instanceof PyLong) {
60-
int e[] = new int[1];
61-
double x = ((PyLong)v).scaledDoubleValue(e);
62-
if (x <= 0.0) throw Py.ValueError("math domain error");
63-
return log(x) + (e[0]*8.0)*log(2.0);
65+
doubleValue = calculateLongLog((PyLong)v);
66+
} else {
67+
doubleValue = log(v.__float__().getValue());
68+
}
69+
if (base != null) {
70+
return check(applyLoggedBase(doubleValue, base));
6471
}
65-
return log(v.__float__().getValue());
72+
return doubleValue;
73+
}
74+
75+
private static double calculateLongLog(PyLong v) {
76+
int e[] = new int[1];
77+
double x = ((PyLong)v).scaledDoubleValue(e);
78+
if (x <= 0.0) throw Py.ValueError("math domain error");
79+
return log(x) + (e[0]*8.0)*log(2.0);
80+
}
81+
82+
private static double applyLoggedBase(double loggedValue, PyObject base) {
83+
double loggedBase;
84+
if (base instanceof PyLong) {
85+
loggedBase = calculateLongLog((PyLong)base);
86+
} else {
87+
loggedBase = log(base.__float__().getValue());
88+
}
89+
return check(loggedValue / loggedBase);
6690
}
6791

6892
private static double log(double v) {
@@ -162,4 +186,12 @@ public static double ldexp(double v, int w) {
162186
public static double hypot(double v, double w) {
163187
return check(ExtraMath.hypot(v, w));
164188
}
189+
190+
public static double radians(double v) {
191+
return check(Math.toRadians(v));
192+
}
193+
194+
public static double degrees(double v) {
195+
return check(Math.toDegrees(v));
196+
}
165197
}

0 commit comments

Comments
 (0)