Author: Alex Gaynor <[email protected]>
Branch: numpy-exp
Changeset: r44164:1b189fc3a310
Date: 2011-05-14 11:39 -0500
http://bitbucket.org/pypy/pypy/changeset/1b189fc3a310/
Log: Started implementing ufuncs, so far only added negative, but this
also includes all the low level support for the compiler to handle
calls, so things like ``5 * negative(ar + ar)`` still don't have
temporary intermediates.
diff --git a/pypy/jit/backend/llgraph/runner.py
b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -209,7 +209,7 @@
llimpl.compile_add_fail_arg(c, var2index[box])
else:
llimpl.compile_add_fail_arg(c, -1)
-
+
x = op.result
if x is not None:
if isinstance(x, history.BoxInt):
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
@@ -1,13 +1,16 @@
-from pypy.interpreter.mixedmodule import MixedModule
+from pypy.interpreter.mixedmodule import MixedModule
class Module(MixedModule):
applevel_name = 'numpy'
-
+
interpleveldefs = {
- 'array': 'numarray.SingleDimArray',
- 'zeros': 'numarray.zeros',
+ 'array': 'interp_numarray.SingleDimArray',
+ 'zeros': 'interp_numarray.zeros',
+
+ # ufuncs
+ 'negative': 'interp_ufuncs.negative',
}
appleveldefs = {}
diff --git a/pypy/module/micronumpy/interp_numarray.py
b/pypy/module/micronumpy/interp_numarray.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -0,0 +1,367 @@
+from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
+from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef
+from pypy.rlib import jit
+from pypy.rlib.nonconst import NonConstant
+from pypy.rpython.lltypesystem import lltype
+from pypy.tool.sourcetools import func_with_new_name
+
+
+def dummy1(v):
+ assert isinstance(v, float)
+ return v
+
+def dummy2(v):
+ assert isinstance(v, float)
+ return v
+
+TP = lltype.Array(lltype.Float, hints={'nolength': True})
+
+numpy_driver = jit.JitDriver(greens = ['bytecode_pos', 'bytecode'],
+ reds = ['result_size', 'i', 'frame',
+ 'result'],
+ virtualizables = ['frame'])
+
+class ComputationFrame(object):
+ _virtualizable2_ = ['valuestackdepth', 'valuestack[*]',
+ 'array_pos', 'arrays[*]',
+ 'float_pos', 'floats[*]',
+ 'function_pos', 'functions[*]',
+ ]
+
+ def __init__(self, arrays, floats, functions):
+ self = jit.hint(self, access_directly=True, fresh_virtualizable=True)
+ self.valuestackdepth = 0
+ self.arrays = arrays
+ self.array_pos = len(arrays)
+ self.floats = floats
+ if NonConstant(0):
+ self.floats = [3.5] # annotator hack for test_zjit
+ self.float_pos = len(floats)
+ self.functions = functions
+ if NonConstant(0):
+ self.functions = [dummy1, dummy2] # another annotator hack
+ self.function_pos = len(functions)
+ self.valuestack = [0.0] * (len(arrays) + len(floats))
+
+ def reset(self):
+ self.valuestackdepth = 0
+ self.array_pos = len(self.arrays)
+ self.float_pos = len(self.floats)
+ self.function_pos = len(self.functions)
+
+ def _get_item(value):
+ pos_name = value + "_pos"
+ array_name = value + "s"
+ def impl(self):
+ p = getattr(self, pos_name) - 1
+ assert p >= 0
+ res = getattr(self, array_name)[p]
+ setattr(self, pos_name, p)
+ return res
+ return func_with_new_name(impl, "get" + value)
+
+ getarray = _get_item("array")
+ getfloat = _get_item("float")
+ getfunction = _get_item("function")
+
+ def popvalue(self):
+ v = self.valuestackdepth - 1
+ assert v >= 0
+ res = self.valuestack[v]
+ self.valuestackdepth = v
+ return res
+
+ def pushvalue(self, v):
+ self.valuestack[self.valuestackdepth] = v
+ self.valuestackdepth += 1
+
+class Code(object):
+ """
+ A chunk of bytecode.
+ """
+
+ def __init__(self, bytecode, arrays=None, floats=None, functions=None):
+ self.bytecode = bytecode
+ self.arrays = arrays or []
+ self.floats = floats or []
+ self.functions = functions or []
+
+ def merge(self, code, other):
+ """
+ Merge this bytecode with the other bytecode, using ``code`` as the
+ bytecode instruction for performing the merge.
+ """
+
+ return Code(code + self.bytecode + other.bytecode,
+ self.arrays + other.arrays,
+ self.floats + other.floats,
+ self.functions + other.functions)
+
+ def intern(self):
+ # the point of these hacks is to intern the bytecode string otherwise
+ # we have to compile new assembler each time, which sucks (we still
+ # have to compile new bytecode, but too bad)
+ try:
+ self.bytecode = JITCODES[self.bytecode]
+ except KeyError:
+ JITCODES[self.bytecode] = self.bytecode
+
+ def compute(self):
+ """
+ Crunch a ``Code`` full of bytecode.
+ """
+
+ bytecode = self.bytecode
+ result_size = self.arrays[0].size
+ result = SingleDimArray(result_size)
+ bytecode_pos = len(bytecode) - 1
+ i = 0
+ frame = ComputationFrame(self.arrays, self.floats, self.functions)
+ while i < result_size:
+ numpy_driver.jit_merge_point(bytecode=bytecode, result=result,
+ result_size=result_size,
+ i=i, frame=frame,
+ bytecode_pos=bytecode_pos)
+ if bytecode_pos == -1:
+ bytecode_pos = len(bytecode) - 1
+ frame.reset()
+ result.storage[i] = frame.valuestack[0]
+ i += 1
+ numpy_driver.can_enter_jit(bytecode=bytecode, result=result,
+ result_size=result_size,
+ i=i, frame=frame,
+ bytecode_pos=bytecode_pos)
+ else:
+ opcode = bytecode[bytecode_pos]
+ if opcode == 'l':
+ # Load array.
+ val = frame.getarray().storage[i]
+ frame.pushvalue(val)
+ elif opcode == 'f':
+ # Load float.
+ val = frame.getfloat()
+ frame.pushvalue(val)
+ elif opcode == 'a':
+ # Add.
+ a = frame.popvalue()
+ b = frame.popvalue()
+ frame.pushvalue(a + b)
+ elif opcode == 's':
+ # Subtract
+ a = frame.popvalue()
+ b = frame.popvalue()
+ frame.pushvalue(a - b)
+ elif opcode == 'm':
+ # Multiply.
+ a = frame.popvalue()
+ b = frame.popvalue()
+ frame.pushvalue(a * b)
+ elif opcode == 'd':
+ a = frame.popvalue()
+ b = frame.popvalue()
+ frame.pushvalue(a / b)
+ elif opcode == 'c':
+ func = frame.getfunction()
+ val = frame.popvalue()
+ frame.pushvalue(func(val))
+ else:
+ raise NotImplementedError(
+ "Can't handle bytecode instruction %s" % opcode)
+ bytecode_pos -= 1
+ return result
+
+JITCODES = {}
+
+class BaseArray(Wrappable):
+ def __init__(self):
+ self.invalidates = []
+
+ def force(self):
+ code = self.compile()
+ code.intern()
+ return code.compute()
+
+ def invalidated(self):
+ for arr in self.invalidates:
+ arr.force_if_needed()
+ self.invalidates = []
+
+ def _binop_impl(bytecode):
+ def impl(self, space, w_other):
+ if isinstance(w_other, BaseArray):
+ res = space.wrap(BinOp(bytecode, self, w_other))
+ w_other.invalidates.append(res)
+ else:
+ res = space.wrap(BinOp(
+ bytecode,
+ self,
+ FloatWrapper(space.float_w(w_other))
+ ))
+ self.invalidates.append(res)
+ return res
+ return func_with_new_name(impl, "binop_%s_impl" % bytecode)
+
+ descr_add = _binop_impl("a")
+ descr_sub = _binop_impl("s")
+ descr_mul = _binop_impl("m")
+ descr_div = _binop_impl("d")
+
+ def compile(self):
+ raise NotImplementedError("abstract base class")
+
+class FloatWrapper(BaseArray):
+ """
+ Intermediate class representing a float literal.
+ """
+
+ def __init__(self, float_value):
+ BaseArray.__init__(self)
+ self.float_value = float_value
+
+ def compile(self):
+ return Code('f', floats=[self.float_value])
+
+class VirtualArray(BaseArray):
+ """
+ Class for representing virtual arrays, such as binary ops or ufuncs
+ """
+ def __init__(self):
+ BaseArray.__init__(self)
+ self.forced_result = None
+
+ def compile(self):
+ if self.forced_result is not None:
+ return self.forced_result.compile()
+
+ def force_if_needed(self):
+ if self.forced_result is None:
+ self.forced_result = self.force()
+
+ def descr_len(self, space):
+ self.force_if_needed()
+ return self.forced_result.descr_len(space)
+
+ @unwrap_spec(item=int)
+ def descr_getitem(self, space, item):
+ self.force_if_needed()
+ return self.forced_result.descr_getitem(space, item)
+
+ @unwrap_spec(item=int, value=float)
+ def descr_setitem(self, space, item, value):
+ self.force_if_needed()
+ self.invalidated()
+ return self.forced_result.descr_setitem(space, item, value)
+
+
+class BinOp(VirtualArray):
+ """
+ Intermediate class for performing binary operations.
+ """
+
+ def __init__(self, opcode, left, right):
+ VirtualArray.__init__(self)
+ self.opcode = opcode
+ self.left = left
+ self.right = right
+
+ def compile(self):
+ result = VirtualArray.compile(self)
+ if result is not None:
+ return result
+
+ left_code = self.left.compile()
+ right_code = self.right.compile()
+ return left_code.merge(self.opcode, right_code)
+
+class Call(VirtualArray):
+ def __init__(self, function, values):
+ VirtualArray.__init__(self)
+ self.function = function
+ self.values = values
+
+ def compile(self):
+ result = VirtualArray.compile(self)
+ if result is not None:
+ return result
+ return Code('', functions=[self.function]).merge('c',
self.values.compile())
+
+
+VirtualArray.typedef = TypeDef(
+ 'Operation',
+ __len__ = interp2app(VirtualArray.descr_len),
+ __getitem__ = interp2app(VirtualArray.descr_getitem),
+ __setitem__ = interp2app(VirtualArray.descr_setitem),
+
+ __add__ = interp2app(BaseArray.descr_add),
+ __sub__ = interp2app(BaseArray.descr_sub),
+ __mul__ = interp2app(BaseArray.descr_mul),
+ __div__ = interp2app(BaseArray.descr_div),
+)
+
+class SingleDimArray(BaseArray):
+ def __init__(self, size):
+ BaseArray.__init__(self)
+ self.size = size
+ self.storage = lltype.malloc(TP, size, zero=True,
+ flavor='raw', track_allocation=False)
+ # XXX find out why test_zjit explodes with trackign of allocations
+
+ def compile(self):
+ return Code('l', arrays=[self])
+
+ def getindex(self, space, item):
+ if item >= self.size:
+ raise operationerrfmt(space.w_IndexError,
+ '%d above array size', item)
+ if item < 0:
+ item += self.size
+ if item < 0:
+ raise operationerrfmt(space.w_IndexError,
+ '%d below zero', item)
+ return item
+
+ def descr_len(self, space):
+ return space.wrap(self.size)
+
+ @unwrap_spec(item=int)
+ def descr_getitem(self, space, item):
+ item = self.getindex(space, item)
+ return space.wrap(self.storage[item])
+
+ @unwrap_spec(item=int, value=float)
+ def descr_setitem(self, space, item, value):
+ item = self.getindex(space, item)
+ self.invalidated()
+ self.storage[item] = value
+
+ def __del__(self):
+ lltype.free(self.storage, flavor='raw')
+
+def descr_new_numarray(space, w_type, w_size_or_iterable):
+ l = space.listview(w_size_or_iterable)
+ arr = SingleDimArray(len(l))
+ i = 0
+ for w_elem in l:
+ arr.storage[i] = space.float_w(space.float(w_elem))
+ i += 1
+ return space.wrap(arr)
+
+@unwrap_spec(ObjSpace, int)
+def zeros(space, size):
+ return space.wrap(SingleDimArray(size))
+
+
+SingleDimArray.typedef = TypeDef(
+ 'numarray',
+ __new__ = interp2app(descr_new_numarray),
+ __len__ = interp2app(SingleDimArray.descr_len),
+ __getitem__ = interp2app(SingleDimArray.descr_getitem),
+ __setitem__ = interp2app(SingleDimArray.descr_setitem),
+
+ __add__ = interp2app(BaseArray.descr_add),
+ __sub__ = interp2app(BaseArray.descr_sub),
+ __mul__ = interp2app(BaseArray.descr_mul),
+ __div__ = interp2app(BaseArray.descr_div),
+)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/interp_ufuncs.py
b/pypy/module/micronumpy/interp_ufuncs.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -0,0 +1,10 @@
+from pypy.interpreter.gateway import unwrap_spec
+from pypy.module.micronumpy.interp_numarray import BaseArray, Call
+
+
+def negative_impl(value):
+ return -value
+
+@unwrap_spec(array=BaseArray)
+def negative(space, array):
+ return Call(negative_impl, array)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/numarray.py
b/pypy/module/micronumpy/numarray.py
deleted file mode 100644
--- a/pypy/module/micronumpy/numarray.py
+++ /dev/null
@@ -1,322 +0,0 @@
-from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
-from pypy.interpreter.error import operationerrfmt
-from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.typedef import TypeDef
-from pypy.rlib import jit
-from pypy.rlib.nonconst import NonConstant
-from pypy.rpython.lltypesystem import lltype
-from pypy.tool.sourcetools import func_with_new_name
-
-
-TP = lltype.Array(lltype.Float, hints={'nolength': True})
-
-numpy_driver = jit.JitDriver(greens = ['bytecode_pos', 'bytecode'],
- reds = ['result_size', 'i', 'frame',
- 'result'],
- virtualizables = ['frame'])
-
-class ComputationFrame(object):
- _virtualizable2_ = ['valuestackdepth', 'valuestack[*]',
- 'array_pos', 'arrays[*]',
- 'float_pos', 'floats[*]',
- ]
-
- def __init__(self, arrays, floats):
- self = jit.hint(self, access_directly=True, fresh_virtualizable=True)
- self.valuestackdepth = 0
- self.arrays = arrays
- self.array_pos = len(arrays)
- self.floats = floats
- if NonConstant(0):
- self.floats = [3.5] # annotator hack for test_jit
- self.float_pos = len(floats)
- self.valuestack = [0.0] * (len(arrays) + len(floats))
-
- def reset(self):
- self.valuestackdepth = 0
- self.array_pos = len(self.arrays)
- self.float_pos = len(self.floats)
-
- def getarray(self):
- p = self.array_pos - 1
- assert p >= 0
- res = self.arrays[p]
- self.array_pos = p
- return res
-
- def getfloat(self):
- p = self.float_pos - 1
- assert p >= 0
- res = self.floats[p]
- self.float_pos = p
- return res
-
- def popvalue(self):
- v = self.valuestackdepth - 1
- assert v >= 0
- res = self.valuestack[v]
- self.valuestackdepth = v
- return res
-
- def pushvalue(self, v):
- self.valuestack[self.valuestackdepth] = v
- self.valuestackdepth += 1
-
-class Code(object):
- """
- A chunk of bytecode.
- """
-
- def __init__(self, bytecode, arrays, floats):
- self.bytecode = bytecode
- self.arrays = arrays
- self.floats = floats
-
- def merge(self, code, other):
- """
- Merge this bytecode with the other bytecode, using ``code`` as the
- bytecode instruction for performing the merge.
- """
-
- return Code(code + self.bytecode + other.bytecode,
- self.arrays + other.arrays,
- self.floats + other.floats)
-
- def intern(self):
- # the point of these hacks is to intern the bytecode string otherwise
- # we have to compile new assembler each time, which sucks (we still
- # have to compile new bytecode, but too bad)
- try:
- self.bytecode = JITCODES[self.bytecode]
- except KeyError:
- JITCODES[self.bytecode] = self.bytecode
-
- def compute(self):
- """
- Crunch a ``Code`` full of bytecode.
- """
-
- bytecode = self.bytecode
- result_size = self.arrays[0].size
- result = SingleDimArray(result_size)
- bytecode_pos = len(bytecode) - 1
- i = 0
- frame = ComputationFrame(self.arrays, self.floats)
- while i < result_size:
- numpy_driver.jit_merge_point(bytecode=bytecode, result=result,
- result_size=result_size,
- i=i, frame=frame,
- bytecode_pos=bytecode_pos)
- if bytecode_pos == -1:
- bytecode_pos = len(bytecode) - 1
- frame.reset()
- result.storage[i] = frame.valuestack[0]
- i += 1
- numpy_driver.can_enter_jit(bytecode=bytecode, result=result,
- result_size=result_size,
- i=i, frame=frame,
- bytecode_pos=bytecode_pos)
- else:
- opcode = bytecode[bytecode_pos]
- if opcode == 'l':
- # Load array.
- val = frame.getarray().storage[i]
- frame.pushvalue(val)
- elif opcode == 'f':
- # Load float.
- val = frame.getfloat()
- frame.pushvalue(val)
- elif opcode == 'a':
- # Add.
- a = frame.popvalue()
- b = frame.popvalue()
- frame.pushvalue(a + b)
- elif opcode == 's':
- # Subtract
- a = frame.popvalue()
- b = frame.popvalue()
- frame.pushvalue(a - b)
- elif opcode == 'm':
- # Multiply.
- a = frame.popvalue()
- b = frame.popvalue()
- frame.pushvalue(a * b)
- elif opcode == 'd':
- a = frame.popvalue()
- b = frame.popvalue()
- frame.pushvalue(a / b)
- else:
- raise NotImplementedError(
- "Can't handle bytecode instruction %s" % opcode)
- bytecode_pos -= 1
- return result
-
-JITCODES = {}
-
-class BaseArray(Wrappable):
- def __init__(self):
- self.invalidates = []
-
- def force(self):
- code = self.compile()
- code.intern()
- return code.compute()
-
- def invalidated(self):
- for arr in self.invalidates:
- arr.force_if_needed()
- self.invalidates = []
-
- def _binop_impl(bytecode):
- def impl(self, space, w_other):
- if isinstance(w_other, BaseArray):
- res = space.wrap(BinOp(bytecode, self, w_other))
- w_other.invalidates.append(res)
- else:
- res = space.wrap(BinOp(
- bytecode,
- self,
- FloatWrapper(space.float_w(w_other))
- ))
- self.invalidates.append(res)
- return res
- return func_with_new_name(impl, "binop_%s_impl" % bytecode)
-
- descr_add = _binop_impl("a")
- descr_sub = _binop_impl("s")
- descr_mul = _binop_impl("m")
- descr_div = _binop_impl("d")
-
- def compile(self):
- raise NotImplementedError("abstract base class")
-
-class FloatWrapper(BaseArray):
- """
- Intermediate class representing a float literal.
- """
-
- def __init__(self, float_value):
- BaseArray.__init__(self)
- self.float_value = float_value
-
- def compile(self):
- return Code('f', [], [self.float_value])
-
-class BinOp(BaseArray):
- """
- Intermediate class for performing binary operations.
- """
-
- def __init__(self, opcode, left, right):
- BaseArray.__init__(self)
- self.opcode = opcode
- self.left = left
- self.right = right
-
- self.forced_result = None
-
- def compile(self):
- if self.forced_result is not None:
- return self.forced_result.compile()
-
- left_code = self.left.compile()
- right_code = self.right.compile()
- return left_code.merge(self.opcode, right_code)
-
- def force_if_needed(self):
- if self.forced_result is None:
- self.forced_result = self.force()
-
- def descr_len(self, space):
- self.force_if_needed()
- return self.forced_result.descr_len(space)
-
- @unwrap_spec(item=int)
- def descr_getitem(self, space, item):
- self.force_if_needed()
- return self.forced_result.descr_getitem(space, item)
-
- @unwrap_spec(item=int, value=float)
- def descr_setitem(self, space, item, value):
- self.force_if_needed()
- self.invalidated()
- return self.forced_result.descr_setitem(space, item, value)
-
-
-BinOp.typedef = TypeDef(
- 'Operation',
- __len__ = interp2app(BinOp.descr_len),
- __getitem__ = interp2app(BinOp.descr_getitem),
- __setitem__ = interp2app(BinOp.descr_setitem),
-
- __add__ = interp2app(BaseArray.descr_add),
- __sub__ = interp2app(BaseArray.descr_sub),
- __mul__ = interp2app(BaseArray.descr_mul),
- __div__ = interp2app(BaseArray.descr_div),
-)
-
-class SingleDimArray(BaseArray):
- def __init__(self, size):
- BaseArray.__init__(self)
- self.size = size
- self.storage = lltype.malloc(TP, size, zero=True,
- flavor='raw', track_allocation=False)
- # XXX find out why test_jit explodes with trackign of allocations
-
- def compile(self):
- return Code('l', [self], [])
-
- def getindex(self, space, item):
- if item >= self.size:
- raise operationerrfmt(space.w_IndexError,
- '%d above array size', item)
- if item < 0:
- item += self.size
- if item < 0:
- raise operationerrfmt(space.w_IndexError,
- '%d below zero', item)
- return item
-
- def descr_len(self, space):
- return space.wrap(self.size)
-
- @unwrap_spec(item=int)
- def descr_getitem(self, space, item):
- item = self.getindex(space, item)
- return space.wrap(self.storage[item])
-
- @unwrap_spec(item=int, value=float)
- def descr_setitem(self, space, item, value):
- item = self.getindex(space, item)
- self.invalidated()
- self.storage[item] = value
-
- def __del__(self):
- lltype.free(self.storage, flavor='raw')
-
-def descr_new_numarray(space, w_type, w_size_or_iterable):
- l = space.listview(w_size_or_iterable)
- arr = SingleDimArray(len(l))
- i = 0
- for w_elem in l:
- arr.storage[i] = space.float_w(space.float(w_elem))
- i += 1
- return space.wrap(arr)
-
-@unwrap_spec(ObjSpace, int)
-def zeros(space, size):
- return space.wrap(SingleDimArray(size))
-
-
-SingleDimArray.typedef = TypeDef(
- 'numarray',
- __new__ = interp2app(descr_new_numarray),
- __len__ = interp2app(SingleDimArray.descr_len),
- __getitem__ = interp2app(SingleDimArray.descr_getitem),
- __setitem__ = interp2app(SingleDimArray.descr_setitem),
-
- __add__ = interp2app(BaseArray.descr_add),
- __sub__ = interp2app(BaseArray.descr_sub),
- __mul__ = interp2app(BaseArray.descr_mul),
- __div__ = interp2app(BaseArray.descr_div),
-)
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_base.py
b/pypy/module/micronumpy/test/test_base.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -0,0 +1,6 @@
+from pypy.conftest import gettestobjspace
+
+
+class BaseNumpyAppTest(object):
+ def setup_class(cls):
+ cls.space = gettestobjspace(usemodules=('micronumpy',))
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_numpy.py
b/pypy/module/micronumpy/test/test_numpy.py
--- a/pypy/module/micronumpy/test/test_numpy.py
+++ b/pypy/module/micronumpy/test/test_numpy.py
@@ -1,11 +1,9 @@
import py
-from pypy.conftest import gettestobjspace
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
-class AppTestNumpyLike(object):
- def setup_class(cls):
- cls.space = gettestobjspace(usemodules=('micronumpy',))
+class AppTestNumArray(BaseNumpyAppTest):
def test_init(self):
from numpy import zeros
a = zeros(15)
@@ -135,69 +133,4 @@
b = a + a
c = b + b
b[1] = 5
- assert c[1] == 4
-
-class AppTestNumpy(object):
- def setup_class(cls):
- py.test.skip("unimplemented")
- cls.space = gettestobjspace(usemodules=('micronumpy',))
-
- def test_zeroes(self):
- from numpy import zeros
- ar = zeros(3, dtype=int)
- assert ar[0] == 0
-
- def test_setitem_getitem(self):
- from numpy import zeros
- ar = zeros(8, dtype=int)
- assert ar[0] == 0
- ar[1] = 3
- assert ar[1] == 3
- raises((TypeError, ValueError), ar.__getitem__, 'xyz')
- raises(IndexError, ar.__getitem__, 38)
- assert ar[-2] == 0
- assert ar[-7] == 3
- assert len(ar) == 8
-
- def test_minimum(self):
- from numpy import zeros, minimum
- ar = zeros(5, dtype=int)
- ar2 = zeros(5, dtype=int)
- ar[0] = 3
- ar[1] = -3
- ar[2] = 8
- ar2[3] = -1
- ar2[4] = 8
- x = minimum(ar, ar2)
- assert x[0] == 0
- assert x[1] == -3
- assert x[2] == 0
- assert x[3] == -1
- assert x[4] == 0
- assert len(x) == 5
- raises(ValueError, minimum, ar, zeros(3, dtype=int))
-
-class AppTestMultiDim(object):
- def setup_class(cls):
- py.test.skip("unimplemented")
- cls.space = gettestobjspace(usemodules=('micronumpy',))
-
- def test_multidim(self):
- from numpy import zeros
- ar = zeros((3, 3), dtype=int)
- assert ar[0, 2] == 0
- raises(IndexError, ar.__getitem__, (3, 0))
- assert ar[-2, 1] == 0
-
- def test_multidim_getset(self):
- from numpy import zeros
- ar = zeros((3, 3, 3), dtype=int)
- ar[1, 2, 1] = 3
- assert ar[1, 2, 1] == 3
- assert ar[-2, 2, 1] == 3
- assert ar[2, 2, 1] == 0
- assert ar[-2, 2, -2] == 3
-
- def test_len(self):
- from numpy import zeros
- assert len(zeros((3, 2, 1), dtype=int)) == 3
+ assert c[1] == 4
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py
b/pypy/module/micronumpy/test/test_ufuncs.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -0,0 +1,11 @@
+from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+
+
+class AppTestUfuncs(BaseNumpyAppTest):
+ def test_negative(self):
+ from numpy import array, negative
+
+ a = array([-5.0, 0.0, 1.0])
+ b = negative(a)
+ for i in range(3):
+ assert b[i] == -a[i]
\ No newline at end of file
diff --git a/pypy/module/micronumpy/test/test_zjit.py
b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -1,5 +1,8 @@
-from pypy.module.micronumpy.numarray import SingleDimArray, BinOp, FloatWrapper
from pypy.jit.metainterp.test.support import LLJitMixin
+from pypy.module.micronumpy.interp_numarray import (SingleDimArray, BinOp,
+ FloatWrapper, Call)
+from pypy.module.micronumpy.interp_ufuncs import negative_impl
+
class FakeSpace(object):
pass
@@ -59,4 +62,19 @@
self.check_loops({"getarrayitem_raw": 2, "float_mul": 1, "float_add":
1,
"setarrayitem_raw": 2, "int_add": 2,
"int_lt": 2, "guard_true": 2, "jump": 2})
+ assert result == f(5)
+
+ def test_ufunc(self):
+ space = self.space
+ def f(i):
+ ar = SingleDimArray(i)
+ v1 = BinOp('a', ar, ar)
+ v2 = Call(negative_impl, v1)
+ return v2.force().storage[3]
+
+ result = self.meta_interp(f, [5], listops=True, backendopt=True)
+ self.check_loops({"getarrayitem_raw": 1, "float_add": 1, "float_neg":
1,
+ "setarrayitem_raw": 1, "int_add": 1,
+ "int_lt": 1, "guard_true": 1, "jump": 1,
+ })
assert result == f(5)
\ No newline at end of file
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit