提交 e642052b authored 作者: nouiz's avatar nouiz

Merge pull request #811 from bouchnic/new_elemwise

New elemwise NEWS.txt: NB added elemwise Trunc, Deg2Rad, Rad2Deg and Expm1
...@@ -1722,6 +1722,18 @@ class Floor(UnaryScalarOp): ...@@ -1722,6 +1722,18 @@ class Floor(UnaryScalarOp):
floor = Floor(same_out_nocomplex, name='floor') floor = Floor(same_out_nocomplex, name='floor')
class Trunc(UnaryScalarOp):
def impl(self, x):
return numpy.trunc(x)
def grad(self, (x,), (gz,)):
return None,
def c_code(self, node, name, (x,), (z,), sub):
return "%(z)s = %(x)s >= 0? floor(%(x)s): -floor(-%(x)s);" % locals()
trunc = Trunc(same_out_nocomplex, name='trunc')
class RoundHalfToEven(UnaryScalarOp): class RoundHalfToEven(UnaryScalarOp):
""" """
This function implement the same rounding than numpy: Round half to even This function implement the same rounding than numpy: Round half to even
...@@ -1978,6 +1990,25 @@ class Exp2(UnaryScalarOp): ...@@ -1978,6 +1990,25 @@ class Exp2(UnaryScalarOp):
exp2 = Exp2(upgrade_to_float, name='exp2') exp2 = Exp2(upgrade_to_float, name='exp2')
class Expm1(UnaryScalarOp):
def impl(self, x):
return numpy.expm1(x)
def grad(self, (x, ), (gz, )):
if x.type in complex_types:
raise NotImplementedError()
elif x.type in float_types:
return gz * exp(x),
else:
return None,
def c_code(self, node, name, (x, ), (z, ), sub):
if node.inputs[0].type in complex_types:
raise NotImplementedError('type not supported', type)
return "%(z)s = exp(%(x)s) - 1;" % locals()
expm1 = Expm1(upgrade_to_float, name='expm1')
class Sqr(UnaryScalarOp): class Sqr(UnaryScalarOp):
def impl(self, x): def impl(self, x):
return x * x return x * x
...@@ -2014,6 +2045,44 @@ class Sqrt(UnaryScalarOp): ...@@ -2014,6 +2045,44 @@ class Sqrt(UnaryScalarOp):
sqrt = Sqrt(upgrade_to_float, name='sqrt') sqrt = Sqrt(upgrade_to_float, name='sqrt')
class Deg2Rad(UnaryScalarOp):
def impl(self, x):
return numpy.deg2rad(x)
def grad(self, (x,), (gz,)):
if gz.type in complex_types:
raise NotImplementedError()
if x.type in float_types:
return gz * numpy.asarray(numpy.pi / 180, gz.type),
else:
return None,
def c_code(self, node, name, (x,), (z,), sub):
if node.inputs[0].type in complex_types:
raise NotImplementedError('type not supported', type)
return "%(z)s = %(x)s * (M_PI / 180.0);" % locals()
deg2rad = Deg2Rad(upgrade_to_float, name='deg2rad')
class Rad2Deg(UnaryScalarOp):
def impl(self, x):
return numpy.rad2deg(x)
def grad(self, (x,), (gz,)):
if gz.type in complex_types:
raise NotImplementedError()
if x.type in float_types:
return gz * numpy.asarray(180. / numpy.pi, gz.type),
else:
return None,
def c_code(self, node, name, (x,), (z,), sub):
if node.inputs[0].type in complex_types:
raise NotImplementedError('type not supported', type)
return "%(z)s = %(x)s * (180.0 / M_PI);" % locals()
rad2deg = Rad2Deg(upgrade_to_float, name='rad2deg')
class Cos(UnaryScalarOp): class Cos(UnaryScalarOp):
def impl(self, x): def impl(self, x):
return numpy.cos(x) return numpy.cos(x)
......
...@@ -2585,6 +2585,11 @@ def exp2(a): ...@@ -2585,6 +2585,11 @@ def exp2(a):
"""2^`a`""" """2^`a`"""
@_scal_elemwise_with_nfunc('expm1', 1, 1)
def expm1(a):
"""e^`a` - 1"""
@_scal_elemwise_with_nfunc('negative', 1, 1) @_scal_elemwise_with_nfunc('negative', 1, 1)
def neg(a): def neg(a):
"""-a""" """-a"""
...@@ -2632,6 +2637,11 @@ def floor(a): ...@@ -2632,6 +2637,11 @@ def floor(a):
"""floor of a""" """floor of a"""
@_scal_elemwise_with_nfunc('trunc', 1, 1)
def trunc(a):
"""trunc of a"""
@constructor @constructor
def iround(a, mode="half_away_from_zero"): def iround(a, mode="half_away_from_zero"):
"""cast(round(a,mode),'int64')""" """cast(round(a,mode),'int64')"""
...@@ -2673,6 +2683,16 @@ def sqrt(a): ...@@ -2673,6 +2683,16 @@ def sqrt(a):
"""square root of a""" """square root of a"""
@_scal_elemwise_with_nfunc('deg2rad', 1, 1)
def deg2rad(a):
"""convert degree a to radian"""
@_scal_elemwise_with_nfunc('rad2deg', 1, 1)
def rad2deg(a):
"""convert radian a to degree"""
@_scal_elemwise_with_nfunc('cos', 1, 1) @_scal_elemwise_with_nfunc('cos', 1, 1)
def cos(a): def cos(a):
"""cosine of a""" """cosine of a"""
......
...@@ -91,6 +91,10 @@ def exp_inplace(a): ...@@ -91,6 +91,10 @@ def exp_inplace(a):
def exp2_inplace(a): def exp2_inplace(a):
"""2^`a` (inplace on `a`)""" """2^`a` (inplace on `a`)"""
@_scal_inplace
def expm1_inplace(a):
"""e^`a` - 1 (inplace on `a`)"""
@_scal_inplace @_scal_inplace
def neg_inplace(a): def neg_inplace(a):
"""-a (inplace on a)""" """-a (inplace on a)"""
...@@ -127,6 +131,10 @@ def ceil_inplace(a): ...@@ -127,6 +131,10 @@ def ceil_inplace(a):
def floor_inplace(a): def floor_inplace(a):
"""floor of `a` (inplace on `a`)""" """floor of `a` (inplace on `a`)"""
@_scal_inplace
def trunc_inplace(a):
"""trunc of `a` (inplace on `a`)"""
@_scal_inplace @_scal_inplace
def round_half_to_even_inplace(a): def round_half_to_even_inplace(a):
"""round_half_to_even_inplace(a) (inplace on `a`)""" """round_half_to_even_inplace(a) (inplace on `a`)"""
...@@ -143,6 +151,14 @@ def sqr_inplace(a): ...@@ -143,6 +151,14 @@ def sqr_inplace(a):
def sqrt_inplace(a): def sqrt_inplace(a):
"""square root of `a` (inplace on `a`)""" """square root of `a` (inplace on `a`)"""
@_scal_inplace
def deg2rad_inplace(a):
"""convert degree `a` to radian(inplace on `a`)"""
@_scal_inplace
def rad2deg_inplace(a):
"""convert radian `a` to degree(inplace on `a`)"""
@_scal_inplace @_scal_inplace
def cos_inplace(a): def cos_inplace(a):
"""cosine of `a` (inplace on `a`)""" """cosine of `a` (inplace on `a`)"""
......
...@@ -810,6 +810,10 @@ _good_broadcast_unary_normal_no_complex = dict( ...@@ -810,6 +810,10 @@ _good_broadcast_unary_normal_no_complex = dict(
empty=[numpy.asarray([])], empty=[numpy.asarray([])],
) )
_grad_broadcast_unary_normal_no_complex = dict(
normal=[numpy.asarray(rand_ranged(-5, 5, (2, 3)), dtype=floatX)],
corner_case=[corner_case_grad])
_grad_broadcast_unary_normal = dict( _grad_broadcast_unary_normal = dict(
normal=[numpy.asarray(rand_ranged(-5, 5, (2, 3)), dtype=floatX)], normal=[numpy.asarray(rand_ranged(-5, 5, (2, 3)), dtype=floatX)],
corner_case = [corner_case_grad], corner_case = [corner_case_grad],
...@@ -905,6 +909,16 @@ FloorTester = makeBroadcastTester(op=tensor.floor, ...@@ -905,6 +909,16 @@ FloorTester = makeBroadcastTester(op=tensor.floor,
# yet it does not... # yet it does not...
grad=_grad_broadcast_unary_normal) grad=_grad_broadcast_unary_normal)
TruncInplaceTester = makeBroadcastTester(
op=inplace.floor_inplace,
expected=lambda a: numpy.asarray(numpy.floor(a), a.dtype),
good=_good_broadcast_unary_normal_no_complex,
inplace=True)
TruncTester = makeBroadcastTester(
op=tensor.floor,
expected=lambda a: numpy.asarray(numpy.floor(a), a.dtype),
good=_good_broadcast_unary_normal_no_complex)
FloorInplaceTester = makeBroadcastTester(op=inplace.floor_inplace, FloorInplaceTester = makeBroadcastTester(op=inplace.floor_inplace,
expected=lambda a: numpy.asarray(numpy.floor(a), a.dtype), expected=lambda a: numpy.asarray(numpy.floor(a), a.dtype),
good=_good_broadcast_unary_normal_no_complex, good=_good_broadcast_unary_normal_no_complex,
...@@ -966,6 +980,18 @@ Exp2InplaceTester = makeBroadcastTester(op=inplace.exp2_inplace, ...@@ -966,6 +980,18 @@ Exp2InplaceTester = makeBroadcastTester(op=inplace.exp2_inplace,
grad=_grad_broadcast_unary_normal, grad=_grad_broadcast_unary_normal,
inplace=True) inplace=True)
Expm1Tester = makeBroadcastTester(op=tensor.expm1,
expected=numpy.expm1,
good=_good_broadcast_unary_normal,
grad=_grad_broadcast_unary_normal)
Expm1InplaceTester = makeBroadcastTester(op=inplace.expm1_inplace,
expected=numpy.expm1,
good=_good_broadcast_unary_normal,
grad=_grad_broadcast_unary_normal,
inplace=True)
_good_broadcast_unary_positive = dict(normal=(rand_ranged(0.001, 5, (2, 3)),), _good_broadcast_unary_positive = dict(normal=(rand_ranged(0.001, 5, (2, 3)),),
integers=(randint_ranged(1, 5, (2, 3)),), integers=(randint_ranged(1, 5, (2, 3)),),
complex=(randc128_ranged(1, 5, (2, 3)),), complex=(randc128_ranged(1, 5, (2, 3)),),
...@@ -1031,6 +1057,39 @@ _good_broadcast_unary_wide = dict( ...@@ -1031,6 +1057,39 @@ _good_broadcast_unary_wide = dict(
empty=(numpy.asarray([]),),) empty=(numpy.asarray([]),),)
_grad_broadcast_unary_wide = dict(normal=(rand_ranged(-1000, 1000, (2, 3)),),) _grad_broadcast_unary_wide = dict(normal=(rand_ranged(-1000, 1000, (2, 3)),),)
if theano.config.floatX == 'float32':
angle_eps = 1e-4
else:
angle_eps = 1e-10
Deg2RadTester = makeBroadcastTester(
op=tensor.deg2rad,
expected=numpy.deg2rad,
good=_good_broadcast_unary_normal_no_complex,
grad=_grad_broadcast_unary_normal_no_complex,
eps=angle_eps)
Deg2RadInplaceTester = makeBroadcastTester(
op=inplace.deg2rad_inplace,
expected=numpy.deg2rad,
good=_good_broadcast_unary_normal_no_complex,
grad=_grad_broadcast_unary_normal_no_complex,
inplace=True,
eps=angle_eps)
Rad2DegTester = makeBroadcastTester(
op=tensor.rad2deg,
expected=numpy.rad2deg,
good=_good_broadcast_unary_normal_no_complex,
grad=_grad_broadcast_unary_normal_no_complex,
eps=angle_eps)
Rad2DegInplaceTester = makeBroadcastTester(
op=inplace.rad2deg_inplace,
expected=numpy.rad2deg,
good=_good_broadcast_unary_normal_no_complex,
grad=_grad_broadcast_unary_normal_no_complex,
inplace=True,
eps=angle_eps)
SinTester = makeBroadcastTester(op=tensor.sin, SinTester = makeBroadcastTester(op=tensor.sin,
expected=numpy.sin, expected=numpy.sin,
good=_good_broadcast_unary_wide, good=_good_broadcast_unary_wide,
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论