提交 abd860d7 authored 作者: Olivier Breuleux's avatar Olivier Breuleux

added modulo

上级 7d72fa72
...@@ -277,6 +277,32 @@ DivInplaceTester = make_broadcast_tester(op = div_inplace, ...@@ -277,6 +277,32 @@ DivInplaceTester = make_broadcast_tester(op = div_inplace,
column = (rand(2, 3), rand(2, 1))), column = (rand(2, 3), rand(2, 1))),
inplace = True) inplace = True)
ModTester = make_broadcast_tester(op = mod,
expected = lambda x, y: x % y,
good = dict(same_shapes = (rand(2, 3), rand(2, 3)),
scalar = (rand(2, 3), rand(1, 1)),
row = (rand(2, 3), rand(1, 3)),
column = (rand(2, 3), rand(2, 1)),
dtype_mixup_1 = (rand(2, 3), randint_nonzero(2, 3)),
dtype_mixup_2 = (randint_nonzero(2, 3), rand(2, 3)),
# integers_positive = (randint_ranged(4, 10, (2, 3)), randint_ranged(1, 6, (2, 3))),
# integers_known_to_fail = (numpy.array(-1), numpy.array(5))
),
# integers = (randint(2, 3), randint_nonzero(2, 3)),
# dtype_mixup_1 = (rand(2, 3), randint_nonzero(2, 3)),
# dtype_mixup_2 = (randint_nonzero(2, 3), rand(2, 3))),
)
ModInplaceTester = make_broadcast_tester(op = mod_inplace,
expected = lambda x, y: x % y,
good = dict(same_shapes = (rand(2, 3), rand(2, 3)),
scalar = (rand(2, 3), rand(1, 1)),
row = (rand(2, 3), rand(1, 3)),
column = (rand(2, 3), rand(2, 1)),
dtype_mixup_1 = (rand(2, 3), randint_nonzero(2, 3)),
dtype_mixup_2 = (randint_nonzero(2, 3), rand(2, 3))
),
inplace = True)
PowTester = make_broadcast_tester(op = pow, PowTester = make_broadcast_tester(op = pow,
expected = lambda x, y: x ** y, expected = lambda x, y: x ** y,
good = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))), good = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
......
...@@ -13,6 +13,7 @@ from scipy import weave ...@@ -13,6 +13,7 @@ from scipy import weave
import cutils import cutils
import utils import utils
import traceback import traceback
import re
def compile_dir(): def compile_dir():
...@@ -69,10 +70,8 @@ class CodeBlock: ...@@ -69,10 +70,8 @@ class CodeBlock:
to jump to. It should also contain a key called 'failure_var' that contains to jump to. It should also contain a key called 'failure_var' that contains
the name of the variable that contains the error code. the name of the variable that contains the error code.
""" """
self.declare = declare #% sub self.declare = declare
# behavior_sub = copy(sub) self.behavior = behavior
# behavior_sub['fail'] = "{%(failure_var)s = %(id)s; goto __label_%(id)i;}" % sub
self.behavior = behavior #% behavior_sub
# the dummy is because gcc throws an error when a label's right next to a closing # the dummy is because gcc throws an error when a label's right next to a closing
# brace (maybe there's an ignore flag for that...) # brace (maybe there's an ignore flag for that...)
# we need the label even if cleanup is empty because the behavior block jumps there # we need the label even if cleanup is empty because the behavior block jumps there
...@@ -492,13 +491,14 @@ class CLinker(Linker): ...@@ -492,13 +491,14 @@ class CLinker(Linker):
args = [] args = []
args += ["storage_%s" % symbol[result] for result in utils.uniq(self.inputs + self.outputs + self.orphans)] args += ["storage_%s" % symbol[result] for result in utils.uniq(self.inputs + self.outputs + self.orphans)]
struct_code = struct_gen(args, init_blocks, blocks, dict(failure_var = failure_var, name = "%(name)s")) struct_code = struct_gen(args, init_blocks, blocks, dict(failure_var = failure_var, name = "<<<<NAME>>>>"))
# The hash calculated on the code identifies it so weave can cache properly. # The hash calculated on the code identifies it so weave can cache properly.
# (the hash has to be used outside of the support code because weave does not consider changes in the support code) # (the hash has to be used outside of the support code because weave does not consider changes in the support code)
hash = md5.md5(struct_code).hexdigest() hash = md5.md5(struct_code).hexdigest()
struct_name = '__struct_compiled_op_%s' % hash struct_name = '__struct_compiled_op_%s' % hash
struct_code %= dict(name = struct_name) #struct_code %= dict(name = struct_name)
struct_code = re.sub("<<<<NAME>>>>", struct_name, struct_code)
self.struct_code = struct_code self.struct_code = struct_code
self.struct_name = struct_name self.struct_name = struct_name
......
...@@ -203,6 +203,7 @@ class _scalar_py_operators: ...@@ -203,6 +203,7 @@ class _scalar_py_operators:
def __sub__(self,other): return sub(self,other) def __sub__(self,other): return sub(self,other)
def __mul__(self,other): return mul(self,other) def __mul__(self,other): return mul(self,other)
def __div__(self,other): return div(self,other) def __div__(self,other): return div(self,other)
def __mod__(self,other): return mod(self,other)
def __pow__(self,other): return pow(self,other) def __pow__(self,other): return pow(self,other)
#ARITHMETIC - RIGHT-OPERAND #ARITHMETIC - RIGHT-OPERAND
...@@ -210,6 +211,7 @@ class _scalar_py_operators: ...@@ -210,6 +211,7 @@ class _scalar_py_operators:
def __rsub__(self,other): return sub(other,self) def __rsub__(self,other): return sub(other,self)
def __rmul__(self,other): return mul(other,self) def __rmul__(self,other): return mul(other,self)
def __rdiv__(self,other): return div(other,self) def __rdiv__(self,other): return div(other,self)
def __rmod__(self,other): return mod(other,self)
def __rpow__(self,other): return pow(other,self) def __rpow__(self,other): return pow(other,self)
class ScalarResult(Result, _scalar_py_operators): class ScalarResult(Result, _scalar_py_operators):
...@@ -496,6 +498,17 @@ class Div(BinaryScalarOp): ...@@ -496,6 +498,17 @@ class Div(BinaryScalarOp):
return gz / y, -(gz * x) / (y * y) return gz / y, -(gz * x) / (y * y)
div = Div(upcast_out, name = 'div') div = Div(upcast_out, name = 'div')
class Mod(BinaryScalarOp):
def impl(self, x, y):
return x % y
def c_code(self, node, name, (x, y), (z, ), sub):
if node.inputs[0].type in int_types and node.inputs[1].type in int_types:
raise NotImplementedError("For integer arguments the behavior of division in C and in Python differ when the quotient is negative (to implement).")
return "%(z)s = %(x)s %% %(y)s;" % locals()
def grad(self, (x, y), (gz, )):
return None, None
mod = Mod(upcast_out, name = 'mod')
class Pow(BinaryScalarOp): class Pow(BinaryScalarOp):
def impl(self, x, y): def impl(self, x, y):
return x ** y return x ** y
......
...@@ -337,6 +337,7 @@ class _tensor_py_operators: ...@@ -337,6 +337,7 @@ class _tensor_py_operators:
def __mul__(self,other): return mul(self,other) def __mul__(self,other): return mul(self,other)
def __div__(self,other): return div(self,other) def __div__(self,other): return div(self,other)
def __pow__(self,other): return pow(self,other) def __pow__(self,other): return pow(self,other)
def __mod__(self,other): return mod(self,other)
#ARITHMETIC - INPLACE #ARITHMETIC - INPLACE
def __iadd__(self,other): return add_inplace(self,other) def __iadd__(self,other): return add_inplace(self,other)
...@@ -350,6 +351,7 @@ class _tensor_py_operators: ...@@ -350,6 +351,7 @@ class _tensor_py_operators:
def __rsub__(self,other): return sub(other,self) def __rsub__(self,other): return sub(other,self)
def __rmul__(self,other): return mul(other,self) def __rmul__(self,other): return mul(other,self)
def __rdiv__(self,other): return div(other,self) def __rdiv__(self,other): return div(other,self)
def __rmod__(self,other): return mod(other,self)
def __rpow__(self,other): return pow(other,self) def __rpow__(self,other): return pow(other,self)
#TRANSPOSE #TRANSPOSE
...@@ -572,6 +574,7 @@ add, add_inplace = _elemwise(scal.add, 'add') ...@@ -572,6 +574,7 @@ add, add_inplace = _elemwise(scal.add, 'add')
sub, sub_inplace = _elemwise(scal.sub, 'sub') sub, sub_inplace = _elemwise(scal.sub, 'sub')
mul, mul_inplace = _elemwise(scal.mul, 'mul') mul, mul_inplace = _elemwise(scal.mul, 'mul')
div, div_inplace = _elemwise(scal.div, 'div') div, div_inplace = _elemwise(scal.div, 'div')
mod, mod_inplace = _elemwise(scal.mod, 'mod')
pow, pow_inplace = _elemwise(scal.pow, 'pow') pow, pow_inplace = _elemwise(scal.pow, 'pow')
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论