Author: mattip Branch: matrixmath-dot Changeset: r50223:c1c81fb495b9 Date: 2011-12-06 17:39 +0200 http://bitbucket.org/pypy/pypy/changeset/c1c81fb495b9/
Log: hg merge with default diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py --- a/lib_pypy/_collections.py +++ b/lib_pypy/_collections.py @@ -379,12 +379,14 @@ class defaultdict(dict): def __init__(self, *args, **kwds): - self.default_factory = None - if 'default_factory' in kwds: - self.default_factory = kwds.pop('default_factory') - elif len(args) > 0 and (callable(args[0]) or args[0] is None): - self.default_factory = args[0] + if len(args) > 0: + default_factory = args[0] args = args[1:] + if not callable(default_factory) and default_factory is not None: + raise TypeError("first argument must be callable") + else: + default_factory = None + self.default_factory = default_factory super(defaultdict, self).__init__(*args, **kwds) def __missing__(self, key): diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py --- a/pypy/jit/backend/llsupport/gc.py +++ b/pypy/jit/backend/llsupport/gc.py @@ -823,6 +823,15 @@ bool(v.value)): # store a non-NULL self._gen_write_barrier(newops, op.getarg(0), v) op = op.copy_and_change(rop.SETFIELD_RAW) + # ---------- write barrier for SETINTERIORFIELD_GC ------ + if op.getopnum() == rop.SETINTERIORFIELD_GC: + val = op.getarg(0) + if val is not last_malloc: + v = op.getarg(2) + if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and + bool(v.value)): # store a non-NULL + self._gen_write_barrier(newops, op.getarg(0), v) + op = op.copy_and_change(rop.SETINTERIORFIELD_RAW) # ---------- write barrier for SETARRAYITEM_GC ---------- if op.getopnum() == rop.SETARRAYITEM_GC: val = op.getarg(0) diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py --- a/pypy/jit/backend/llsupport/test/test_gc.py +++ b/pypy/jit/backend/llsupport/test/test_gc.py @@ -570,6 +570,28 @@ assert operations[1].getarg(2) == v_value assert operations[1].getdescr() == array_descr + def test_rewrite_assembler_5(self): + S = lltype.GcStruct('S') + A = lltype.GcArray(lltype.Struct('A', ('x', lltype.Ptr(S)))) + interiordescr = get_interiorfield_descr(self.gc_ll_descr, A, + A.OF, 'x') + wbdescr = self.gc_ll_descr.write_barrier_descr + ops = parse(""" + [p1, p2] + setinteriorfield_gc(p1, 0, p2, descr=interiordescr) + jump(p1, p2) + """, namespace=locals()) + expected = parse(""" + [p1, p2] + cond_call_gc_wb(p1, p2, descr=wbdescr) + setinteriorfield_raw(p1, 0, p2, descr=interiordescr) + jump(p1, p2) + """, namespace=locals()) + operations = get_deep_immutable_oplist(ops.operations) + operations = self.gc_ll_descr.rewrite_assembler(self.fake_cpu, + operations, []) + equaloplists(operations, expected.operations) + def test_rewrite_assembler_initialization_store(self): S = lltype.GcStruct('S', ('parent', OBJECT), ('x', lltype.Signed)) diff --git a/pypy/jit/backend/x86/test/test_zrpy_gc.py b/pypy/jit/backend/x86/test/test_zrpy_gc.py --- a/pypy/jit/backend/x86/test/test_zrpy_gc.py +++ b/pypy/jit/backend/x86/test/test_zrpy_gc.py @@ -490,8 +490,8 @@ check(a[i].y.i == n + i * 100 + 2) check(a[i].z.i == n + i * 100 + 3) i += 1 + n -= x.foo return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s - f(123, *[None]*11) # check that the check() are ok return None, f, None def test_compile_framework_7_interior(self): diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py --- a/pypy/jit/metainterp/compile.py +++ b/pypy/jit/metainterp/compile.py @@ -298,7 +298,7 @@ pass class ResumeGuardDescr(ResumeDescr): - _counter = 0 # if < 0, there is one counter per value; + _counter = 0 # on a GUARD_VALUE, there is one counter per value; _counters = None # they get stored in _counters then. # this class also gets the following attributes stored by resume.py code @@ -309,10 +309,13 @@ rd_virtuals = None rd_pendingfields = lltype.nullptr(PENDINGFIELDSP.TO) - CNT_INT = -0x20000000 - CNT_REF = -0x40000000 - CNT_FLOAT = -0x60000000 - CNT_MASK = 0x1FFFFFFF + CNT_BASE_MASK = 0x0FFFFFFF # the base counter value + CNT_BUSY_FLAG = 0x10000000 # if set, busy tracing from the guard + CNT_TYPE_MASK = 0x60000000 # mask for the type + + CNT_INT = 0x20000000 + CNT_REF = 0x40000000 + CNT_FLOAT = 0x60000000 def store_final_boxes(self, guard_op, boxes): guard_op.setfailargs(boxes) @@ -326,6 +329,8 @@ except ValueError: return # xxx probably very rare else: + if i > self.CNT_BASE_MASK: + return # probably never, but better safe than sorry if box.type == history.INT: cnt = self.CNT_INT elif box.type == history.REF: @@ -334,14 +339,17 @@ cnt = self.CNT_FLOAT else: assert 0, box.type - # we build the following value for _counter, which is always - # a negative value + assert cnt > self.CNT_BASE_MASK self._counter = cnt | i def handle_fail(self, metainterp_sd, jitdriver_sd): if self.must_compile(metainterp_sd, jitdriver_sd): - return self._trace_and_compile_from_bridge(metainterp_sd, - jitdriver_sd) + self.start_compiling() + try: + return self._trace_and_compile_from_bridge(metainterp_sd, + jitdriver_sd) + finally: + self.done_compiling() else: from pypy.jit.metainterp.blackhole import resume_in_blackhole resume_in_blackhole(metainterp_sd, jitdriver_sd, self) @@ -359,12 +367,22 @@ def must_compile(self, metainterp_sd, jitdriver_sd): trace_eagerness = jitdriver_sd.warmstate.trace_eagerness - if self._counter >= 0: + # + if self._counter <= self.CNT_BASE_MASK: + # simple case: just counting from 0 to trace_eagerness self._counter += 1 return self._counter >= trace_eagerness - else: - index = self._counter & self.CNT_MASK - typetag = self._counter & ~ self.CNT_MASK + # + # do we have the BUSY flag? If so, we're tracing right now, e.g. in an + # outer invocation of the same function, so don't trace again for now. + elif self._counter & self.CNT_BUSY_FLAG: + return False + # + else: # we have a GUARD_VALUE that fails. Make a _counters instance + # (only now, when the guard is actually failing at least once), + # and use it to record some statistics about the failing values. + index = self._counter & self.CNT_BASE_MASK + typetag = self._counter & self.CNT_TYPE_MASK counters = self._counters if typetag == self.CNT_INT: intvalue = metainterp_sd.cpu.get_latest_value_int(index) @@ -391,7 +409,16 @@ assert 0, typetag return counter >= trace_eagerness - def reset_counter_from_failure(self): + def start_compiling(self): + # start tracing and compiling from this guard. + self._counter |= self.CNT_BUSY_FLAG + + def done_compiling(self): + # done tracing and compiling from this guard. Either the bridge has + # been successfully compiled, in which case whatever value we store + # in self._counter will not be seen any more, or not, in which case + # we should reset the counter to 0, in order to wait a bit until the + # next attempt. if self._counter >= 0: self._counter = 0 self._counters = None @@ -608,9 +635,6 @@ metainterp.set_compiled_merge_points(self.original_greenkey, old_loop_tokens) - def reset_counter_from_failure(self): - pass - def compile_new_bridge(metainterp, old_loop_tokens, resumekey, retraced=False): """Try to compile a new bridge leading from the beginning of the history diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py --- a/pypy/jit/metainterp/pyjitpl.py +++ b/pypy/jit/metainterp/pyjitpl.py @@ -1790,7 +1790,6 @@ self.staticdata.profiler.count(reason) debug_print('~~~ ABORTING TRACING') self.staticdata.stats.aborted() - self.resumekey.reset_counter_from_failure() def blackhole_if_trace_too_long(self): warmrunnerstate = self.jitdriver_sd.warmstate diff --git a/pypy/jit/metainterp/test/test_math.py b/pypy/jit/metainterp/test/test_math.py new file mode 100644 --- /dev/null +++ b/pypy/jit/metainterp/test/test_math.py @@ -0,0 +1,47 @@ +import math +from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin +from pypy.rlib.rfloat import isinf, isnan, INFINITY, NAN + +class MathTests: + + def test_math_sqrt(self): + def f(x): + try: + return math.sqrt(x) + except ValueError: + return -INFINITY + + res = self.interp_operations(f, [0.0]) + assert res == 0.0 + self.check_operations_history(call_pure=1) + # + res = self.interp_operations(f, [25.0]) + assert res == 5.0 + self.check_operations_history(call_pure=1) + # + res = self.interp_operations(f, [-0.0]) + assert str(res) == '-0.0' + self.check_operations_history(call_pure=1) + # + res = self.interp_operations(f, [1000000.0]) + assert res == 1000.0 + self.check_operations_history(call_pure=1) + # + res = self.interp_operations(f, [-1.0]) + assert res == -INFINITY + self.check_operations_history(call_pure=0) + # + res = self.interp_operations(f, [INFINITY]) + assert isinf(res) and not isnan(res) and res > 0.0 + self.check_operations_history(call_pure=0) + # + res = self.interp_operations(f, [NAN]) + assert isnan(res) and not isinf(res) + self.check_operations_history(call_pure=0) + + +class TestOOtype(MathTests, OOJitMixin): + pass + +class TestLLtype(MathTests, LLJitMixin): + pass diff --git a/pypy/jit/metainterp/test/test_recursive.py b/pypy/jit/metainterp/test/test_recursive.py --- a/pypy/jit/metainterp/test/test_recursive.py +++ b/pypy/jit/metainterp/test/test_recursive.py @@ -1238,6 +1238,31 @@ self.meta_interp(portal, [0, 0, 0], inline=True) self.check_resops(call_may_force=0, call=0) + def test_dont_repeatedly_trace_from_the_same_guard(self): + driver = JitDriver(greens = [], reds = ['level', 'i']) + + def portal(level): + if level == 0: + i = -10 + else: + i = 0 + # + while True: + driver.jit_merge_point(level=level, i=i) + if level == 25: + return 42 + i += 1 + if i <= 0: # <- guard + continue # first make a loop + else: + # then we fail the guard above, doing a recursive call, + # which will itself fail the same guard above, and so on + return portal(level + 1) + + self.meta_interp(portal, [0]) + self.check_loop_count_at_most(2) # and not, e.g., 24 + + class TestLLtype(RecursiveTests, LLJitMixin): pass diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py --- a/pypy/module/_collections/app_defaultdict.py +++ b/pypy/module/_collections/app_defaultdict.py @@ -13,12 +13,14 @@ class defaultdict(dict): def __init__(self, *args, **kwds): - self.default_factory = None - if 'default_factory' in kwds: - self.default_factory = kwds.pop('default_factory') - elif len(args) > 0 and (callable(args[0]) or args[0] is None): - self.default_factory = args[0] + if len(args) > 0: + default_factory = args[0] args = args[1:] + if not callable(default_factory) and default_factory is not None: + raise TypeError("first argument must be callable") + else: + default_factory = None + self.default_factory = default_factory super(defaultdict, self).__init__(*args, **kwds) def __missing__(self, key): diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py --- a/pypy/module/_collections/test/test_defaultdict.py +++ b/pypy/module/_collections/test/test_defaultdict.py @@ -19,11 +19,22 @@ def test_keyerror_without_factory(self): from _collections import defaultdict - d1 = defaultdict() - for key in ['foo', (1,)]: - try: - d1[key] - except KeyError, err: - assert err.args[0] == key - else: - assert 0, "expected KeyError" + for d1 in [defaultdict(), defaultdict(None)]: + for key in ['foo', (1,)]: + try: + d1[key] + except KeyError, err: + assert err.args[0] == key + else: + assert 0, "expected KeyError" + + def test_noncallable(self): + from _collections import defaultdict + raises(TypeError, defaultdict, [('a', 5)]) + d = defaultdict(None, [('a', 5)]) + assert d.items() == [('a', 5)] + + def test_kwds(self): + from _collections import defaultdict + d = defaultdict(default_factory=5) + assert d.keys() == ['default_factory'] diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py --- a/pypy/module/_socket/interp_func.py +++ b/pypy/module/_socket/interp_func.py @@ -1,7 +1,7 @@ from pypy.interpreter.gateway import unwrap_spec from pypy.module._socket.interp_socket import converted_error, W_RSocket from pypy.rlib import rsocket -from pypy.rlib.rsocket import SocketError +from pypy.rlib.rsocket import SocketError, INVALID_SOCKET from pypy.interpreter.error import OperationError def gethostname(space): @@ -284,7 +284,7 @@ space.wrap(socktype), space.wrap(protocol), space.wrap(canonname), - addr.as_object(-1, space)]) # -1 as per cpython + addr.as_object(INVALID_SOCKET, space)]) # -1 as per cpython for (family, socktype, protocol, canonname, addr) in lst] return space.newlist(lst1) 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 @@ -32,6 +32,7 @@ 'int_': 'interp_boxes.W_LongBox', 'inexact': 'interp_boxes.W_InexactBox', 'floating': 'interp_boxes.W_FloatingBox', + 'float32': 'interp_boxes.W_Float32Box', 'float64': 'interp_boxes.W_Float64Box', } @@ -76,4 +77,5 @@ 'inf': 'app_numpy.inf', 'e': 'app_numpy.e', 'arange': 'app_numpy.arange', + 'reshape': 'app_numpy.reshape', } diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py --- a/pypy/module/micronumpy/app_numpy.py +++ b/pypy/module/micronumpy/app_numpy.py @@ -36,3 +36,39 @@ j += 1 i += step return arr + +def reshape(a, shape): + '''reshape(a, newshape) + Gives a new shape to an array without changing its data. + + Parameters + ---------- + a : array_like + Array to be reshaped. + newshape : int or tuple of ints + The new shape should be compatible with the original shape. If + an integer, then the result will be a 1-D array of that length. + One shape dimension can be -1. In this case, the value is inferred + from the length of the array and remaining dimensions. + + Returns + ------- + reshaped_array : ndarray + This will be a new view object if possible; otherwise, it will + be a copy. + + + See Also + -------- + ndarray.reshape : Equivalent method. + + Notes + ----- + + It is not always possible to change the shape of an array without + copying the data. If you want an error to be raise if the data is copied, + you should assign the new shape to the shape attribute of the array +''' + if not hasattr(a, 'reshape'): + a = numpypy.array(a) + return a.reshape(shape) diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py --- a/pypy/module/micronumpy/interp_boxes.py +++ b/pypy/module/micronumpy/interp_boxes.py @@ -258,6 +258,8 @@ W_Float32Box.typedef = TypeDef("float32", W_FloatingBox.typedef, __module__ = "numpypy", + + __new__ = interp2app(W_Float32Box.descr__new__.im_func), ) W_Float64Box.typedef = TypeDef("float64", (W_FloatingBox.typedef, float_typedef), diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -98,6 +98,107 @@ endshape[i] = remainder[i] return endshape +def get_shape_from_iterable(space, old_size, w_iterable): + new_size = 0 + new_shape = [] + if space.isinstance_w(w_iterable, space.w_int): + new_size = space.int_w(w_iterable) + if new_size < 0: + new_size = old_size + new_shape = [new_size, ] + else: + neg_dim = -1 + batch = space.listview(w_iterable) + #Allow for shape = (1,2,3) or shape = ((1,2,3)) + if len(batch) > 1 and space.issequence_w(batch[0]): + batch = space.listview(batch[0]) + new_size = 1 + if len(batch) < 1: + if old_size == 1: + #Scalars can have an empty size. + new_size = 1 + else: + new_size = 0 + new_shape = [] + i = 0 + for elem in batch: + s = space.int_w(elem) + if s < 0: + if neg_dim >= 0: + raise OperationError(space.w_ValueError, space.wrap( + "can only specify one unknown dimension")) + s = 1 + neg_dim = i + new_size *= s + new_shape.append(s) + i += 1 + if neg_dim >= 0: + new_shape[neg_dim] = old_size / new_size + new_size *= new_shape[neg_dim] + if new_size != old_size: + raise OperationError(space.w_ValueError, + space.wrap("total size of new array must be unchanged")) + return new_shape + +#Recalculating strides. Find the steps that the iteration does for each +#dimension, given the stride and shape. Then try to create a new stride that +#fits the new shape, using those steps. If there is a shape/step mismatch +#(meaning that the realignment of elements crosses from one step into another) +#return None so that the caller can raise an exception. +def calc_new_strides(new_shape, old_shape, old_strides): + #Return the proper strides for new_shape, or None + # if the mapping crosses stepping boundaries + + #Assumes that prod(old_shape) ==prod(new_shape), len(old_shape) > 1 and + # len(new_shape) > 0 + steps = [] + last_step = 1 + oldI = 0 + new_strides = [] + if old_strides[0] < old_strides[-1]: + for i in range(len(old_shape)): + steps.append(old_strides[i] / last_step) + last_step *= old_shape[i] + cur_step = steps[0] + n_new_elems_used = 1 + n_old_elems_to_use = old_shape[0] + for s in new_shape: + new_strides.append(cur_step * n_new_elems_used) + n_new_elems_used *= s + while n_new_elems_used > n_old_elems_to_use: + oldI += 1 + if steps[oldI] != steps[oldI - 1]: + return None + n_old_elems_to_use *= old_shape[oldI] + if n_new_elems_used == n_old_elems_to_use: + oldI += 1 + if oldI >= len(old_shape): + break + cur_step = steps[oldI] + n_old_elems_to_use *= old_shape[oldI] + else: + for i in range(len(old_shape) - 1, -1, -1): + steps.insert(0, old_strides[i] / last_step) + last_step *= old_shape[i] + cur_step = steps[-1] + n_new_elems_used = 1 + oldI = -1 + n_old_elems_to_use = old_shape[-1] + for s in new_shape[::-1]: + new_strides.insert(0, cur_step * n_new_elems_used) + n_new_elems_used *= s + while n_new_elems_used > n_old_elems_to_use: + oldI -= 1 + if steps[oldI] != steps[oldI + 1]: + return None + n_old_elems_to_use *= old_shape[oldI] + if n_new_elems_used == n_old_elems_to_use: + oldI -= 1 + if oldI < -len(old_shape): + break + cur_step = steps[oldI] + n_old_elems_to_use *= old_shape[oldI] + return new_strides # Iterators for arrays # -------------------- @@ -567,6 +668,12 @@ def descr_get_shape(self, space): return space.newtuple([space.wrap(i) for i in self.shape]) + def descr_set_shape(self, space, w_iterable): + concrete = self.get_concrete() + new_shape = get_shape_from_iterable(space, + concrete.find_size(), w_iterable) + concrete.setshape(space, new_shape) + def descr_get_size(self, space): return space.wrap(self.find_size()) @@ -814,10 +921,44 @@ strides += self.strides[s:] backstrides += self.backstrides[s:] new_sig = signature.Signature.find_sig([ - NDimSlice.signature, self.signature, + W_NDimSlice.signature, self.signature, ]) - return NDimSlice(self, new_sig, start, strides[:], backstrides[:], - shape[:]) + return W_NDimSlice(self, new_sig, start, strides[:], backstrides[:], + shape[:]) + + def descr_reshape(self, space, w_args): + """reshape(...) + a.reshape(shape) + + Returns an array containing the same data with a new shape. + + Refer to `%s.reshape` for full documentation. + + See Also + -------- + numpy.reshape : equivalent function +""" % 'numpypy' + concrete = self.get_concrete() + new_shape = get_shape_from_iterable(space, + concrete.find_size(), w_args) + #Since we got to here, prod(new_shape) == self.size + new_strides = calc_new_strides(new_shape, + concrete.shape, concrete.strides) + if new_strides: + #We can create a view, strides somehow match up. + new_sig = signature.Signature.find_sig([ + W_NDimSlice.signature, self.signature, ]) + ndims = len(new_shape) + new_backstrides = [0] * ndims + for nd in range(ndims): + new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd] + arr = W_NDimSlice(self, new_sig, self.start, new_strides, + new_backstrides, new_shape) + else: + #Create copy with contiguous data + arr = concrete.copy() + arr.setshape(space, new_shape) + return arr def descr_mean(self, space): return space.div(self.descr_sumpromote(space), @@ -836,7 +977,7 @@ if len(concrete.shape) < 2: return space.wrap(self) new_sig = signature.Signature.find_sig([ - NDimSlice.signature, self.signature + W_NDimSlice.signature, self.signature ]) strides = [] backstrides = [] @@ -845,8 +986,8 @@ strides.append(concrete.strides[i]) backstrides.append(concrete.backstrides[i]) shape.append(concrete.shape[i]) - return space.wrap(NDimSlice(concrete, new_sig, self.start, strides[:], - backstrides[:], shape[:])) + return space.wrap(W_NDimSlice(concrete, new_sig, self.start, strides[:], + backstrides[:], shape[:])) def descr_get_flatiter(self, space): return space.wrap(W_FlatIterator(self)) @@ -915,6 +1056,11 @@ def debug_repr(self): return 'Scalar' + def setshape(self, space, new_shape): + # In order to get here, we already checked that prod(new_shape)==1, + # so in order to have a consistent API, let it go through. + pass + class VirtualArray(BaseArray): """ Class for representing virtual arrays, such as binary ops or ufuncs @@ -1047,7 +1193,6 @@ return self.forced_result.start_iter(res_shape) if res_shape is None: res_shape = self.shape # we still force the shape on children - #TODO: use left_start_dim, right_start_dim if they are not [-1, -1] if self.left_start_dim[0] >= 0: ldim = self.left_start_dim[1] rdim = self.right_start_dim[1] @@ -1120,13 +1265,46 @@ return space.wrap(self.shape[0]) return space.wrap(1) + def setshape(self, space, new_shape): + if len(self.shape) < 1: + return + elif len(self.shape) < 2: + #TODO: this code could be refactored into calc_strides + #but then calc_strides would have to accept a stepping factor + strides = [] + backstrides = [] + s = self.strides[0] + if self.order == 'C': + new_shape.reverse() + for sh in new_shape: + strides.append(s) + backstrides.append(s * (sh - 1)) + s *= sh + if self.order == 'C': + strides.reverse() + backstrides.reverse() + new_shape.reverse() + self.strides = strides[:] + self.backstrides = backstrides[:] + self.shape = new_shape[:] + return + new_strides = calc_new_strides(new_shape, self.shape, self.strides) + if new_strides is None: + raise OperationError(space.w_AttributeError, space.wrap( + "incompatible shape for a non-contiguous array")) + new_backstrides = [0] * len(new_shape) + for nd in range(len(new_shape)): + new_backstrides[nd] = (new_shape[nd] - 1) * new_strides[nd] + self.strides = new_strides[:] + self.backstrides = new_backstrides[:] + self.shape = new_shape[:] -class NDimSlice(ViewArray): +class W_NDimSlice(ViewArray): signature = signature.BaseSignature() def __init__(self, parent, signature, start, strides, backstrides, shape): - if isinstance(parent, NDimSlice): + if isinstance(parent, W_NDimSlice): parent = parent.parent ViewArray.__init__(self, parent, signature, strides, backstrides, shape) self.start = start @@ -1175,9 +1353,11 @@ def copy(self): array = W_NDimArray(self.size, self.shape[:], self.find_dtype()) iter = self.start_iter() + a_iter = array.start_iter() while not iter.done(): - array.setitem(iter.get_offset(), self.getitem(iter.get_offset())) + array.setitem(a_iter.offset, self.getitem(iter.offset)) iter = iter.next(len(self.shape)) + a_iter = a_iter.next(len(array.shape)) return array class W_NDimArray(BaseArray): @@ -1235,6 +1415,10 @@ return ArrayIterator(self.size) raise NotImplementedError # use ViewIterator simply, test it + def setshape(self, space, new_shape): + self.shape = new_shape + self.calc_strides(new_shape) + def debug_repr(self): return 'Array' @@ -1359,7 +1543,8 @@ __debug_repr__ = interp2app(BaseArray.descr_debug_repr), dtype = GetSetProperty(BaseArray.descr_get_dtype), - shape = GetSetProperty(BaseArray.descr_get_shape), + shape = GetSetProperty(BaseArray.descr_get_shape, + BaseArray.descr_set_shape), size = GetSetProperty(BaseArray.descr_get_size), T = GetSetProperty(BaseArray.descr_get_transpose), @@ -1377,6 +1562,7 @@ dot = interp2app(BaseArray.descr_dot), copy = interp2app(BaseArray.descr_copy), + reshape = interp2app(BaseArray.descr_reshape), ) diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py --- a/pypy/module/micronumpy/test/test_dtypes.py +++ b/pypy/module/micronumpy/test/test_dtypes.py @@ -240,6 +240,13 @@ assert numpy.dtype(numpy.int64).type is numpy.int64 assert numpy.int64(3) == 3 + def test_float32(self): + import numpypy as numpy + + assert numpy.float32.mro() == [numpy.float32, numpy.floating, numpy.inexact, numpy.number, numpy.generic, object] + + assert numpy.float32(12) == numpy.float64(12) + def test_float64(self): import numpypy as numpy diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py --- a/pypy/module/micronumpy/test/test_numarray.py +++ b/pypy/module/micronumpy/test/test_numarray.py @@ -158,6 +158,13 @@ assert shape_agreement(self.space, [5, 2], [4, 3, 5, 2]) == [4, 3, 5, 2] + def test_calc_new_strides(self): + from pypy.module.micronumpy.interp_numarray import calc_new_strides + assert calc_new_strides([2, 4], [4, 2], [4, 2]) == [8, 2] + assert calc_new_strides([2, 4, 3], [8, 3], [1, 16]) == [1, 2, 16] + assert calc_new_strides([2, 3, 4], [8, 3], [1, 16]) is None + assert calc_new_strides([24], [2, 4, 3], [48, 6, 1]) is None + assert calc_new_strides([24], [2, 4, 3], [24, 6, 2]) == [2] class AppTestNumArray(BaseNumpyAppTest): def test_ndarray(self): @@ -216,8 +223,8 @@ assert a[2] == 4 def test_copy(self): - from numpypy import array - a = array(range(5)) + from numpypy import arange, array + a = arange(5) b = a.copy() for i in xrange(5): assert b[i] == a[i] @@ -227,6 +234,11 @@ a = array(1) assert a.copy() == a + a = arange(8) + b = a[::2] + c = b.copy() + assert (c == b).all() + def test_iterator_init(self): from numpypy import array a = array(range(5)) @@ -339,6 +351,76 @@ c = a[:3] assert c.shape == (3,) + def test_set_shape(self): + from numpypy import array, zeros + a = array([]) + a.shape = [] + a = array(range(12)) + a.shape = (3, 4) + assert (a == [range(4), range(4, 8), range(8, 12)]).all() + a.shape = (3, 2, 2) + assert a[1, 1, 1] == 7 + a.shape = (3, -1, 2) + assert a.shape == (3, 2, 2) + a.shape = 12 + assert a.shape == (12, ) + exc = raises(ValueError, "a.shape = 10") + assert str(exc.value) == "total size of new array must be unchanged" + a = array(3) + a.shape = () + #numpy allows this + a.shape = (1,) + + def test_reshape(self): + from numpypy import array, zeros + a = array(range(12)) + exc = raises(ValueError, "b = a.reshape((3, 10))") + assert str(exc.value) == "total size of new array must be unchanged" + b = a.reshape((3, 4)) + assert b.shape == (3, 4) + assert (b == [range(4), range(4, 8), range(8, 12)]).all() + b[:, 0] = 1000 + assert (a == [1000, 1, 2, 3, 1000, 5, 6, 7, 1000, 9, 10, 11]).all() + a = zeros((4, 2, 3)) + a.shape = (12, 2) + + def test_slice_reshape(self): + from numpypy import zeros, arange + a = zeros((4, 2, 3)) + b = a[::2, :, :] + b.shape = (2, 6) + exc = raises(AttributeError, "b.shape = 12") + assert str(exc.value) == \ + "incompatible shape for a non-contiguous array" + b = a[::2, :, :].reshape((2, 6)) + assert b.shape == (2, 6) + b = arange(20)[1:17:2] + b.shape = (4, 2) + assert (b == [[1, 3], [5, 7], [9, 11], [13, 15]]).all() + c = b.reshape((2, 4)) + assert (c == [[1, 3, 5, 7], [9, 11, 13, 15]]).all() + + z = arange(96).reshape((12, -1)) + assert z.shape == (12, 8) + y = z.reshape((4, 3, 8)) + v = y[:, ::2, :] + w = y.reshape(96) + u = v.reshape(64) + assert y[1, 2, 1] == z[5, 1] + y[1, 2, 1] = 1000 + #z, y, w, v are views of eachother + assert z[5, 1] == 1000 + assert v[1, 1, 1] == 1000 + assert w[41] == 1000 + #u is not a view, it is a copy! + assert u[25] == 41 + + def test_reshape_varargs(self): + skip("How do I do varargs in rpython? reshape should accept a" + " variable number of arguments") + z = arange(96).reshape(12, -1) + y = z.reshape(4, 3, 8) + def test_add(self): from numpypy import array a = array(range(5)) @@ -1174,3 +1256,14 @@ a = arange(0, 0.8, 0.1) assert len(a) == 8 assert arange(False, True, True).dtype is dtype(int) + + +class AppTestRanges(BaseNumpyAppTest): + def test_app_reshape(self): + from numpypy import arange, array, dtype, reshape + a = arange(12) + b = reshape(a, (3, 4)) + assert b.shape == (3, 4) + a = range(12) + b = reshape(a, (3, 4)) + assert b.shape == (3, 4) 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 @@ -8,13 +8,12 @@ from pypy.jit.metainterp import pyjitpl from pypy.jit.metainterp.test.support import LLJitMixin from pypy.jit.metainterp.warmspot import reset_stats -from pypy.module.micronumpy import interp_boxes, interp_ufuncs, signature -from pypy.module.micronumpy.compile import (numpy_compile, FakeSpace, - FloatObject, IntObject, BoolObject, Parser, InterpreterState) -from pypy.module.micronumpy.interp_numarray import (W_NDimArray, NDimSlice, +from pypy.module.micronumpy import interp_boxes +from pypy.module.micronumpy.compile import (FakeSpace, + IntObject, Parser, InterpreterState) +from pypy.module.micronumpy.interp_numarray import (W_NDimArray, BaseArray) from pypy.rlib.nonconst import NonConstant -from pypy.rpython.annlowlevel import llstr, hlstr class TestNumpyJIt(LLJitMixin): @@ -186,7 +185,8 @@ # sure it was optimized correctly. # XXX the comment above is wrong now. We need preferrably a way to # count the two loops separately - self.check_resops({'setinteriorfield_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 41, + py.test.skip("counting exact number of classes is nonsense") + self.check_resops({'setarrayitem_raw': 4, 'guard_nonnull': 1, 'getfield_gc': 35, 'guard_class': 22, 'int_add': 8, 'float_mul': 2, 'guard_isnull': 2, 'jump': 4, 'int_ge': 4, 'getinteriorfield_raw': 4, 'float_add': 2, 'guard_false': 4, diff --git a/pypy/rlib/_rsocket_rffi.py b/pypy/rlib/_rsocket_rffi.py --- a/pypy/rlib/_rsocket_rffi.py +++ b/pypy/rlib/_rsocket_rffi.py @@ -418,7 +418,7 @@ if _MSVC: def invalid_socket(fd): return fd == INVALID_SOCKET - INVALID_SOCKET = intmask(cConfig.INVALID_SOCKET) + INVALID_SOCKET = r_uint(cConfig.INVALID_SOCKET) else: def invalid_socket(fd): return fd < 0 diff --git a/pypy/rlib/rsocket.py b/pypy/rlib/rsocket.py --- a/pypy/rlib/rsocket.py +++ b/pypy/rlib/rsocket.py @@ -20,6 +20,7 @@ from pypy.rlib.rarithmetic import intmask, r_uint from pypy.rpython.lltypesystem import lltype, rffi from pypy.rpython.lltypesystem.rffi import sizeof, offsetof +INVALID_SOCKET = _c.INVALID_SOCKET def mallocbuf(buffersize): return lltype.malloc(rffi.CCHARP.TO, buffersize, flavor='raw') _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit