Пример #1
0
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
Пример #2
0
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 
Пример #3
0
    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)
Пример #4
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()
            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
Пример #5
0
        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):
Пример #6
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
Пример #7
0
        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)
Пример #8
0
    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)
Пример #9
0
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
Пример #10
0
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
Пример #11
0
 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
Пример #12
0
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
Пример #13
0
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
Пример #14
0
    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)
Пример #15
0
    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)
Пример #16
0
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
Пример #17
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

    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