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

added modulo

上级 7d72fa72
......@@ -277,6 +277,32 @@ DivInplaceTester = make_broadcast_tester(op = div_inplace,
column = (rand(2, 3), rand(2, 1))),
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,
expected = lambda x, y: x ** y,
good = dict(same_shapes = (rand_ranged(1, 5, (2, 3)), rand_ranged(-3, 3, (2, 3))),
......
......@@ -13,6 +13,7 @@ from scipy import weave
import cutils
import utils
import traceback
import re
def compile_dir():
......@@ -69,10 +70,8 @@ class CodeBlock:
to jump to. It should also contain a key called 'failure_var' that contains
the name of the variable that contains the error code.
"""
self.declare = declare #% sub
# behavior_sub = copy(sub)
# behavior_sub['fail'] = "{%(failure_var)s = %(id)s; goto __label_%(id)i;}" % sub
self.behavior = behavior #% behavior_sub
self.declare = declare
self.behavior = behavior
# 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...)
# we need the label even if cleanup is empty because the behavior block jumps there
......@@ -492,13 +491,14 @@ class CLinker(Linker):
args = []
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 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()
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_name = struct_name
......
......@@ -203,6 +203,7 @@ class _scalar_py_operators:
def __sub__(self,other): return sub(self,other)
def __mul__(self,other): return mul(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)
#ARITHMETIC - RIGHT-OPERAND
......@@ -210,6 +211,7 @@ class _scalar_py_operators:
def __rsub__(self,other): return sub(other,self)
def __rmul__(self,other): return mul(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)
class ScalarResult(Result, _scalar_py_operators):
......@@ -496,6 +498,17 @@ class Div(BinaryScalarOp):
return gz / y, -(gz * x) / (y * y)
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):
def impl(self, x, y):
return x ** y
......
......@@ -337,6 +337,7 @@ class _tensor_py_operators:
def __mul__(self,other): return mul(self,other)
def __div__(self,other): return div(self,other)
def __pow__(self,other): return pow(self,other)
def __mod__(self,other): return mod(self,other)
#ARITHMETIC - INPLACE
def __iadd__(self,other): return add_inplace(self,other)
......@@ -350,6 +351,7 @@ class _tensor_py_operators:
def __rsub__(self,other): return sub(other,self)
def __rmul__(self,other): return mul(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)
#TRANSPOSE
......@@ -572,6 +574,7 @@ add, add_inplace = _elemwise(scal.add, 'add')
sub, sub_inplace = _elemwise(scal.sub, 'sub')
mul, mul_inplace = _elemwise(scal.mul, 'mul')
div, div_inplace = _elemwise(scal.div, 'div')
mod, mod_inplace = _elemwise(scal.mod, 'mod')
pow, pow_inplace = _elemwise(scal.pow, 'pow')
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论