[pypy-commit] pypy default: (taavi) Merged numpy-ufuncs2, adds a ton of more ufuncs to numpypy.
alex_gaynor
noreply at buildbot.pypy.org
Fri Mar 16 21:58:41 CET 2012
Author: Alex Gaynor <alex.gaynor at gmail.com>
Branch:
Changeset: r53733:9bca9727b9a9
Date: 2012-03-16 15:57 -0500
http://bitbucket.org/pypy/pypy/changeset/9bca9727b9a9/
Log: (taavi) Merged numpy-ufuncs2, adds a ton of more ufuncs to numpypy.
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -67,6 +67,7 @@
("arccos", "arccos"),
("arcsin", "arcsin"),
("arctan", "arctan"),
+ ("arctan2", "arctan2"),
("arccosh", "arccosh"),
("arcsinh", "arcsinh"),
("arctanh", "arctanh"),
@@ -77,7 +78,10 @@
("true_divide", "true_divide"),
("equal", "equal"),
("exp", "exp"),
+ ("exp2", "exp2"),
+ ("expm1", "expm1"),
("fabs", "fabs"),
+ ("fmod", "fmod"),
("floor", "floor"),
("ceil", "ceil"),
("greater", "greater"),
@@ -92,8 +96,10 @@
("radians", "radians"),
("degrees", "degrees"),
("deg2rad", "radians"),
+ ("rad2deg", "degrees"),
("reciprocal", "reciprocal"),
("sign", "sign"),
+ ("signbit", "signbit"),
("sin", "sin"),
("sinh", "sinh"),
("subtract", "subtract"),
@@ -106,6 +112,9 @@
('bitwise_not', 'invert'),
('isnan', 'isnan'),
('isinf', 'isinf'),
+ ('isneginf', 'isneginf'),
+ ('isposinf', 'isposinf'),
+ ('isfinite', 'isfinite'),
('logical_and', 'logical_and'),
('logical_xor', 'logical_xor'),
('logical_not', 'logical_not'),
@@ -116,6 +125,8 @@
('log1p', 'log1p'),
('power', 'power'),
('floor_divide', 'floor_divide'),
+ ('logaddexp', 'logaddexp'),
+ ('logaddexp2', 'logaddexp2'),
]:
interpleveldefs[exposed] = "interp_ufuncs.get(space).%s" % impl
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -404,6 +404,9 @@
("greater_equal", "ge", 2, {"comparison_func": True}),
("isnan", "isnan", 1, {"bool_result": True}),
("isinf", "isinf", 1, {"bool_result": True}),
+ ("isneginf", "isneginf", 1, {"bool_result": True}),
+ ("isposinf", "isposinf", 1, {"bool_result": True}),
+ ("isfinite", "isfinite", 1, {"bool_result": True}),
('logical_and', 'logical_and', 2, {'comparison_func': True,
'identity': 1}),
@@ -421,12 +424,16 @@
("negative", "neg", 1),
("absolute", "abs", 1),
("sign", "sign", 1, {"promote_bools": True}),
+ ("signbit", "signbit", 1, {"bool_result": True}),
("reciprocal", "reciprocal", 1),
("fabs", "fabs", 1, {"promote_to_float": True}),
+ ("fmod", "fmod", 2, {"promote_to_float": True}),
("floor", "floor", 1, {"promote_to_float": True}),
("ceil", "ceil", 1, {"promote_to_float": True}),
("exp", "exp", 1, {"promote_to_float": True}),
+ ("exp2", "exp2", 1, {"promote_to_float": True}),
+ ("expm1", "expm1", 1, {"promote_to_float": True}),
('sqrt', 'sqrt', 1, {'promote_to_float': True}),
@@ -436,6 +443,7 @@
("arcsin", "arcsin", 1, {"promote_to_float": True}),
("arccos", "arccos", 1, {"promote_to_float": True}),
("arctan", "arctan", 1, {"promote_to_float": True}),
+ ("arctan2", "arctan2", 2, {"promote_to_float": True}),
("sinh", "sinh", 1, {"promote_to_float": True}),
("cosh", "cosh", 1, {"promote_to_float": True}),
("tanh", "tanh", 1, {"promote_to_float": True}),
@@ -450,6 +458,8 @@
("log2", "log2", 1, {"promote_to_float": True}),
("log10", "log10", 1, {"promote_to_float": True}),
("log1p", "log1p", 1, {"promote_to_float": True}),
+ ("logaddexp", "logaddexp", 2, {"promote_to_float": True}),
+ ("logaddexp2", "logaddexp2", 2, {"promote_to_float": True}),
]:
self.add_ufunc(space, *ufunc_def)
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -113,14 +113,37 @@
assert (divide(array([-10]), array([2])) == array([-5])).all()
+ def test_true_divide(self):
+ from _numpypy import array, true_divide
+
+ a = array([0, 1, 2, 3, 4, 1, -1])
+ b = array([4, 4, 4, 4, 4, 0, 0])
+ c = true_divide(a, b)
+ assert (c == [0.0, 0.25, 0.5, 0.75, 1.0, float('inf'), float('-inf')]).all()
+
+ assert math.isnan(true_divide(0, 0))
+
def test_fabs(self):
from _numpypy import array, fabs
- from math import fabs as math_fabs
+ from math import fabs as math_fabs, isnan
a = array([-5.0, -0.0, 1.0])
b = fabs(a)
for i in range(3):
assert b[i] == math_fabs(a[i])
+ assert fabs(float('inf')) == float('inf')
+ assert fabs(float('-inf')) == float('inf')
+ assert isnan(fabs(float('nan')))
+
+ def test_fmod(self):
+ from _numpypy import fmod
+ import math
+
+ assert fmod(-1e-100, 1e100) == -1e-100
+ assert fmod(3, float('inf')) == 3
+ assert (fmod([-3, -2, -1, 1, 2, 3], 2) == [-1, 0, -1, 1, 0, 1]).all()
+ for v in [float('inf'), float('-inf'), float('nan'), float('-nan')]:
+ assert math.isnan(fmod(v, 2))
def test_minimum(self):
from _numpypy import array, minimum
@@ -172,6 +195,15 @@
assert a[0] == 1
assert a[1] == 0
+ def test_signbit(self):
+ from _numpypy import signbit, copysign
+ import struct
+
+ assert (signbit([0, 0.0, 1, 1.0, float('inf'), float('nan')]) ==
+ [False, False, False, False, False, False]).all()
+ assert (signbit([-0, -0.0, -1, -1.0, float('-inf'), -float('nan'), float('-nan')]) ==
+ [False, True, True, True, True, True, True]).all()
+
def test_reciporocal(self):
from _numpypy import array, reciprocal
@@ -231,13 +263,46 @@
a = array([-5.0, -0.0, 0.0, 12345678.0, float("inf"),
-float('inf'), -12343424.0])
b = exp(a)
- for i in range(4):
+ for i in range(len(a)):
try:
res = math.exp(a[i])
except OverflowError:
res = float('inf')
assert b[i] == res
+ def test_exp2(self):
+ import math
+ from _numpypy import array, exp2
+
+ a = array([-5.0, -0.0, 0.0, 2, 12345678.0, float("inf"),
+ -float('inf'), -12343424.0])
+ b = exp2(a)
+ for i in range(len(a)):
+ try:
+ res = 2 ** a[i]
+ except OverflowError:
+ res = float('inf')
+ assert b[i] == res
+
+ assert exp2(3) == 8
+ assert math.isnan(exp2(float("nan")))
+
+ def test_expm1(self):
+ import math
+ from _numpypy import array, expm1
+
+ a = array([-5.0, -0.0, 0.0, 12345678.0, float("inf"),
+ -float('inf'), -12343424.0])
+ b = expm1(a)
+ for i in range(4):
+ try:
+ res = math.exp(a[i]) - 1
+ except OverflowError:
+ res = float('inf')
+ assert b[i] == res
+
+ assert expm1(1e-50) == 1e-50
+
def test_sin(self):
import math
from _numpypy import array, sin
@@ -310,6 +375,21 @@
b = arctan(a)
assert math.isnan(b[0])
+ def test_arctan2(self):
+ import math
+ from _numpypy import array, arctan2
+
+ # From the numpy documentation
+ assert (
+ arctan2(
+ [0., 0., 1., -1., float('inf'), float('inf')],
+ [0., -0., float('inf'), float('inf'), float('inf'), float('-inf')]) ==
+ [0., math.pi, 0., -0., math.pi/4, 3*math.pi/4]).all()
+
+ a = array([float('nan')])
+ b = arctan2(a, 0)
+ assert math.isnan(b[0])
+
def test_sinh(self):
import math
from _numpypy import array, sinh
@@ -415,6 +495,19 @@
for i in range(len(a)):
assert b[i] == math.degrees(a[i])
+ def test_rad2deg(self):
+ import math
+ from _numpypy import rad2deg, array
+ a = array([
+ -181, -180, -179,
+ 181, 180, 179,
+ 359, 360, 361,
+ 400, -1, 0, 1,
+ float('inf'), float('-inf')])
+ b = rad2deg(a)
+ for i in range(len(a)):
+ assert b[i] == math.degrees(a[i])
+
def test_reduce_errors(self):
from _numpypy import sin, add
@@ -510,6 +603,26 @@
assert (isinf(array([0.2, float('inf'), float('nan')])) == [False, True, False]).all()
assert isinf(array([0.2])).dtype.kind == 'b'
+ def test_isposinf_isneginf(self):
+ from _numpypy import isneginf, isposinf
+ assert isposinf(float('inf'))
+ assert not isposinf(float('-inf'))
+ assert not isposinf(float('nan'))
+ assert not isposinf(0)
+ assert not isposinf(0.0)
+ assert isneginf(float('-inf'))
+ assert not isneginf(float('inf'))
+ assert not isneginf(float('nan'))
+ assert not isneginf(0)
+ assert not isneginf(0.0)
+
+ def test_isfinite(self):
+ from _numpypy import isfinite
+ assert (isfinite([0, 0.0, 1e50, -1e-50]) ==
+ [True, True, True, True]).all()
+ assert (isfinite([float('-inf'), float('inf'), float('-nan'), float('nan')]) ==
+ [False, False, False, False]).all()
+
def test_logical_ops(self):
from _numpypy import logical_and, logical_or, logical_xor, logical_not
@@ -544,7 +657,7 @@
assert log1p(float('inf')) == float('inf')
assert (log1p([0, 1e-50, math.e - 1]) == [0, 1e-50, 1]).all()
- def test_power(self):
+ def test_power_float(self):
import math
from _numpypy import power, array
a = array([1., 2., 3.])
@@ -558,9 +671,94 @@
for i in range(len(a)):
assert c[i] == a[i] ** b[i]
+ assert power(2, float('inf')) == float('inf')
+ assert power(float('inf'), float('inf')) == float('inf')
+ assert power(12345.0, 12345.0) == float('inf')
+ assert power(-12345.0, 12345.0) == float('-inf')
+ assert power(-12345.0, 12346.0) == float('inf')
+ assert math.isnan(power(-1, 1.1))
+ assert math.isnan(power(-1, -1.1))
+ assert power(-2.0, -1) == -0.5
+ assert power(-2.0, -2) == 0.25
+ assert power(12345.0, -12345.0) == 0
+ assert power(float('-inf'), 2) == float('inf')
+ assert power(float('-inf'), 2.5) == float('inf')
+ assert power(float('-inf'), 3) == float('-inf')
+
+ def test_power_int(self):
+ import math
+ from _numpypy import power, array
+ a = array([1, 2, 3])
+ b = power(a, 3)
+ for i in range(len(a)):
+ assert b[i] == a[i] ** 3
+
+ a = array([1, 2, 3])
+ b = array([1, 2, 3])
+ c = power(a, b)
+ for i in range(len(a)):
+ assert c[i] == a[i] ** b[i]
+
+ # assert power(12345, 12345) == -9223372036854775808
+ # assert power(-12345, 12345) == -9223372036854775808
+ # assert power(-12345, 12346) == -9223372036854775808
+ assert power(2, 0) == 1
+ assert power(2, -1) == 0
+ assert power(2, -2) == 0
+ assert power(-2, -1) == 0
+ assert power(-2, -2) == 0
+ assert power(12345, -12345) == 0
+
def test_floordiv(self):
from _numpypy import floor_divide, array
a = array([1., 2., 3., 4., 5., 6., 6.01])
b = floor_divide(a, 2.5)
for i in range(len(a)):
assert b[i] == a[i] // 2.5
+
+ def test_logaddexp(self):
+ import math
+ from _numpypy import logaddexp
+
+ # From the numpy documentation
+ prob1 = math.log(1e-50)
+ prob2 = math.log(2.5e-50)
+ prob12 = logaddexp(prob1, prob2)
+ assert math.fabs(-113.87649168120691 - prob12) < 0.000000000001
+
+ assert logaddexp(0, 0) == math.log(2)
+ assert logaddexp(float('-inf'), 0) == 0
+ assert logaddexp(12345678, 12345678) == float('inf')
+
+ assert math.isnan(logaddexp(float('nan'), 1))
+ assert math.isnan(logaddexp(1, float('nan')))
+ assert math.isnan(logaddexp(float('nan'), float('inf')))
+ assert math.isnan(logaddexp(float('inf'), float('nan')))
+ assert logaddexp(float('-inf'), float('-inf')) == float('-inf')
+ assert logaddexp(float('-inf'), float('inf')) == float('inf')
+ assert logaddexp(float('inf'), float('-inf')) == float('inf')
+ assert logaddexp(float('inf'), float('inf')) == float('inf')
+
+ def test_logaddexp2(self):
+ import math
+ from _numpypy import logaddexp2
+ log2 = math.log(2)
+
+ # From the numpy documentation
+ prob1 = math.log(1e-50) / log2
+ prob2 = math.log(2.5e-50) / log2
+ prob12 = logaddexp2(prob1, prob2)
+ assert math.fabs(-164.28904982231052 - prob12) < 0.000000000001
+
+ assert logaddexp2(0, 0) == 1
+ assert logaddexp2(float('-inf'), 0) == 0
+ assert logaddexp2(12345678, 12345678) == float('inf')
+
+ assert math.isnan(logaddexp2(float('nan'), 1))
+ assert math.isnan(logaddexp2(1, float('nan')))
+ assert math.isnan(logaddexp2(float('nan'), float('inf')))
+ assert math.isnan(logaddexp2(float('inf'), float('nan')))
+ assert logaddexp2(float('-inf'), float('-inf')) == float('-inf')
+ assert logaddexp2(float('-inf'), float('inf')) == float('inf')
+ assert logaddexp2(float('inf'), float('-inf')) == float('inf')
+ assert logaddexp2(float('inf'), float('inf')) == float('inf')
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -155,6 +155,14 @@
def isinf(self, v):
return False
+ @raw_unary_op
+ def isneginf(self, v):
+ return False
+
+ @raw_unary_op
+ def isposinf(self, v):
+ return False
+
@raw_binary_op
def eq(self, v1, v2):
return v1 == v2
@@ -293,6 +301,8 @@
@simple_binary_op
def pow(self, v1, v2):
+ if v2 < 0:
+ return 0
res = 1
while v2 > 0:
if v2 & 1:
@@ -440,7 +450,15 @@
@simple_binary_op
def pow(self, v1, v2):
- return math.pow(v1, v2)
+ try:
+ return math.pow(v1, v2)
+ except ValueError:
+ return rfloat.NAN
+ except OverflowError:
+ if math.modf(v2)[0] == 0 and math.modf(v2 / 2)[0] != 0:
+ # Odd integer powers result in the same sign as the base
+ return rfloat.copysign(rfloat.INFINITY, v1)
+ return rfloat.INFINITY
@simple_binary_op
def copysign(self, v1, v2):
@@ -452,10 +470,21 @@
return 0.0
return rfloat.copysign(1.0, v)
+ @raw_unary_op
+ def signbit(self, v):
+ return rfloat.copysign(1.0, v) < 0.0
+
@simple_unary_op
def fabs(self, v):
return math.fabs(v)
+ @simple_binary_op
+ def fmod(self, v1, v2):
+ try:
+ return math.fmod(v1, v2)
+ except ValueError:
+ return rfloat.NAN
+
@simple_unary_op
def reciprocal(self, v):
if v == 0.0:
@@ -478,6 +507,20 @@
return rfloat.INFINITY
@simple_unary_op
+ def exp2(self, v):
+ try:
+ return math.pow(2, v)
+ except OverflowError:
+ return rfloat.INFINITY
+
+ @simple_unary_op
+ def expm1(self, v):
+ try:
+ return rfloat.expm1(v)
+ except OverflowError:
+ return rfloat.INFINITY
+
+ @simple_unary_op
def sin(self, v):
return math.sin(v)
@@ -505,6 +548,10 @@
def arctan(self, v):
return math.atan(v)
+ @simple_binary_op
+ def arctan2(self, v1, v2):
+ return math.atan2(v1, v2)
+
@simple_unary_op
def sinh(self, v):
return math.sinh(v)
@@ -550,6 +597,18 @@
def isinf(self, v):
return rfloat.isinf(v)
+ @raw_unary_op
+ def isneginf(self, v):
+ return rfloat.isinf(v) and v < 0
+
+ @raw_unary_op
+ def isposinf(self, v):
+ return rfloat.isinf(v) and v > 0
+
+ @raw_unary_op
+ def isfinite(self, v):
+ return not (rfloat.isinf(v) or rfloat.isnan(v))
+
@simple_unary_op
def radians(self, v):
return v * degToRad
@@ -601,6 +660,48 @@
except ValueError:
return rfloat.NAN
+ @simple_binary_op
+ def logaddexp(self, v1, v2):
+ try:
+ v1e = math.exp(v1)
+ except OverflowError:
+ v1e = rfloat.INFINITY
+ try:
+ v2e = math.exp(v2)
+ except OverflowError:
+ v2e = rfloat.INFINITY
+
+ v12e = v1e + v2e
+ try:
+ return math.log(v12e)
+ except ValueError:
+ if v12e == 0.0:
+ # CPython raises ValueError here, so we have to check
+ # the value to find the correct numpy return value
+ return -rfloat.INFINITY
+ return rfloat.NAN
+
+ @simple_binary_op
+ def logaddexp2(self, v1, v2):
+ try:
+ v1e = math.pow(2, v1)
+ except OverflowError:
+ v1e = rfloat.INFINITY
+ try:
+ v2e = math.pow(2, v2)
+ except OverflowError:
+ v2e = rfloat.INFINITY
+
+ v12e = v1e + v2e
+ try:
+ return math.log(v12e) / log2
+ except ValueError:
+ if v12e == 0.0:
+ # CPython raises ValueError here, so we have to check
+ # the value to find the correct numpy return value
+ return -rfloat.INFINITY
+ return rfloat.NAN
+
class Float32(BaseType, Float):
T = rffi.FLOAT
More information about the pypy-commit
mailing list