def _descriptor_from_pep3118_format(space, c_format): descr = descriptor.decode_w_dtype(space, space.newtext(c_format)) if descr: return descr msg = "invalid PEP 3118 format string: '%s'" % c_format space.warn(space.newtext(msg), space.w_RuntimeWarning) return None
def _descriptor_from_pep3118_format(space, c_format): descr = descriptor.decode_w_dtype(space, space.wrap(c_format)) if descr: return descr msg = "invalid PEP 3118 format string: '%s'" % c_format space.warn(space.wrap(msg), space.w_RuntimeWarning) return None
def __init__(self, space, w_seq, w_flags, w_op_flags, w_op_dtypes, w_casting, w_op_axes, w_itershape, buffersize=0, order='K'): from pypy.module.micronumpy.ufuncs import find_binop_result_dtype self.order = order self.external_loop = False self.buffered = False self.tracked_index = '' self.common_dtype = False self.delay_bufalloc = False self.grow_inner = False self.ranged = False self.refs_ok = False self.reduce_ok = False self.zerosize_ok = False self.index_iter = None self.done = False self.first_next = True self.op_axes = [] # convert w_seq operands to a list of W_NDimArray if space.isinstance_w(w_seq, space.w_tuple) or \ space.isinstance_w(w_seq, space.w_list): w_seq_as_list = space.listview(w_seq) self.seq = [convert_to_array(space, w_elem) if not space.is_none(w_elem) else None for w_elem in w_seq_as_list] else: self.seq = [convert_to_array(space, w_seq)] parse_func_flags(space, self, w_flags) self.op_flags = parse_op_arg(space, 'op_flags', w_op_flags, len(self.seq), parse_op_flag) # handle w_op_axes oa_ndim = -1 if not space.is_none(w_op_axes): oa_ndim = self.set_op_axes(space, w_op_axes) self.ndim = calculate_ndim(self.seq, oa_ndim) # handle w_op_dtypes part 1: creating self.dtypes list from input if not space.is_none(w_op_dtypes): w_seq_as_list = space.listview(w_op_dtypes) self.dtypes = [decode_w_dtype(space, w_elem) for w_elem in w_seq_as_list] if len(self.dtypes) != len(self.seq): raise oefmt(space.w_ValueError, "op_dtypes must be a tuple/list matching the number of ops") else: self.dtypes = [] # handle None or writable operands, calculate my shape outargs = [i for i in range(len(self.seq)) if self.seq[i] is None or self.op_flags[i].rw == 'w'] if len(outargs) > 0: out_shape = shape_agreement_multiple(space, [self.seq[i] for i in outargs]) else: out_shape = None if space.isinstance_w(w_itershape, space.w_tuple) or \ space.isinstance_w(w_itershape, space.w_list): self.shape = [space.int_w(i) for i in space.listview(w_itershape)] else: self.shape = shape_agreement_multiple(space, self.seq, shape=out_shape) if len(outargs) > 0: # Make None operands writeonly and flagged for allocation if len(self.dtypes) > 0: out_dtype = self.dtypes[outargs[0]] else: out_dtype = None for i in range(len(self.seq)): if self.seq[i] is None: self.op_flags[i].allocate = True continue if self.op_flags[i].rw == 'w': continue out_dtype = find_binop_result_dtype( space, self.seq[i].get_dtype(), out_dtype) for i in outargs: if self.seq[i] is None: # XXX can we postpone allocation to later? self.seq[i] = W_NDimArray.from_shape(space, self.shape, out_dtype) else: if not self.op_flags[i].broadcast: # Raises if ooutput cannot be broadcast shape_agreement(space, self.shape, self.seq[i], False) if self.tracked_index != "": if self.order == "K": self.order = self.seq[0].implementation.order if self.tracked_index == "multi": backward = False else: backward = self.order != self.tracked_index self.index_iter = IndexIterator(self.shape, backward=backward) # handle w_op_dtypes part 2: copy where needed if possible if len(self.dtypes) > 0: for i in range(len(self.seq)): selfd = self.dtypes[i] seq_d = self.seq[i].get_dtype() if not selfd: self.dtypes[i] = seq_d elif selfd != seq_d: if not 'r' in self.op_flags[i].tmp_copy: raise oefmt(space.w_TypeError, "Iterator operand required copying or " "buffering for operand %d", i) impl = self.seq[i].implementation new_impl = impl.astype(space, selfd) self.seq[i] = W_NDimArray(new_impl) else: #copy them from seq self.dtypes = [s.get_dtype() for s in self.seq] # create an iterator for each operand self.iters = [] for i in range(len(self.seq)): it = get_iter(space, self.order, self.seq[i], self.shape, self.dtypes[i], self.op_flags[i], self) it.contiguous = False self.iters.append((it, it.reset())) if self.external_loop: coalesce_axes(self, space)
def _array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False): from pypy.module.micronumpy import strides # for anything that isn't already an array, try __array__ method first if not isinstance(w_object, W_NDimArray): w_array = try_array_method(space, w_object, w_dtype) if w_array is not None: # continue with w_array, but do further operations in place w_object = w_array copy = False if not isinstance(w_object, W_NDimArray): w_array = try_interface_method(space, w_object) if w_array is not None: w_object = w_array copy = False dtype = descriptor.decode_w_dtype(space, w_dtype) if space.is_none(w_order): order = 'C' else: order = space.str_w(w_order) if order == 'K': order = 'C' if order != 'C': # or order != 'F': raise oefmt(space.w_ValueError, "Unknown order: %s", order) if isinstance(w_object, W_NDimArray): if (dtype is None or w_object.get_dtype() is dtype): if copy and (subok or type(w_object) is W_NDimArray): return w_object.descr_copy(space, w_order) elif not copy and (subok or type(w_object) is W_NDimArray): return w_object if subok and not type(w_object) is W_NDimArray: raise oefmt(space.w_NotImplementedError, "array(..., subok=True) only partially implemented") # we have a ndarray, but need to copy or change dtype if dtype is None: dtype = w_object.get_dtype() if dtype != w_object.get_dtype(): # silently reject the copy value copy = True if copy: shape = w_object.get_shape() elems_w = [None] * w_object.get_size() elsize = w_object.get_dtype().elsize # TODO - use w_object.implementation without copying to a list # unfortunately that causes a union error in translation for i in range(w_object.get_size()): elems_w[i] = w_object.implementation.getitem(i * elsize) else: imp = w_object.implementation with imp as storage: sz = support.product(w_object.get_shape()) * dtype.elsize return W_NDimArray.from_shape_and_storage(space, w_object.get_shape(), storage, dtype, storage_bytes=sz, w_base=w_object, start=imp.start) else: # not an array shape, elems_w = strides.find_shape_and_elems(space, w_object, dtype) if dtype is None or (dtype.is_str_or_unicode() and dtype.elsize < 1): dtype = strides.find_dtype_for_seq(space, elems_w, dtype) if dtype is None: dtype = descriptor.get_dtype_cache(space).w_float64dtype elif dtype.is_str_or_unicode() and dtype.elsize < 1: # promote S0 -> S1, U0 -> U1 dtype = descriptor.variable_dtype(space, dtype.char + '1') w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order) if support.product(shape) == 1: w_arr.set_scalar_value(dtype.coerce(space, elems_w[0])) else: loop.assign(space, w_arr, elems_w) return w_arr
raise if w_interface is None: # happens from compile.py return None version = space.int_w(space.finditem(w_interface, space.wrap("version"))) if version < 3: raise oefmt(space.w_NotImplementedError, "__array_interface__ version %d not supported", version) # make a view into the data w_shape = space.finditem(w_interface, space.wrap('shape')) w_dtype = space.finditem(w_interface, space.wrap('typestr')) w_descr = space.finditem(w_interface, space.wrap('descr')) data_w = space.listview(space.finditem(w_interface, space.wrap('data'))) w_strides = space.finditem(w_interface, space.wrap('strides')) shape = [space.int_w(i) for i in space.listview(w_shape)] dtype = descriptor.decode_w_dtype(space, w_dtype) rw = space.is_true(data_w[1]) #print 'create view from shape',shape,'dtype',dtype,'descr',w_descr,'data',data_w[0],'rw',rw raise oefmt(space.w_NotImplementedError, "creating array from __array_interface__ not supported yet") return @unwrap_spec(ndmin=int, copy=bool, subok=bool) def array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False, ndmin=0):
def _array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False): from pypy.module.micronumpy import strides # for anything that isn't already an array, try __array__ method first if not isinstance(w_object, W_NDimArray): w_array = try_array_method(space, w_object, w_dtype) if w_array is not None: # continue with w_array, but do further operations in place w_object = w_array copy = False if not isinstance(w_object, W_NDimArray): w_array = try_interface_method(space, w_object) if w_array is not None: w_object = w_array copy = False dtype = descriptor.decode_w_dtype(space, w_dtype) if space.is_none(w_order): order = 'C' else: order = space.str_w(w_order) if order == 'K': order = 'C' if order != 'C': # or order != 'F': raise oefmt(space.w_ValueError, "Unknown order: %s", order) if isinstance(w_object, W_NDimArray): if (dtype is None or w_object.get_dtype() is dtype): if copy and (subok or type(w_object) is W_NDimArray): return w_object.descr_copy(space, w_order) elif not copy and (subok or type(w_object) is W_NDimArray): return w_object if subok and not type(w_object) is W_NDimArray: raise oefmt(space.w_NotImplementedError, "array(..., subok=True) only partially implemented") # we have a ndarray, but need to copy or change dtype if dtype is None: dtype = w_object.get_dtype() if dtype != w_object.get_dtype(): # silently reject the copy value copy = True if copy: shape = w_object.get_shape() w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order) if support.product(shape) == 1: w_arr.set_scalar_value(dtype.coerce(space, w_object.implementation.getitem(0))) else: loop.setslice(space, shape, w_arr.implementation, w_object.implementation) return w_arr else: imp = w_object.implementation w_base = w_object if imp.base() is not None: w_base = imp.base() with imp as storage: sz = support.product(w_object.get_shape()) * dtype.elsize return W_NDimArray.from_shape_and_storage(space, w_object.get_shape(), storage, dtype, storage_bytes=sz, w_base=w_base, start=imp.start) else: # not an array shape, elems_w = strides.find_shape_and_elems(space, w_object, dtype) if dtype is None and space.isinstance_w(w_object, space.w_buffer): dtype = descriptor.get_dtype_cache(space).w_uint8dtype if dtype is None or (dtype.is_str_or_unicode() and dtype.elsize < 1): dtype = find_dtype_for_seq(space, elems_w, dtype) if dtype is None: dtype = descriptor.get_dtype_cache(space).w_float64dtype elif dtype.is_str_or_unicode() and dtype.elsize < 1: # promote S0 -> S1, U0 -> U1 dtype = descriptor.variable_dtype(space, dtype.char + '1') w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order) if support.product(shape) == 1: # safe from overflow since from_shape checks w_arr.set_scalar_value(dtype.coerce(space, elems_w[0])) else: loop.assign(space, w_arr, elems_w) return w_arr
raise if w_interface is None: # happens from compile.py return None version = space.int_w(space.finditem(w_interface, space.wrap("version"))) if version < 3: raise oefmt(space.w_NotImplementedError, "__array_interface__ version %d not supported", version) # make a view into the data w_shape = space.finditem(w_interface, space.wrap('shape')) w_dtype = space.finditem(w_interface, space.wrap('typestr')) w_descr = space.finditem(w_interface, space.wrap('descr')) data_w = space.listview(space.finditem(w_interface, space.wrap('data'))) w_strides = space.finditem(w_interface, space.wrap('strides')) shape = [space.int_w(i) for i in space.listview(w_shape)] dtype = descriptor.decode_w_dtype(space, w_dtype) rw = space.is_true(data_w[1]) #print 'create view from shape',shape,'dtype',dtype,'descr',w_descr,'data',data_w[0],'rw',rw raise oefmt(space.w_NotImplementedError, "creating array from __array_interface__ not supported yet") return @unwrap_spec(ndmin=int, copy=bool, subok=bool) def array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False, ndmin=0): w_res = _array(space, w_object, w_dtype, copy, w_order, subok) shape = w_res.get_shape() if len(shape) < ndmin: shape = [1] * (ndmin - len(shape)) + shape impl = w_res.implementation.set_shape(space, w_res, shape)
def __init__( self, space, w_seq, w_flags, w_op_flags, w_op_dtypes, w_casting, w_op_axes, w_itershape, buffersize=0, order=NPY.KEEPORDER, allow_backward=True, ): self.external_loop = False self.buffered = False self.tracked_index = "" self.common_dtype = False self.delay_bufalloc = False self.grow_inner = False self.ranged = False self.refs_ok = False self.reduce_ok = False self.zerosize_ok = False self.index_iter = None self.done = False self.first_next = True self.op_axes = [] self.allow_backward = allow_backward if not space.is_w(w_casting, space.w_None): self.casting = space.str_w(w_casting) else: self.casting = "safe" # convert w_seq operands to a list of W_NDimArray if space.isinstance_w(w_seq, space.w_tuple) or space.isinstance_w(w_seq, space.w_list): w_seq_as_list = space.listview(w_seq) self.seq = [ convert_to_array(space, w_elem) if not space.is_none(w_elem) else None for w_elem in w_seq_as_list ] else: self.seq = [convert_to_array(space, w_seq)] if order == NPY.ANYORDER: # 'A' means "'F' order if all the arrays are Fortran contiguous, # 'C' order otherwise" order = NPY.CORDER for s in self.seq: if s and not (s.get_flags() & NPY.ARRAY_F_CONTIGUOUS): break else: order = NPY.FORTRANORDER elif order == NPY.KEEPORDER: # 'K' means "as close to the order the array elements appear in # memory as possible", so match self.order to seq.order order = NPY.CORDER for s in self.seq: if s and not (s.get_order() == NPY.FORTRANORDER): break else: order = NPY.FORTRANORDER self.order = order parse_func_flags(space, self, w_flags) self.op_flags = parse_op_arg(space, "op_flags", w_op_flags, len(self.seq), parse_op_flag) # handle w_op_axes oa_ndim = -1 if not space.is_none(w_op_axes): oa_ndim = self.set_op_axes(space, w_op_axes) self.ndim = calculate_ndim(self.seq, oa_ndim) # handle w_op_dtypes part 1: creating self.dtypes list from input if not space.is_none(w_op_dtypes): w_seq_as_list = space.listview(w_op_dtypes) self.dtypes = [decode_w_dtype(space, w_elem) for w_elem in w_seq_as_list] if len(self.dtypes) != len(self.seq): raise oefmt(space.w_ValueError, "op_dtypes must be a tuple/list matching the number of ops") else: self.dtypes = [] # handle None or writable operands, calculate my shape outargs = [i for i in range(len(self.seq)) if self.seq[i] is None or self.op_flags[i].rw == "w"] if len(outargs) > 0: out_shape = shape_agreement_multiple(space, [self.seq[i] for i in outargs]) else: out_shape = None if space.isinstance_w(w_itershape, space.w_tuple) or space.isinstance_w(w_itershape, space.w_list): self.shape = [space.int_w(i) for i in space.listview(w_itershape)] else: self.shape = shape_agreement_multiple(space, self.seq, shape=out_shape) if len(outargs) > 0: # Make None operands writeonly and flagged for allocation if len(self.dtypes) > 0: out_dtype = self.dtypes[outargs[0]] else: out_dtype = None for i in range(len(self.seq)): if self.seq[i] is None: self.op_flags[i].allocate = True continue if self.op_flags[i].rw == "w": continue out_dtype = find_binop_result_dtype(space, self.seq[i].get_dtype(), out_dtype) for i in outargs: if self.seq[i] is None: # XXX can we postpone allocation to later? self.seq[i] = W_NDimArray.from_shape(space, self.shape, out_dtype) else: if not self.op_flags[i].broadcast: # Raises if output cannot be broadcast try: shape_agreement(space, self.shape, self.seq[i], False) except OperationError as e: raise oefmt( space.w_ValueError, "non-broadcastable" " output operand with shape %s doesn't match " "the broadcast shape %s", str(self.seq[i].get_shape()), str(self.shape), ) if self.tracked_index != "": order = self.order if order == NPY.KEEPORDER: order = self.seq[0].implementation.order if self.tracked_index == "multi": backward = False else: backward = (order == NPY.CORDER and self.tracked_index != "C") or ( order == NPY.FORTRANORDER and self.tracked_index != "F" ) self.index_iter = IndexIterator(self.shape, backward=backward) # handle w_op_dtypes part 2: copy where needed if possible if len(self.dtypes) > 0: for i in range(len(self.seq)): self_d = self.dtypes[i] seq_d = self.seq[i].get_dtype() if not self_d: self.dtypes[i] = seq_d elif self_d != seq_d: impl = self.seq[i].implementation if self.buffered or "r" in self.op_flags[i].tmp_copy: if not can_cast_array(space, self.seq[i], self_d, self.casting): raise oefmt( space.w_TypeError, "Iterator operand %d" " dtype could not be cast from %s to %s" " according to the rule '%s'", i, space.str_w(seq_d.descr_repr(space)), space.str_w(self_d.descr_repr(space)), self.casting, ) order = support.get_order_as_CF(impl.order, self.order) new_impl = impl.astype(space, self_d, order).copy(space) self.seq[i] = W_NDimArray(new_impl) else: raise oefmt( space.w_TypeError, "Iterator " "operand required copying or buffering, " "but neither copying nor buffering was " "enabled", ) if "w" in self.op_flags[i].rw: if not can_cast_type(space, self_d, seq_d, self.casting): raise oefmt( space.w_TypeError, "Iterator" " requested dtype could not be cast from " " %s to %s, the operand %d dtype, accord" "ing to the rule '%s'", space.str_w(self_d.descr_repr(space)), space.str_w(seq_d.descr_repr(space)), i, self.casting, ) elif self.buffered and not (self.external_loop and len(self.seq) < 2): for i in range(len(self.seq)): if i not in outargs: self.seq[i] = self.seq[i].descr_copy(space, w_order=space.wrap(self.order)) self.dtypes = [s.get_dtype() for s in self.seq] else: # copy them from seq self.dtypes = [s.get_dtype() for s in self.seq] # create an iterator for each operand self.iters = [] for i in range(len(self.seq)): it = self.get_iter(space, i) it.contiguous = False self.iters.append((it, it.reset())) if self.external_loop: coalesce_axes(self, space)
def try_interface_method(space, w_object, copy): try: w_interface = space.getattr(w_object, space.newtext("__array_interface__")) if w_interface is None: return None, False version_w = space.finditem(w_interface, space.newtext("version")) if version_w is None: raise oefmt(space.w_ValueError, "__array_interface__ found without" " 'version' key") if not space.isinstance_w(version_w, space.w_int): raise oefmt( space.w_ValueError, "__array_interface__ found with" " non-int 'version' key") version = space.int_w(version_w) if version < 3: raise oefmt(space.w_ValueError, "__array_interface__ version %d not supported", version) # make a view into the data w_shape = space.finditem(w_interface, space.newtext('shape')) w_dtype = space.finditem(w_interface, space.newtext('typestr')) w_descr = space.finditem(w_interface, space.newtext('descr')) w_data = space.finditem(w_interface, space.newtext('data')) w_strides = space.finditem(w_interface, space.newtext('strides')) if w_shape is None or w_dtype is None: raise oefmt( space.w_ValueError, "__array_interface__ missing one or more required keys: shape, typestr" ) if w_descr is not None: raise oefmt(space.w_NotImplementedError, "__array_interface__ descr not supported yet") if w_strides is None or space.is_w(w_strides, space.w_None): strides = None else: strides = [space.int_w(i) for i in space.listview(w_strides)] shape = [space.int_w(i) for i in space.listview(w_shape)] dtype = descriptor.decode_w_dtype(space, w_dtype) if dtype is None: raise oefmt(space.w_ValueError, "__array_interface__ could not decode dtype %R", w_dtype) if w_data is not None and (space.isinstance_w(w_data, space.w_tuple) or space.isinstance_w(w_data, space.w_list)): data_w = space.listview(w_data) w_data = rffi.cast(RAW_STORAGE_PTR, space.int_w(data_w[0])) read_only = space.is_true(data_w[1]) or copy offset = 0 w_base = w_object if read_only: w_base = None return W_NDimArray.from_shape_and_storage(space, shape, w_data, dtype, w_base=w_base, strides=strides, start=offset), read_only if w_data is None: w_data = w_object w_offset = space.finditem(w_interface, space.newtext('offset')) if w_offset is None: offset = 0 else: offset = space.int_w(w_offset) #print 'create view from shape',shape,'dtype',dtype,'data',data if strides is not None: raise oefmt(space.w_NotImplementedError, "__array_interface__ strides not fully supported yet") arr = frombuffer(space, w_data, dtype, support.product(shape), offset) new_impl = arr.implementation.reshape(arr, shape) return W_NDimArray(new_impl), False except OperationError as e: if e.match(space, space.w_AttributeError): return None, False raise
def _array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False): from pypy.module.micronumpy.boxes import W_GenericBox # numpy testing calls array(type(array([]))) and expects a ValueError if space.isinstance_w(w_object, space.w_type): raise oefmt(space.w_ValueError, "cannot create ndarray from type instance") # for anything that isn't already an array, try __array__ method first dtype = descriptor.decode_w_dtype(space, w_dtype) if not isinstance(w_object, W_NDimArray): w_array = try_array_method(space, w_object, w_dtype) if w_array is None: if (not space.isinstance_w(w_object, space.w_bytes) and not space.isinstance_w(w_object, space.w_unicode) and not isinstance(w_object, W_GenericBox)): # use buffer interface w_object = _array_from_buffer_3118(space, w_object, dtype) else: # continue with w_array, but do further operations in place w_object = w_array copy = False dtype = w_object.get_dtype() if not isinstance(w_object, W_NDimArray): w_array, _copy = try_interface_method(space, w_object, copy) if w_array is not None: w_object = w_array copy = _copy dtype = w_object.get_dtype() if isinstance(w_object, W_NDimArray): npy_order = order_converter(space, w_order, NPY.ANYORDER) if (dtype is None or w_object.get_dtype() is dtype) and ( subok or type(w_object) is W_NDimArray): flags = w_object.get_flags() must_copy = copy must_copy |= (npy_order == NPY.CORDER and not flags & NPY.ARRAY_C_CONTIGUOUS) must_copy |= (npy_order == NPY.FORTRANORDER and not flags & NPY.ARRAY_F_CONTIGUOUS) if must_copy: return w_object.descr_copy(space, space.newint(npy_order)) else: return w_object if subok and not type(w_object) is W_NDimArray: raise oefmt(space.w_NotImplementedError, "array(..., subok=True) only partially implemented") # we have a ndarray, but need to copy or change dtype if dtype is None: dtype = w_object.get_dtype() if dtype != w_object.get_dtype(): # silently reject the copy value copy = True if copy: shape = w_object.get_shape() order = support.get_order_as_CF(w_object.get_order(), npy_order) w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order) if support.product(shape) == 1: w_arr.set_scalar_value( dtype.coerce(space, w_object.implementation.getitem(0))) else: loop.setslice(space, shape, w_arr.implementation, w_object.implementation) return w_arr else: imp = w_object.implementation w_base = w_object sz = w_base.get_size() * dtype.elsize if imp.base() is not None: w_base = imp.base() if type(w_base) is W_NDimArray: sz = w_base.get_size() * dtype.elsize else: # this must succeed (mmap, buffer, ...) sz = space.int_w(space.call_method(w_base, 'size')) with imp as storage: return W_NDimArray.from_shape_and_storage(space, w_object.get_shape(), storage, dtype, storage_bytes=sz, w_base=w_base, strides=imp.strides, start=imp.start) else: # not an array npy_order = order_converter(space, w_order, NPY.CORDER) shape, elems_w = find_shape_and_elems(space, w_object, dtype) if dtype is None and space.isinstance_w(w_object, space.w_buffer): dtype = descriptor.get_dtype_cache(space).w_uint8dtype if dtype is None or (dtype.is_str_or_unicode() and dtype.elsize < 1): dtype = find_dtype_for_seq(space, elems_w, dtype) w_arr = W_NDimArray.from_shape(space, shape, dtype, order=npy_order) if support.product( shape) == 1: # safe from overflow since from_shape checks w_arr.set_scalar_value(dtype.coerce(space, elems_w[0])) else: loop.assign(space, w_arr, elems_w) return w_arr
def reduce(self, space, w_obj, w_axis, keepdims=False, out=None, dtype=None, cumulative=False): if self.argcount != 2: raise oefmt(space.w_ValueError, "reduce only supported for binary functions") assert isinstance(self, W_Ufunc2) obj = convert_to_array(space, w_obj) if obj.get_dtype().is_flexible(): raise oefmt(space.w_TypeError, "cannot perform reduce with flexible type") obj_shape = obj.get_shape() if obj.is_scalar(): return obj.get_scalar_value() shapelen = len(obj_shape) if space.is_none(w_axis): axis = maxint else: if space.isinstance_w(w_axis, space.w_tuple) and space.len_w(w_axis) == 1: w_axis = space.getitem(w_axis, space.wrap(0)) axis = space.int_w(w_axis) if axis < -shapelen or axis >= shapelen: raise oefmt(space.w_ValueError, "'axis' entry is out of bounds") if axis < 0: axis += shapelen assert axis >= 0 dtype = descriptor.decode_w_dtype(space, dtype) if dtype is None: if self.comparison_func: dtype = descriptor.get_dtype_cache(space).w_booldtype else: dtype = find_unaryop_result_dtype( space, obj.get_dtype(), promote_to_float=self.promote_to_float, promote_to_largest=self.promote_to_largest, promote_bools=self.promote_bools, ) if self.identity is None: for i in range(shapelen): if space.is_none(w_axis) or i == axis: if obj_shape[i] == 0: raise oefmt(space.w_ValueError, "zero-size array to reduction operation %s " "which has no identity", self.name) if shapelen > 1 and axis < shapelen: temp = None if cumulative: shape = obj_shape[:] temp_shape = obj_shape[:axis] + obj_shape[axis + 1:] if out: dtype = out.get_dtype() temp = W_NDimArray.from_shape(space, temp_shape, dtype, w_instance=obj) elif keepdims: shape = obj_shape[:axis] + [1] + obj_shape[axis + 1:] else: shape = obj_shape[:axis] + obj_shape[axis + 1:] if out: # Test for shape agreement # XXX maybe we need to do broadcasting here, although I must # say I don't understand the details for axis reduce if len(out.get_shape()) > len(shape): raise oefmt(space.w_ValueError, "output parameter for reduction operation %s " "has too many dimensions", self.name) elif len(out.get_shape()) < len(shape): raise oefmt(space.w_ValueError, "output parameter for reduction operation %s " "does not have enough dimensions", self.name) elif out.get_shape() != shape: raise oefmt(space.w_ValueError, "output parameter shape mismatch, expecting " "[%s], got [%s]", ",".join([str(x) for x in shape]), ",".join([str(x) for x in out.get_shape()]), ) dtype = out.get_dtype() else: out = W_NDimArray.from_shape(space, shape, dtype, w_instance=obj) if obj.get_size() == 0: if self.identity is not None: out.fill(space, self.identity.convert_to(space, dtype)) return out return loop.do_axis_reduce(space, shape, self.func, obj, dtype, axis, out, self.identity, cumulative, temp) if cumulative: if out: if out.get_shape() != [obj.get_size()]: raise OperationError(space.w_ValueError, space.wrap( "out of incompatible size")) else: out = W_NDimArray.from_shape(space, [obj.get_size()], dtype, w_instance=obj) loop.compute_reduce_cumulative(space, obj, out, dtype, self.func, self.identity) return out if out: if len(out.get_shape()) > 0: raise oefmt(space.w_ValueError, "output parameter for reduction operation %s has " "too many dimensions", self.name) dtype = out.get_dtype() res = loop.compute_reduce(space, obj, dtype, self.func, self.done_func, self.identity) if out: out.set_scalar_value(res) return out if keepdims: shape = [1] * len(obj_shape) out = W_NDimArray.from_shape(space, [1] * len(obj_shape), dtype, w_instance=obj) out.implementation.setitem(0, res) return out return res
def try_interface_method(space, w_object, copy): try: w_interface = space.getattr(w_object, space.wrap("__array_interface__")) if w_interface is None: return None, False version_w = space.finditem(w_interface, space.wrap("version")) if version_w is None: raise oefmt(space.w_ValueError, "__array_interface__ found without" " 'version' key") if not space.isinstance_w(version_w, space.w_int): raise oefmt(space.w_ValueError, "__array_interface__ found with" " non-int 'version' key") version = space.int_w(version_w) if version < 3: raise oefmt(space.w_ValueError, "__array_interface__ version %d not supported", version) # make a view into the data w_shape = space.finditem(w_interface, space.wrap('shape')) w_dtype = space.finditem(w_interface, space.wrap('typestr')) w_descr = space.finditem(w_interface, space.wrap('descr')) w_data = space.finditem(w_interface, space.wrap('data')) w_strides = space.finditem(w_interface, space.wrap('strides')) if w_shape is None or w_dtype is None: raise oefmt(space.w_ValueError, "__array_interface__ missing one or more required keys: shape, typestr" ) if w_descr is not None: raise oefmt(space.w_NotImplementedError, "__array_interface__ descr not supported yet") if w_strides is None or space.is_w(w_strides, space.w_None): strides = None else: strides = [space.int_w(i) for i in space.listview(w_strides)] shape = [space.int_w(i) for i in space.listview(w_shape)] dtype = descriptor.decode_w_dtype(space, w_dtype) if dtype is None: raise oefmt(space.w_ValueError, "__array_interface__ could not decode dtype %R", w_dtype ) if w_data is not None and (space.isinstance_w(w_data, space.w_tuple) or space.isinstance_w(w_data, space.w_list)): data_w = space.listview(w_data) w_data = rffi.cast(RAW_STORAGE_PTR, space.int_w(data_w[0])) read_only = space.is_true(data_w[1]) or copy offset = 0 w_base = w_object if read_only: w_base = None return W_NDimArray.from_shape_and_storage(space, shape, w_data, dtype, w_base=w_base, strides=strides, start=offset), read_only if w_data is None: w_data = w_object w_offset = space.finditem(w_interface, space.wrap('offset')) if w_offset is None: offset = 0 else: offset = space.int_w(w_offset) #print 'create view from shape',shape,'dtype',dtype,'data',data if strides is not None: raise oefmt(space.w_NotImplementedError, "__array_interface__ strides not fully supported yet") arr = frombuffer(space, w_data, dtype, support.product(shape), offset) new_impl = arr.implementation.reshape(arr, shape) return W_NDimArray(new_impl), False except OperationError as e: if e.match(space, space.w_AttributeError): return None, False raise
def _array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False): from pypy.module.micronumpy.boxes import W_GenericBox # numpy testing calls array(type(array([]))) and expects a ValueError if space.isinstance_w(w_object, space.w_type): raise oefmt(space.w_ValueError, "cannot create ndarray from type instance") # for anything that isn't already an array, try __array__ method first dtype = descriptor.decode_w_dtype(space, w_dtype) if not isinstance(w_object, W_NDimArray): w_array = try_array_method(space, w_object, w_dtype) if w_array is None: if ( not space.isinstance_w(w_object, space.w_str) and not space.isinstance_w(w_object, space.w_unicode) and not isinstance(w_object, W_GenericBox)): # use buffer interface w_object = _array_from_buffer_3118(space, w_object, dtype) else: # continue with w_array, but do further operations in place w_object = w_array copy = False dtype = w_object.get_dtype() if not isinstance(w_object, W_NDimArray): w_array, _copy = try_interface_method(space, w_object, copy) if w_array is not None: w_object = w_array copy = _copy dtype = w_object.get_dtype() if isinstance(w_object, W_NDimArray): npy_order = order_converter(space, w_order, NPY.ANYORDER) if (dtype is None or w_object.get_dtype() is dtype) and (subok or type(w_object) is W_NDimArray): flags = w_object.get_flags() must_copy = copy must_copy |= (npy_order == NPY.CORDER and not flags & NPY.ARRAY_C_CONTIGUOUS) must_copy |= (npy_order == NPY.FORTRANORDER and not flags & NPY.ARRAY_F_CONTIGUOUS) if must_copy: return w_object.descr_copy(space, space.wrap(npy_order)) else: return w_object if subok and not type(w_object) is W_NDimArray: raise oefmt(space.w_NotImplementedError, "array(..., subok=True) only partially implemented") # we have a ndarray, but need to copy or change dtype if dtype is None: dtype = w_object.get_dtype() if dtype != w_object.get_dtype(): # silently reject the copy value copy = True if copy: shape = w_object.get_shape() order = support.get_order_as_CF(w_object.get_order(), npy_order) w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order) if support.product(shape) == 1: w_arr.set_scalar_value(dtype.coerce(space, w_object.implementation.getitem(0))) else: loop.setslice(space, shape, w_arr.implementation, w_object.implementation) return w_arr else: imp = w_object.implementation w_base = w_object sz = w_base.get_size() * dtype.elsize if imp.base() is not None: w_base = imp.base() if type(w_base) is W_NDimArray: sz = w_base.get_size() * dtype.elsize else: # this must succeed (mmap, buffer, ...) sz = space.int_w(space.call_method(w_base, 'size')) with imp as storage: return W_NDimArray.from_shape_and_storage(space, w_object.get_shape(), storage, dtype, storage_bytes=sz, w_base=w_base, strides=imp.strides, start=imp.start) else: # not an array npy_order = order_converter(space, w_order, NPY.CORDER) shape, elems_w = find_shape_and_elems(space, w_object, dtype) if dtype is None and space.isinstance_w(w_object, space.w_buffer): dtype = descriptor.get_dtype_cache(space).w_uint8dtype if dtype is None or (dtype.is_str_or_unicode() and dtype.elsize < 1): dtype = find_dtype_for_seq(space, elems_w, dtype) w_arr = W_NDimArray.from_shape(space, shape, dtype, order=npy_order) if support.product(shape) == 1: # safe from overflow since from_shape checks w_arr.set_scalar_value(dtype.coerce(space, elems_w[0])) else: loop.assign(space, w_arr, elems_w) return w_arr
def __init__(self, space, w_seq, w_flags, w_op_flags, w_op_dtypes, w_casting, w_op_axes, w_itershape, buffersize=0, order=NPY.KEEPORDER, allow_backward=True): self.external_loop = False self.buffered = False self.tracked_index = '' self.common_dtype = False self.delay_bufalloc = False self.grow_inner = False self.ranged = False self.refs_ok = False self.reduce_ok = False self.zerosize_ok = False self.index_iter = None self.done = False self.first_next = True self.op_axes = [] self.allow_backward = allow_backward if not space.is_w(w_casting, space.w_None): self.casting = space.str_w(w_casting) else: self.casting = 'safe' # convert w_seq operands to a list of W_NDimArray if space.isinstance_w(w_seq, space.w_tuple) or \ space.isinstance_w(w_seq, space.w_list): w_seq_as_list = space.listview(w_seq) self.seq = [ convert_to_array(space, w_elem) if not space.is_none(w_elem) else None for w_elem in w_seq_as_list ] else: self.seq = [convert_to_array(space, w_seq)] if order == NPY.ANYORDER: # 'A' means "'F' order if all the arrays are Fortran contiguous, # 'C' order otherwise" order = NPY.CORDER for s in self.seq: if s and not (s.get_flags() & NPY.ARRAY_F_CONTIGUOUS): break else: order = NPY.FORTRANORDER elif order == NPY.KEEPORDER: # 'K' means "as close to the order the array elements appear in # memory as possible", so match self.order to seq.order order = NPY.CORDER for s in self.seq: if s and not (s.get_order() == NPY.FORTRANORDER): break else: order = NPY.FORTRANORDER self.order = order parse_func_flags(space, self, w_flags) self.op_flags = parse_op_arg(space, 'op_flags', w_op_flags, len(self.seq), parse_op_flag) # handle w_op_axes oa_ndim = -1 if not space.is_none(w_op_axes): oa_ndim = self.set_op_axes(space, w_op_axes) self.ndim = calculate_ndim(self.seq, oa_ndim) # handle w_op_dtypes part 1: creating self.dtypes list from input if not space.is_none(w_op_dtypes): w_seq_as_list = space.listview(w_op_dtypes) self.dtypes = [ decode_w_dtype(space, w_elem) for w_elem in w_seq_as_list ] if len(self.dtypes) != len(self.seq): raise oefmt( space.w_ValueError, "op_dtypes must be a tuple/list matching the number of ops" ) else: self.dtypes = [] # handle None or writable operands, calculate my shape outargs = [ i for i in range(len(self.seq)) if self.seq[i] is None or self.op_flags[i].rw == 'w' ] if len(outargs) > 0: out_shape = shape_agreement_multiple( space, [self.seq[i] for i in outargs]) else: out_shape = None if space.isinstance_w(w_itershape, space.w_tuple) or \ space.isinstance_w(w_itershape, space.w_list): self.shape = [space.int_w(i) for i in space.listview(w_itershape)] else: self.shape = shape_agreement_multiple(space, self.seq, shape=out_shape) if len(outargs) > 0: # Make None operands writeonly and flagged for allocation if len(self.dtypes) > 0: out_dtype = self.dtypes[outargs[0]] else: out_dtype = None for i in range(len(self.seq)): if self.seq[i] is None: self.op_flags[i].allocate = True continue if self.op_flags[i].rw == 'w': continue out_dtype = find_binop_result_dtype( space, self.seq[i].get_dtype(), out_dtype) for i in outargs: if self.seq[i] is None: # XXX can we postpone allocation to later? self.seq[i] = W_NDimArray.from_shape( space, self.shape, out_dtype) else: if not self.op_flags[i].broadcast: # Raises if output cannot be broadcast try: shape_agreement(space, self.shape, self.seq[i], False) except OperationError as e: raise oefmt( space.w_ValueError, "non-broadcastable" " output operand with shape %s doesn't match " "the broadcast shape %s", str(self.seq[i].get_shape()), str(self.shape)) if self.tracked_index != "": order = self.order if order == NPY.KEEPORDER: order = self.seq[0].implementation.order if self.tracked_index == "multi": backward = False else: backward = ((order == NPY.CORDER and self.tracked_index != 'C') or (order == NPY.FORTRANORDER and self.tracked_index != 'F')) self.index_iter = IndexIterator(self.shape, backward=backward) # handle w_op_dtypes part 2: copy where needed if possible if len(self.dtypes) > 0: for i in range(len(self.seq)): self_d = self.dtypes[i] seq_d = self.seq[i].get_dtype() if not self_d: self.dtypes[i] = seq_d elif self_d != seq_d: impl = self.seq[i].implementation if self.buffered or 'r' in self.op_flags[i].tmp_copy: if not can_cast_array(space, self.seq[i], self_d, self.casting): raise oefmt( space.w_TypeError, "Iterator operand %d" " dtype could not be cast from %s to %s" " according to the rule '%s'", i, space.str_w(seq_d.descr_repr(space)), space.str_w(self_d.descr_repr(space)), self.casting) order = support.get_order_as_CF(impl.order, self.order) new_impl = impl.astype(space, self_d, order).copy(space) self.seq[i] = W_NDimArray(new_impl) else: raise oefmt( space.w_TypeError, "Iterator " "operand required copying or buffering, " "but neither copying nor buffering was " "enabled") if 'w' in self.op_flags[i].rw: if not can_cast_type(space, self_d, seq_d, self.casting): raise oefmt( space.w_TypeError, "Iterator" " requested dtype could not be cast from " " %s to %s, the operand %d dtype, accord" "ing to the rule '%s'", space.str_w(self_d.descr_repr(space)), space.str_w(seq_d.descr_repr(space)), i, self.casting) elif self.buffered and not (self.external_loop and len(self.seq) < 2): for i in range(len(self.seq)): if i not in outargs: self.seq[i] = self.seq[i].descr_copy(space, w_order=space.wrap( self.order)) self.dtypes = [s.get_dtype() for s in self.seq] else: #copy them from seq self.dtypes = [s.get_dtype() for s in self.seq] # create an iterator for each operand self.iters = [] for i in range(len(self.seq)): it = self.get_iter(space, i) it.contiguous = False self.iters.append((it, it.reset())) if self.external_loop: coalesce_axes(self, space)
def __init__(self, space, w_seq, w_flags, w_op_flags, w_op_dtypes, w_casting, w_op_axes, w_itershape, buffersize=0, order='K'): self.order = order self.external_loop = False self.buffered = False self.tracked_index = '' self.common_dtype = False self.delay_bufalloc = False self.grow_inner = False self.ranged = False self.refs_ok = False self.reduce_ok = False self.zerosize_ok = False self.index_iter = None self.done = False self.first_next = True self.op_axes = [] # convert w_seq operands to a list of W_NDimArray if space.isinstance_w(w_seq, space.w_tuple) or \ space.isinstance_w(w_seq, space.w_list): w_seq_as_list = space.listview(w_seq) self.seq = [ convert_to_array(space, w_elem) if not space.is_none(w_elem) else None for w_elem in w_seq_as_list ] else: self.seq = [convert_to_array(space, w_seq)] parse_func_flags(space, self, w_flags) self.op_flags = parse_op_arg(space, 'op_flags', w_op_flags, len(self.seq), parse_op_flag) # handle w_op_axes oa_ndim = -1 if not space.is_none(w_op_axes): oa_ndim = self.set_op_axes(space, w_op_axes) self.ndim = calculate_ndim(self.seq, oa_ndim) # handle w_op_dtypes part 1: creating self.dtypes list from input if not space.is_none(w_op_dtypes): w_seq_as_list = space.listview(w_op_dtypes) self.dtypes = [ decode_w_dtype(space, w_elem) for w_elem in w_seq_as_list ] if len(self.dtypes) != len(self.seq): raise oefmt( space.w_ValueError, "op_dtypes must be a tuple/list matching the number of ops" ) else: self.dtypes = [] # handle None or writable operands, calculate my shape outargs = [ i for i in range(len(self.seq)) if self.seq[i] is None or self.op_flags[i].rw == 'w' ] if len(outargs) > 0: out_shape = shape_agreement_multiple( space, [self.seq[i] for i in outargs]) else: out_shape = None if space.isinstance_w(w_itershape, space.w_tuple) or \ space.isinstance_w(w_itershape, space.w_list): self.shape = [space.int_w(i) for i in space.listview(w_itershape)] else: self.shape = shape_agreement_multiple(space, self.seq, shape=out_shape) if len(outargs) > 0: # Make None operands writeonly and flagged for allocation if len(self.dtypes) > 0: out_dtype = self.dtypes[outargs[0]] else: out_dtype = None for i in range(len(self.seq)): if self.seq[i] is None: self.op_flags[i].allocate = True continue if self.op_flags[i].rw == 'w': continue out_dtype = find_binop_result_dtype( space, self.seq[i].get_dtype(), out_dtype) for i in outargs: if self.seq[i] is None: # XXX can we postpone allocation to later? self.seq[i] = W_NDimArray.from_shape( space, self.shape, out_dtype) else: if not self.op_flags[i].broadcast: # Raises if ooutput cannot be broadcast shape_agreement(space, self.shape, self.seq[i], False) if self.tracked_index != "": if self.order == "K": self.order = self.seq[0].implementation.order if self.tracked_index == "multi": backward = False else: backward = self.order != self.tracked_index self.index_iter = IndexIterator(self.shape, backward=backward) # handle w_op_dtypes part 2: copy where needed if possible if len(self.dtypes) > 0: for i in range(len(self.seq)): selfd = self.dtypes[i] seq_d = self.seq[i].get_dtype() if not selfd: self.dtypes[i] = seq_d elif selfd != seq_d: if not 'r' in self.op_flags[i].tmp_copy: raise oefmt( space.w_TypeError, "Iterator operand required copying or " "buffering for operand %d", i) impl = self.seq[i].implementation new_impl = impl.astype(space, selfd) self.seq[i] = W_NDimArray(new_impl) else: #copy them from seq self.dtypes = [s.get_dtype() for s in self.seq] # create an iterator for each operand self.iters = [] for i in range(len(self.seq)): it = get_iter(space, self.order, self.seq[i], self.shape, self.dtypes[i], self.op_flags[i], self) it.contiguous = False self.iters.append((it, it.reset())) if self.external_loop: coalesce_axes(self, space)
def array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False, ndmin=0): from pypy.module.micronumpy import strides # for anything that isn't already an array, try __array__ method first if not isinstance(w_object, W_NDimArray): w___array__ = space.lookup(w_object, "__array__") if w___array__ is not None: if space.is_none(w_dtype): w_dtype = space.w_None w_array = space.get_and_call_function(w___array__, w_object, w_dtype) if isinstance(w_array, W_NDimArray): # feed w_array back into array() for other properties return array(space, w_array, w_dtype, False, w_order, subok, ndmin) else: raise oefmt(space.w_ValueError, "object __array__ method not producing an array") dtype = descriptor.decode_w_dtype(space, w_dtype) if space.is_none(w_order): order = 'C' else: order = space.str_w(w_order) if order == 'K': order = 'C' if order != 'C': # or order != 'F': raise oefmt(space.w_ValueError, "Unknown order: %s", order) # arrays with correct dtype if isinstance(w_object, W_NDimArray) and \ (space.is_none(w_dtype) or w_object.get_dtype() is dtype): shape = w_object.get_shape() if copy: w_ret = w_object.descr_copy(space) else: if ndmin <= len(shape): return w_object new_impl = w_object.implementation.set_shape(space, w_object, shape) w_ret = W_NDimArray(new_impl) if ndmin > len(shape): shape = [1] * (ndmin - len(shape)) + shape w_ret.implementation = w_ret.implementation.set_shape(space, w_ret, shape) return w_ret # not an array or incorrect dtype shape, elems_w = strides.find_shape_and_elems(space, w_object, dtype) if dtype is None or (dtype.is_str_or_unicode() and dtype.elsize < 1): dtype = strides.find_dtype_for_seq(space, elems_w, dtype) if dtype is None: dtype = descriptor.get_dtype_cache(space).w_float64dtype elif dtype.is_str_or_unicode() and dtype.elsize < 1: # promote S0 -> S1, U0 -> U1 dtype = descriptor.variable_dtype(space, dtype.char + '1') if ndmin > len(shape): shape = [1] * (ndmin - len(shape)) + shape w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order) if len(elems_w) == 1: w_arr.set_scalar_value(dtype.coerce(space, elems_w[0])) else: loop.assign(space, w_arr, elems_w) return w_arr
def _array(space, w_object, w_dtype=None, copy=True, w_order=None, subok=False): from pypy.module.micronumpy import strides # for anything that isn't already an array, try __array__ method first if not isinstance(w_object, W_NDimArray): w_array = try_array_method(space, w_object, w_dtype) if w_array is not None: # continue with w_array, but do further operations in place w_object = w_array copy = False dtype = descriptor.decode_w_dtype(space, w_dtype) if space.is_none(w_order): order = 'C' else: order = space.str_w(w_order) if order == 'K': order = 'C' if order != 'C': # or order != 'F': raise oefmt(space.w_ValueError, "Unknown order: %s", order) if isinstance(w_object, W_NDimArray): if (dtype is None or w_object.get_dtype() is dtype): if copy and (subok or type(w_object) is W_NDimArray): return w_object.descr_copy(space, w_order) elif not copy and (subok or type(w_object) is W_NDimArray): return w_object # we have a ndarray, but need to copy or change dtype or create W_NDimArray if dtype is None: dtype = w_object.get_dtype() if dtype != w_object.get_dtype(): # silently reject the copy value copy = True if copy: shape = w_object.get_shape() _elems_w = w_object.reshape(space, space.wrap(-1)) elems_w = [None] * w_object.get_size() for i in range(len(elems_w)): elems_w[i] = _elems_w.descr_getitem(space, space.wrap(i)) elif subok: raise oefmt(space.w_NotImplementedError, "array(...copy=False, subok=True) not implemented yet") else: sz = support.product(w_object.get_shape()) * dtype.elsize return W_NDimArray.from_shape_and_storage(space, w_object.get_shape(),w_object.implementation.storage, dtype, storage_bytes=sz, w_base=w_object) else: # not an array shape, elems_w = strides.find_shape_and_elems(space, w_object, dtype) if dtype is None or (dtype.is_str_or_unicode() and dtype.elsize < 1): dtype = strides.find_dtype_for_seq(space, elems_w, dtype) if dtype is None: dtype = descriptor.get_dtype_cache(space).w_float64dtype elif dtype.is_str_or_unicode() and dtype.elsize < 1: # promote S0 -> S1, U0 -> U1 dtype = descriptor.variable_dtype(space, dtype.char + '1') w_arr = W_NDimArray.from_shape(space, shape, dtype, order=order) if len(elems_w) == 1: w_arr.set_scalar_value(dtype.coerce(space, elems_w[0])) else: loop.assign(space, w_arr, elems_w) return w_arr