diff options
Diffstat (limited to 'numpy/core')
109 files changed, 9765 insertions, 5239 deletions
diff --git a/numpy/core/__init__.py b/numpy/core/__init__.py index f6b9534eb..41314cee4 100644 --- a/numpy/core/__init__.py +++ b/numpy/core/__init__.py @@ -18,7 +18,7 @@ del envbak del os from . import umath -from . import _internal # for freeze programs +from . import _internal # for freeze programs from . import numerictypes as nt multiarray.set_typeDict(nt.sctypeDict) from . import numeric @@ -40,8 +40,7 @@ from . import shape_base from .shape_base import * del nt -from .fromnumeric import amax as max, amin as min, \ - round_ as round +from .fromnumeric import amax as max, amin as min, round_ as round from .numeric import absolute as abs __all__ = ['char', 'rec', 'memmap'] diff --git a/numpy/core/_internal.py b/numpy/core/_internal.py index d32f59390..879f4a224 100644 --- a/numpy/core/_internal.py +++ b/numpy/core/_internal.py @@ -8,9 +8,11 @@ from __future__ import division, absolute_import, print_function import re import sys -import warnings -from numpy.compat import asbytes, bytes +from numpy.compat import asbytes, basestring +from .multiarray import dtype, array, ndarray +import ctypes +from .numerictypes import object_ if (sys.byteorder == 'little'): _nbo = asbytes('<') @@ -18,7 +20,6 @@ else: _nbo = asbytes('>') def _makenames_list(adict, align): - from .multiarray import dtype allfields = [] fnames = list(adict.keys()) for fname in fnames: @@ -52,7 +53,6 @@ def _makenames_list(adict, align): # a dictionary without "names" and "formats" # fields is used as a data-type descriptor. def _usefields(adict, align): - from .multiarray import dtype try: names = adict[-1] except KeyError: @@ -72,10 +72,10 @@ def _usefields(adict, align): else: titles.append(None) - return dtype({"names" : names, - "formats" : formats, - "offsets" : offsets, - "titles" : titles}, align) + return dtype({"names": names, + "formats": formats, + "offsets": offsets, + "titles": titles}, align) # construct an array_protocol descriptor list @@ -100,7 +100,6 @@ def _array_descr(descriptor): else: return (_array_descr(subdtype[0]), subdtype[1]) - names = descriptor.names ordered_fields = [fields[x] + (x,) for x in names] result = [] @@ -130,7 +129,6 @@ def _array_descr(descriptor): # so don't remove the name here, or you'll # break backward compatibilty. def _reconstruct(subtype, shape, dtype): - from .multiarray import ndarray return ndarray.__new__(subtype, shape, dtype) @@ -140,7 +138,7 @@ format_re = re.compile(asbytes( r'(?P<order1>[<>|=]?)' r'(?P<repeats> *[(]?[ ,0-9L]*[)]? *)' r'(?P<order2>[<>|=]?)' - r'(?P<dtype>[A-Za-z0-9.]*(?:\[[a-zA-Z0-9,.]+\])?)')) + r'(?P<dtype>[A-Za-z0-9.?]*(?:\[[a-zA-Z0-9,.]+\])?)')) sep_re = re.compile(asbytes(r'\s*,\s*')) space_re = re.compile(asbytes(r'\s+$')) @@ -167,8 +165,8 @@ def _commastring(astr): mo = sep_re.match(astr, pos=startindex) if not mo: raise ValueError( - 'format number %d of "%s" is not recognized' % - (len(result)+1, astr)) + 'format number %d of "%s" is not recognized' % + (len(result)+1, astr)) startindex = mo.end() if order2 == asbytes(''): @@ -179,7 +177,9 @@ def _commastring(astr): order1 = _convorder.get(order1, order1) order2 = _convorder.get(order2, order2) if (order1 != order2): - raise ValueError('inconsistent byte-order specification %s and %s' % (order1, order2)) + raise ValueError( + 'inconsistent byte-order specification %s and %s' % + (order1, order2)) order = order1 if order in [asbytes('|'), asbytes('='), _nbo]: @@ -194,12 +194,10 @@ def _commastring(astr): return result def _getintp_ctype(): - from .multiarray import dtype val = _getintp_ctype.cache if val is not None: return val char = dtype('p').char - import ctypes if (char == 'i'): val = ctypes.c_int elif char == 'l': @@ -224,7 +222,6 @@ class _missing_ctypes(object): class _ctypes(object): def __init__(self, array, ptr=None): try: - import ctypes self._ctypes = ctypes except ImportError: self._ctypes = _missing_ctypes() @@ -287,23 +284,221 @@ def _newnames(datatype, order): return tuple(list(order) + nameslist) raise ValueError("unsupported order value: %s" % (order,)) -# Given an array with fields and a sequence of field names -# construct a new array with just those fields copied over -def _index_fields(ary, fields): - from .multiarray import empty, dtype, array +def _index_fields(ary, names): + """ Given a structured array and a sequence of field names + construct new array with just those fields. + + Parameters + ---------- + ary : ndarray + Structured array being subscripted + names : string or list of strings + Either a single field name, or a list of field names + + Returns + ------- + sub_ary : ndarray + If `names` is a single field name, the return value is identical to + ary.getfield, a writeable view into `ary`. If `names` is a list of + field names the return value is a copy of `ary` containing only those + fields. This is planned to return a view in the future. + + Raises + ------ + ValueError + If `ary` does not contain a field given in `names`. + + """ dt = ary.dtype - names = [name for name in fields if name in dt.names] - formats = [dt.fields[name][0] for name in fields if name in dt.names] - offsets = [dt.fields[name][1] for name in fields if name in dt.names] + #use getfield to index a single field + if isinstance(names, basestring): + try: + return ary.getfield(dt.fields[names][0], dt.fields[names][1]) + except KeyError: + raise ValueError("no field of name %s" % names) + + for name in names: + if name not in dt.fields: + raise ValueError("no field of name %s" % name) + + formats = [dt.fields[name][0] for name in names] + offsets = [dt.fields[name][1] for name in names] + + view_dtype = {'names': names, 'formats': formats, + 'offsets': offsets, 'itemsize': dt.itemsize} + + # return copy for now (future plan to return ary.view(dtype=view_dtype)) + copy_dtype = {'names': view_dtype['names'], + 'formats': view_dtype['formats']} + return array(ary.view(dtype=view_dtype), dtype=copy_dtype, copy=True) + + +def _get_all_field_offsets(dtype, base_offset=0): + """ Returns the types and offsets of all fields in a (possibly structured) + data type, including nested fields and subarrays. + + Parameters + ---------- + dtype : data-type + Data type to extract fields from. + base_offset : int, optional + Additional offset to add to all field offsets. + + Returns + ------- + fields : list of (data-type, int) pairs + A flat list of (dtype, byte offset) pairs. + + """ + fields = [] + if dtype.fields is not None: + for name in dtype.names: + sub_dtype = dtype.fields[name][0] + sub_offset = dtype.fields[name][1] + base_offset + fields.extend(_get_all_field_offsets(sub_dtype, sub_offset)) + else: + if dtype.shape: + sub_offsets = _get_all_field_offsets(dtype.base, base_offset) + count = 1 + for dim in dtype.shape: + count *= dim + fields.extend((typ, off + dtype.base.itemsize*j) + for j in range(count) for (typ, off) in sub_offsets) + else: + fields.append((dtype, base_offset)) + return fields + +def _check_field_overlap(new_fields, old_fields): + """ Perform object memory overlap tests for two data-types (see + _view_is_safe). + + This function checks that new fields only access memory contained in old + fields, and that non-object fields are not interpreted as objects and vice + versa. + + Parameters + ---------- + new_fields : list of (data-type, int) pairs + Flat list of (dtype, byte offset) pairs for the new data type, as + returned by _get_all_field_offsets. + old_fields: list of (data-type, int) pairs + Flat list of (dtype, byte offset) pairs for the old data type, as + returned by _get_all_field_offsets. + + Raises + ------ + TypeError + If the new fields are incompatible with the old fields + + """ + + #first go byte by byte and check we do not access bytes not in old_fields + new_bytes = set() + for tp, off in new_fields: + new_bytes.update(set(range(off, off+tp.itemsize))) + old_bytes = set() + for tp, off in old_fields: + old_bytes.update(set(range(off, off+tp.itemsize))) + if new_bytes.difference(old_bytes): + raise TypeError("view would access data parent array doesn't own") + + #next check that we do not interpret non-Objects as Objects, and vv + obj_offsets = [off for (tp, off) in old_fields if tp.type is object_] + obj_size = dtype(object_).itemsize + + for fld_dtype, fld_offset in new_fields: + if fld_dtype.type is object_: + # check we do not create object views where + # there are no objects. + if fld_offset not in obj_offsets: + raise TypeError("cannot view non-Object data as Object type") + else: + # next check we do not create non-object views + # where there are already objects. + # see validate_object_field_overlap for a similar computation. + for obj_offset in obj_offsets: + if (fld_offset < obj_offset + obj_size and + obj_offset < fld_offset + fld_dtype.itemsize): + raise TypeError("cannot view Object as non-Object type") + +def _getfield_is_safe(oldtype, newtype, offset): + """ Checks safety of getfield for object arrays. + + As in _view_is_safe, we need to check that memory containing objects is not + reinterpreted as a non-object datatype and vice versa. + + Parameters + ---------- + oldtype : data-type + Data type of the original ndarray. + newtype : data-type + Data type of the field being accessed by ndarray.getfield + offset : int + Offset of the field being accessed by ndarray.getfield + + Raises + ------ + TypeError + If the field access is invalid + + """ + new_fields = _get_all_field_offsets(newtype, offset) + old_fields = _get_all_field_offsets(oldtype) + # raises if there is a problem + _check_field_overlap(new_fields, old_fields) + +def _view_is_safe(oldtype, newtype): + """ Checks safety of a view involving object arrays, for example when + doing:: + + np.zeros(10, dtype=oldtype).view(newtype) + + We need to check that + 1) No memory that is not an object will be interpreted as a object, + 2) No memory containing an object will be interpreted as an arbitrary type. + Both cases can cause segfaults, eg in the case the view is written to. + Strategy here is to also disallow views where newtype has any field in a + place oldtype doesn't. + + Parameters + ---------- + oldtype : data-type + Data type of original ndarray + newtype : data-type + Data type of the view + + Raises + ------ + TypeError + If the new type is incompatible with the old type. + + """ + new_fields = _get_all_field_offsets(newtype) + new_size = newtype.itemsize + + old_fields = _get_all_field_offsets(oldtype) + old_size = oldtype.itemsize + + # if the itemsizes are not equal, we need to check that all the + # 'tiled positions' of the object match up. Here, we allow + # for arbirary itemsizes (even those possibly disallowed + # due to stride/data length issues). + if old_size == new_size: + new_num = old_num = 1 + else: + gcd_new_old = _gcd(new_size, old_size) + new_num = old_size // gcd_new_old + old_num = new_size // gcd_new_old - view_dtype = {'names':names, 'formats':formats, 'offsets':offsets, 'itemsize':dt.itemsize} - view = ary.view(dtype=view_dtype) + # get position of fields within the tiling + new_fieldtile = [(tp, off + new_size*j) + for j in range(new_num) for (tp, off) in new_fields] + old_fieldtile = [(tp, off + old_size*j) + for j in range(old_num) for (tp, off) in old_fields] - # Return a copy for now until behavior is fully deprecated - # in favor of returning view - copy_dtype = {'names':view_dtype['names'], 'formats':view_dtype['formats']} - return array(view, dtype=copy_dtype, copy=True) + # raises if there is a problem + _check_field_overlap(new_fieldtile, old_fieldtile) # Given a string containing a PEP 3118 format specifier, # construct a Numpy dtype @@ -330,7 +525,7 @@ _pep3118_native_map = { 's': 'S', 'w': 'U', 'O': 'O', - 'x': 'V', # padding + 'x': 'V', # padding } _pep3118_native_typechars = ''.join(_pep3118_native_map.keys()) @@ -354,24 +549,23 @@ _pep3118_standard_map = { 's': 'S', 'w': 'U', 'O': 'O', - 'x': 'V', # padding + 'x': 'V', # padding } _pep3118_standard_typechars = ''.join(_pep3118_standard_map.keys()) def _dtype_from_pep3118(spec, byteorder='@', is_subdtype=False): - from numpy.core.multiarray import dtype - fields = {} offset = 0 explicit_name = False this_explicit_name = False common_alignment = 1 is_padding = False - last_offset = 0 dummy_name_index = [0] + def next_dummy_name(): dummy_name_index[0] += 1 + def get_dummy_name(): while True: name = 'f%d' % dummy_name_index[0] @@ -495,7 +689,6 @@ def _dtype_from_pep3118(spec, byteorder='@', is_subdtype=False): raise RuntimeError("Duplicate field name '%s' in PEP3118 format" % name) fields[name] = (value, offset) - last_offset = offset if not this_explicit_name: next_dummy_name() @@ -505,8 +698,8 @@ def _dtype_from_pep3118(spec, byteorder='@', is_subdtype=False): offset += extra_offset # Check if this was a simple 1-item type - if len(fields) == 1 and not explicit_name and fields['f0'][1] == 0 \ - and not is_subdtype: + if (len(fields) == 1 and not explicit_name and + fields['f0'][1] == 0 and not is_subdtype): ret = fields['f0'][0] else: ret = dtype(fields) @@ -526,15 +719,13 @@ def _dtype_from_pep3118(spec, byteorder='@', is_subdtype=False): def _add_trailing_padding(value, padding): """Inject the specified number of padding bytes at the end of a dtype""" - from numpy.core.multiarray import dtype - if value.fields is None: vfields = {'f0': (value, 0)} else: vfields = dict(value.fields) - if value.names and value.names[-1] == '' and \ - value[''].char == 'V': + if (value.names and value.names[-1] == '' and + value[''].char == 'V'): # A trailing padding field is already present vfields[''] = ('V%d' % (vfields[''][0].itemsize + padding), vfields[''][1]) @@ -566,5 +757,9 @@ def _prod(a): def _gcd(a, b): """Calculate the greatest common divisor of a and b""" while b: - a, b = b, a%b + a, b = b, a % b return a + +# Exception used in shares_memory() +class TooHardError(RuntimeError): + pass diff --git a/numpy/core/_methods.py b/numpy/core/_methods.py index 00716e1b4..5fc2bc445 100644 --- a/numpy/core/_methods.py +++ b/numpy/core/_methods.py @@ -58,7 +58,6 @@ def _mean(a, axis=None, dtype=None, out=None, keepdims=False): if rcount == 0: warnings.warn("Mean of empty slice.", RuntimeWarning) - # Cast bool, unsigned int, and int to float64 by default if dtype is None and issubclass(arr.dtype.type, (nt.integer, nt.bool_)): dtype = mu.dtype('f8') diff --git a/numpy/core/arrayprint.py b/numpy/core/arrayprint.py index 2dc56928c..a28b5a89e 100644 --- a/numpy/core/arrayprint.py +++ b/numpy/core/arrayprint.py @@ -19,7 +19,8 @@ import sys from functools import reduce from . import numerictypes as _nt from .umath import maximum, minimum, absolute, not_equal, isnan, isinf -from .multiarray import format_longfloat, datetime_as_string, datetime_data +from .multiarray import (array, format_longfloat, datetime_as_string, + datetime_data) from .fromnumeric import ravel from .numeric import asarray @@ -30,10 +31,11 @@ else: _MAXINT = sys.maxint _MININT = -sys.maxint - 1 -def product(x, y): return x*y +def product(x, y): + return x*y _summaryEdgeItems = 3 # repr N leading and trailing items of each dimension -_summaryThreshold = 1000 # total items > triggers array summarization +_summaryThreshold = 1000 # total items > triggers array summarization _float_output_precision = 8 _float_output_suppress_small = False @@ -148,9 +150,10 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None, ... suppress=False, threshold=1000, formatter=None) """ - global _summaryThreshold, _summaryEdgeItems, _float_output_precision, \ - _line_width, _float_output_suppress_small, _nan_str, _inf_str, \ - _formatter + global _summaryThreshold, _summaryEdgeItems, _float_output_precision + global _line_width, _float_output_suppress_small, _nan_str, _inf_str + global _formatter + if linewidth is not None: _line_width = linewidth if threshold is not None: @@ -253,17 +256,17 @@ def _array2string(a, max_line_width, precision, suppress_small, separator=' ', summary_insert = "" data = ravel(asarray(a)) - formatdict = {'bool' : _boolFormatter, - 'int' : IntegerFormat(data), - 'float' : FloatFormat(data, precision, suppress_small), - 'longfloat' : LongFloatFormat(precision), - 'complexfloat' : ComplexFormat(data, precision, + formatdict = {'bool': _boolFormatter, + 'int': IntegerFormat(data), + 'float': FloatFormat(data, precision, suppress_small), + 'longfloat': LongFloatFormat(precision), + 'complexfloat': ComplexFormat(data, precision, suppress_small), - 'longcomplexfloat' : LongComplexFormat(precision), - 'datetime' : DatetimeFormat(data), - 'timedelta' : TimedeltaFormat(data), - 'numpystr' : repr_format, - 'str' : str} + 'longcomplexfloat': LongComplexFormat(precision), + 'datetime': DatetimeFormat(data), + 'timedelta': TimedeltaFormat(data), + 'numpystr': repr_format, + 'str': str} if formatter is not None: fkeys = [k for k in formatter.keys() if formatter[k] is not None] @@ -286,38 +289,31 @@ def _array2string(a, max_line_width, precision, suppress_small, separator=' ', if key in fkeys: formatdict[key] = formatter[key] - try: - format_function = a._format - msg = "The `_format` attribute is deprecated in Numpy 2.0 and " \ - "will be removed in 2.1. Use the `formatter` kw instead." - import warnings - warnings.warn(msg, DeprecationWarning) - except AttributeError: - # find the right formatting function for the array - dtypeobj = a.dtype.type - if issubclass(dtypeobj, _nt.bool_): - format_function = formatdict['bool'] - elif issubclass(dtypeobj, _nt.integer): - if issubclass(dtypeobj, _nt.timedelta64): - format_function = formatdict['timedelta'] - else: - format_function = formatdict['int'] - elif issubclass(dtypeobj, _nt.floating): - if issubclass(dtypeobj, _nt.longfloat): - format_function = formatdict['longfloat'] - else: - format_function = formatdict['float'] - elif issubclass(dtypeobj, _nt.complexfloating): - if issubclass(dtypeobj, _nt.clongfloat): - format_function = formatdict['longcomplexfloat'] - else: - format_function = formatdict['complexfloat'] - elif issubclass(dtypeobj, (_nt.unicode_, _nt.string_)): - format_function = formatdict['numpystr'] - elif issubclass(dtypeobj, _nt.datetime64): - format_function = formatdict['datetime'] + # find the right formatting function for the array + dtypeobj = a.dtype.type + if issubclass(dtypeobj, _nt.bool_): + format_function = formatdict['bool'] + elif issubclass(dtypeobj, _nt.integer): + if issubclass(dtypeobj, _nt.timedelta64): + format_function = formatdict['timedelta'] + else: + format_function = formatdict['int'] + elif issubclass(dtypeobj, _nt.floating): + if issubclass(dtypeobj, _nt.longfloat): + format_function = formatdict['longfloat'] else: - format_function = formatdict['numpystr'] + format_function = formatdict['float'] + elif issubclass(dtypeobj, _nt.complexfloating): + if issubclass(dtypeobj, _nt.clongfloat): + format_function = formatdict['longcomplexfloat'] + else: + format_function = formatdict['complexfloat'] + elif issubclass(dtypeobj, (_nt.unicode_, _nt.string_)): + format_function = formatdict['numpystr'] + elif issubclass(dtypeobj, _nt.datetime64): + format_function = formatdict['datetime'] + else: + format_function = formatdict['numpystr'] # skip over "[" next_line_prefix = " " @@ -440,17 +436,9 @@ def array2string(a, max_line_width=None, precision=None, if a.shape == (): x = a.item() - try: - lst = a._format(x) - msg = "The `_format` attribute is deprecated in Numpy " \ - "2.0 and will be removed in 2.1. Use the " \ - "`formatter` kw instead." - import warnings - warnings.warn(msg, DeprecationWarning) - except AttributeError: - if isinstance(x, tuple): - x = _convert_arrays(x) - lst = style(x) + if isinstance(x, tuple): + x = _convert_arrays(x) + lst = style(x) elif reduce(product, a.shape) == 0: # treat as a null array if any of shape elements == 0 lst = "[]" @@ -483,10 +471,13 @@ def _formatArray(a, format_function, rank, max_line_len, return str(obj) if summary_insert and 2*edge_items < len(a): - leading_items, trailing_items, summary_insert1 = \ - edge_items, edge_items, summary_insert + leading_items = edge_items + trailing_items = edge_items + summary_insert1 = summary_insert else: - leading_items, trailing_items, summary_insert1 = 0, len(a), "" + leading_items = 0 + trailing_items = len(a) + summary_insert1 = "" if rank == 1: s = "" @@ -748,10 +739,22 @@ class DatetimeFormat(object): class TimedeltaFormat(object): def __init__(self, data): if data.dtype.kind == 'm': - v = data.view('i8') - max_str_len = max(len(str(maximum.reduce(v))), - len(str(minimum.reduce(v)))) + nat_value = array(['NaT'], dtype=data.dtype)[0] + v = data[not_equal(data, nat_value)].view('i8') + if len(v) > 0: + # Max str length of non-NaT elements + max_str_len = max(len(str(maximum.reduce(v))), + len(str(minimum.reduce(v)))) + else: + max_str_len = 0 + if len(v) < len(data): + # data contains a NaT + max_str_len = max(max_str_len, 5) self.format = '%' + str(max_str_len) + 'd' + self._nat = "'NaT'".rjust(max_str_len) def __call__(self, x): - return self.format % x.astype('i8') + if x + 1 == x: + return self._nat + else: + return self.format % x.astype('i8') diff --git a/numpy/core/bento.info b/numpy/core/bento.info deleted file mode 100644 index aaf261ddc..000000000 --- a/numpy/core/bento.info +++ /dev/null @@ -1,40 +0,0 @@ -HookFile: bscript - -Library: - CompiledLibrary: lib/npymath - Sources: - src/npymath/_signbit.c, - src/npymath/ieee754.c.src, - src/npymath/npy_math.c.src, - src/npymath/npy_math_complex.c.src, - src/npymath/halffloat.c - CompiledLibrary: npysort - Sources: - src/private/npy_partition.h.src, - src/private/npy_binsearch.h.src, - src/npysort/quicksort.c.src, - src/npysort/mergesort.c.src, - src/npysort/heapsort.c.src, - src/npysort/selection.c.src, - src/npysort/binsearch.c.src - Extension: multiarray - Sources: - src/multiarray/multiarraymodule_onefile.c - Extension: multiarray_tests - Sources: - src/multiarray/multiarray_tests.c.src - Extension: umath - Sources: - src/umath/umathmodule_onefile.c - Extension: umath_tests - Sources: - src/umath/umath_tests.c.src - Extension: test_rational - Sources: - src/umath/test_rational.c.src - Extension: struct_ufunc_test - Sources: - src/umath/struct_ufunc_test.c.src - Extension: operand_flag_tests - Sources: - src/umath/operand_flag_tests.c.src diff --git a/numpy/core/bscript b/numpy/core/bscript deleted file mode 100644 index 48d18b885..000000000 --- a/numpy/core/bscript +++ /dev/null @@ -1,545 +0,0 @@ -import os -import sys - -from bento.commands import hooks - -import waflib -import waflib.Errors -from waflib.Task \ - import \ - Task -waflib.Logs.verbose = 1 - -# Importing this adds new checkers to waf configure context - I don't like this -# way of working, should find a more explicit way to attach new functions to -# context. -import numpy.build_utils.waf - -from code_generators.numpy_api \ - import \ - multiarray_api, ufunc_api -from code_generators import generate_numpy_api, generate_ufunc_api, \ - generate_umath - -from setup_common \ - import \ - OPTIONAL_STDFUNCS_MAYBE, OPTIONAL_STDFUNCS, C99_FUNCS_EXTENDED, \ - C99_FUNCS_SINGLE, C99_COMPLEX_TYPES, C99_COMPLEX_FUNCS, \ - MANDATORY_FUNCS, C_ABI_VERSION, C_API_VERSION - -ENABLE_SEPARATE_COMPILATION = (os.environ.get('NPY_SEPARATE_COMPILATION', "1") != "0") -NPY_RELAXED_STRIDES_CHECKING = (os.environ.get('NPY_RELAXED_STRIDES_CHECKING', "1") != "0") - -NUMPYCONFIG_SYM = [] - -# FIXME -if ENABLE_SEPARATE_COMPILATION: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_ENABLE_SEPARATE_COMPILATION', '#define NPY_ENABLE_SEPARATE_COMPILATION 1')) -else: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_ENABLE_SEPARATE_COMPILATION', '')) - -if NPY_RELAXED_STRIDES_CHECKING: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_RELAXED_STRIDES_CHECKING', '#define NPY_RELAXED_STRIDES_CHECKING 1')) -else: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_RELAXED_STRIDES_CHECKING', '')) - -NUMPYCONFIG_SYM.append(('VISIBILITY_HIDDEN', '__attribute__((visibility("hidden")))')) - -NUMPYCONFIG_SYM.append(('NPY_ABI_VERSION', '0x%.8X' % C_ABI_VERSION)) -NUMPYCONFIG_SYM.append(('NPY_API_VERSION', '0x%.8X' % C_API_VERSION)) - -global PYTHON_HAS_UNICODE_WIDE - -def is_npy_no_signal(): - """Return True if the NPY_NO_SIGNAL symbol must be defined in configuration - header.""" - return sys.platform == 'win32' - -def define_no_smp(): - """Returns True if we should define NPY_NOSMP, False otherwise.""" - #-------------------------------- - # Checking SMP and thread options - #-------------------------------- - # Perhaps a fancier check is in order here. - # so that threads are only enabled if there - # are actually multiple CPUS? -- but - # threaded code can be nice even on a single - # CPU so that long-calculating code doesn't - # block. - return 'NPY_NOSMP' in os.environ - -def write_numpy_config(conf): - subst_dict = {} - for key, value in NUMPYCONFIG_SYM: - subst_dict["@%s@" % key] = str(value) - node = conf.path.find_node("include/numpy/_numpyconfig.h.in") - cnt = node.read() - for k, v in subst_dict.items(): - cnt = cnt.replace(k, v) - assert node is not None - onode = conf.bldnode.make_node(node.path_from(conf.srcnode)).change_ext("") - onode.write(cnt) - -def write_numpy_inifiles(conf): - subst_dict = dict([("@sep@", os.path.sep), ("@pkgname@", "numpy.core")]) - for inifile in ["mlib.ini.in", "npymath.ini.in"]: - node = conf.path.find_node(inifile) - cnt = node.read() - for k, v in subst_dict.items(): - cnt = cnt.replace(k, v) - assert node is not None - outfile = os.path.join("lib", "npy-pkg-config", inifile) - onode = conf.bldnode.make_node(node.path_from(conf.srcnode).replace( - inifile, outfile)).change_ext("") - onode.write(cnt) - -def type_checks(conf): - header_name = "Python.h" - features = "c pyext" - for c_type in ("int", "long", "short"): - macro_name = "SIZEOF_%s" % numpy.build_utils.waf.sanitize_string(c_type) - conf.check_declaration(macro_name, header_name=header_name, - features=features) - NUMPYCONFIG_SYM.append((macro_name, macro_name)) - - for c_type, e_size in (("float", 4), ("double", 8), ("long double", [12, 16])): - macro_name = "SIZEOF_%s" % numpy.build_utils.waf.sanitize_string(c_type) - size = conf.check_type_size(c_type, header_name=header_name, - features=features, expected_sizes=e_size) - NUMPYCONFIG_SYM.append((macro_name, str(size))) - - macro_name = "SIZEOF_COMPLEX_%s" % numpy.build_utils.waf.sanitize_string(c_type) - complex_def = "struct {%s __x; %s __y;}" % (c_type, c_type) - size = conf.check_type_size(complex_def, header_name=header_name, - features=features, expected_sizes=2*size) - NUMPYCONFIG_SYM.append((macro_name, str(size))) - - if sys.platform != 'darwin': - conf.check_ldouble_representation() - - size = conf.check_type_size("Py_intptr_t", header_name=header_name, - expected_sizes=[4, 8], features=features) - NUMPYCONFIG_SYM.append(('SIZEOF_%s' % numpy.build_utils.waf.sanitize_string("Py_intptr_t"), - '%d' % size)) - - size = conf.check_type_size("off_t", header_name=header_name, - expected_sizes=[4, 8], features=features) - NUMPYCONFIG_SYM.append(('SIZEOF_%s' % numpy.build_utils.waf.sanitize_string("off_t"), - '%d' % size)) - - # We check declaration AND type because that's how distutils does it. - try: - conf.check_declaration("PY_LONG_LONG", header_name=header_name, - features=features) - size = conf.check_type_size("PY_LONG_LONG", header_name=header_name, - features=features, expected_sizes=[4, 8]) - NUMPYCONFIG_SYM.append(("DEFINE_NPY_SIZEOF_LONGLONG", - "#define NPY_SIZEOF_LONGLONG %d" % size)) - NUMPYCONFIG_SYM.append(("DEFINE_NPY_SIZEOF_PY_LONG_LONG", - "#define NPY_SIZEOF_PY_LONG_LONG %d" % size)) - except waflib.Errors.ConfigurationError: - NUMPYCONFIG_SYM.append(("DEFINE_NPY_SIZEOF_LONGLONG", "")) - NUMPYCONFIG_SYM.append(("DEFINE_NPY_SIZEOF_PY_LONG_LONG", "")) - - conf.check_declaration("CHAR_BIT", header_name=header_name, features=features) - - # Check whether we need our own wide character support - global PYTHON_HAS_UNICODE_WIDE - try: - conf.check_declaration('Py_UNICODE_WIDE', header_name=header_name, features=features) - PYTHON_HAS_UNICODE_WIDE = False - except waflib.Errors.ConfigurationError: - PYTHON_HAS_UNICODE_WIDE = True - - try: - conf.check_declaration('PyOS_ascii_strtod', header_name=header_name, features=features) - except waflib.Errors.ConfigurationError: - try: - conf.check_func('strtod') - conf.define('PyOS_ascii_strtod', 'strtod') - except waflib.Errors.ConfigurationError: - pass - -def signal_smp_checks(conf): - if is_npy_no_signal(): - NUMPYCONFIG_SYM.append(("DEFINE_NPY_NO_SIGNAL", "#define NPY_NO_SIGNAL\n")) - conf.define("__NPY_PRIVATE_NO_SIGNAL", 1) - else: - NUMPYCONFIG_SYM.append(("DEFINE_NPY_NO_SIGNAL", "")) - - if define_no_smp(): - NUMPYCONFIG_SYM.append(("NPY_NO_SMP", 1)) - else: - NUMPYCONFIG_SYM.append(("NPY_NO_SMP", 0)) - -def check_math_runtime(conf): - header_name = "Python.h math.h" - features = "c cprogram pyext" - - mlibs = [None, "m", "cpml"] - mathlib = os.environ.get('MATHLIB') - if mathlib: - mlibs.insert(0, mathlib) - - mlib = None - for lib in mlibs: - try: - if lib is None: - kw = {} - else: - kw = {"lib": lib} - st = conf.check_functions_at_once(["exp"], uselib_store="M", **kw) - mlib = lib or [] - break - except waflib.Errors.ConfigurationError: - pass - if mlib is None: - raise waflib.Errors.ConfigurationError("No math lib found !") - - # XXX: this is ugly: mathlib has nothing to do in a public header file - NUMPYCONFIG_SYM.append(('MATHLIB', ','.join(mlib))) - - # FIXME: look more into those additional mandatory functions - MANDATORY_FUNCS.extend(["pow"]) - conf.check_functions_at_once(MANDATORY_FUNCS, use="M") - - #mfuncs = ('expl', 'expf', 'log1p', 'expm1', 'asinh', 'atanhf', 'atanhl', - # 'rint', 'trunc') - #conf.check_functions_at_once(mfuncs, use="M") - - header_name = "Python.h math.h" - # XXX: with MSVC compiler, one needs to have cprogram defined. Find out why. - features = "c pyext cprogram" - for f in OPTIONAL_STDFUNCS_MAYBE: - try: - conf.check_declaration("HAVE_%s" % numpy.build_utils.waf.sanitize_string(f), - header_name=header_name, - features=features) - OPTIONAL_STDFUNCS.remove(f) - except waflib.Errors.ConfigurationError: - pass - - conf.check_functions_at_once(OPTIONAL_STDFUNCS, - features=features, mandatory=False, use="M") - conf.check_functions_at_once(C99_FUNCS_SINGLE, - features=features, mandatory=False, use="M") - conf.check_functions_at_once(C99_FUNCS_EXTENDED, - features=features, mandatory=False, use="M") - # TODO: add OPTIONAL_HEADERS, OPTIONAL_INTRINSICS and - # OPTIONAL_GCC_ATTRIBUTES (see setup.py and gh-3766). These are - # performance optimizations for GCC. - - for f in ["isnan", "isinf", "signbit", "isfinite"]: - try: - conf.check_declaration("HAVE_DECL_%s" % f.upper(), header_name=header_name, - features=features) - NUMPYCONFIG_SYM.append(('DEFINE_NPY_HAVE_DECL_%s' % f.upper(), - '#define NPY_HAVE_DECL_%s' % f.upper())) - except waflib.Errors.ConfigurationError: - try: - conf.check_declaration(f, header_name=header_name, features=features) - NUMPYCONFIG_SYM.append(('DEFINE_NPY_HAVE_DECL_%s' % f.upper(), - '#define NPY_HAVE_DECL_%s' % f.upper())) - except waflib.Errors.ConfigurationError: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_HAVE_DECL_%s' % f.upper(), '')) - -def check_complex(conf): - if conf.check_header("complex.h", mandatory=False): - NUMPYCONFIG_SYM.append(('DEFINE_NPY_USE_C99_COMPLEX', - '#define NPY_USE_C99_COMPLEX 1')) - for t in C99_COMPLEX_TYPES: - try: - conf.check_type(t, header_name='complex.h') - NUMPYCONFIG_SYM.append(('DEFINE_NPY_HAVE_%s' % numpy.build_utils.waf.sanitize_string(t), - '#define NPY_HAVE_%s' % numpy.build_utils.waf.sanitize_string(t))) - except waflib.Errors.ConfigurationError: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_HAVE_%s' % numpy.build_utils.waf.sanitize_string(t), '')) - - for prec in ["", "f", "l"]: - flist = [f + prec for f in C99_COMPLEX_FUNCS] - conf.check_functions_at_once(flist, use="M") - else: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_USE_C99_COMPLEX', '')) - for t in C99_COMPLEX_TYPES: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_HAVE_%s' % numpy.build_utils.waf.sanitize_string(t), '')) - -def check_win32_specifics(conf): - from numpy.distutils.misc_util import get_build_architecture - arch = get_build_architecture() - - # On win32, force long double format string to be 'g', not - # 'Lg', since the MS runtime does not support long double whose - # size is > sizeof(double) - if arch == "Intel" or arch == "AMD64": - conf.define('FORCE_NO_LONG_DOUBLE_FORMATTING', 1) - -@hooks.post_configure -def post_configure(context): - conf = context.waf_context - - try: - conf.check_header("endian.h") - NUMPYCONFIG_SYM.append(('DEFINE_NPY_HAVE_ENDIAN_H', - '#define NPY_HAVE_ENDIAN_H 1')) - except waflib.Errors.ConfigurationError: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_HAVE_ENDIAN_H', '')) - - try: - conf.check_declaration('PRIdPTR', header_name='inttypes.h') - NUMPYCONFIG_SYM.append(('DEFINE_NPY_USE_C99_FORMATS', '#define NPY_USE_C99_FORMATS 1')) - except waflib.Errors.ConfigurationError: - NUMPYCONFIG_SYM.append(('DEFINE_NPY_USE_C99_FORMATS', '')) - - type_checks(conf) - signal_smp_checks(conf) - check_math_runtime(conf) - numpy.build_utils.waf.check_inline(conf) - check_complex(conf) - check_win32_specifics(conf) - - if ENABLE_SEPARATE_COMPILATION: - conf.define("ENABLE_SEPARATE_COMPILATION", 1) - - conf.env["CONFIG_HEADER_TEMPLATE"] = """\ -%(content)s -#ifndef _NPY_NPY_CONFIG_H_ -#error config.h should never be included directly, include npy_config.h instead -#endif""" - conf.write_config_header("config.h") - - write_numpy_config(conf) - - write_numpy_inifiles(conf) - - conf.env.INCLUDES = [".", "include", "include/numpy"] - - # FIXME: Should be handled in bento context - conf.store() - -class numpy_api_generator(Task): - vars = ["API_TUPLE"] - color = "BLUE" - before = ["c"] - def run(self): - targets = [o.path_from(self.generator.bld.srcnode) for o in self.outputs] - generate_numpy_api.do_generate_api(targets, self.env.API_TUPLE) - return 0 - -class ufunc_api_generator(Task): - vars = ["API_TUPLE"] - color = "BLUE" - before = ["c"] - def run(self): - targets = [o.path_from(self.generator.bld.srcnode) for o in self.outputs] - generate_ufunc_api.do_generate_api(targets, self.env.API_TUPLE) - return 0 - -@waflib.TaskGen.feature("numpy_api_gen") -def process_multiarray_api_generator(self): - tsk = self.create_task("numpy_api_generator") - if hasattr(self, "api_tuple"): - tsk.env.API_TUPLE = self.api_tuple - else: - if not "API_TUPLE" in tsk.env: - tsk.env.API_TUPLE = () - header = "__%s.h" % self.pattern - source = "__%s.c" % self.pattern - txt = self.pattern + ".txt" - files = [header, source, txt] - tsk.set_outputs([self.path.find_or_declare(f) for f in files]) - - self.bld.register_outputs("numpy_gen_headers", "multiarray", - [output for output in tsk.outputs if output.suffix() == ".h"], - target_dir="$sitedir/numpy/core/include/numpy") - - return tsk - -@waflib.TaskGen.feature("ufunc_api_gen") -def process_api_ufunc_generator(self): - tsk = self.create_task("ufunc_api_generator") - if hasattr(self, "api_tuple"): - tsk.env.API_TUPLE = self.api_tuple - else: - if not "API_TUPLE" in tsk.env: - tsk.env.API_TUPLE = () - header = "__%s.h" % self.pattern - source = "__%s.c" % self.pattern - txt = self.pattern + ".txt" - files = [header, source, txt] - tsk.set_outputs([self.path.find_or_declare(f) for f in files]) - - headers = [output for output in tsk.outputs if output.suffix() == ".h"] - self.bld.register_outputs("numpy_gen_headers", "ufunc", headers, - target_dir="$sitedir/numpy/core/include/numpy") - return tsk - -class umath_generator(Task): - vars = ["API_TUPLE"] - color = "BLUE" - before = ["c"] - ext_in = ".in" - def run(self): - if len(self.outputs) > 1: - raise ValueError("Only one target (the .c file) is expected in the umath generator task") - code = generate_umath.make_code(generate_umath.defdict, generate_umath.__file__) - self.outputs[0].write(code) - return 0 - -@waflib.TaskGen.feature("umath_gen") -def process_umath_generator(self): - tsk = self.create_task("umath_generator") - source = "__%s.c" % self.pattern - tsk.set_outputs(self.path.find_or_declare(source)) - return tsk - -from os.path import join as pjoin -@hooks.pre_build -def pre_build(context): - bld = context.waf_context - - context.register_category("numpy_gen_inifiles") - inifile_mlib = context.local_node.declare(os.path.join( - "lib", "npy-pkg-config", "mlib.ini")) - inifile_npymath = context.local_node.declare(os.path.join( - "lib", "npy-pkg-config", "npymath.ini")) - context.register_outputs("numpy_gen_inifiles", "numpyconfig", - [inifile_mlib, inifile_npymath]) - - context.register_category("numpy_gen_headers") - - numpyconfig_h = context.local_node.declare(os.path.join("include", "numpy", "_numpyconfig.h")) - context.register_outputs("numpy_gen_headers", "numpyconfig", [numpyconfig_h]) - - context.tweak_library("lib/npymath", includes=["src/private", "src/npymath", "include"]) - - context.tweak_library("npysort", - includes=[".", "src/private", "src/npysort"], - use="npymath") - - def builder_multiarray(extension): - bld(name="multiarray_api", - features="numpy_api_gen", - api_tuple=multiarray_api, - pattern="multiarray_api") - - multiarray_templates = ["src/multiarray/scalartypes.c.src", - "src/multiarray/arraytypes.c.src", - "src/multiarray/nditer_templ.c.src", - "src/multiarray/lowlevel_strided_loops.c.src", - "src/private/templ_common.h.src", - "src/multiarray/einsum.c.src"] - bld(target="multiarray_templates", source=multiarray_templates) - if ENABLE_SEPARATE_COMPILATION: - sources = [ - pjoin('src', 'multiarray', 'arrayobject.c'), - pjoin('src', 'multiarray', 'alloc.c'), - pjoin('src', 'multiarray', 'arraytypes.c.src'), - pjoin('src', 'multiarray', 'array_assign.c'), - pjoin('src', 'multiarray', 'array_assign_array.c'), - pjoin('src', 'multiarray', 'array_assign_scalar.c'), - pjoin('src', 'multiarray', 'buffer.c'), - pjoin('src', 'multiarray', 'calculation.c'), - pjoin('src', 'multiarray', 'common.c'), - pjoin('src', 'multiarray', 'compiled_base.c'), - pjoin('src', 'multiarray', 'conversion_utils.c'), - pjoin('src', 'multiarray', 'convert.c'), - pjoin('src', 'multiarray', 'convert_datatype.c'), - pjoin('src', 'multiarray', 'ctors.c'), - pjoin('src', 'multiarray', 'datetime.c'), - pjoin('src', 'multiarray', 'datetime_busday.c'), - pjoin('src', 'multiarray', 'datetime_busdaycal.c'), - pjoin('src', 'multiarray', 'datetime_strings.c'), - pjoin('src', 'multiarray', 'descriptor.c'), - pjoin('src', 'multiarray', 'dtype_transfer.c'), - pjoin('src', 'multiarray', 'einsum.c.src'), - pjoin('src', 'multiarray', 'flagsobject.c'), - pjoin('src', 'multiarray', 'getset.c'), - pjoin('src', 'multiarray', 'hashdescr.c'), - pjoin('src', 'multiarray', 'item_selection.c'), - pjoin('src', 'multiarray', 'iterators.c'), - pjoin('src', 'multiarray', 'lowlevel_strided_loops.c.src'), - pjoin('src', 'multiarray', 'mapping.c'), - pjoin('src', 'multiarray', 'methods.c'), - pjoin('src', 'multiarray', 'multiarraymodule.c'), - pjoin('src', 'multiarray', 'nditer_templ.c.src'), - pjoin('src', 'multiarray', 'nditer_api.c'), - pjoin('src', 'multiarray', 'nditer_constr.c'), - pjoin('src', 'multiarray', 'nditer_pywrap.c'), - pjoin('src', 'multiarray', 'number.c'), - pjoin('src', 'multiarray', 'numpymemoryview.c'), - pjoin('src', 'multiarray', 'numpyos.c'), - pjoin('src', 'multiarray', 'refcount.c'), - pjoin('src', 'multiarray', 'scalarapi.c'), - pjoin('src', 'multiarray', 'scalartypes.c.src'), - pjoin('src', 'multiarray', 'sequence.c'), - pjoin('src', 'multiarray', 'shape.c'), - pjoin('src', 'multiarray', 'ucsnarrow.c'), - pjoin('src', 'multiarray', 'usertypes.c'), - pjoin('src', 'multiarray', 'vdot.c'), - pjoin('src', 'private', 'templ_common.h.src'), - ] - - if bld.env.HAS_CBLAS: - sources.extend([pjoin('src', 'multiarray', 'cblasfuncs.c'), - pjoin('src', 'multiarray', 'python_xerbla.c'), - ]) - else: - sources = extension.sources - - use = 'npysort npymath' - defines = ['_FILE_OFFSET_BITS=64', - '_LARGEFILE_SOURCE=1', - '_LARGEFILE64_SOURCE=1'] - - if bld.env.HAS_CBLAS: - use += ' CBLAS' - defines.append('HAVE_CBLAS') - - includes = ["src/multiarray", "src/private"] - return context.default_builder(extension, - includes=includes, - source=sources, - use=use, - defines=defines - ) - context.register_builder("multiarray", builder_multiarray) - - def build_ufunc(extension): - bld(features="ufunc_api_gen", - api_tuple=ufunc_api, - pattern="ufunc_api", - name="ufunc_api") - - ufunc_templates = [ - "src/umath/scalarmath.c.src", - "src/umath/loops.h.src", - "src/umath/loops.c.src", - "src/umath/funcs.inc.src", - "src/umath/simd.inc.src"] - bld(target="ufunc_templates", source=ufunc_templates) - - bld(features="umath_gen", - pattern="umath_generated", - name="umath_gen") - - includes = ["src/umath", "src/multiarray", "src/private"] - if ENABLE_SEPARATE_COMPILATION: - sources = [ - pjoin("src", "umath", "scalarmath.c.src"), - pjoin("src", "umath", "loops.h.src"), - pjoin("src", "umath", "loops.c.src"), - pjoin('src', 'umath', 'reduction.c'), - pjoin('src', 'umath', 'ufunc_object.c'), - pjoin('src', 'umath', 'ufunc_type_resolution.c'), - pjoin("src", "umath", "umathmodule.c"), - ] - else: - sources = extension.sources - return context.default_builder(extension, - includes=includes, - source=sources, - use="npymath") - context.register_builder("umath", build_ufunc) - - context.tweak_extension("multiarray_tests", use="npymath", includes=["src/private"]) - context.tweak_extension("umath_tests", use="npymath", includes=["src/private"]) diff --git a/numpy/core/code_generators/cversions.txt b/numpy/core/code_generators/cversions.txt index acfced812..dea6d0ecf 100644 --- a/numpy/core/code_generators/cversions.txt +++ b/numpy/core/code_generators/cversions.txt @@ -29,3 +29,6 @@ # The interface has not changed, but the hash is different due to # the annotations, so keep the previous version number. 0x00000009 = 982c4ebb6e7e4c194bf46b1535b4ef1b + +# Version 10 (NumPy 1.10) Added PyArray_CheckAnyScalarExact +0x0000000a = 9b8bce614655d3eb02acddcb508203cb diff --git a/numpy/core/code_generators/generate_ufunc_api.py b/numpy/core/code_generators/generate_ufunc_api.py index b594fccf7..7a33004e4 100644 --- a/numpy/core/code_generators/generate_ufunc_api.py +++ b/numpy/core/code_generators/generate_ufunc_api.py @@ -37,7 +37,7 @@ static void **PyUFunc_API=NULL; %s -static int +static NPY_INLINE int _import_umath(void) { PyObject *numpy = PyImport_ImportModule("numpy.core.umath"); diff --git a/numpy/core/defchararray.py b/numpy/core/defchararray.py index cc6cb5a38..e18f912d6 100644 --- a/numpy/core/defchararray.py +++ b/numpy/core/defchararray.py @@ -25,17 +25,18 @@ from numpy.core.multiarray import _vec_string from numpy.compat import asbytes, long import numpy -__all__ = ['chararray', - 'equal', 'not_equal', 'greater_equal', 'less_equal', 'greater', 'less', - 'str_len', 'add', 'multiply', 'mod', 'capitalize', 'center', 'count', - 'decode', 'encode', 'endswith', 'expandtabs', 'find', 'format', - 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', - 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', - 'partition', 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', - 'rsplit', 'rstrip', 'split', 'splitlines', 'startswith', 'strip', - 'swapcase', 'title', 'translate', 'upper', 'zfill', - 'isnumeric', 'isdecimal', - 'array', 'asarray'] +__all__ = [ + 'chararray', 'equal', 'not_equal', 'greater_equal', 'less_equal', + 'greater', 'less', 'str_len', 'add', 'multiply', 'mod', 'capitalize', + 'center', 'count', 'decode', 'encode', 'endswith', 'expandtabs', + 'find', 'index', 'isalnum', 'isalpha', 'isdigit', 'islower', 'isspace', + 'istitle', 'isupper', 'join', 'ljust', 'lower', 'lstrip', 'partition', + 'replace', 'rfind', 'rindex', 'rjust', 'rpartition', 'rsplit', + 'rstrip', 'split', 'splitlines', 'startswith', 'strip', 'swapcase', + 'title', 'translate', 'upper', 'zfill', 'isnumeric', 'isdecimal', + 'array', 'asarray' + ] + _globalvar = 0 if sys.version_info[0] >= 3: @@ -55,8 +56,8 @@ def _use_unicode(*args): result should be unicode. """ for x in args: - if (isinstance(x, _unicode) - or issubclass(numpy.asarray(x).dtype.type, unicode_)): + if (isinstance(x, _unicode) or + issubclass(numpy.asarray(x).dtype.type, unicode_)): return unicode_ return string_ @@ -1068,7 +1069,7 @@ def replace(a, old, new, count=None): """ return _to_string_or_unicode_array( _vec_string( - a, object_, 'replace', [old, new] +_clean_args(count))) + a, object_, 'replace', [old, new] + _clean_args(count))) def rfind(a, sub, start=0, end=None): @@ -1849,12 +1850,14 @@ class chararray(ndarray): def __getitem__(self, obj): val = ndarray.__getitem__(self, obj) - if issubclass(val.dtype.type, character) and not _len(val) == 0: + + if isinstance(val, character): temp = val.rstrip() if _len(temp) == 0: val = '' else: val = temp + return val # IMPLEMENTATION NOTE: Most of the methods of this class are @@ -2037,7 +2040,6 @@ class chararray(ndarray): """ return count(self, sub, start, end) - def decode(self, encoding=None, errors=None): """ Calls `str.decode` element-wise. @@ -2608,10 +2610,10 @@ def array(obj, itemsize=None, copy=True, unicode=None, order=None): if order is not None: obj = numpy.asarray(obj, order=order) - if (copy - or (itemsize != obj.itemsize) - or (not unicode and isinstance(obj, unicode_)) - or (unicode and isinstance(obj, string_))): + if (copy or + (itemsize != obj.itemsize) or + (not unicode and isinstance(obj, unicode_)) or + (unicode and isinstance(obj, string_))): obj = obj.astype((dtype, long(itemsize))) return obj @@ -2650,7 +2652,7 @@ def asarray(obj, itemsize=None, unicode=None, order=None): end when comparing values 3) vectorized string operations are provided as methods - (e.g. `str.endswith`) and infix operators (e.g. +, *, %) + (e.g. `str.endswith`) and infix operators (e.g. ``+``, ``*``,``%``) Parameters ---------- diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py index 549647df2..10f4a98c5 100644 --- a/numpy/core/fromnumeric.py +++ b/numpy/core/fromnumeric.py @@ -579,10 +579,12 @@ def partition(a, kth, axis=-1, kind='introselect', order=None): sorting. The default is -1, which sorts along the last axis. kind : {'introselect'}, optional Selection algorithm. Default is 'introselect'. - order : list, optional - When `a` is a structured array, this argument specifies which fields - to compare first, second, and so on. This list does not need to - include all of the fields. + order : str or list of str, optional + When `a` is an array with fields defined, this argument specifies + which fields to compare first, second, etc. A single field can + be specified as a string. Not all fields need be specified, but + unspecified fields will still be used, in the order in which they + come up in the dtype, to break ties. Returns ------- @@ -662,10 +664,12 @@ def argpartition(a, kth, axis=-1, kind='introselect', order=None): the flattened array is used. kind : {'introselect'}, optional Selection algorithm. Default is 'introselect' - order : list, optional + order : str or list of str, optional When `a` is an array with fields defined, this argument specifies - which fields to compare first, second, etc. Not all fields need be - specified. + which fields to compare first, second, etc. A single field can + be specified as a string, and not all fields need be specified, + but unspecified fields will still be used, in the order in which + they come up in the dtype, to break ties. Returns ------- @@ -718,10 +722,12 @@ def sort(a, axis=-1, kind='quicksort', order=None): sorting. The default is -1, which sorts along the last axis. kind : {'quicksort', 'mergesort', 'heapsort'}, optional Sorting algorithm. Default is 'quicksort'. - order : list, optional - When `a` is a structured array, this argument specifies which fields - to compare first, second, and so on. This list does not need to - include all of the fields. + order : str or list of str, optional + When `a` is an array with fields defined, this argument specifies + which fields to compare first, second, etc. A single field can + be specified as a string, and not all fields need be specified, + but unspecified fields will still be used, in the order in which + they come up in the dtype, to break ties. Returns ------- @@ -831,10 +837,12 @@ def argsort(a, axis=-1, kind='quicksort', order=None): the flattened array is used. kind : {'quicksort', 'mergesort', 'heapsort'}, optional Sorting algorithm. - order : list, optional + order : str or list of str, optional When `a` is an array with fields defined, this argument specifies - which fields to compare first, second, etc. Not all fields need be - specified. + which fields to compare first, second, etc. A single field can + be specified as a string, and not all fields need be specified, + but unspecified fields will still be used, in the order in which + they come up in the dtype, to break ties. Returns ------- @@ -1041,10 +1049,11 @@ def searchsorted(a, v, side='left', sorter=None): If 'right', return the last such index. If there is no suitable index, return either 0 or N (where N is the length of `a`). sorter : 1-D array_like, optional - .. versionadded:: 1.7.0 Optional array of integer indices that sort array a into ascending order. They are typically the result of argsort. + .. versionadded:: 1.7.0 + Returns ------- indices : array of ints @@ -1362,8 +1371,7 @@ def trace(a, offset=0, axis1=0, axis2=1, dtype=None, out=None): def ravel(a, order='C'): - """ - Return a flattened array. + """Return a contiguous flattened array. A 1-D array, containing the elements of the input, is returned. A copy is made only if needed. @@ -1378,18 +1386,21 @@ def ravel(a, order='C'): Input array. The elements in `a` are read in the order specified by `order`, and packed as a 1-D array. order : {'C','F', 'A', 'K'}, optional - The elements of `a` are read using this index order. 'C' means to - index the elements in C-like order, with the last axis index changing - fastest, back to the first axis index changing slowest. 'F' means to - index the elements in Fortran-like index order, with the first index - changing fastest, and the last index changing slowest. Note that the - 'C' and 'F' options take no account of the memory layout of the - underlying array, and only refer to the order of axis indexing. - 'A' means to read the elements in Fortran-like index order if `a` is - Fortran *contiguous* in memory, C-like order otherwise. 'K' means to - read the elements in the order they occur in memory, except for - reversing the data when strides are negative. By default, 'C' index - order is used. + + The elements of `a` are read using this index order. 'C' means + to index the elements in row-major, C-style order, + with the last axis index changing fastest, back to the first + axis index changing slowest. 'F' means to index the elements + in column-major, Fortran-style order, with the + first index changing fastest, and the last index changing + slowest. Note that the 'C' and 'F' options take no account of + the memory layout of the underlying array, and only refer to + the order of axis indexing. 'A' means to read the elements in + Fortran-like index order if `a` is Fortran *contiguous* in + memory, C-like order otherwise. 'K' means to read the + elements in the order they occur in memory, except for + reversing the data when strides are negative. By default, 'C' + index order is used. Returns ------- @@ -1404,14 +1415,19 @@ def ravel(a, order='C'): ndarray.flat : 1-D iterator over an array. ndarray.flatten : 1-D array copy of the elements of an array in row-major order. + ndarray.reshape : Change the shape of an array without changing its data. Notes ----- - In C-like (row-major) order, in two dimensions, the row index varies the - slowest, and the column index the quickest. This can be generalized to - multiple dimensions, where row-major order implies that the index along the - first axis varies slowest, and the index along the last quickest. The - opposite holds for Fortran-like, or column-major, index ordering. + In row-major, C-style order, in two dimensions, the row index + varies the slowest, and the column index the quickest. This can + be generalized to multiple dimensions, where row-major order + implies that the index along the first axis varies slowest, and + the index along the last quickest. The opposite holds for + column-major, Fortran-style index ordering. + + When a view is desired in as many cases as possible, ``arr.reshape(-1)`` + may be preferable. Examples -------- @@ -1465,9 +1481,11 @@ def nonzero(a): """ Return the indices of the elements that are non-zero. - Returns a tuple of arrays, one for each dimension of `a`, containing - the indices of the non-zero elements in that dimension. The - corresponding non-zero values can be obtained with:: + Returns a tuple of arrays, one for each dimension of `a`, + containing the indices of the non-zero elements in that + dimension. The values in `a` are always tested and returned in + row-major, C-style order. The corresponding non-zero + values can be obtained with:: a[nonzero(a)] @@ -1770,6 +1788,11 @@ def sum(a, axis=None, dtype=None, out=None, keepdims=False): Arithmetic is modular when using integer types, and no error is raised on overflow. + The sum of an empty array is the neutral element 0: + + >>> np.sum([]) + 0.0 + Examples -------- >>> np.sum([0.5, 1.5]) @@ -2413,6 +2436,11 @@ def prod(a, axis=None, dtype=None, out=None, keepdims=False): >>> np.prod(x) #random 16 + The product of an empty array is the neutral element 1: + + >>> np.prod([]) + 1.0 + Examples -------- By default, calculate the product of all elements: @@ -2606,6 +2634,7 @@ def rank(a): 0 """ + # 2014-04-12, 1.9 warnings.warn( "`rank` is deprecated; use the `ndim` attribute or function instead. " "To find the rank of a matrix see `numpy.linalg.matrix_rank`.", @@ -2929,16 +2958,16 @@ def std(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False): In single precision, std() can be inaccurate: - >>> a = np.zeros((2,512*512), dtype=np.float32) - >>> a[0,:] = 1.0 - >>> a[1,:] = 0.1 + >>> a = np.zeros((2, 512*512), dtype=np.float32) + >>> a[0, :] = 1.0 + >>> a[1, :] = 0.1 >>> np.std(a) - 0.45172946707416706 + 0.45000005 Computing the standard deviation in float64 is more accurate: >>> np.std(a, dtype=np.float64) - 0.44999999925552653 + 0.44999999925494177 """ if type(a) is not mu.ndarray: @@ -3025,7 +3054,7 @@ def var(a, axis=None, dtype=None, out=None, ddof=0, Examples -------- - >>> a = np.array([[1,2],[3,4]]) + >>> a = np.array([[1, 2], [3, 4]]) >>> np.var(a) 1.25 >>> np.var(a, axis=0) @@ -3035,18 +3064,18 @@ def var(a, axis=None, dtype=None, out=None, ddof=0, In single precision, var() can be inaccurate: - >>> a = np.zeros((2,512*512), dtype=np.float32) - >>> a[0,:] = 1.0 - >>> a[1,:] = 0.1 + >>> a = np.zeros((2, 512*512), dtype=np.float32) + >>> a[0, :] = 1.0 + >>> a[1, :] = 0.1 >>> np.var(a) - 0.20405951142311096 + 0.20250003 Computing the variance in float64 is more accurate: >>> np.var(a, dtype=np.float64) - 0.20249999932997387 + 0.20249999932944759 >>> ((1-0.55)**2 + (0.1-0.55)**2)/2 - 0.20250000000000001 + 0.2025 """ if type(a) is not mu.ndarray: diff --git a/numpy/core/function_base.py b/numpy/core/function_base.py index 1e759e0c2..05fea557a 100644 --- a/numpy/core/function_base.py +++ b/numpy/core/function_base.py @@ -1,9 +1,9 @@ from __future__ import division, absolute_import, print_function -__all__ = ['logspace', 'linspace'] +__all__ = ['logspace', 'linspace', 'may_share_memory'] from . import numeric as _nx -from .numeric import array, result_type, NaN +from .numeric import result_type, NaN, shares_memory, MAY_SHARE_BOUNDS, TooHardError def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None): @@ -25,7 +25,7 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None): evenly spaced samples, so that `stop` is excluded. Note that the step size changes when `endpoint` is False. num : int, optional - Number of samples to generate. Default is 50. + Number of samples to generate. Default is 50. Must be non-negative. endpoint : bool, optional If True, `stop` is the last sample. Otherwise, it is not included. Default is True. @@ -82,6 +82,8 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None): """ num = int(num) + if num < 0: + raise ValueError("Number of samples, %s, must be non-negative." % num) div = (num - 1) if endpoint else num # Convert float/complex array scalars to float, gh-3504 @@ -199,3 +201,46 @@ def logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None): if dtype is None: return _nx.power(base, y) return _nx.power(base, y).astype(dtype) + + +def may_share_memory(a, b, max_work=None): + """Determine if two arrays can share memory + + A return of True does not necessarily mean that the two arrays + share any element. It just means that they *might*. + + Only the memory bounds of a and b are checked by default. + + Parameters + ---------- + a, b : ndarray + Input arrays + max_work : int, optional + Effort to spend on solving the overlap problem. See + `shares_memory` for details. Default for ``may_share_memory`` + is to do a bounds check. + + Returns + ------- + out : bool + + See Also + -------- + shares_memory + + Examples + -------- + >>> np.may_share_memory(np.array([1,2]), np.array([5,8,9])) + False + >>> x = np.zeros([3, 4]) + >>> np.may_share_memory(x[:,0], x[:,1]) + True + + """ + if max_work is None: + max_work = MAY_SHARE_BOUNDS + try: + return shares_memory(a, b, max_work=max_work) + except (TooHardError, OverflowError): + # Unable to determine, assume yes + return True diff --git a/numpy/core/getlimits.py b/numpy/core/getlimits.py index bd1c4571b..2ea9c0e11 100644 --- a/numpy/core/getlimits.py +++ b/numpy/core/getlimits.py @@ -12,7 +12,8 @@ from .numeric import array def _frz(a): """fix rank-0 --> rank-1""" - if a.ndim == 0: a.shape = (1,) + if a.ndim == 0: + a.shape = (1,) return a _convert_to_float = { @@ -170,25 +171,25 @@ class finfo(object): return self def __str__(self): - return '''\ -Machine parameters for %(dtype)s ---------------------------------------------------------------------- -precision=%(precision)3s resolution= %(_str_resolution)s -machep=%(machep)6s eps= %(_str_eps)s -negep =%(negep)6s epsneg= %(_str_epsneg)s -minexp=%(minexp)6s tiny= %(_str_tiny)s -maxexp=%(maxexp)6s max= %(_str_max)s -nexp =%(nexp)6s min= -max ---------------------------------------------------------------------- -''' % self.__dict__ + fmt = ( + 'Machine parameters for %(dtype)s\n' + '---------------------------------------------------------------\n' + 'precision=%(precision)3s resolution= %(_str_resolution)s\n' + 'machep=%(machep)6s eps= %(_str_eps)s\n' + 'negep =%(negep)6s epsneg= %(_str_epsneg)s\n' + 'minexp=%(minexp)6s tiny= %(_str_tiny)s\n' + 'maxexp=%(maxexp)6s max= %(_str_max)s\n' + 'nexp =%(nexp)6s min= -max\n' + '---------------------------------------------------------------\n' + ) + return fmt % self.__dict__ def __repr__(self): c = self.__class__.__name__ d = self.__dict__.copy() d['klass'] = c - return ("%(klass)s(resolution=%(resolution)s, min=-%(_str_max)s," \ - + " max=%(_str_max)s, dtype=%(dtype)s)") \ - % d + return (("%(klass)s(resolution=%(resolution)s, min=-%(_str_max)s," + " max=%(_str_max)s, dtype=%(dtype)s)") % d) class iinfo(object): @@ -249,7 +250,7 @@ class iinfo(object): self.kind = self.dtype.kind self.bits = self.dtype.itemsize * 8 self.key = "%s%d" % (self.kind, self.bits) - if not self.kind in 'iu': + if self.kind not in 'iu': raise ValueError("Invalid integer data type.") def min(self): @@ -282,13 +283,14 @@ class iinfo(object): def __str__(self): """String representation.""" - return '''\ -Machine parameters for %(dtype)s ---------------------------------------------------------------------- -min = %(min)s -max = %(max)s ---------------------------------------------------------------------- -''' % {'dtype': self.dtype, 'min': self.min, 'max': self.max} + fmt = ( + 'Machine parameters for %(dtype)s\n' + '---------------------------------------------------------------\n' + 'min = %(min)s\n' + 'max = %(max)s\n' + '---------------------------------------------------------------\n' + ) + return fmt % {'dtype': self.dtype, 'min': self.min, 'max': self.max} def __repr__(self): return "%s(min=%s, max=%s, dtype=%s)" % (self.__class__.__name__, diff --git a/numpy/core/include/numpy/ndarraytypes.h b/numpy/core/include/numpy/ndarraytypes.h index edae27c72..8403ee29f 100644 --- a/numpy/core/include/numpy/ndarraytypes.h +++ b/numpy/core/include/numpy/ndarraytypes.h @@ -156,7 +156,7 @@ typedef enum { typedef enum { - NPY_INTROSELECT=0, + NPY_INTROSELECT=0 } NPY_SELECTKIND; #define NPY_NSELECTS (NPY_INTROSELECT + 1) @@ -202,7 +202,7 @@ typedef enum { /* Allow safe casts or casts within the same kind */ NPY_SAME_KIND_CASTING=3, /* Allow any casts */ - NPY_UNSAFE_CASTING=4, + NPY_UNSAFE_CASTING=4 } NPY_CASTING; typedef enum { @@ -1099,27 +1099,6 @@ struct PyArrayIterObject_tag { } \ } while (0) -#define _PyArray_ITER_NEXT3(it) do { \ - if ((it)->coordinates[2] < (it)->dims_m1[2]) { \ - (it)->coordinates[2]++; \ - (it)->dataptr += (it)->strides[2]; \ - } \ - else { \ - (it)->coordinates[2] = 0; \ - (it)->dataptr -= (it)->backstrides[2]; \ - if ((it)->coordinates[1] < (it)->dims_m1[1]) { \ - (it)->coordinates[1]++; \ - (it)->dataptr += (it)->strides[1]; \ - } \ - else { \ - (it)->coordinates[1] = 0; \ - (it)->coordinates[0]++; \ - (it)->dataptr += (it)->strides[0] \ - (it)->backstrides[1]; \ - } \ - } \ -} while (0) - #define PyArray_ITER_NEXT(it) do { \ _PyAIT(it)->index++; \ if (_PyAIT(it)->nd_m1 == 0) { \ diff --git a/numpy/core/include/numpy/npy_3kcompat.h b/numpy/core/include/numpy/npy_3kcompat.h index ef5b5694c..72ddaf66b 100644 --- a/numpy/core/include/numpy/npy_3kcompat.h +++ b/numpy/core/include/numpy/npy_3kcompat.h @@ -272,35 +272,8 @@ npy_PyFile_Check(PyObject *file) return 1; } -/* - * DEPRECATED DO NOT USE - * use npy_PyFile_DupClose2 instead - * this function will mess ups python3 internal file object buffering - * Close the dup-ed file handle, and seek the Python one to the current position - */ -static NPY_INLINE int -npy_PyFile_DupClose(PyObject *file, FILE* handle) -{ - PyObject *ret; - Py_ssize_t position; - position = npy_ftell(handle); - fclose(handle); - - ret = PyObject_CallMethod(file, "seek", NPY_SSIZE_T_PYFMT "i", position, 0); - if (ret == NULL) { - return -1; - } - Py_DECREF(ret); - return 0; -} - - #else -/* DEPRECATED, DO NOT USE */ -#define npy_PyFile_DupClose(f, h) npy_PyFile_DupClose2((f), (h), 0) - -/* use these */ static NPY_INLINE FILE * npy_PyFile_Dup2(PyObject *file, const char *NPY_UNUSED(mode), npy_off_t *NPY_UNUSED(orig_pos)) @@ -319,24 +292,6 @@ npy_PyFile_DupClose2(PyObject *NPY_UNUSED(file), FILE* NPY_UNUSED(handle), #endif -/* - * DEPRECATED, DO NOT USE - * Use npy_PyFile_Dup2 instead. - * This function will mess up python3 internal file object buffering. - * Get a FILE* handle to the file represented by the Python object. - */ -static NPY_INLINE FILE* -npy_PyFile_Dup(PyObject *file, char *mode) -{ - npy_off_t orig; - if (DEPRECATE("npy_PyFile_Dup is deprecated, use " - "npy_PyFile_Dup2") < 0) { - return NULL; - } - - return npy_PyFile_Dup2(file, mode, &orig); -} - static NPY_INLINE PyObject* npy_PyFile_OpenFile(PyObject *filename, const char *mode) { diff --git a/numpy/core/include/numpy/npy_math.h b/numpy/core/include/numpy/npy_math.h index 8f5d8e6c7..3dae583f3 100644 --- a/numpy/core/include/numpy/npy_math.h +++ b/numpy/core/include/numpy/npy_math.h @@ -87,7 +87,7 @@ NPY_INLINE static float __npy_nzerof(void) #define NPY_PI_4f 0.785398163397448309615660845819875721F /* pi/4 */ #define NPY_1_PIf 0.318309886183790671537767526745028724F /* 1/pi */ #define NPY_2_PIf 0.636619772367581343075535053490057448F /* 2/pi */ -#define NPY_EULERf 0.577215664901532860606512090082402431F /* Euler constan*/ +#define NPY_EULERf 0.577215664901532860606512090082402431F /* Euler constant */ #define NPY_SQRT2f 1.414213562373095048801688724209698079F /* sqrt(2) */ #define NPY_SQRT1_2f 0.707106781186547524400844362104849039F /* 1/sqrt(2) */ @@ -101,7 +101,7 @@ NPY_INLINE static float __npy_nzerof(void) #define NPY_PI_4l 0.785398163397448309615660845819875721L /* pi/4 */ #define NPY_1_PIl 0.318309886183790671537767526745028724L /* 1/pi */ #define NPY_2_PIl 0.636619772367581343075535053490057448L /* 2/pi */ -#define NPY_EULERl 0.577215664901532860606512090082402431L /* Euler constan*/ +#define NPY_EULERl 0.577215664901532860606512090082402431L /* Euler constant */ #define NPY_SQRT2l 1.414213562373095048801688724209698079L /* sqrt(2) */ #define NPY_SQRT1_2l 0.707106781186547524400844362104849039L /* 1/sqrt(2) */ @@ -163,7 +163,7 @@ double npy_spacing(double x); #ifndef NPY_HAVE_DECL_ISNAN #define npy_isnan(x) ((x) != (x)) #else - #ifdef _MSC_VER + #if defined(_MSC_VER) && (_MSC_VER < 1900) #define npy_isnan(x) _isnan((x)) #else #define npy_isnan(x) isnan(x) @@ -194,7 +194,7 @@ double npy_spacing(double x); #ifndef NPY_HAVE_DECL_ISINF #define npy_isinf(x) (!npy_isfinite(x) && !npy_isnan(x)) #else - #ifdef _MSC_VER + #if defined(_MSC_VER) && (_MSC_VER < 1900) #define npy_isinf(x) (!_finite((x)) && !_isnan((x))) #else #define npy_isinf(x) isinf((x)) diff --git a/numpy/core/include/numpy/numpyconfig.h b/numpy/core/include/numpy/numpyconfig.h index 9d6dce004..cbf4a62b9 100644 --- a/numpy/core/include/numpy/numpyconfig.h +++ b/numpy/core/include/numpy/numpyconfig.h @@ -31,5 +31,7 @@ #define NPY_1_7_API_VERSION 0x00000007 #define NPY_1_8_API_VERSION 0x00000008 #define NPY_1_9_API_VERSION 0x00000008 +#define NPY_1_10_API_VERSION 0x00000008 +#define NPY_1_11_API_VERSION 0x00000008 #endif diff --git a/numpy/core/machar.py b/numpy/core/machar.py index 9eb4430a6..6f2735d32 100644 --- a/numpy/core/machar.py +++ b/numpy/core/machar.py @@ -94,16 +94,19 @@ class MachAr(object): Cambridge University Press, 2002, p. 31. """ + def __init__(self, float_conv=float,int_conv=int, float_to_float=float, - float_to_str = lambda v:'%24.16e' % v, - title = 'Python floating point number'): + float_to_str=lambda v:'%24.16e' % v, + title='Python floating point number'): """ - float_conv - convert integer to float (array) - int_conv - convert float (array) to integer - float_to_float - convert float array to float - float_to_str - convert array float to str - title - description of used floating point numbers + + float_conv - convert integer to float (array) + int_conv - convert float (array) to integer + float_to_float - convert float array to float + float_to_str - convert array float to str + title - description of used floating point numbers + """ # We ignore all errors here because we are purposely triggering # underflow to detect the properties of the runninng arch. @@ -169,7 +172,7 @@ class MachAr(object): irnd = 1 tempa = a + beta temp = tempa + betah - if irnd==0 and any(temp-tempa != zero): + if irnd == 0 and any(temp-tempa != zero): irnd = 2 # Determine negep and epsneg @@ -188,7 +191,7 @@ class MachAr(object): # Prevent infinite loop on PPC with gcc 4.0: if negep < 0: raise RuntimeError("could not determine machine tolerance " - "for 'negep', locals() -> %s" % (locals())) + "for 'negep', locals() -> %s" % (locals())) else: raise RuntimeError(msg % (_, one.dtype)) negep = -negep @@ -211,7 +214,7 @@ class MachAr(object): # Determine ngrd ngrd = 0 temp = one + eps - if irnd==0 and any(temp*one - one != zero): + if irnd == 0 and any(temp*one - one != zero): ngrd = 1 # Determine iexp @@ -223,9 +226,9 @@ class MachAr(object): for _ in range(max_iterN): y = z z = y*y - a = z*one # Check here for underflow + a = z*one # Check here for underflow temp = z*t - if any(a+a == zero) or any(abs(z)>=y): + if any(a+a == zero) or any(abs(z) >= y): break temp1 = temp * betain if any(temp1*beta == z): @@ -251,7 +254,7 @@ class MachAr(object): y = y * betain a = y * one temp = y * t - if any(a+a != zero) and any(abs(y) < xmin): + if any((a + a) != zero) and any(abs(y) < xmin): k = k + 1 temp1 = temp * betain if any(temp1*beta == y) and any(temp != y): @@ -285,7 +288,7 @@ class MachAr(object): xmax = xmax / (xmin*beta*beta*beta) i = maxexp + minexp + 3 for j in range(i): - if ibeta==2: + if ibeta == 2: xmax = xmax + xmax else: xmax = xmax * beta @@ -322,16 +325,17 @@ class MachAr(object): self._str_resolution = float_to_str(resolution) def __str__(self): - return '''\ -Machine parameters for %(title)s ---------------------------------------------------------------------- -ibeta=%(ibeta)s it=%(it)s iexp=%(iexp)s ngrd=%(ngrd)s irnd=%(irnd)s -machep=%(machep)s eps=%(_str_eps)s (beta**machep == epsilon) -negep =%(negep)s epsneg=%(_str_epsneg)s (beta**epsneg) -minexp=%(minexp)s xmin=%(_str_xmin)s (beta**minexp == tiny) -maxexp=%(maxexp)s xmax=%(_str_xmax)s ((1-epsneg)*beta**maxexp == huge) ---------------------------------------------------------------------- -''' % self.__dict__ + fmt = ( + 'Machine parameters for %(title)s\n' + '---------------------------------------------------------------------\n' + 'ibeta=%(ibeta)s it=%(it)s iexp=%(iexp)s ngrd=%(ngrd)s irnd=%(irnd)s\n' + 'machep=%(machep)s eps=%(_str_eps)s (beta**machep == epsilon)\n' + 'negep =%(negep)s epsneg=%(_str_epsneg)s (beta**epsneg)\n' + 'minexp=%(minexp)s xmin=%(_str_xmin)s (beta**minexp == tiny)\n' + 'maxexp=%(maxexp)s xmax=%(_str_xmax)s ((1-epsneg)*beta**maxexp == huge)\n' + '---------------------------------------------------------------------\n' + ) + return fmt % self.__dict__ if __name__ == '__main__': diff --git a/numpy/core/memmap.py b/numpy/core/memmap.py index 4b10f361c..70d7b72b4 100644 --- a/numpy/core/memmap.py +++ b/numpy/core/memmap.py @@ -1,14 +1,11 @@ from __future__ import division, absolute_import, print_function -__all__ = ['memmap'] - -import warnings -import sys - import numpy as np from .numeric import uint8, ndarray, dtype from numpy.compat import long, basestring +__all__ = ['memmap'] + dtypedescr = dtype valid_filemodes = ["r", "c", "r+", "w+"] writeable_filemodes = ["r+", "w+"] @@ -21,8 +18,7 @@ mode_equivalents = { } class memmap(ndarray): - """ - Create a memory-map to an array stored in a *binary* file on disk. + """Create a memory-map to an array stored in a *binary* file on disk. Memory-mapped files are used for accessing small segments of large files on disk, without reading the entire file into memory. Numpy's @@ -79,8 +75,9 @@ class memmap(ndarray): will be 1-D with the number of elements determined by file size and data-type. order : {'C', 'F'}, optional - Specify the order of the ndarray memory layout: C (row-major) or - Fortran (column-major). This only has an effect if the shape is + Specify the order of the ndarray memory layout: + :term:`row-major`, C-style or :term:`column-major`, + Fortran-style. This only has an effect if the shape is greater than 1-D. The default order is 'C'. Attributes @@ -200,6 +197,7 @@ class memmap(ndarray): """ __array_priority__ = -100.0 + def __new__(subtype, filename, dtype=uint8, mode='r+', offset=0, shape=None, order='C'): # Import here to minimize 'import numpy' overhead diff --git a/numpy/core/numeric.py b/numpy/core/numeric.py index 7a0fa4b62..1b7dfca3e 100644 --- a/numpy/core/numeric.py +++ b/numpy/core/numeric.py @@ -1,6 +1,5 @@ from __future__ import division, absolute_import, print_function -import os import sys import warnings import collections @@ -11,6 +10,7 @@ from .umath import (invert, sin, UFUNC_BUFSIZE_DEFAULT, ERR_IGNORE, ERR_DEFAULT, PINF, NAN) from . import numerictypes from .numerictypes import longlong, intc, int_, float_, complex_, bool_ +from ._internal import TooHardError if sys.version_info[0] >= 3: import pickle @@ -21,29 +21,28 @@ else: loads = pickle.loads -__all__ = ['newaxis', 'ndarray', 'flatiter', 'nditer', 'nested_iters', 'ufunc', - 'arange', 'array', 'zeros', 'count_nonzero', - 'empty', 'broadcast', 'dtype', 'fromstring', 'fromfile', - 'frombuffer', 'int_asbuffer', 'where', 'argwhere', 'copyto', - 'concatenate', 'fastCopyAndTranspose', 'lexsort', 'set_numeric_ops', - 'can_cast', 'promote_types', 'min_scalar_type', 'result_type', - 'asarray', 'asanyarray', 'ascontiguousarray', 'asfortranarray', - 'isfortran', 'empty_like', 'zeros_like', 'ones_like', - 'correlate', 'convolve', 'inner', 'dot', 'einsum', 'outer', 'vdot', - 'alterdot', 'restoredot', 'roll', 'rollaxis', 'cross', 'tensordot', - 'array2string', 'get_printoptions', 'set_printoptions', - 'array_repr', 'array_str', 'set_string_function', - 'little_endian', 'require', - 'fromiter', 'array_equal', 'array_equiv', - 'indices', 'fromfunction', 'isclose', - 'load', 'loads', 'isscalar', 'binary_repr', 'base_repr', - 'ones', 'identity', 'allclose', 'compare_chararrays', 'putmask', - 'seterr', 'geterr', 'setbufsize', 'getbufsize', - 'seterrcall', 'geterrcall', 'errstate', 'flatnonzero', - 'Inf', 'inf', 'infty', 'Infinity', - 'nan', 'NaN', 'False_', 'True_', 'bitwise_not', - 'CLIP', 'RAISE', 'WRAP', 'MAXDIMS', 'BUFSIZE', 'ALLOW_THREADS', - 'ComplexWarning', 'may_share_memory', 'full', 'full_like'] +__all__ = [ + 'newaxis', 'ndarray', 'flatiter', 'nditer', 'nested_iters', 'ufunc', + 'arange', 'array', 'zeros', 'count_nonzero', 'empty', 'broadcast', + 'dtype', 'fromstring', 'fromfile', 'frombuffer', 'int_asbuffer', + 'where', 'argwhere', 'copyto', 'concatenate', 'fastCopyAndTranspose', + 'lexsort', 'set_numeric_ops', 'can_cast', 'promote_types', + 'min_scalar_type', 'result_type', 'asarray', 'asanyarray', + 'ascontiguousarray', 'asfortranarray', 'isfortran', 'empty_like', + 'zeros_like', 'ones_like', 'correlate', 'convolve', 'inner', 'dot', + 'einsum', 'outer', 'vdot', 'alterdot', 'restoredot', 'roll', + 'rollaxis', 'cross', 'tensordot', 'array2string', 'get_printoptions', + 'set_printoptions', 'array_repr', 'array_str', 'set_string_function', + 'little_endian', 'require', 'fromiter', 'array_equal', 'array_equiv', + 'indices', 'fromfunction', 'isclose', 'load', 'loads', 'isscalar', + 'binary_repr', 'base_repr', 'ones', 'identity', 'allclose', + 'compare_chararrays', 'putmask', 'seterr', 'geterr', 'setbufsize', + 'getbufsize', 'seterrcall', 'geterrcall', 'errstate', 'flatnonzero', + 'Inf', 'inf', 'infty', 'Infinity', 'nan', 'NaN', 'False_', 'True_', + 'bitwise_not', 'CLIP', 'RAISE', 'WRAP', 'MAXDIMS', 'BUFSIZE', + 'ALLOW_THREADS', 'ComplexWarning', 'full', 'full_like', 'matmul', + 'shares_memory', 'MAY_SHARE_BOUNDS', 'MAY_SHARE_EXACT', 'TooHardError', + ] if sys.version_info[0] < 3: __all__.extend(['getbuffer', 'newbuffer']) @@ -67,6 +66,8 @@ RAISE = multiarray.RAISE MAXDIMS = multiarray.MAXDIMS ALLOW_THREADS = multiarray.ALLOW_THREADS BUFSIZE = multiarray.BUFSIZE +MAY_SHARE_BOUNDS = multiarray.MAY_SHARE_BOUNDS +MAY_SHARE_EXACT = multiarray.MAY_SHARE_EXACT ndarray = multiarray.ndarray flatiter = multiarray.flatiter @@ -88,14 +89,16 @@ def zeros_like(a, dtype=None, order='K', subok=True): The shape and data-type of `a` define these same attributes of the returned array. dtype : data-type, optional - .. versionadded:: 1.6.0 Overrides the data type of the result. - order : {'C', 'F', 'A', or 'K'}, optional + .. versionadded:: 1.6.0 + order : {'C', 'F', 'A', or 'K'}, optional Overrides the memory layout of the result. 'C' means C-order, 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, 'C' otherwise. 'K' means match the layout of `a` as closely as possible. + + .. versionadded:: 1.6.0 subok : bool, optional. If True, then the newly created array will use the sub-class type of 'a', otherwise it will be a base-class array. Defaults @@ -194,14 +197,16 @@ def ones_like(a, dtype=None, order='K', subok=True): The shape and data-type of `a` define these same attributes of the returned array. dtype : data-type, optional - .. versionadded:: 1.6.0 Overrides the data type of the result. - order : {'C', 'F', 'A', or 'K'}, optional + .. versionadded:: 1.6.0 + order : {'C', 'F', 'A', or 'K'}, optional Overrides the memory layout of the result. 'C' means C-order, 'F' means F-order, 'A' means 'F' if `a` is Fortran contiguous, 'C' otherwise. 'K' means match the layout of `a` as closely as possible. + + .. versionadded:: 1.6.0 subok : bool, optional. If True, then the newly created array will use the sub-class type of 'a', otherwise it will be a base-class array. Defaults @@ -373,7 +378,7 @@ fromstring = multiarray.fromstring fromiter = multiarray.fromiter fromfile = multiarray.fromfile frombuffer = multiarray.frombuffer -may_share_memory = multiarray.may_share_memory +shares_memory = multiarray.shares_memory if sys.version_info[0] < 3: newbuffer = multiarray.newbuffer getbuffer = multiarray.getbuffer @@ -390,10 +395,14 @@ lexsort = multiarray.lexsort compare_chararrays = multiarray.compare_chararrays putmask = multiarray.putmask einsum = multiarray.einsum +dot = multiarray.dot +inner = multiarray.inner +vdot = multiarray.vdot +matmul = multiarray.matmul + def asarray(a, dtype=None, order=None): - """ - Convert the input to an array. + """Convert the input to an array. Parameters ---------- @@ -404,8 +413,9 @@ def asarray(a, dtype=None, order=None): dtype : data-type, optional By default, the data-type is inferred from the input data. order : {'C', 'F'}, optional - Whether to use row-major ('C') or column-major ('F' for FORTRAN) - memory representation. Defaults to 'C'. + Whether to use row-major (C-style) or + column-major (Fortran-style) memory representation. + Defaults to 'C'. Returns ------- @@ -462,8 +472,7 @@ def asarray(a, dtype=None, order=None): return array(a, dtype, copy=False, order=order) def asanyarray(a, dtype=None, order=None): - """ - Convert the input to an ndarray, but pass ndarray subclasses through. + """Convert the input to an ndarray, but pass ndarray subclasses through. Parameters ---------- @@ -474,8 +483,8 @@ def asanyarray(a, dtype=None, order=None): dtype : data-type, optional By default, the data-type is inferred from the input data. order : {'C', 'F'}, optional - Whether to use row-major ('C') or column-major ('F') memory - representation. Defaults to 'C'. + Whether to use row-major (C-style) or column-major + (Fortran-style) memory representation. Defaults to 'C'. Returns ------- @@ -817,15 +826,15 @@ def flatnonzero(a): return a.ravel().nonzero()[0] _mode_from_name_dict = {'v': 0, - 's' : 1, - 'f' : 2} + 's': 1, + 'f': 2} def _mode_from_name(mode): if isinstance(mode, basestring): return _mode_from_name_dict[mode.lower()[0]] return mode -def correlate(a, v, mode='valid', old_behavior=False): +def correlate(a, v, mode='valid'): """ Cross-correlation of two 1-dimensional sequences. @@ -843,12 +852,10 @@ def correlate(a, v, mode='valid', old_behavior=False): Input sequences. mode : {'valid', 'same', 'full'}, optional Refer to the `convolve` docstring. Note that the default - is `valid`, unlike `convolve`, which uses `full`. + is 'valid', unlike `convolve`, which uses 'full'. old_behavior : bool - If True, uses the old behavior from Numeric, - (correlate(a,v) == correlate(v,a), and the conjugate is not taken - for complex arrays). If False, uses the conventional signal - processing definition. + `old_behavior` was removed in NumPy 1.10. If you need the old + behavior, use `multiarray.correlate`. Returns ------- @@ -858,6 +865,7 @@ def correlate(a, v, mode='valid', old_behavior=False): See Also -------- convolve : Discrete, linear convolution of two one-dimensional sequences. + multiarray.correlate : Old, no conjugate, version of correlate. Notes ----- @@ -891,19 +899,7 @@ def correlate(a, v, mode='valid', old_behavior=False): """ mode = _mode_from_name(mode) -# the old behavior should be made available under a different name, see thread -# http://thread.gmane.org/gmane.comp.python.numeric.general/12609/focus=12630 - if old_behavior: - warnings.warn(""" -The old behavior of correlate was deprecated for 1.4.0, and will be completely removed -for NumPy 2.0. - -The new behavior fits the conventional definition of correlation: inputs are -never swapped, and the second argument is conjugated for complex arrays.""", - DeprecationWarning) - return multiarray.correlate(a, v, mode) - else: - return multiarray.correlate2(a, v, mode) + return multiarray.correlate2(a, v, mode) def convolve(a,v,mode='full'): """ @@ -931,11 +927,11 @@ def convolve(a,v,mode='full'): completely, and boundary effects may be seen. 'same': - Mode `same` returns output of length ``max(M, N)``. Boundary + Mode 'same' returns output of length ``max(M, N)``. Boundary effects are still visible. 'valid': - Mode `valid` returns output of length + Mode 'valid' returns output of length ``max(M, N) - min(M, N) + 1``. The convolution product is only given for points where the signals overlap completely. Values outside the signal boundary have no effect. @@ -995,9 +991,9 @@ def convolve(a,v,mode='full'): a, v = array(a, copy=False, ndmin=1), array(v, copy=False, ndmin=1) if (len(v) > len(a)): a, v = v, a - if len(a) == 0 : + if len(a) == 0: raise ValueError('a cannot be empty') - if len(v) == 0 : + if len(v) == 0: raise ValueError('v cannot be empty') mode = _mode_from_name(mode) return multiarray.correlate(a, v[::-1], mode) @@ -1024,9 +1020,10 @@ def outer(a, b, out=None): Second input vector. Input is flattened if not already 1-dimensional. out : (M, N) ndarray, optional - .. versionadded:: 1.9.0 A location where the result is stored + .. versionadded:: 1.9.0 + Returns ------- out : (M, N) ndarray @@ -1081,11 +1078,6 @@ def outer(a, b, out=None): b = asarray(b) return multiply(a.ravel()[:, newaxis], b.ravel()[newaxis,:], out) -# try to import blas optimized dot if available -envbak = os.environ.copy() -dot = multiarray.dot -inner = multiarray.inner -vdot = multiarray.vdot def alterdot(): """ @@ -1113,6 +1105,7 @@ def alterdot(): restoredot : `restoredot` undoes the effects of `alterdot`. """ + # 2014-08-13, 1.10 warnings.warn("alterdot no longer does anything.", DeprecationWarning) @@ -1136,6 +1129,7 @@ def restoredot(): alterdot : `restoredot` undoes the effects of `alterdot`. """ + # 2014-08-13, 1.10 warnings.warn("restoredot no longer does anything.", DeprecationWarning) @@ -1287,7 +1281,8 @@ def tensordot(a, b, axes=2): bs = b.shape ndb = len(b.shape) equal = True - if (na != nb): equal = False + if na != nb: + equal = False else: for k in range(na): if as_[axes_a[k]] != bs[axes_b[k]]: @@ -1478,8 +1473,9 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): axisb : int, optional Axis of `b` that defines the vector(s). By default, the last axis. axisc : int, optional - Axis of `c` containing the cross product vector(s). By default, the - last axis. + Axis of `c` containing the cross product vector(s). Ignored if + both input vectors have dimension 2, as the return is scalar. + By default, the last axis. axis : int, optional If defined, the axis of `a`, `b` and `c` that defines the vector(s) and cross product(s). Overrides `axisa`, `axisb` and `axisc`. @@ -1504,6 +1500,7 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): Notes ----- .. versionadded:: 1.9.0 + Supports full broadcasting of the inputs. Examples @@ -1570,6 +1567,12 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): axisa, axisb, axisc = (axis,) * 3 a = asarray(a) b = asarray(b) + # Check axisa and axisb are within bounds + axis_msg = "'axis{0}' out of bounds" + if axisa < -a.ndim or axisa >= a.ndim: + raise ValueError(axis_msg.format('a')) + if axisb < -b.ndim or axisb >= b.ndim: + raise ValueError(axis_msg.format('b')) # Move working axis to the end of the shape a = rollaxis(a, axisa, a.ndim) b = rollaxis(b, axisb, b.ndim) @@ -1578,10 +1581,13 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): if a.shape[-1] not in (2, 3) or b.shape[-1] not in (2, 3): raise ValueError(msg) - # Create the output array + # Create the output array shape = broadcast(a[..., 0], b[..., 0]).shape if a.shape[-1] == 3 or b.shape[-1] == 3: shape += (3,) + # Check axisc is within bounds + if axisc < -len(shape) or axisc >= len(shape): + raise ValueError(axis_msg.format('c')) dtype = promote_types(a.dtype, b.dtype) cp = empty(shape, dtype) @@ -1604,12 +1610,9 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): # a0 * b1 - a1 * b0 multiply(a0, b1, out=cp) cp -= a1 * b0 - if cp.ndim == 0: - return cp - else: - # This works because we are moving the last axis - return rollaxis(cp, -1, axisc) + return cp else: + assert b.shape[-1] == 3 # cp0 = a1 * b2 - 0 (a2 = 0) # cp1 = 0 - a0 * b2 (a2 = 0) # cp2 = a0 * b1 - a1 * b0 @@ -1618,7 +1621,8 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): negative(cp1, out=cp1) multiply(a0, b1, out=cp2) cp2 -= a1 * b0 - elif a.shape[-1] == 3: + else: + assert a.shape[-1] == 3 if b.shape[-1] == 3: # cp0 = a1 * b2 - a2 * b1 # cp1 = a2 * b0 - a0 * b2 @@ -1633,6 +1637,7 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): multiply(a1, b0, out=tmp) cp2 -= tmp else: + assert b.shape[-1] == 2 # cp0 = 0 - a2 * b1 (b2 = 0) # cp1 = a2 * b0 - 0 (b2 = 0) # cp2 = a0 * b1 - a1 * b0 @@ -1642,11 +1647,8 @@ def cross(a, b, axisa=-1, axisb=-1, axisc=-1, axis=None): multiply(a0, b1, out=cp2) cp2 -= a1 * b0 - if cp.ndim == 1: - return cp - else: - # This works because we are moving the last axis - return rollaxis(cp, -1, axisc) + # This works because we are moving the last axis + return rollaxis(cp, -1, axisc) #Use numarray's printing function from .arrayprint import array2string, get_printoptions, set_printoptions @@ -1700,14 +1702,14 @@ def array_repr(arr, max_line_width=None, precision=None, suppress_small=None): 'array([ 0.000001, 0. , 2. , 3. ])' """ - if arr.size > 0 or arr.shape==(0,): + if arr.size > 0 or arr.shape == (0,): lst = array2string(arr, max_line_width, precision, suppress_small, ', ', "array(") - else: # show zero-length shape unless it is (0,) + else: # show zero-length shape unless it is (0,) lst = "[], shape=%s" % (repr(arr.shape),) if arr.__class__ is not ndarray: - cName= arr.__class__.__name__ + cName = arr.__class__.__name__ else: cName = "array" @@ -1899,7 +1901,7 @@ def indices(dimensions, dtype=int): for i, dim in enumerate(dimensions): tmp = arange(dim, dtype=dtype) tmp.shape = (1,)*i + (dim,)+(1,)*(N-i-1) - newdim = dimensions[:i] + (1,)+ dimensions[i+1:] + newdim = dimensions[:i] + (1,) + dimensions[i+1:] val = zeros(newdim, dtype) add(tmp, val, res[i]) return res @@ -2227,10 +2229,11 @@ def allclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False): atol : float The absolute tolerance parameter (see Notes). equal_nan : bool - .. versionadded:: 1.10.0 Whether to compare NaN's as equal. If True, NaN's in `a` will be considered equal to NaN's in `b` in the output array. + .. versionadded:: 1.10.0 + Returns ------- allclose : bool @@ -2546,13 +2549,17 @@ def seterr(all=None, divide=None, over=None, under=None, invalid=None): pyvals = umath.geterrobj() old = geterr() - if divide is None: divide = all or old['divide'] - if over is None: over = all or old['over'] - if under is None: under = all or old['under'] - if invalid is None: invalid = all or old['invalid'] + if divide is None: + divide = all or old['divide'] + if over is None: + over = all or old['over'] + if under is None: + under = all or old['under'] + if invalid is None: + invalid = all or old['invalid'] maskvalue = ((_errdict[divide] << SHIFT_DIVIDEBYZERO) + - (_errdict[over] << SHIFT_OVERFLOW ) + + (_errdict[over] << SHIFT_OVERFLOW) + (_errdict[under] << SHIFT_UNDERFLOW) + (_errdict[invalid] << SHIFT_INVALID)) @@ -2624,9 +2631,9 @@ def setbufsize(size): if size > 10e6: raise ValueError("Buffer size, %s, is too big." % size) if size < 5: - raise ValueError("Buffer size, %s, is too small." %size) + raise ValueError("Buffer size, %s, is too small." % size) if size % 16 != 0: - raise ValueError("Buffer size, %s, is not a multiple of 16." %size) + raise ValueError("Buffer size, %s, is not a multiple of 16." % size) pyvals = umath.geterrobj() old = getbufsize() @@ -2847,6 +2854,7 @@ class errstate(object): """ # Note that we don't want to run the above doctests because they will fail # without a from __future__ import with_statement + def __init__(self, **kwargs): self.call = kwargs.pop('call', _Unspecified) self.kwargs = kwargs diff --git a/numpy/core/numerictypes.py b/numpy/core/numerictypes.py index 0c03cce89..7dc6e0bd8 100644 --- a/numpy/core/numerictypes.py +++ b/numpy/core/numerictypes.py @@ -82,6 +82,18 @@ Exported symbols include: """ from __future__ import division, absolute_import, print_function +import types as _types +import sys +import numbers + +from numpy.compat import bytes, long +from numpy.core.multiarray import ( + typeinfo, ndarray, array, empty, dtype, datetime_data, + datetime_as_string, busday_offset, busday_count, is_busday, + busdaycalendar + ) + + # we add more at the bottom __all__ = ['sctypeDict', 'sctypeNA', 'typeDict', 'typeNA', 'sctypes', 'ScalarType', 'obj2sctype', 'cast', 'nbytes', 'sctype2char', @@ -90,15 +102,6 @@ __all__ = ['sctypeDict', 'sctypeNA', 'typeDict', 'typeNA', 'sctypes', 'busday_offset', 'busday_count', 'is_busday', 'busdaycalendar', ] -from numpy.core.multiarray import ( - typeinfo, ndarray, array, empty, dtype, datetime_data, - datetime_as_string, busday_offset, busday_count, is_busday, - busdaycalendar - ) -import types as _types -import sys -from numpy.compat import bytes, long -import numbers # we don't export these for import *, but we do want them accessible # as numerictypes.bool, etc. @@ -117,16 +120,9 @@ else: _all_chars = [chr(_m) for _m in range(256)] _ascii_upper = _all_chars[65:65+26] _ascii_lower = _all_chars[97:97+26] -LOWER_TABLE="".join(_all_chars[:65] + _ascii_lower + _all_chars[65+26:]) -UPPER_TABLE="".join(_all_chars[:97] + _ascii_upper + _all_chars[97+26:]) +LOWER_TABLE = "".join(_all_chars[:65] + _ascii_lower + _all_chars[65+26:]) +UPPER_TABLE = "".join(_all_chars[:97] + _ascii_upper + _all_chars[97+26:]) -#import string -# assert (string.maketrans(string.ascii_uppercase, string.ascii_lowercase) == \ -# LOWER_TABLE) -# assert (string.maketrnas(string_ascii_lowercase, string.ascii_uppercase) == \ -# UPPER_TABLE) -#LOWER_TABLE = string.maketrans(string.ascii_uppercase, string.ascii_lowercase) -#UPPER_TABLE = string.maketrans(string.ascii_lowercase, string.ascii_uppercase) def english_lower(s): """ Apply English case rules to convert ASCII strings to all lower case. @@ -251,30 +247,30 @@ def bitname(obj): if name == 'bool_': char = 'b' base = 'bool' - elif name=='void': + elif name == 'void': char = 'V' base = 'void' - elif name=='object_': + elif name == 'object_': char = 'O' base = 'object' bits = 0 - elif name=='datetime64': + elif name == 'datetime64': char = 'M' - elif name=='timedelta64': + elif name == 'timedelta64': char = 'm' if sys.version_info[0] >= 3: - if name=='bytes_': + if name == 'bytes_': char = 'S' base = 'bytes' - elif name=='str_': + elif name == 'str_': char = 'U' base = 'str' else: - if name=='string_': + if name == 'string_': char = 'S' base = 'string' - elif name=='unicode_': + elif name == 'unicode_': char = 'U' base = 'unicode' @@ -310,11 +306,12 @@ def _add_aliases(): typeobj = typeinfo[a][-1] # insert bit-width version for this class (if relevant) base, bit, char = bitname(typeobj) - if base[-3:] == 'int' or char[0] in 'ui': continue + if base[-3:] == 'int' or char[0] in 'ui': + continue if base != '': myname = "%s%d" % (base, bit) - if (name != 'longdouble' and name != 'clongdouble') or \ - myname not in allTypes.keys(): + if ((name != 'longdouble' and name != 'clongdouble') or + myname not in allTypes.keys()): allTypes[myname] = typeobj sctypeDict[myname] = typeobj if base == 'complex': @@ -334,15 +331,10 @@ def _add_aliases(): sctypeNA[char] = na_name _add_aliases() -# Integers handled so that -# The int32, int64 types should agree exactly with -# PyArray_INT32, PyArray_INT64 in C -# We need to enforce the same checking as is done -# in arrayobject.h where the order of getting a -# bit-width match is: -# long, longlong, int, short, char -# for int8, int16, int32, int64, int128 - +# Integers are handled so that the int32 and int64 types should agree +# exactly with NPY_INT32, NPY_INT64. We need to enforce the same checking +# as is done in arrayobject.h where the order of getting a bit-width match +# is long, longlong, int, short, char. def _add_integer_aliases(): _ctypes = ['LONG', 'LONGLONG', 'INT', 'SHORT', 'BYTE'] for ctype in _ctypes: @@ -549,7 +541,7 @@ _python_types = {int: 'int_', bytes: 'bytes_', unicode: 'unicode_', buffer_type: 'void', - } + } if sys.version_info[0] >= 3: def _python_type(t): @@ -778,6 +770,7 @@ class _typedict(dict): first they have to be populated. """ + def __getitem__(self, obj): return dict.__getitem__(self, obj2sctype(obj)) @@ -864,7 +857,7 @@ except AttributeError: ScalarType.extend(_sctype2char_dict.keys()) ScalarType = tuple(ScalarType) for key in _sctype2char_dict.keys(): - cast[key] = lambda x, k=key : array(x, copy=False).astype(k) + cast[key] = lambda x, k=key: array(x, copy=False).astype(k) # Create the typestring lookup dictionary _typestr = _typedict() @@ -965,6 +958,7 @@ def _register_types(): numbers.Integral.register(integer) numbers.Complex.register(inexact) numbers.Real.register(floating) + _register_types() def find_common_type(array_types, scalar_types): diff --git a/numpy/core/records.py b/numpy/core/records.py index 243645436..4a995533a 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -139,6 +139,7 @@ class format_parser: dtype([('f0', '<f8'), ('f1', '<i4'), ('f2', '|S5')]) """ + def __init__(self, formats, names, titles, aligned=False, byteorder=None): self._parseFormats(formats, aligned) self._setfieldnames(names, titles) @@ -245,13 +246,12 @@ class record(nt.void): #happens if field is Object type return obj if dt.fields: - return obj.view((record, obj.dtype.descr)) + return obj.view((self.__class__, obj.dtype.fields)) return obj else: raise AttributeError("'record' object has no " "attribute '%s'" % attr) - def __setattr__(self, attr, val): if attr in ['setfield', 'getfield', 'dtype']: raise AttributeError("Cannot set '%s' attribute" % attr) @@ -266,6 +266,16 @@ class record(nt.void): raise AttributeError("'record' object has no " "attribute '%s'" % attr) + def __getitem__(self, indx): + obj = nt.void.__getitem__(self, indx) + + # copy behavior of record.__getattribute__, + if isinstance(obj, nt.void) and obj.dtype.fields: + return obj.view((self.__class__, obj.dtype.fields)) + else: + # return a single element + return obj + def pprint(self): """Pretty-print all fields.""" # pretty-print all fields @@ -286,8 +296,7 @@ class record(nt.void): # the fields (and any subfields) class recarray(ndarray): - """ - Construct an ndarray that allows field access using attributes. + """Construct an ndarray that allows field access using attributes. Arrays may have a data-types containing fields, analogous to columns in a spread sheet. An example is ``[(x, int), (y, float)]``, @@ -336,7 +345,7 @@ class recarray(ndarray): offset : int, optional Start reading buffer (`buf`) from this offset onwards. order : {'C', 'F'}, optional - Row-major or column-major order. + Row-major (C-style) or column-major (Fortran-style) order. Returns ------- @@ -414,13 +423,19 @@ class recarray(ndarray): strides=strides, order=order) return self + def __array_finalize__(self, obj): + if self.dtype.type is not record: + # if self.dtype is not np.record, invoke __setattr__ which will + # convert it to a record if it is a void dtype. + self.dtype = self.dtype + def __getattribute__(self, attr): # See if ndarray has this attr, and return it if so. (note that this # means a field with the same name as an ndarray attr cannot be # accessed by attribute). try: return object.__getattribute__(self, attr) - except AttributeError: # attr must be a fieldname + except AttributeError: # attr must be a fieldname pass # look for a field with this name @@ -438,7 +453,7 @@ class recarray(ndarray): # to preserve numpy.record type if present), since nested structured # fields do not inherit type. if obj.dtype.fields: - return obj.view(dtype=(self.dtype.type, obj.dtype.descr)) + return obj.view(dtype=(self.dtype.type, obj.dtype.fields)) else: return obj.view(ndarray) @@ -447,6 +462,11 @@ class recarray(ndarray): # Undo any "setting" of the attribute and do a setfield # Thus, you can't create attributes on-the-fly that are field names. def __setattr__(self, attr, val): + + # Automatically convert (void) dtypes to records. + if attr == 'dtype' and issubclass(val.type, nt.void): + val = sb.dtype((record, val)) + newattr = attr not in self.__dict__ try: ret = object.__setattr__(self, attr, val) @@ -459,9 +479,10 @@ class recarray(ndarray): fielddict = ndarray.__getattribute__(self, 'dtype').fields or {} if attr not in fielddict: return ret - if newattr: # We just added this one - try: # or this setattr worked on an internal - # attribute. + if newattr: + # We just added this one or this setattr worked on an + # internal attribute. + try: object.__delattr__(self, attr) except: return ret @@ -478,7 +499,7 @@ class recarray(ndarray): # we might also be returning a single element if isinstance(obj, ndarray): if obj.dtype.fields: - return obj.view(dtype=(self.dtype.type, obj.dtype.descr)) + return obj.view(dtype=(self.dtype.type, obj.dtype.fields)) else: return obj.view(type=ndarray) else: @@ -487,14 +508,16 @@ class recarray(ndarray): def __repr__(self): # get data/shape string. logic taken from numeric.array_repr - if self.size > 0 or self.shape==(0,): + if self.size > 0 or self.shape == (0,): lst = sb.array2string(self, separator=', ') else: # show zero-length shape unless it is (0,) lst = "[], shape=%s" % (repr(self.shape),) - if self.dtype.type is record: + if (self.dtype.type is record + or (not issubclass(self.dtype.type, nt.void))): # If this is a full record array (has numpy.record dtype), + # or if it has a scalar (non-void) dtype with no records, # represent it using the rec.array function. Since rec.array # converts dtype to a numpy.record for us, use only dtype.descr, # not repr(dtype). @@ -503,7 +526,8 @@ class recarray(ndarray): (lst, lf, repr(self.dtype.descr))) else: # otherwise represent it using np.array plus a view - # (There is currently (v1.10) no other easy way to create it) + # This should only happen if the user is playing + # strange games with dtypes. lf = '\n'+' '*len("array(") return ('array(%s, %sdtype=%s).view(numpy.recarray)' % (lst, lf, str(self.dtype))) @@ -525,22 +549,6 @@ class recarray(ndarray): else: return self.setfield(val, *res) - def view(self, dtype=None, type=None): - if dtype is None: - return ndarray.view(self, type) - elif type is None: - try: - if issubclass(dtype, ndarray): - return ndarray.view(self, dtype) - except TypeError: - pass - dtype = sb.dtype(dtype) - if dtype.fields is None: - return self.__array__().view(dtype) - return ndarray.view(self, dtype) - else: - return ndarray.view(self, dtype, type) - def fromarrays(arrayList, dtype=None, shape=None, formats=None, names=None, titles=None, aligned=False, byteorder=None): @@ -677,7 +685,6 @@ def fromstring(datastring, dtype=None, shape=None, offset=0, formats=None, """ create a (read-only) record array from binary data contained in a string""" - if dtype is None and formats is None: raise ValueError("Must have dtype= or formats=") @@ -750,7 +757,7 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None, shapesize = shapeprod * itemsize if shapesize < 0: shape = list(shape) - shape[ shape.index(-1) ] = size / -shapesize + shape[shape.index(-1)] = size / -shapesize shape = tuple(shape) shapeprod = sb.array(shape).prod() @@ -775,10 +782,9 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None, """Construct a record array from a wide-variety of objects. """ - if (isinstance(obj, (type(None), str)) or isfileobj(obj)) \ - and (formats is None) \ - and (dtype is None): - raise ValueError("Must define formats (or dtype) if object is "\ + if ((isinstance(obj, (type(None), str)) or isfileobj(obj)) and + (formats is None) and (dtype is None)): + raise ValueError("Must define formats (or dtype) if object is " "None, string, or an open file") kwds = {} @@ -789,10 +795,10 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None, aligned, byteorder)._descr else: kwds = {'formats': formats, - 'names' : names, - 'titles' : titles, - 'aligned' : aligned, - 'byteorder' : byteorder + 'names': names, + 'titles': titles, + 'aligned': aligned, + 'byteorder': byteorder } if obj is None: @@ -828,10 +834,7 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None, new = obj if copy: new = new.copy() - res = new.view(recarray) - if issubclass(res.dtype.type, nt.void): - res.dtype = sb.dtype((record, res.dtype)) - return res + return new.view(recarray) else: interface = getattr(obj, "__array_interface__", None) @@ -840,7 +843,4 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None, obj = sb.array(obj) if dtype is not None and (obj.dtype != dtype): obj = obj.view(dtype) - res = obj.view(recarray) - if issubclass(res.dtype.type, nt.void): - res.dtype = sb.dtype((record, res.dtype)) - return res + return obj.view(recarray) diff --git a/numpy/core/setup.py b/numpy/core/setup.py index 7f0649158..361bf9082 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -3,15 +3,15 @@ from __future__ import division, print_function import imp import os import sys -import shutil import pickle import copy import warnings -import re from os.path import join from numpy.distutils import log from distutils.dep_util import newer from distutils.sysconfig import get_config_var +from numpy._build_utils.apple_accelerate import (uses_accelerate_framework, + get_sgemv_fix) from setup_common import * @@ -246,7 +246,7 @@ def check_ieee_macros(config): # Note: including Python.h is necessary because it modifies some math.h # definitions for f in macros: - st = config.check_decl(f, headers = ["Python.h", "math.h"]) + st = config.check_decl(f, headers=["Python.h", "math.h"]) if st: _add_decl(f) @@ -275,7 +275,7 @@ def check_types(config_cmd, ext, build_dir): result = config_cmd.check_header('Python.h') if not result: raise SystemError( - "Cannot compile 'Python.h'. Perhaps you need to "\ + "Cannot compile 'Python.h'. Perhaps you need to " "install python-dev|python-devel.") res = config_cmd.check_header("endian.h") if res: @@ -284,7 +284,7 @@ def check_types(config_cmd, ext, build_dir): # Check basic types sizes for type in ('short', 'int', 'long'): - res = config_cmd.check_decl("SIZEOF_%s" % sym2def(type), headers = ["Python.h"]) + res = config_cmd.check_decl("SIZEOF_%s" % sym2def(type), headers=["Python.h"]) if res: public_defines.append(('NPY_SIZEOF_%s' % sym2def(type), "SIZEOF_%s" % sym2def(type))) else: @@ -296,7 +296,7 @@ def check_types(config_cmd, ext, build_dir): for type in ('float', 'double', 'long double'): already_declared = config_cmd.check_decl("SIZEOF_%s" % sym2def(type), - headers = ["Python.h"]) + headers=["Python.h"]) res = config_cmd.check_type_size(type, expected=expected[type]) if res >= 0: public_defines.append(('NPY_SIZEOF_%s' % sym2def(type), '%d' % res)) @@ -316,7 +316,6 @@ def check_types(config_cmd, ext, build_dir): else: raise SystemError("Checking sizeof (%s) failed !" % complex_def) - for type in ('Py_intptr_t', 'off_t'): res = config_cmd.check_type_size(type, headers=["Python.h"], library_dirs=[pythonlib_dir()], @@ -349,7 +348,7 @@ def check_types(config_cmd, ext, build_dir): if not config_cmd.check_decl('CHAR_BIT', headers=['Python.h']): raise RuntimeError( - "Config wo CHAR_BIT is not supported"\ + "Config wo CHAR_BIT is not supported" ", please contact the maintainers") return private_defines, public_defines @@ -381,7 +380,7 @@ def visibility_define(config): def configuration(parent_package='',top_path=None): from numpy.distutils.misc_util import Configuration, dot_join - from numpy.distutils.system_info import get_info, default_lib_dirs + from numpy.distutils.system_info import get_info config = Configuration('core', parent_package, top_path) local_dir = config.local_path @@ -400,7 +399,7 @@ def configuration(parent_package='',top_path=None): open(generate_umath_py, 'U'), generate_umath_py, ('.py', 'U', 1)) - header_dir = 'include/numpy' # this is relative to config.path_in_package + header_dir = 'include/numpy' # this is relative to config.path_in_package cocache = CallOnceOnly() @@ -430,7 +429,7 @@ def configuration(parent_package='',top_path=None): moredefs.append('__NPY_PRIVATE_NO_SIGNAL') # Windows checks - if sys.platform=='win32' or os.name=='nt': + if sys.platform == 'win32' or os.name == 'nt': win32_checks(moredefs) # C99 restrict keyword @@ -557,7 +556,7 @@ def configuration(parent_package='',top_path=None): moredefs.append(('NPY_RELAXED_STRIDES_CHECKING', 1)) # Check wether we can use inttypes (C99) formats - if config_cmd.check_decl('PRIdPTR', headers = ['inttypes.h']): + if config_cmd.check_decl('PRIdPTR', headers=['inttypes.h']): moredefs.append(('NPY_USE_C99_FORMATS', 1)) # visibility check @@ -644,7 +643,7 @@ def configuration(parent_package='',top_path=None): # generate_numpyconfig_h as sources *before* adding npymath. config.add_extension('_dummy', - sources = [join('src', 'dummymodule.c'), + sources=[join('src', 'dummymodule.c'), generate_config_h, generate_numpyconfig_h, generate_numpy_api] @@ -655,6 +654,7 @@ def configuration(parent_package='',top_path=None): ####################################################################### subst_dict = dict([("sep", os.path.sep), ("pkgname", "numpy.core")]) + def get_mathlib_info(*args): # Another ugly hack: the mathlib info is known once build_src is run, # but we cannot use add_installed_pkg_config here either, so we only @@ -677,7 +677,8 @@ def configuration(parent_package='',top_path=None): npymath_sources = [join('src', 'npymath', 'npy_math.c.src'), join('src', 'npymath', 'ieee754.c.src'), join('src', 'npymath', 'npy_math_complex.c.src'), - join('src', 'npymath', 'halffloat.c')] + join('src', 'npymath', 'halffloat.c') + ] config.add_installed_library('npymath', sources=npymath_sources + [get_mathlib_info], install_dir='lib') @@ -691,19 +692,18 @@ def configuration(parent_package='',top_path=None): ####################################################################### # This library is created for the build but it is not installed - npysort_sources=[join('src', 'npysort', 'quicksort.c.src'), - join('src', 'npysort', 'mergesort.c.src'), - join('src', 'npysort', 'heapsort.c.src'), - join('src', 'private', 'npy_partition.h.src'), - join('src', 'npysort', 'selection.c.src'), - join('src', 'private', 'npy_binsearch.h.src'), - join('src', 'npysort', 'binsearch.c.src'), - ] + npysort_sources = [join('src', 'npysort', 'quicksort.c.src'), + join('src', 'npysort', 'mergesort.c.src'), + join('src', 'npysort', 'heapsort.c.src'), + join('src', 'private', 'npy_partition.h.src'), + join('src', 'npysort', 'selection.c.src'), + join('src', 'private', 'npy_binsearch.h.src'), + join('src', 'npysort', 'binsearch.c.src'), + ] config.add_library('npysort', sources=npysort_sources, include_dirs=[]) - ####################################################################### # multiarray module # ####################################################################### @@ -720,7 +720,8 @@ def configuration(parent_package='',top_path=None): join(local_dir, subpath, 'nditer_templ.c.src'), join(local_dir, subpath, 'lowlevel_strided_loops.c.src'), join(local_dir, subpath, 'einsum.c.src'), - join(local_dir, 'src', 'private', 'templ_common.h.src')] + join(local_dir, 'src', 'private', 'templ_common.h.src') + ] # numpy.distutils generate .c from .c.src in weird directories, we have # to add them there as they depend on the build_dir @@ -735,6 +736,7 @@ def configuration(parent_package='',top_path=None): join('src', 'multiarray', 'array_assign.h'), join('src', 'multiarray', 'buffer.h'), join('src', 'multiarray', 'calculation.h'), + join('src', 'multiarray', 'cblasfuncs.h'), join('src', 'multiarray', 'common.h'), join('src', 'multiarray', 'convert_datatype.h'), join('src', 'multiarray', 'convert.h'), @@ -758,8 +760,11 @@ def configuration(parent_package='',top_path=None): join('src', 'multiarray', 'ucsnarrow.h'), join('src', 'multiarray', 'usertypes.h'), join('src', 'multiarray', 'vdot.h'), + join('src', 'private', 'npy_config.h'), join('src', 'private', 'templ_common.h.src'), join('src', 'private', 'lowlevel_strided_loops.h'), + join('src', 'private', 'mem_overlap.h'), + join('src', 'private', 'npy_extint128.h'), join('include', 'numpy', 'arrayobject.h'), join('include', 'numpy', '_neighborhood_iterator_imp.h'), join('include', 'numpy', 'npy_endian.h'), @@ -829,14 +834,19 @@ def configuration(parent_package='',top_path=None): join('src', 'multiarray', 'ucsnarrow.c'), join('src', 'multiarray', 'vdot.c'), join('src', 'private', 'templ_common.h.src'), + join('src', 'private', 'mem_overlap.c'), ] blas_info = get_info('blas_opt', 0) - if blas_info and ('HAVE_CBLAS', None) in blas_info.get('define_macros', []): + if blas_info and ('HAVE_CBLAS', None) in blas_info.get('define_macros', []): extra_info = blas_info + # These files are also in MANIFEST.in so that they are always in + # the source distribution independently of HAVE_CBLAS. multiarray_src.extend([join('src', 'multiarray', 'cblasfuncs.c'), join('src', 'multiarray', 'python_xerbla.c'), - ]) + ]) + if uses_accelerate_framework(blas_info): + multiarray_src.extend(get_sgemv_fix()) else: extra_info = {} @@ -845,7 +855,6 @@ def configuration(parent_package='',top_path=None): multiarray_src = [join('src', 'multiarray', 'multiarraymodule_onefile.c')] multiarray_src.append(generate_multiarray_templated_sources) - config.add_extension('multiarray', sources=multiarray_src + [generate_config_h, @@ -881,7 +890,6 @@ def configuration(parent_package='',top_path=None): cmd.ensure_finalized() cmd.template_sources(sources, ext) - def generate_umath_c(ext, build_dir): target = join(build_dir, header_dir, '__umath_generated.c') dir = os.path.dirname(target) @@ -922,50 +930,52 @@ def configuration(parent_package='',top_path=None): umath_src.append(join('src', 'umath', 'simd.inc.src')) config.add_extension('umath', - sources = umath_src + + sources=umath_src + [generate_config_h, generate_numpyconfig_h, generate_umath_c, generate_ufunc_api], - depends = deps + umath_deps, - libraries = ['npymath'], + depends=deps + umath_deps, + libraries=['npymath'], ) - ####################################################################### # umath_tests module # ####################################################################### config.add_extension('umath_tests', - sources = [join('src', 'umath', 'umath_tests.c.src')]) + sources=[join('src', 'umath', 'umath_tests.c.src')]) ####################################################################### # custom rational dtype module # ####################################################################### config.add_extension('test_rational', - sources = [join('src', 'umath', 'test_rational.c.src')]) + sources=[join('src', 'umath', 'test_rational.c.src')]) ####################################################################### # struct_ufunc_test module # ####################################################################### config.add_extension('struct_ufunc_test', - sources = [join('src', 'umath', 'struct_ufunc_test.c.src')]) + sources=[join('src', 'umath', 'struct_ufunc_test.c.src')]) ####################################################################### # multiarray_tests module # ####################################################################### config.add_extension('multiarray_tests', - sources = [join('src', 'multiarray', 'multiarray_tests.c.src')]) + sources=[join('src', 'multiarray', 'multiarray_tests.c.src'), + join('src', 'private', 'mem_overlap.c')], + depends=[join('src', 'private', 'mem_overlap.h'), + join('src', 'private', 'npy_extint128.h')]) ####################################################################### # operand_flag_tests module # ####################################################################### config.add_extension('operand_flag_tests', - sources = [join('src', 'umath', 'operand_flag_tests.c.src')]) + sources=[join('src', 'umath', 'operand_flag_tests.c.src')]) config.add_data_dir('tests') config.add_data_dir('tests/data') @@ -974,6 +984,6 @@ def configuration(parent_package='',top_path=None): return config -if __name__=='__main__': +if __name__ == '__main__': from numpy.distutils.core import setup setup(configuration=configuration) diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index 6abbe5ff2..68efd1791 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -2,12 +2,12 @@ from __future__ import division, absolute_import, print_function # Code common to build tools import sys -from os.path import join import warnings import copy import binascii -from distutils.ccompiler import CompileError +from numpy.distutils.misc_util import mingw32 + #------------------- # Versioning support @@ -35,7 +35,8 @@ C_ABI_VERSION = 0x01000009 # 0x00000008 - 1.7.x # 0x00000009 - 1.8.x # 0x00000009 - 1.9.x -C_API_VERSION = 0x00000009 +# 0x0000000a - 1.10.x +C_API_VERSION = 0x0000000a class MismatchCAPIWarning(Warning): pass @@ -53,11 +54,13 @@ def is_released(config): return True def get_api_versions(apiversion, codegen_dir): - """Return current C API checksum and the recorded checksum for the given - version of the C API version.""" - api_files = [join(codegen_dir, 'numpy_api_order.txt'), - join(codegen_dir, 'ufunc_api_order.txt')] + """ + Return current C API checksum and the recorded checksum. + + Return current C API checksum and the recorded checksum for the given + version of the C API version. + """ # Compute the hash of the current API as defined in the .txt files in # code_generators sys.path.insert(0, codegen_dir) @@ -82,11 +85,12 @@ def check_api_version(apiversion, codegen_dir): # To compute the checksum of the current API, use # code_generators/cversions.py script if not curapi_hash == api_hash: - msg = "API mismatch detected, the C API version " \ - "numbers have to be updated. Current C api version is %d, " \ - "with checksum %s, but recorded checksum for C API version %d in " \ - "codegen_dir/cversions.txt is %s. If functions were added in the " \ - "C API, you have to update C_API_VERSION in %s." + msg = ("API mismatch detected, the C API version " + "numbers have to be updated. Current C api version is %d, " + "with checksum %s, but recorded checksum for C API version %d in " + "codegen_dir/cversions.txt is %s. If functions were added in the " + "C API, you have to update C_API_VERSION in %s." + ) warnings.warn(msg % (apiversion, curapi_hash, apiversion, api_hash, __file__), MismatchCAPIWarning) @@ -100,13 +104,13 @@ MANDATORY_FUNCS = ["sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", OPTIONAL_STDFUNCS = ["expm1", "log1p", "acosh", "asinh", "atanh", "rint", "trunc", "exp2", "log2", "hypot", "atan2", "pow", "copysign", "nextafter", "ftello", "fseeko", - "strtoll", "strtoull", "cbrt"] + "strtoll", "strtoull", "cbrt", "strtold_l",] OPTIONAL_HEADERS = [ # sse headers only enabled automatically on amd64/x32 builds - "xmmintrin.h", # SSE - "emmintrin.h", # SSE2 + "xmmintrin.h", # SSE + "emmintrin.h", # SSE2 "features.h", # for glibc version linux ] @@ -120,8 +124,8 @@ OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'), ("__builtin_bswap64", '5u'), ("__builtin_expect", '5, 0'), ("__builtin_mul_overflow", '5, 5, (int*)5'), - ("_mm_load_ps", '(float*)0', "xmmintrin.h"), # SSE - ("_mm_load_pd", '(double*)0', "emmintrin.h"), # SSE2 + ("_mm_load_ps", '(float*)0', "xmmintrin.h"), # SSE + ("_mm_load_pd", '(double*)0', "emmintrin.h"), # SSE2 ] # function attributes @@ -133,7 +137,7 @@ OPTIONAL_FUNCTION_ATTRIBUTES = [('__attribute__((optimize("unroll-loops")))', 'attribute_optimize_opt_3'), ('__attribute__((nonnull (1)))', 'attribute_nonnull'), - ] + ] # variable attributes tested via "int %s a" % attribute OPTIONAL_VARIABLE_ATTRIBUTES = ["__thread", "__declspec(thread)"] @@ -179,6 +183,15 @@ def check_long_double_representation(cmd): cmd._check_compiler() body = LONG_DOUBLE_REPRESENTATION_SRC % {'type': 'long double'} + # Disable whole program optimization (the default on vs2015, with python 3.5+) + # which generates intermediary object files and prevents checking the + # float representation. + if sys.platform == "win32" and not mingw32(): + try: + cmd.compiler.compile_options.remove("/GL") + except ValueError: + pass + # We need to use _compile because we need the object filename src, obj = cmd._compile(body, None, None, 'c') try: @@ -281,10 +294,10 @@ _MOTOROLA_EXTENDED_12B = ['300', '031', '000', '000', '353', '171', _IEEE_QUAD_PREC_BE = ['300', '031', '326', '363', '105', '100', '000', '000', '000', '000', '000', '000', '000', '000', '000', '000'] _IEEE_QUAD_PREC_LE = _IEEE_QUAD_PREC_BE[::-1] -_DOUBLE_DOUBLE_BE = ['301', '235', '157', '064', '124', '000', '000', '000'] + \ - ['000'] * 8 -_DOUBLE_DOUBLE_LE = ['000', '000', '000', '124', '064', '157', '235', '301'] + \ - ['000'] * 8 +_DOUBLE_DOUBLE_BE = (['301', '235', '157', '064', '124', '000', '000', '000'] + + ['000'] * 8) +_DOUBLE_DOUBLE_LE = (['000', '000', '000', '124', '064', '157', '235', '301'] + + ['000'] * 8) def long_double_representation(lines): """Given a binary dump as given by GNU od -b, look for long double diff --git a/numpy/core/shape_base.py b/numpy/core/shape_base.py index ae684fb42..0dd2e164a 100644 --- a/numpy/core/shape_base.py +++ b/numpy/core/shape_base.py @@ -1,9 +1,10 @@ from __future__ import division, absolute_import, print_function -__all__ = ['atleast_1d', 'atleast_2d', 'atleast_3d', 'vstack', 'hstack'] +__all__ = ['atleast_1d', 'atleast_2d', 'atleast_3d', 'vstack', 'hstack', + 'stack'] from . import numeric as _nx -from .numeric import array, asanyarray, newaxis +from .numeric import asanyarray, newaxis def atleast_1d(*arys): """ @@ -47,9 +48,9 @@ def atleast_1d(*arys): res = [] for ary in arys: ary = asanyarray(ary) - if len(ary.shape) == 0 : + if len(ary.shape) == 0: result = ary.reshape(1) - else : + else: result = ary res.append(result) if len(res) == 1: @@ -97,11 +98,11 @@ def atleast_2d(*arys): res = [] for ary in arys: ary = asanyarray(ary) - if len(ary.shape) == 0 : + if len(ary.shape) == 0: result = ary.reshape(1, 1) - elif len(ary.shape) == 1 : + elif len(ary.shape) == 1: result = ary[newaxis,:] - else : + else: result = ary res.append(result) if len(res) == 1: @@ -196,9 +197,10 @@ def vstack(tup): See Also -------- + stack : Join a sequence of arrays along a new axis. hstack : Stack arrays in sequence horizontally (column wise). dstack : Stack arrays in sequence depth wise (along third dimension). - concatenate : Join a sequence of arrays together. + concatenate : Join a sequence of arrays along an existing axis. vsplit : Split array into a list of multiple sub-arrays vertically. Notes @@ -246,9 +248,10 @@ def hstack(tup): See Also -------- + stack : Join a sequence of arrays along a new axis. vstack : Stack arrays in sequence vertically (row wise). dstack : Stack arrays in sequence depth wise (along third axis). - concatenate : Join a sequence of arrays together. + concatenate : Join a sequence of arrays along an existing axis. hsplit : Split array along second axis. Notes @@ -275,3 +278,73 @@ def hstack(tup): return _nx.concatenate(arrs, 0) else: return _nx.concatenate(arrs, 1) + +def stack(arrays, axis=0): + """ + Join a sequence of arrays along a new axis. + + The `axis` parameter specifies the index of the new axis in the dimensions + of the result. For example, if ``axis=0`` it will be the first dimension + and if ``axis=-1`` it will be the last dimension. + + .. versionadded:: 1.10.0 + + Parameters + ---------- + arrays : sequence of array_like + Each array must have the same shape. + axis : int, optional + The axis in the result array along which the input arrays are stacked. + + Returns + ------- + stacked : ndarray + The stacked array has one more dimension than the input arrays. + + See Also + -------- + concatenate : Join a sequence of arrays along an existing axis. + split : Split array into a list of multiple sub-arrays of equal size. + + Examples + -------- + >>> arrays = [np.random.randn(3, 4) for _ in range(10)] + >>> np.stack(arrays, axis=0).shape + (10, 3, 4) + + >>> np.stack(arrays, axis=1).shape + (3, 10, 4) + + >>> np.stack(arrays, axis=2).shape + (3, 4, 10) + + >>> a = np.array([1, 2, 3]) + >>> b = np.array([2, 3, 4]) + >>> np.stack((a, b)) + array([[1, 2, 3], + [2, 3, 4]]) + + >>> np.stack((a, b), axis=-1) + array([[1, 2], + [2, 3], + [3, 4]]) + + """ + arrays = [asanyarray(arr) for arr in arrays] + if not arrays: + raise ValueError('need at least one array to stack') + + shapes = set(arr.shape for arr in arrays) + if len(shapes) != 1: + raise ValueError('all input arrays must have the same shape') + + result_ndim = arrays[0].ndim + 1 + if not -result_ndim <= axis < result_ndim: + msg = 'axis {0} out of bounds [-{1}, {1})'.format(axis, result_ndim) + raise IndexError(msg) + if axis < 0: + axis += result_ndim + + sl = (slice(None),) * axis + (_nx.newaxis,) + expanded_arrays = [arr[sl] for arr in arrays] + return _nx.concatenate(expanded_arrays, axis=axis) diff --git a/numpy/core/src/multiarray/array_assign.c b/numpy/core/src/multiarray/array_assign.c index fa764d758..a48e245d8 100644 --- a/numpy/core/src/multiarray/array_assign.c +++ b/numpy/core/src/multiarray/array_assign.c @@ -23,6 +23,7 @@ #include "array_assign.h" #include "common.h" #include "lowlevel_strided_loops.h" +#include "mem_overlap.h" /* See array_assign.h for parameter documentation */ NPY_NO_EXPORT int @@ -101,27 +102,17 @@ raw_array_is_aligned(int ndim, char *data, npy_intp *strides, int alignment) } -/* Gets a half-open range [start, end) which contains the array data */ -NPY_NO_EXPORT void -get_array_memory_extents(PyArrayObject *arr, - npy_uintp *out_start, npy_uintp *out_end) -{ - npy_intp low, upper; - offset_bounds_from_strides(PyArray_ITEMSIZE(arr), PyArray_NDIM(arr), - PyArray_DIMS(arr), PyArray_STRIDES(arr), - &low, &upper); - *out_start = (npy_uintp)PyArray_DATA(arr) + (npy_uintp)low; - *out_end = (npy_uintp)PyArray_DATA(arr) + (npy_uintp)upper; -} - /* Returns 1 if the arrays have overlapping data, 0 otherwise */ NPY_NO_EXPORT int arrays_overlap(PyArrayObject *arr1, PyArrayObject *arr2) { - npy_uintp start1 = 0, start2 = 0, end1 = 0, end2 = 0; - - get_array_memory_extents(arr1, &start1, &end1); - get_array_memory_extents(arr2, &start2, &end2); + mem_overlap_t result; - return (start1 < end2) && (start2 < end1); + result = solve_may_share_memory(arr1, arr2, NPY_MAY_SHARE_BOUNDS); + if (result == MEM_OVERLAP_NO) { + return 0; + } + else { + return 1; + } } diff --git a/numpy/core/src/multiarray/arrayobject.c b/numpy/core/src/multiarray/arrayobject.c index 6e48ef381..fd5b15a0a 100644 --- a/numpy/core/src/multiarray/arrayobject.c +++ b/numpy/core/src/multiarray/arrayobject.c @@ -51,6 +51,7 @@ maintainer email: oliphant.travis@ieee.org #include "buffer.h" #include "array_assign.h" #include "alloc.h" +#include "mem_overlap.h" /*NUMPY_API Compute the size of an array (in number of items) @@ -738,6 +739,7 @@ array_might_be_written(PyArrayObject *obj) "The quick fix is to make an explicit copy (e.g., do\n" "arr.diagonal().copy() or arr[['f0','f1']].copy())."; if (PyArray_FLAGS(obj) & NPY_ARRAY_WARN_ON_WRITE) { + /* 2012-07-17, 1.7 */ if (DEPRECATE_FUTUREWARNING(msg) < 0) { return -1; } @@ -1295,9 +1297,40 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) PyObject *obj_self = (PyObject *)self; PyObject *result = NULL; + /* Special case for string arrays (which don't and currently can't have + * ufunc loops defined, so there's no point in trying). + */ + if (PyArray_ISSTRING(self)) { + array_other = (PyArrayObject *)PyArray_FromObject(other, + NPY_NOTYPE, 0, 0); + if (array_other == NULL) { + PyErr_Clear(); + /* Never mind, carry on, see what happens */ + } + else if (!PyArray_ISSTRING(array_other)) { + Py_DECREF(array_other); + /* Never mind, carry on, see what happens */ + } + else { + result = _strings_richcompare(self, array_other, cmp_op, 0); + Py_DECREF(array_other); + return result; + } + /* If we reach this point, it means that we are not comparing + * string-to-string. It's possible that this will still work out, + * e.g. if the other array is an object array, then both will be cast + * to object or something? I don't know how that works actually, but + * it does, b/c this works: + * l = ["a", "b"] + * assert np.array(l, dtype="S1") == np.array(l, dtype="O") + * So we fall through and see what happens. + */ + } + switch (cmp_op) { case Py_LT: - if (needs_right_binop_forward(obj_self, other, "__gt__", 0)) { + if (needs_right_binop_forward(obj_self, other, "__gt__", 0) && + Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) { /* See discussion in number.c */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; @@ -1306,7 +1339,8 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) n_ops.less); break; case Py_LE: - if (needs_right_binop_forward(obj_self, other, "__ge__", 0)) { + if (needs_right_binop_forward(obj_self, other, "__ge__", 0) && + Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1315,6 +1349,7 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) break; case Py_EQ: if (other == Py_None) { + /* 2013-07-25, 1.7 */ if (DEPRECATE_FUTUREWARNING("comparison to `None` will result in " "an elementwise object comparison in the future.") < 0) { return NULL; @@ -1322,15 +1357,6 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) Py_INCREF(Py_False); return Py_False; } - if (needs_right_binop_forward(obj_self, other, "__eq__", 0)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - result = PyArray_GenericBinaryFunction(self, - (PyObject *)other, - n_ops.equal); - if (result && result != Py_NotImplemented) - break; /* * The ufunc does not support void/structured types, so these @@ -1347,7 +1373,13 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) * this way. */ if (array_other == NULL) { + /* 2015-05-07, 1.10 */ PyErr_Clear(); + if (DEPRECATE( + "elementwise == comparison failed and returning scalar " + "instead; this will raise an error in the future.") < 0) { + return NULL; + } Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1356,18 +1388,32 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) PyArray_DESCR(array_other), NPY_EQUIV_CASTING); if (_res == 0) { - Py_DECREF(result); + /* 2015-05-07, 1.10 */ Py_DECREF(array_other); + if (DEPRECATE_FUTUREWARNING( + "elementwise == comparison failed and returning scalar " + "instead; this will raise an error or perform " + "elementwise comparison in the future.") < 0) { + return NULL; + } Py_INCREF(Py_False); return Py_False; } else { - Py_DECREF(result); result = _void_compare(self, array_other, cmp_op); } Py_DECREF(array_other); return result; } + + if (needs_right_binop_forward(obj_self, other, "__eq__", 0) && + Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + result = PyArray_GenericBinaryFunction(self, + (PyObject *)other, + n_ops.equal); /* * If the comparison results in NULL, then the * two array objects can not be compared together; @@ -1378,9 +1424,10 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) * Comparisons should raise errors when element-wise comparison * is not possible. */ + /* 2015-05-14, 1.10 */ PyErr_Clear(); - if (DEPRECATE("elementwise comparison failed; " - "this will raise the error in the future.") < 0) { + if (DEPRECATE("elementwise == comparison failed; " + "this will raise an error in the future.") < 0) { return NULL; } @@ -1390,6 +1437,7 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) break; case Py_NE: if (other == Py_None) { + /* 2013-07-25, 1.8 */ if (DEPRECATE_FUTUREWARNING("comparison to `None` will result in " "an elementwise object comparison in the future.") < 0) { return NULL; @@ -1397,14 +1445,6 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) Py_INCREF(Py_True); return Py_True; } - if (needs_right_binop_forward(obj_self, other, "__ne__", 0)) { - Py_INCREF(Py_NotImplemented); - return Py_NotImplemented; - } - result = PyArray_GenericBinaryFunction(self, (PyObject *)other, - n_ops.not_equal); - if (result && result != Py_NotImplemented) - break; /* * The ufunc does not support void/structured types, so these @@ -1421,7 +1461,13 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) * this way. */ if (array_other == NULL) { + /* 2015-05-07, 1.10 */ PyErr_Clear(); + if (DEPRECATE( + "elementwise != comparison failed and returning scalar " + "instead; this will raise an error in the future.") < 0) { + return NULL; + } Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1430,27 +1476,40 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) PyArray_DESCR(array_other), NPY_EQUIV_CASTING); if (_res == 0) { - Py_DECREF(result); + /* 2015-05-07, 1.10 */ Py_DECREF(array_other); + if (DEPRECATE_FUTUREWARNING( + "elementwise != comparison failed and returning scalar " + "instead; this will raise an error or perform " + "elementwise comparison in the future.") < 0) { + return NULL; + } Py_INCREF(Py_True); return Py_True; } else { - Py_DECREF(result); result = _void_compare(self, array_other, cmp_op); Py_DECREF(array_other); } return result; } + if (needs_right_binop_forward(obj_self, other, "__ne__", 0) && + Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + result = PyArray_GenericBinaryFunction(self, (PyObject *)other, + n_ops.not_equal); if (result == NULL) { /* * Comparisons should raise errors when element-wise comparison * is not possible. */ + /* 2015-05-14, 1.10 */ PyErr_Clear(); - if (DEPRECATE("elementwise comparison failed; " - "this will raise the error in the future.") < 0) { + if (DEPRECATE("elementwise != comparison failed; " + "this will raise an error in the future.") < 0) { return NULL; } @@ -1459,7 +1518,8 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) } break; case Py_GT: - if (needs_right_binop_forward(obj_self, other, "__lt__", 0)) { + if (needs_right_binop_forward(obj_self, other, "__lt__", 0) && + Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1467,7 +1527,8 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) n_ops.greater); break; case Py_GE: - if (needs_right_binop_forward(obj_self, other, "__le__", 0)) { + if (needs_right_binop_forward(obj_self, other, "__le__", 0) && + Py_TYPE(obj_self)->tp_richcompare != Py_TYPE(other)->tp_richcompare) { Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } @@ -1478,24 +1539,6 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op) result = Py_NotImplemented; Py_INCREF(result); } - if (result == Py_NotImplemented) { - /* Try to handle string comparisons */ - if (PyArray_TYPE(self) == NPY_OBJECT) { - return result; - } - array_other = (PyArrayObject *)PyArray_FromObject(other, - NPY_NOTYPE, 0, 0); - if (array_other == NULL) { - PyErr_Clear(); - return result; - } - if (PyArray_ISSTRING(self) && PyArray_ISSTRING(array_other)) { - Py_DECREF(result); - result = _strings_richcompare(self, (PyArrayObject *) - array_other, cmp_op, 0); - } - Py_DECREF(array_other); - } return result; } @@ -1769,7 +1812,11 @@ NPY_NO_EXPORT PyTypeObject PyArray_Type = { &array_as_number, /* tp_as_number */ &array_as_sequence, /* tp_as_sequence */ &array_as_mapping, /* tp_as_mapping */ - PyObject_HashNotImplemented, /* tp_hash */ + /* + * The tp_hash slot will be set PyObject_HashNotImplemented when the + * module is loaded. + */ + (hashfunc)0, /* tp_hash */ (ternaryfunc)0, /* tp_call */ (reprfunc)array_str, /* tp_str */ (getattrofunc)0, /* tp_getattro */ @@ -1780,7 +1827,7 @@ NPY_NO_EXPORT PyTypeObject PyArray_Type = { | Py_TPFLAGS_CHECKTYPES | Py_TPFLAGS_HAVE_NEWBUFFER #endif - | Py_TPFLAGS_BASETYPE), /* tp_flags */ + | Py_TPFLAGS_BASETYPE), /* tp_flags */ 0, /* tp_doc */ (traverseproc)0, /* tp_traverse */ diff --git a/numpy/core/src/multiarray/arraytypes.c.src b/numpy/core/src/multiarray/arraytypes.c.src index 8287c2268..68944a1bd 100644 --- a/numpy/core/src/multiarray/arraytypes.c.src +++ b/numpy/core/src/multiarray/arraytypes.c.src @@ -33,7 +33,6 @@ #include "npy_cblas.h" #include <limits.h> - /* ***************************************************************************** ** PYTHON TYPES TO C TYPES ** @@ -170,7 +169,10 @@ npy_strtoull(const char *str, char **endptr, int base) * LongLong, ULongLong, Half, Float, Double# */ static PyObject * -@TYPE@_getitem(char *ip, PyArrayObject *ap) { +@TYPE@_getitem(void *input, void *vap) +{ + PyArrayObject *ap = vap; + char *ip = input; @type@ t1; if ((ap == NULL) || PyArray_ISBEHAVED_RO(ap)) { @@ -184,7 +186,9 @@ static PyObject * } static int -@TYPE@_setitem(PyObject *op, char *ov, PyArrayObject *ap) { +@TYPE@_setitem(PyObject *op, void *ov, void *vap) +{ + PyArrayObject *ap = vap; @type@ temp; /* ensures alignment */ if (PyArray_IsScalar(op, @kind@)) { @@ -225,7 +229,10 @@ static int * #type = npy_float, npy_double# */ static PyObject * -@TYPE@_getitem(char *ip, PyArrayObject *ap) { +@TYPE@_getitem(void *input, void *vap) +{ + PyArrayObject *ap = vap; + char *ip = input; @type@ t1, t2; if ((ap == NULL) || PyArray_ISBEHAVED_RO(ap)) { @@ -254,8 +261,9 @@ static PyObject * * #kind = CFloat, CDouble, CLongDouble# */ static int -@NAME@_setitem(PyObject *op, char *ov, PyArrayObject *ap) +@NAME@_setitem(PyObject *op, void *ov, void *vap) { + PyArrayObject *ap = vap; Py_complex oop; PyObject *op2; @type@ temp; @@ -300,18 +308,68 @@ static int /**end repeat**/ +static NPY_INLINE npy_longdouble +string_to_long_double(PyObject*op) +{ + char *s; + char *end; + npy_longdouble temp; + PyObject* b; + + if (PyUnicode_Check(op)) { + b = PyUnicode_AsUTF8String(op); + if (!b) { + return 0; + } + } + else { + b = op; + Py_XINCREF(b); + } + s = PyBytes_AsString(b); + if (s) { + errno = 0; + temp = NumPyOS_ascii_strtold(s, &end); + if (end==s || *end) { + PyErr_Format(PyExc_ValueError, + "invalid literal for long double: %s", + s); + Py_XDECREF(b); + return 0; + } + else if (errno) { + PyErr_Format(PyExc_ValueError, + "invalid literal for long double: %s (%s)", + s, + strerror(errno)); + Py_XDECREF(b); + return 0; + } + Py_XDECREF(b); + } + else { + /* Probably wasn't a string, try converting it via a python double */ + PyErr_Clear(); + Py_XDECREF(b); + temp = (npy_longdouble) MyPyFloat_AsDouble(op); + } + return temp; +} + /* * These return array scalars which are different than other date-types. */ static PyObject * -LONGDOUBLE_getitem(char *ip, PyArrayObject *ap) +LONGDOUBLE_getitem(void *ip, void *ap) { - return PyArray_Scalar(ip, PyArray_DESCR(ap), NULL); + return PyArray_Scalar(ip, PyArray_DESCR((PyArrayObject *)ap), NULL); } static int -LONGDOUBLE_setitem(PyObject *op, char *ov, PyArrayObject *ap) { +LONGDOUBLE_setitem(PyObject *op, void *ov, void *vap) +{ + PyArrayObject *ap = vap; /* ensure alignment */ npy_longdouble temp; @@ -319,7 +377,11 @@ LONGDOUBLE_setitem(PyObject *op, char *ov, PyArrayObject *ap) { temp = ((PyLongDoubleScalarObject *)op)->obval; } else { - temp = (npy_longdouble) MyPyFloat_AsDouble(op); + /* In case something funny happened in PyArray_IsScalar */ + if (PyErr_Occurred()) { + return -1; + } + temp = string_to_long_double(op); } if (PyErr_Occurred()) { return -1; @@ -335,15 +397,16 @@ LONGDOUBLE_setitem(PyObject *op, char *ov, PyArrayObject *ap) { } static PyObject * -CLONGDOUBLE_getitem(char *ip, PyArrayObject *ap) +CLONGDOUBLE_getitem(void *ip, void *ap) { - return PyArray_Scalar(ip, PyArray_DESCR(ap), NULL); + return PyArray_Scalar(ip, PyArray_DESCR((PyArrayObject *)ap), NULL); } /* UNICODE */ static PyObject * -UNICODE_getitem(char *ip, PyArrayObject *ap) +UNICODE_getitem(void *ip, void *vap) { + PyArrayObject *ap = vap; Py_ssize_t size = PyArray_ITEMSIZE(ap); int swap = !PyArray_ISNOTSWAPPED(ap); int align = !PyArray_ISALIGNED(ap); @@ -352,8 +415,9 @@ UNICODE_getitem(char *ip, PyArrayObject *ap) } static int -UNICODE_setitem(PyObject *op, char *ov, PyArrayObject *ap) +UNICODE_setitem(PyObject *op, void *ov, void *vap) { + PyArrayObject *ap = vap; PyObject *temp; Py_UNICODE *ptr; int datalen; @@ -416,7 +480,7 @@ UNICODE_setitem(PyObject *op, char *ov, PyArrayObject *ap) #endif /* Fill in the rest of the space with 0 */ if (PyArray_DESCR(ap)->elsize > datalen) { - memset(ov + datalen, 0, (PyArray_DESCR(ap)->elsize - datalen)); + memset((char*)ov + datalen, 0, (PyArray_DESCR(ap)->elsize - datalen)); } if (!PyArray_ISNOTSWAPPED(ap)) { byte_swap_vector(ov, PyArray_DESCR(ap)->elsize >> 2, 4); @@ -431,13 +495,14 @@ UNICODE_setitem(PyObject *op, char *ov, PyArrayObject *ap) * will truncate all ending NULLs in returned string. */ static PyObject * -STRING_getitem(char *ip, PyArrayObject *ap) +STRING_getitem(void *ip, void *vap) { + PyArrayObject *ap = vap; /* Will eliminate NULLs at the end */ char *ptr; int size = PyArray_DESCR(ap)->elsize; - ptr = ip + size - 1; + ptr = (char *)ip + size - 1; while (size > 0 && *ptr-- == '\0') { size--; } @@ -445,8 +510,9 @@ STRING_getitem(char *ip, PyArrayObject *ap) } static int -STRING_setitem(PyObject *op, char *ov, PyArrayObject *ap) +STRING_setitem(PyObject *op, void *ov, void *vap) { + PyArrayObject *ap = vap; char *ptr; Py_ssize_t len; PyObject *temp = NULL; @@ -513,7 +579,7 @@ STRING_setitem(PyObject *op, char *ov, PyArrayObject *ap) * Then fill the rest of the element size with NULL */ if (PyArray_DESCR(ap)->elsize > len) { - memset(ov + len, 0, (PyArray_DESCR(ap)->elsize - len)); + memset((char *)ov + len, 0, (PyArray_DESCR(ap)->elsize - len)); } Py_DECREF(temp); return 0; @@ -524,13 +590,12 @@ STRING_setitem(PyObject *op, char *ov, PyArrayObject *ap) #define __ALIGNED(obj, sz) ((((size_t) obj) % (sz))==0) static PyObject * -OBJECT_getitem(char *ip, PyArrayObject *ap) +OBJECT_getitem(void *ip, void *NPY_UNUSED(ap)) { PyObject *obj; NPY_COPY_PYOBJECT_PTR(&obj, ip); if (obj == NULL) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } else { Py_INCREF(obj); @@ -540,7 +605,7 @@ OBJECT_getitem(char *ip, PyArrayObject *ap) static int -OBJECT_setitem(PyObject *op, char *ov, PyArrayObject *ap) +OBJECT_setitem(PyObject *op, void *ov, void *NPY_UNUSED(ap)) { PyObject *obj; @@ -582,8 +647,10 @@ unpack_field(PyObject * value, PyArray_Descr ** descr, npy_intp * offset) static PyObject * -VOID_getitem(char *ip, PyArrayObject *ap) +VOID_getitem(void *input, void *vap) { + PyArrayObject *ap = vap; + char *ip = input; PyArrayObject *u = NULL; PyArray_Descr* descr; int itemsize; @@ -713,9 +780,11 @@ VOID_getitem(char *ip, PyArrayObject *ap) NPY_NO_EXPORT int PyArray_CopyObject(PyArrayObject *, PyObject *); static int -VOID_setitem(PyObject *op, char *ip, PyArrayObject *ap) +VOID_setitem(PyObject *op, void *input, void *vap) { - PyArray_Descr* descr; + char *ip = input; + PyArrayObject *ap = vap; + PyArray_Descr *descr; int itemsize=PyArray_DESCR(ap)->elsize; int res; @@ -727,7 +796,7 @@ VOID_setitem(PyObject *op, char *ip, PyArrayObject *ap) PyObject *tup; int savedflags; - res = -1; + res = 0; /* get the names from the fields dictionary*/ names = descr->names; n = PyTuple_GET_SIZE(names); @@ -824,7 +893,9 @@ fail: } static PyObject * -DATETIME_getitem(char *ip, PyArrayObject *ap) { +DATETIME_getitem(void *ip, void *vap) +{ + PyArrayObject *ap = vap; npy_datetime dt; PyArray_DatetimeMetaData *meta = NULL; @@ -846,7 +917,9 @@ DATETIME_getitem(char *ip, PyArrayObject *ap) { static PyObject * -TIMEDELTA_getitem(char *ip, PyArrayObject *ap) { +TIMEDELTA_getitem(void *ip, void *vap) +{ + PyArrayObject *ap = vap; npy_timedelta td; PyArray_DatetimeMetaData *meta = NULL; @@ -867,7 +940,9 @@ TIMEDELTA_getitem(char *ip, PyArrayObject *ap) { } static int -DATETIME_setitem(PyObject *op, char *ov, PyArrayObject *ap) { +DATETIME_setitem(PyObject *op, void *ov, void *vap) +{ + PyArrayObject *ap = vap; /* ensure alignment */ npy_datetime temp = 0; PyArray_DatetimeMetaData *meta = NULL; @@ -897,7 +972,9 @@ DATETIME_setitem(PyObject *op, char *ov, PyArrayObject *ap) { } static int -TIMEDELTA_setitem(PyObject *op, char *ov, PyArrayObject *ap) { +TIMEDELTA_setitem(PyObject *op, void *ov, void *vap) +{ + PyArrayObject *ap = vap; /* ensure alignment */ npy_timedelta temp = 0; PyArray_DatetimeMetaData *meta = NULL; @@ -958,9 +1035,12 @@ TIMEDELTA_setitem(PyObject *op, char *ov, PyArrayObject *ap) { * npy_datetime, npy_timedelta# */ static void -@FROMTYPE@_to_@TOTYPE@(@fromtype@ *ip, @totype@ *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +@FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const @fromtype@ *ip = input; + @totype@ *op = output; + while (n--) { *op++ = (@totype@)*ip++; } @@ -973,9 +1053,12 @@ static void * #fromtype = npy_float, npy_double, npy_longdouble# */ static void -@FROMTYPE@_to_@TOTYPE@(@fromtype@ *ip, @totype@ *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +@FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const @fromtype@ *ip = input; + @totype@ *op = output; + while (n--) { *op++ = (@totype@)*ip; ip += 2; @@ -998,18 +1081,24 @@ static void */ static void -@TYPE@_to_HALF(@type@ *ip, npy_half *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +@TYPE@_to_HALF(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const @type@ *ip = input; + npy_half *op = output; + while (n--) { *op++ = npy_float_to_half((float)(*ip++)); } } static void -HALF_to_@TYPE@(npy_half *ip, @type@ *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +HALF_to_@TYPE@(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const npy_half *ip = input; + @type@ *op = output; + while (n--) { *op++ = (@type@)npy_half_to_float(*ip++); } @@ -1031,9 +1120,12 @@ HALF_to_@TYPE@(npy_half *ip, @type@ *op, npy_intp n, */ static void -@TYPE@_to_HALF(@itype@ *ip, npy_half *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +@TYPE@_to_HALF(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const @itype@ *ip = input; + npy_half *op = output; + while (n--) { *op++ = npy_@name@bits_to_halfbits(*ip); #if @iscomplex@ @@ -1045,9 +1137,12 @@ static void } static void -HALF_to_@TYPE@(npy_half *ip, @itype@ *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +HALF_to_@TYPE@(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const npy_half *ip = input; + @itype@ *op = output; + while (n--) { *op++ = npy_halfbits_to_@name@bits(*ip++); #if @iscomplex@ @@ -1059,9 +1154,12 @@ HALF_to_@TYPE@(npy_half *ip, @itype@ *op, npy_intp n, /**end repeat**/ static void -CLONGDOUBLE_to_HALF(npy_longdouble *ip, npy_half *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +CLONGDOUBLE_to_HALF(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const npy_longdouble *ip = input; + npy_half *op = output; + while (n--) { *op++ = npy_double_to_half((double) (*ip++)); ip += 2; @@ -1069,9 +1167,12 @@ CLONGDOUBLE_to_HALF(npy_longdouble *ip, npy_half *op, npy_intp n, } static void -HALF_to_CLONGDOUBLE(npy_half *ip, npy_longdouble *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +HALF_to_CLONGDOUBLE(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const npy_half *ip = input; + npy_longdouble *op = output; + while (n--) { *op++ = npy_half_to_double(*ip++); *op++ = 0; @@ -1092,9 +1193,12 @@ HALF_to_CLONGDOUBLE(npy_half *ip, npy_longdouble *op, npy_intp n, * npy_datetime, npy_timedelta# */ static void -@FROMTYPE@_to_BOOL(@fromtype@ *ip, npy_bool *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +@FROMTYPE@_to_BOOL(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const @fromtype@ *ip = input; + npy_bool *op = output; + while (n--) { *op++ = (npy_bool)(*ip++ != NPY_FALSE); } @@ -1102,9 +1206,12 @@ static void /**end repeat**/ static void -HALF_to_BOOL(npy_half *ip, npy_bool *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +HALF_to_BOOL(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const npy_half *ip = input; + npy_bool *op = output; + while (n--) { *op++ = (npy_bool)(!npy_half_iszero(*ip++)); } @@ -1114,14 +1221,17 @@ HALF_to_BOOL(npy_half *ip, npy_bool *op, npy_intp n, * * #FROMTYPE = CFLOAT, CDOUBLE, CLONGDOUBLE# * #fromtype = npy_cfloat, npy_cdouble, npy_clongdouble# -*/ + */ static void -@FROMTYPE@_to_BOOL(@fromtype@ *ip, npy_bool *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +@FROMTYPE@_to_BOOL(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const @fromtype@ *ip = input; + npy_bool *op = output; + while (n--) { - *op = (npy_bool)(((*ip).real != NPY_FALSE) || - ((*ip).imag != NPY_FALSE)); + *op = (npy_bool)((ip->real != NPY_FALSE) || + (ip->imag != NPY_FALSE)); op++; ip++; } @@ -1141,9 +1251,12 @@ static void * #zero = 0*10, NPY_HALF_ZERO, 0*5# */ static void -BOOL_to_@TOTYPE@(npy_bool *ip, @totype@ *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +BOOL_to_@TOTYPE@(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const npy_bool *ip = input; + @totype@ *op = output; + while (n--) { *op++ = (@totype@)((*ip++ != NPY_FALSE) ? @one@ : @zero@); } @@ -1169,9 +1282,12 @@ BOOL_to_@TOTYPE@(npy_bool *ip, @totype@ *op, npy_intp n, * npy_datetime, npy_timedelta# */ static void -@FROMTYPE@_to_@TOTYPE@(@fromtype@ *ip, @totype@ *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +@FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const @fromtype@ *ip = input; + @totype@ *op = output; + while (n--) { *op++ = (@totype@)*ip++; *op++ = 0.0; @@ -1192,9 +1308,12 @@ static void * #fromtype = npy_float, npy_double, npy_longdouble# */ static void -@FROMTYPE@_to_@TOTYPE@(@fromtype@ *ip, @totype@ *op, npy_intp n, - PyArrayObject *NPY_UNUSED(aip), PyArrayObject *NPY_UNUSED(aop)) +@FROMTYPE@_to_@TOTYPE@(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *NPY_UNUSED(aop)) { + const @fromtype@ *ip = input; + @totype@ *op = output; + n <<= 1; while (n--) { *op++ = (@totype@)*ip++; @@ -1223,15 +1342,19 @@ static void * #skip = 1*18, PyArray_DESCR(aip)->elsize*3, 1*3# */ static void -@FROMTYPE@_to_OBJECT(@fromtype@ *ip, PyObject **op, npy_intp n, - PyArrayObject *aip, PyArrayObject *NPY_UNUSED(aop)) +@FROMTYPE@_to_OBJECT(void *input, void *output, npy_intp n, + void *vaip, void *NPY_UNUSED(aop)) { + @fromtype@ *ip = input; + PyObject **op = output; + PyArrayObject *aip = vaip; + npy_intp i; int skip = @skip@; PyObject *tmp; for (i = 0; i < n; i++, ip +=skip, op++) { tmp = *op; - *op = @FROMTYPE@_getitem((char *)ip, aip); + *op = @FROMTYPE@_getitem(ip, aip); Py_XDECREF(tmp); } } @@ -1281,18 +1404,21 @@ static void * #skip = 1*18, PyArray_DESCR(aop)->elsize*3, 1*2# */ static void -OBJECT_to_@TOTYPE@(PyObject **ip, @totype@ *op, npy_intp n, - PyArrayObject *_NPY_UNUSED@TOTYPE@(aip), PyArrayObject *aop) +OBJECT_to_@TOTYPE@(void *input, void *output, npy_intp n, + void *NPY_UNUSED(aip), void *aop) { + PyObject **ip = input; + @totype@ *op = output; + npy_intp i; int skip = @skip@; for (i = 0; i < n; i++, ip++, op += skip) { if (*ip == NULL) { - @TOTYPE@_setitem(Py_False, (char *)op, aop); + @TOTYPE@_setitem(Py_False, op, aop); } else { - @TOTYPE@_setitem(*ip, (char *)op, aop); + @TOTYPE@_setitem(*ip, op, aop); } } } @@ -1331,16 +1457,20 @@ OBJECT_to_@TOTYPE@(PyObject **ip, @totype@ *op, npy_intp n, #define IS_@from@ static void -@from@_to_@to@(@fromtyp@ *ip, @totyp@ *op, npy_intp n, PyArrayObject *aip, - PyArrayObject *aop) +@from@_to_@to@(void *input, void *output, npy_intp n, + void *vaip, void *aop) { + @fromtyp@ *ip = input; + @totyp@ *op = output; + PyArrayObject *aip = vaip; + npy_intp i; PyObject *temp = NULL, *new; int skip = PyArray_DESCR(aip)->elsize; int oskip = @oskip@; for (i = 0; i < n; i++, ip+=skip, op+=oskip) { - temp = @from@_getitem((char *)ip, aip); + temp = @from@_getitem(ip, aip); if (temp == NULL) { return; } @@ -1374,7 +1504,7 @@ static void } } - if (@to@_setitem(temp,(char *)op, aop)) { + if (@to@_setitem(temp, op, aop)) { Py_DECREF(temp); return; } @@ -1387,20 +1517,24 @@ static void #else static void -@from@_to_@to@(@fromtyp@ *ip, @totyp@ *op, npy_intp n, PyArrayObject *aip, - PyArrayObject *aop) +@from@_to_@to@(void *input, void *output, npy_intp n, + void *vaip, void *aop) { + @fromtyp@ *ip = input; + @totyp@ *op = output; + PyArrayObject *aip = vaip; + npy_intp i; PyObject *temp = NULL; int skip = PyArray_DESCR(aip)->elsize; int oskip = @oskip@; for (i = 0; i < n; i++, ip+=skip, op+=oskip) { - temp = @from@_getitem((char *)ip, aip); + temp = @from@_getitem(ip, aip); if (temp == NULL) { return; } - if (@to@_setitem(temp,(char *)op, aop)) { + if (@to@_setitem(temp, op, aop)) { Py_DECREF(temp); return; } @@ -1431,20 +1565,25 @@ static void * npy_datetime, npy_timedelta)*3# */ static void -@from@_to_@to@(@fromtyp@ *ip, @totyp@ *op, npy_intp n, PyArrayObject *aip, - PyArrayObject *aop) +@from@_to_@to@(void *input, void *output, npy_intp n, + void *vaip, void *vaop) { + @fromtyp@ *ip = input; + @totyp@ *op = output; + PyArrayObject *aip = vaip; + PyArrayObject *aop = vaop; + npy_intp i; PyObject *temp = NULL; int skip = 1; int oskip = PyArray_DESCR(aop)->elsize; for (i = 0; i < n; i++, ip += skip, op += oskip) { - temp = @from@_getitem((char *)ip, aip); + temp = @from@_getitem(ip, aip); if (temp == NULL) { Py_INCREF(Py_False); temp = Py_False; } - if (@to@_setitem(temp,(char *)op, aop)) { + if (@to@_setitem(temp, op, aop)) { Py_DECREF(temp); return; } @@ -1484,8 +1623,8 @@ static int /**end repeat**/ /**begin repeat - * #fname = FLOAT, DOUBLE, LONGDOUBLE# - * #type = npy_float, npy_double, npy_longdouble# + * #fname = FLOAT, DOUBLE# + * #type = npy_float, npy_double# */ static int @fname@_scan(FILE *fp, @type@ *ip, void *NPY_UNUSED(ignore), @@ -1501,6 +1640,18 @@ static int /**end repeat**/ static int +LONGDOUBLE_scan(FILE *fp, npy_longdouble *ip, void *NPY_UNUSED(ignore), + PyArray_Descr *NPY_UNUSED(ignored)) +{ + long double result; + int ret; + + ret = NumPyOS_ascii_ftoLf(fp, &result); + *ip = (npy_longdouble) result; + return ret; +} + +static int HALF_scan(FILE *fp, npy_half *ip, void *NPY_UNUSED(ignore), PyArray_Descr *NPY_UNUSED(ignored)) { @@ -1574,53 +1725,64 @@ BOOL_scan(FILE *fp, npy_bool *ip, void *NPY_UNUSED(ignore), * npy_longlong*2# */ static int -@fname@_fromstr(char *str, @type@ *ip, char **endptr, +@fname@_fromstr(char *str, void *ip, char **endptr, PyArray_Descr *NPY_UNUSED(ignore)) { @btype@ result; result = @func@(str, endptr, 10); - *ip = (@type@) result; + *(@type@ *)ip = result; return 0; } /**end repeat**/ /**begin repeat * - * #fname = FLOAT, DOUBLE, LONGDOUBLE# - * #type = npy_float, npy_double, npy_longdouble# + * #fname = FLOAT, DOUBLE# + * #type = npy_float, npy_double# */ static int -@fname@_fromstr(char *str, @type@ *ip, char **endptr, +@fname@_fromstr(char *str, void *ip, char **endptr, PyArray_Descr *NPY_UNUSED(ignore)) { double result; result = NumPyOS_ascii_strtod(str, endptr); - *ip = (@type@) result; + *(@type@ *)ip = result; return 0; } /**end repeat**/ static int -HALF_fromstr(char *str, npy_half *ip, char **endptr, +LONGDOUBLE_fromstr(char *str, void *ip, char **endptr, + PyArray_Descr *NPY_UNUSED(ignore)) +{ + long double result; + + result = NumPyOS_ascii_strtold(str, endptr); + *(npy_longdouble *)ip = result; + return 0; +} + +static int +HALF_fromstr(char *str, void *ip, char **endptr, PyArray_Descr *NPY_UNUSED(ignore)) { double result; result = NumPyOS_ascii_strtod(str, endptr); - *ip = npy_double_to_half(result); + *(npy_half *)ip = npy_double_to_half(result); return 0; } static int -BOOL_fromstr(char *str, npy_bool *ip, char **endptr, +BOOL_fromstr(char *str, void *ip, char **endptr, PyArray_Descr *NPY_UNUSED(ignore)) { double result; result = NumPyOS_ascii_strtod(str, endptr); - *ip = (npy_bool) (result != 0.0); + *(npy_bool *)ip = (result != 0.0); return 0; } @@ -2298,9 +2460,13 @@ STRING_nonzero (char *ip, PyArrayObject *ap) int len = PyArray_DESCR(ap)->elsize; int i; npy_bool nonz = NPY_FALSE; + npy_bool seen_null = NPY_FALSE; for (i = 0; i < len; i++) { - if (!Py_STRING_ISSPACE(*ip)) { + if (*ip == '\0') { + seen_null = NPY_TRUE; + } + else if (seen_null || !Py_STRING_ISSPACE(*ip)) { nonz = NPY_TRUE; break; } @@ -2321,6 +2487,7 @@ UNICODE_nonzero (npy_ucs4 *ip, PyArrayObject *ap) int len = PyArray_DESCR(ap)->elsize >> 2; int i; npy_bool nonz = NPY_FALSE; + npy_bool seen_null = NPY_FALSE; char *buffer = NULL; if ((!PyArray_ISNOTSWAPPED(ap)) || (!PyArray_ISALIGNED(ap))) { @@ -2336,7 +2503,10 @@ UNICODE_nonzero (npy_ucs4 *ip, PyArrayObject *ap) } for (i = 0; i < len; i++) { - if (!PyArray_UCS4_ISSPACE(*ip)) { + if (*ip == '\0') { + seen_null = NPY_TRUE; + } + else if (seen_null || !PyArray_UCS4_ISSPACE(*ip)) { nonz = NPY_TRUE; break; } @@ -2690,8 +2860,10 @@ VOID_compare(char *ip1, char *ip2, PyArrayObject *ap) PyArray_Descr *descr; PyObject *names, *key; PyObject *tup; + PyArrayObject_fields dummy_struct; + PyArrayObject *dummy = (PyArrayObject *)&dummy_struct; char *nip1, *nip2; - int i, res = 0, swap=0; + int i, res = 0, swap = 0; if (!PyArray_HASFIELDS(ap)) { return STRING_compare(ip1, ip2, ap); @@ -2703,34 +2875,29 @@ VOID_compare(char *ip1, char *ip2, PyArrayObject *ap) */ names = descr->names; for (i = 0; i < PyTuple_GET_SIZE(names); i++) { - PyArray_Descr * new; + PyArray_Descr *new; npy_intp offset; key = PyTuple_GET_ITEM(names, i); tup = PyDict_GetItem(descr->fields, key); if (unpack_field(tup, &new, &offset) < 0) { goto finish; } - /* - * TODO: temporarily modifying the array like this - * is bad coding style, should be changed. - */ - ((PyArrayObject_fields *)ap)->descr = new; - swap = PyArray_ISBYTESWAPPED(ap); + /* descr is the only field checked by compare or copyswap */ + dummy_struct.descr = new; + swap = PyArray_ISBYTESWAPPED(dummy); nip1 = ip1 + offset; nip2 = ip2 + offset; - if ((swap) || (new->alignment > 1)) { - if ((swap) || (!npy_is_aligned(nip1, new->alignment))) { + if (swap || new->alignment > 1) { + if (swap || !npy_is_aligned(nip1, new->alignment)) { /* create buffer and copy */ nip1 = npy_alloc_cache(new->elsize); if (nip1 == NULL) { goto finish; } - memcpy(nip1, ip1+offset, new->elsize); - if (swap) - new->f->copyswap(nip1, NULL, swap, ap); + new->f->copyswap(nip1, ip1 + offset, swap, dummy); } - if ((swap) || (!npy_is_aligned(nip2, new->alignment))) { - /* copy data to a buffer */ + if (swap || !npy_is_aligned(nip2, new->alignment)) { + /* create buffer and copy */ nip2 = npy_alloc_cache(new->elsize); if (nip2 == NULL) { if (nip1 != ip1 + offset) { @@ -2738,13 +2905,11 @@ VOID_compare(char *ip1, char *ip2, PyArrayObject *ap) } goto finish; } - memcpy(nip2, ip2 + offset, new->elsize); - if (swap) - new->f->copyswap(nip2, NULL, swap, ap); + new->f->copyswap(nip2, ip2 + offset, swap, dummy); } } - res = new->f->compare(nip1, nip2, ap); - if ((swap) || (new->alignment > 1)) { + res = new->f->compare(nip1, nip2, dummy); + if (swap || new->alignment > 1) { if (nip1 != ip1 + offset) { npy_free_cache(nip1, new->elsize); } @@ -2758,7 +2923,6 @@ VOID_compare(char *ip1, char *ip2, PyArrayObject *ap) } finish: - ((PyArrayObject_fields *)ap)->descr = descr; return res; } @@ -2897,18 +3061,16 @@ BOOL_argmin(npy_bool *ip, npy_intp n, npy_intp *min_ind, * #fname = BYTE, UBYTE, SHORT, USHORT, INT, UINT, * LONG, ULONG, LONGLONG, ULONGLONG, * HALF, FLOAT, DOUBLE, LONGDOUBLE, - * CFLOAT, CDOUBLE, CLONGDOUBLE, - * DATETIME, TIMEDELTA# + * CFLOAT, CDOUBLE, CLONGDOUBLE# * #type = npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint, * npy_long, npy_ulong, npy_longlong, npy_ulonglong, * npy_half, npy_float, npy_double, npy_longdouble, - * npy_float, npy_double, npy_longdouble, - * npy_datetime, npy_timedelta# - * #isfloat = 0*10, 1*7, 0*2# - * #isnan = nop*10, npy_half_isnan, npy_isnan*6, nop*2# - * #le = _LESS_THAN_OR_EQUAL*10, npy_half_le, _LESS_THAN_OR_EQUAL*8# - * #iscomplex = 0*14, 1*3, 0*2# - * #incr = ip++*14, ip+=2*3, ip++*2# + * npy_float, npy_double, npy_longdouble# + * #isfloat = 0*10, 1*7# + * #isnan = nop*10, npy_half_isnan, npy_isnan*6# + * #le = _LESS_THAN_OR_EQUAL*10, npy_half_le, _LESS_THAN_OR_EQUAL*6# + * #iscomplex = 0*14, 1*3# + * #incr = ip++*14, ip+=2*3# */ static int @fname@_argmin(@type@ *ip, npy_intp n, npy_intp *min_ind, @@ -2972,33 +3134,75 @@ static int #undef _LESS_THAN_OR_EQUAL +/**begin repeat + * + * #fname = DATETIME, TIMEDELTA# + * #type = npy_datetime, npy_timedelta# + */ static int -OBJECT_argmax(PyObject **ip, npy_intp n, npy_intp *max_ind, +@fname@_argmin(@type@ *ip, npy_intp n, npy_intp *min_ind, PyArrayObject *NPY_UNUSED(aip)) { + /* NPY_DATETIME_NAT is smaller than every other value, we skip + * it for consistency with min(). + */ npy_intp i; - PyObject *mp = ip[0]; + @type@ mp = NPY_DATETIME_NAT; - *max_ind = 0; - i = 1; - while (i < n && mp == NULL) { + i = 0; + while (i < n && mp == NPY_DATETIME_NAT) { mp = ip[i]; i++; } + if (i == n) { + /* All NaTs: return 0 */ + *min_ind = 0; + return 0; + } + *min_ind = i - 1; for (; i < n; i++) { - ip++; -#if defined(NPY_PY3K) - if (*ip != NULL && PyObject_RichCompareBool(*ip, mp, Py_GT) == 1) { -#else - if (*ip != NULL && PyObject_Compare(*ip, mp) > 0) { -#endif - mp = *ip; - *max_ind = i; + if (mp > ip[i] && ip[i] != NPY_DATETIME_NAT) { + mp = ip[i]; + *min_ind = i; } } return 0; } +/**end repeat**/ + +static int +OBJECT_argmax(PyObject **ip, npy_intp n, npy_intp *max_ind, + PyArrayObject *NPY_UNUSED(aip)) +{ + npy_intp i; + + *max_ind = 0; + /* Skip over all leading NULL entries */ + for (i = 0; i < n && ip[i] == NULL; ++i); + if (i < n) { + /* Found first non-NULL entry */ + PyObject *mp = ip[i]; + *max_ind = i; + for (i = i + 1; i < n; ++i) { + PyObject *val = ip[i]; + if (val != NULL) { + int greater_than = PyObject_RichCompareBool(val, mp, Py_GT); + + if (greater_than < 0) { + return 0; + } + if (greater_than) { + mp = val; + *max_ind = i; + } + } + } + } + + return 0; +} + /**begin repeat * * #fname = STRING, UNICODE# @@ -3033,28 +3237,33 @@ static int static int OBJECT_argmin(PyObject **ip, npy_intp n, npy_intp *min_ind, - PyArrayObject *NPY_UNUSED(aip)) + PyArrayObject *NPY_UNUSED(aip)) { npy_intp i; - PyObject *mp = ip[0]; *min_ind = 0; - i = 1; - while (i < n && mp == NULL) { - mp = ip[i]; - i++; - } - for (; i < n; i++) { - ip++; -#if defined(NPY_PY3K) - if (*ip != NULL && PyObject_RichCompareBool(mp, *ip, Py_GT) == 1) { -#else - if (*ip != NULL && PyObject_Compare(mp, *ip) > 0) { -#endif - mp = *ip; - *min_ind = i; + /* Skip over all leading NULL entries */ + for (i = 0; i < n && ip[i] == NULL; ++i); + if (i < n) { + /* Found first non-NULL entry */ + PyObject *mp = ip[i]; + *min_ind = i; + for (i = i + 1; i < n ; ++i) { + PyObject *val = ip[i]; + if (val != NULL) { + int less_than = PyObject_RichCompareBool(val, mp, Py_LT); + + if (less_than < 0) { + return 0; + } + if (less_than) { + mp = val; + *min_ind = i; + } + } } } + return 0; } @@ -3935,50 +4144,50 @@ small_correlate(const char * d_, npy_intp dstride, */ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = { { - (PyArray_VectorUnaryFunc*)@from@_to_BOOL, - (PyArray_VectorUnaryFunc*)@from@_to_BYTE, - (PyArray_VectorUnaryFunc*)@from@_to_UBYTE, - (PyArray_VectorUnaryFunc*)@from@_to_SHORT, - (PyArray_VectorUnaryFunc*)@from@_to_USHORT, - (PyArray_VectorUnaryFunc*)@from@_to_INT, - (PyArray_VectorUnaryFunc*)@from@_to_UINT, - (PyArray_VectorUnaryFunc*)@from@_to_LONG, - (PyArray_VectorUnaryFunc*)@from@_to_ULONG, - (PyArray_VectorUnaryFunc*)@from@_to_LONGLONG, - (PyArray_VectorUnaryFunc*)@from@_to_ULONGLONG, - (PyArray_VectorUnaryFunc*)@from@_to_FLOAT, - (PyArray_VectorUnaryFunc*)@from@_to_DOUBLE, - (PyArray_VectorUnaryFunc*)@from@_to_LONGDOUBLE, - (PyArray_VectorUnaryFunc*)@from@_to_CFLOAT, - (PyArray_VectorUnaryFunc*)@from@_to_CDOUBLE, - (PyArray_VectorUnaryFunc*)@from@_to_CLONGDOUBLE, - (PyArray_VectorUnaryFunc*)@from@_to_OBJECT, - (PyArray_VectorUnaryFunc*)@from@_to_STRING, - (PyArray_VectorUnaryFunc*)@from@_to_UNICODE, - (PyArray_VectorUnaryFunc*)@from@_to_VOID + @from@_to_BOOL, + @from@_to_BYTE, + @from@_to_UBYTE, + @from@_to_SHORT, + @from@_to_USHORT, + @from@_to_INT, + @from@_to_UINT, + @from@_to_LONG, + @from@_to_ULONG, + @from@_to_LONGLONG, + @from@_to_ULONGLONG, + @from@_to_FLOAT, + @from@_to_DOUBLE, + @from@_to_LONGDOUBLE, + @from@_to_CFLOAT, + @from@_to_CDOUBLE, + @from@_to_CLONGDOUBLE, + @from@_to_OBJECT, + @from@_to_STRING, + @from@_to_UNICODE, + @from@_to_VOID }, - (PyArray_GetItemFunc*)@from@_getitem, - (PyArray_SetItemFunc*)@from@_setitem, + @from@_getitem, + @from@_setitem, (PyArray_CopySwapNFunc*)@from@_copyswapn, (PyArray_CopySwapFunc*)@from@_copyswap, (PyArray_CompareFunc*)@from@_compare, (PyArray_ArgFunc*)@from@_argmax, (PyArray_DotFunc*)NULL, (PyArray_ScanFunc*)@from@_scan, - (PyArray_FromStrFunc*)@from@_fromstr, + @from@_fromstr, (PyArray_NonzeroFunc*)@from@_nonzero, (PyArray_FillFunc*)NULL, (PyArray_FillWithScalarFunc*)NULL, #if @sort@ { - (PyArray_SortFunc *)quicksort_@suff@, - (PyArray_SortFunc *)heapsort_@suff@, - (PyArray_SortFunc *)mergesort_@suff@ + quicksort_@suff@, + heapsort_@suff@, + mergesort_@suff@ }, { - (PyArray_ArgSortFunc *)aquicksort_@suff@, - (PyArray_ArgSortFunc *)aheapsort_@suff@, - (PyArray_ArgSortFunc *)amergesort_@suff@ + aquicksort_@suff@, + aheapsort_@suff@, + amergesort_@suff@ }, #else { @@ -4077,50 +4286,50 @@ static PyArray_Descr @from@_Descr = { static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = { { - (PyArray_VectorUnaryFunc*)@from@_to_BOOL, - (PyArray_VectorUnaryFunc*)@from@_to_BYTE, - (PyArray_VectorUnaryFunc*)@from@_to_UBYTE, - (PyArray_VectorUnaryFunc*)@from@_to_SHORT, - (PyArray_VectorUnaryFunc*)@from@_to_USHORT, - (PyArray_VectorUnaryFunc*)@from@_to_INT, - (PyArray_VectorUnaryFunc*)@from@_to_UINT, - (PyArray_VectorUnaryFunc*)@from@_to_LONG, - (PyArray_VectorUnaryFunc*)@from@_to_ULONG, - (PyArray_VectorUnaryFunc*)@from@_to_LONGLONG, - (PyArray_VectorUnaryFunc*)@from@_to_ULONGLONG, - (PyArray_VectorUnaryFunc*)@from@_to_FLOAT, - (PyArray_VectorUnaryFunc*)@from@_to_DOUBLE, - (PyArray_VectorUnaryFunc*)@from@_to_LONGDOUBLE, - (PyArray_VectorUnaryFunc*)@from@_to_CFLOAT, - (PyArray_VectorUnaryFunc*)@from@_to_CDOUBLE, - (PyArray_VectorUnaryFunc*)@from@_to_CLONGDOUBLE, - (PyArray_VectorUnaryFunc*)@from@_to_OBJECT, - (PyArray_VectorUnaryFunc*)@from@_to_STRING, - (PyArray_VectorUnaryFunc*)@from@_to_UNICODE, - (PyArray_VectorUnaryFunc*)@from@_to_VOID + @from@_to_BOOL, + @from@_to_BYTE, + @from@_to_UBYTE, + @from@_to_SHORT, + @from@_to_USHORT, + @from@_to_INT, + @from@_to_UINT, + @from@_to_LONG, + @from@_to_ULONG, + @from@_to_LONGLONG, + @from@_to_ULONGLONG, + @from@_to_FLOAT, + @from@_to_DOUBLE, + @from@_to_LONGDOUBLE, + @from@_to_CFLOAT, + @from@_to_CDOUBLE, + @from@_to_CLONGDOUBLE, + @from@_to_OBJECT, + @from@_to_STRING, + @from@_to_UNICODE, + @from@_to_VOID }, - (PyArray_GetItemFunc*)@from@_getitem, - (PyArray_SetItemFunc*)@from@_setitem, + @from@_getitem, + @from@_setitem, (PyArray_CopySwapNFunc*)@from@_copyswapn, (PyArray_CopySwapFunc*)@from@_copyswap, (PyArray_CompareFunc*)@from@_compare, (PyArray_ArgFunc*)@from@_argmax, (PyArray_DotFunc*)@from@_dot, (PyArray_ScanFunc*)@from@_scan, - (PyArray_FromStrFunc*)@from@_fromstr, + @from@_fromstr, (PyArray_NonzeroFunc*)@from@_nonzero, (PyArray_FillFunc*)@from@_fill, (PyArray_FillWithScalarFunc*)@from@_fillwithscalar, #if @sort@ { - (PyArray_SortFunc *)quicksort_@suff@, - (PyArray_SortFunc *)heapsort_@suff@, - (PyArray_SortFunc *)mergesort_@suff@ + quicksort_@suff@, + heapsort_@suff@, + mergesort_@suff@ }, { - (PyArray_ArgSortFunc *)aquicksort_@suff@, - (PyArray_ArgSortFunc *)aheapsort_@suff@, - (PyArray_ArgSortFunc *)amergesort_@suff@ + aquicksort_@suff@, + aheapsort_@suff@, + amergesort_@suff@ }, #else { diff --git a/numpy/core/src/multiarray/calculation.c b/numpy/core/src/multiarray/calculation.c index edcca9857..e3cec21b1 100644 --- a/numpy/core/src/multiarray/calculation.c +++ b/numpy/core/src/multiarray/calculation.c @@ -618,7 +618,7 @@ PyArray_Round(PyArrayObject *a, int decimals, PyArrayObject *out) } /* arr.real = a.real.round(decimals) */ - part = PyObject_GetAttrString(arr, "real"); + part = PyObject_GetAttrString((PyObject *)a, "real"); if (part == NULL) { Py_DECREF(arr); return NULL; @@ -639,7 +639,7 @@ PyArray_Round(PyArrayObject *a, int decimals, PyArrayObject *out) } /* arr.imag = a.imag.round(decimals) */ - part = PyObject_GetAttrString(arr, "imag"); + part = PyObject_GetAttrString((PyObject *)a, "imag"); if (part == NULL) { Py_DECREF(arr); return NULL; diff --git a/numpy/core/src/multiarray/common.c b/numpy/core/src/multiarray/common.c index 816778b91..3352c3529 100644 --- a/numpy/core/src/multiarray/common.c +++ b/numpy/core/src/multiarray/common.c @@ -684,7 +684,16 @@ _IsAligned(PyArrayObject *ap) /* alignment 1 types should have a efficient alignment for copy loops */ if (PyArray_ISFLEXIBLE(ap) || PyArray_ISSTRING(ap)) { - alignment = NPY_MAX_COPY_ALIGNMENT; + npy_intp itemsize = PyArray_ITEMSIZE(ap); + /* power of two sizes may be loaded in larger moves */ + if (((itemsize & (itemsize - 1)) == 0)) { + alignment = itemsize > NPY_MAX_COPY_ALIGNMENT ? + NPY_MAX_COPY_ALIGNMENT : itemsize; + } + else { + /* if not power of two it will be accessed bytewise */ + alignment = 1; + } } if (alignment == 1) { @@ -756,39 +765,6 @@ _IsWriteable(PyArrayObject *ap) } -/* Gets a half-open range [start, end) of offsets from the data pointer */ -NPY_NO_EXPORT void -offset_bounds_from_strides(const int itemsize, const int nd, - const npy_intp *dims, const npy_intp *strides, - npy_intp *lower_offset, npy_intp *upper_offset) { - npy_intp max_axis_offset; - npy_intp lower = 0; - npy_intp upper = 0; - int i; - - for (i = 0; i < nd; i++) { - if (dims[i] == 0) { - /* If the array size is zero, return an empty range */ - *lower_offset = 0; - *upper_offset = 0; - return; - } - /* Expand either upwards or downwards depending on stride */ - max_axis_offset = strides[i] * (dims[i] - 1); - if (max_axis_offset > 0) { - upper += max_axis_offset; - } - else { - lower += max_axis_offset; - } - } - /* Return a half-open range */ - upper += itemsize; - *lower_offset = lower; - *upper_offset = upper; -} - - /** * Convert an array shape to a string such as "(1, 2)". * diff --git a/numpy/core/src/multiarray/common.h b/numpy/core/src/multiarray/common.h index 9cf2e27bf..11993829f 100644 --- a/numpy/core/src/multiarray/common.h +++ b/numpy/core/src/multiarray/common.h @@ -65,11 +65,6 @@ _IsAligned(PyArrayObject *ap); NPY_NO_EXPORT npy_bool _IsWriteable(PyArrayObject *ap); -NPY_NO_EXPORT void -offset_bounds_from_strides(const int itemsize, const int nd, - const npy_intp *dims, const npy_intp *strides, - npy_intp *lower_offset, npy_intp *upper_offset); - NPY_NO_EXPORT PyObject * convert_shape_to_string(npy_intp n, npy_intp *vals, char *ending); diff --git a/numpy/core/src/multiarray/compiled_base.c b/numpy/core/src/multiarray/compiled_base.c index baf405d1e..8ffeedac2 100644 --- a/numpy/core/src/multiarray/compiled_base.c +++ b/numpy/core/src/multiarray/compiled_base.c @@ -96,7 +96,7 @@ arr_bincount(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds) PyObject *list = NULL, *weight=Py_None, *mlength=Py_None; PyArrayObject *lst=NULL, *ans=NULL, *wts=NULL; npy_intp *numbers, *ians, len , mx, mn, ans_size, minlength; - int i; + npy_intp i; double *weights , *dans; static char *kwlist[] = {"list", "weights", "minlength", NULL}; @@ -156,7 +156,7 @@ arr_bincount(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds) ians = (npy_intp *)(PyArray_DATA(ans)); NPY_BEGIN_ALLOW_THREADS; for (i = 0; i < len; i++) - ians [numbers [i]] += 1; + ians[numbers[i]] += 1; NPY_END_ALLOW_THREADS; Py_DECREF(lst); } @@ -344,6 +344,7 @@ arr_insert_loop(char *mptr, char *vptr, char *input_data, char *zero, /* If we move past value data. Reset */ if (copied >= numvals) { vptr = avals_data; + copied = 0; } } mptr += melsize; @@ -427,6 +428,21 @@ arr_insert(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict) } objarray = (PyArray_DESCR(ainput)->type_num == NPY_OBJECT); + if (!numvals) { + /* nothing to insert! fail unless none of mask is true */ + const char *iter = mptr; + const char *const last = iter + PyArray_NBYTES(amask); + while (iter != last && !memcmp(iter, zero, melsize)) { + iter += melsize; + } + if (iter != last) { + PyErr_SetString(PyExc_ValueError, + "Cannot insert from an empty array!"); + goto fail; + } + goto finish; + } + /* Handle zero-dimensional case separately */ if (nd == 0) { if (memcmp(mptr,zero,melsize) != 0) { @@ -440,8 +456,7 @@ arr_insert(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict) Py_DECREF(avals); PyDataMem_FREE(zero); Py_DECREF(ainput); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } totmask = (int) PyArray_SIZE(amask); @@ -462,12 +477,12 @@ arr_insert(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict) NPY_END_ALLOW_THREADS; } +finish: Py_DECREF(amask); Py_DECREF(avals); PyDataMem_FREE(zero); Py_DECREF(ainput); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; fail: PyDataMem_FREE(zero); @@ -477,6 +492,8 @@ fail: return NULL; } +#define LIKELY_IN_CACHE_SIZE 8 + /** @brief find index of a sorted array such that arr[i] <= key < arr[i + 1]. * * If an starting index guess is in-range, the array values around this @@ -497,12 +514,13 @@ fail: * @return index */ static npy_intp -binary_search_with_guess(double key, double arr [], npy_intp len, - npy_intp guess) +binary_search_with_guess(const npy_double key, const npy_double *arr, + npy_intp len, npy_intp guess) { npy_intp imin = 0; npy_intp imax = len; + /* Handle keys outside of the arr range first */ if (key > arr[len - 1]) { return len; } @@ -510,35 +528,63 @@ binary_search_with_guess(double key, double arr [], npy_intp len, return -1; } - if (guess < 0) { - guess = 0; - } - else if (guess >= len - 1) { - guess = len - 2; - } + /* + * It would seem that for the following code to work, 'len' should + * at least be 4. But because of the way 'guess' is normalized, it + * will always be set to 1 if len <= 4. Given that, and that keys + * outside of the 'arr' bounds have already been handled, and the + * order in which comparisons happen below, it should become obvious + * that it will work with any array of at least 2 items. + */ + assert (len >= 2); - /* check most likely values: guess, guess + 1, guess - 1 */ - if ((key > arr[guess]) && (key <= arr[guess + 1])) { - return guess; + if (guess > len - 3) { + guess = len - 3; } - else if ((guess < len - 2) && (key > arr[guess + 1]) && - (key <= arr[guess + 2])) { - return guess + 1; + if (guess < 1) { + guess = 1; } - else if ((guess > 1) && (key > arr[guess - 1]) && - (key <= arr[guess])) { - return guess - 1; - } - /* may be able to restrict bounds to range likely to be in memory */ - if ((guess > 8) && (key > arr[guess - 8])) { - imin = guess - 8; + + /* check most likely values: guess - 1, guess, guess + 1 */ + if (key <= arr[guess]) { + if (key <= arr[guess - 1]) { + imax = guess - 1; + /* last attempt to restrict search to items in cache */ + if (guess > LIKELY_IN_CACHE_SIZE && + key > arr[guess - LIKELY_IN_CACHE_SIZE]) { + imin = guess - LIKELY_IN_CACHE_SIZE; + } + } + else { + /* key > arr[guess - 1] */ + return guess - 1; + } } - if ((guess < len - 9) && (key <= arr[guess + 8])) { - imax = guess + 8; + else { + /* key > arr[guess] */ + if (key <= arr[guess + 1]) { + return guess; + } + else { + /* key > arr[guess + 1] */ + if (key <= arr[guess + 2]) { + return guess + 1; + } + else { + /* key > arr[guess + 2] */ + imin = guess + 2; + /* last attempt to restrict search to items in cache */ + if (guess < len - LIKELY_IN_CACHE_SIZE - 1 && + key <= arr[guess + LIKELY_IN_CACHE_SIZE]) { + imax = guess + LIKELY_IN_CACHE_SIZE; + } + } + } } + /* finally, find index by bisection */ while (imin < imax) { - npy_intp imid = imin + ((imax - imin) >> 1); + const npy_intp imid = imin + ((imax - imin) >> 1); if (key >= arr[imid]) { imin = imid + 1; } @@ -549,6 +595,8 @@ binary_search_with_guess(double key, double arr [], npy_intp len, return imin - 1; } +#undef LIKELY_IN_CACHE_SIZE + NPY_NO_EXPORT PyObject * arr_interp(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict) { @@ -556,12 +604,15 @@ arr_interp(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict) PyObject *fp, *xp, *x; PyObject *left = NULL, *right = NULL; PyArrayObject *afp = NULL, *axp = NULL, *ax = NULL, *af = NULL; - npy_intp i, lenx, lenxp, j, jprev; - double lval, rval; - double *dy, *dx, *dz, *dres, *slopes; + npy_intp i, lenx, lenxp; + npy_double lval, rval; + const npy_double *dy, *dx, *dz; + npy_double *dres, *slopes = NULL; static char *kwlist[] = {"x", "xp", "fp", "left", "right", NULL}; + NPY_BEGIN_THREADS_DEF; + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "OOO|OO", kwlist, &x, &xp, &fp, &left, &right)) { return NULL; @@ -579,29 +630,29 @@ arr_interp(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict) if (ax == NULL) { goto fail; } - lenxp = PyArray_DIMS(axp)[0]; + lenxp = PyArray_SIZE(axp); if (lenxp == 0) { PyErr_SetString(PyExc_ValueError, "array of sample points is empty"); goto fail; } - if (PyArray_DIMS(afp)[0] != lenxp) { + if (PyArray_SIZE(afp) != lenxp) { PyErr_SetString(PyExc_ValueError, "fp and xp are not of the same length."); goto fail; } af = (PyArrayObject *)PyArray_SimpleNew(PyArray_NDIM(ax), - PyArray_DIMS(ax), NPY_DOUBLE); + PyArray_DIMS(ax), NPY_DOUBLE); if (af == NULL) { goto fail; } lenx = PyArray_SIZE(ax); - dy = (double *)PyArray_DATA(afp); - dx = (double *)PyArray_DATA(axp); - dz = (double *)PyArray_DATA(ax); - dres = (double *)PyArray_DATA(af); + dy = (const npy_double *)PyArray_DATA(afp); + dx = (const npy_double *)PyArray_DATA(axp); + dz = (const npy_double *)PyArray_DATA(ax); + dres = (npy_double *)PyArray_DATA(af); /* Get left and right fill values. */ if ((left == NULL) || (left == Py_None)) { lval = dy[0]; @@ -613,7 +664,7 @@ arr_interp(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict) } } if ((right == NULL) || (right == Py_None)) { - rval = dy[lenxp-1]; + rval = dy[lenxp - 1]; } else { rval = PyFloat_AsDouble(right); @@ -622,72 +673,67 @@ arr_interp(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwdict) } } - /* only pre-calculate slopes if there are relatively few of them. */ - j = jprev = 0; - if (lenxp <= lenx) { - slopes = (double *) PyArray_malloc((lenxp - 1)*sizeof(double)); - if (! slopes) { - goto fail; - } - NPY_BEGIN_ALLOW_THREADS; - for (i = 0; i < lenxp - 1; i++) { - slopes[i] = (dy[i + 1] - dy[i])/(dx[i + 1] - dx[i]); + /* binary_search_with_guess needs at least a 2 item long array */ + if (lenxp == 1) { + const npy_double xp_val = dx[0]; + const npy_double fp_val = dy[0]; + + NPY_BEGIN_THREADS_THRESHOLDED(lenx); + for (i = 0; i < lenx; ++i) { + const npy_double x_val = dz[i]; + dres[i] = (x_val < xp_val) ? lval : + ((x_val > xp_val) ? rval : fp_val); } - for (i = 0; i < lenx; i++) { - const double x = dz[i]; + NPY_END_THREADS; + } + else { + npy_intp j = 0; - if (npy_isnan(x)) { - dres[i] = x; - continue; + /* only pre-calculate slopes if there are relatively few of them. */ + if (lenxp <= lenx) { + slopes = PyArray_malloc((lenxp - 1) * sizeof(npy_double)); + if (slopes == NULL) { + goto fail; } + } - j = binary_search_with_guess(x, dx, lenxp, jprev); - jprev = j; - if (j == -1) { - dres[i] = lval; - } - else if (j == lenxp - 1) { - dres[i] = dy[j]; - } - else if (j == lenxp) { - dres[i] = rval; - } - else { - dres[i] = slopes[j]*(x - dx[j]) + dy[j]; + NPY_BEGIN_THREADS; + + if (slopes != NULL) { + for (i = 0; i < lenxp - 1; ++i) { + slopes[i] = (dy[i+1] - dy[i]) / (dx[i+1] - dx[i]); } } - NPY_END_ALLOW_THREADS; - PyArray_free(slopes); - } - else { - NPY_BEGIN_ALLOW_THREADS; - for (i = 0; i < lenx; i++) { - const double x = dz[i]; - if (npy_isnan(x)) { - dres[i] = x; + for (i = 0; i < lenx; ++i) { + const npy_double x_val = dz[i]; + + if (npy_isnan(x_val)) { + dres[i] = x_val; continue; } - j = binary_search_with_guess(x, dx, lenxp, jprev); - jprev = j; + j = binary_search_with_guess(x_val, dx, lenxp, j); if (j == -1) { dres[i] = lval; } - else if (j == lenxp - 1) { - dres[i] = dy[j]; - } else if (j == lenxp) { dres[i] = rval; } + else if (j == lenxp - 1) { + dres[i] = dy[j]; + } else { - const double slope = (dy[j + 1] - dy[j])/(dx[j + 1] - dx[j]); - dres[i] = slope*(x - dx[j]) + dy[j]; + const npy_double slope = (slopes != NULL) ? slopes[j] : + (dy[j+1] - dy[j]) / (dx[j+1] - dx[j]); + dres[i] = slope*(x_val - dx[j]) + dy[j]; } } - NPY_END_ALLOW_THREADS; + + NPY_END_THREADS; } + PyArray_free(slopes); Py_DECREF(afp); Py_DECREF(axp); Py_DECREF(ax); @@ -1225,7 +1271,7 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args) PyObject *str; char *docstr; static char *msg = "already has a docstring"; - PyObject *tp_dict; + PyObject *tp_dict = PyArrayDescr_Type.tp_dict; PyObject *myobj; static PyTypeObject *PyMemberDescr_TypePtr = NULL; static PyTypeObject *PyGetSetDescr_TypePtr = NULL; @@ -1233,12 +1279,10 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args) /* Don't add docstrings */ if (Py_OptimizeFlag > 1) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } if (PyGetSetDescr_TypePtr == NULL) { - tp_dict = PyArrayDescr_Type.tp_dict; /* Get "subdescr" */ myobj = PyDict_GetItemString(tp_dict, "fields"); if (myobj != NULL) { @@ -1315,8 +1359,7 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args) "Cannot set a docstring for that object"); return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #undef _TESTDOC1 @@ -1324,8 +1367,7 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args) #undef _ADDDOC Py_INCREF(str); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } diff --git a/numpy/core/src/multiarray/conversion_utils.c b/numpy/core/src/multiarray/conversion_utils.c index 096a363f1..88064c1d6 100644 --- a/numpy/core/src/multiarray/conversion_utils.c +++ b/numpy/core/src/multiarray/conversion_utils.c @@ -777,19 +777,16 @@ PyArray_PyIntAsIntp_ErrMsg(PyObject *o, const char * msg) #endif PyObject *obj, *err; - if (!o) { + /* + * Be a bit stricter and not allow bools. + * np.bool_ is also disallowed as Boolean arrays do not currently + * support index. + */ + if (!o || PyBool_Check(o) || PyArray_IsScalar(o, Bool)) { PyErr_SetString(PyExc_TypeError, msg); return -1; } - /* Be a bit stricter and not allow bools, np.bool_ is handled later */ - if (PyBool_Check(o)) { - if (DEPRECATE("using a boolean instead of an integer" - " will result in an error in the future") < 0) { - return -1; - } - } - /* * Since it is the usual case, first check if o is an integer. This is * an exact check, since otherwise __index__ is used. @@ -815,82 +812,22 @@ PyArray_PyIntAsIntp_ErrMsg(PyObject *o, const char * msg) return (npy_intp)long_value; } - /* Disallow numpy.bool_. Boolean arrays do not currently support index. */ - if (PyArray_IsScalar(o, Bool)) { - if (DEPRECATE("using a boolean instead of an integer" - " will result in an error in the future") < 0) { - return -1; - } - } - /* * The most general case. PyNumber_Index(o) covers everything * including arrays. In principle it may be possible to replace * the whole function by PyIndex_AsSSize_t after deprecation. */ obj = PyNumber_Index(o); - if (obj) { + if (obj == NULL) { + return -1; + } #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP) - long_value = PyLong_AsLongLong(obj); + long_value = PyLong_AsLongLong(obj); #else - long_value = PyLong_AsLong(obj); -#endif - Py_DECREF(obj); - goto finish; - } - else { - /* - * Set the TypeError like PyNumber_Index(o) would after trying - * the general case. - */ - PyErr_Clear(); - } - - /* - * For backward compatibility check the number C-Api number protcol - * This should be removed up the finish label after deprecation. - */ - if (Py_TYPE(o)->tp_as_number != NULL && - Py_TYPE(o)->tp_as_number->nb_int != NULL) { - obj = Py_TYPE(o)->tp_as_number->nb_int(o); - if (obj == NULL) { - return -1; - } - #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP) - long_value = PyLong_AsLongLong(obj); - #else - long_value = PyLong_AsLong(obj); - #endif - Py_DECREF(obj); - } -#if !defined(NPY_PY3K) - else if (Py_TYPE(o)->tp_as_number != NULL && - Py_TYPE(o)->tp_as_number->nb_long != NULL) { - obj = Py_TYPE(o)->tp_as_number->nb_long(o); - if (obj == NULL) { - return -1; - } - #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP) - long_value = PyLong_AsLongLong(obj); - #else - long_value = PyLong_AsLong(obj); - #endif - Py_DECREF(obj); - } + long_value = PyLong_AsLong(obj); #endif - else { - PyErr_SetString(PyExc_TypeError, msg); - return -1; - } - /* Give a deprecation warning, unless there was already an error */ - if (!error_converting(long_value)) { - if (DEPRECATE("using a non-integer number instead of an integer" - " will result in an error in the future") < 0) { - return -1; - } - } + Py_DECREF(obj); - finish: if (error_converting(long_value)) { err = PyErr_Occurred(); /* Only replace TypeError's here, which are the normal errors. */ @@ -899,8 +836,9 @@ PyArray_PyIntAsIntp_ErrMsg(PyObject *o, const char * msg) } return -1; } + goto overflow_check; /* silence unused warning */ - overflow_check: +overflow_check: #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP) #if (NPY_SIZEOF_LONGLONG > NPY_SIZEOF_INTP) if ((long_value < NPY_MIN_INTP) || (long_value > NPY_MAX_INTP)) { @@ -1023,9 +961,6 @@ NPY_NO_EXPORT int PyArray_TypestrConvert(int itemsize, int gentype) { int newtype = NPY_NOTYPE; - PyArray_Descr *temp; - const char *msg = "Specified size is invalid for this data type.\n" - "Size will be ignored in NumPy 1.7 but may throw an exception in future versions."; switch (gentype) { case NPY_GENBOOLLTR: @@ -1142,6 +1077,7 @@ PyArray_TypestrConvert(int itemsize, int gentype) if (itemsize == 4 || itemsize == 8) { int ret = 0; if (evil_global_disable_warn_O4O8_flag) { + /* 2012-02-04, 1.7, not sure when this can be removed */ ret = DEPRECATE("DType strings 'O4' and 'O8' are " "deprecated because they are platform " "specific. Use 'O' instead"); @@ -1179,31 +1115,6 @@ PyArray_TypestrConvert(int itemsize, int gentype) break; } - /* - * Raise deprecate warning if new type hasn't been - * set yet and size char is invalid. - * This should eventually be changed to an error in - * future NumPy versions. - */ - if (newtype == NPY_NOTYPE) { - temp = PyArray_DescrFromType(gentype); - if (temp != NULL) { - if (temp->elsize != itemsize) { - if (DEPRECATE(msg) < 0) { - Py_DECREF(temp); - return -1; - } - - newtype = gentype; - } - else { - newtype = gentype; - } - - Py_DECREF(temp); - } - } - return newtype; } diff --git a/numpy/core/src/multiarray/convert.c b/numpy/core/src/multiarray/convert.c index e1c2cb8d9..7cb27581a 100644 --- a/numpy/core/src/multiarray/convert.c +++ b/numpy/core/src/multiarray/convert.c @@ -171,7 +171,7 @@ PyArray_ToFile(PyArrayObject *self, FILE *fp, char *sep, char *format) /* * standard writing */ - strobj = PyObject_Str(obj); + strobj = PyObject_Repr(obj); Py_DECREF(obj); if (strobj == NULL) { Py_DECREF(it); @@ -565,6 +565,7 @@ PyArray_View(PyArrayObject *self, PyArray_Descr *type, PyTypeObject *pytype) flags, (PyObject *)self); if (ret == NULL) { + Py_XDECREF(type); return NULL; } @@ -572,7 +573,7 @@ PyArray_View(PyArrayObject *self, PyArray_Descr *type, PyTypeObject *pytype) Py_INCREF(self); if (PyArray_SetBaseObject(ret, (PyObject *)self) < 0) { Py_DECREF(ret); - Py_DECREF(type); + Py_XDECREF(type); return NULL; } diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index e88e17028..e23cbe3c9 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -45,7 +45,18 @@ static int fromstr_next_element(char **s, void *dptr, PyArray_Descr *dtype, const char *end) { - int r = dtype->f->fromstr(*s, dptr, s, dtype); + char *e = *s; + int r = dtype->f->fromstr(*s, dptr, &e, dtype); + /* + * fromstr always returns 0 for basic dtypes + * s points to the end of the parsed string + * if an error occurs s is not changed + */ + if (*s == e) { + /* Nothing read */ + return -1; + } + *s = e; if (end != NULL && *s > end) { return -1; } @@ -57,7 +68,14 @@ fromfile_next_element(FILE **fp, void *dptr, PyArray_Descr *dtype, void *NPY_UNUSED(stream_data)) { /* the NULL argument is for backwards-compatibility */ - return dtype->f->scanfunc(*fp, dptr, NULL, dtype); + int r = dtype->f->scanfunc(*fp, dptr, NULL, dtype); + /* r can be EOF or the number of items read (0 or 1) */ + if (r == 1) { + return 0; + } + else { + return -1; + } } /* @@ -568,7 +586,8 @@ PyArray_AssignFromSequence(PyArrayObject *self, PyObject *v) static int discover_itemsize(PyObject *s, int nd, int *itemsize, int string_type) { - int n, r, i; + int r; + npy_intp n, i; if (PyArray_Check(s)) { *itemsize = PyArray_MAX(*itemsize, PyArray_ITEMSIZE((PyArrayObject *)s)); @@ -645,7 +664,8 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it, int *out_is_object) { PyObject *e; - int r, n, i; + int r; + npy_intp n, i; Py_buffer buffer_view; PyObject * seq; @@ -2450,6 +2470,7 @@ PyArray_FromDimsAndDataAndDescr(int nd, int *d, char msg[] = "PyArray_FromDimsAndDataAndDescr: use PyArray_NewFromDescr."; if (DEPRECATE(msg) < 0) { + /* 2009-04-30, 1.5 */ return NULL; } if (!PyArray_ISNBO(descr->byteorder)) @@ -2474,6 +2495,7 @@ PyArray_FromDims(int nd, int *d, int type) char msg[] = "PyArray_FromDims: use PyArray_SimpleNew."; if (DEPRECATE(msg) < 0) { + /* 2009-04-30, 1.5 */ return NULL; } ret = (PyArrayObject *)PyArray_FromDimsAndDataAndDescr(nd, d, @@ -3275,6 +3297,7 @@ array_from_text(PyArray_Descr *dtype, npy_intp num, char *sep, size_t *nread, dptr = PyArray_DATA(r); for (i= 0; num < 0 || i < num; i++) { if (next(&stream, dptr, dtype, stream_data) < 0) { + /* EOF */ break; } *nread += 1; diff --git a/numpy/core/src/multiarray/datetime.c b/numpy/core/src/multiarray/datetime.c index a870650fc..9e4e00e9c 100644 --- a/numpy/core/src/multiarray/datetime.c +++ b/numpy/core/src/multiarray/datetime.c @@ -2808,8 +2808,7 @@ convert_datetime_to_pyobject(npy_datetime dt, PyArray_DatetimeMetaData *meta) * into None. */ if (dt == NPY_DATETIME_NAT || meta->base == NPY_FR_GENERIC) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /* If the type's precision is greater than microseconds, return an int */ @@ -2862,8 +2861,7 @@ convert_timedelta_to_pyobject(npy_timedelta td, PyArray_DatetimeMetaData *meta) * Convert NaT (not-a-time) into None. */ if (td == NPY_DATETIME_NAT) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /* diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c index bbcd5da36..05397228e 100644 --- a/numpy/core/src/multiarray/descriptor.c +++ b/numpy/core/src/multiarray/descriptor.c @@ -29,6 +29,8 @@ #define NPY_NEXT_ALIGNED_OFFSET(offset, alignment) \ (((offset) + (alignment) - 1) & (-(alignment))) +#define PyDictProxy_Check(obj) (Py_TYPE(obj) == &PyDictProxy_Type) + static PyObject *typeDict = NULL; /* Must be explicitly loaded */ static PyArray_Descr * @@ -143,8 +145,7 @@ array_set_typeDict(PyObject *NPY_UNUSED(ignored), PyObject *args) typeDict = dict; /* Create an internal reference to it */ Py_INCREF(dict); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } #define _chk_byteorder(arg) (arg == '>' || arg == '<' || \ @@ -271,7 +272,7 @@ _convert_from_tuple(PyObject *obj) type->elsize = itemsize; } } - else if (PyDict_Check(val)) { + else if (PyDict_Check(val) || PyDictProxy_Check(val)) { /* Assume it's a metadata dictionary */ if (PyDict_Merge(type->metadata, val, 0) == -1) { Py_DECREF(type); @@ -508,8 +509,14 @@ _convert_from_array_descr(PyObject *obj, int align) && (PyUString_Check(title) || PyUnicode_Check(title)) #endif && (PyDict_GetItem(fields, title) != NULL))) { - PyErr_SetString(PyExc_ValueError, - "two fields with the same name"); +#if defined(NPY_PY3K) + name = PyUnicode_AsUTF8String(name); +#endif + PyErr_Format(PyExc_ValueError, + "field '%s' occurs more than once", PyString_AsString(name)); +#if defined(NPY_PY3K) + Py_DECREF(name); +#endif goto fail; } dtypeflags |= (conv->flags & NPY_FROM_FIELDS); @@ -945,15 +952,21 @@ _convert_from_dict(PyObject *obj, int align) if (fields == NULL) { return (PyArray_Descr *)PyErr_NoMemory(); } - names = PyDict_GetItemString(obj, "names"); - descrs = PyDict_GetItemString(obj, "formats"); + /* Use PyMapping_GetItemString to support dictproxy objects as well */ + names = PyMapping_GetItemString(obj, "names"); + descrs = PyMapping_GetItemString(obj, "formats"); if (!names || !descrs) { Py_DECREF(fields); + PyErr_Clear(); return _use_fields_dict(obj, align); } n = PyObject_Length(names); - offsets = PyDict_GetItemString(obj, "offsets"); - titles = PyDict_GetItemString(obj, "titles"); + offsets = PyMapping_GetItemString(obj, "offsets"); + titles = PyMapping_GetItemString(obj, "titles"); + if (!offsets || !titles) { + PyErr_Clear(); + } + if ((n > PyObject_Length(descrs)) || (offsets && (n > PyObject_Length(offsets))) || (titles && (n > PyObject_Length(titles)))) { @@ -967,8 +980,10 @@ _convert_from_dict(PyObject *obj, int align) * If a property 'aligned' is in the dict, it overrides the align flag * to be True if it not already true. */ - tmp = PyDict_GetItemString(obj, "aligned"); - if (tmp != NULL) { + tmp = PyMapping_GetItemString(obj, "aligned"); + if (tmp == NULL) { + PyErr_Clear(); + } else { if (tmp == Py_True) { align = 1; } @@ -1139,8 +1154,10 @@ _convert_from_dict(PyObject *obj, int align) } /* Override the itemsize if provided */ - tmp = PyDict_GetItemString(obj, "itemsize"); - if (tmp != NULL) { + tmp = PyMapping_GetItemString(obj, "itemsize"); + if (tmp == NULL) { + PyErr_Clear(); + } else { itemsize = (int)PyInt_AsLong(tmp); if (itemsize == -1 && PyErr_Occurred()) { Py_DECREF(new); @@ -1169,17 +1186,18 @@ _convert_from_dict(PyObject *obj, int align) } /* Add the metadata if provided */ - metadata = PyDict_GetItemString(obj, "metadata"); + metadata = PyMapping_GetItemString(obj, "metadata"); - if (new->metadata == NULL) { + if (metadata == NULL) { + PyErr_Clear(); + } + else if (new->metadata == NULL) { new->metadata = metadata; Py_XINCREF(new->metadata); } - else if (metadata != NULL) { - if (PyDict_Merge(new->metadata, metadata, 0) == -1) { - Py_DECREF(new); - return NULL; - } + else if (PyDict_Merge(new->metadata, metadata, 0) == -1) { + Py_DECREF(new); + return NULL; } return new; @@ -1447,7 +1465,7 @@ PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at) } return NPY_SUCCEED; } - else if (PyDict_Check(obj)) { + else if (PyDict_Check(obj) || PyDictProxy_Check(obj)) { /* or a dictionary */ *at = _convert_from_dict(obj,0); if (*at == NULL) { @@ -1655,8 +1673,7 @@ static PyObject * arraydescr_subdescr_get(PyArray_Descr *self) { if (!PyDataType_HASSUBARRAY(self)) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return Py_BuildValue("OO", (PyObject *)self->subarray->base, self->subarray->shape); @@ -1679,8 +1696,12 @@ arraydescr_protocol_typestr_get(PyArray_Descr *self) if (self->type_num == NPY_UNICODE) { size >>= 2; } - - ret = PyUString_FromFormat("%c%c%d", endian, basic_, size); + if (self->type_num == NPY_OBJECT) { + ret = PyUString_FromFormat("%c%c", endian, basic_); + } + else { + ret = PyUString_FromFormat("%c%c%d", endian, basic_, size); + } if (PyDataType_ISDATETIME(self)) { PyArray_DatetimeMetaData *meta; @@ -1905,8 +1926,7 @@ static PyObject * arraydescr_fields_get(PyArray_Descr *self) { if (!PyDataType_HASFIELDS(self)) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return PyDictProxy_New(self->fields); } @@ -1915,8 +1935,7 @@ static PyObject * arraydescr_metadata_get(PyArray_Descr *self) { if (self->metadata == NULL) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return PyDictProxy_New(self->metadata); } @@ -1936,8 +1955,7 @@ static PyObject * arraydescr_names_get(PyArray_Descr *self) { if (!PyDataType_HASFIELDS(self)) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } Py_INCREF(self->names); return self->names; @@ -1963,6 +1981,8 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val) } /* + * FIXME + * * This deprecation has been temporarily removed for the NumPy 1.7 * release. It should be re-added after the 1.7 branch is done, * and a convenience API to replace the typical use-cases for @@ -2380,8 +2400,7 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args) char dtypeflags; if (self->fields == Py_None) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } if (PyTuple_GET_SIZE(args) != 1 || !(PyTuple_Check(PyTuple_GET_ITEM(args, 0)))) { @@ -2725,8 +2744,7 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args) Py_XDECREF(old_metadata); } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /*NUMPY_API @@ -2744,7 +2762,7 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args) NPY_NO_EXPORT int PyArray_DescrAlignConverter(PyObject *obj, PyArray_Descr **at) { - if (PyDict_Check(obj)) { + if (PyDict_Check(obj) || PyDictProxy_Check(obj)) { *at = _convert_from_dict(obj, 1); } else if (PyBytes_Check(obj)) { @@ -2780,7 +2798,7 @@ PyArray_DescrAlignConverter(PyObject *obj, PyArray_Descr **at) NPY_NO_EXPORT int PyArray_DescrAlignConverter2(PyObject *obj, PyArray_Descr **at) { - if (PyDict_Check(obj)) { + if (PyDict_Check(obj) || PyDictProxy_Check(obj)) { *at = _convert_from_dict(obj, 1); } else if (PyBytes_Check(obj)) { diff --git a/numpy/core/src/multiarray/einsum.c.src b/numpy/core/src/multiarray/einsum.c.src index 5b1bb77fa..bde543703 100644 --- a/numpy/core/src/multiarray/einsum.c.src +++ b/numpy/core/src/multiarray/einsum.c.src @@ -1399,28 +1399,19 @@ finish_after_unrolled_loop: */ case @i@+1: # if @nop@ == 1 - *((npy_bool *)data_out + @i@) = (*((npy_bool *)data0 + @i@)) || - (*((npy_bool *)data_out + @i@)); - data0 += 8*sizeof(npy_bool); - data_out += 8*sizeof(npy_bool); + ((npy_bool *)data_out)[@i@] = ((npy_bool *)data0)[@i@] || + ((npy_bool *)data_out)[@i@]; # elif @nop@ == 2 - *((npy_bool *)data_out + @i@) = - ((*((npy_bool *)data0 + @i@)) && - (*((npy_bool *)data1 + @i@))) || - (*((npy_bool *)data_out + @i@)); - data0 += 8*sizeof(npy_bool); - data1 += 8*sizeof(npy_bool); - data_out += 8*sizeof(npy_bool); + ((npy_bool *)data_out)[@i@] = + (((npy_bool *)data0)[@i@] && + ((npy_bool *)data1)[@i@]) || + ((npy_bool *)data_out)[@i@]; # elif @nop@ == 3 - *((npy_bool *)data_out + @i@) = - ((*((npy_bool *)data0 + @i@)) && - (*((npy_bool *)data1 + @i@)) && - (*((npy_bool *)data2 + @i@))) || - (*((npy_bool *)data_out + @i@)); - data0 += 8*sizeof(npy_bool); - data1 += 8*sizeof(npy_bool); - data2 += 8*sizeof(npy_bool); - data_out += 8*sizeof(npy_bool); + ((npy_bool *)data_out)[@i@] = + (((npy_bool *)data0)[@i@] && + ((npy_bool *)data1)[@i@] && + ((npy_bool *)data2)[@i@]) || + ((npy_bool *)data_out)[@i@]; # endif /**end repeat1**/ case 0: @@ -1770,14 +1761,14 @@ get_sum_of_products_function(int nop, int type_num, } /* Check for all contiguous */ - for (iop = 0; iop < nop; ++iop) { + for (iop = 0; iop < nop + 1; ++iop) { if (fixed_strides[iop] != itemsize) { break; } } /* Contiguous loop */ - if (iop == nop) { + if (iop == nop + 1) { return _allcontig_specialized_table[type_num][nop <= 3 ? nop : 0]; } diff --git a/numpy/core/src/multiarray/getset.c b/numpy/core/src/multiarray/getset.c index 5374f42e7..5147b9735 100644 --- a/numpy/core/src/multiarray/getset.c +++ b/numpy/core/src/multiarray/getset.c @@ -9,14 +9,15 @@ #include "numpy/arrayobject.h" #include "npy_config.h" - #include "npy_pycompat.h" +#include "npy_import.h" #include "common.h" #include "scalartypes.h" #include "descriptor.h" #include "getset.h" #include "arrayobject.h" +#include "mem_overlap.h" /******************* array attribute get and set routines ******************/ @@ -223,8 +224,7 @@ static PyObject * array_protocol_strides_get(PyArrayObject *self) { if (PyArray_ISCONTIGUOUS(self)) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } return PyArray_IntTupleFromIntp(PyArray_NDIM(self), PyArray_STRIDES(self)); } @@ -435,6 +435,13 @@ array_descr_set(PyArrayObject *self, PyObject *arg) npy_intp newdim; int i; char *msg = "new type not compatible with array."; + PyObject *safe; + static PyObject *checkfunc = NULL; + + npy_cache_import("numpy.core._internal", "_view_is_safe", &checkfunc); + if (checkfunc == NULL) { + return -1; + } if (arg == NULL) { PyErr_SetString(PyExc_AttributeError, @@ -449,15 +456,13 @@ array_descr_set(PyArrayObject *self, PyObject *arg) return -1; } - if (PyDataType_FLAGCHK(newtype, NPY_ITEM_HASOBJECT) || - PyDataType_FLAGCHK(newtype, NPY_ITEM_IS_POINTER) || - PyDataType_FLAGCHK(PyArray_DESCR(self), NPY_ITEM_HASOBJECT) || - PyDataType_FLAGCHK(PyArray_DESCR(self), NPY_ITEM_IS_POINTER)) { - PyErr_SetString(PyExc_TypeError, - "Cannot change data-type for object array."); + /* check that we are not reinterpreting memory containing Objects */ + safe = PyObject_CallFunction(checkfunc, "OO", PyArray_DESCR(self), newtype); + if (safe == NULL) { Py_DECREF(newtype); return -1; } + Py_DECREF(safe); if (newtype->elsize == 0) { /* Allow a void view */ @@ -618,8 +623,7 @@ static PyObject * array_base_get(PyArrayObject *self) { if (PyArray_BASE(self) == NULL) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } else { Py_INCREF(PyArray_BASE(self)); @@ -897,8 +901,7 @@ array_transpose_get(PyArrayObject *self) static PyObject * array_finalize_get(PyArrayObject *NPY_UNUSED(self)) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } NPY_NO_EXPORT PyGetSetDef array_getsetlist[] = { diff --git a/numpy/core/src/multiarray/hashdescr.c b/numpy/core/src/multiarray/hashdescr.c index fa5fb95cd..6ed4f7905 100644 --- a/numpy/core/src/multiarray/hashdescr.c +++ b/numpy/core/src/multiarray/hashdescr.c @@ -28,7 +28,7 @@ static int _is_array_descr_builtin(PyArray_Descr* descr); static int _array_descr_walk(PyArray_Descr* descr, PyObject *l); -static int _array_descr_walk_fields(PyObject* fields, PyObject* l); +static int _array_descr_walk_fields(PyObject *names, PyObject* fields, PyObject* l); static int _array_descr_builtin(PyArray_Descr* descr, PyObject *l); /* @@ -86,7 +86,6 @@ static int _array_descr_builtin(PyArray_Descr* descr, PyObject *l) "(Hash) Error while computing builting hash"); goto clean_t; } - Py_INCREF(item); PyList_Append(l, item); } @@ -104,18 +103,35 @@ clean_t: * * Return 0 on success */ -static int _array_descr_walk_fields(PyObject* fields, PyObject* l) +static int _array_descr_walk_fields(PyObject *names, PyObject* fields, PyObject* l) { - PyObject *key, *value, *foffset, *fdescr; + PyObject *key, *value, *foffset, *fdescr, *ftitle; Py_ssize_t pos = 0; int st; - while (PyDict_Next(fields, &pos, &key, &value)) { + if (!PyTuple_Check(names)) { + PyErr_SetString(PyExc_SystemError, + "(Hash) names is not a tuple ???"); + return -1; + } + if (!PyDict_Check(fields)) { + PyErr_SetString(PyExc_SystemError, + "(Hash) fields is not a dict ???"); + return -1; + } + + for (pos = 0; pos < PyTuple_GET_SIZE(names); pos++) { /* * For each field, add the key + descr + offset to l */ - + key = PyTuple_GET_ITEM(names, pos); + value = PyDict_GetItem(fields, key); /* XXX: are those checks necessary ? */ + if (value == NULL) { + PyErr_SetString(PyExc_SystemError, + "(Hash) names and fields inconsistent ???"); + return -1; + } if (!PyUString_Check(key)) { PyErr_SetString(PyExc_SystemError, "(Hash) key of dtype dict not a string ???"); @@ -126,15 +142,14 @@ static int _array_descr_walk_fields(PyObject* fields, PyObject* l) "(Hash) value of dtype dict not a dtype ???"); return -1; } - if (PyTuple_Size(value) < 2) { + if (PyTuple_GET_SIZE(value) < 2) { PyErr_SetString(PyExc_SystemError, "(Hash) Less than 2 items in dtype dict ???"); return -1; } - Py_INCREF(key); PyList_Append(l, key); - fdescr = PyTuple_GetItem(value, 0); + fdescr = PyTuple_GET_ITEM(value, 0); if (!PyArray_DescrCheck(fdescr)) { PyErr_SetString(PyExc_SystemError, "(Hash) First item in compound dtype tuple not a descr ???"); @@ -149,16 +164,20 @@ static int _array_descr_walk_fields(PyObject* fields, PyObject* l) } } - foffset = PyTuple_GetItem(value, 1); + foffset = PyTuple_GET_ITEM(value, 1); if (!PyInt_Check(foffset)) { PyErr_SetString(PyExc_SystemError, "(Hash) Second item in compound dtype tuple not an int ???"); return -1; } else { - Py_INCREF(foffset); PyList_Append(l, foffset); } + + if (PyTuple_GET_SIZE(value) > 2) { + ftitle = PyTuple_GET_ITEM(value, 2); + PyList_Append(l, ftitle); + } } return 0; @@ -186,12 +205,10 @@ static int _array_descr_walk_subarray(PyArray_ArrayDescr* adescr, PyObject *l) "(Hash) Error while getting shape item of subarray dtype ???"); return -1; } - Py_INCREF(item); PyList_Append(l, item); } } else if (PyInt_Check(adescr->shape)) { - Py_INCREF(adescr->shape); PyList_Append(l, adescr->shape); } else { @@ -219,12 +236,7 @@ static int _array_descr_walk(PyArray_Descr* descr, PyObject *l) } else { if(descr->fields != NULL && descr->fields != Py_None) { - if (!PyDict_Check(descr->fields)) { - PyErr_SetString(PyExc_SystemError, - "(Hash) fields is not a dict ???"); - return -1; - } - st = _array_descr_walk_fields(descr->fields, l); + st = _array_descr_walk_fields(descr->names, descr->fields, l); if (st) { return -1; } @@ -245,8 +257,7 @@ static int _array_descr_walk(PyArray_Descr* descr, PyObject *l) */ static int _PyArray_DescrHashImp(PyArray_Descr *descr, npy_hash_t *hash) { - PyObject *l, *tl, *item; - Py_ssize_t i; + PyObject *l, *tl; int st; l = PyList_New(0); @@ -256,44 +267,31 @@ static int _PyArray_DescrHashImp(PyArray_Descr *descr, npy_hash_t *hash) st = _array_descr_walk(descr, l); if (st) { - goto clean_l; + Py_DECREF(l); + return -1; } /* * Convert the list to tuple and compute the tuple hash using python * builtin function */ - tl = PyTuple_New(PyList_Size(l)); - for(i = 0; i < PyList_Size(l); ++i) { - item = PyList_GetItem(l, i); - if (item == NULL) { - PyErr_SetString(PyExc_SystemError, - "(Hash) Error while translating the list into a tuple " \ - "(NULL item)"); - goto clean_tl; - } - PyTuple_SetItem(tl, i, item); - } + tl = PyList_AsTuple(l); + Py_DECREF(l); + if (tl == NULL) + return -1; *hash = PyObject_Hash(tl); + Py_DECREF(tl); if (*hash == -1) { /* XXX: does PyObject_Hash set an exception on failure ? */ #if 0 PyErr_SetString(PyExc_SystemError, "(Hash) Error while hashing final tuple"); #endif - goto clean_tl; + return -1; } - Py_DECREF(tl); - Py_DECREF(l); return 0; - -clean_tl: - Py_DECREF(tl); -clean_l: - Py_DECREF(l); - return -1; } NPY_NO_EXPORT npy_hash_t diff --git a/numpy/core/src/multiarray/item_selection.c b/numpy/core/src/multiarray/item_selection.c index c59a125e0..d3b9a036d 100644 --- a/numpy/core/src/multiarray/item_selection.c +++ b/numpy/core/src/multiarray/item_selection.c @@ -408,8 +408,7 @@ PyArray_PutTo(PyArrayObject *self, PyObject* values0, PyObject *indices0, if (copied) { Py_DECREF(self); } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; fail: Py_XDECREF(indices); @@ -482,8 +481,7 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0) if (nv <= 0) { Py_XDECREF(values); Py_XDECREF(mask); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } src = PyArray_DATA(values); @@ -527,8 +525,7 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0) if (copied) { Py_DECREF(self); } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; fail: Py_XDECREF(mask); @@ -1160,6 +1157,7 @@ partition_prep_kth_array(PyArrayObject * ktharray, npy_intp nkth, i; if (!PyArray_CanCastSafely(PyArray_TYPE(ktharray), NPY_INTP)) { + /* 2013-05-18, 1.8 */ if (DEPRECATE("Calling partition with a non integer index" " will result in an error in the future") < 0) { return NULL; @@ -1230,7 +1228,7 @@ PyArray_Partition(PyArrayObject *op, PyArrayObject * ktharray, int axis, if (which < 0 || which >= NPY_NSELECTS) { PyErr_SetString(PyExc_ValueError, "not a valid partition kind"); - return NULL; + return -1; } part = get_partition_func(PyArray_TYPE(op), which); if (part == NULL) { @@ -1241,7 +1239,7 @@ PyArray_Partition(PyArrayObject *op, PyArrayObject * ktharray, int axis, else { PyErr_SetString(PyExc_TypeError, "type does not have compare function"); - return NULL; + return -1; } } @@ -1724,7 +1722,7 @@ PyArray_SearchSorted(PyArrayObject *op1, PyObject *op2, } /* ret is a contiguous array of intp type to hold returned indexes */ - ret = (PyArrayObject *)PyArray_New(Py_TYPE(ap2), PyArray_NDIM(ap2), + ret = (PyArrayObject *)PyArray_New(&PyArray_Type, PyArray_NDIM(ap2), PyArray_DIMS(ap2), NPY_INTP, NULL, NULL, 0, 0, (PyObject *)ap2); if (ret == NULL) { @@ -2334,36 +2332,27 @@ finish: } /* Create views into ret, one for each dimension */ - if (ndim == 1) { - /* Directly switch to one dimensions (dimension 1 is 1 anyway) */ - ((PyArrayObject_fields *)ret)->nd = 1; - PyTuple_SET_ITEM(ret_tuple, 0, (PyObject *)ret); - } - else { - for (i = 0; i < ndim; ++i) { - PyArrayObject *view; - npy_intp stride = ndim * NPY_SIZEOF_INTP; - - view = (PyArrayObject *)PyArray_New(Py_TYPE(self), 1, - &nonzero_count, - NPY_INTP, &stride, - PyArray_BYTES(ret) + i*NPY_SIZEOF_INTP, - 0, 0, (PyObject *)self); - if (view == NULL) { - Py_DECREF(ret); - Py_DECREF(ret_tuple); - return NULL; - } - Py_INCREF(ret); - if (PyArray_SetBaseObject(view, (PyObject *)ret) < 0) { - Py_DECREF(ret); - Py_DECREF(ret_tuple); - } - PyTuple_SET_ITEM(ret_tuple, i, (PyObject *)view); + for (i = 0; i < ndim; ++i) { + npy_intp stride = ndim * NPY_SIZEOF_INTP; + + PyArrayObject *view = (PyArrayObject *)PyArray_New(Py_TYPE(ret), 1, + &nonzero_count, NPY_INTP, &stride, + PyArray_BYTES(ret) + i*NPY_SIZEOF_INTP, + 0, PyArray_FLAGS(ret), (PyObject *)ret); + if (view == NULL) { + Py_DECREF(ret); + Py_DECREF(ret_tuple); + return NULL; } - - Py_DECREF(ret); + Py_INCREF(ret); + if (PyArray_SetBaseObject(view, (PyObject *)ret) < 0) { + Py_DECREF(ret); + Py_DECREF(ret_tuple); + return NULL; + } + PyTuple_SET_ITEM(ret_tuple, i, (PyObject *)view); } + Py_DECREF(ret); return ret_tuple; } diff --git a/numpy/core/src/multiarray/iterators.c b/numpy/core/src/multiarray/iterators.c index 81c6b2a8e..829994b1e 100644 --- a/numpy/core/src/multiarray/iterators.c +++ b/numpy/core/src/multiarray/iterators.c @@ -1577,7 +1577,8 @@ static PyObject * arraymultiter_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *kwds) { - Py_ssize_t n, i; + Py_ssize_t n = 0; + Py_ssize_t i, j, k; PyArrayMultiIterObject *multi; PyObject *arr; @@ -1587,13 +1588,27 @@ arraymultiter_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *k return NULL; } - n = PyTuple_Size(args); + for (j = 0; j < PyTuple_Size(args); ++j) { + PyObject *obj = PyTuple_GET_ITEM(args, j); + + if (PyObject_IsInstance(obj, (PyObject *)&PyArrayMultiIter_Type)) { + /* + * If obj is a multi-iterator, all its arrays will be added + * to the new multi-iterator. + */ + n += ((PyArrayMultiIterObject *)obj)->numiter; + } + else { + /* If not, will try to convert it to a single array */ + ++n; + } + } if (n < 2 || n > NPY_MAXARGS) { if (PyErr_Occurred()) { return NULL; } PyErr_Format(PyExc_ValueError, - "Need at least two and fewer than (%d) " \ + "Need at least two and fewer than (%d) " "array objects.", NPY_MAXARGS); return NULL; } @@ -1606,20 +1621,38 @@ arraymultiter_new(PyTypeObject *NPY_UNUSED(subtype), PyObject *args, PyObject *k multi->numiter = n; multi->index = 0; - for (i = 0; i < n; i++) { - multi->iters[i] = NULL; - } - for (i = 0; i < n; i++) { - arr = PyArray_FromAny(PyTuple_GET_ITEM(args, i), NULL, 0, 0, 0, NULL); - if (arr == NULL) { - goto fail; + i = 0; + for (j = 0; j < PyTuple_GET_SIZE(args); ++j) { + PyObject *obj = PyTuple_GET_ITEM(args, j); + PyArrayIterObject *it; + + if (PyObject_IsInstance(obj, (PyObject *)&PyArrayMultiIter_Type)) { + PyArrayMultiIterObject *mit = (PyArrayMultiIterObject *)obj; + + for (k = 0; k < mit->numiter; ++k) { + arr = (PyObject *)mit->iters[k]->ao; + assert (arr != NULL); + it = (PyArrayIterObject *)PyArray_IterNew(arr); + if (it == NULL) { + goto fail; + } + multi->iters[i++] = it; + } } - if ((multi->iters[i] = (PyArrayIterObject *)PyArray_IterNew(arr)) - == NULL) { - goto fail; + else { + arr = PyArray_FromAny(obj, NULL, 0, 0, 0, NULL); + if (arr == NULL) { + goto fail; + } + it = (PyArrayIterObject *)PyArray_IterNew(arr); + if (it == NULL) { + goto fail; + } + multi->iters[i++] = it; + Py_DECREF(arr); } - Py_DECREF(arr); } + assert (i == n); if (PyArray_Broadcast(multi) < 0) { goto fail; } @@ -1760,8 +1793,7 @@ arraymultiter_reset(PyArrayMultiIterObject *self, PyObject *args) return NULL; } PyArray_MultiIter_RESET(self); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyMethodDef arraymultiter_methods[] = { diff --git a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src index 38e7656f3..0fe63c13b 100644 --- a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src +++ b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src @@ -199,9 +199,11 @@ static NPY_GCC_OPT_3 void npy_intp N, npy_intp NPY_UNUSED(src_itemsize), NpyAuxData *NPY_UNUSED(data)) { -# if @elsize@ != 16 +#if @elsize@ != 16 +# if !(@elsize@ == 1 && @dst_contig@) @type@ temp; -# else +# endif +#else npy_uint64 temp0, temp1; #endif #if @is_aligned@ && @elsize@ != 16 diff --git a/numpy/core/src/multiarray/mapping.c b/numpy/core/src/multiarray/mapping.c index a510c7b0c..42a12db14 100644 --- a/numpy/core/src/multiarray/mapping.c +++ b/numpy/core/src/multiarray/mapping.c @@ -11,6 +11,7 @@ #include "npy_config.h" #include "npy_pycompat.h" +#include "npy_import.h" #include "common.h" #include "iterators.h" @@ -214,6 +215,7 @@ prepare_index(PyArrayObject *self, PyObject *index, } for (i = 0; i < n; i++) { PyObject *tmp_obj = PySequence_GetItem(index, i); + /* if getitem fails (unusual) treat this as a single index */ if (tmp_obj == NULL) { PyErr_Clear(); make_tuple = 0; @@ -283,34 +285,13 @@ prepare_index(PyArrayObject *self, PyObject *index, /* Index is an ellipsis (`...`) */ if (obj == Py_Ellipsis) { - /* - * If there is more then one Ellipsis, it is replaced. Deprecated, - * since it is hard to imagine anyone using two Ellipsis and - * actually planning on all but the first being automatically - * replaced with a slice. - */ + /* At most one ellipsis in an index */ if (index_type & HAS_ELLIPSIS) { - if (DEPRECATE( - "an index can only have a single Ellipsis (`...`); " - "replace all but one with slices (`:`).") < 0) { - goto failed_building_indices; - } - index_type |= HAS_SLICE; - - indices[curr_idx].type = HAS_SLICE; - indices[curr_idx].object = PySlice_New(NULL, NULL, NULL); - - if (indices[curr_idx].object == NULL) { - goto failed_building_indices; - } - - used_ndim += 1; - new_ndim += 1; - curr_idx += 1; - continue; + PyErr_Format(PyExc_IndexError, + "an index can only have a single ellipsis ('...')"); + goto failed_building_indices; } index_type |= HAS_ELLIPSIS; - indices[curr_idx].type = HAS_ELLIPSIS; indices[curr_idx].object = NULL; /* number of slices it is worth, won't update if it is 0: */ @@ -412,99 +393,8 @@ prepare_index(PyArrayObject *self, PyObject *index, goto failed_building_indices; } } - /* - * Special case to allow 0-d boolean indexing with - * scalars. Should be removed after boolean-array - * like as integer-array like deprecation. - * (does not cover ufunc.at, because it does not use the - * boolean special case, but that should not matter...) - * Since all but strictly boolean indices are invalid, - * there is no need for any further conversion tries. - */ - else if (PyArray_NDIM(self) == 0) { - arr = tmp_arr; - } else { - /* - * These Checks can be removed after deprecation, since - * they should then be either correct already or error out - * later just like a normal array. - */ - if (PyArray_ISBOOL(tmp_arr)) { - if (DEPRECATE_FUTUREWARNING( - "in the future, boolean array-likes will be " - "handled as a boolean array index") < 0) { - Py_DECREF(tmp_arr); - goto failed_building_indices; - } - if (PyArray_NDIM(tmp_arr) == 0) { - /* - * Need to raise an error here, since the - * DeprecationWarning before was not triggered. - * TODO: A `False` triggers a Deprecation *not* a - * a FutureWarning. - */ - PyErr_SetString(PyExc_IndexError, - "in the future, 0-d boolean arrays will be " - "interpreted as a valid boolean index"); - Py_DECREF(tmp_arr); - goto failed_building_indices; - } - else { - arr = tmp_arr; - } - } - /* - * Note: Down the road, the integers will be cast to intp. - * The user has to make sure they can be safely cast. - * If not, we might index wrong instead of an giving - * an error. - */ - else if (!PyArray_ISINTEGER(tmp_arr)) { - if (PyArray_NDIM(tmp_arr) == 0) { - /* match integer deprecation warning */ - if (DEPRECATE( - "using a non-integer number instead of an " - "integer will result in an error in the " - "future") < 0) { - - /* The error message raised in the future */ - PyErr_SetString(PyExc_IndexError, - "only integers, slices (`:`), ellipsis (`...`), " - "numpy.newaxis (`None`) and integer or boolean " - "arrays are valid indices"); - Py_DECREF((PyObject *)tmp_arr); - goto failed_building_indices; - } - } - else { - if (DEPRECATE( - "non integer (and non boolean) array-likes " - "will not be accepted as indices in the " - "future") < 0) { - - /* Error message to be raised in the future */ - PyErr_SetString(PyExc_IndexError, - "non integer (and non boolean) array-likes will " - "not be accepted as indices in the future"); - Py_DECREF((PyObject *)tmp_arr); - goto failed_building_indices; - } - } - } - - arr = (PyArrayObject *)PyArray_FromArray(tmp_arr, - PyArray_DescrFromType(NPY_INTP), - NPY_ARRAY_FORCECAST); - - if (arr == NULL) { - /* Since this will be removed, handle this later */ - PyErr_Clear(); - arr = tmp_arr; - } - else { - Py_DECREF((PyObject *)tmp_arr); - } + arr = tmp_arr; } } else { @@ -566,6 +456,7 @@ prepare_index(PyArrayObject *self, PyObject *index, index_type |= HAS_FANCY; indices[curr_idx].type = HAS_0D_BOOL; + indices[curr_idx].value = 1; /* TODO: This can't fail, right? Is there a faster way? */ if (PyObject_IsTrue((PyObject *)arr)) { @@ -612,6 +503,7 @@ prepare_index(PyArrayObject *self, PyObject *index, index_type |= HAS_FANCY; for (i=0; i < n; i++) { indices[curr_idx].type = HAS_FANCY; + indices[curr_idx].value = PyArray_DIM(arr, i); indices[curr_idx].object = (PyObject *)nonzero_result[i]; used_ndim += 1; @@ -654,6 +546,7 @@ prepare_index(PyArrayObject *self, PyObject *index, index_type |= HAS_FANCY; indices[curr_idx].type = HAS_FANCY; + indices[curr_idx].value = -1; indices[curr_idx].object = (PyObject *)arr; used_ndim += 1; @@ -741,7 +634,7 @@ prepare_index(PyArrayObject *self, PyObject *index, /* * At this point indices are all set correctly, no bounds checking * has been made and the new array may still have more dimensions - * then is possible. + * than is possible and boolean indexing arrays may have an incorrect shape. * * Check this now so we do not have to worry about it later. * It can happen for fancy indexing or with newaxis. @@ -756,6 +649,50 @@ prepare_index(PyArrayObject *self, PyObject *index, NPY_MAXDIMS, (new_ndim + fancy_ndim)); goto failed_building_indices; } + + /* + * If we had a fancy index, we may have had a boolean array index. + * So check if this had the correct shape now that we can find out + * which axes it acts on. + */ + used_ndim = 0; + for (i = 0; i < curr_idx; i++) { + if ((indices[i].type == HAS_FANCY) && indices[i].value > 0) { + if (indices[i].value != PyArray_DIM(self, used_ndim)) { + static PyObject *warning; + + char err_msg[174]; + PyOS_snprintf(err_msg, sizeof(err_msg), + "boolean index did not match indexed array along " + "dimension %d; dimension is %" NPY_INTP_FMT + " but corresponding boolean dimension is %" NPY_INTP_FMT, + used_ndim, PyArray_DIM(self, used_ndim), + indices[i].value); + + npy_cache_import( + "numpy", "VisibleDeprecationWarning", &warning); + if (warning == NULL) { + goto failed_building_indices; + } + + if (PyErr_WarnEx(warning, err_msg, 1) < 0) { + goto failed_building_indices; + } + break; + } + } + + if (indices[i].type == HAS_ELLIPSIS) { + used_ndim += indices[i].value; + } + else if ((indices[i].type == HAS_NEWAXIS) || + (indices[i].type == HAS_0D_BOOL)) { + used_ndim += 0; + } + else { + used_ndim += 1; + } + } } *num = curr_idx; @@ -1173,8 +1110,6 @@ array_assign_boolean_subscript(PyArrayObject *self, return -1; } - NPY_BEGIN_THREADS_NDITER(iter); - innerstrides = NpyIter_GetInnerStrideArray(iter); dataptrs = NpyIter_GetDataPtrArray(iter); @@ -1194,6 +1129,8 @@ array_assign_boolean_subscript(PyArrayObject *self, return -1; } + NPY_BEGIN_THREADS_NDITER(iter); + do { innersize = *NpyIter_GetInnerLoopSizePtr(iter); self_data = dataptrs[0]; @@ -1313,6 +1250,52 @@ array_subscript_asarray(PyArrayObject *self, PyObject *op) return PyArray_EnsureAnyArray(array_subscript(self, op)); } +NPY_NO_EXPORT int +obj_is_string_or_stringlist(PyObject *op) +{ +#if defined(NPY_PY3K) + if (PyUnicode_Check(op)) { +#else + if (PyString_Check(op) || PyUnicode_Check(op)) { +#endif + return 1; + } + else if (PySequence_Check(op) && !PyTuple_Check(op)) { + int seqlen, i; + PyObject *obj = NULL; + seqlen = PySequence_Size(op); + + /* quit if we come across a 0-d array (seqlen==-1) or a 0-len array */ + if (seqlen == -1) { + PyErr_Clear(); + return 0; + } + if (seqlen == 0) { + return 0; + } + + for (i = 0; i < seqlen; i++) { + obj = PySequence_GetItem(op, i); + if (obj == NULL) { + /* only happens for strange sequence objects. Silently fail */ + PyErr_Clear(); + return 0; + } + +#if defined(NPY_PY3K) + if (!PyUnicode_Check(obj)) { +#else + if (!PyString_Check(obj) && !PyUnicode_Check(obj)) { +#endif + Py_DECREF(obj); + return 0; + } + Py_DECREF(obj); + } + return 1; + } + return 0; +} /* * General function for indexing a NumPy array with a Python object. @@ -1322,7 +1305,7 @@ array_subscript(PyArrayObject *self, PyObject *op) { int index_type; int index_num; - int i, ndim, fancy_ndim, fancy; + int i, ndim, fancy_ndim; /* * Index info array. We can have twice as many indices as dimensions * (because of None). The + 1 is to not need to check as much. @@ -1334,76 +1317,26 @@ array_subscript(PyArrayObject *self, PyObject *op) PyArrayMapIterObject * mit = NULL; - /* Check for multiple field access */ - if (PyDataType_HASFIELDS(PyArray_DESCR(self))) { - /* Check for single field access */ - /* - * TODO: Moving this code block into the HASFIELDS, means that - * string integers temporarily work as indices. - */ - if (PyString_Check(op) || PyUnicode_Check(op)) { - PyObject *temp, *obj; - - if (PyDataType_HASFIELDS(PyArray_DESCR(self))) { - obj = PyDict_GetItem(PyArray_DESCR(self)->fields, op); - if (obj != NULL) { - PyArray_Descr *descr; - int offset; - PyObject *title; - - if (PyArg_ParseTuple(obj, "Oi|O", &descr, &offset, &title)) { - Py_INCREF(descr); - return PyArray_GetField(self, descr, offset); - } - } - } + /* return fields if op is a string index */ + if (PyDataType_HASFIELDS(PyArray_DESCR(self)) && + obj_is_string_or_stringlist(op)) { + PyObject *obj; + static PyObject *indexfunc = NULL; + npy_cache_import("numpy.core._internal", "_index_fields", &indexfunc); + if (indexfunc == NULL) { + return NULL; + } - temp = op; - if (PyUnicode_Check(op)) { - temp = PyUnicode_AsUnicodeEscapeString(op); - } - PyErr_Format(PyExc_ValueError, - "field named %s not found", - PyBytes_AsString(temp)); - if (temp != op) { - Py_DECREF(temp); - } + obj = PyObject_CallFunction(indexfunc, "OO", self, op); + if (obj == NULL) { return NULL; } - else if (PySequence_Check(op) && !PyTuple_Check(op)) { - int seqlen, i; - PyObject *obj; - seqlen = PySequence_Size(op); - for (i = 0; i < seqlen; i++) { - obj = PySequence_GetItem(op, i); - if (!PyString_Check(obj) && !PyUnicode_Check(obj)) { - Py_DECREF(obj); - break; - } - Py_DECREF(obj); - } - /* - * Extract multiple fields if all elements in sequence - * are either string or unicode (i.e. no break occurred). - */ - fancy = ((seqlen > 0) && (i == seqlen)); - if (fancy) { - PyObject *_numpy_internal; - _numpy_internal = PyImport_ImportModule("numpy.core._internal"); - if (_numpy_internal == NULL) { - return NULL; - } - obj = PyObject_CallMethod(_numpy_internal, - "_index_fields", "OO", self, op); - Py_DECREF(_numpy_internal); - if (obj == NULL) { - return NULL; - } - PyArray_ENABLEFLAGS((PyArrayObject*)obj, NPY_ARRAY_WARN_ON_WRITE); - return obj; - } + /* warn if writing to a copy. copies will have no base */ + if (PyArray_BASE((PyArrayObject*)obj) == NULL) { + PyArray_ENABLEFLAGS((PyArrayObject*)obj, NPY_ARRAY_WARN_ON_WRITE); } + return obj; } /* Prepare the indices */ @@ -1682,10 +1615,11 @@ attempt_1d_fallback(PyArrayObject *self, PyObject *ind, PyObject *op) if (iter_ass_subscript(self_iter, ind, op) < 0) { goto fail; } - + Py_XDECREF((PyObject *)self_iter); Py_DECREF(err); + /* 2014-06-12, 1.9 */ if (DEPRECATE( "assignment will raise an error in the future, most likely " "because your index result shape does not match the value array " @@ -1699,6 +1633,7 @@ attempt_1d_fallback(PyArrayObject *self, PyObject *ind, PyObject *op) if (!PyErr_ExceptionMatches(err)) { PyObject *err, *val, *tb; PyErr_Fetch(&err, &val, &tb); + /* 2014-06-12, 1.9 */ DEPRECATE_FUTUREWARNING( "assignment exception type will change in the future"); PyErr_Restore(err, val, tb); @@ -1735,35 +1670,39 @@ array_assign_subscript(PyArrayObject *self, PyObject *ind, PyObject *op) return -1; } - /* Single field access */ - if (PyDataType_HASFIELDS(PyArray_DESCR(self))) { - if (PyString_Check(ind) || PyUnicode_Check(ind)) { - PyObject *obj; - - obj = PyDict_GetItem(PyArray_DESCR(self)->fields, ind); - if (obj != NULL) { - PyArray_Descr *descr; - int offset; - PyObject *title; + /* field access */ + if (PyDataType_HASFIELDS(PyArray_DESCR(self)) && + obj_is_string_or_stringlist(ind)) { + PyObject *obj; + static PyObject *indexfunc = NULL; - if (PyArg_ParseTuple(obj, "Oi|O", &descr, &offset, &title)) { - Py_INCREF(descr); - return PyArray_SetField(self, descr, offset, op); - } - } #if defined(NPY_PY3K) - PyErr_Format(PyExc_ValueError, - "field named %S not found", - ind); + if (!PyUnicode_Check(ind)) { #else - PyErr_Format(PyExc_ValueError, - "field named %s not found", - PyString_AsString(ind)); + if (!PyString_Check(ind) && !PyUnicode_Check(ind)) { #endif + PyErr_SetString(PyExc_ValueError, + "multi-field assignment is not supported"); + } + + npy_cache_import("numpy.core._internal", "_index_fields", &indexfunc); + if (indexfunc == NULL) { return -1; } - } + obj = PyObject_CallFunction(indexfunc, "OO", self, ind); + if (obj == NULL) { + return -1; + } + + if (PyArray_CopyObject((PyArrayObject*)obj, op) < 0) { + Py_DECREF(obj); + return -1; + } + Py_DECREF(obj); + + return 0; + } /* Prepare the indices */ index_type = prepare_index(self, ind, indices, &index_num, @@ -2446,7 +2385,7 @@ PyArray_MapIterCheckIndices(PyArrayMapIterObject *mit) NpyIter_IterNextFunc *op_iternext; npy_intp outer_dim, indval; int outer_axis; - npy_intp itersize, iterstride; + npy_intp itersize, *iterstride; char **iterptr; PyArray_Descr *intp_type; int i; @@ -2517,7 +2456,7 @@ PyArray_MapIterCheckIndices(PyArrayMapIterObject *mit) NPY_BEGIN_THREADS_NDITER(op_iter); iterptr = NpyIter_GetDataPtrArray(op_iter); - iterstride = NpyIter_GetInnerStrideArray(op_iter)[0]; + iterstride = NpyIter_GetInnerStrideArray(op_iter); do { itersize = *NpyIter_GetInnerLoopSizePtr(op_iter); while (itersize--) { @@ -2528,7 +2467,7 @@ PyArray_MapIterCheckIndices(PyArrayMapIterObject *mit) NpyIter_Deallocate(op_iter); return -1; } - *iterptr += iterstride; + *iterptr += *iterstride; } } while (op_iternext(op_iter)); diff --git a/numpy/core/src/multiarray/mapping.h b/numpy/core/src/multiarray/mapping.h index f59f6bb22..40ccabd62 100644 --- a/numpy/core/src/multiarray/mapping.h +++ b/numpy/core/src/multiarray/mapping.h @@ -19,7 +19,11 @@ typedef struct { * Object of index: slice, array, or NULL. Owns a reference. */ PyObject *object; - /* Value of an integer index or number of slices an Ellipsis is worth */ + /* + * Value of an integer index, number of slices an Ellipsis is worth, + * -1 if input was an integer array and the original size of the + * boolean array if it is a converted boolean array. + */ npy_intp value; /* kind of index, see constants in mapping.c */ int type; diff --git a/numpy/core/src/multiarray/methods.c b/numpy/core/src/multiarray/methods.c index 851a37456..fd329cb8c 100644 --- a/numpy/core/src/multiarray/methods.c +++ b/numpy/core/src/multiarray/methods.c @@ -10,6 +10,7 @@ #include "npy_config.h" #include "npy_pycompat.h" +#include "npy_import.h" #include "ufunc_override.h" #include "common.h" #include "ctors.h" @@ -149,8 +150,7 @@ array_fill(PyArrayObject *self, PyObject *args) if (PyArray_FillWithScalar(self, obj) < 0) { return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -359,15 +359,23 @@ NPY_NO_EXPORT PyObject * PyArray_GetField(PyArrayObject *self, PyArray_Descr *typed, int offset) { PyObject *ret = NULL; + PyObject *safe; + static PyObject *checkfunc = NULL; - if (offset < 0 || (offset + typed->elsize) > PyArray_DESCR(self)->elsize) { - PyErr_Format(PyExc_ValueError, - "Need 0 <= offset <= %d for requested type " - "but received offset = %d", - PyArray_DESCR(self)->elsize-typed->elsize, offset); - Py_DECREF(typed); + npy_cache_import("numpy.core._internal", "_getfield_is_safe", &checkfunc); + if (checkfunc == NULL) { return NULL; } + + /* check that we are not reinterpreting memory containing Objects */ + /* only returns True or raises */ + safe = PyObject_CallFunction(checkfunc, "OOi", PyArray_DESCR(self), + typed, offset); + if (safe == NULL) { + return NULL; + } + Py_DECREF(safe); + ret = PyArray_NewFromDescr(Py_TYPE(self), typed, PyArray_NDIM(self), PyArray_DIMS(self), @@ -418,23 +426,12 @@ PyArray_SetField(PyArrayObject *self, PyArray_Descr *dtype, PyObject *ret = NULL; int retval = 0; - if (offset < 0 || (offset + dtype->elsize) > PyArray_DESCR(self)->elsize) { - PyErr_Format(PyExc_ValueError, - "Need 0 <= offset <= %d for requested type " - "but received offset = %d", - PyArray_DESCR(self)->elsize-dtype->elsize, offset); - Py_DECREF(dtype); - return -1; - } - ret = PyArray_NewFromDescr(Py_TYPE(self), - dtype, PyArray_NDIM(self), PyArray_DIMS(self), - PyArray_STRIDES(self), PyArray_BYTES(self) + offset, - PyArray_FLAGS(self), (PyObject *)self); + /* getfield returns a view we can write to */ + ret = PyArray_GetField(self, dtype, offset); if (ret == NULL) { return -1; } - PyArray_UpdateFlags((PyArrayObject *)ret, NPY_ARRAY_UPDATE_ALL); retval = PyArray_CopyObject((PyArrayObject *)ret, val); Py_DECREF(ret); return retval; @@ -456,18 +453,10 @@ array_setfield(PyArrayObject *self, PyObject *args, PyObject *kwds) return NULL; } - if (PyDataType_REFCHK(PyArray_DESCR(self))) { - PyErr_SetString(PyExc_RuntimeError, - "cannot call setfield on an object array"); - Py_DECREF(dtype); - return NULL; - } - if (PyArray_SetField(self, dtype, offset, value) < 0) { return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /* This doesn't change the descriptor just the actual data... @@ -605,8 +594,7 @@ array_tofile(PyArrayObject *self, PyObject *args, PyObject *kwds) goto fail; } Py_DECREF(file); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; fail: Py_DECREF(file); @@ -757,8 +745,7 @@ array_setscalar(PyArrayObject *self, PyObject *args) return NULL; } else { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } } @@ -1055,14 +1042,12 @@ array_resize(PyArrayObject *self, PyObject *args, PyObject *kwds) } if (size == 0) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } else if (size == 1) { obj = PyTuple_GET_ITEM(args, 0); if (obj == Py_None) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } args = obj; } @@ -1079,8 +1064,7 @@ array_resize(PyArrayObject *self, PyObject *args, PyObject *kwds) return NULL; } Py_DECREF(ret); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -1177,8 +1161,7 @@ array_sort(PyArrayObject *self, PyObject *args, PyObject *kwds) if (val < 0) { return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -1246,8 +1229,7 @@ array_partition(PyArrayObject *self, PyObject *args, PyObject *kwds) if (val < 0) { return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -1806,8 +1788,7 @@ array_setstate(PyArrayObject *self, PyObject *args) PyArray_UpdateFlags(self, NPY_ARRAY_UPDATE_ALL); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /*NUMPY_API*/ @@ -1884,8 +1865,7 @@ array_dump(PyArrayObject *self, PyObject *args) if (ret < 0) { return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } @@ -2305,8 +2285,7 @@ array_setflags(PyArrayObject *self, PyObject *args, PyObject *kwds) } } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } diff --git a/numpy/core/src/multiarray/multiarray_tests.c.src b/numpy/core/src/multiarray/multiarray_tests.c.src index a80d3af19..5e247e15e 100644 --- a/numpy/core/src/multiarray/multiarray_tests.c.src +++ b/numpy/core/src/multiarray/multiarray_tests.c.src @@ -1,6 +1,9 @@ +/* -*-c-*- */ #define NPY_NO_DEPRECATED_API NPY_API_VERSION #include <Python.h> #include "numpy/arrayobject.h" +#include "mem_overlap.h" +#include "npy_extint128.h" /* test PyArray_IsPythonScalar, before including private py3 compat header */ static PyObject * @@ -155,7 +158,7 @@ test_neighborhood_iterator(PyObject* NPY_UNUSED(self), PyObject* args) for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) { PyObject* bound; bound = PySequence_GetItem(b, i); - if (bounds == NULL) { + if (bound == NULL) { goto clean_itx; } if (!PyInt_Check(bound)) { @@ -314,7 +317,7 @@ test_neighborhood_iterator_oob(PyObject* NPY_UNUSED(self), PyObject* args) for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) { PyObject* bound; bound = PySequence_GetItem(b1, i); - if (bounds == NULL) { + if (bound == NULL) { goto clean_itx; } if (!PyInt_Check(bound)) { @@ -338,7 +341,7 @@ test_neighborhood_iterator_oob(PyObject* NPY_UNUSED(self), PyObject* args) for (i = 0; i < 2 * PyArray_NDIM(ax); ++i) { PyObject* bound; bound = PySequence_GetItem(b2, i); - if (bounds == NULL) { + if (bound == NULL) { goto clean_itx; } if (!PyInt_Check(bound)) { @@ -412,8 +415,7 @@ test_pydatamem_seteventhook_start(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUS { malloc_free_counts[0] = malloc_free_counts[1] = 0; old_hook = PyDataMem_SetEventHook(test_hook, (void *) malloc_free_counts, &old_data); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject* @@ -440,8 +442,7 @@ test_pydatamem_seteventhook_end(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } @@ -563,8 +564,7 @@ inplace_increment(PyObject *dummy, PyObject *args) Py_DECREF(mit); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; fail: Py_XDECREF(mit); @@ -762,7 +762,7 @@ array_indexing(PyObject *NPY_UNUSED(self), PyObject *args) if (mode == 1) { if (PySequence_SetItem(arr, i, op) < 0) { return NULL; - } + } Py_RETURN_NONE; } @@ -950,6 +950,607 @@ test_nditer_too_large(PyObject *NPY_UNUSED(self), PyObject *args) { } +static PyObject * +array_solve_diophantine(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) +{ + PyObject *A = NULL; + PyObject *U = NULL; + Py_ssize_t b_input = 0; + Py_ssize_t max_work = -1; + int simplify = 0; + int require_ub_nontrivial = 0; + static char *kwlist[] = {"A", "U", "b", "max_work", "simplify", + "require_ub_nontrivial", NULL}; + + diophantine_term_t terms[2*NPY_MAXDIMS+2]; + npy_int64 x[2*NPY_MAXDIMS+2]; + npy_int64 b; + unsigned int nterms, j; + mem_overlap_t result = MEM_OVERLAP_YES; + PyObject *retval = NULL; + NPY_BEGIN_THREADS_DEF; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O!O!n|nii", kwlist, + &PyTuple_Type, &A, + &PyTuple_Type, &U, + &b_input, &max_work, &simplify, + &require_ub_nontrivial)) { + return NULL; + } + + if (PyTuple_GET_SIZE(A) > sizeof(terms) / sizeof(diophantine_term_t)) { + PyErr_SetString(PyExc_ValueError, "too many terms in equation"); + goto fail; + } + + nterms = PyTuple_GET_SIZE(A); + + if (PyTuple_GET_SIZE(U) != nterms) { + PyErr_SetString(PyExc_ValueError, "A, U must be tuples of equal length"); + goto fail; + } + + for (j = 0; j < nterms; ++j) { + terms[j].a = (npy_int64)PyInt_AsSsize_t(PyTuple_GET_ITEM(A, j)); + if (terms[j].a == -1 && PyErr_Occurred()) { + goto fail; + } + terms[j].ub = (npy_int64)PyInt_AsSsize_t(PyTuple_GET_ITEM(U, j)); + if (terms[j].ub == -1 && PyErr_Occurred()) { + goto fail; + } + } + + b = b_input; + + NPY_BEGIN_THREADS; + if (simplify && !require_ub_nontrivial) { + if (diophantine_simplify(&nterms, terms, b)) { + result = MEM_OVERLAP_OVERFLOW; + } + } + if (result == MEM_OVERLAP_YES) { + result = solve_diophantine(nterms, terms, b, max_work, require_ub_nontrivial, x); + } + NPY_END_THREADS; + + if (result == MEM_OVERLAP_YES) { + retval = PyTuple_New(nterms); + if (retval == NULL) { + goto fail; + } + + for (j = 0; j < nterms; ++j) { + PyObject *obj; +#if defined(NPY_PY3K) + obj = PyLong_FromSsize_t(x[j]); +#else + obj = PyInt_FromSsize_t(x[j]); +#endif + if (obj == NULL) { + goto fail; + } + PyTuple_SET_ITEM(retval, j, obj); + } + } + else if (result == MEM_OVERLAP_NO) { + retval = Py_None; + Py_INCREF(retval); + } + else if (result == MEM_OVERLAP_ERROR) { + PyErr_SetString(PyExc_ValueError, "Invalid arguments"); + } + else if (result == MEM_OVERLAP_OVERFLOW) { + PyErr_SetString(PyExc_OverflowError, "Integer overflow"); + } + else if (result == MEM_OVERLAP_TOO_HARD) { + PyErr_SetString(PyExc_RuntimeError, "Too much work done"); + } + else { + PyErr_SetString(PyExc_RuntimeError, "Unknown error"); + } + + return retval; + +fail: + Py_XDECREF(retval); + return NULL; +} + + +static PyObject * +array_internal_overlap(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) +{ + PyArrayObject * self = NULL; + static char *kwlist[] = {"self", "max_work", NULL}; + + mem_overlap_t result; + Py_ssize_t max_work = NPY_MAY_SHARE_EXACT; + NPY_BEGIN_THREADS_DEF; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|n", kwlist, + PyArray_Converter, &self, + &max_work)) { + return NULL; + } + + if (max_work < -2) { + PyErr_SetString(PyExc_ValueError, "Invalid value for max_work"); + goto fail; + } + + NPY_BEGIN_THREADS; + result = solve_may_have_internal_overlap(self, max_work); + NPY_END_THREADS; + + Py_XDECREF(self); + + if (result == MEM_OVERLAP_NO) { + Py_RETURN_FALSE; + } + else if (result == MEM_OVERLAP_YES) { + Py_RETURN_TRUE; + } + else if (result == MEM_OVERLAP_OVERFLOW) { + PyErr_SetString(PyExc_OverflowError, + "Integer overflow in computing overlap"); + return NULL; + } + else if (result == MEM_OVERLAP_TOO_HARD) { + PyErr_SetString(PyExc_ValueError, + "Exceeded max_work"); + return NULL; + } + else { + /* Doesn't happen usually */ + PyErr_SetString(PyExc_RuntimeError, + "Error in computing overlap"); + return NULL; + } + +fail: + Py_XDECREF(self); + return NULL; +} + + +static PyObject * +pylong_from_int128(npy_extint128_t value) +{ + PyObject *val_64 = NULL, *val = NULL, *tmp = NULL, *tmp2 = NULL; + + val_64 = PyLong_FromLong(64); + if (val_64 == NULL) { + goto fail; + } + + val = PyLong_FromUnsignedLongLong(value.hi); + if (val == NULL) { + goto fail; + } + + tmp = PyNumber_Lshift(val, val_64); + if (tmp == NULL) { + goto fail; + } + + Py_DECREF(val); + val = tmp; + + tmp = PyLong_FromUnsignedLongLong(value.lo); + if (tmp == NULL) { + goto fail; + } + + tmp2 = PyNumber_Or(val, tmp); + if (tmp2 == NULL) { + goto fail; + } + + Py_DECREF(val); + Py_DECREF(tmp); + + val = NULL; + tmp = NULL; + + if (value.sign < 0) { + val = PyNumber_Negative(tmp2); + if (val == NULL) { + goto fail; + } + Py_DECREF(tmp2); + return val; + } + else { + val = tmp2; + } + return val; + +fail: + Py_XDECREF(val_64); + Py_XDECREF(tmp); + Py_XDECREF(tmp2); + Py_XDECREF(val); + return NULL; +} + + +static int +int128_from_pylong(PyObject *obj, npy_extint128_t *result) +{ + PyObject *long_obj = NULL, *val_64 = NULL, *val_0 = NULL, + *mask_64 = NULL, *max_128 = NULL, *hi_bits = NULL, + *lo_bits = NULL, *tmp = NULL; + int cmp; + int negative_zero = 0; + + if (PyBool_Check(obj)) { + /* False means negative zero */ + negative_zero = 1; + } + + long_obj = PyObject_CallFunction((PyObject*)&PyLong_Type, "O", obj); + if (long_obj == NULL) { + goto fail; + } + + val_0 = PyLong_FromLong(0); + if (val_0 == NULL) { + goto fail; + } + + val_64 = PyLong_FromLong(64); + if (val_64 == NULL) { + goto fail; + } + + mask_64 = PyLong_FromUnsignedLongLong(0xffffffffffffffffULL); + if (mask_64 == NULL) { + goto fail; + } + + tmp = PyNumber_Lshift(mask_64, val_64); + if (tmp == NULL) { + goto fail; + } + max_128 = PyNumber_Or(tmp, mask_64); + if (max_128 == NULL) { + goto fail; + } + Py_DECREF(tmp); + tmp = NULL; + + cmp = PyObject_RichCompareBool(long_obj, val_0, Py_LT); + if (cmp == -1) { + goto fail; + } + else if (cmp == 1) { + tmp = PyNumber_Negative(long_obj); + if (tmp == NULL) { + goto fail; + } + Py_DECREF(long_obj); + long_obj = tmp; + tmp = NULL; + result->sign = -1; + } + else { + result->sign = 1; + } + + cmp = PyObject_RichCompareBool(long_obj, max_128, Py_GT); + if (cmp == 1) { + PyErr_SetString(PyExc_OverflowError, ""); + goto fail; + } + else if (cmp == -1) { + goto fail; + } + + hi_bits = PyNumber_Rshift(long_obj, val_64); + if (hi_bits == NULL) { + goto fail; + } + + lo_bits = PyNumber_And(long_obj, mask_64); + if (lo_bits == NULL) { + goto fail; + } + + result->hi = PyLong_AsUnsignedLongLong(hi_bits); + if (result->hi == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) { + goto fail; + } + + result->lo = PyLong_AsUnsignedLongLong(lo_bits); + if (result->lo == (unsigned PY_LONG_LONG)-1 && PyErr_Occurred()) { + goto fail; + } + + if (negative_zero && result->hi == 0 && result->lo == 0) { + result->sign = -1; + } + + Py_XDECREF(long_obj); + Py_XDECREF(val_64); + Py_XDECREF(val_0); + Py_XDECREF(mask_64); + Py_XDECREF(max_128); + Py_XDECREF(hi_bits); + Py_XDECREF(lo_bits); + Py_XDECREF(tmp); + return 0; + +fail: + Py_XDECREF(long_obj); + Py_XDECREF(val_64); + Py_XDECREF(val_0); + Py_XDECREF(mask_64); + Py_XDECREF(max_128); + Py_XDECREF(hi_bits); + Py_XDECREF(lo_bits); + Py_XDECREF(tmp); + return -1; +} + + +static PyObject * +extint_safe_binop(PyObject *NPY_UNUSED(self), PyObject *args) { + PY_LONG_LONG a, b, c; + int op; + char overflow = 0; + if (!PyArg_ParseTuple(args, "LLi", &a, &b, &op)) { + return NULL; + } + if (op == 1) { + c = safe_add(a, b, &overflow); + } + else if (op == 2) { + c = safe_sub(a, b, &overflow); + } + else if (op == 3) { + c = safe_mul(a, b, &overflow); + } + else { + PyErr_SetString(PyExc_ValueError, "invalid op"); + return NULL; + } + if (overflow) { + PyErr_SetString(PyExc_OverflowError, ""); + return NULL; + } + return PyLong_FromLongLong(c); +} + + +static PyObject * +extint_to_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PY_LONG_LONG a; + if (!PyArg_ParseTuple(args, "L", &a)) { + return NULL; + } + return pylong_from_int128(to_128(a)); +} + + +static PyObject * +extint_to_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a; + PY_LONG_LONG r; + char overflow = 0; + if (!PyArg_ParseTuple(args, "O", &a_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + r = to_64(a, &overflow); + if (overflow) { + PyErr_SetString(PyExc_OverflowError, ""); + return NULL; + } + return PyLong_FromLongLong(r); +} + + +static PyObject * +extint_mul_64_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PY_LONG_LONG a, b; + npy_extint128_t c; + if (!PyArg_ParseTuple(args, "LL", &a, &b)) { + return NULL; + } + c = mul_64_64(a, b); + return pylong_from_int128(c); +} + + +static PyObject * +extint_add_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj, *b_obj; + npy_extint128_t a, b, c; + char overflow = 0; + if (!PyArg_ParseTuple(args, "OO", &a_obj, &b_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a) || int128_from_pylong(b_obj, &b)) { + return NULL; + } + c = add_128(a, b, &overflow); + if (overflow) { + PyErr_SetString(PyExc_OverflowError, ""); + return NULL; + } + return pylong_from_int128(c); +} + + +static PyObject * +extint_sub_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj, *b_obj; + npy_extint128_t a, b, c; + char overflow = 0; + if (!PyArg_ParseTuple(args, "OO", &a_obj, &b_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a) || int128_from_pylong(b_obj, &b)) { + return NULL; + } + c = sub_128(a, b, &overflow); + if (overflow) { + PyErr_SetString(PyExc_OverflowError, ""); + return NULL; + } + return pylong_from_int128(c); +} + + +static PyObject * +extint_neg_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, b; + if (!PyArg_ParseTuple(args, "O", &a_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + b = neg_128(a); + return pylong_from_int128(b); +} + + +static PyObject * +extint_shl_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, b; + if (!PyArg_ParseTuple(args, "O", &a_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + b = shl_128(a); + return pylong_from_int128(b); +} + + +static PyObject * +extint_shr_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, b; + if (!PyArg_ParseTuple(args, "O", &a_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + b = shr_128(a); + return pylong_from_int128(b); +} + + +static PyObject * +extint_gt_128(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj, *b_obj; + npy_extint128_t a, b; + if (!PyArg_ParseTuple(args, "OO", &a_obj, &b_obj)) { + return NULL; + } + if (int128_from_pylong(a_obj, &a) || int128_from_pylong(b_obj, &b)) { + return NULL; + } + if (gt_128(a, b)) { + Py_RETURN_TRUE; + } + else { + Py_RETURN_FALSE; + } +} + + +static PyObject * +extint_divmod_128_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj, *ret = NULL, *tmp = NULL; + npy_extint128_t a, c; + PY_LONG_LONG b; + npy_int64 mod; + if (!PyArg_ParseTuple(args, "OL", &a_obj, &b)) { + goto fail; + } + if (b <= 0) { + PyErr_SetString(PyExc_ValueError, ""); + goto fail; + } + if (int128_from_pylong(a_obj, &a)) { + goto fail; + } + + c = divmod_128_64(a, b, &mod); + + ret = PyTuple_New(2); + + tmp = pylong_from_int128(c); + if (tmp == NULL) { + goto fail; + } + PyTuple_SET_ITEM(ret, 0, tmp); + + tmp = PyLong_FromLongLong(mod); + if (tmp == NULL) { + goto fail; + } + PyTuple_SET_ITEM(ret, 1, tmp); + return ret; + +fail: + Py_XDECREF(ret); + Py_XDECREF(tmp); + return NULL; +} + + +static PyObject * +extint_floordiv_128_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, c; + PY_LONG_LONG b; + if (!PyArg_ParseTuple(args, "OL", &a_obj, &b)) { + return NULL; + } + if (b <= 0) { + PyErr_SetString(PyExc_ValueError, ""); + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + c = floordiv_128_64(a, b); + return pylong_from_int128(c); +} + + +static PyObject * +extint_ceildiv_128_64(PyObject *NPY_UNUSED(self), PyObject *args) { + PyObject *a_obj; + npy_extint128_t a, c; + PY_LONG_LONG b; + if (!PyArg_ParseTuple(args, "OL", &a_obj, &b)) { + return NULL; + } + if (b <= 0) { + PyErr_SetString(PyExc_ValueError, ""); + return NULL; + } + if (int128_from_pylong(a_obj, &a)) { + return NULL; + } + c = ceildiv_128_64(a, b); + return pylong_from_int128(c); +} + + static PyMethodDef Multiarray_TestsMethods[] = { {"IsPythonScalar", IsPythonScalar, @@ -992,6 +1593,51 @@ static PyMethodDef Multiarray_TestsMethods[] = { {"test_nditer_too_large", test_nditer_too_large, METH_VARARGS, NULL}, + {"solve_diophantine", + (PyCFunction)array_solve_diophantine, + METH_VARARGS | METH_KEYWORDS, NULL}, + {"internal_overlap", + (PyCFunction)array_internal_overlap, + METH_VARARGS | METH_KEYWORDS, NULL}, + {"extint_safe_binop", + extint_safe_binop, + METH_VARARGS, NULL}, + {"extint_to_128", + extint_to_128, + METH_VARARGS, NULL}, + {"extint_to_64", + extint_to_64, + METH_VARARGS, NULL}, + {"extint_mul_64_64", + extint_mul_64_64, + METH_VARARGS, NULL}, + {"extint_add_128", + extint_add_128, + METH_VARARGS, NULL}, + {"extint_sub_128", + extint_sub_128, + METH_VARARGS, NULL}, + {"extint_neg_128", + extint_neg_128, + METH_VARARGS, NULL}, + {"extint_shl_128", + extint_shl_128, + METH_VARARGS, NULL}, + {"extint_shr_128", + extint_shr_128, + METH_VARARGS, NULL}, + {"extint_gt_128", + extint_gt_128, + METH_VARARGS, NULL}, + {"extint_divmod_128_64", + extint_divmod_128_64, + METH_VARARGS, NULL}, + {"extint_floordiv_128_64", + extint_floordiv_128_64, + METH_VARARGS, NULL}, + {"extint_ceildiv_128_64", + extint_ceildiv_128_64, + METH_VARARGS, NULL}, {NULL, NULL, 0, NULL} /* Sentinel */ }; diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 1a8fda94d..14df0899e 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -27,8 +27,8 @@ #include "numpy/npy_math.h" #include "npy_config.h" - #include "npy_pycompat.h" +#include "npy_import.h" NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0; @@ -60,10 +60,12 @@ NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0; #include "vdot.h" #include "templ_common.h" /* for npy_mul_with_overflow_intp */ #include "compiled_base.h" +#include "mem_overlap.h" /* Only here for API compatibility */ NPY_NO_EXPORT PyTypeObject PyBigArray_Type; + /*NUMPY_API * Get Priority from object */ @@ -239,7 +241,7 @@ PyArray_AsCArray(PyObject **op, void *ptr, npy_intp *dims, int nd, *op = (PyObject *)ap; return 0; - fail: +fail: PyErr_SetString(PyExc_MemoryError, "no memory"); return -1; } @@ -256,6 +258,7 @@ PyArray_As1D(PyObject **op, char **ptr, int *d1, int typecode) PyArray_Descr *descr; static const char msg[] = "PyArray_As1D: use PyArray_AsCArray."; + /* 2008-07-14, 1.5 */ if (DEPRECATE(msg) < 0) { return -1; } @@ -277,6 +280,7 @@ PyArray_As2D(PyObject **op, char ***ptr, int *d1, int *d2, int typecode) PyArray_Descr *descr; static const char msg[] = "PyArray_As1D: use PyArray_AsCArray."; + /* 2008-07-14, 1.5 */ if (DEPRECATE(msg) < 0) { return -1; } @@ -346,16 +350,6 @@ PyArray_ConcatenateArrays(int narrays, PyArrayObject **arrays, int axis) axis += ndim; } - if (ndim == 1 && axis != 0) { - static const char msg[] = "axis != 0 for ndim == 1; " - "this will raise an error in " - "future versions of numpy"; - if (DEPRECATE(msg) < 0) { - return NULL; - } - axis = 0; - } - if (axis < 0 || axis >= ndim) { PyErr_Format(PyExc_IndexError, "axis %d out of bounds [0, %d)", orig_axis, ndim); @@ -478,7 +472,7 @@ PyArray_ConcatenateFlattenedArrays(int narrays, PyArrayObject **arrays, PyTypeObject *subtype = &PyArray_Type; double priority = NPY_PRIORITY; int iarrays; - npy_intp stride, sizes[NPY_MAXDIMS]; + npy_intp stride; npy_intp shape = 0; PyArray_Descr *dtype = NULL; PyArrayObject *ret = NULL; @@ -495,7 +489,7 @@ PyArray_ConcatenateFlattenedArrays(int narrays, PyArrayObject **arrays, * array's shape. */ for (iarrays = 0; iarrays < narrays; ++iarrays) { - shape += sizes[iarrays] = PyArray_SIZE(arrays[iarrays]); + shape += PyArray_SIZE(arrays[iarrays]); /* Check for overflow */ if (shape < 0) { PyErr_SetString(PyExc_ValueError, @@ -550,7 +544,7 @@ PyArray_ConcatenateFlattenedArrays(int narrays, PyArrayObject **arrays, for (iarrays = 0; iarrays < narrays; ++iarrays) { /* Adjust the window dimensions for this array */ - sliding_view->dimensions[0] = sizes[iarrays]; + sliding_view->dimensions[0] = PyArray_SIZE(arrays[iarrays]); /* Copy the data for this array */ if (PyArray_CopyAsFlat((PyArrayObject *)sliding_view, arrays[iarrays], @@ -561,7 +555,8 @@ PyArray_ConcatenateFlattenedArrays(int narrays, PyArrayObject **arrays, } /* Slide to the start of the next window */ - sliding_view->data += sliding_view->strides[0] * sizes[iarrays]; + sliding_view->data += + sliding_view->strides[0] * PyArray_SIZE(arrays[iarrays]); } Py_DECREF(sliding_view); @@ -930,7 +925,7 @@ PyArray_InnerProduct(PyObject *op1, PyObject *op2) Py_DECREF(ap2); return (PyObject *)ret; - fail: +fail: Py_XDECREF(ap1); Py_XDECREF(ap2); Py_XDECREF(ret); @@ -1049,7 +1044,8 @@ PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out) goto fail; } - op = PyArray_DATA(ret); os = PyArray_DESCR(ret)->elsize; + op = PyArray_DATA(ret); + os = PyArray_DESCR(ret)->elsize; axis = PyArray_NDIM(ap1)-1; it1 = (PyArrayIterObject *) PyArray_IterAllButAxis((PyObject *)ap1, &axis); @@ -1083,7 +1079,7 @@ PyArray_MatrixProduct2(PyObject *op1, PyObject *op2, PyArrayObject* out) Py_DECREF(ap2); return (PyObject *)ret; - fail: +fail: Py_XDECREF(ap1); Py_XDECREF(ap2); Py_XDECREF(ret); @@ -1263,47 +1259,41 @@ clean_ret: static int _pyarray_revert(PyArrayObject *ret) { - npy_intp length; - npy_intp i; - PyArray_CopySwapFunc *copyswap; - char *tmp = NULL, *sw1, *sw2; - npy_intp os; - char *op; - - length = PyArray_DIMS(ret)[0]; - copyswap = PyArray_DESCR(ret)->f->copyswap; - - tmp = PyArray_malloc(PyArray_DESCR(ret)->elsize); - if (tmp == NULL) { - return -1; + npy_intp length = PyArray_DIM(ret, 0); + npy_intp os = PyArray_DESCR(ret)->elsize; + char *op = PyArray_DATA(ret); + char *sw1 = op; + char *sw2; + + if (PyArray_ISNUMBER(ret) && !PyArray_ISCOMPLEX(ret)) { + /* Optimization for unstructured dtypes */ + PyArray_CopySwapNFunc *copyswapn = PyArray_DESCR(ret)->f->copyswapn; + sw2 = op + length * os - 1; + /* First reverse the whole array byte by byte... */ + while(sw1 < sw2) { + const char tmp = *sw1; + *sw1++ = *sw2; + *sw2-- = tmp; + } + /* ...then swap in place every item */ + copyswapn(op, os, NULL, 0, length, 1, NULL); } - - os = PyArray_DESCR(ret)->elsize; - op = PyArray_DATA(ret); - sw1 = op; - sw2 = op + (length - 1) * os; - if (PyArray_ISFLEXIBLE(ret) || PyArray_ISOBJECT(ret)) { - for(i = 0; i < length/2; ++i) { - memmove(tmp, sw1, os); - copyswap(tmp, NULL, 0, NULL); - memmove(sw1, sw2, os); - copyswap(sw1, NULL, 0, NULL); - memmove(sw2, tmp, os); - copyswap(sw2, NULL, 0, NULL); - sw1 += os; - sw2 -= os; + else { + char *tmp = PyArray_malloc(PyArray_DESCR(ret)->elsize); + if (tmp == NULL) { + return -1; } - } else { - for(i = 0; i < length/2; ++i) { + sw2 = op + (length - 1) * os; + while (sw1 < sw2) { memcpy(tmp, sw1, os); memcpy(sw1, sw2, os); memcpy(sw2, tmp, os); sw1 += os; sw2 -= os; } + PyArray_free(tmp); } - PyArray_free(tmp); return 0; } @@ -1842,10 +1832,9 @@ array_copyto(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) Py_XDECREF(src); Py_XDECREF(wheremask); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; - fail: +fail: Py_XDECREF(src); Py_XDECREF(wheremask); return NULL; @@ -1888,7 +1877,7 @@ array_empty(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) PyDimMem_FREE(shape.ptr); return (PyObject *)ret; - fail: +fail: Py_XDECREF(typecode); PyDimMem_FREE(shape.ptr); return NULL; @@ -1919,7 +1908,7 @@ array_empty_like(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) return (PyObject *)ret; - fail: +fail: Py_XDECREF(prototype); Py_XDECREF(dtype); return NULL; @@ -2042,7 +2031,7 @@ array_zeros(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) PyDimMem_FREE(shape.ptr); return (PyObject *)ret; - fail: +fail: Py_XDECREF(typecode); PyDimMem_FREE(shape.ptr); return (PyObject *)ret; @@ -2130,8 +2119,6 @@ array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds) } fp = npy_PyFile_Dup2(file, "rb", &orig_pos); if (fp == NULL) { - PyErr_SetString(PyExc_IOError, - "first argument must be an open file"); Py_DECREF(file); return NULL; } @@ -2266,8 +2253,10 @@ array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args) { int typenum; char *ip1, *ip2, *op; - npy_intp n, stride; + npy_intp n, stride1, stride2; PyObject *op1, *op2; + npy_intp newdimptr[1] = {-1}; + PyArray_Dims newdims = {newdimptr, 1}; PyArrayObject *ap1 = NULL, *ap2 = NULL, *ret = NULL; PyArray_Descr *type; PyArray_DotFunc *vdot; @@ -2291,7 +2280,8 @@ array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args) Py_DECREF(type); goto fail; } - op1 = PyArray_Ravel(ap1, NPY_CORDER); + + op1 = PyArray_Newshape(ap1, &newdims, NPY_CORDER); if (op1 == NULL) { Py_DECREF(type); goto fail; @@ -2303,7 +2293,7 @@ array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args) if (ap2 == NULL) { goto fail; } - op2 = PyArray_Ravel(ap2, NPY_CORDER); + op2 = PyArray_Newshape(ap2, &newdims, NPY_CORDER); if (op2 == NULL) { goto fail; } @@ -2323,7 +2313,8 @@ array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args) } n = PyArray_DIM(ap1, 0); - stride = type->elsize; + stride1 = PyArray_STRIDE(ap1, 0); + stride2 = PyArray_STRIDE(ap2, 0); ip1 = PyArray_DATA(ap1); ip2 = PyArray_DATA(ap2); op = PyArray_DATA(ret); @@ -2351,11 +2342,11 @@ array_vdot(PyObject *NPY_UNUSED(dummy), PyObject *args) } if (n < 500) { - vdot(ip1, stride, ip2, stride, op, n, NULL); + vdot(ip1, stride1, ip2, stride2, op, n, NULL); } else { NPY_BEGIN_THREADS_DESCR(type); - vdot(ip1, stride, ip2, stride, op, n, NULL); + vdot(ip1, stride1, ip2, stride2, op, n, NULL); NPY_END_THREADS_DESCR(type); } @@ -2370,6 +2361,171 @@ fail: } + +/* + * matmul + * + * Implements the protocol used by the '@' operator defined in PEP 364. + * Not in the NUMPY API at this time, maybe later. + * + * + * in1: Left hand side operand + * in2: Right hand side operand + * out: Either NULL, or an array into which the output should be placed. + * + * Returns NULL on error. + * Returns NotImplemented on priority override. + */ +static PyObject * +array_matmul(PyObject *NPY_UNUSED(m), PyObject *args, PyObject* kwds) +{ + static PyObject *matmul = NULL; + int errval; + PyObject *override = NULL; + PyObject *in1, *in2, *out = NULL; + char* kwlist[] = {"a", "b", "out", NULL }; + PyArrayObject *ap1, *ap2, *ret = NULL; + NPY_ORDER order = NPY_KEEPORDER; + NPY_CASTING casting = NPY_SAFE_CASTING; + PyArray_Descr *dtype; + int nd1, nd2, typenum; + char *subscripts; + PyArrayObject *ops[2]; + + npy_cache_import("numpy.core.multiarray", "matmul", &matmul); + if (matmul == NULL) { + return NULL; + } + + errval = PyUFunc_CheckOverride((PyUFuncObject*)matmul, "__call__", + args, kwds, &override, 2); + if (errval) { + return NULL; + } + else if (override) { + return override; + } + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|O", kwlist, + &in1, &in2, &out)) { + return NULL; + } + + if (out == Py_None) { + out = NULL; + } + if (out != NULL && !PyArray_Check(out)) { + PyErr_SetString(PyExc_TypeError, + "'out' must be an array"); + return NULL; + } + + dtype = PyArray_DescrFromObject(in1, NULL); + dtype = PyArray_DescrFromObject(in2, dtype); + if (dtype == NULL) { + PyErr_SetString(PyExc_ValueError, + "Cannot find a common data type."); + return NULL; + } + typenum = dtype->type_num; + + if (typenum == NPY_OBJECT) { + /* matmul is not currently implemented for object arrays */ + PyErr_SetString(PyExc_TypeError, + "Object arrays are not currently supported"); + Py_DECREF(dtype); + return NULL; + } + + ap1 = (PyArrayObject *)PyArray_FromAny(in1, dtype, 0, 0, + NPY_ARRAY_ALIGNED, NULL); + if (ap1 == NULL) { + return NULL; + } + + Py_INCREF(dtype); + ap2 = (PyArrayObject *)PyArray_FromAny(in2, dtype, 0, 0, + NPY_ARRAY_ALIGNED, NULL); + if (ap2 == NULL) { + Py_DECREF(ap1); + return NULL; + } + + if (PyArray_NDIM(ap1) == 0 || PyArray_NDIM(ap2) == 0) { + /* Scalars are rejected */ + PyErr_SetString(PyExc_ValueError, + "Scalar operands are not allowed, use '*' instead"); + return NULL; + } + + nd1 = PyArray_NDIM(ap1); + nd2 = PyArray_NDIM(ap2); + +#if defined(HAVE_CBLAS) + if (nd1 <= 2 && nd2 <= 2 && + (NPY_DOUBLE == typenum || NPY_CDOUBLE == typenum || + NPY_FLOAT == typenum || NPY_CFLOAT == typenum)) { + return cblas_matrixproduct(typenum, ap1, ap2, (PyArrayObject *)out); + } +#endif + + /* + * Use einsum for the stacked cases. This is a quick implementation + * to avoid setting up the proper iterators. Einsum broadcasts, so + * we need to check dimensions before the call. + */ + if (nd1 == 1 && nd2 == 1) { + /* vector vector */ + if (PyArray_DIM(ap1, 0) != PyArray_DIM(ap2, 0)) { + dot_alignment_error(ap1, 0, ap2, 0); + goto fail; + } + subscripts = "i, i"; + } + else if (nd1 == 1) { + /* vector matrix */ + if (PyArray_DIM(ap1, 0) != PyArray_DIM(ap2, nd2 - 2)) { + dot_alignment_error(ap1, 0, ap2, nd2 - 2); + goto fail; + } + subscripts = "i, ...ij"; + } + else if (nd2 == 1) { + /* matrix vector */ + if (PyArray_DIM(ap1, nd1 - 1) != PyArray_DIM(ap2, 0)) { + dot_alignment_error(ap1, nd1 - 1, ap2, 0); + goto fail; + } + subscripts = "...i, i"; + } + else { + /* matrix * matrix */ + if (PyArray_DIM(ap1, nd1 - 1) != PyArray_DIM(ap2, nd2 - 2)) { + dot_alignment_error(ap1, nd1 - 1, ap2, nd2 - 2); + goto fail; + } + subscripts = "...ij, ...jk"; + } + ops[0] = ap1; + ops[1] = ap2; + ret = PyArray_EinsteinSum(subscripts, 2, ops, NULL, order, casting, + (PyArrayObject *)out); + Py_DECREF(ap1); + Py_DECREF(ap2); + + /* If no output was supplied, possibly convert to a scalar */ + if (ret != NULL && out == NULL) { + return PyArray_Return((PyArrayObject *)ret); + } + return (PyObject *)ret; + +fail: + Py_XDECREF(ap1); + Py_XDECREF(ap2); + return NULL; +} + + static int einsum_sub_op_from_str(PyObject *args, PyObject **str_obj, char **subscripts, PyArrayObject **op) @@ -2863,7 +3019,7 @@ array__reconstruct(PyObject *NPY_UNUSED(dummy), PyObject *args) return ret; - fail: +fail: evil_global_disable_warn_O4O8_flag = 0; Py_XDECREF(dtype); @@ -2892,8 +3048,7 @@ array_set_string_function(PyObject *NPY_UNUSED(self), PyObject *args, return NULL; } PyArray_SetStringFunction(op, repr); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -3092,7 +3247,7 @@ PyArray_Where(PyObject *condition, PyObject *x, PyObject *y) return ret; } - fail: +fail: Py_DECREF(arr); Py_XDECREF(ax); Py_XDECREF(ay); @@ -3841,30 +3996,88 @@ test_interrupt(PyObject *NPY_UNUSED(self), PyObject *args) return PyInt_FromLong(a); } + static PyObject * -array_may_share_memory(PyObject *NPY_UNUSED(ignored), PyObject *args) +array_shares_memory(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds) { PyArrayObject * self = NULL; PyArrayObject * other = NULL; - int overlap; + PyObject *max_work_obj = NULL; + static char *kwlist[] = {"self", "other", "max_work", NULL}; - if (!PyArg_ParseTuple(args, "O&O&", PyArray_Converter, &self, - PyArray_Converter, &other)) { + mem_overlap_t result; + static PyObject *too_hard_cls = NULL; + Py_ssize_t max_work = NPY_MAY_SHARE_EXACT; + NPY_BEGIN_THREADS_DEF; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&O&|O", kwlist, + PyArray_Converter, &self, + PyArray_Converter, &other, + &max_work_obj)) { return NULL; } - overlap = arrays_overlap(self, other); + if (max_work_obj == NULL || max_work_obj == Py_None) { + /* noop */ + } + else if (PyLong_Check(max_work_obj)) { + max_work = PyLong_AsSsize_t(max_work_obj); + } +#if !defined(NPY_PY3K) + else if (PyInt_Check(max_work_obj)) { + max_work = PyInt_AsSsize_t(max_work_obj); + } +#endif + else { + PyErr_SetString(PyExc_ValueError, "max_work must be an integer"); + goto fail; + } + + if (max_work < -2) { + PyErr_SetString(PyExc_ValueError, "Invalid value for max_work"); + goto fail; + } + + NPY_BEGIN_THREADS; + result = solve_may_share_memory(self, other, max_work); + NPY_END_THREADS; + Py_XDECREF(self); Py_XDECREF(other); - if (overlap) { + if (result == MEM_OVERLAP_NO) { + Py_RETURN_FALSE; + } + else if (result == MEM_OVERLAP_YES) { Py_RETURN_TRUE; } + else if (result == MEM_OVERLAP_OVERFLOW) { + PyErr_SetString(PyExc_OverflowError, + "Integer overflow in computing overlap"); + return NULL; + } + else if (result == MEM_OVERLAP_TOO_HARD) { + npy_cache_import("numpy.core._internal", "TooHardError", + &too_hard_cls); + if (too_hard_cls) { + PyErr_SetString(too_hard_cls, "Exceeded max_work"); + } + return NULL; + } else { - Py_RETURN_FALSE; + /* Doesn't happen usually */ + PyErr_SetString(PyExc_RuntimeError, + "Error in computing overlap"); + return NULL; } + +fail: + Py_XDECREF(self); + Py_XDECREF(other); + return NULL; } + static struct PyMethodDef array_module_methods[] = { {"_get_ndarray_c_version", (PyCFunction)array__get_ndarray_c_version, @@ -3938,6 +4151,9 @@ static struct PyMethodDef array_module_methods[] = { {"vdot", (PyCFunction)array_vdot, METH_VARARGS | METH_KEYWORDS, NULL}, + {"matmul", + (PyCFunction)array_matmul, + METH_VARARGS | METH_KEYWORDS, NULL}, {"einsum", (PyCFunction)array_einsum, METH_VARARGS|METH_KEYWORDS, NULL}, @@ -3968,9 +4184,9 @@ static struct PyMethodDef array_module_methods[] = { {"result_type", (PyCFunction)array_result_type, METH_VARARGS, NULL}, - {"may_share_memory", - (PyCFunction)array_may_share_memory, - METH_VARARGS, NULL}, + {"shares_memory", + (PyCFunction)array_shares_memory, + METH_VARARGS | METH_KEYWORDS, NULL}, /* Datetime-related functions */ {"datetime_data", (PyCFunction)array_datetime_data, @@ -4281,6 +4497,7 @@ intern_strings(void) npy_ma_str_ndmin; } + #if defined(NPY_PY3K) static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, @@ -4324,6 +4541,13 @@ PyMODINIT_FUNC initmultiarray(void) { if (!d) { goto err; } + + /* + * Before calling PyType_Ready, initialize the tp_hash slot in + * PyArray_Type to work around mingw32 not being able initialize + * static structure slots with functions from the Python C_API. + */ + PyArray_Type.tp_hash = PyObject_HashNotImplemented; if (PyType_Ready(&PyArray_Type) < 0) { return RETVAL; } @@ -4420,6 +4644,9 @@ PyMODINIT_FUNC initmultiarray(void) { ADDCONST(RAISE); ADDCONST(WRAP); ADDCONST(MAXDIMS); + + ADDCONST(MAY_SHARE_BOUNDS); + ADDCONST(MAY_SHARE_EXACT); #undef ADDCONST Py_INCREF(&PyArray_Type); diff --git a/numpy/core/src/multiarray/multiarraymodule_onefile.c b/numpy/core/src/multiarray/multiarraymodule_onefile.c index 3940d009b..3924f3cf4 100644 --- a/numpy/core/src/multiarray/multiarraymodule_onefile.c +++ b/numpy/core/src/multiarray/multiarraymodule_onefile.c @@ -53,6 +53,7 @@ #include "ucsnarrow.c" #include "arrayobject.c" #include "numpymemoryview.c" +#include "mem_overlap.c" #include "multiarraymodule.c" #include "compiled_base.c" diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c index 636dd6b96..9c5afedf6 100644 --- a/numpy/core/src/multiarray/nditer_constr.c +++ b/numpy/core/src/multiarray/nditer_constr.c @@ -168,6 +168,7 @@ NpyIter_AdvancedNew(int nop, PyArrayObject **op_in, npy_uint32 flags, "deprecated. Use `oa_ndim == -1` or the MultiNew " "iterator for NumPy <1.8 compatibility"; if (DEPRECATE(mesg) < 0) { + /* 2013-02-23, 1.8 */ return NULL; } oa_ndim = -1; diff --git a/numpy/core/src/multiarray/nditer_pywrap.c b/numpy/core/src/multiarray/nditer_pywrap.c index 77c45434f..25e48ba05 100644 --- a/numpy/core/src/multiarray/nditer_pywrap.c +++ b/numpy/core/src/multiarray/nditer_pywrap.c @@ -2227,6 +2227,14 @@ npyiter_seq_ass_slice(NewNpyArrayIterObject *self, Py_ssize_t ilow, return 0; } +/* Py3 changes PySlice_GetIndices' first argument's type to PyObject* */ +#ifdef NPY_PY3K +# define slice_getindices PySlice_GetIndices +#else +# define slice_getindices(op, nop, start, end, step) \ + PySlice_GetIndices((PySliceObject *)op, nop, start, end, step) +#endif + static PyObject * npyiter_subscript(NewNpyArrayIterObject *self, PyObject *op) { @@ -2253,8 +2261,7 @@ npyiter_subscript(NewNpyArrayIterObject *self, PyObject *op) } else if (PySlice_Check(op)) { Py_ssize_t istart = 0, iend = 0, istep = 0; - if (PySlice_GetIndices((PySliceObject *)op, - NpyIter_GetNOp(self->iter), + if (slice_getindices(op, NpyIter_GetNOp(self->iter), &istart, &iend, &istep) < 0) { return NULL; } @@ -2303,8 +2310,7 @@ npyiter_ass_subscript(NewNpyArrayIterObject *self, PyObject *op, } else if (PySlice_Check(op)) { Py_ssize_t istart = 0, iend = 0, istep = 0; - if (PySlice_GetIndices((PySliceObject *)op, - NpyIter_GetNOp(self->iter), + if (slice_getindices(op, NpyIter_GetNOp(self->iter), &istart, &iend, &istep) < 0) { return -1; } diff --git a/numpy/core/src/multiarray/number.c b/numpy/core/src/multiarray/number.c index 9c6e43c69..fec015a30 100644 --- a/numpy/core/src/multiarray/number.c +++ b/numpy/core/src/multiarray/number.c @@ -8,11 +8,10 @@ #include "numpy/arrayobject.h" #include "npy_config.h" - #include "npy_pycompat.h" - -#include "number.h" +#include "npy_import.h" #include "common.h" +#include "number.h" /************************************************************************* **************** Implement Number Protocol **************************** @@ -111,6 +110,13 @@ has_ufunc_attr(PyObject * obj) { * [occurs if the other object is a strict subclass provided * the operation is not in-place] * + * An additional check is made in GIVE_UP_IF_HAS_RIGHT_BINOP macro below: + * + * (iv) other.__class__.__r*__ is not self.__class__.__r*__ + * + * This is needed, because CPython does not call __rmul__ if + * the tp_number slots of the two objects are the same. + * * This always prioritizes the __r*__ routines over __numpy_ufunc__, independent * of whether the other object is an ndarray subclass or not. */ @@ -146,13 +152,19 @@ needs_right_binop_forward(PyObject *self, PyObject *other, } } -#define GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, left_name, right_name, inplace) \ - do { \ - if (needs_right_binop_forward((PyObject *)m1, m2, right_name, \ - inplace)) { \ - Py_INCREF(Py_NotImplemented); \ - return Py_NotImplemented; \ - } \ +/* In pure-Python, SAME_SLOTS can be replaced by + getattr(m1, op_name) is getattr(m2, op_name) */ +#define SAME_SLOTS(m1, m2, slot_name) \ + (Py_TYPE(m1)->tp_as_number != NULL && Py_TYPE(m2)->tp_as_number != NULL && \ + Py_TYPE(m1)->tp_as_number->slot_name == Py_TYPE(m2)->tp_as_number->slot_name) + +#define GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, left_name, right_name, inplace, slot_name) \ + do { \ + if (needs_right_binop_forward((PyObject *)m1, m2, right_name, inplace) && \ + (inplace || !SAME_SLOTS(m1, m2, slot_name))) { \ + Py_INCREF(Py_NotImplemented); \ + return Py_NotImplemented; \ + } \ } while (0) @@ -291,6 +303,10 @@ PyArray_GenericBinaryFunction(PyArrayObject *m1, PyObject *m2, PyObject *op) * See also: * - https://github.com/numpy/numpy/issues/3502 * - https://github.com/numpy/numpy/issues/3503 + * + * NB: there's another copy of this code in + * numpy.ma.core.MaskedArray._delegate_binop + * which should possibly be updated when this is. */ double m1_prio = PyArray_GetPriority((PyObject *)m1, NPY_SCALAR_PRIORITY); @@ -339,21 +355,21 @@ PyArray_GenericInplaceUnaryFunction(PyArrayObject *m1, PyObject *op) static PyObject * array_add(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__add__", "__radd__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__add__", "__radd__", 0, nb_add); return PyArray_GenericBinaryFunction(m1, m2, n_ops.add); } static PyObject * array_subtract(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__sub__", "__rsub__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__sub__", "__rsub__", 0, nb_subtract); return PyArray_GenericBinaryFunction(m1, m2, n_ops.subtract); } static PyObject * array_multiply(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__mul__", "__rmul__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__mul__", "__rmul__", 0, nb_multiply); return PyArray_GenericBinaryFunction(m1, m2, n_ops.multiply); } @@ -361,7 +377,7 @@ array_multiply(PyArrayObject *m1, PyObject *m2) static PyObject * array_divide(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__div__", "__rdiv__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__div__", "__rdiv__", 0, nb_divide); return PyArray_GenericBinaryFunction(m1, m2, n_ops.divide); } #endif @@ -369,10 +385,37 @@ array_divide(PyArrayObject *m1, PyObject *m2) static PyObject * array_remainder(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__mod__", "__rmod__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__mod__", "__rmod__", 0, nb_remainder); return PyArray_GenericBinaryFunction(m1, m2, n_ops.remainder); } + +#if PY_VERSION_HEX >= 0x03050000 +/* Need this to be version dependent on account of the slot check */ +static PyObject * +array_matrix_multiply(PyArrayObject *m1, PyObject *m2) +{ + static PyObject *matmul = NULL; + + npy_cache_import("numpy.core.multiarray", "matmul", &matmul); + if (matmul == NULL) { + return NULL; + } + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__matmul__", "__rmatmul__", + 0, nb_matrix_multiply); + return PyArray_GenericBinaryFunction(m1, m2, matmul); +} + +static PyObject * +array_inplace_matrix_multiply(PyArrayObject *m1, PyObject *m2) +{ + PyErr_SetString(PyExc_TypeError, + "In-place matrix multiplication is not (yet) supported. " + "Use 'a = a @ b' instead of 'a @= b'."); + return NULL; +} +#endif + /* Determine if object is a scalar and if so, convert the object * to a double and place it in the out_exponent argument * and return the "scalar kind" as a result. If the object is @@ -533,7 +576,7 @@ array_power(PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo)) { /* modulo is ignored! */ PyObject *value; - GIVE_UP_IF_HAS_RIGHT_BINOP(a1, o2, "__pow__", "__rpow__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(a1, o2, "__pow__", "__rpow__", 0, nb_power); value = fast_scalar_power(a1, o2, 0); if (!value) { value = PyArray_GenericBinaryFunction(a1, o2, n_ops.power); @@ -563,56 +606,56 @@ array_invert(PyArrayObject *m1) static PyObject * array_left_shift(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__lshift__", "__rlshift__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__lshift__", "__rlshift__", 0, nb_lshift); return PyArray_GenericBinaryFunction(m1, m2, n_ops.left_shift); } static PyObject * array_right_shift(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__rshift__", "__rrshift__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__rshift__", "__rrshift__", 0, nb_rshift); return PyArray_GenericBinaryFunction(m1, m2, n_ops.right_shift); } static PyObject * array_bitwise_and(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__and__", "__rand__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__and__", "__rand__", 0, nb_and); return PyArray_GenericBinaryFunction(m1, m2, n_ops.bitwise_and); } static PyObject * array_bitwise_or(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__or__", "__ror__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__or__", "__ror__", 0, nb_or); return PyArray_GenericBinaryFunction(m1, m2, n_ops.bitwise_or); } static PyObject * array_bitwise_xor(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__xor__", "__rxor__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__xor__", "__rxor__", 0, nb_xor); return PyArray_GenericBinaryFunction(m1, m2, n_ops.bitwise_xor); } static PyObject * array_inplace_add(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__iadd__", "__radd__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__iadd__", "__radd__", 1, nb_inplace_add); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.add); } static PyObject * array_inplace_subtract(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__isub__", "__rsub__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__isub__", "__rsub__", 1, nb_inplace_subtract); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.subtract); } static PyObject * array_inplace_multiply(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__imul__", "__rmul__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__imul__", "__rmul__", 1, nb_inplace_multiply); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.multiply); } @@ -620,7 +663,7 @@ array_inplace_multiply(PyArrayObject *m1, PyObject *m2) static PyObject * array_inplace_divide(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__idiv__", "__rdiv__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__idiv__", "__rdiv__", 1, nb_inplace_divide); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.divide); } #endif @@ -628,7 +671,7 @@ array_inplace_divide(PyArrayObject *m1, PyObject *m2) static PyObject * array_inplace_remainder(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__imod__", "__rmod__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__imod__", "__rmod__", 1, nb_inplace_remainder); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.remainder); } @@ -637,7 +680,7 @@ array_inplace_power(PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo { /* modulo is ignored! */ PyObject *value; - GIVE_UP_IF_HAS_RIGHT_BINOP(a1, o2, "__ipow__", "__rpow__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(a1, o2, "__ipow__", "__rpow__", 1, nb_inplace_power); value = fast_scalar_power(a1, o2, 1); if (!value) { value = PyArray_GenericInplaceBinaryFunction(a1, o2, n_ops.power); @@ -648,56 +691,56 @@ array_inplace_power(PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo static PyObject * array_inplace_left_shift(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__ilshift__", "__rlshift__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__ilshift__", "__rlshift__", 1, nb_inplace_lshift); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.left_shift); } static PyObject * array_inplace_right_shift(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__irshift__", "__rrshift__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__irshift__", "__rrshift__", 1, nb_inplace_rshift); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.right_shift); } static PyObject * array_inplace_bitwise_and(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__iand__", "__rand__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__iand__", "__rand__", 1, nb_inplace_and); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.bitwise_and); } static PyObject * array_inplace_bitwise_or(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__ior__", "__ror__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__ior__", "__ror__", 1, nb_inplace_or); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.bitwise_or); } static PyObject * array_inplace_bitwise_xor(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__ixor__", "__rxor__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__ixor__", "__rxor__", 1, nb_inplace_xor); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.bitwise_xor); } static PyObject * array_floor_divide(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__floordiv__", "__rfloordiv__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__floordiv__", "__rfloordiv__", 0, nb_floor_divide); return PyArray_GenericBinaryFunction(m1, m2, n_ops.floor_divide); } static PyObject * array_true_divide(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__truediv__", "__rtruediv__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__truediv__", "__rtruediv__", 0, nb_true_divide); return PyArray_GenericBinaryFunction(m1, m2, n_ops.true_divide); } static PyObject * array_inplace_floor_divide(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__ifloordiv__", "__rfloordiv__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__ifloordiv__", "__rfloordiv__", 1, nb_inplace_floor_divide); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.floor_divide); } @@ -705,11 +748,12 @@ array_inplace_floor_divide(PyArrayObject *m1, PyObject *m2) static PyObject * array_inplace_true_divide(PyArrayObject *m1, PyObject *m2) { - GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__itruediv__", "__rtruediv__", 1); + GIVE_UP_IF_HAS_RIGHT_BINOP(m1, m2, "__itruediv__", "__rtruediv__", 1, nb_inplace_true_divide); return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.true_divide); } + static int _array_nonzero(PyArrayObject *mp) { @@ -737,7 +781,7 @@ static PyObject * array_divmod(PyArrayObject *op1, PyObject *op2) { PyObject *divp, *modp, *result; - GIVE_UP_IF_HAS_RIGHT_BINOP(op1, op2, "__divmod__", "__rdivmod__", 0); + GIVE_UP_IF_HAS_RIGHT_BINOP(op1, op2, "__divmod__", "__rdivmod__", 0, nb_divmod); divp = array_floor_divide(op1, op2); if (divp == NULL) { @@ -981,17 +1025,11 @@ _array_copy_nice(PyArrayObject *self) static PyObject * array_index(PyArrayObject *v) { - if (!PyArray_ISINTEGER(v) || PyArray_SIZE(v) != 1) { - PyErr_SetString(PyExc_TypeError, "only integer arrays with " \ - "one element can be converted to an index"); + if (!PyArray_ISINTEGER(v) || PyArray_NDIM(v) != 0) { + PyErr_SetString(PyExc_TypeError, + "only integer scalar arrays can be converted to a scalar index"); return NULL; } - if (PyArray_NDIM(v) != 0) { - if (DEPRECATE("converting an array with ndim > 0 to an index" - " will result in an error in the future") < 0) { - return NULL; - } - } return PyArray_DESCR(v)->f->getitem(PyArray_DATA(v), v); } @@ -1053,5 +1091,9 @@ NPY_NO_EXPORT PyNumberMethods array_as_number = { (binaryfunc)array_true_divide, /*nb_true_divide*/ (binaryfunc)array_inplace_floor_divide, /*nb_inplace_floor_divide*/ (binaryfunc)array_inplace_true_divide, /*nb_inplace_true_divide*/ - (unaryfunc)array_index, /* nb_index */ + (unaryfunc)array_index, /*nb_index */ +#if PY_VERSION_HEX >= 0x03050000 + (binaryfunc)array_matrix_multiply, /*nb_matrix_multiply*/ + (binaryfunc)array_inplace_matrix_multiply, /*nb_inplace_matrix_multiply*/ +#endif }; diff --git a/numpy/core/src/multiarray/numpymemoryview.c b/numpy/core/src/multiarray/numpymemoryview.c index ccc5f33ed..3f5616601 100644 --- a/numpy/core/src/multiarray/numpymemoryview.c +++ b/numpy/core/src/multiarray/numpymemoryview.c @@ -112,8 +112,7 @@ _IntTupleFromSsizet(int len, Py_ssize_t *vals) PyObject *intTuple; if (vals == NULL) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } intTuple = PyTuple_New(len); if (!intTuple) return NULL; diff --git a/numpy/core/src/multiarray/numpyos.c b/numpy/core/src/multiarray/numpyos.c index dddead7ea..450ec40b6 100644 --- a/numpy/core/src/multiarray/numpyos.c +++ b/numpy/core/src/multiarray/numpyos.c @@ -13,6 +13,13 @@ #include "npy_pycompat.h" +#ifdef HAVE_STRTOLD_L +#include <stdlib.h> +#include <xlocale.h> +#endif + + + /* * From the C99 standard, section 7.19.6: The exponent always contains at least * two digits, and only as many more digits as necessary to represent the @@ -507,10 +514,12 @@ NumPyOS_ascii_strtod(const char *s, char** endptr) /* * ## 2 * - * At least Python versions <= 2.6.1 + * At least Python versions <= 2.6.8 * * Fails to do best-efforts parsing of strings of the form "1<DP>234" * where <DP> is the decimal point under the foreign locale. + * This is because PyOS_ascii_strtod is buggy, and will completely + * refuse to parse the string, rather than parsing the first part "1". */ if (decimal_point[0] != '.' || decimal_point[1] != 0) { p = s; @@ -539,13 +548,88 @@ NumPyOS_ascii_strtod(const char *s, char** endptr) return NumPyOS_ascii_strtod_plain(s, endptr); } +NPY_NO_EXPORT long double +NumPyOS_ascii_strtold(const char *s, char** endptr) +{ + const char *p; + long double result; +#ifdef HAVE_STRTOLD_L + locale_t clocale; +#endif + + while (NumPyOS_ascii_isspace(*s)) { + ++s; + } + + /* + * ##1 + * + * Recognize POSIX inf/nan representations on all platforms. + */ + p = s; + result = 1.0; + if (*p == '-') { + result = -1.0; + ++p; + } + else if (*p == '+') { + ++p; + } + if (NumPyOS_ascii_strncasecmp(p, "nan", 3) == 0) { + p += 3; + if (*p == '(') { + ++p; + while (NumPyOS_ascii_isalnum(*p) || *p == '_') { + ++p; + } + if (*p == ')') { + ++p; + } + } + if (endptr != NULL) { + *endptr = (char*)p; + } + return NPY_NAN; + } + else if (NumPyOS_ascii_strncasecmp(p, "inf", 3) == 0) { + p += 3; + if (NumPyOS_ascii_strncasecmp(p, "inity", 5) == 0) { + p += 5; + } + if (endptr != NULL) { + *endptr = (char*)p; + } + return result*NPY_INFINITY; + } + /* End of ##1 */ + +#ifdef HAVE_STRTOLD_L + clocale = newlocale(LC_ALL_MASK, "C", NULL); + if (clocale) { + errno = 0; + result = strtold_l(s, endptr, clocale); + freelocale(clocale); + if (errno) { + *endptr = (char*)s; + } + } + else { + *endptr = (char*)s; + result = 0; + } + return result; +#else + return NumPyOS_ascii_strtod(s, endptr); +#endif +} /* - * NumPyOS_ascii_ftolf: + * read_numberlike_string: * * fp: FILE pointer * * value: Place to store the value read * - * Similar to PyOS_ascii_strtod, except that it reads input from a file. + * Read what looks like valid numeric input and store it in a buffer + * for later parsing as a number. * * Similarly to fscanf, this function always consumes leading whitespace, * and any text that could be the leading part in valid input. @@ -555,17 +639,17 @@ NumPyOS_ascii_strtod(const char *s, char** endptr) * * 1 if a number read, * * EOF if end-of-file met before reading anything. */ -NPY_NO_EXPORT int -NumPyOS_ascii_ftolf(FILE *fp, double *value) +static int +read_numberlike_string(FILE *fp, char *buffer, size_t buflen) { - char buffer[FLOAT_FORMATBUFLEN + 1]; + char *endp; char *p; int c; int ok; /* - * Pass on to PyOS_ascii_strtod the leftmost matching part in regexp + * Fill buffer with the leftmost matching part in regexp * * \s*[+-]? ( [0-9]*\.[0-9]+([eE][+-]?[0-9]+) * | nan ( \([:alphanum:_]*\) )? @@ -583,7 +667,7 @@ NumPyOS_ascii_ftolf(FILE *fp, double *value) #define NEXT_CHAR() \ do { \ - if (c == EOF || endp >= buffer + FLOAT_FORMATBUFLEN) \ + if (c == EOF || endp >= buffer + buflen - 1) \ END_MATCH(); \ *endp++ = (char)c; \ c = getc(fp); \ @@ -668,11 +752,8 @@ buffer_filled: ungetc(c, fp); *endp = '\0'; - /* 5. try to convert buffer. */ - *value = NumPyOS_ascii_strtod(buffer, &p); - /* return 1 if something read, else 0 */ - return (buffer == p) ? 0 : 1; + return (buffer == endp) ? 0 : 1; } #undef END_MATCH @@ -681,3 +762,50 @@ buffer_filled: #undef MATCH_ONE_OR_NONE #undef MATCH_ONE_OR_MORE #undef MATCH_ZERO_OR_MORE + +/* + * NumPyOS_ascii_ftolf: + * * fp: FILE pointer + * * value: Place to store the value read + * + * Similar to PyOS_ascii_strtod, except that it reads input from a file. + * + * Similarly to fscanf, this function always consumes leading whitespace, + * and any text that could be the leading part in valid input. + * + * Return value: similar to fscanf. + * * 0 if no number read, + * * 1 if a number read, + * * EOF if end-of-file met before reading anything. + */ +NPY_NO_EXPORT int +NumPyOS_ascii_ftolf(FILE *fp, double *value) +{ + char buffer[FLOAT_FORMATBUFLEN + 1]; + char *p; + int r; + + r = read_numberlike_string(fp, buffer, FLOAT_FORMATBUFLEN+1); + + if (r != EOF && r != 0) { + *value = NumPyOS_ascii_strtod(buffer, &p); + r = (p == buffer) ? 0 : 1; + } + return r; +} + +NPY_NO_EXPORT int +NumPyOS_ascii_ftoLf(FILE *fp, long double *value) +{ + char buffer[FLOAT_FORMATBUFLEN + 1]; + char *p; + int r; + + r = read_numberlike_string(fp, buffer, FLOAT_FORMATBUFLEN+1); + + if (r != EOF && r != 0) { + *value = NumPyOS_ascii_strtold(buffer, &p); + r = (p == buffer) ? 0 : 1; + } + return r; +} diff --git a/numpy/core/src/multiarray/numpyos.h b/numpy/core/src/multiarray/numpyos.h index 6f247e608..3bf77391e 100644 --- a/numpy/core/src/multiarray/numpyos.h +++ b/numpy/core/src/multiarray/numpyos.h @@ -19,10 +19,16 @@ NumPyOS_ascii_formatl(char *buffer, size_t buf_size, NPY_NO_EXPORT double NumPyOS_ascii_strtod(const char *s, char** endptr); +NPY_NO_EXPORT long double +NumPyOS_ascii_strtold(const char *s, char** endptr); + NPY_NO_EXPORT int NumPyOS_ascii_ftolf(FILE *fp, double *value); NPY_NO_EXPORT int +NumPyOS_ascii_ftoLf(FILE *fp, long double *value); + +NPY_NO_EXPORT int NumPyOS_ascii_isspace(char c); #endif diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index 252e5b726..b5e0fde85 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -1308,8 +1308,7 @@ gentype_typedescr_get(PyObject *self) static PyObject * gentype_base_get(PyObject *NPY_UNUSED(self)) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } @@ -1652,33 +1651,13 @@ gentype_@name@(PyObject *self, PyObject *args, PyObject *kwds) static PyObject * voidtype_getfield(PyVoidScalarObject *self, PyObject *args, PyObject *kwds) { - PyObject *ret, *newargs; - - newargs = PyTuple_GetSlice(args, 0, 2); - if (newargs == NULL) { - return NULL; - } - ret = gentype_generic_method((PyObject *)self, newargs, kwds, "getfield"); - Py_DECREF(newargs); - if (!ret) { - return ret; - } - if (PyArray_IsScalar(ret, Generic) && \ - (!PyArray_IsScalar(ret, Void))) { - PyArray_Descr *new; - void *ptr; - if (!PyArray_ISNBO(self->descr->byteorder)) { - new = PyArray_DescrFromScalar(ret); - ptr = scalar_value(ret, new); - byte_swap_vector(ptr, 1, new->elsize); - Py_DECREF(new); - } - } - return ret; + /* Use ndarray's getfield to obtain the field safely */ + return gentype_generic_method((PyObject *)self, args, kwds, "getfield"); } static PyObject * -gentype_setfield(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args), PyObject *NPY_UNUSED(kwds)) +gentype_setfield(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args), + PyObject *NPY_UNUSED(kwds)) { PyErr_SetString(PyExc_TypeError, "Can't set fields in a non-void array scalar."); @@ -1688,61 +1667,76 @@ gentype_setfield(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args), PyObjec static PyObject * voidtype_setfield(PyVoidScalarObject *self, PyObject *args, PyObject *kwds) { - PyArray_Descr *typecode = NULL; - int offset = 0; - PyObject *value; - PyArrayObject *src; - int mysize; - char *dptr; - static char *kwlist[] = {"value", "dtype", "offset", 0}; - - if ((self->flags & NPY_ARRAY_WRITEABLE) != NPY_ARRAY_WRITEABLE) { - PyErr_SetString(PyExc_RuntimeError, "Can't write to memory"); + /* + * We would like to use ndarray's setfield because it performs safety + * checks on the field datatypes and because it broadcasts properly. + * However, as a special case, void-scalar assignment broadcasts + * differently from ndarrays when assigning to an object field: Assignment + * to an ndarray object field broadcasts, but assignment to a void-scalar + * object-field should not, in order to allow nested ndarrays. + * These lines should then behave identically: + * + * b = np.zeros(1, dtype=[('x', 'O')]) + * b[0]['x'] = arange(3) # uses voidtype_setfield + * b['x'][0] = arange(3) # uses ndarray setitem + * + * Ndarray's setfield would try to broadcast the lhs. Instead we use + * ndarray getfield to get the field safely, then setitem to set the value + * without broadcast. Note we also want subarrays to be set properly, ie + * + * a = np.zeros(1, dtype=[('x', 'i', 5)]) + * a[0]['x'] = 1 + * + * sets all values to 1. Setitem does this. + */ + PyObject *getfield_args, *value, *arr, *meth, *arr_field, *emptytuple; + + value = PyTuple_GetItem(args, 0); + if (value == NULL) { return NULL; } - if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO&|i", kwlist, - &value, - PyArray_DescrConverter, - &typecode, &offset)) { - Py_XDECREF(typecode); + getfield_args = PyTuple_GetSlice(args, 1, 3); + if (getfield_args == NULL) { return NULL; } - mysize = Py_SIZE(self); - - if (offset < 0 || (offset + typecode->elsize) > mysize) { - PyErr_Format(PyExc_ValueError, - "Need 0 <= offset <= %d for requested type " \ - "but received offset = %d", - mysize-typecode->elsize, offset); - Py_DECREF(typecode); + /* 1. Convert to 0-d array and use getfield */ + arr = PyArray_FromScalar((PyObject*)self, NULL); + if (arr == NULL) { + Py_DECREF(getfield_args); return NULL; } - - dptr = self->obval + offset; - - if (typecode->type_num == NPY_OBJECT) { - PyObject *temp; - Py_INCREF(value); - NPY_COPY_PYOBJECT_PTR(&temp, dptr); - Py_XDECREF(temp); - NPY_COPY_PYOBJECT_PTR(dptr, &value); - Py_DECREF(typecode); + meth = PyObject_GetAttrString(arr, "getfield"); + if (meth == NULL) { + Py_DECREF(getfield_args); + Py_DECREF(arr); + return NULL; + } + if (kwds == NULL) { + arr_field = PyObject_CallObject(meth, getfield_args); } else { - /* Copy data from value to correct place in dptr */ - src = (PyArrayObject *)PyArray_FromAny(value, typecode, - 0, 0, NPY_ARRAY_CARRAY, NULL); - if (src == NULL) { - return NULL; - } - typecode->f->copyswap(dptr, PyArray_DATA(src), - !PyArray_ISNBO(self->descr->byteorder), - src); - Py_DECREF(src); + arr_field = PyObject_Call(meth, getfield_args, kwds); + } + Py_DECREF(getfield_args); + Py_DECREF(meth); + Py_DECREF(arr); + + if(arr_field == NULL){ + return NULL; + } + + /* 2. Fill the resulting array using setitem */ + emptytuple = PyTuple_New(0); + if (PyObject_SetItem(arr_field, emptytuple, value) < 0) { + Py_DECREF(arr_field); + Py_DECREF(emptytuple); + return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_DECREF(arr_field); + Py_DECREF(emptytuple); + + Py_RETURN_NONE; } @@ -1836,8 +1830,7 @@ fail: static PyObject * gentype_setstate(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args)) { - Py_INCREF(Py_None); - return (Py_None); + Py_RETURN_NONE; } static PyObject * @@ -1853,8 +1846,7 @@ gentype_dump(PyObject *self, PyObject *args) if (ret < 0) { return NULL; } - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } static PyObject * @@ -1872,8 +1864,7 @@ static PyObject * gentype_setflags(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args), PyObject *NPY_UNUSED(kwds)) { - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /* @@ -2170,7 +2161,7 @@ static PyObject * voidtype_item(PyVoidScalarObject *self, Py_ssize_t n) { npy_intp m; - PyObject *flist=NULL, *fieldinfo; + PyObject *flist=NULL, *fieldind, *fieldparam, *fieldinfo, *ret; if (!(PyDataType_HASFIELDS(self->descr))) { PyErr_SetString(PyExc_IndexError, @@ -2186,9 +2177,13 @@ voidtype_item(PyVoidScalarObject *self, Py_ssize_t n) PyErr_Format(PyExc_IndexError, "invalid index (%d)", (int) n); return NULL; } - fieldinfo = PyDict_GetItem(self->descr->fields, - PyTuple_GET_ITEM(flist, n)); - return voidtype_getfield(self, fieldinfo, NULL); + /* no error checking needed: descr->names is well structured */ + fieldind = PyTuple_GET_ITEM(flist, n); + fieldparam = PyDict_GetItem(self->descr->fields, fieldind); + fieldinfo = PyTuple_GetSlice(fieldparam, 0, 2); + ret = voidtype_getfield(self, fieldinfo, NULL); + Py_DECREF(fieldinfo); + return ret; } @@ -2197,7 +2192,7 @@ static PyObject * voidtype_subscript(PyVoidScalarObject *self, PyObject *ind) { npy_intp n; - PyObject *fieldinfo; + PyObject *ret, *fieldinfo, *fieldparam; if (!(PyDataType_HASFIELDS(self->descr))) { PyErr_SetString(PyExc_IndexError, @@ -2211,11 +2206,14 @@ voidtype_subscript(PyVoidScalarObject *self, PyObject *ind) if (PyBytes_Check(ind) || PyUnicode_Check(ind)) { #endif /* look up in fields */ - fieldinfo = PyDict_GetItem(self->descr->fields, ind); - if (!fieldinfo) { + fieldparam = PyDict_GetItem(self->descr->fields, ind); + if (!fieldparam) { goto fail; } - return voidtype_getfield(self, fieldinfo, NULL); + fieldinfo = PyTuple_GetSlice(fieldparam, 0, 2); + ret = voidtype_getfield(self, fieldinfo, NULL); + Py_DECREF(fieldinfo); + return ret; } /* try to convert it to a number */ @@ -2575,7 +2573,7 @@ static PyObject * PyArrayObject *arr; PyArray_Descr *typecode = NULL; #if (@work@ != 0) || (@default@ == 1) - void *thisfunc = (void *)@name@_arrtype_new; + void *thisfunc = (void *)@name@_arrtype_new; #endif #if !(@default@ == 2) int itemsize; diff --git a/numpy/core/src/multiarray/shape.c b/numpy/core/src/multiarray/shape.c index 03bfc6a7a..f46f820ca 100644 --- a/numpy/core/src/multiarray/shape.c +++ b/numpy/core/src/multiarray/shape.c @@ -154,8 +154,7 @@ PyArray_Resize(PyArrayObject *self, PyArray_Dims *newshape, int refcheck, PyArray_FLAGS(self), &(((PyArrayObject_fields *)self)->flags)); memmove(PyArray_DIMS(self), new_dimensions, new_nd*sizeof(npy_intp)); memmove(PyArray_STRIDES(self), new_strides, new_nd*sizeof(npy_intp)); - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } /* @@ -941,55 +940,51 @@ PyArray_Ravel(PyArrayObject *arr, NPY_ORDER order) order = NPY_FORTRANORDER; } } + else if (order == NPY_ANYORDER) { + order = PyArray_ISFORTRAN(arr) ? NPY_FORTRANORDER : NPY_CORDER; + } - if (order != NPY_KEEPORDER) { - return PyArray_Newshape(arr, &newdim, order); + if (order == NPY_CORDER && PyArray_IS_C_CONTIGUOUS(arr)) { + return PyArray_Newshape(arr, &newdim, NPY_CORDER); + } + else if (order == NPY_FORTRANORDER && PyArray_IS_F_CONTIGUOUS(arr)) { + return PyArray_Newshape(arr, &newdim, NPY_FORTRANORDER); } /* For KEEPORDER, check if we can make a flattened view */ - else { + else if (order == NPY_KEEPORDER) { npy_stride_sort_item strideperm[NPY_MAXDIMS]; - npy_intp stride = 0, base_stride = NPY_MIN_INTP; + npy_intp stride; int i, ndim = PyArray_NDIM(arr); PyArray_CreateSortedStridePerm(PyArray_NDIM(arr), PyArray_STRIDES(arr), strideperm); + /* The output array must be contiguous, so the first stride is fixed */ + stride = PyArray_ITEMSIZE(arr); + for (i = ndim-1; i >= 0; --i) { if (PyArray_DIM(arr, strideperm[i].perm) == 1) { /* A size one dimension does not matter */ continue; } - if (base_stride == NPY_MIN_INTP) { - stride = strideperm[i].stride; - base_stride = stride; - } - else if (strideperm[i].stride != stride) { + if (strideperm[i].stride != stride) { break; } stride *= PyArray_DIM(arr, strideperm[i].perm); } -#if NPY_RELAXED_STRIDES_CHECKING == 0 - /* - * For tidyness, cannot be reached with relaxed strides checking - * since the array is guaranteed contiguous (without, not sure...) - */ - if (base_stride == NPY_MIN_INTP) { - base_stride = PyArray_ITEMSIZE(arr); - } -#endif - /* If all the strides matched a contiguous layout, return a view */ if (i < 0) { PyArrayObject *ret; + stride = PyArray_ITEMSIZE(arr); val[0] = PyArray_SIZE(arr); Py_INCREF(PyArray_DESCR(arr)); ret = (PyArrayObject *)PyArray_NewFromDescr(Py_TYPE(arr), PyArray_DESCR(arr), 1, val, - &base_stride, + &stride, PyArray_BYTES(arr), PyArray_FLAGS(arr), (PyObject *)arr); diff --git a/numpy/core/src/multiarray/ucsnarrow.c b/numpy/core/src/multiarray/ucsnarrow.c index 54a9d5671..8e293e9f2 100644 --- a/numpy/core/src/multiarray/ucsnarrow.c +++ b/numpy/core/src/multiarray/ucsnarrow.c @@ -136,7 +136,8 @@ PyUnicode_FromUCS4(char *src, Py_ssize_t size, int swap, int align) /* produce PyUnicode object */ #ifdef Py_UNICODE_WIDE { - ret = (PyUnicodeObject *)PyUnicode_FromUnicode(buf, (Py_ssize_t) ucs4len); + ret = (PyUnicodeObject *)PyUnicode_FromUnicode((Py_UNICODE*)buf, + (Py_ssize_t) ucs4len); if (ret == NULL) { goto fail; } diff --git a/numpy/core/src/npymath/npy_math_complex.c.src b/numpy/core/src/npymath/npy_math_complex.c.src index 94cb7e29d..c4867e28d 100644 --- a/numpy/core/src/npymath/npy_math_complex.c.src +++ b/numpy/core/src/npymath/npy_math_complex.c.src @@ -33,12 +33,13 @@ */ #include "npy_math_common.h" #include "npy_math_private.h" +#include <numpy/utils.h> #define raise_inexact() do { volatile npy_float junk = 1 + tiny; } while(0) -static npy_float tiny = 3.9443045e-31f; +static __COMP_NPY_UNUSED npy_float tiny = 3.9443045e-31f; /**begin repeat @@ -183,6 +184,8 @@ npy_carg@c@(@ctype@ z) #define SCALED_CEXP_LOWERL 11357.216553474703895L #define SCALED_CEXP_UPPERL 22756.021937783004509L +#ifndef HAVE_CEXP@C@ + static @ctype@ _npy_scaled_cexp@c@(@type@ x, @type@ y, npy_int expt) @@ -209,7 +212,6 @@ _npy_scaled_cexp@c@(@type@ x, @type@ y, npy_int expt) npy_ldexp@c@(mant * mantsin, expt + exsin)); } -#ifndef HAVE_CEXP@C@ @ctype@ npy_cexp@c@(@ctype@ z) { diff --git a/numpy/core/src/npymath/npy_math_private.h b/numpy/core/src/npymath/npy_math_private.h index 284d203bf..d75b9e991 100644 --- a/numpy/core/src/npymath/npy_math_private.h +++ b/numpy/core/src/npymath/npy_math_private.h @@ -486,8 +486,12 @@ do { \ */ #ifdef NPY_USE_C99_COMPLEX -/* Microsoft C defines _MSC_VER */ -#ifdef _MSC_VER +/* + * Microsoft C defines _MSC_VER + * Intel compiler does not use MSVC complex types, but defines _MSC_VER by + * default. + */ +#if defined(_MSC_VER) && !defined(__INTEL_COMPILER) typedef union { npy_cdouble npy_z; _Dcomplex c99_z; @@ -536,4 +540,5 @@ typedef union { } __npy_clongdouble_to_c99_cast; #endif /* !NPY_USE_C99_COMPLEX */ + #endif /* !_NPY_MATH_PRIVATE_H_ */ diff --git a/numpy/core/src/npysort/heapsort.c.src b/numpy/core/src/npysort/heapsort.c.src index 88f7978cc..c2e3b63cb 100644 --- a/numpy/core/src/npysort/heapsort.c.src +++ b/numpy/core/src/npysort/heapsort.c.src @@ -61,13 +61,13 @@ */ int -heapsort_@suff@(@type@ *start, npy_intp n, void *NOT_USED) +heapsort_@suff@(void *start, npy_intp n, void *NOT_USED) { @type@ tmp, *a; npy_intp i,j,l; /* The array needs to be offset by one for heapsort indexing */ - a = start - 1; + a = (@type@ *)start - 1; for (l = n>>1; l > 0; --l) { tmp = a[l]; @@ -112,8 +112,9 @@ heapsort_@suff@(@type@ *start, npy_intp n, void *NOT_USED) int -aheapsort_@suff@(@type@ *v, npy_intp *tosort, npy_intp n, void *NOT_USED) +aheapsort_@suff@(void *vv, npy_intp *tosort, npy_intp n, void *NOT_USED) { + @type@ *v = vv; npy_intp *a, i,j,l, tmp; /* The arrays need to be offset by one for heapsort indexing */ a = tosort - 1; @@ -177,11 +178,12 @@ aheapsort_@suff@(@type@ *v, npy_intp *tosort, npy_intp n, void *NOT_USED) */ int -heapsort_@suff@(@type@ *start, npy_intp n, PyArrayObject *arr) +heapsort_@suff@(void *start, npy_intp n, void *varr) { + PyArrayObject *arr = varr; size_t len = PyArray_ITEMSIZE(arr)/sizeof(@type@); @type@ *tmp = malloc(PyArray_ITEMSIZE(arr)); - @type@ *a = start - len; + @type@ *a = (@type@ *)start - len; npy_intp i, j, l; if (tmp == NULL) { @@ -230,8 +232,10 @@ heapsort_@suff@(@type@ *start, npy_intp n, PyArrayObject *arr) int -aheapsort_@suff@(@type@ *v, npy_intp *tosort, npy_intp n, PyArrayObject *arr) +aheapsort_@suff@(void *vv, npy_intp *tosort, npy_intp n, void *varr) { + @type@ *v = vv; + PyArrayObject *arr = varr; size_t len = PyArray_ITEMSIZE(arr)/sizeof(@type@); npy_intp *a, i,j,l, tmp; @@ -288,12 +292,13 @@ aheapsort_@suff@(@type@ *v, npy_intp *tosort, npy_intp n, PyArrayObject *arr) int -npy_heapsort(char *start, npy_intp num, PyArrayObject *arr) +npy_heapsort(void *start, npy_intp num, void *varr) { + PyArrayObject *arr = varr; npy_intp elsize = PyArray_ITEMSIZE(arr); PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare; char *tmp = malloc(elsize); - char *a = start - elsize; + char *a = (char *)start - elsize; npy_intp i, j, l; if (tmp == NULL) { @@ -344,8 +349,10 @@ npy_heapsort(char *start, npy_intp num, PyArrayObject *arr) int -npy_aheapsort(char *v, npy_intp *tosort, npy_intp n, PyArrayObject *arr) +npy_aheapsort(void *vv, npy_intp *tosort, npy_intp n, void *varr) { + char *v = vv; + PyArrayObject *arr = varr; npy_intp elsize = PyArray_ITEMSIZE(arr); PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare; npy_intp *a, i, j, l, tmp; diff --git a/numpy/core/src/npysort/mergesort.c.src b/numpy/core/src/npysort/mergesort.c.src index 406be66d0..fc82e2135 100644 --- a/numpy/core/src/npysort/mergesort.c.src +++ b/numpy/core/src/npysort/mergesort.c.src @@ -104,7 +104,7 @@ mergesort0_@suff@(@type@ *pl, @type@ *pr, @type@ *pw) int -mergesort_@suff@(@type@ *start, npy_intp num, void *NOT_USED) +mergesort_@suff@(void *start, npy_intp num, void *NOT_USED) { @type@ *pl, *pr, *pw; @@ -167,7 +167,7 @@ amergesort0_@suff@(npy_intp *pl, npy_intp *pr, @type@ *v, npy_intp *pw) int -amergesort_@suff@(@type@ *v, npy_intp *tosort, npy_intp num, void *NOT_USED) +amergesort_@suff@(void *v, npy_intp *tosort, npy_intp num, void *NOT_USED) { npy_intp *pl, *pr, *pw; @@ -246,8 +246,9 @@ mergesort0_@suff@(@type@ *pl, @type@ *pr, @type@ *pw, @type@ *vp, size_t len) int -mergesort_@suff@(@type@ *start, npy_intp num, PyArrayObject *arr) +mergesort_@suff@(void *start, npy_intp num, void *varr) { + PyArrayObject *arr = varr; size_t elsize = PyArray_ITEMSIZE(arr); size_t len = elsize / sizeof(@type@); @type@ *pl, *pr, *pw, *vp; @@ -321,8 +322,9 @@ amergesort0_@suff@(npy_intp *pl, npy_intp *pr, @type@ *v, npy_intp *pw, size_t l int -amergesort_@suff@(@type@ *v, npy_intp *tosort, npy_intp num, PyArrayObject *arr) +amergesort_@suff@(void *v, npy_intp *tosort, npy_intp num, void *varr) { + PyArrayObject *arr = varr; size_t elsize = PyArray_ITEMSIZE(arr); size_t len = elsize / sizeof(@type@); npy_intp *pl, *pr, *pw; @@ -396,8 +398,9 @@ npy_mergesort0(char *pl, char *pr, char *pw, char *vp, npy_intp elsize, int -npy_mergesort(char *start, npy_intp num, PyArrayObject *arr) +npy_mergesort(void *start, npy_intp num, void *varr) { + PyArrayObject *arr = varr; npy_intp elsize = PyArray_ITEMSIZE(arr); PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare; char *pl = start; @@ -465,8 +468,9 @@ npy_amergesort0(npy_intp *pl, npy_intp *pr, char *v, npy_intp *pw, int -npy_amergesort(char *v, npy_intp *tosort, npy_intp num, PyArrayObject *arr) +npy_amergesort(void *v, npy_intp *tosort, npy_intp num, void *varr) { + PyArrayObject *arr = varr; npy_intp elsize = PyArray_ITEMSIZE(arr); PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare; npy_intp *pl, *pr, *pw; diff --git a/numpy/core/src/npysort/quicksort.c.src b/numpy/core/src/npysort/quicksort.c.src index 5334aca76..91b5e67f5 100644 --- a/numpy/core/src/npysort/quicksort.c.src +++ b/numpy/core/src/npysort/quicksort.c.src @@ -61,11 +61,11 @@ */ int -quicksort_@suff@(@type@ *start, npy_intp num, void *NOT_USED) +quicksort_@suff@(void *start, npy_intp num, void *NOT_USED) { @type@ vp; @type@ *pl = start; - @type@ *pr = start + num - 1; + @type@ *pr = pl + num - 1; @type@ *stack[PYA_QS_STACK]; @type@ **sptr = stack; @type@ *pm, *pi, *pj, *pk; @@ -126,8 +126,9 @@ quicksort_@suff@(@type@ *start, npy_intp num, void *NOT_USED) int -aquicksort_@suff@(@type@ *v, npy_intp* tosort, npy_intp num, void *NOT_USED) +aquicksort_@suff@(void *vv, npy_intp* tosort, npy_intp num, void *NOT_USED) { + @type@ *v = vv; @type@ vp; npy_intp *pl = tosort; npy_intp *pr = tosort + num - 1; @@ -208,12 +209,13 @@ aquicksort_@suff@(@type@ *v, npy_intp* tosort, npy_intp num, void *NOT_USED) */ int -quicksort_@suff@(@type@ *start, npy_intp num, PyArrayObject *arr) +quicksort_@suff@(void *start, npy_intp num, void *varr) { + PyArrayObject *arr = varr; const size_t len = PyArray_ITEMSIZE(arr)/sizeof(@type@); @type@ *vp = malloc(PyArray_ITEMSIZE(arr)); @type@ *pl = start; - @type@ *pr = start + (num - 1)*len; + @type@ *pr = pl + (num - 1)*len; @type@ *stack[PYA_QS_STACK], **sptr = stack, *pm, *pi, *pj, *pk; if (vp == NULL) { @@ -279,8 +281,10 @@ quicksort_@suff@(@type@ *start, npy_intp num, PyArrayObject *arr) int -aquicksort_@suff@(@type@ *v, npy_intp* tosort, npy_intp num, PyArrayObject *arr) +aquicksort_@suff@(void *vv, npy_intp* tosort, npy_intp num, void *varr) { + @type@ *v = vv; + PyArrayObject *arr = varr; size_t len = PyArray_ITEMSIZE(arr)/sizeof(@type@); @type@ *vp; npy_intp *pl = tosort; @@ -355,13 +359,14 @@ aquicksort_@suff@(@type@ *v, npy_intp* tosort, npy_intp num, PyArrayObject *arr) int -npy_quicksort(char *start, npy_intp num, PyArrayObject *arr) +npy_quicksort(void *start, npy_intp num, void *varr) { + PyArrayObject *arr = varr; npy_intp elsize = PyArray_ITEMSIZE(arr); PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare; char *vp = malloc(elsize); char *pl = start; - char *pr = start + (num - 1)*elsize; + char *pr = pl + (num - 1)*elsize; char *stack[PYA_QS_STACK]; char **sptr = stack; char *pm, *pi, *pj, *pk; @@ -439,8 +444,10 @@ npy_quicksort(char *start, npy_intp num, PyArrayObject *arr) int -npy_aquicksort(char *v, npy_intp* tosort, npy_intp num, PyArrayObject *arr) +npy_aquicksort(void *vv, npy_intp* tosort, npy_intp num, void *varr) { + char *v = vv; + PyArrayObject *arr = varr; npy_intp elsize = PyArray_ITEMSIZE(arr); PyArray_CompareFunc *cmp = PyArray_DESCR(arr)->f->compare; char *vp; diff --git a/numpy/core/src/private/mem_overlap.c b/numpy/core/src/private/mem_overlap.c new file mode 100644 index 000000000..3cab83497 --- /dev/null +++ b/numpy/core/src/private/mem_overlap.c @@ -0,0 +1,905 @@ +/* + Solving memory overlap integer programs and bounded Diophantine equations with + positive coefficients. + + Asking whether two strided arrays `a` and `b` overlap is equivalent to + asking whether there is a solution to the following problem:: + + sum(stride_a[i] * x_a[i] for i in range(ndim_a)) + - + sum(stride_b[i] * x_b[i] for i in range(ndim_b)) + == + base_b - base_a + + 0 <= x_a[i] < shape_a[i] + 0 <= x_b[i] < shape_b[i] + + for some integer x_a, x_b. Itemsize needs to be considered as an additional + dimension with stride 1 and size itemsize. + + Negative strides can be changed to positive (and vice versa) by changing + variables x[i] -> shape[i] - 1 - x[i], and zero strides can be dropped, so + that the problem can be recast into a bounded Diophantine equation with + positive coefficients:: + + sum(a[i] * x[i] for i in range(n)) == b + + a[i] > 0 + + 0 <= x[i] <= ub[i] + + This problem is NP-hard --- runtime of algorithms grows exponentially with + increasing ndim. + + + *Algorithm description* + + A straightforward algorithm that excludes infeasible solutions using GCD-based + pruning is outlined in Ref. [1]. It is implemented below. A number of other + algorithms exist in the literature; however, this one seems to have + performance satisfactory for the present purpose. + + The idea is that an equation:: + + a_1 x_1 + a_2 x_2 + ... + a_n x_n = b + 0 <= x_i <= ub_i, i = 1...n + + implies:: + + a_2' x_2' + a_3 x_3 + ... + a_n x_n = b + + 0 <= x_i <= ub_i, i = 2...n + + 0 <= x_1' <= c_1 ub_1 + c_2 ub_2 + + with a_2' = gcd(a_1, a_2) and x_2' = c_1 x_1 + c_2 x_2 with c_1 = (a_1/a_1'), + and c_2 = (a_2/a_1'). This procedure can be repeated to obtain:: + + a_{n-1}' x_{n-1}' + a_n x_n = b + + 0 <= x_{n-1}' <= ub_{n-1}' + + 0 <= x_n <= ub_n + + Now, one can enumerate all candidate solutions for x_n. For each, one can use + the previous-level equation to enumerate potential solutions for x_{n-1}, with + transformed right-hand side b -> b - a_n x_n. And so forth, until after n-1 + nested for loops we either arrive at a candidate solution for x_1 (in which + case we have found one solution to the problem), or find that the equations do + not allow any solutions either for x_1 or one of the intermediate x_i (in + which case we have proved there is no solution for the upper-level candidates + chosen). If no solution is found for any candidate x_n, we have proved the + problem is infeasible --- which for the memory overlap problem means there is + no overlap. + + + *Performance* + + Some common ndarray cases are easy for the algorithm: + + - Two arrays whose memory ranges do not overlap. + + These will be excluded by the bounds on x_n, with max_work=1. We also add + this check as a fast path, to avoid computing GCDs needlessly, as this can + take some time. + + - Arrays produced by continuous slicing of a continuous parent array (no + internal overlap), e.g., a=x[:,0,:], b=x[:,1,:]. The strides taken together, + mapped positive, and duplicates then satisfy gcd(stride[0], .., stride[j]) = + stride[j] for some ordering. + + In this case, for each x[i] at most one candidate exists, given that the + algorithm runs with strides sorted from largest to smallest. The problem can + be written as:: + + sum a_j x_j ?= b = sum a_j z_j + + a_j = n_{j+1} * n_{j+2} * ... * n_d, a_d = 1 + 0 <= x_j <= u_j <= 2*n_j - 2 + 0 <= z_j <= n_j - 1 + + b is the offset of the last element of the second array from the start of + the first. z_j are uniquely determined because of the gcd property. For + each x_j, the bounds at first sight allow x_j=z_j and x_j=z_j+n_j. However, + u_j <= n_j - 1 + z_j, so that at most one candidate is left. + + - Two arrays with stride-incommensurate starting points. For example, + a=x[:,::2], b=x[:,1::2]. + + The base address difference is incommensurate with all strides, so that + there are no solution candidates to consider. For itemsize != 1, similar + result is obtained for x_{n-1}. + + The above cases cover arrays produced by typical slicing of well-behaved + parent arrays. More generally, more difficult cases can result:: + + x = np.arange(4*20).reshape(4, 20).astype(np.int8) + a = x[:,::7] + b = x[:,3::3] + + <=> + + 20*x1 + 7*x2 + 3*x3 = 78 (= 3 + 3*20 + 5*3) + 0 <= x1 <= 6, 0 <= x2 <= 2, 0 <= x3 <= 5 + + Non-overlapping in this case relies on x.shape[1] <= lcm(7, 3) = 21. However, + elimination of x1 does not restrict candidate values for x3, so the algorithm + ends up considering all values x3=0...5 separately. + + The upper bound for work done is prod(shape_a)*prod(shape_b), which scales + faster than than work done by binary ufuncs, after broadcasting, + prod(shape_a). The bound may be loose, but it is possible to construct hard + instances where ufunc is faster (adapted from [2,3]):: + + from numpy.lib.stride_tricks import as_strided + # Construct non-overlapping x1 and x2 + x = np.zeros([192163377], dtype=np.int8) + x1 = as_strided(x, strides=(36674, 61119, 85569), shape=(1049, 1049, 1049)) + x2 = as_strided(x[64023025:], strides=(12223, 12224, 1), shape=(1049, 1049, 1)) + + To avoid such worst cases, the amount of work done needs to be capped. If the + overlap problem is related to ufuncs, one suitable cap choice is to scale + max_work with the number of elements of the array. (Ref. [3] describes a more + efficient algorithm for solving problems similar to the above --- however, + also it must scale exponentially.) + + + *Integer overflows* + + The algorithm is written in fixed-width integers, and can terminate with + failure if integer overflow is detected (the implementation catches all + cases). Potential failure modes: + + - Array extent sum(stride*(shape-1)) is too large (for int64). + + - Minimal solutions to a_i x_i + a_j x_j == b are too large, + in some of the intermediate equations. + + We do this part of the computation in 128-bit integers. + + In general, overflows are expected only if array size is close to + NPY_INT64_MAX, requiring ~exabyte size arrays, which is usually not possible. + + References + ---------- + .. [1] P. Ramachandran, ''Use of Extended Euclidean Algorithm in Solving + a System of Linear Diophantine Equations with Bounded Variables''. + Algorithmic Number Theory, Lecture Notes in Computer Science **4076**, + 182-192 (2006). doi:10.1007/11792086_14 + + .. [2] Cornuejols, Urbaniak, Weismantel, and Wolsey, + ''Decomposition of integer programs and of generating sets.'', + Lecture Notes in Computer Science 1284, 92-103 (1997). + + .. [3] K. Aardal, A.K. Lenstra, + ''Hard equality constrained integer knapsacks'', + Lecture Notes in Computer Science 2337, 350-366 (2002). +*/ + +/* + Copyright (c) 2015 Pauli Virtanen + All rights reserved. + Licensed under 3-clause BSD license, see LICENSE.txt. +*/ +#include <stdlib.h> +#include <stdio.h> +#include <assert.h> +#include <Python.h> + +#define NPY_NO_DEPRECATED_API NPY_API_VERSION +#include "numpy/ndarraytypes.h" +#include "mem_overlap.h" +#include "npy_extint128.h" + + +#define MAX(a, b) (((a) >= (b)) ? (a) : (b)) +#define MIN(a, b) (((a) <= (b)) ? (a) : (b)) + + +/** + * Euclid's algorithm for GCD. + * + * Solves for gamma*a1 + epsilon*a2 == gcd(a1, a2) + * providing |gamma| < |a2|/gcd, |epsilon| < |a1|/gcd. + */ +static void +euclid(npy_int64 a1, npy_int64 a2, npy_int64 *a_gcd, npy_int64 *gamma, npy_int64 *epsilon) +{ + npy_int64 gamma1, gamma2, epsilon1, epsilon2, r; + + assert(a1 > 0); + assert(a2 > 0); + + gamma1 = 1; + gamma2 = 0; + epsilon1 = 0; + epsilon2 = 1; + + /* The numbers remain bounded by |a1|, |a2| during + the iteration, so no integer overflows */ + while (1) { + if (a2 > 0) { + r = a1/a2; + a1 -= r*a2; + gamma1 -= r*gamma2; + epsilon1 -= r*epsilon2; + } + else { + *a_gcd = a1; + *gamma = gamma1; + *epsilon = epsilon1; + break; + } + + if (a1 > 0) { + r = a2/a1; + a2 -= r*a1; + gamma2 -= r*gamma1; + epsilon2 -= r*epsilon1; + } + else { + *a_gcd = a2; + *gamma = gamma2; + *epsilon = epsilon2; + break; + } + } +} + + +/** + * Precompute GCD and bounds transformations + */ +static int +diophantine_precompute(unsigned int n, + diophantine_term_t *E, + diophantine_term_t *Ep, + npy_int64 *Gamma, npy_int64 *Epsilon) +{ + npy_int64 a_gcd, gamma, epsilon, c1, c2; + unsigned int j; + char overflow = 0; + + assert(n >= 2); + + euclid(E[0].a, E[1].a, &a_gcd, &gamma, &epsilon); + Ep[0].a = a_gcd; + Gamma[0] = gamma; + Epsilon[0] = epsilon; + + if (n > 2) { + c1 = E[0].a / a_gcd; + c2 = E[1].a / a_gcd; + + /* Ep[0].ub = E[0].ub * c1 + E[1].ub * c2; */ + Ep[0].ub = safe_add(safe_mul(E[0].ub, c1, &overflow), + safe_mul(E[1].ub, c2, &overflow), &overflow); + if (overflow) { + return 1; + } + } + + for (j = 2; j < n; ++j) { + euclid(Ep[j-2].a, E[j].a, &a_gcd, &gamma, &epsilon); + Ep[j-1].a = a_gcd; + Gamma[j-1] = gamma; + Epsilon[j-1] = epsilon; + + if (j < n - 1) { + c1 = Ep[j-2].a / a_gcd; + c2 = E[j].a / a_gcd; + + /* Ep[j-1].ub = c1 * Ep[j-2].ub + c2 * E[j].ub; */ + Ep[j-1].ub = safe_add(safe_mul(c1, Ep[j-2].ub, &overflow), + safe_mul(c2, E[j].ub, &overflow), &overflow); + + if (overflow) { + return 1; + } + } + } + + return 0; +} + + +/** + * Depth-first bounded Euclid search + */ +static mem_overlap_t +diophantine_dfs(unsigned int n, + unsigned int v, + diophantine_term_t *E, + diophantine_term_t *Ep, + npy_int64 *Gamma, npy_int64 *Epsilon, + npy_int64 b, + Py_ssize_t max_work, + int require_ub_nontrivial, + npy_int64 *x, + Py_ssize_t *count) +{ + npy_int64 a_gcd, gamma, epsilon, a1, u1, a2, u2, c, r, c1, c2, t, t_l, t_u, b2, x1, x2; + npy_extint128_t x10, x20, t_l1, t_l2, t_u1, t_u2; + mem_overlap_t res; + char overflow = 0; + + if (max_work >= 0 && *count >= max_work) { + return MEM_OVERLAP_TOO_HARD; + } + + /* Fetch precomputed values for the reduced problem */ + if (v == 1) { + a1 = E[0].a; + u1 = E[0].ub; + } + else { + a1 = Ep[v-2].a; + u1 = Ep[v-2].ub; + } + + a2 = E[v].a; + u2 = E[v].ub; + + a_gcd = Ep[v-1].a; + gamma = Gamma[v-1]; + epsilon = Epsilon[v-1]; + + /* Generate set of allowed solutions */ + c = b / a_gcd; + r = b % a_gcd; + if (r != 0) { + ++*count; + return MEM_OVERLAP_NO; + } + + c1 = a2 / a_gcd; + c2 = a1 / a_gcd; + + /* + The set to enumerate is: + x1 = gamma*c + c1*t + x2 = epsilon*c - c2*t + t integer + 0 <= x1 <= u1 + 0 <= x2 <= u2 + and we have c, c1, c2 >= 0 + */ + + x10 = mul_64_64(gamma, c); + x20 = mul_64_64(epsilon, c); + + t_l1 = ceildiv_128_64(neg_128(x10), c1); + t_l2 = ceildiv_128_64(sub_128(x20, to_128(u2), &overflow), c2); + + t_u1 = floordiv_128_64(sub_128(to_128(u1), x10, &overflow), c1); + t_u2 = floordiv_128_64(x20, c2); + + if (overflow) { + return MEM_OVERLAP_OVERFLOW; + } + + if (gt_128(t_l2, t_l1)) { + t_l1 = t_l2; + } + + if (gt_128(t_u1, t_u2)) { + t_u1 = t_u2; + } + + if (gt_128(t_l1, t_u1)) { + ++*count; + return MEM_OVERLAP_NO; + } + + t_l = to_64(t_l1, &overflow); + t_u = to_64(t_u1, &overflow); + + x10 = add_128(x10, mul_64_64(c1, t_l), &overflow); + x20 = sub_128(x20, mul_64_64(c2, t_l), &overflow); + + t_u = safe_sub(t_u, t_l, &overflow); + t_l = 0; + x1 = to_64(x10, &overflow); + x2 = to_64(x20, &overflow); + + if (overflow) { + return MEM_OVERLAP_OVERFLOW; + } + + /* The bounds t_l, t_u ensure the x computed below do not overflow */ + + if (v == 1) { + /* Base case */ + if (t_u >= t_l) { + x[0] = x1 + c1*t_l; + x[1] = x2 - c2*t_l; + if (require_ub_nontrivial) { + int j, is_ub_trivial; + + is_ub_trivial = 1; + for (j = 0; j < n; ++j) { + if (x[j] != E[j].ub/2) { + is_ub_trivial = 0; + break; + } + } + + if (is_ub_trivial) { + /* Ignore 'trivial' solution */ + ++*count; + return MEM_OVERLAP_NO; + } + } + return MEM_OVERLAP_YES; + } + ++*count; + return MEM_OVERLAP_NO; + } + else { + /* Recurse to all candidates */ + for (t = t_l; t <= t_u; ++t) { + x[v] = x2 - c2*t; + + /* b2 = b - a2*x[v]; */ + b2 = safe_sub(b, safe_mul(a2, x[v], &overflow), &overflow); + if (overflow) { + return MEM_OVERLAP_OVERFLOW; + } + + res = diophantine_dfs(n, v-1, E, Ep, Gamma, Epsilon, + b2, max_work, require_ub_nontrivial, + x, count); + if (res != MEM_OVERLAP_NO) { + return res; + } + } + ++*count; + return MEM_OVERLAP_NO; + } +} + + +/** + * Solve bounded Diophantine equation + * + * The problem considered is:: + * + * A[0] x[0] + A[1] x[1] + ... + A[n-1] x[n-1] == b + * 0 <= x[i] <= U[i] + * A[i] > 0 + * + * Solve via depth-first Euclid's algorithm, as explained in [1]. + * + * If require_ub_nontrivial!=0, look for solutions to the problem + * where b = A[0]*(U[0]/2) + ... + A[n]*(U[n-1]/2) but ignoring + * the trivial solution x[i] = U[i]/2. All U[i] must be divisible by 2. + * The value given for `b` is ignored in this case. + */ +NPY_VISIBILITY_HIDDEN mem_overlap_t +solve_diophantine(unsigned int n, diophantine_term_t *E, npy_int64 b, + Py_ssize_t max_work, int require_ub_nontrivial, npy_int64 *x) +{ + unsigned int j; + + for (j = 0; j < n; ++j) { + if (E[j].a <= 0) { + return MEM_OVERLAP_ERROR; + } + else if (E[j].ub < 0) { + return MEM_OVERLAP_NO; + } + } + + if (require_ub_nontrivial) { + npy_int64 ub_sum = 0; + char overflow = 0; + for (j = 0; j < n; ++j) { + if (E[j].ub % 2 != 0) { + return MEM_OVERLAP_ERROR; + } + ub_sum = safe_add(ub_sum, + safe_mul(E[j].a, E[j].ub/2, &overflow), + &overflow); + } + if (overflow) { + return MEM_OVERLAP_ERROR; + } + b = ub_sum; + } + + if (b < 0) { + return MEM_OVERLAP_NO; + } + + if (n == 0) { + if (require_ub_nontrivial) { + /* Only trivial solution for 0-variable problem */ + return MEM_OVERLAP_NO; + } + if (b == 0) { + return MEM_OVERLAP_YES; + } + return MEM_OVERLAP_NO; + } + else if (n == 1) { + if (require_ub_nontrivial) { + /* Only trivial solution for 1-variable problem */ + return MEM_OVERLAP_NO; + } + if (b % E[0].a == 0) { + x[0] = b / E[0].a; + if (x[0] >= 0 && x[0] <= E[0].ub) { + return MEM_OVERLAP_YES; + } + } + return MEM_OVERLAP_NO; + } + else { + diophantine_term_t Ep[n]; + npy_int64 Epsilon[n], Gamma[n]; + Py_ssize_t count = 0; + + if (diophantine_precompute(n, E, Ep, Gamma, Epsilon)) { + return MEM_OVERLAP_OVERFLOW; + } + return diophantine_dfs(n, n-1, E, Ep, Gamma, Epsilon, b, max_work, + require_ub_nontrivial, x, &count); + } +} + + +static int +diophantine_sort_A(const void *xp, const void *yp) +{ + npy_int64 xa = ((diophantine_term_t*)xp)->a; + npy_int64 ya = ((diophantine_term_t*)yp)->a; + + if (xa < ya) { + return 1; + } + else if (ya < xa) { + return -1; + } + else { + return 0; + } +} + + +/** + * Simplify Diophantine decision problem. + * + * Combine identical coefficients, remove unnecessary variables, and trim + * bounds. + * + * The feasible/infeasible decision result is retained. + * + * Returns: 0 (success), -1 (integer overflow). + */ +NPY_VISIBILITY_HIDDEN int +diophantine_simplify(unsigned int *n, diophantine_term_t *E, npy_int64 b) +{ + unsigned int i, j, m; + char overflow = 0; + + /* Skip obviously infeasible cases */ + for (j = 0; j < *n; ++j) { + if (E[j].ub < 0) { + return 0; + } + } + + if (b < 0) { + return 0; + } + + /* Sort vs. coefficients */ + qsort(E, *n, sizeof(diophantine_term_t), diophantine_sort_A); + + /* Combine identical coefficients */ + m = *n; + i = 0; + for (j = 1; j < m; ++j) { + if (E[i].a == E[j].a) { + E[i].ub = safe_add(E[i].ub, E[j].ub, &overflow); + --*n; + } + else { + ++i; + if (i != j) { + E[i] = E[j]; + } + } + } + + /* Trim bounds and remove unnecessary variables */ + m = *n; + i = 0; + for (j = 0; j < m; ++j) { + E[j].ub = MIN(E[j].ub, b / E[j].a); + if (E[j].ub == 0) { + /* If the problem is feasible at all, x[i]=0 */ + --*n; + } + else { + if (i != j) { + E[i] = E[j]; + } + ++i; + } + } + + if (overflow) { + return -1; + } + else { + return 0; + } +} + + +/* Gets a half-open range [start, end) of offsets from the data pointer */ +NPY_VISIBILITY_HIDDEN void +offset_bounds_from_strides(const int itemsize, const int nd, + const npy_intp *dims, const npy_intp *strides, + npy_intp *lower_offset, npy_intp *upper_offset) +{ + npy_intp max_axis_offset; + npy_intp lower = 0; + npy_intp upper = 0; + int i; + + for (i = 0; i < nd; i++) { + if (dims[i] == 0) { + /* If the array size is zero, return an empty range */ + *lower_offset = 0; + *upper_offset = 0; + return; + } + /* Expand either upwards or downwards depending on stride */ + max_axis_offset = strides[i] * (dims[i] - 1); + if (max_axis_offset > 0) { + upper += max_axis_offset; + } + else { + lower += max_axis_offset; + } + } + /* Return a half-open range */ + upper += itemsize; + *lower_offset = lower; + *upper_offset = upper; +} + + +/* Gets a half-open range [start, end) which contains the array data */ +static void +get_array_memory_extents(PyArrayObject *arr, + npy_uintp *out_start, npy_uintp *out_end, + npy_uintp *num_bytes) +{ + npy_intp low, upper; + int j; + offset_bounds_from_strides(PyArray_ITEMSIZE(arr), PyArray_NDIM(arr), + PyArray_DIMS(arr), PyArray_STRIDES(arr), + &low, &upper); + *out_start = (npy_uintp)PyArray_DATA(arr) + (npy_uintp)low; + *out_end = (npy_uintp)PyArray_DATA(arr) + (npy_uintp)upper; + + *num_bytes = PyArray_ITEMSIZE(arr); + for (j = 0; j < PyArray_NDIM(arr); ++j) { + *num_bytes *= PyArray_DIM(arr, j); + } +} + + +static int +strides_to_terms(PyArrayObject *arr, diophantine_term_t *terms, + unsigned int *nterms, int skip_empty) +{ + unsigned int i; + + for (i = 0; i < PyArray_NDIM(arr); ++i) { + if (skip_empty) { + if (PyArray_DIM(arr, i) <= 1 || PyArray_STRIDE(arr, i) == 0) { + continue; + } + } + + terms[*nterms].a = PyArray_STRIDE(arr, i); + + if (terms[*nterms].a < 0) { + terms[*nterms].a = -terms[*nterms].a; + } + + if (terms[*nterms].a < 0) { + /* integer overflow */ + return 1; + } + + terms[*nterms].ub = PyArray_DIM(arr, i) - 1; + ++*nterms; + } + + return 0; +} + + +/** + * Determine whether two arrays share some memory. + * + * Returns: 0 (no shared memory), 1 (shared memory), or < 0 (failed to solve). + * + * Note that failures to solve can occur due to integer overflows, or effort + * required solving the problem exceeding max_work. The general problem is + * NP-hard and worst case runtime is exponential in the number of dimensions. + * max_work controls the amount of work done, either exact (max_work == -1), only + * a simple memory extent check (max_work == 0), or set an upper bound + * max_work > 0 for the number of solution candidates considered. + */ +NPY_VISIBILITY_HIDDEN mem_overlap_t +solve_may_share_memory(PyArrayObject *a, PyArrayObject *b, + Py_ssize_t max_work) +{ + npy_int64 rhs; + diophantine_term_t terms[2*NPY_MAXDIMS+2]; + npy_uintp start1 = 0, start2 = 0, end1 = 0, end2 = 0, size1 = 0, size2 = 0; + npy_int64 x[2*NPY_MAXDIMS+2]; + unsigned int nterms; + + get_array_memory_extents(a, &start1, &end1, &size1); + get_array_memory_extents(b, &start2, &end2, &size2); + + if (!(start1 < end2 && start2 < end1 && start1 < end1 && start2 < end2)) { + /* Memory extents don't overlap */ + return MEM_OVERLAP_NO; + } + + if (max_work == 0) { + /* Too much work required, give up */ + return MEM_OVERLAP_TOO_HARD; + } + + /* Convert problem to Diophantine equation form with positive coefficients. + The bounds computed by offset_bounds_from_strides correspond to + all-positive strides. + + start1 + sum(abs(stride1)*x1) + == start2 + sum(abs(stride2)*x2) + == end1 - 1 - sum(abs(stride1)*x1') + == end2 - 1 - sum(abs(stride2)*x2') + + <=> + + sum(abs(stride1)*x1) + sum(abs(stride2)*x2') + == end2 - 1 - start1 + + OR + + sum(abs(stride1)*x1') + sum(abs(stride2)*x2) + == end1 - 1 - start2 + + We pick the problem with the smaller RHS (they are non-negative due to + the extent check above.) + */ + + rhs = MIN(end2 - 1 - start1, end1 - 1 - start2); + + if (rhs != (npy_uintp)rhs) { + /* Integer overflow */ + return MEM_OVERLAP_OVERFLOW; + } + + nterms = 0; + if (strides_to_terms(a, terms, &nterms, 1)) { + return MEM_OVERLAP_OVERFLOW; + } + if (strides_to_terms(b, terms, &nterms, 1)) { + return MEM_OVERLAP_OVERFLOW; + } + if (PyArray_ITEMSIZE(a) > 1) { + terms[nterms].a = 1; + terms[nterms].ub = PyArray_ITEMSIZE(a) - 1; + ++nterms; + } + if (PyArray_ITEMSIZE(b) > 1) { + terms[nterms].a = 1; + terms[nterms].ub = PyArray_ITEMSIZE(b) - 1; + ++nterms; + } + + /* Simplify, if possible */ + if (diophantine_simplify(&nterms, terms, rhs)) { + /* Integer overflow */ + return MEM_OVERLAP_OVERFLOW; + } + + /* Solve */ + return solve_diophantine(nterms, terms, rhs, max_work, 0, x); +} + + +/** + * Determine whether an array has internal overlap. + * + * Returns: 0 (no overlap), 1 (overlap), or < 0 (failed to solve). + * + * max_work and reasons for solver failures are as in solve_may_share_memory. + */ +NPY_VISIBILITY_HIDDEN mem_overlap_t +solve_may_have_internal_overlap(PyArrayObject *a, Py_ssize_t max_work) +{ + diophantine_term_t terms[NPY_MAXDIMS+1]; + npy_int64 x[NPY_MAXDIMS+1]; + unsigned int nterms; + int i, j; + + if (PyArray_ISCONTIGUOUS(a)) { + /* Quick case */ + return MEM_OVERLAP_NO; + } + + /* The internal memory overlap problem is looking for two different + solutions to + + sum(a*x) = b, 0 <= x[i] <= ub[i] + + for any b. Equivalently, + + sum(a*x0) - sum(a*x1) = 0 + + Mapping the coefficients on the left by x0'[i] = x0[i] if a[i] > 0 + else ub[i]-x0[i] and opposite for x1, we have + + sum(abs(a)*(x0' + x1')) = sum(abs(a)*ub) + + Now, x0!=x1 if for some i we have x0'[i] + x1'[i] != ub[i]. + We can now change variables to z[i] = x0'[i] + x1'[i] so the problem + becomes + + sum(abs(a)*z) = sum(abs(a)*ub), 0 <= z[i] <= 2*ub[i], z != ub + + This can be solved with solve_diophantine. + */ + + nterms = 0; + if (strides_to_terms(a, terms, &nterms, 0)) { + return MEM_OVERLAP_OVERFLOW; + } + if (PyArray_ITEMSIZE(a) > 1) { + terms[nterms].a = 1; + terms[nterms].ub = PyArray_ITEMSIZE(a) - 1; + ++nterms; + } + + /* Get rid of zero coefficients and empty terms */ + i = 0; + for (j = 0; j < nterms; ++j) { + if (terms[j].ub == 0) { + continue; + } + else if (terms[j].ub < 0) { + return MEM_OVERLAP_NO; + } + else if (terms[j].a == 0) { + return MEM_OVERLAP_YES; + } + if (i != j) { + terms[i] = terms[j]; + } + ++i; + } + nterms = i; + + /* Double bounds to get the internal overlap problem */ + for (j = 0; j < nterms; ++j) { + terms[j].ub *= 2; + } + + /* Sort vs. coefficients; cannot call diophantine_simplify because it may + change the decision problem inequality part */ + qsort(terms, nterms, sizeof(diophantine_term_t), diophantine_sort_A); + + /* Solve */ + return solve_diophantine(nterms, terms, -1, max_work, 1, x); +} diff --git a/numpy/core/src/private/mem_overlap.h b/numpy/core/src/private/mem_overlap.h new file mode 100644 index 000000000..8044f1663 --- /dev/null +++ b/numpy/core/src/private/mem_overlap.h @@ -0,0 +1,50 @@ +#ifndef MEM_OVERLAP_H_ +#define MEM_OVERLAP_H_ + +#include "npy_config.h" +#include "numpy/ndarraytypes.h" + + +/* Bounds check only */ +#define NPY_MAY_SHARE_BOUNDS 0 + +/* Exact solution */ +#define NPY_MAY_SHARE_EXACT -1 + + +typedef enum { + MEM_OVERLAP_NO = 0, /* no solution exists */ + MEM_OVERLAP_YES = 1, /* solution found */ + MEM_OVERLAP_TOO_HARD = -1, /* max_work exceeded */ + MEM_OVERLAP_OVERFLOW = -2, /* algorithm failed due to integer overflow */ + MEM_OVERLAP_ERROR = -3 /* invalid input */ +} mem_overlap_t; + + +typedef struct { + npy_int64 a; + npy_int64 ub; +} diophantine_term_t; + +NPY_VISIBILITY_HIDDEN mem_overlap_t +solve_diophantine(unsigned int n, diophantine_term_t *E, + npy_int64 b, Py_ssize_t max_work, int require_nontrivial, + npy_int64 *x); + +NPY_VISIBILITY_HIDDEN int +diophantine_simplify(unsigned int *n, diophantine_term_t *E, npy_int64 b); + +NPY_VISIBILITY_HIDDEN mem_overlap_t +solve_may_share_memory(PyArrayObject *a, PyArrayObject *b, + Py_ssize_t max_work); + +NPY_VISIBILITY_HIDDEN mem_overlap_t +solve_may_have_internal_overlap(PyArrayObject *a, Py_ssize_t max_work); + +NPY_VISIBILITY_HIDDEN void +offset_bounds_from_strides(const int itemsize, const int nd, + const npy_intp *dims, const npy_intp *strides, + npy_intp *lower_offset, npy_intp *upper_offset); + +#endif + diff --git a/numpy/core/src/private/npy_config.h b/numpy/core/src/private/npy_config.h index 6e98dc7e9..fa20eb4f3 100644 --- a/numpy/core/src/private/npy_config.h +++ b/numpy/core/src/private/npy_config.h @@ -3,6 +3,7 @@ #include "config.h" #include "numpy/numpyconfig.h" +#include "numpy/npy_cpu.h" /* * largest alignment the copy loops might require @@ -13,7 +14,11 @@ * amd64 is not harmed much by the bloat as the system provides 16 byte * alignment by default. */ +#if (defined NPY_CPU_X86 || defined _WIN32) +#define NPY_MAX_COPY_ALIGNMENT 8 +#else #define NPY_MAX_COPY_ALIGNMENT 16 +#endif /* blacklist */ @@ -27,7 +32,7 @@ #endif /* Disable broken MS math functions */ -#if defined(_MSC_VER) || defined(__MINGW32_VERSION) +#if (defined(_MSC_VER) && (_MSC_VER < 1900)) || defined(__MINGW32_VERSION) #undef HAVE_ATAN2 #undef HAVE_ATAN2F @@ -39,6 +44,32 @@ #endif +#if defined(_MSC_VER) && (_MSC_VER == 1900) + +#undef HAVE_CASIN +#undef HAVE_CASINF +#undef HAVE_CASINL +#undef HAVE_CASINH +#undef HAVE_CASINHF +#undef HAVE_CASINHL +#undef HAVE_CATAN +#undef HAVE_CATANF +#undef HAVE_CATANL +#undef HAVE_CATANH +#undef HAVE_CATANHF +#undef HAVE_CATANHL + +#endif + + +/* Intel C for Windows uses POW for 64 bits longdouble*/ +#if defined(_MSC_VER) && defined(__INTEL_COMPILER) +#if defined(HAVE_POWL) && (NPY_SIZEOF_LONGDOUBLE == 8) +#undef HAVE_POWL +#endif +#endif /* defined(_MSC_VER) && defined(__INTEL_COMPILER) */ + + /* Disable broken gnu trig functions on linux */ #if defined(__linux__) && defined(__GNUC__) diff --git a/numpy/core/src/private/npy_extint128.h b/numpy/core/src/private/npy_extint128.h new file mode 100644 index 000000000..a887ff317 --- /dev/null +++ b/numpy/core/src/private/npy_extint128.h @@ -0,0 +1,317 @@ +#ifndef NPY_EXTINT128_H_ +#define NPY_EXTINT128_H_ + + +typedef struct { + signed char sign; + npy_uint64 lo, hi; +} npy_extint128_t; + + +/* Integer addition with overflow checking */ +static NPY_INLINE npy_int64 +safe_add(npy_int64 a, npy_int64 b, char *overflow_flag) +{ + if (a > 0 && b > NPY_MAX_INT64 - a) { + *overflow_flag = 1; + } + else if (a < 0 && b < NPY_MIN_INT64 - a) { + *overflow_flag = 1; + } + return a + b; +} + + +/* Integer subtraction with overflow checking */ +static NPY_INLINE npy_int64 +safe_sub(npy_int64 a, npy_int64 b, char *overflow_flag) +{ + if (a >= 0 && b < a - NPY_MAX_INT64) { + *overflow_flag = 1; + } + else if (a < 0 && b > a - NPY_MIN_INT64) { + *overflow_flag = 1; + } + return a - b; +} + + +/* Integer multiplication with overflow checking */ +static NPY_INLINE npy_int64 +safe_mul(npy_int64 a, npy_int64 b, char *overflow_flag) +{ + if (a > 0) { + if (b > NPY_MAX_INT64 / a || b < NPY_MIN_INT64 / a) { + *overflow_flag = 1; + } + } + else if (a < 0) { + if (b > 0 && a < NPY_MIN_INT64 / b) { + *overflow_flag = 1; + } + else if (b < 0 && a < NPY_MAX_INT64 / b) { + *overflow_flag = 1; + } + } + return a * b; +} + + +/* Long integer init */ +static NPY_INLINE npy_extint128_t +to_128(npy_int64 x) +{ + npy_extint128_t result; + result.sign = (x >= 0 ? 1 : -1); + if (x >= 0) { + result.lo = x; + } + else { + result.lo = (npy_uint64)(-(x + 1)) + 1; + } + result.hi = 0; + return result; +} + + +static NPY_INLINE npy_int64 +to_64(npy_extint128_t x, char *overflow) +{ + if (x.hi != 0 || + (x.sign > 0 && x.lo > NPY_MAX_INT64) || + (x.sign < 0 && x.lo != 0 && x.lo - 1 > -(NPY_MIN_INT64 + 1))) { + *overflow = 1; + } + return x.lo * x.sign; +} + + +/* Long integer multiply */ +static NPY_INLINE npy_extint128_t +mul_64_64(npy_int64 a, npy_int64 b) +{ + npy_extint128_t x, y, z; + npy_uint64 x1, x2, y1, y2, r1, r2, prev; + + x = to_128(a); + y = to_128(b); + + x1 = x.lo & 0xffffffff; + x2 = x.lo >> 32; + + y1 = y.lo & 0xffffffff; + y2 = y.lo >> 32; + + r1 = x1*y2; + r2 = x2*y1; + + z.sign = x.sign * y.sign; + z.hi = x2*y2 + (r1 >> 32) + (r2 >> 32); + z.lo = x1*y1; + + /* Add with carry */ + prev = z.lo; + z.lo += (r1 << 32); + if (z.lo < prev) { + ++z.hi; + } + + prev = z.lo; + z.lo += (r2 << 32); + if (z.lo < prev) { + ++z.hi; + } + + return z; +} + + +/* Long integer add */ +static NPY_INLINE npy_extint128_t +add_128(npy_extint128_t x, npy_extint128_t y, char *overflow) +{ + npy_extint128_t z; + + if (x.sign == y.sign) { + z.sign = x.sign; + z.hi = x.hi + y.hi; + if (z.hi < x.hi) { + *overflow = 1; + } + z.lo = x.lo + y.lo; + if (z.lo < x.lo) { + if (z.hi == NPY_MAX_UINT64) { + *overflow = 1; + } + ++z.hi; + } + } + else if (x.hi > y.hi || (x.hi == y.hi && x.lo >= y.lo)) { + z.sign = x.sign; + z.hi = x.hi - y.hi; + z.lo = x.lo; + z.lo -= y.lo; + if (z.lo > x.lo) { + --z.hi; + } + } + else { + z.sign = y.sign; + z.hi = y.hi - x.hi; + z.lo = y.lo; + z.lo -= x.lo; + if (z.lo > y.lo) { + --z.hi; + } + } + + return z; +} + + +/* Long integer negation */ +static NPY_INLINE npy_extint128_t +neg_128(npy_extint128_t x) +{ + npy_extint128_t z = x; + z.sign *= -1; + return z; +} + + +static NPY_INLINE npy_extint128_t +sub_128(npy_extint128_t x, npy_extint128_t y, char *overflow) +{ + return add_128(x, neg_128(y), overflow); +} + + +static NPY_INLINE npy_extint128_t +shl_128(npy_extint128_t v) +{ + npy_extint128_t z; + z = v; + z.hi <<= 1; + z.hi |= (z.lo & (((npy_uint64)1) << 63)) >> 63; + z.lo <<= 1; + return z; +} + + +static NPY_INLINE npy_extint128_t +shr_128(npy_extint128_t v) +{ + npy_extint128_t z; + z = v; + z.lo >>= 1; + z.lo |= (z.hi & 0x1) << 63; + z.hi >>= 1; + return z; +} + +static NPY_INLINE int +gt_128(npy_extint128_t a, npy_extint128_t b) +{ + if (a.sign > 0 && b.sign > 0) { + return (a.hi > b.hi) || (a.hi == b.hi && a.lo > b.lo); + } + else if (a.sign < 0 && b.sign < 0) { + return (a.hi < b.hi) || (a.hi == b.hi && a.lo < b.lo); + } + else if (a.sign > 0 && b.sign < 0) { + return a.hi != 0 || a.lo != 0 || b.hi != 0 || b.lo != 0; + } + else { + return 0; + } +} + + +/* Long integer divide */ +static NPY_INLINE npy_extint128_t +divmod_128_64(npy_extint128_t x, npy_int64 b, npy_int64 *mod) +{ + npy_extint128_t remainder, pointer, result, divisor; + char overflow = 0; + + assert(b > 0); + + if (b <= 1 || x.hi == 0) { + result.sign = x.sign; + result.lo = x.lo / b; + result.hi = x.hi / b; + *mod = x.sign * (x.lo % b); + return result; + } + + /* Long division, not the most efficient choice */ + remainder = x; + remainder.sign = 1; + + divisor.sign = 1; + divisor.hi = 0; + divisor.lo = b; + + result.sign = 1; + result.lo = 0; + result.hi = 0; + + pointer.sign = 1; + pointer.lo = 1; + pointer.hi = 0; + + while ((divisor.hi & (((npy_uint64)1) << 63)) == 0 && + gt_128(remainder, divisor)) { + divisor = shl_128(divisor); + pointer = shl_128(pointer); + } + + while (pointer.lo || pointer.hi) { + if (!gt_128(divisor, remainder)) { + remainder = sub_128(remainder, divisor, &overflow); + result = add_128(result, pointer, &overflow); + } + divisor = shr_128(divisor); + pointer = shr_128(pointer); + } + + /* Fix signs and return; cannot overflow */ + result.sign = x.sign; + *mod = x.sign * remainder.lo; + + return result; +} + + +/* Divide and round down (positive divisor; no overflows) */ +static NPY_INLINE npy_extint128_t +floordiv_128_64(npy_extint128_t a, npy_int64 b) +{ + npy_extint128_t result; + npy_int64 remainder; + char overflow = 0; + assert(b > 0); + result = divmod_128_64(a, b, &remainder); + if (a.sign < 0 && remainder != 0) { + result = sub_128(result, to_128(1), &overflow); + } + return result; +} + + +/* Divide and round up (positive divisor; no overflows) */ +static NPY_INLINE npy_extint128_t +ceildiv_128_64(npy_extint128_t a, npy_int64 b) +{ + npy_extint128_t result; + npy_int64 remainder; + char overflow = 0; + assert(b > 0); + result = divmod_128_64(a, b, &remainder); + if (a.sign > 0 && remainder != 0) { + result = add_128(result, to_128(1), &overflow); + } + return result; +} + +#endif diff --git a/numpy/core/src/private/npy_import.h b/numpy/core/src/private/npy_import.h new file mode 100644 index 000000000..221e1e645 --- /dev/null +++ b/numpy/core/src/private/npy_import.h @@ -0,0 +1,32 @@ +#ifndef NPY_IMPORT_H +#define NPY_IMPORT_H + +#include <Python.h> + +/*! \brief Fetch and cache Python function. + * + * Import a Python function and cache it for use. The function checks if + * cache is NULL, and if not NULL imports the Python function specified by + * \a module and \a function, increments its reference count, and stores + * the result in \a cache. Usually \a cache will be a static variable and + * should be initialized to NULL. On error \a cache will contain NULL on + * exit, + * + * @param module Absolute module name. + * @param attr module attribute to cache. + * @param cache Storage location for imported function. + */ +NPY_INLINE static void +npy_cache_import(const char *module, const char *attr, PyObject **cache) +{ + if (*cache == NULL) { + PyObject *mod = PyImport_ImportModule(module); + + if (mod != NULL) { + *cache = PyObject_GetAttrString(mod, attr); + Py_DECREF(mod); + } + } +} + +#endif diff --git a/numpy/core/src/private/npy_sort.h b/numpy/core/src/private/npy_sort.h index 85630b2df..511d71b01 100644 --- a/numpy/core/src/private/npy_sort.h +++ b/numpy/core/src/private/npy_sort.h @@ -10,187 +10,187 @@ #define NPY_ECOMP 2 -int quicksort_bool(npy_bool *vec, npy_intp cnt, void *null); -int heapsort_bool(npy_bool *vec, npy_intp cnt, void *null); -int mergesort_bool(npy_bool *vec, npy_intp cnt, void *null); -int aquicksort_bool(npy_bool *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_bool(npy_bool *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_bool(npy_bool *vec, npy_intp *ind, npy_intp cnt, void *null); +int quicksort_bool(void *vec, npy_intp cnt, void *null); +int heapsort_bool(void *vec, npy_intp cnt, void *null); +int mergesort_bool(void *vec, npy_intp cnt, void *null); +int aquicksort_bool(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_bool(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_bool(void *vec, npy_intp *ind, npy_intp cnt, void *null); -int quicksort_byte(npy_byte *vec, npy_intp cnt, void *null); -int heapsort_byte(npy_byte *vec, npy_intp cnt, void *null); -int mergesort_byte(npy_byte *vec, npy_intp cnt, void *null); -int aquicksort_byte(npy_byte *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_byte(npy_byte *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_byte(npy_byte *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_ubyte(npy_ubyte *vec, npy_intp cnt, void *null); -int heapsort_ubyte(npy_ubyte *vec, npy_intp cnt, void *null); -int mergesort_ubyte(npy_ubyte *vec, npy_intp cnt, void *null); -int aquicksort_ubyte(npy_ubyte *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_ubyte(npy_ubyte *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_ubyte(npy_ubyte *vec, npy_intp *ind, npy_intp cnt, void *null); +int quicksort_byte(void *vec, npy_intp cnt, void *null); +int heapsort_byte(void *vec, npy_intp cnt, void *null); +int mergesort_byte(void *vec, npy_intp cnt, void *null); +int aquicksort_byte(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_byte(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_byte(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_ubyte(void *vec, npy_intp cnt, void *null); +int heapsort_ubyte(void *vec, npy_intp cnt, void *null); +int mergesort_ubyte(void *vec, npy_intp cnt, void *null); +int aquicksort_ubyte(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_ubyte(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_ubyte(void *vec, npy_intp *ind, npy_intp cnt, void *null); -int quicksort_short(npy_short *vec, npy_intp cnt, void *null); -int heapsort_short(npy_short *vec, npy_intp cnt, void *null); -int mergesort_short(npy_short *vec, npy_intp cnt, void *null); -int aquicksort_short(npy_short *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_short(npy_short *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_short(npy_short *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_ushort(npy_ushort *vec, npy_intp cnt, void *null); -int heapsort_ushort(npy_ushort *vec, npy_intp cnt, void *null); -int mergesort_ushort(npy_ushort *vec, npy_intp cnt, void *null); -int aquicksort_ushort(npy_ushort *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_ushort(npy_ushort *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_ushort(npy_ushort *vec, npy_intp *ind, npy_intp cnt, void *null); +int quicksort_short(void *vec, npy_intp cnt, void *null); +int heapsort_short(void *vec, npy_intp cnt, void *null); +int mergesort_short(void *vec, npy_intp cnt, void *null); +int aquicksort_short(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_short(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_short(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_ushort(void *vec, npy_intp cnt, void *null); +int heapsort_ushort(void *vec, npy_intp cnt, void *null); +int mergesort_ushort(void *vec, npy_intp cnt, void *null); +int aquicksort_ushort(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_ushort(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_ushort(void *vec, npy_intp *ind, npy_intp cnt, void *null); -int quicksort_int(npy_int *vec, npy_intp cnt, void *null); -int heapsort_int(npy_int *vec, npy_intp cnt, void *null); -int mergesort_int(npy_int *vec, npy_intp cnt, void *null); -int aquicksort_int(npy_int *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_int(npy_int *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_int(npy_int *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_uint(npy_uint *vec, npy_intp cnt, void *null); -int heapsort_uint(npy_uint *vec, npy_intp cnt, void *null); -int mergesort_uint(npy_uint *vec, npy_intp cnt, void *null); -int aquicksort_uint(npy_uint *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_uint(npy_uint *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_uint(npy_uint *vec, npy_intp *ind, npy_intp cnt, void *null); +int quicksort_int(void *vec, npy_intp cnt, void *null); +int heapsort_int(void *vec, npy_intp cnt, void *null); +int mergesort_int(void *vec, npy_intp cnt, void *null); +int aquicksort_int(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_int(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_int(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_uint(void *vec, npy_intp cnt, void *null); +int heapsort_uint(void *vec, npy_intp cnt, void *null); +int mergesort_uint(void *vec, npy_intp cnt, void *null); +int aquicksort_uint(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_uint(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_uint(void *vec, npy_intp *ind, npy_intp cnt, void *null); -int quicksort_long(npy_long *vec, npy_intp cnt, void *null); -int heapsort_long(npy_long *vec, npy_intp cnt, void *null); -int mergesort_long(npy_long *vec, npy_intp cnt, void *null); -int aquicksort_long(npy_long *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_long(npy_long *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_long(npy_long *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_ulong(npy_ulong *vec, npy_intp cnt, void *null); -int heapsort_ulong(npy_ulong *vec, npy_intp cnt, void *null); -int mergesort_ulong(npy_ulong *vec, npy_intp cnt, void *null); -int aquicksort_ulong(npy_ulong *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_ulong(npy_ulong *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_ulong(npy_ulong *vec, npy_intp *ind, npy_intp cnt, void *null); +int quicksort_long(void *vec, npy_intp cnt, void *null); +int heapsort_long(void *vec, npy_intp cnt, void *null); +int mergesort_long(void *vec, npy_intp cnt, void *null); +int aquicksort_long(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_long(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_long(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_ulong(void *vec, npy_intp cnt, void *null); +int heapsort_ulong(void *vec, npy_intp cnt, void *null); +int mergesort_ulong(void *vec, npy_intp cnt, void *null); +int aquicksort_ulong(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_ulong(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_ulong(void *vec, npy_intp *ind, npy_intp cnt, void *null); -int quicksort_longlong(npy_longlong *vec, npy_intp cnt, void *null); -int heapsort_longlong(npy_longlong *vec, npy_intp cnt, void *null); -int mergesort_longlong(npy_longlong *vec, npy_intp cnt, void *null); -int aquicksort_longlong(npy_longlong *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_longlong(npy_longlong *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_longlong(npy_longlong *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_ulonglong(npy_ulonglong *vec, npy_intp cnt, void *null); -int heapsort_ulonglong(npy_ulonglong *vec, npy_intp cnt, void *null); -int mergesort_ulonglong(npy_ulonglong *vec, npy_intp cnt, void *null); -int aquicksort_ulonglong(npy_ulonglong *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_ulonglong(npy_ulonglong *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_ulonglong(npy_ulonglong *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_half(npy_ushort *vec, npy_intp cnt, void *null); -int heapsort_half(npy_ushort *vec, npy_intp cnt, void *null); -int mergesort_half(npy_ushort *vec, npy_intp cnt, void *null); -int aquicksort_half(npy_ushort *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_half(npy_ushort *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_half(npy_ushort *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_float(npy_float *vec, npy_intp cnt, void *null); -int heapsort_float(npy_float *vec, npy_intp cnt, void *null); -int mergesort_float(npy_float *vec, npy_intp cnt, void *null); -int aquicksort_float(npy_float *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_float(npy_float *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_float(npy_float *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_double(npy_double *vec, npy_intp cnt, void *null); -int heapsort_double(npy_double *vec, npy_intp cnt, void *null); -int mergesort_double(npy_double *vec, npy_intp cnt, void *null); -int aquicksort_double(npy_double *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_double(npy_double *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_double(npy_double *vec, npy_intp *ind, npy_intp cnt, void *null); +int quicksort_longlong(void *vec, npy_intp cnt, void *null); +int heapsort_longlong(void *vec, npy_intp cnt, void *null); +int mergesort_longlong(void *vec, npy_intp cnt, void *null); +int aquicksort_longlong(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_longlong(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_longlong(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_ulonglong(void *vec, npy_intp cnt, void *null); +int heapsort_ulonglong(void *vec, npy_intp cnt, void *null); +int mergesort_ulonglong(void *vec, npy_intp cnt, void *null); +int aquicksort_ulonglong(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_ulonglong(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_ulonglong(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_half(void *vec, npy_intp cnt, void *null); +int heapsort_half(void *vec, npy_intp cnt, void *null); +int mergesort_half(void *vec, npy_intp cnt, void *null); +int aquicksort_half(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_half(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_half(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_float(void *vec, npy_intp cnt, void *null); +int heapsort_float(void *vec, npy_intp cnt, void *null); +int mergesort_float(void *vec, npy_intp cnt, void *null); +int aquicksort_float(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_float(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_float(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_double(void *vec, npy_intp cnt, void *null); +int heapsort_double(void *vec, npy_intp cnt, void *null); +int mergesort_double(void *vec, npy_intp cnt, void *null); +int aquicksort_double(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_double(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_double(void *vec, npy_intp *ind, npy_intp cnt, void *null); -int quicksort_longdouble(npy_longdouble *vec, npy_intp cnt, void *null); -int heapsort_longdouble(npy_longdouble *vec, npy_intp cnt, void *null); -int mergesort_longdouble(npy_longdouble *vec, npy_intp cnt, void *null); -int aquicksort_longdouble(npy_longdouble *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_longdouble(npy_longdouble *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_longdouble(npy_longdouble *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_cfloat(npy_cfloat *vec, npy_intp cnt, void *null); -int heapsort_cfloat(npy_cfloat *vec, npy_intp cnt, void *null); -int mergesort_cfloat(npy_cfloat *vec, npy_intp cnt, void *null); -int aquicksort_cfloat(npy_cfloat *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_cfloat(npy_cfloat *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_cfloat(npy_cfloat *vec, npy_intp *ind, npy_intp cnt, void *null); +int quicksort_longdouble(void *vec, npy_intp cnt, void *null); +int heapsort_longdouble(void *vec, npy_intp cnt, void *null); +int mergesort_longdouble(void *vec, npy_intp cnt, void *null); +int aquicksort_longdouble(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_longdouble(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_longdouble(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_cfloat(void *vec, npy_intp cnt, void *null); +int heapsort_cfloat(void *vec, npy_intp cnt, void *null); +int mergesort_cfloat(void *vec, npy_intp cnt, void *null); +int aquicksort_cfloat(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_cfloat(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_cfloat(void *vec, npy_intp *ind, npy_intp cnt, void *null); -int quicksort_cdouble(npy_cdouble *vec, npy_intp cnt, void *null); -int heapsort_cdouble(npy_cdouble *vec, npy_intp cnt, void *null); -int mergesort_cdouble(npy_cdouble *vec, npy_intp cnt, void *null); -int aquicksort_cdouble(npy_cdouble *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_cdouble(npy_cdouble *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_cdouble(npy_cdouble *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_clongdouble(npy_clongdouble *vec, npy_intp cnt, void *null); -int heapsort_clongdouble(npy_clongdouble *vec, npy_intp cnt, void *null); -int mergesort_clongdouble(npy_clongdouble *vec, npy_intp cnt, void *null); -int aquicksort_clongdouble(npy_clongdouble *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_clongdouble(npy_clongdouble *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_clongdouble(npy_clongdouble *vec, npy_intp *ind, npy_intp cnt, void *null); +int quicksort_cdouble(void *vec, npy_intp cnt, void *null); +int heapsort_cdouble(void *vec, npy_intp cnt, void *null); +int mergesort_cdouble(void *vec, npy_intp cnt, void *null); +int aquicksort_cdouble(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_cdouble(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_cdouble(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_clongdouble(void *vec, npy_intp cnt, void *null); +int heapsort_clongdouble(void *vec, npy_intp cnt, void *null); +int mergesort_clongdouble(void *vec, npy_intp cnt, void *null); +int aquicksort_clongdouble(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_clongdouble(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_clongdouble(void *vec, npy_intp *ind, npy_intp cnt, void *null); -int quicksort_string(npy_char *vec, npy_intp cnt, PyArrayObject *arr); -int heapsort_string(npy_char *vec, npy_intp cnt, PyArrayObject *arr); -int mergesort_string(npy_char *vec, npy_intp cnt, PyArrayObject *arr); -int aquicksort_string(npy_char *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr); -int aheapsort_string(npy_char *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr); -int amergesort_string(npy_char *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr); - - -int quicksort_unicode(npy_ucs4 *vec, npy_intp cnt, PyArrayObject *arr); -int heapsort_unicode(npy_ucs4 *vec, npy_intp cnt, PyArrayObject *arr); -int mergesort_unicode(npy_ucs4 *vec, npy_intp cnt, PyArrayObject *arr); -int aquicksort_unicode(npy_ucs4 *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr); -int aheapsort_unicode(npy_ucs4 *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr); -int amergesort_unicode(npy_ucs4 *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr); +int quicksort_string(void *vec, npy_intp cnt, void *arr); +int heapsort_string(void *vec, npy_intp cnt, void *arr); +int mergesort_string(void *vec, npy_intp cnt, void *arr); +int aquicksort_string(void *vec, npy_intp *ind, npy_intp cnt, void *arr); +int aheapsort_string(void *vec, npy_intp *ind, npy_intp cnt, void *arr); +int amergesort_string(void *vec, npy_intp *ind, npy_intp cnt, void *arr); + + +int quicksort_unicode(void *vec, npy_intp cnt, void *arr); +int heapsort_unicode(void *vec, npy_intp cnt, void *arr); +int mergesort_unicode(void *vec, npy_intp cnt, void *arr); +int aquicksort_unicode(void *vec, npy_intp *ind, npy_intp cnt, void *arr); +int aheapsort_unicode(void *vec, npy_intp *ind, npy_intp cnt, void *arr); +int amergesort_unicode(void *vec, npy_intp *ind, npy_intp cnt, void *arr); -int quicksort_datetime(npy_datetime *vec, npy_intp cnt, void *null); -int heapsort_datetime(npy_datetime *vec, npy_intp cnt, void *null); -int mergesort_datetime(npy_datetime *vec, npy_intp cnt, void *null); -int aquicksort_datetime(npy_datetime *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_datetime(npy_datetime *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_datetime(npy_datetime *vec, npy_intp *ind, npy_intp cnt, void *null); - - -int quicksort_timedelta(npy_timedelta *vec, npy_intp cnt, void *null); -int heapsort_timedelta(npy_timedelta *vec, npy_intp cnt, void *null); -int mergesort_timedelta(npy_timedelta *vec, npy_intp cnt, void *null); -int aquicksort_timedelta(npy_timedelta *vec, npy_intp *ind, npy_intp cnt, void *null); -int aheapsort_timedelta(npy_timedelta *vec, npy_intp *ind, npy_intp cnt, void *null); -int amergesort_timedelta(npy_timedelta *vec, npy_intp *ind, npy_intp cnt, void *null); +int quicksort_datetime(void *vec, npy_intp cnt, void *null); +int heapsort_datetime(void *vec, npy_intp cnt, void *null); +int mergesort_datetime(void *vec, npy_intp cnt, void *null); +int aquicksort_datetime(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_datetime(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_datetime(void *vec, npy_intp *ind, npy_intp cnt, void *null); + + +int quicksort_timedelta(void *vec, npy_intp cnt, void *null); +int heapsort_timedelta(void *vec, npy_intp cnt, void *null); +int mergesort_timedelta(void *vec, npy_intp cnt, void *null); +int aquicksort_timedelta(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int aheapsort_timedelta(void *vec, npy_intp *ind, npy_intp cnt, void *null); +int amergesort_timedelta(void *vec, npy_intp *ind, npy_intp cnt, void *null); -int npy_quicksort(char *vec, npy_intp cnt, PyArrayObject *arr); -int npy_heapsort(char *vec, npy_intp cnt, PyArrayObject *arr); -int npy_mergesort(char *vec, npy_intp cnt, PyArrayObject *arr); -int npy_aquicksort(char *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr); -int npy_aheapsort(char *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr); -int npy_amergesort(char *vec, npy_intp *ind, npy_intp cnt, PyArrayObject *arr); +int npy_quicksort(void *vec, npy_intp cnt, void *arr); +int npy_heapsort(void *vec, npy_intp cnt, void *arr); +int npy_mergesort(void *vec, npy_intp cnt, void *arr); +int npy_aquicksort(void *vec, npy_intp *ind, npy_intp cnt, void *arr); +int npy_aheapsort(void *vec, npy_intp *ind, npy_intp cnt, void *arr); +int npy_amergesort(void *vec, npy_intp *ind, npy_intp cnt, void *arr); #endif diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index a69fc8147..e57dd5bd0 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -603,11 +603,21 @@ PyUFunc_On_Om(char **args, npy_intp *dimensions, npy_intp *steps, void *func) if (result == NULL) { return; } - if (PyTuple_Check(result)) { - if (nout != PyTuple_Size(result)) { - Py_DECREF(result); - return; - } + if (nout == 0 && result == Py_None) { + /* No output expected, no output received, continue */ + Py_DECREF(result); + } + else if (nout == 1) { + /* Single output expected, assign and continue */ + op = (PyObject **)ptrs[nin]; + Py_XDECREF(*op); + *op = result; + } + else if (PyTuple_Check(result) && nout == PyTuple_Size(result)) { + /* + * Multiple returns match expected number of outputs, assign + * and continue. Will also gobble empty tuples if nout == 0. + */ for(j = 0; j < nout; j++) { op = (PyObject **)ptrs[j+nin]; Py_XDECREF(*op); @@ -617,9 +627,9 @@ PyUFunc_On_Om(char **args, npy_intp *dimensions, npy_intp *steps, void *func) Py_DECREF(result); } else { - op = (PyObject **)ptrs[nin]; - Py_XDECREF(*op); - *op = result; + /* Mismatch between returns and expected outputs, exit */ + Py_DECREF(result); + return; } for(j = 0; j < ntot; j++) { ptrs[j] += steps[j]; @@ -1130,26 +1140,17 @@ NPY_NO_EXPORT void NPY_NO_EXPORT void @TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) { - if (IS_BINARY_REDUCE) { - BINARY_REDUCE_LOOP(@type@) { - const @type@ in2 = *(@type@ *)ip2; - io1 = (io1 @OP@ in2 || in2 == NPY_DATETIME_NAT) ? io1 : in2; + BINARY_LOOP { + const @type@ in1 = *(@type@ *)ip1; + const @type@ in2 = *(@type@ *)ip2; + if (in1 == NPY_DATETIME_NAT) { + *((@type@ *)op1) = in2; } - *((@type@ *)iop1) = io1; - } - else { - BINARY_LOOP { - const @type@ in1 = *(@type@ *)ip1; - const @type@ in2 = *(@type@ *)ip2; - if (in1 == NPY_DATETIME_NAT) { - *((@type@ *)op1) = in2; - } - else if (in2 == NPY_DATETIME_NAT) { - *((@type@ *)op1) = in1; - } - else { - *((@type@ *)op1) = (in1 @OP@ in2) ? in1 : in2; - } + else if (in2 == NPY_DATETIME_NAT) { + *((@type@ *)op1) = in1; + } + else { + *((@type@ *)op1) = (in1 @OP@ in2) ? in1 : in2; } } } @@ -1285,11 +1286,17 @@ TIMEDELTA_md_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void BINARY_LOOP { const npy_timedelta in1 = *(npy_timedelta *)ip1; const double in2 = *(double *)ip2; - if (in1 == NPY_DATETIME_NAT || npy_isnan(in2)) { + if (in1 == NPY_DATETIME_NAT) { *((npy_timedelta *)op1) = NPY_DATETIME_NAT; } else { - *((npy_timedelta *)op1) = (npy_timedelta)(in1 * in2); + double result = in1 * in2; + if (npy_isfinite(result)) { + *((npy_timedelta *)op1) = (npy_timedelta)result; + } + else { + *((npy_timedelta *)op1) = NPY_DATETIME_NAT; + } } } } @@ -1300,11 +1307,17 @@ TIMEDELTA_dm_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void BINARY_LOOP { const double in1 = *(double *)ip1; const npy_timedelta in2 = *(npy_timedelta *)ip2; - if (npy_isnan(in1) || in2 == NPY_DATETIME_NAT) { + if (in2 == NPY_DATETIME_NAT) { *((npy_timedelta *)op1) = NPY_DATETIME_NAT; } else { - *((npy_timedelta *)op1) = (npy_timedelta)(in1 * in2); + double result = in1 * in2; + if (npy_isfinite(result)) { + *((npy_timedelta *)op1) = (npy_timedelta)result; + } + else { + *((npy_timedelta *)op1) = NPY_DATETIME_NAT; + } } } } @@ -1336,11 +1349,11 @@ TIMEDELTA_md_m_divide(char **args, npy_intp *dimensions, npy_intp *steps, void * } else { double result = in1 / in2; - if (npy_isnan(result)) { - *((npy_timedelta *)op1) = NPY_DATETIME_NAT; + if (npy_isfinite(result)) { + *((npy_timedelta *)op1) = (npy_timedelta)result; } else { - *((npy_timedelta *)op1) = (npy_timedelta)(result); + *((npy_timedelta *)op1) = NPY_DATETIME_NAT; } } } @@ -2563,6 +2576,7 @@ OBJECT_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUS if (ret_obj == NULL) { #if @identity@ != -1 if (in1 == in2) { + /* 2014-01-26, 1.9 */ PyErr_Clear(); if (DEPRECATE("numpy @kind@ will not check object identity " "in the future. The comparison error will " @@ -2580,6 +2594,7 @@ OBJECT_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUS if (ret == -1) { #if @identity@ != -1 if (in1 == in2) { + /* 2014-01-26, 1.9 */ PyErr_Clear(); if (DEPRECATE("numpy @kind@ will not check object identity " "in the future. The error trying to get the " @@ -2595,6 +2610,7 @@ OBJECT_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUS } #if @identity@ != -1 if ((in1 == in2) && ((npy_bool)ret != @identity@)) { + /* 2014-01-26, 1.9 */ if (DEPRECATE_FUTUREWARNING( "numpy @kind@ will not check object identity " "in the future. The comparison did not return the " diff --git a/numpy/core/src/umath/scalarmath.c.src b/numpy/core/src/umath/scalarmath.c.src index e2c8137b3..010261214 100644 --- a/numpy/core/src/umath/scalarmath.c.src +++ b/numpy/core/src/umath/scalarmath.c.src @@ -485,10 +485,8 @@ static void /**begin repeat - * #name = byte, short, int, long, longlong, - * float, double, longdouble# - * #type = npy_byte, npy_short, npy_int, npy_long, npy_longlong, - * npy_float, npy_double, npy_longdouble# + * #name = byte, short, int, long, longlong# + * #type = npy_byte, npy_short, npy_int, npy_long, npy_longlong# */ static void @name@_ctype_absolute(@type@ a, @type@ *out) @@ -497,6 +495,18 @@ static void } /**end repeat**/ +/**begin repeat + * #name = float, double, longdouble# + * #type = npy_float, npy_double, npy_longdouble# + * #c = f,,l# + */ +static void +@name@_ctype_absolute(@type@ a, @type@ *out) +{ + *out = npy_fabs@c@(a); +} +/**end repeat**/ + static void half_ctype_absolute(npy_half a, npy_half *out) { @@ -1407,7 +1417,7 @@ static PyObject * * #func = (PyLong_FromLongLong, PyLong_FromUnsignedLongLong)*5, * PyLong_FromDouble*7, PyFloat_FromDouble*17# */ -static PyObject * +static NPY_INLINE PyObject * @name@_@which@(PyObject *obj) { #if @cmplx@ diff --git a/numpy/core/src/umath/simd.inc.src b/numpy/core/src/umath/simd.inc.src index 5b111eb0d..77cc54711 100644 --- a/numpy/core/src/umath/simd.inc.src +++ b/numpy/core/src/umath/simd.inc.src @@ -27,6 +27,22 @@ #include <stdlib.h> #include <string.h> /* for memcpy */ +/* Figure out the right abs function for pointer addresses */ +static NPY_INLINE npy_intp +abs_intp(npy_intp x) +{ +#if (NPY_SIZEOF_INTP <= NPY_SIZEOF_INT) + return abs(x); +#elif (NPY_SIZEOF_INTP <= NPY_SIZEOF_LONG) + return labs(x); +#elif defined(_MSC_VER) && (_MSC_VER < 1600) + /* llabs is not available with Visual Studio 2008 */ + return x > 0 ? x : -x; +#else + return llabs(x); +#endif +} + /* * stride is equal to element size and input and destination are equal or * don't overlap within one register @@ -34,10 +50,11 @@ #define IS_BLOCKABLE_UNARY(esize, vsize) \ (steps[0] == (esize) && steps[0] == steps[1] && \ (npy_is_aligned(args[0], esize) && npy_is_aligned(args[1], esize)) && \ - ((abs(args[1] - args[0]) >= (vsize)) || ((abs(args[1] - args[0]) == 0)))) + ((abs_intp(args[1] - args[0]) >= (vsize)) || \ + ((abs_intp(args[1] - args[0]) == 0)))) #define IS_BLOCKABLE_REDUCE(esize, vsize) \ - (steps[1] == (esize) && abs(args[1] - args[0]) >= (vsize) && \ + (steps[1] == (esize) && abs_intp(args[1] - args[0]) >= (vsize) && \ npy_is_aligned(args[1], (esize)) && \ npy_is_aligned(args[0], (esize))) @@ -45,20 +62,26 @@ (steps[0] == steps[1] && steps[1] == steps[2] && steps[2] == (esize) && \ npy_is_aligned(args[2], (esize)) && npy_is_aligned(args[1], (esize)) && \ npy_is_aligned(args[0], (esize)) && \ - (abs(args[2] - args[0]) >= (vsize) || abs(args[2] - args[0]) == 0) && \ - (abs(args[2] - args[1]) >= (vsize) || abs(args[2] - args[1]) >= 0)) + (abs_intp(args[2] - args[0]) >= (vsize) || \ + abs_intp(args[2] - args[0]) == 0) && \ + (abs_intp(args[2] - args[1]) >= (vsize) || \ + abs_intp(args[2] - args[1]) >= 0)) #define IS_BLOCKABLE_BINARY_SCALAR1(esize, vsize) \ (steps[0] == 0 && steps[1] == steps[2] && steps[2] == (esize) && \ npy_is_aligned(args[2], (esize)) && npy_is_aligned(args[1], (esize)) && \ - ((abs(args[2] - args[1]) >= (vsize)) || (abs(args[2] - args[1]) == 0)) && \ - abs(args[2] - args[0]) >= (esize)) + ((abs_intp(args[2] - args[1]) >= (vsize)) || \ + (abs_intp(args[2] - args[1]) == 0)) && \ + abs_intp(args[2] - args[0]) >= (esize)) #define IS_BLOCKABLE_BINARY_SCALAR2(esize, vsize) \ (steps[1] == 0 && steps[0] == steps[2] && steps[2] == (esize) && \ npy_is_aligned(args[2], (esize)) && npy_is_aligned(args[0], (esize)) && \ - ((abs(args[2] - args[0]) >= (vsize)) || (abs(args[2] - args[0]) == 0)) && \ - abs(args[2] - args[1]) >= (esize)) + ((abs_intp(args[2] - args[0]) >= (vsize)) || \ + (abs_intp(args[2] - args[0]) == 0)) && \ + abs_intp(args[2] - args[1]) >= (esize)) + +#undef abs_intp #define IS_BLOCKABLE_BINARY_BOOL(esize, vsize) \ (steps[0] == (esize) && steps[0] == steps[1] && steps[2] == (1) && \ @@ -520,8 +543,7 @@ sse2_ordered_cmp_@kind@_@TYPE@(const @type@ a, const @type@ b) @vtype@ v = @vpre@_@VOP@_@vsufs@(@vpre@_load_@vsufs@(&a), @vpre@_load_@vsufs@(&b)); @vpre@_store_@vsufs@(&tmp, v); - return sizeof(@type@) == 4 ? - (*(npy_uint32 *)&tmp) & 1 : (*(npy_uint64 *)&tmp) & 1; + return !(tmp == 0.); } static void diff --git a/numpy/core/src/umath/test_rational.c.src b/numpy/core/src/umath/test_rational.c.src index 5c4f29f73..b0c06e1ac 100644 --- a/numpy/core/src/umath/test_rational.c.src +++ b/numpy/core/src/umath/test_rational.c.src @@ -543,7 +543,7 @@ pyrational_str(PyObject* self) { } } -static long +static npy_hash_t pyrational_hash(PyObject* self) { rational x = ((PyRational*)self)->r; /* Use a fairly weak hash as Python expects */ diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index 36201b3ea..779773101 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -105,7 +105,17 @@ _error_handler(int method, PyObject *errobj, char *errtype, int retstatus, int * PyObject *pyfunc, *ret, *args; char *name = PyBytes_AS_STRING(PyTuple_GET_ITEM(errobj,0)); char msg[100]; - NPY_ALLOW_C_API_DEF; + + NPY_ALLOW_C_API_DEF + + /* don't need C API for a simple print */ + if (method == UFUNC_ERR_PRINT) { + if (*first) { + fprintf(stderr, "Warning: %s encountered in %s\n", errtype, name); + *first = 0; + } + return 0; + } NPY_ALLOW_C_API; switch(method) { @@ -140,12 +150,6 @@ _error_handler(int method, PyObject *errobj, char *errtype, int retstatus, int * } Py_DECREF(ret); break; - case UFUNC_ERR_PRINT: - if (*first) { - fprintf(stderr, "Warning: %s encountered in %s\n", errtype, name); - *first = 0; - } - break; case UFUNC_ERR_LOG: if (first) { *first = 0; @@ -523,38 +527,6 @@ PyUFunc_GetPyValues(char *name, int *bufsize, int *errmask, PyObject **errobj) return _extract_pyvals(ref, name, bufsize, errmask, errobj); } -#define GETATTR(str, rstr) do {if (strcmp(name, #str) == 0) \ - return PyObject_HasAttrString(op, "__" #rstr "__");} while (0); - -static int -_has_reflected_op(PyObject *op, const char *name) -{ - GETATTR(add, radd); - GETATTR(subtract, rsub); - GETATTR(multiply, rmul); - GETATTR(divide, rdiv); - GETATTR(true_divide, rtruediv); - GETATTR(floor_divide, rfloordiv); - GETATTR(remainder, rmod); - GETATTR(power, rpow); - GETATTR(left_shift, rlshift); - GETATTR(right_shift, rrshift); - GETATTR(bitwise_and, rand); - GETATTR(bitwise_xor, rxor); - GETATTR(bitwise_or, ror); - /* Comparisons */ - GETATTR(equal, eq); - GETATTR(not_equal, ne); - GETATTR(greater, lt); - GETATTR(less, gt); - GETATTR(greater_equal, le); - GETATTR(less_equal, ge); - return 0; -} - -#undef GETATTR - - /* Return the position of next non-white-space char in the string */ static int _next_non_white_space(const char* str, int offset) @@ -896,16 +868,122 @@ get_ufunc_arguments(PyUFuncObject *ufunc, } } - /* - * Indicate not implemented if there are flexible objects (structured - * type or string) but no object types and no registered struct - * dtype ufuncs. - * - * Not sure - adding this increased to 246 errors, 150 failures. - */ if (any_flexible && !any_flexible_userloops && !any_object) { - return -2; - + /* Traditionally, we return -2 here (meaning "NotImplemented") anytime + * we hit the above condition. + * + * This condition basically means "we are doomed", b/c the "flexible" + * dtypes -- strings and void -- cannot have their own ufunc loops + * registered (except via the special "flexible userloops" mechanism), + * and they can't be cast to anything except object (and we only cast + * to object if any_object is true). So really we should do nothing + * here and continue and let the proper error be raised. But, we can't + * quite yet, b/c of backcompat. + * + * Most of the time, this NotImplemented either got returned directly + * to the user (who can't do anything useful with it), or got passed + * back out of a special function like __mul__. And fortunately, for + * almost all special functions, the end result of this was a + * TypeError. Which is also what we get if we just continue without + * this special case, so this special case is unnecessary. + * + * The only thing that actually depended on the NotImplemented is + * array_richcompare, which did two things with it. First, it needed + * to see this NotImplemented in order to implement the special-case + * comparisons for + * + * string < <= == != >= > string + * void == != void + * + * Now it checks for those cases first, before trying to call the + * ufunc, so that's no problem. What it doesn't handle, though, is + * cases like + * + * float < string + * + * or + * + * float == void + * + * For those, it just let the NotImplemented bubble out, and accepted + * Python's default handling. And unfortunately, for comparisons, + * Python's default is *not* to raise an error. Instead, it returns + * something that depends on the operator: + * + * == return False + * != return True + * < <= >= > Python 2: use "fallback" (= weird and broken) ordering + * Python 3: raise TypeError (hallelujah) + * + * In most cases this is straightforwardly broken, because comparison + * of two arrays should always return an array, and here we end up + * returning a scalar. However, there is an exception: if we are + * comparing two scalars for equality, then it actually is correct to + * return a scalar bool instead of raising an error. If we just + * removed this special check entirely, then "np.float64(1) == 'foo'" + * would raise an error instead of returning False, which is genuinely + * wrong. + * + * The proper end goal here is: + * 1) == and != should be implemented in a proper vectorized way for + * all types. The short-term hack for this is just to add a + * special case to PyUFunc_DefaultLegacyInnerLoopSelector where + * if it can't find a comparison loop for the given types, and + * the ufunc is np.equal or np.not_equal, then it returns a loop + * that just fills the output array with False (resp. True). Then + * array_richcompare could trust that whenever its special cases + * don't apply, simply calling the ufunc will do the right thing, + * even without this special check. + * 2) < <= >= > should raise an error if no comparison function can + * be found. array_richcompare already handles all string <> + * string cases, and void dtypes don't have ordering, so again + * this would mean that array_richcompare could simply call the + * ufunc and it would do the right thing (i.e., raise an error), + * again without needing this special check. + * + * So this means that for the transition period, our goal is: + * == and != on scalars should simply return NotImplemented like + * they always did, since everything ends up working out correctly + * in this case only + * == and != on arrays should issue a FutureWarning and then return + * NotImplemented + * < <= >= > on all flexible dtypes on py2 should raise a + * DeprecationWarning, and then return NotImplemented. On py3 we + * skip the warning, though, b/c it would just be immediately be + * followed by an exception anyway. + * + * And for all other operations, we let things continue as normal. + */ + /* strcmp() is a hack but I think we can get away with it for this + * temporary measure. + */ + if (!strcmp(ufunc_name, "equal") || + !strcmp(ufunc_name, "not_equal")) { + /* Warn on non-scalar, return NotImplemented regardless */ + assert(nin == 2); + if (PyArray_NDIM(out_op[0]) != 0 || + PyArray_NDIM(out_op[1]) != 0) { + if (DEPRECATE_FUTUREWARNING( + "elementwise comparison failed; returning scalar " + "instead, but in the future will perform elementwise " + "comparison") < 0) { + return -1; + } + } + return -2; + } + else if (!strcmp(ufunc_name, "less") || + !strcmp(ufunc_name, "less_equal") || + !strcmp(ufunc_name, "greater") || + !strcmp(ufunc_name, "greater_equal")) { +#if !defined(NPY_PY3K) + if (DEPRECATE("unorderable dtypes; returning scalar but in " + "the future this will be an error") < 0) { + return -1; + } +#endif + return -2; + } } /* Get positional output arguments */ @@ -2142,26 +2220,6 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc, goto fail; } - /* - * FAIL with NotImplemented if the other object has - * the __r<op>__ method and has a higher priority than - * the current op (signalling it can handle ndarray's). - */ - if (nin == 2 && nout == 1 && dtypes[1]->type_num == NPY_OBJECT) { - PyObject *_obj = PyTuple_GET_ITEM(args, 1); - if (!PyArray_CheckExact(_obj)) { - double self_prio, other_prio; - self_prio = PyArray_GetPriority(PyTuple_GET_ITEM(args, 0), - NPY_SCALAR_PRIORITY); - other_prio = PyArray_GetPriority(_obj, NPY_SCALAR_PRIORITY); - if (self_prio < other_prio && - _has_reflected_op(_obj, ufunc_name)) { - retval = -2; - goto fail; - } - } - } - #if NPY_UF_DBG_TRACING printf("input types:\n"); for (i = 0; i < nin; ++i) { @@ -2521,27 +2579,6 @@ PyUFunc_GenericFunction(PyUFuncObject *ufunc, } } - /* - * FAIL with NotImplemented if the other object has - * the __r<op>__ method and has __array_priority__ as - * an attribute (signalling it can handle ndarray's) - * and is not already an ndarray or a subtype of the same type. - */ - if (nin == 2 && nout == 1 && dtypes[1]->type_num == NPY_OBJECT) { - PyObject *_obj = PyTuple_GET_ITEM(args, 1); - if (!PyArray_Check(_obj)) { - double self_prio, other_prio; - self_prio = PyArray_GetPriority(PyTuple_GET_ITEM(args, 0), - NPY_SCALAR_PRIORITY); - other_prio = PyArray_GetPriority(_obj, NPY_SCALAR_PRIORITY); - if (self_prio < other_prio && - _has_reflected_op(_obj, ufunc_name)) { - retval = -2; - goto fail; - } - } - } - #if NPY_UF_DBG_TRACING printf("input types:\n"); for (i = 0; i < nin; ++i) { @@ -4222,13 +4259,16 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds) return NULL; } else if (ufunc->nin == 2 && ufunc->nout == 1) { - /* To allow the other argument to be given a chance */ + /* + * For array_richcompare's benefit -- see the long comment in + * get_ufunc_arguments. + */ Py_INCREF(Py_NotImplemented); return Py_NotImplemented; } else { PyErr_SetString(PyExc_TypeError, - "Not implemented for this type"); + "XX can't happen, please report a bug XX"); return NULL; } } @@ -4401,8 +4441,7 @@ ufunc_seterr(PyObject *NPY_UNUSED(dummy), PyObject *args) return NULL; } #endif - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } @@ -5547,7 +5586,7 @@ ufunc_get_identity(PyUFuncObject *ufunc) case PyUFunc_Zero: return PyInt_FromLong(0); } - return Py_None; + Py_RETURN_NONE; } static PyObject * diff --git a/numpy/core/src/umath/ufunc_type_resolution.c b/numpy/core/src/umath/ufunc_type_resolution.c index fe2e8cac3..6f4f4123d 100644 --- a/numpy/core/src/umath/ufunc_type_resolution.c +++ b/numpy/core/src/umath/ufunc_type_resolution.c @@ -384,9 +384,10 @@ PyUFunc_NegativeTypeResolver(PyUFuncObject *ufunc, /* The type resolver would have upcast already */ if (out_dtypes[0]->type_num == NPY_BOOL) { - if (DEPRECATE("numpy boolean negative (the unary `-` operator) is " - "deprecated, use the bitwise_xor (the `^` operator) " - "or the logical_xor function instead.") < 0) { + /* 2013-12-05, 1.9 */ + if (DEPRECATE("numpy boolean negative, the `-` operator, is " + "deprecated, use the `~` operator or the logical_not " + "function instead.") < 0) { return -1; } } @@ -799,8 +800,9 @@ PyUFunc_SubtractionTypeResolver(PyUFuncObject *ufunc, /* The type resolver would have upcast already */ if (out_dtypes[0]->type_num == NPY_BOOL) { - if (DEPRECATE("numpy boolean subtract (the binary `-` operator) is " - "deprecated, use the bitwise_xor (the `^` operator) " + /* 2013-12-05, 1.9 */ + if (DEPRECATE("numpy boolean subtract, the `-` operator, is " + "deprecated, use the bitwise_xor, the `^` operator, " "or the logical_xor function instead.") < 0) { return -1; } @@ -2106,7 +2108,6 @@ type_tuple_type_resolver(PyUFuncObject *self, for (i = 0; i < self->ntypes; ++i) { char *orig_types = self->types + i*self->nargs; - int matched = 1; /* Copy the types into an int array for matching */ for (j = 0; j < nop; ++j) { @@ -2116,17 +2117,17 @@ type_tuple_type_resolver(PyUFuncObject *self, if (n_specified == nop) { for (j = 0; j < nop; ++j) { if (types[j] != specified_types[j] && - specified_types[j] != NPY_NOTYPE) { - matched = 0; + specified_types[j] != NPY_NOTYPE) { break; } } - } else { - if (types[nin] != specified_types[0]) { - matched = 0; + if (j < nop) { + /* no match */ + continue; } } - if (!matched) { + else if (types[nin] != specified_types[0]) { + /* no match */ continue; } @@ -2136,29 +2137,23 @@ type_tuple_type_resolver(PyUFuncObject *self, types, NULL, &no_castable_output, &err_src_typecode, &err_dst_typecode)) { - /* Error */ case -1: + /* Error */ return -1; - /* It worked */ + case 0: + /* Cannot cast inputs */ + continue; case 1: + /* Success */ set_ufunc_loop_data_types(self, op, out_dtype, types, NULL); return 0; - /* Didn't work */ - case 0: - PyErr_Format(PyExc_TypeError, - "found a loop for ufunc '%s' " - "matching the type-tuple, " - "but the inputs and/or outputs could not be " - "cast according to the casting rule", - ufunc_name); - return -1; } } /* If no function was found, throw an error */ PyErr_Format(PyExc_TypeError, - "No loop matching the specified signature was found " - "for ufunc %s", ufunc_name); + "No loop matching the specified signature and casting\n" + "was found for ufunc %s", ufunc_name); return -1; } diff --git a/numpy/core/src/umath/umathmodule.c b/numpy/core/src/umath/umathmodule.c index 624588410..b1da2aeed 100644 --- a/numpy/core/src/umath/umathmodule.c +++ b/numpy/core/src/umath/umathmodule.c @@ -242,8 +242,7 @@ add_newdoc_ufunc(PyObject *NPY_UNUSED(dummy), PyObject *args) strcpy(newdocstr, docstr); ufunc->doc = newdocstr; - Py_INCREF(Py_None); - return Py_None; + Py_RETURN_NONE; } diff --git a/numpy/core/tests/test_api.py b/numpy/core/tests/test_api.py index ebb8e4b1b..876cab4d7 100644 --- a/numpy/core/tests/test_api.py +++ b/numpy/core/tests/test_api.py @@ -1,22 +1,23 @@ from __future__ import division, absolute_import, print_function import sys -import warnings import numpy as np -from numpy.testing import * from numpy.compat import sixu +from numpy.testing import ( + run_module_suite, assert_, assert_equal, assert_array_equal, + assert_raises +) # Switch between new behaviour when NPY_RELAXED_STRIDES_CHECKING is set. NPY_RELAXED_STRIDES_CHECKING = np.ones((10, 1), order='C').flags.f_contiguous def test_array_array(): - obj = object() tobj = type(object) ones11 = np.ones((1, 1), np.float64) tndarray = type(ones11) - # Test is_ndarary + # Test is_ndarray assert_equal(np.array(ones11, dtype=np.float64), ones11) old_refcount = sys.getrefcount(tndarray) np.array(ones11) diff --git a/numpy/core/tests/test_arrayprint.py b/numpy/core/tests/test_arrayprint.py index 44bf5f397..5759a0984 100644 --- a/numpy/core/tests/test_arrayprint.py +++ b/numpy/core/tests/test_arrayprint.py @@ -3,9 +3,12 @@ from __future__ import division, absolute_import, print_function import sys + import numpy as np -from numpy.testing import * from numpy.compat import sixu +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal +) class TestArrayRepr(object): def test_nan_inf(self): @@ -81,6 +84,7 @@ class TestArray2String(TestCase): return 'o' else: return 'O' + x = np.arange(3) if sys.version_info[0] >= 3: x_hex = "[0x0 0x1 0x2]" @@ -88,30 +92,31 @@ class TestArray2String(TestCase): else: x_hex = "[0x0L 0x1L 0x2L]" x_oct = "[0L 01L 02L]" - assert_(np.array2string(x, formatter={'all':_format_function}) == \ + assert_(np.array2string(x, formatter={'all':_format_function}) == "[. o O]") - assert_(np.array2string(x, formatter={'int_kind':_format_function}) ==\ + assert_(np.array2string(x, formatter={'int_kind':_format_function}) == "[. o O]") - assert_(np.array2string(x, formatter={'all':lambda x: "%.4f" % x}) == \ + assert_(np.array2string(x, formatter={'all':lambda x: "%.4f" % x}) == "[0.0000 1.0000 2.0000]") - assert_equal(np.array2string(x, formatter={'int':lambda x: hex(x)}), \ + assert_equal(np.array2string(x, formatter={'int':lambda x: hex(x)}), x_hex) - assert_equal(np.array2string(x, formatter={'int':lambda x: oct(x)}), \ + assert_equal(np.array2string(x, formatter={'int':lambda x: oct(x)}), x_oct) x = np.arange(3.) - assert_(np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x}) == \ + assert_(np.array2string(x, formatter={'float_kind':lambda x: "%.2f" % x}) == "[0.00 1.00 2.00]") - assert_(np.array2string(x, formatter={'float':lambda x: "%.2f" % x}) == \ + assert_(np.array2string(x, formatter={'float':lambda x: "%.2f" % x}) == "[0.00 1.00 2.00]") s = np.array(['abc', 'def']) - assert_(np.array2string(s, formatter={'numpystr':lambda s: s*2}) == \ - '[abcabc defdef]') + assert_(np.array2string(s, formatter={'numpystr':lambda s: s*2}) == + '[abcabc defdef]') class TestPrintOptions: """Test getting and setting global print options.""" + def setUp(self): self.oldopts = np.get_printoptions() @@ -162,6 +167,5 @@ def test_unicode_object_array(): assert_equal(repr(x), expected) - if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index 4e432f885..5fa281867 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -1,11 +1,16 @@ from __future__ import division, absolute_import, print_function -import os, pickle +import pickle +import warnings + import numpy import numpy as np -from numpy.testing import * -from numpy.compat import asbytes import datetime +from numpy.compat import asbytes +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_raises, + dec +) # Use pytz to test out various time zones if available try: @@ -20,7 +25,7 @@ class TestDateTime(TestCase): for unit in ['Y', 'M', 'W', 'D', 'h', 'm', 's', 'ms', 'us', 'ns', 'ps', 'fs', 'as']: - dt1 = np.dtype('M8[750%s]'%unit) + dt1 = np.dtype('M8[750%s]' % unit) assert_(dt1 == np.dtype('datetime64[750%s]' % unit)) dt2 = np.dtype('m8[%s]' % unit) assert_(dt2 == np.dtype('timedelta64[%s]' % unit)) @@ -50,11 +55,11 @@ class TestDateTime(TestCase): assert_raises(TypeError, np.dtype, 'm8[badunit]') assert_raises(TypeError, np.dtype, 'M8[YY]') assert_raises(TypeError, np.dtype, 'm8[YY]') - assert_warns(DeprecationWarning, np.dtype, 'm4') - assert_warns(DeprecationWarning, np.dtype, 'M7') - assert_warns(DeprecationWarning, np.dtype, 'm7') - assert_warns(DeprecationWarning, np.dtype, 'M16') - assert_warns(DeprecationWarning, np.dtype, 'm16') + assert_raises(TypeError, np.dtype, 'm4') + assert_raises(TypeError, np.dtype, 'M7') + assert_raises(TypeError, np.dtype, 'm7') + assert_raises(TypeError, np.dtype, 'M16') + assert_raises(TypeError, np.dtype, 'm16') def test_datetime_casting_rules(self): # Cannot cast safely/same_kind between timedelta and datetime @@ -522,7 +527,7 @@ class TestDateTime(TestCase): a = np.array(['2011-03-16T13:55Z', '1920-01-01T03:12Z'], dtype='M') assert_equal(np.array2string(a, separator=', ', - formatter={'datetime': lambda x : + formatter={'datetime': lambda x: "'%s'" % np.datetime_as_string(x, timezone='UTC')}), "['2011-03-16T13:55Z', '1920-01-01T03:12Z']") @@ -530,6 +535,17 @@ class TestDateTime(TestCase): a = np.array(['2010', 'NaT', '2030']).astype('M') assert_equal(str(a), "['2010' 'NaT' '2030']") + def test_timedelta_array_str(self): + a = np.array([-1, 0, 100], dtype='m') + assert_equal(str(a), "[ -1 0 100]") + a = np.array(['NaT', 'NaT'], dtype='m') + assert_equal(str(a), "['NaT' 'NaT']") + # Check right-alignment with NaTs + a = np.array([-1, 'NaT', 0], dtype='m') + assert_equal(str(a), "[ -1 'NaT' 0]") + a = np.array([-1, 'NaT', 1234567], dtype='m') + assert_equal(str(a), "[ -1 'NaT' 1234567]") + def test_pickle(self): # Check that pickle roundtripping works dt = np.dtype('M8[7D]') @@ -597,11 +613,11 @@ class TestDateTime(TestCase): def cast(): numpy.datetime64("1971-01-01 00:00:00.000000000000000").astype("<M8[D]") assert_raises(OverflowError, cast) + def cast2(): numpy.datetime64("2014").astype("<M8[fs]") assert_raises(OverflowError, cast2) - def test_pyobject_roundtrip(self): # All datetime types should be able to roundtrip through object a = np.array([0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -946,6 +962,21 @@ class TestDateTime(TestCase): # float * M8 assert_raises(TypeError, np.multiply, 1.5, dta) + # NaTs + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', category=RuntimeWarning) + nat = np.timedelta64('NaT') + def check(a, b, res): + assert_equal(a * b, res) + assert_equal(b * a, res) + for tp in (int, float): + check(nat, tp(2), nat) + check(nat, tp(0), nat) + for f in (float('inf'), float('nan')): + check(np.timedelta64(1), f, nat) + check(np.timedelta64(0), f, nat) + check(nat, f, nat) + def test_datetime_divide(self): for dta, tda, tdb, tdc, tdd in \ [ @@ -995,6 +1026,24 @@ class TestDateTime(TestCase): # float / M8 assert_raises(TypeError, np.divide, 1.5, dta) + # NaTs + with warnings.catch_warnings(): + warnings.filterwarnings('ignore', category=RuntimeWarning) + nat = np.timedelta64('NaT') + for tp in (int, float): + assert_equal(np.timedelta64(1) / tp(0), nat) + assert_equal(np.timedelta64(0) / tp(0), nat) + assert_equal(nat / tp(0), nat) + assert_equal(nat / tp(2), nat) + # Division by inf + assert_equal(np.timedelta64(1) / float('inf'), np.timedelta64(0)) + assert_equal(np.timedelta64(0) / float('inf'), np.timedelta64(0)) + assert_equal(nat / float('inf'), nat) + # Division by nan + assert_equal(np.timedelta64(1) / float('nan'), nat) + assert_equal(np.timedelta64(0) / float('nan'), nat) + assert_equal(nat / float('nan'), nat) + def test_datetime_compare(self): # Test all the comparison operators a = np.datetime64('2000-03-12T18:00:00.000000-0600') @@ -1069,7 +1118,7 @@ class TestDateTime(TestCase): def test_hours(self): t = np.ones(3, dtype='M8[s]') t[0] = 60*60*24 + 60*60*10 - assert_(t[0].item().hour == 10 ) + assert_(t[0].item().hour == 10) def test_divisor_conversion_year(self): assert_(np.dtype('M8[Y/4]') == np.dtype('M8[3M]')) @@ -1105,10 +1154,10 @@ class TestDateTime(TestCase): def test_divisor_conversion_fs(self): assert_(np.dtype('M8[fs/100]') == np.dtype('M8[10as]')) - self.assertRaises(ValueError, lambda : np.dtype('M8[3fs/10000]')) + self.assertRaises(ValueError, lambda: np.dtype('M8[3fs/10000]')) def test_divisor_conversion_as(self): - self.assertRaises(ValueError, lambda : np.dtype('M8[as/10]')) + self.assertRaises(ValueError, lambda: np.dtype('M8[as/10]')) def test_string_parser_variants(self): # Allow space instead of 'T' between date and time @@ -1130,7 +1179,6 @@ class TestDateTime(TestCase): assert_equal(np.datetime64('1977-03-02T12:30-0230'), np.datetime64('1977-03-02T15:00Z')) - def test_string_parser_error_check(self): # Arbitrary bad string assert_raises(ValueError, np.array, ['badvalue'], np.dtype('M8[us]')) @@ -1209,7 +1257,6 @@ class TestDateTime(TestCase): assert_raises(ValueError, np.array, ['1980-02-03 01:01:00-25:00'], np.dtype('M8[us]')) - def test_creation_overflow(self): date = '1980-03-23 20:00:00Z' timesteps = np.array([date], dtype='datetime64[s]')[0].astype(np.int64) @@ -1301,39 +1348,31 @@ class TestDateTime(TestCase): # unit='auto' parameter assert_equal(np.datetime_as_string( - np.datetime64('2032-07-18T12:23:34.123456Z', 'us'), - unit='auto'), - '2032-07-18T12:23:34.123456Z') + np.datetime64('2032-07-18T12:23:34.123456Z', 'us'), unit='auto'), + '2032-07-18T12:23:34.123456Z') assert_equal(np.datetime_as_string( - np.datetime64('2032-07-18T12:23:34.12Z', 'us'), - unit='auto'), - '2032-07-18T12:23:34.120Z') + np.datetime64('2032-07-18T12:23:34.12Z', 'us'), unit='auto'), + '2032-07-18T12:23:34.120Z') assert_equal(np.datetime_as_string( - np.datetime64('2032-07-18T12:23:34Z', 'us'), - unit='auto'), - '2032-07-18T12:23:34Z') + np.datetime64('2032-07-18T12:23:34Z', 'us'), unit='auto'), + '2032-07-18T12:23:34Z') assert_equal(np.datetime_as_string( - np.datetime64('2032-07-18T12:23:00Z', 'us'), - unit='auto'), - '2032-07-18T12:23Z') + np.datetime64('2032-07-18T12:23:00Z', 'us'), unit='auto'), + '2032-07-18T12:23Z') # 'auto' doesn't split up hour and minute assert_equal(np.datetime_as_string( - np.datetime64('2032-07-18T12:00:00Z', 'us'), - unit='auto'), - '2032-07-18T12:00Z') + np.datetime64('2032-07-18T12:00:00Z', 'us'), unit='auto'), + '2032-07-18T12:00Z') assert_equal(np.datetime_as_string( - np.datetime64('2032-07-18T00:00:00Z', 'us'), - unit='auto'), - '2032-07-18') + np.datetime64('2032-07-18T00:00:00Z', 'us'), unit='auto'), + '2032-07-18') # 'auto' doesn't split up the date assert_equal(np.datetime_as_string( - np.datetime64('2032-07-01T00:00:00Z', 'us'), - unit='auto'), - '2032-07-01') + np.datetime64('2032-07-01T00:00:00Z', 'us'), unit='auto'), + '2032-07-01') assert_equal(np.datetime_as_string( - np.datetime64('2032-01-01T00:00:00Z', 'us'), - unit='auto'), - '2032-01-01') + np.datetime64('2032-01-01T00:00:00Z', 'us'), unit='auto'), + '2032-01-01') @dec.skipif(not _has_pytz, "The pytz module is not available.") def test_datetime_as_string_timezone(self): @@ -1599,7 +1638,7 @@ class TestDateTime(TestCase): np.datetime64('2011-11-10')) # A bigger forward jump across more than one week/holiday - holidays=['2011-10-10', '2011-11-11', '2011-11-24', + holidays = ['2011-10-10', '2011-11-11', '2011-11-24', '2011-12-25', '2011-05-30', '2011-02-21', '2011-12-26', '2012-01-02'] bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays) @@ -1701,10 +1740,10 @@ class TestDateTime(TestCase): np.datetime64('2012-03-08')) def test_datetime_busday_holidays_count(self): - holidays=['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24', - '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17', - '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30', - '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10'] + holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24', + '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17', + '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30', + '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10'] bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays) # Validate against busday_offset broadcast against @@ -1737,11 +1776,11 @@ class TestDateTime(TestCase): assert_equal(np.busday_count('2011-04', '2011-03', weekmask='Mon'), -4) def test_datetime_is_busday(self): - holidays=['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24', - '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17', - '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30', - '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10', - 'NaT'] + holidays = ['2011-01-01', '2011-10-10', '2011-11-11', '2011-11-24', + '2011-12-25', '2011-05-30', '2011-02-21', '2011-01-17', + '2011-12-26', '2012-01-02', '2011-02-21', '2011-05-30', + '2011-07-01', '2011-07-04', '2011-09-05', '2011-10-10', + 'NaT'] bdd = np.busdaycalendar(weekmask='1111100', holidays=holidays) # Weekend/weekday tests diff --git a/numpy/core/tests/test_defchararray.py b/numpy/core/tests/test_defchararray.py index 2b45ba4bc..9ef316481 100644 --- a/numpy/core/tests/test_defchararray.py +++ b/numpy/core/tests/test_defchararray.py @@ -1,14 +1,15 @@ from __future__ import division, absolute_import, print_function -from numpy.testing import * -from numpy.core import * -import numpy as np import sys -from numpy.core.multiarray import _vec_string +import numpy as np +from numpy.core.multiarray import _vec_string from numpy.compat import asbytes, asbytes_nested, sixu +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_array_equal +) -kw_unicode_true = {'unicode': True} # make 2to3 work properly +kw_unicode_true = {'unicode': True} # make 2to3 work properly kw_unicode_false = {'unicode': False} class TestBasic(TestCase): @@ -58,8 +59,10 @@ class TestBasic(TestCase): assert_array_equal(B, A) assert_equal(B.dtype, A.dtype) assert_equal(B.shape, A.shape) + def fail(): - B = np.char.array(A, **kw_unicode_false) + np.char.array(A, **kw_unicode_false) + self.assertRaises(UnicodeEncodeError, fail) def test_unicode_upconvert(self): @@ -82,38 +85,52 @@ class TestBasic(TestCase): class TestVecString(TestCase): def test_non_existent_method(self): + def fail(): _vec_string('a', np.string_, 'bogus') + self.assertRaises(AttributeError, fail) def test_non_string_array(self): + def fail(): _vec_string(1, np.string_, 'strip') + self.assertRaises(TypeError, fail) def test_invalid_args_tuple(self): + def fail(): _vec_string(['a'], np.string_, 'strip', 1) + self.assertRaises(TypeError, fail) def test_invalid_type_descr(self): + def fail(): _vec_string(['a'], 'BOGUS', 'strip') + self.assertRaises(TypeError, fail) def test_invalid_function_args(self): + def fail(): _vec_string(['a'], np.string_, 'strip', (1,)) + self.assertRaises(TypeError, fail) def test_invalid_result_type(self): + def fail(): _vec_string(['a'], np.integer, 'strip') + self.assertRaises(TypeError, fail) def test_broadcast_error(self): + def fail(): _vec_string([['abc', 'def']], np.integer, 'find', (['a', 'd', 'j'],)) + self.assertRaises(ValueError, fail) @@ -125,12 +142,12 @@ class TestWhitespace(TestCase): ['789', 'xyz']]).view(np.chararray) def test1(self): - assert_(all(self.A == self.B)) - assert_(all(self.A >= self.B)) - assert_(all(self.A <= self.B)) - assert_(not any(self.A > self.B)) - assert_(not any(self.A < self.B)) - assert_(not any(self.A != self.B)) + assert_(np.all(self.A == self.B)) + assert_(np.all(self.A >= self.B)) + assert_(np.all(self.A <= self.B)) + assert_(not np.any(self.A > self.B)) + assert_(not np.any(self.A < self.B)) + assert_(not np.any(self.A != self.B)) class TestChar(TestCase): def setUp(self): @@ -210,8 +227,10 @@ class TestInformation(TestCase): assert_(issubclass(self.A.endswith('').dtype.type, np.bool_)) assert_array_equal(self.A.endswith(' '), [[1, 0], [0, 0], [1, 0]]) assert_array_equal(self.A.endswith('3', 0, 3), [[0, 0], [1, 0], [1, 0]]) + def fail(): self.A.endswith('3', 'fdjk') + self.assertRaises(TypeError, fail) def test_find(self): @@ -222,8 +241,10 @@ class TestInformation(TestCase): assert_array_equal(self.A.find(['1', 'P']), [[-1, -1], [0, -1], [0, 1]]) def test_index(self): + def fail(): self.A.index('a') + self.assertRaises(ValueError, fail) assert_(np.char.index('abcba', 'b') == 1) assert_(issubclass(np.char.index('abcba', 'b').dtype.type, np.integer)) @@ -264,8 +285,10 @@ class TestInformation(TestCase): assert_array_equal(self.A.rfind(['1', 'P']), [[-1, -1], [0, -1], [0, 2]]) def test_rindex(self): + def fail(): self.A.rindex('a') + self.assertRaises(ValueError, fail) assert_(np.char.rindex('abcba', 'b') == 3) assert_(issubclass(np.char.rindex('abcba', 'b').dtype.type, np.integer)) @@ -274,8 +297,10 @@ class TestInformation(TestCase): assert_(issubclass(self.A.startswith('').dtype.type, np.bool_)) assert_array_equal(self.A.startswith(' '), [[1, 0], [0, 0], [0, 0]]) assert_array_equal(self.A.startswith('1', 0, 3), [[0, 0], [1, 0], [1, 0]]) + def fail(): self.A.startswith('3', 'fdjk') + self.assertRaises(TypeError, fail) @@ -290,30 +315,32 @@ class TestMethods(TestCase): [sixu('123 \t 345 \0 '), sixu('UPPER')]]).view(np.chararray) def test_capitalize(self): + tgt = asbytes_nested([[' abc ', ''], + ['12345', 'Mixedcase'], + ['123 \t 345 \0 ', 'Upper']]) assert_(issubclass(self.A.capitalize().dtype.type, np.string_)) - assert_array_equal(self.A.capitalize(), asbytes_nested([ - [' abc ', ''], - ['12345', 'Mixedcase'], - ['123 \t 345 \0 ', 'Upper']])) + assert_array_equal(self.A.capitalize(), tgt) + + tgt = [[sixu(' \u03c3 '), ''], + ['12345', 'Mixedcase'], + ['123 \t 345 \0 ', 'Upper']] assert_(issubclass(self.B.capitalize().dtype.type, np.unicode_)) - assert_array_equal(self.B.capitalize(), [ - [sixu(' \u03c3 '), ''], - ['12345', 'Mixedcase'], - ['123 \t 345 \0 ', 'Upper']]) + assert_array_equal(self.B.capitalize(), tgt) def test_center(self): assert_(issubclass(self.A.center(10).dtype.type, np.string_)) - widths = np.array([[10, 20]]) C = self.A.center([10, 20]) assert_array_equal(np.char.str_len(C), [[10, 20], [10, 20], [12, 20]]) + C = self.A.center(20, asbytes('#')) assert_(np.all(C.startswith(asbytes('#')))) assert_(np.all(C.endswith(asbytes('#')))) + C = np.char.center(asbytes('FOO'), [[10, 20], [15, 8]]) + tgt = asbytes_nested([[' FOO ', ' FOO '], + [' FOO ', ' FOO ']]) assert_(issubclass(C.dtype.type, np.string_)) - assert_array_equal(C, asbytes_nested([ - [' FOO ', ' FOO '], - [' FOO ', ' FOO ']])) + assert_array_equal(C, tgt) def test_decode(self): if sys.version_info[0] >= 3: @@ -329,7 +356,7 @@ class TestMethods(TestCase): def test_expandtabs(self): T = self.A.expandtabs() - assert_(T[2][0] == asbytes('123 345')) + assert_(T[2, 0] == asbytes('123 345 \0')) def test_join(self): if sys.version_info[0] >= 3: @@ -344,154 +371,164 @@ class TestMethods(TestCase): assert_(issubclass(A.dtype.type, np.unicode_)) else: assert_(issubclass(A.dtype.type, np.string_)) - assert_array_equal(np.char.join([',', '#'], A0), - [ - [' ,a,b,c, ', ''], - ['1,2,3,4,5', 'M#i#x#e#d#C#a#s#e'], - ['1,2,3, ,\t, ,3,4,5, ,\x00, ', 'U#P#P#E#R']]) + tgt = np.array([[' ,a,b,c, ', ''], + ['1,2,3,4,5', 'M#i#x#e#d#C#a#s#e'], + ['1,2,3, ,\t, ,3,4,5, ,\x00, ', 'U#P#P#E#R']]) + assert_array_equal(np.char.join([',', '#'], A0), tgt) def test_ljust(self): assert_(issubclass(self.A.ljust(10).dtype.type, np.string_)) - widths = np.array([[10, 20]]) + C = self.A.ljust([10, 20]) assert_array_equal(np.char.str_len(C), [[10, 20], [10, 20], [12, 20]]) + C = self.A.ljust(20, asbytes('#')) assert_array_equal(C.startswith(asbytes('#')), [ [False, True], [False, False], [False, False]]) assert_(np.all(C.endswith(asbytes('#')))) + C = np.char.ljust(asbytes('FOO'), [[10, 20], [15, 8]]) + tgt = asbytes_nested([['FOO ', 'FOO '], + ['FOO ', 'FOO ']]) assert_(issubclass(C.dtype.type, np.string_)) - assert_array_equal(C, asbytes_nested([ - ['FOO ', 'FOO '], - ['FOO ', 'FOO ']])) + assert_array_equal(C, tgt) def test_lower(self): + tgt = asbytes_nested([[' abc ', ''], + ['12345', 'mixedcase'], + ['123 \t 345 \0 ', 'upper']]) assert_(issubclass(self.A.lower().dtype.type, np.string_)) - assert_array_equal(self.A.lower(), asbytes_nested([ - [' abc ', ''], - ['12345', 'mixedcase'], - ['123 \t 345 \0 ', 'upper']])) + assert_array_equal(self.A.lower(), tgt) + + tgt = [[sixu(' \u03c3 '), sixu('')], + [sixu('12345'), sixu('mixedcase')], + [sixu('123 \t 345 \0 '), sixu('upper')]] assert_(issubclass(self.B.lower().dtype.type, np.unicode_)) - assert_array_equal(self.B.lower(), [ - [sixu(' \u03c3 '), sixu('')], - [sixu('12345'), sixu('mixedcase')], - [sixu('123 \t 345 \0 '), sixu('upper')]]) + assert_array_equal(self.B.lower(), tgt) def test_lstrip(self): + tgt = asbytes_nested([['abc ', ''], + ['12345', 'MixedCase'], + ['123 \t 345 \0 ', 'UPPER']]) assert_(issubclass(self.A.lstrip().dtype.type, np.string_)) - assert_array_equal(self.A.lstrip(), asbytes_nested([ - ['abc ', ''], - ['12345', 'MixedCase'], - ['123 \t 345 \0 ', 'UPPER']])) - assert_array_equal(self.A.lstrip(asbytes_nested(['1', 'M'])), - asbytes_nested([ - [' abc', ''], - ['2345', 'ixedCase'], - ['23 \t 345 \x00', 'UPPER']])) + assert_array_equal(self.A.lstrip(), tgt) + + tgt = asbytes_nested([[' abc', ''], + ['2345', 'ixedCase'], + ['23 \t 345 \x00', 'UPPER']]) + assert_array_equal(self.A.lstrip(asbytes_nested(['1', 'M'])), tgt) + + tgt = [[sixu('\u03a3 '), ''], + ['12345', 'MixedCase'], + ['123 \t 345 \0 ', 'UPPER']] assert_(issubclass(self.B.lstrip().dtype.type, np.unicode_)) - assert_array_equal(self.B.lstrip(), [ - [sixu('\u03a3 '), ''], - ['12345', 'MixedCase'], - ['123 \t 345 \0 ', 'UPPER']]) + assert_array_equal(self.B.lstrip(), tgt) def test_partition(self): P = self.A.partition(asbytes_nested(['3', 'M'])) + tgt = asbytes_nested([[(' abc ', '', ''), ('', '', '')], + [('12', '3', '45'), ('', 'M', 'ixedCase')], + [('12', '3', ' \t 345 \0 '), ('UPPER', '', '')]]) assert_(issubclass(P.dtype.type, np.string_)) - assert_array_equal(P, asbytes_nested([ - [(' abc ', '', ''), ('', '', '')], - [('12', '3', '45'), ('', 'M', 'ixedCase')], - [('12', '3', ' \t 345 \0 '), ('UPPER', '', '')]])) + assert_array_equal(P, tgt) def test_replace(self): R = self.A.replace(asbytes_nested(['3', 'a']), asbytes_nested(['##########', '@'])) + tgt = asbytes_nested([[' abc ', ''], + ['12##########45', 'MixedC@se'], + ['12########## \t ##########45 \x00', 'UPPER']]) assert_(issubclass(R.dtype.type, np.string_)) - assert_array_equal(R, asbytes_nested([ - [' abc ', ''], - ['12##########45', 'MixedC@se'], - ['12########## \t ##########45 \x00', 'UPPER']])) + assert_array_equal(R, tgt) if sys.version_info[0] < 3: # NOTE: b'abc'.replace(b'a', 'b') is not allowed on Py3 R = self.A.replace(asbytes('a'), sixu('\u03a3')) + tgt = [[sixu(' \u03a3bc '), ''], + ['12345', sixu('MixedC\u03a3se')], + ['123 \t 345 \x00', 'UPPER']] assert_(issubclass(R.dtype.type, np.unicode_)) - assert_array_equal(R, [ - [sixu(' \u03a3bc '), ''], - ['12345', sixu('MixedC\u03a3se')], - ['123 \t 345 \x00', 'UPPER']]) + assert_array_equal(R, tgt) def test_rjust(self): assert_(issubclass(self.A.rjust(10).dtype.type, np.string_)) - widths = np.array([[10, 20]]) + C = self.A.rjust([10, 20]) assert_array_equal(np.char.str_len(C), [[10, 20], [10, 20], [12, 20]]) + C = self.A.rjust(20, asbytes('#')) assert_(np.all(C.startswith(asbytes('#')))) assert_array_equal(C.endswith(asbytes('#')), [[False, True], [False, False], [False, False]]) + C = np.char.rjust(asbytes('FOO'), [[10, 20], [15, 8]]) + tgt = asbytes_nested([[' FOO', ' FOO'], + [' FOO', ' FOO']]) assert_(issubclass(C.dtype.type, np.string_)) - assert_array_equal(C, asbytes_nested([ - [' FOO', ' FOO'], - [' FOO', ' FOO']])) + assert_array_equal(C, tgt) def test_rpartition(self): P = self.A.rpartition(asbytes_nested(['3', 'M'])) + tgt = asbytes_nested([[('', '', ' abc '), ('', '', '')], + [('12', '3', '45'), ('', 'M', 'ixedCase')], + [('123 \t ', '3', '45 \0 '), ('', '', 'UPPER')]]) assert_(issubclass(P.dtype.type, np.string_)) - assert_array_equal(P, asbytes_nested([ - [('', '', ' abc '), ('', '', '')], - [('12', '3', '45'), ('', 'M', 'ixedCase')], - [('123 \t ', '3', '45 \0 '), ('', '', 'UPPER')]])) + assert_array_equal(P, tgt) def test_rsplit(self): A = self.A.rsplit(asbytes('3')) + tgt = asbytes_nested([[[' abc '], ['']], + [['12', '45'], ['MixedCase']], + [['12', ' \t ', '45 \x00 '], ['UPPER']]]) assert_(issubclass(A.dtype.type, np.object_)) - assert_equal(A.tolist(), asbytes_nested([ - [[' abc '], ['']], - [['12', '45'], ['MixedCase']], - [['12', ' \t ', '45 \x00 '], ['UPPER']]])) + assert_equal(A.tolist(), tgt) def test_rstrip(self): assert_(issubclass(self.A.rstrip().dtype.type, np.string_)) - assert_array_equal(self.A.rstrip(), asbytes_nested([ - [' abc', ''], - ['12345', 'MixedCase'], - ['123 \t 345', 'UPPER']])) - assert_array_equal(self.A.rstrip(asbytes_nested(['5', 'ER'])), - asbytes_nested([ - [' abc ', ''], - ['1234', 'MixedCase'], - ['123 \t 345 \x00', 'UPP']])) + + tgt = asbytes_nested([[' abc', ''], + ['12345', 'MixedCase'], + ['123 \t 345', 'UPPER']]) + assert_array_equal(self.A.rstrip(), tgt) + + tgt = asbytes_nested([[' abc ', ''], + ['1234', 'MixedCase'], + ['123 \t 345 \x00', 'UPP'] + ]) + assert_array_equal(self.A.rstrip(asbytes_nested(['5', 'ER'])), tgt) + + tgt = [[sixu(' \u03a3'), ''], + ['12345', 'MixedCase'], + ['123 \t 345', 'UPPER']] assert_(issubclass(self.B.rstrip().dtype.type, np.unicode_)) - assert_array_equal(self.B.rstrip(), [ - [sixu(' \u03a3'), ''], - ['12345', 'MixedCase'], - ['123 \t 345', 'UPPER']]) + assert_array_equal(self.B.rstrip(), tgt) def test_strip(self): + tgt = asbytes_nested([['abc', ''], + ['12345', 'MixedCase'], + ['123 \t 345', 'UPPER']]) assert_(issubclass(self.A.strip().dtype.type, np.string_)) - assert_array_equal(self.A.strip(), asbytes_nested([ - ['abc', ''], - ['12345', 'MixedCase'], - ['123 \t 345', 'UPPER']])) - assert_array_equal(self.A.strip(asbytes_nested(['15', 'EReM'])), - asbytes_nested([ - [' abc ', ''], - ['234', 'ixedCas'], - ['23 \t 345 \x00', 'UPP']])) + assert_array_equal(self.A.strip(), tgt) + + tgt = asbytes_nested([[' abc ', ''], + ['234', 'ixedCas'], + ['23 \t 345 \x00', 'UPP']]) + assert_array_equal(self.A.strip(asbytes_nested(['15', 'EReM'])), tgt) + + tgt = [[sixu('\u03a3'), ''], + ['12345', 'MixedCase'], + ['123 \t 345', 'UPPER']] assert_(issubclass(self.B.strip().dtype.type, np.unicode_)) - assert_array_equal(self.B.strip(), [ - [sixu('\u03a3'), ''], - ['12345', 'MixedCase'], - ['123 \t 345', 'UPPER']]) + assert_array_equal(self.B.strip(), tgt) def test_split(self): A = self.A.split(asbytes('3')) + tgt = asbytes_nested([ + [[' abc '], ['']], + [['12', '45'], ['MixedCase']], + [['12', ' \t ', '45 \x00 '], ['UPPER']]]) assert_(issubclass(A.dtype.type, np.object_)) - assert_equal(A.tolist(), asbytes_nested([ - [[' abc '], ['']], - [['12', '45'], ['MixedCase']], - [['12', ' \t ', '45 \x00 '], ['UPPER']]])) + assert_equal(A.tolist(), tgt) def test_splitlines(self): A = np.char.array(['abc\nfds\nwer']).splitlines() @@ -500,52 +537,59 @@ class TestMethods(TestCase): assert_(len(A[0]) == 3) def test_swapcase(self): + tgt = asbytes_nested([[' ABC ', ''], + ['12345', 'mIXEDcASE'], + ['123 \t 345 \0 ', 'upper']]) assert_(issubclass(self.A.swapcase().dtype.type, np.string_)) - assert_array_equal(self.A.swapcase(), asbytes_nested([ - [' ABC ', ''], - ['12345', 'mIXEDcASE'], - ['123 \t 345 \0 ', 'upper']])) + assert_array_equal(self.A.swapcase(), tgt) + + tgt = [[sixu(' \u03c3 '), sixu('')], + [sixu('12345'), sixu('mIXEDcASE')], + [sixu('123 \t 345 \0 '), sixu('upper')]] assert_(issubclass(self.B.swapcase().dtype.type, np.unicode_)) - assert_array_equal(self.B.swapcase(), [ - [sixu(' \u03c3 '), sixu('')], - [sixu('12345'), sixu('mIXEDcASE')], - [sixu('123 \t 345 \0 '), sixu('upper')]]) + assert_array_equal(self.B.swapcase(), tgt) def test_title(self): + tgt = asbytes_nested([[' Abc ', ''], + ['12345', 'Mixedcase'], + ['123 \t 345 \0 ', 'Upper']]) assert_(issubclass(self.A.title().dtype.type, np.string_)) - assert_array_equal(self.A.title(), asbytes_nested([ - [' Abc ', ''], - ['12345', 'Mixedcase'], - ['123 \t 345 \0 ', 'Upper']])) + assert_array_equal(self.A.title(), tgt) + + tgt = [[sixu(' \u03a3 '), sixu('')], + [sixu('12345'), sixu('Mixedcase')], + [sixu('123 \t 345 \0 '), sixu('Upper')]] assert_(issubclass(self.B.title().dtype.type, np.unicode_)) - assert_array_equal(self.B.title(), [ - [sixu(' \u03a3 '), sixu('')], - [sixu('12345'), sixu('Mixedcase')], - [sixu('123 \t 345 \0 '), sixu('Upper')]]) + assert_array_equal(self.B.title(), tgt) def test_upper(self): + tgt = asbytes_nested([[' ABC ', ''], + ['12345', 'MIXEDCASE'], + ['123 \t 345 \0 ', 'UPPER']]) assert_(issubclass(self.A.upper().dtype.type, np.string_)) - assert_array_equal(self.A.upper(), asbytes_nested([ - [' ABC ', ''], - ['12345', 'MIXEDCASE'], - ['123 \t 345 \0 ', 'UPPER']])) + assert_array_equal(self.A.upper(), tgt) + + tgt = [[sixu(' \u03a3 '), sixu('')], + [sixu('12345'), sixu('MIXEDCASE')], + [sixu('123 \t 345 \0 '), sixu('UPPER')]] assert_(issubclass(self.B.upper().dtype.type, np.unicode_)) - assert_array_equal(self.B.upper(), [ - [sixu(' \u03a3 '), sixu('')], - [sixu('12345'), sixu('MIXEDCASE')], - [sixu('123 \t 345 \0 '), sixu('UPPER')]]) + assert_array_equal(self.B.upper(), tgt) def test_isnumeric(self): + def fail(): self.A.isnumeric() + self.assertRaises(TypeError, fail) assert_(issubclass(self.B.isnumeric().dtype.type, np.bool_)) assert_array_equal(self.B.isnumeric(), [ [False, False], [True, False], [False, False]]) def test_isdecimal(self): + def fail(): self.A.isdecimal() + self.assertRaises(TypeError, fail) assert_(issubclass(self.B.isdecimal().dtype.type, np.bool_)) assert_array_equal(self.B.isdecimal(), [ @@ -626,9 +670,26 @@ class TestOperations(TestCase): except TypeError: pass else: - self.fail("chararray __rmod__ should fail with " \ + self.fail("chararray __rmod__ should fail with " "non-string objects") + def test_slice(self): + """Regression test for https://github.com/numpy/numpy/issues/5982""" + + arr = np.array([['abc ', 'def '], ['geh ', 'ijk ']], + dtype='S4').view(np.chararray) + sl1 = arr[:] + assert_array_equal(sl1, arr) + assert sl1.base is arr + assert sl1.base.base is arr.base + + sl2 = arr[:, :] + assert_array_equal(sl2, arr) + assert sl2.base is arr + assert sl2.base.base is arr.base + + assert arr[0, 0] == asbytes('abc') + def test_empty_indexing(): """Regression test for ticket 1948.""" diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index 9e2248205..3e76409c5 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -5,6 +5,7 @@ to document how deprecations should eventually be turned into errors. """ from __future__ import division, absolute_import, print_function +import sys import operator import warnings @@ -74,29 +75,33 @@ class _DeprecationTestCase(object): function(*args, **kwargs) except (Exception if function_fails else tuple()): pass + # just in case, clear the registry num_found = 0 for warning in self.log: if warning.category is DeprecationWarning: num_found += 1 elif not ignore_others: - raise AssertionError("expected DeprecationWarning but %s given" - % warning.category) + raise AssertionError( + "expected DeprecationWarning but got: %s" % + (warning.category,)) if num is not None and num_found != num: - raise AssertionError("%i warnings found but %i expected" - % (len(self.log), num)) + msg = "%i warnings found but %i expected." % (len(self.log), num) + lst = [w.category for w in self.log] + raise AssertionError("\n".join([msg] + [lst])) with warnings.catch_warnings(): warnings.filterwarnings("error", message=self.message, - category=DeprecationWarning) - + category=DeprecationWarning) try: function(*args, **kwargs) if exceptions != tuple(): - raise AssertionError("No error raised during function call") + raise AssertionError( + "No error raised during function call") except exceptions: if exceptions == tuple(): - raise AssertionError("Error raised during function call") + raise AssertionError( + "Error raised during function call") def assert_not_deprecated(self, function, args=(), kwargs={}): """Test if DeprecationWarnings are given and raised. @@ -110,245 +115,32 @@ class _DeprecationTestCase(object): exceptions=tuple(), args=args, kwargs=kwargs) -class TestFloatNonIntegerArgumentDeprecation(_DeprecationTestCase): - """ - These test that ``DeprecationWarning`` is given when you try to use - non-integers as arguments to for indexing and slicing e.g. ``a[0.0:5]`` - and ``a[0.5]``, or other functions like ``array.reshape(1., -1)``. - - After deprecation, changes need to be done inside conversion_utils.c - in PyArray_PyIntAsIntp and possibly PyArray_IntpConverter. - In iterators.c the function slice_GetIndices could be removed in favor - of its python equivalent and in mapping.c the function _tuple_of_integers - can be simplified (if ``np.array([1]).__index__()`` is also deprecated). - - As for the deprecation time-frame: via Ralf Gommers, - - "Hard to put that as a version number, since we don't know if the - version after 1.8 will be 6 months or 2 years after. I'd say 2 - years is reasonable." - - I interpret this to mean 2 years after the 1.8 release. Possibly - giving a PendingDeprecationWarning before that (which is visible - by default) +class TestBooleanUnaryMinusDeprecation(_DeprecationTestCase): + """Test deprecation of unary boolean `-`. While + and * are well + defined, unary - is not and even a corrected form seems to have + no real uses. + The deprecation process was started in NumPy 1.9. """ - message = "using a non-integer number instead of an integer " \ - "will result in an error in the future" - - def test_indexing(self): - a = np.array([[[5]]]) - - def assert_deprecated(*args, **kwargs): - self.assert_deprecated(*args, exceptions=(IndexError,), **kwargs) - - assert_deprecated(lambda: a[0.0]) - assert_deprecated(lambda: a[0, 0.0]) - assert_deprecated(lambda: a[0.0, 0]) - assert_deprecated(lambda: a[0.0,:]) - assert_deprecated(lambda: a[:, 0.0]) - assert_deprecated(lambda: a[:, 0.0,:]) - assert_deprecated(lambda: a[0.0,:,:]) - assert_deprecated(lambda: a[0, 0, 0.0]) - assert_deprecated(lambda: a[0.0, 0, 0]) - assert_deprecated(lambda: a[0, 0.0, 0]) - assert_deprecated(lambda: a[-1.4]) - assert_deprecated(lambda: a[0, -1.4]) - assert_deprecated(lambda: a[-1.4, 0]) - assert_deprecated(lambda: a[-1.4,:]) - assert_deprecated(lambda: a[:, -1.4]) - assert_deprecated(lambda: a[:, -1.4,:]) - assert_deprecated(lambda: a[-1.4,:,:]) - assert_deprecated(lambda: a[0, 0, -1.4]) - assert_deprecated(lambda: a[-1.4, 0, 0]) - assert_deprecated(lambda: a[0, -1.4, 0]) - - # Test that the slice parameter deprecation warning doesn't mask - # the scalar index warning. - assert_deprecated(lambda: a[0.0:, 0.0], num=2) - assert_deprecated(lambda: a[0.0:, 0.0,:], num=2) - - def test_valid_indexing(self): - a = np.array([[[5]]]) - assert_not_deprecated = self.assert_not_deprecated - - assert_not_deprecated(lambda: a[np.array([0])]) - assert_not_deprecated(lambda: a[[0, 0]]) - assert_not_deprecated(lambda: a[:, [0, 0]]) - assert_not_deprecated(lambda: a[:, 0,:]) - assert_not_deprecated(lambda: a[:,:,:]) - - def test_slicing(self): - a = np.array([[5]]) - - def assert_deprecated(*args, **kwargs): - self.assert_deprecated(*args, exceptions=(IndexError,), **kwargs) - - # start as float. - assert_deprecated(lambda: a[0.0:]) - assert_deprecated(lambda: a[0:, 0.0:2]) - assert_deprecated(lambda: a[0.0::2, :0]) - assert_deprecated(lambda: a[0.0:1:2,:]) - assert_deprecated(lambda: a[:, 0.0:]) - # stop as float. - assert_deprecated(lambda: a[:0.0]) - assert_deprecated(lambda: a[:0, 1:2.0]) - assert_deprecated(lambda: a[:0.0:2, :0]) - assert_deprecated(lambda: a[:0.0,:]) - assert_deprecated(lambda: a[:, 0:4.0:2]) - # step as float. - assert_deprecated(lambda: a[::1.0]) - assert_deprecated(lambda: a[0:, :2:2.0]) - assert_deprecated(lambda: a[1::4.0, :0]) - assert_deprecated(lambda: a[::5.0,:]) - assert_deprecated(lambda: a[:, 0:4:2.0]) - # mixed. - assert_deprecated(lambda: a[1.0:2:2.0], num=2) - assert_deprecated(lambda: a[1.0::2.0], num=2) - assert_deprecated(lambda: a[0:, :2.0:2.0], num=2) - assert_deprecated(lambda: a[1.0:1:4.0, :0], num=2) - assert_deprecated(lambda: a[1.0:5.0:5.0,:], num=3) - assert_deprecated(lambda: a[:, 0.4:4.0:2.0], num=3) - # should still get the DeprecationWarning if step = 0. - assert_deprecated(lambda: a[::0.0], function_fails=True) - - def test_valid_slicing(self): - a = np.array([[[5]]]) - assert_not_deprecated = self.assert_not_deprecated - - assert_not_deprecated(lambda: a[::]) - assert_not_deprecated(lambda: a[0:]) - assert_not_deprecated(lambda: a[:2]) - assert_not_deprecated(lambda: a[0:2]) - assert_not_deprecated(lambda: a[::2]) - assert_not_deprecated(lambda: a[1::2]) - assert_not_deprecated(lambda: a[:2:2]) - assert_not_deprecated(lambda: a[1:2:2]) - - def test_non_integer_argument_deprecations(self): - a = np.array([[5]]) - - self.assert_deprecated(np.reshape, args=(a, (1., 1., -1)), num=2) - self.assert_deprecated(np.reshape, args=(a, (np.array(1.), -1))) - self.assert_deprecated(np.take, args=(a, [0], 1.)) - self.assert_deprecated(np.take, args=(a, [0], np.float64(1.))) - - def test_non_integer_sequence_multiplication(self): - # Numpy scalar sequence multiply should not work with non-integers - def mult(a, b): - return a * b - self.assert_deprecated(mult, args=([1], np.float_(3))) - self.assert_not_deprecated(mult, args=([1], np.int_(3))) - - def test_reduce_axis_float_index(self): - d = np.zeros((3,3,3)) - self.assert_deprecated(np.min, args=(d, 0.5)) - self.assert_deprecated(np.min, num=1, args=(d, (0.5, 1))) - self.assert_deprecated(np.min, num=1, args=(d, (1, 2.2))) - self.assert_deprecated(np.min, num=2, args=(d, (.2, 1.2))) - - -class TestBooleanArgumentDeprecation(_DeprecationTestCase): - """This tests that using a boolean as integer argument/indexing is - deprecated. - - This should be kept in sync with TestFloatNonIntegerArgumentDeprecation - and like it is handled in PyArray_PyIntAsIntp. - """ - message = "using a boolean instead of an integer " \ - "will result in an error in the future" - - def test_bool_as_int_argument(self): - a = np.array([[[1]]]) - - self.assert_deprecated(np.reshape, args=(a, (True, -1))) - self.assert_deprecated(np.reshape, args=(a, (np.bool_(True), -1))) - # Note that operator.index(np.array(True)) does not work, a boolean - # array is thus also deprecated, but not with the same message: - assert_raises(TypeError, operator.index, np.array(True)) - self.assert_deprecated(np.take, args=(a, [0], False)) - self.assert_deprecated(lambda: a[False:True:True], exceptions=IndexError, num=3) - self.assert_deprecated(lambda: a[False, 0], exceptions=IndexError) - self.assert_deprecated(lambda: a[False, 0, 0], exceptions=IndexError) - - -class TestArrayToIndexDeprecation(_DeprecationTestCase): - """This tests that creating an an index from an array is deprecated - if the array is not 0d. - - This can probably be deprecated somewhat faster then the integer - deprecations. The deprecation period started with NumPy 1.8. - For deprecation this needs changing of array_index in number.c - """ - message = "converting an array with ndim \> 0 to an index will result " \ - "in an error in the future" - - def test_array_to_index_deprecation(self): - # This drops into the non-integer deprecation, which is ignored here, - # so no exception is expected. The raising is effectively tested above. - a = np.array([[[1]]]) - - self.assert_deprecated(operator.index, args=(np.array([1]),)) - self.assert_deprecated(np.reshape, args=(a, (a, -1)), exceptions=()) - self.assert_deprecated(np.take, args=(a, [0], a), exceptions=()) - # Check slicing. Normal indexing checks arrays specifically. - self.assert_deprecated(lambda: a[a:a:a], exceptions=(), num=3) - -class TestNonIntegerArrayLike(_DeprecationTestCase): - """Tests that array likes, i.e. lists give a deprecation warning - when they cannot be safely cast to an integer. - """ - message = "non integer \(and non boolean\) array-likes will not be " \ - "accepted as indices in the future" - - def test_basic(self): - a = np.arange(10) - self.assert_deprecated(a.__getitem__, args=([0.5, 1.5],), - exceptions=IndexError) - self.assert_deprecated(a.__getitem__, args=((['1', '2'],),), - exceptions=IndexError) - - self.assert_not_deprecated(a.__getitem__, ([],)) - - def test_boolean_futurewarning(self): - a = np.arange(10) - with warnings.catch_warnings(): - warnings.filterwarnings('always') - assert_warns(FutureWarning, a.__getitem__, [True]) - # Unfortunatly, the deprecation warning takes precedence: - #assert_warns(FutureWarning, a.__getitem__, True) - - with warnings.catch_warnings(): - warnings.filterwarnings('error') - assert_raises(FutureWarning, a.__getitem__, [True]) - #assert_raises(FutureWarning, a.__getitem__, True) + message = r"numpy boolean negative, the `-` operator, .*" + def test_unary_minus_operator_deprecation(self): + array = np.array([True]) + generic = np.bool_(True) -class TestMultipleEllipsisDeprecation(_DeprecationTestCase): - message = "an index can only have a single Ellipsis \(`...`\); replace " \ - "all but one with slices \(`:`\)." - - def test_basic(self): - a = np.arange(10) - self.assert_deprecated(a.__getitem__, args=((Ellipsis, Ellipsis),)) - - with warnings.catch_warnings(): - warnings.filterwarnings('ignore', '', DeprecationWarning) - # Just check that this works: - b = a[...,...] - assert_array_equal(a, b) - assert_raises(IndexError, a.__getitem__, ((Ellipsis, ) * 3,)) + # Unary minus/negative ufunc: + self.assert_deprecated(operator.neg, args=(array,)) + self.assert_deprecated(operator.neg, args=(generic,)) -class TestBooleanSubtractDeprecations(_DeprecationTestCase): - """Test deprecation of boolean `-`. While + and * are well - defined, - is not and even a corrected form seems to have +class TestBooleanBinaryMinusDeprecation(_DeprecationTestCase): + """Test deprecation of binary boolean `-`. While + and * are well + defined, binary - is not and even a corrected form seems to have no real uses. The deprecation process was started in NumPy 1.9. """ - message = r"numpy boolean .* \(the .* `-` operator\) is deprecated, " \ - "use the bitwise" + message = r"numpy boolean subtract, the `-` operator, .*" def test_operator_deprecation(self): array = np.array([True]) @@ -358,10 +150,6 @@ class TestBooleanSubtractDeprecations(_DeprecationTestCase): self.assert_deprecated(operator.sub, args=(array, array)) self.assert_deprecated(operator.sub, args=(generic, generic)) - # Unary minus/negative ufunc: - self.assert_deprecated(operator.neg, args=(array,)) - self.assert_deprecated(operator.neg, args=(generic,)) - class TestRankDeprecation(_DeprecationTestCase): """Test that np.rank is deprecated. The function should simply be @@ -382,8 +170,7 @@ class TestComparisonDeprecations(_DeprecationTestCase): Also test FutureWarning for the None comparison. """ - message = "elementwise comparison failed; " \ - "this will raise the error in the future." + message = "elementwise.* comparison failed; .*" def test_normal_types(self): for op in (operator.eq, operator.ne): @@ -424,6 +211,7 @@ class TestComparisonDeprecations(_DeprecationTestCase): def test_scalar_none_comparison(self): # Scalars should still just return false and not give a warnings. + # The comparisons are flagged by pep8, ignore that. with warnings.catch_warnings(record=True) as w: warnings.filterwarnings('always', '', FutureWarning) assert_(not np.float32(1) == None) @@ -442,6 +230,57 @@ class TestComparisonDeprecations(_DeprecationTestCase): # it has to be considered when the deprecations is done. assert_(np.equal(np.datetime64('NaT'), None)) + def test_void_dtype_equality_failures(self): + class NotArray(object): + def __array__(self): + raise TypeError + + # Needed so Python 3 does not raise DeprecationWarning twice. + def __ne__(self, other): + return NotImplemented + + self.assert_deprecated(lambda: np.arange(2) == NotArray()) + self.assert_deprecated(lambda: np.arange(2) != NotArray()) + + struct1 = np.zeros(2, dtype="i4,i4") + struct2 = np.zeros(2, dtype="i4,i4,i4") + + assert_warns(FutureWarning, lambda: struct1 == 1) + assert_warns(FutureWarning, lambda: struct1 == struct2) + assert_warns(FutureWarning, lambda: struct1 != 1) + assert_warns(FutureWarning, lambda: struct1 != struct2) + + def test_array_richcompare_legacy_weirdness(self): + # It doesn't really work to use assert_deprecated here, b/c part of + # the point of assert_deprecated is to check that when warnings are + # set to "error" mode then the error is propagated -- which is good! + # But here we are testing a bunch of code that is deprecated *because* + # it has the habit of swallowing up errors and converting them into + # different warnings. So assert_warns will have to be sufficient. + assert_warns(FutureWarning, lambda: np.arange(2) == "a") + assert_warns(FutureWarning, lambda: np.arange(2) != "a") + # No warning for scalar comparisons + with warnings.catch_warnings(): + warnings.filterwarnings("error") + assert_(not (np.array(0) == "a")) + assert_(np.array(0) != "a") + assert_(not (np.int16(0) == "a")) + assert_(np.int16(0) != "a") + + for arg1 in [np.asarray(0), np.int16(0)]: + struct = np.zeros(2, dtype="i4,i4") + for arg2 in [struct, "a"]: + for f in [operator.lt, operator.le, operator.gt, operator.ge]: + if sys.version_info[0] >= 3: + # py3 + with warnings.catch_warnings() as l: + warnings.filterwarnings("always") + assert_raises(TypeError, f, arg1, arg2) + assert not l + else: + # py2 + assert_warns(DeprecationWarning, f, arg1, arg2) + class TestIdentityComparisonDeprecations(_DeprecationTestCase): """This tests the equal and not_equal object ufuncs identity check @@ -508,5 +347,32 @@ class TestAlterdotRestoredotDeprecations(_DeprecationTestCase): self.assert_deprecated(np.restoredot) +class TestBooleanIndexShapeMismatchDeprecation(): + """Tests deprecation for boolean indexing where the boolean array + does not match the input array along the given diemsions. + """ + message = r"boolean index did not match indexed array" + + def test_simple(self): + arr = np.ones((5, 4, 3)) + index = np.array([True]) + #self.assert_deprecated(arr.__getitem__, args=(index,)) + assert_warns(np.VisibleDeprecationWarning, + arr.__getitem__, index) + + index = np.array([False] * 6) + #self.assert_deprecated(arr.__getitem__, args=(index,)) + assert_warns(np.VisibleDeprecationWarning, + arr.__getitem__, index) + + index = np.zeros((4, 4), dtype=bool) + #self.assert_deprecated(arr.__getitem__, args=(index,)) + assert_warns(np.VisibleDeprecationWarning, + arr.__getitem__, index) + #self.assert_deprecated(arr.__getitem__, args=((slice(None), index),)) + assert_warns(np.VisibleDeprecationWarning, + arr.__getitem__, (slice(None), index)) + + if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py index 852660432..496664622 100644 --- a/numpy/core/tests/test_dtype.py +++ b/numpy/core/tests/test_dtype.py @@ -1,9 +1,13 @@ from __future__ import division, absolute_import, print_function import sys + import numpy as np -from numpy.testing import * from numpy.core.test_rational import rational +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_raises, + dec +) def assert_dtype_equal(a, b): assert_equal(a, b) @@ -50,38 +54,35 @@ class TestBuiltin(TestCase): self.assertTrue(hash(left) == hash(right)) def test_invalid_types(self): - # Make sure invalid type strings raise a warning. - # For now, display a deprecation warning for invalid - # type sizes. In the future this should be changed - # to an exception. - - assert_warns(DeprecationWarning, np.dtype, 'O3') - assert_warns(DeprecationWarning, np.dtype, 'O5') - assert_warns(DeprecationWarning, np.dtype, 'O7') - assert_warns(DeprecationWarning, np.dtype, 'b3') - assert_warns(DeprecationWarning, np.dtype, 'h4') - assert_warns(DeprecationWarning, np.dtype, 'I5') - assert_warns(DeprecationWarning, np.dtype, 'e3') - assert_warns(DeprecationWarning, np.dtype, 'f5') + # Make sure invalid type strings raise an error + + assert_raises(TypeError, np.dtype, 'O3') + assert_raises(TypeError, np.dtype, 'O5') + assert_raises(TypeError, np.dtype, 'O7') + assert_raises(TypeError, np.dtype, 'b3') + assert_raises(TypeError, np.dtype, 'h4') + assert_raises(TypeError, np.dtype, 'I5') + assert_raises(TypeError, np.dtype, 'e3') + assert_raises(TypeError, np.dtype, 'f5') if np.dtype('g').itemsize == 8 or np.dtype('g').itemsize == 16: - assert_warns(DeprecationWarning, np.dtype, 'g12') + assert_raises(TypeError, np.dtype, 'g12') elif np.dtype('g').itemsize == 12: - assert_warns(DeprecationWarning, np.dtype, 'g16') + assert_raises(TypeError, np.dtype, 'g16') if np.dtype('l').itemsize == 8: - assert_warns(DeprecationWarning, np.dtype, 'l4') - assert_warns(DeprecationWarning, np.dtype, 'L4') + assert_raises(TypeError, np.dtype, 'l4') + assert_raises(TypeError, np.dtype, 'L4') else: - assert_warns(DeprecationWarning, np.dtype, 'l8') - assert_warns(DeprecationWarning, np.dtype, 'L8') + assert_raises(TypeError, np.dtype, 'l8') + assert_raises(TypeError, np.dtype, 'L8') if np.dtype('q').itemsize == 8: - assert_warns(DeprecationWarning, np.dtype, 'q4') - assert_warns(DeprecationWarning, np.dtype, 'Q4') + assert_raises(TypeError, np.dtype, 'q4') + assert_raises(TypeError, np.dtype, 'Q4') else: - assert_warns(DeprecationWarning, np.dtype, 'q8') - assert_warns(DeprecationWarning, np.dtype, 'Q8') + assert_raises(TypeError, np.dtype, 'q8') + assert_raises(TypeError, np.dtype, 'Q8') def test_bad_param(self): # Can't give a size that's too small @@ -248,6 +249,20 @@ class TestRecord(TestCase): ('f1', 'datetime64[Y]'), ('f2', 'i8')])) + def test_from_dictproxy(self): + # Tests for PR #5920 + dt = np.dtype({'names': ['a', 'b'], 'formats': ['i4', 'f4']}) + assert_dtype_equal(dt, np.dtype(dt.fields)) + dt2 = np.dtype((np.void, dt.fields)) + assert_equal(dt2.fields, dt.fields) + + def test_bool_commastring(self): + d = np.dtype('?,?,?') # raises? + assert_equal(len(d.names), 3) + for n in d.names: + assert_equal(d.fields[n][0], np.dtype('?')) + + class TestSubarray(TestCase): def test_single_subarray(self): a = np.dtype((np.int, (2))) @@ -319,13 +334,16 @@ class TestSubarray(TestCase): # List gets converted dt = np.dtype([('a', 'f4', l)]) assert_(isinstance(dt['a'].shape, tuple)) - # + # + class IntLike(object): def __index__(self): return 3 + def __int__(self): # (a PyNumber_Check fails without __int__) return 3 + dt = np.dtype([('a', 'f4', IntLike())]) assert_(isinstance(dt['a'].shape, tuple)) assert_(isinstance(dt['a'].shape[0], int)) @@ -356,6 +374,7 @@ class TestSubarray(TestCase): class TestMonsterType(TestCase): """Test deeply nested subtypes.""" + def test1(self): simple1 = np.dtype({'names': ['r', 'b'], 'formats': ['u1', 'u1'], 'titles': ['Red pixel', 'Blue pixel']}) @@ -505,12 +524,12 @@ class TestString(TestCase): @dec.skipif(sys.version_info[0] >= 3) def test_dtype_str_with_long_in_shape(self): - # Pull request #376 - dt = np.dtype('(1L,)i4') + # Pull request #376, should not error + np.dtype('(1L,)i4') def test_base_dtype_with_object_type(self): - # Issue gh-2798 - a = np.array(['a'], dtype="O").astype(("O", [("name", "O")])) + # Issue gh-2798, should not error. + np.array(['a'], dtype="O").astype(("O", [("name", "O")])) def test_empty_string_to_object(self): # Pull request #4722 @@ -527,7 +546,6 @@ class TestDtypeAttributeDeletion(object): for s in attr: assert_raises(AttributeError, delattr, dt, s) - def test_dtype_writable_attributes_deletion(self): dt = np.dtype(np.double) attr = ["names"] @@ -545,7 +563,8 @@ class TestDtypeAttributes(TestCase): def test_name_dtype_subclass(self): # Ticket #4357 - class user_def_subcls(np.void): pass + class user_def_subcls(np.void): + pass assert_equal(np.dtype(user_def_subcls).name, 'user_def_subcls') diff --git a/numpy/core/tests/test_einsum.py b/numpy/core/tests/test_einsum.py index e32a05df3..1f863a7db 100644 --- a/numpy/core/tests/test_einsum.py +++ b/numpy/core/tests/test_einsum.py @@ -1,11 +1,12 @@ from __future__ import division, absolute_import, print_function -import sys import warnings -from decimal import Decimal import numpy as np -from numpy.testing import * +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_array_equal, + assert_raises + ) class TestEinSum(TestCase): def test_einsum_errors(self): @@ -91,7 +92,7 @@ class TestEinSum(TestCase): b = np.einsum(a, [0, 1]) assert_(b.base is a) assert_equal(b, a) - + # output is writeable whenever input is writeable b = np.einsum("...", a) assert_(b.flags['WRITEABLE']) @@ -250,7 +251,7 @@ class TestEinSum(TestCase): assert_equal(np.einsum(a, [0, 0]), np.trace(a).astype(dtype)) # multiply(a, b) - assert_equal(np.einsum("..., ...", 3, 4), 12) # scalar case + assert_equal(np.einsum("..., ...", 3, 4), 12) # scalar case for n in range(1, 17): a = np.arange(3*n, dtype=dtype).reshape(3, n) b = np.arange(2*3*n, dtype=dtype).reshape(2, 3, n) @@ -358,14 +359,17 @@ class TestEinSum(TestCase): d = np.arange(18, dtype=dtype).reshape(3, 6) np.einsum("ij,jk,kl", a, b, c, out=d, - dtype='f8', casting='unsafe') - assert_equal(d, a.astype('f8').dot(b.astype('f8') - ).dot(c.astype('f8')).astype(dtype)) + dtype='f8', casting='unsafe') + tgt = a.astype('f8').dot(b.astype('f8')) + tgt = tgt.dot(c.astype('f8')).astype(dtype) + assert_equal(d, tgt) + d[...] = 0 np.einsum(a, [0, 1], b, [1, 2], c, [2, 3], out=d, - dtype='f8', casting='unsafe') - assert_equal(d, a.astype('f8').dot(b.astype('f8') - ).dot(c.astype('f8')).astype(dtype)) + dtype='f8', casting='unsafe') + tgt = a.astype('f8').dot(b.astype('f8')) + tgt = tgt.dot(c.astype('f8')).astype(dtype) + assert_equal(d, tgt) # tensordot(a, b) if np.dtype(dtype) != np.dtype('f2'): @@ -393,10 +397,10 @@ class TestEinSum(TestCase): c = np.array([True, True, False, True, True, False, True, True]) assert_equal(np.einsum("i,i,i->i", a, b, c, dtype='?', casting='unsafe'), - np.logical_and(np.logical_and(a!=0, b!=0), c!=0)) + np.logical_and(np.logical_and(a != 0, b != 0), c != 0)) assert_equal(np.einsum(a, [0], b, [0], c, [0], [0], dtype='?', casting='unsafe'), - np.logical_and(np.logical_and(a!=0, b!=0), c!=0)) + np.logical_and(np.logical_and(a != 0, b != 0), c != 0)) a = np.arange(9, dtype=dtype) assert_equal(np.einsum(",i->", 3, a), 3*np.sum(a)) @@ -442,49 +446,49 @@ class TestEinSum(TestCase): assert_equal(np.einsum('z,mz,zm->', p, q, r), 253) def test_einsum_sums_int8(self): - self.check_einsum_sums('i1'); + self.check_einsum_sums('i1') def test_einsum_sums_uint8(self): - self.check_einsum_sums('u1'); + self.check_einsum_sums('u1') def test_einsum_sums_int16(self): - self.check_einsum_sums('i2'); + self.check_einsum_sums('i2') def test_einsum_sums_uint16(self): - self.check_einsum_sums('u2'); + self.check_einsum_sums('u2') def test_einsum_sums_int32(self): - self.check_einsum_sums('i4'); + self.check_einsum_sums('i4') def test_einsum_sums_uint32(self): - self.check_einsum_sums('u4'); + self.check_einsum_sums('u4') def test_einsum_sums_int64(self): - self.check_einsum_sums('i8'); + self.check_einsum_sums('i8') def test_einsum_sums_uint64(self): - self.check_einsum_sums('u8'); + self.check_einsum_sums('u8') def test_einsum_sums_float16(self): - self.check_einsum_sums('f2'); + self.check_einsum_sums('f2') def test_einsum_sums_float32(self): - self.check_einsum_sums('f4'); + self.check_einsum_sums('f4') def test_einsum_sums_float64(self): - self.check_einsum_sums('f8'); + self.check_einsum_sums('f8') def test_einsum_sums_longdouble(self): - self.check_einsum_sums(np.longdouble); + self.check_einsum_sums(np.longdouble) def test_einsum_sums_cfloat64(self): - self.check_einsum_sums('c8'); + self.check_einsum_sums('c8') def test_einsum_sums_cfloat128(self): - self.check_einsum_sums('c16'); + self.check_einsum_sums('c16') def test_einsum_sums_clongdouble(self): - self.check_einsum_sums(np.clongdouble); + self.check_einsum_sums(np.clongdouble) def test_einsum_misc(self): # This call used to crash because of a bug in @@ -520,17 +524,17 @@ class TestEinSum(TestCase): ref = np.einsum('ijk,j->ijk',A, B) assert_equal(np.einsum('ij...,j...->ij...',A, B), ref) assert_equal(np.einsum('ij...,...j->ij...',A, B), ref) - assert_equal(np.einsum('ij...,j->ij...',A, B), ref) # used to raise error + assert_equal(np.einsum('ij...,j->ij...',A, B), ref) # used to raise error A = np.arange(12).reshape((4,3)) B = np.arange(6).reshape((3,2)) ref = np.einsum('ik,kj->ij', A, B) assert_equal(np.einsum('ik...,k...->i...', A, B), ref) assert_equal(np.einsum('ik...,...kj->i...j', A, B), ref) - assert_equal(np.einsum('...k,kj', A, B), ref) # used to raise error - assert_equal(np.einsum('ik,k...->i...', A, B), ref) # used to raise error + assert_equal(np.einsum('...k,kj', A, B), ref) # used to raise error + assert_equal(np.einsum('ik,k...->i...', A, B), ref) # used to raise error - dims=[2,3,4,5]; + dims = [2,3,4,5] a = np.arange(np.prod(dims)).reshape(dims) v = np.arange(dims[2]) ref = np.einsum('ijkl,k->ijl', a, v) @@ -539,9 +543,9 @@ class TestEinSum(TestCase): assert_equal(np.einsum('...kl,k...', a, v), ref) # no real diff from 1st - J,K,M=160,160,120; - A=np.arange(J*K*M).reshape(1,1,1,J,K,M) - B=np.arange(J*K*M*3).reshape(J,K,M,3) + J,K,M = 160,160,120 + A = np.arange(J*K*M).reshape(1,1,1,J,K,M) + B = np.arange(J*K*M*3).reshape(J,K,M,3) ref = np.einsum('...lmn,...lmno->...o', A, B) assert_equal(np.einsum('...lmn,lmno->...o', A, B), ref) # used to raise error @@ -571,7 +575,7 @@ class TestEinSum(TestCase): # made repeatable by changing random arrays to aranges. A = np.arange(3*3).reshape(3,3).astype(np.float64) B = np.arange(3*3*64*64).reshape(3,3,64,64).astype(np.float32) - es = np.einsum ('cl,cpxy->lpxy', A,B) + es = np.einsum('cl,cpxy->lpxy', A,B) tp = np.tensordot(A,B, axes=(0,0)) assert_equal(es, tp) @@ -585,6 +589,39 @@ class TestEinSum(TestCase): y2 = x[idx[:, None], idx[:, None], idx, idx] assert_equal(y1, y2) + def test_einsum_all_contig_non_contig_output(self): + # Issue gh-5907, tests that the all contiguous special case + # actually checks the contiguity of the output + x = np.ones((5, 5)) + out = np.ones(10)[::2] + correct_base = np.ones(10) + correct_base[::2] = 5 + # Always worked (inner iteration is done with 0-stride): + np.einsum('mi,mi,mi->m', x, x, x, out=out) + assert_array_equal(out.base, correct_base) + # Example 1: + out = np.ones(10)[::2] + np.einsum('im,im,im->m', x, x, x, out=out) + assert_array_equal(out.base, correct_base) + # Example 2, buffering causes x to be contiguous but + # special cases do not catch the operation before: + out = np.ones((2, 2, 2))[..., 0] + correct_base = np.ones((2, 2, 2)) + correct_base[..., 0] = 2 + x = np.ones((2, 2), np.float32) + np.einsum('ij,jk->ik', x, x, out=out) + assert_array_equal(out.base, correct_base) + + def test_small_boolean_arrays(self): + # See gh-5946. + # Use array of True embedded in False. + a = np.zeros((16, 1, 1), dtype=np.bool_)[:2] + a[...] = True + out = np.zeros((16, 1, 1), dtype=np.bool_)[:2] + tgt = np.ones((2,1,1), dtype=np.bool_) + res = np.einsum('...ij,...jk->...ik', a, a, out=out) + assert_equal(res, tgt) + if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_errstate.py b/numpy/core/tests/test_errstate.py index 7eb0aba2e..7fc749a7e 100644 --- a/numpy/core/tests/test_errstate.py +++ b/numpy/core/tests/test_errstate.py @@ -39,6 +39,7 @@ class TestErrstate(TestCase): def test_errcall(self): def foo(*args): print(args) + olderrcall = np.geterrcall() with np.errstate(call=foo): assert_(np.geterrcall() is foo, 'call is not foo') diff --git a/numpy/core/tests/test_extint128.py b/numpy/core/tests/test_extint128.py new file mode 100644 index 000000000..2afae2f6b --- /dev/null +++ b/numpy/core/tests/test_extint128.py @@ -0,0 +1,225 @@ +from __future__ import division, absolute_import, print_function + +import sys +import itertools +import contextlib +import operator + +import numpy as np +import numpy.core.multiarray_tests as mt +from numpy.compat import long + +from numpy.testing import assert_raises, assert_equal + + +INT64_MAX = np.iinfo(np.int64).max +INT64_MIN = np.iinfo(np.int64).min +INT64_MID = 2**32 + +# int128 is not two's complement, the sign bit is separate +INT128_MAX = 2**128 - 1 +INT128_MIN = -INT128_MAX +INT128_MID = 2**64 + +INT64_VALUES = ( + [INT64_MIN + j for j in range(20)] + + [INT64_MAX - j for j in range(20)] + + [INT64_MID + j for j in range(-20, 20)] + + [2*INT64_MID + j for j in range(-20, 20)] + + [INT64_MID//2 + j for j in range(-20, 20)] + + list(range(-70, 70)) +) + +INT128_VALUES = ( + [INT128_MIN + j for j in range(20)] + + [INT128_MAX - j for j in range(20)] + + [INT128_MID + j for j in range(-20, 20)] + + [2*INT128_MID + j for j in range(-20, 20)] + + [INT128_MID//2 + j for j in range(-20, 20)] + + list(range(-70, 70)) + + [False] # negative zero +) + +INT64_POS_VALUES = [x for x in INT64_VALUES if x > 0] + + +@contextlib.contextmanager +def exc_iter(*args): + """ + Iterate over Cartesian product of *args, and if an exception is raised, + add information of the current iterate. + """ + + value = [None] + + def iterate(): + for v in itertools.product(*args): + value[0] = v + yield v + + try: + yield iterate() + except: + import traceback + msg = "At: %r\n%s" % (repr(value[0]), + traceback.format_exc()) + raise AssertionError(msg) + + +def test_safe_binop(): + # Test checked arithmetic routines + + ops = [ + (operator.add, 1), + (operator.sub, 2), + (operator.mul, 3) + ] + + with exc_iter(ops, INT64_VALUES, INT64_VALUES) as it: + for xop, a, b in it: + pyop, op = xop + c = pyop(a, b) + + if not (INT64_MIN <= c <= INT64_MAX): + assert_raises(OverflowError, mt.extint_safe_binop, a, b, op) + else: + d = mt.extint_safe_binop(a, b, op) + if c != d: + # assert_equal is slow + assert_equal(d, c) + + +def test_to_128(): + with exc_iter(INT64_VALUES) as it: + for a, in it: + b = mt.extint_to_128(a) + if a != b: + assert_equal(b, a) + + +def test_to_64(): + with exc_iter(INT128_VALUES) as it: + for a, in it: + if not (INT64_MIN <= a <= INT64_MAX): + assert_raises(OverflowError, mt.extint_to_64, a) + else: + b = mt.extint_to_64(a) + if a != b: + assert_equal(b, a) + + +def test_mul_64_64(): + with exc_iter(INT64_VALUES, INT64_VALUES) as it: + for a, b in it: + c = a * b + d = mt.extint_mul_64_64(a, b) + if c != d: + assert_equal(d, c) + + +def test_add_128(): + with exc_iter(INT128_VALUES, INT128_VALUES) as it: + for a, b in it: + c = a + b + if not (INT128_MIN <= c <= INT128_MAX): + assert_raises(OverflowError, mt.extint_add_128, a, b) + else: + d = mt.extint_add_128(a, b) + if c != d: + assert_equal(d, c) + + +def test_sub_128(): + with exc_iter(INT128_VALUES, INT128_VALUES) as it: + for a, b in it: + c = a - b + if not (INT128_MIN <= c <= INT128_MAX): + assert_raises(OverflowError, mt.extint_sub_128, a, b) + else: + d = mt.extint_sub_128(a, b) + if c != d: + assert_equal(d, c) + + +def test_neg_128(): + with exc_iter(INT128_VALUES) as it: + for a, in it: + b = -a + c = mt.extint_neg_128(a) + if b != c: + assert_equal(c, b) + + +def test_shl_128(): + with exc_iter(INT128_VALUES) as it: + for a, in it: + if a < 0: + b = -(((-a) << 1) & (2**128-1)) + else: + b = (a << 1) & (2**128-1) + c = mt.extint_shl_128(a) + if b != c: + assert_equal(c, b) + + +def test_shr_128(): + with exc_iter(INT128_VALUES) as it: + for a, in it: + if a < 0: + b = -((-a) >> 1) + else: + b = a >> 1 + c = mt.extint_shr_128(a) + if b != c: + assert_equal(c, b) + + +def test_gt_128(): + with exc_iter(INT128_VALUES, INT128_VALUES) as it: + for a, b in it: + c = a > b + d = mt.extint_gt_128(a, b) + if c != d: + assert_equal(d, c) + + +def test_divmod_128_64(): + with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it: + for a, b in it: + if a >= 0: + c, cr = divmod(a, b) + else: + c, cr = divmod(-a, b) + c = -c + cr = -cr + + d, dr = mt.extint_divmod_128_64(a, b) + + if c != d or d != dr or b*d + dr != a: + assert_equal(d, c) + assert_equal(dr, cr) + assert_equal(b*d + dr, a) + + +def test_floordiv_128_64(): + with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it: + for a, b in it: + c = a // b + d = mt.extint_floordiv_128_64(a, b) + + if c != d: + assert_equal(d, c) + + +def test_ceildiv_128_64(): + with exc_iter(INT128_VALUES, INT64_POS_VALUES) as it: + for a, b in it: + c = (a + b - 1) // b + d = mt.extint_ceildiv_128_64(a, b) + + if c != d: + assert_equal(d, c) + + +if __name__ == "__main__": + run_module_suite() diff --git a/numpy/core/tests/test_function_base.py b/numpy/core/tests/test_function_base.py index a64d44473..2df7ba3ea 100644 --- a/numpy/core/tests/test_function_base.py +++ b/numpy/core/tests/test_function_base.py @@ -1,8 +1,12 @@ from __future__ import division, absolute_import, print_function -from numpy.testing import * from numpy import (logspace, linspace, dtype, array, finfo, typecodes, arange, isnan) +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_raises, + assert_array_equal +) + class TestLogspace(TestCase): @@ -34,6 +38,7 @@ class TestLinspace(TestCase): assert_(y[-1] == 10) y = linspace(2, 10, endpoint=0) assert_(y[-1] < 10) + assert_raises(ValueError, linspace, 0, 10, num=-1) def test_corner(self): y = list(linspace(0, 1, 1)) @@ -72,9 +77,9 @@ class TestLinspace(TestCase): def test_complex(self): lim1 = linspace(1 + 2j, 3 + 4j, 5) - t1 = array([ 1.0+2.j , 1.5+2.5j, 2.0+3.j , 2.5+3.5j, 3.0+4.j]) + t1 = array([ 1.0+2.j, 1.5+2.5j, 2.0+3.j, 2.5+3.5j, 3.0+4.j]) lim2 = linspace(1j, 10, 5) - t2 = array([ 0.0+1.j , 2.5+0.75j, 5.0+0.5j , 7.5+0.25j, 10.0+0.j]) + t2 = array([ 0.0+1.j, 2.5+0.75j, 5.0+0.5j, 7.5+0.25j, 10.0+0.j]) assert_equal(lim1, t1) assert_equal(lim2, t2) @@ -106,7 +111,6 @@ class TestLinspace(TestCase): def __rdiv__(self, x): return PhysicalQuantity(float(x) / float(self)) - a = PhysicalQuantity(0.0) b = PhysicalQuantity(1.0) assert_equal(linspace(a, b), linspace(0.0, 1.0)) diff --git a/numpy/core/tests/test_getlimits.py b/numpy/core/tests/test_getlimits.py index 6ccdbd5de..c36d7c068 100644 --- a/numpy/core/tests/test_getlimits.py +++ b/numpy/core/tests/test_getlimits.py @@ -3,11 +3,12 @@ """ from __future__ import division, absolute_import, print_function -from numpy.testing import * - +import numpy as np from numpy.core import finfo, iinfo from numpy import half, single, double, longdouble -import numpy as np +from numpy.testing import ( + TestCase, run_module_suite, assert_equal +) ################################################## @@ -65,17 +66,7 @@ class TestRepr(TestCase): def test_finfo_repr(self): expected = "finfo(resolution=1e-06, min=-3.4028235e+38," + \ " max=3.4028235e+38, dtype=float32)" - # Python 2.5 float formatting on Windows adds an extra 0 to the - # exponent. So test for both. Once 2.5 compatibility is dropped, this - # can simply use `assert_equal(repr(np.finfo(np.float32)), expected)`. - expected_win25 = "finfo(resolution=1e-006, min=-3.4028235e+038," + \ - " max=3.4028235e+038, dtype=float32)" - - actual = repr(np.finfo(np.float32)) - if not actual == expected: - if not actual == expected_win25: - msg = build_err_msg([actual, desired], verbose=True) - raise AssertionError(msg) + assert_equal(repr(np.finfo(np.float32)), expected) def test_instances(): diff --git a/numpy/core/tests/test_half.py b/numpy/core/tests/test_half.py index 928db48b7..56b574ae8 100644 --- a/numpy/core/tests/test_half.py +++ b/numpy/core/tests/test_half.py @@ -28,9 +28,8 @@ class TestHalf(TestCase): # An array of all non-NaN float16 values, in sorted order self.nonan_f16 = np.concatenate( - (np.arange(0xfc00, 0x7fff, -1, dtype=uint16), - np.arange(0x0000, 0x7c01, 1, dtype=uint16)) - ) + (np.arange(0xfc00, 0x7fff, -1, dtype=uint16), + np.arange(0x0000, 0x7c01, 1, dtype=uint16))) self.nonan_f16.dtype = float16 self.nonan_f32 = np.array(self.nonan_f16, dtype=float32) self.nonan_f64 = np.array(self.nonan_f16, dtype=float64) @@ -104,10 +103,10 @@ class TestHalf(TestCase): """Confirms a small number of known half values""" a = np.array([1.0, -1.0, 2.0, -2.0, - 0.0999755859375, 0.333251953125, # 1/10, 1/3 + 0.0999755859375, 0.333251953125, # 1/10, 1/3 65504, -65504, # Maximum magnitude - 2.0**(-14), -2.0**(-14), # Minimum normal - 2.0**(-24), -2.0**(-24), # Minimum subnormal + 2.0**(-14), -2.0**(-14), # Minimum normal + 2.0**(-24), -2.0**(-24), # Minimum subnormal 0, -1/1e1000, # Signed zeros np.inf, -np.inf]) b = np.array([0x3c00, 0xbc00, @@ -126,7 +125,7 @@ class TestHalf(TestCase): a = np.array([2.0**-25 + 2.0**-35, # Rounds to minimum subnormal 2.0**-25, # Underflows to zero (nearest even mode) 2.0**-26, # Underflows to zero - 1.0+2.0**-11 + 2.0**-16, # rounds to 1.0+2**(-10) + 1.0+2.0**-11 + 2.0**-16, # rounds to 1.0+2**(-10) 1.0+2.0**-11, # rounds to 1.0 (nearest even mode) 1.0+2.0**-12, # rounds to 1.0 65519, # rounds to 65504 @@ -155,17 +154,16 @@ class TestHalf(TestCase): a manual conversion.""" # Create an array of all finite float16s - a_f16 = self.finite_f16 - a_bits = a_f16.view(dtype=uint16) + a_bits = self.finite_f16.view(dtype=uint16) # Convert to 64-bit float manually - a_sgn = (-1.0)**((a_bits&0x8000) >> 15) - a_exp = np.array((a_bits&0x7c00) >> 10, dtype=np.int32) - 15 - a_man = (a_bits&0x03ff) * 2.0**(-10) + a_sgn = (-1.0)**((a_bits & 0x8000) >> 15) + a_exp = np.array((a_bits & 0x7c00) >> 10, dtype=np.int32) - 15 + a_man = (a_bits & 0x03ff) * 2.0**(-10) # Implicit bit of normalized floats - a_man[a_exp!=-15] += 1 + a_man[a_exp != -15] += 1 # Denormalized exponent is -14 - a_exp[a_exp==-15] = -14 + a_exp[a_exp == -15] = -14 a_manual = a_sgn * a_man * 2.0**a_exp @@ -174,7 +172,7 @@ class TestHalf(TestCase): bad_index = a32_fail[0] assert_equal(self.finite_f32, a_manual, "First non-equal is half value %x -> %g != %g" % - (a[bad_index], + (self.finite_f16[bad_index], self.finite_f32[bad_index], a_manual[bad_index])) @@ -183,7 +181,7 @@ class TestHalf(TestCase): bad_index = a64_fail[0] assert_equal(self.finite_f64, a_manual, "First non-equal is half value %x -> %g != %g" % - (a[bad_index], + (self.finite_f16[bad_index], self.finite_f64[bad_index], a_manual[bad_index])) @@ -272,7 +270,6 @@ class TestHalf(TestCase): assert_equal(np.nextafter(a_f16[1:], hinf), a_f16[:-1]) assert_equal(np.nextafter(a_f16[:-1], -hinf), a_f16[1:]) - def test_half_ufuncs(self): """Test the various ufuncs""" diff --git a/numpy/core/tests/test_indexerrors.py b/numpy/core/tests/test_indexerrors.py index e5dc9dbab..e6b6be361 100644 --- a/numpy/core/tests/test_indexerrors.py +++ b/numpy/core/tests/test_indexerrors.py @@ -1,8 +1,7 @@ from __future__ import division, absolute_import, print_function import numpy as np -from numpy.testing import TestCase, run_module_suite, assert_raises, assert_equal, assert_ -import sys +from numpy.testing import TestCase, run_module_suite, assert_raises class TestIndexErrors(TestCase): '''Tests to exercise indexerrors not covered by other tests.''' diff --git a/numpy/core/tests/test_indexing.py b/numpy/core/tests/test_indexing.py index 3beef71fb..38280d05e 100644 --- a/numpy/core/tests/test_indexing.py +++ b/numpy/core/tests/test_indexing.py @@ -3,11 +3,15 @@ from __future__ import division, absolute_import, print_function import sys import warnings import functools +import operator import numpy as np from numpy.core.multiarray_tests import array_indexing from itertools import product -from numpy.testing import * +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_raises, + assert_array_equal, assert_warns +) try: @@ -18,6 +22,69 @@ except ImportError: class TestIndexing(TestCase): + def test_index_no_floats(self): + a = np.array([[[5]]]) + + assert_raises(IndexError, lambda: a[0.0]) + assert_raises(IndexError, lambda: a[0, 0.0]) + assert_raises(IndexError, lambda: a[0.0, 0]) + assert_raises(IndexError, lambda: a[0.0,:]) + assert_raises(IndexError, lambda: a[:, 0.0]) + assert_raises(IndexError, lambda: a[:, 0.0,:]) + assert_raises(IndexError, lambda: a[0.0,:,:]) + assert_raises(IndexError, lambda: a[0, 0, 0.0]) + assert_raises(IndexError, lambda: a[0.0, 0, 0]) + assert_raises(IndexError, lambda: a[0, 0.0, 0]) + assert_raises(IndexError, lambda: a[-1.4]) + assert_raises(IndexError, lambda: a[0, -1.4]) + assert_raises(IndexError, lambda: a[-1.4, 0]) + assert_raises(IndexError, lambda: a[-1.4,:]) + assert_raises(IndexError, lambda: a[:, -1.4]) + assert_raises(IndexError, lambda: a[:, -1.4,:]) + assert_raises(IndexError, lambda: a[-1.4,:,:]) + assert_raises(IndexError, lambda: a[0, 0, -1.4]) + assert_raises(IndexError, lambda: a[-1.4, 0, 0]) + assert_raises(IndexError, lambda: a[0, -1.4, 0]) + assert_raises(IndexError, lambda: a[0.0:, 0.0]) + assert_raises(IndexError, lambda: a[0.0:, 0.0,:]) + + def test_slicing_no_floats(self): + a = np.array([[5]]) + + # start as float. + assert_raises(IndexError, lambda: a[0.0:]) + assert_raises(IndexError, lambda: a[0:, 0.0:2]) + assert_raises(IndexError, lambda: a[0.0::2, :0]) + assert_raises(IndexError, lambda: a[0.0:1:2,:]) + assert_raises(IndexError, lambda: a[:, 0.0:]) + # stop as float. + assert_raises(IndexError, lambda: a[:0.0]) + assert_raises(IndexError, lambda: a[:0, 1:2.0]) + assert_raises(IndexError, lambda: a[:0.0:2, :0]) + assert_raises(IndexError, lambda: a[:0.0,:]) + assert_raises(IndexError, lambda: a[:, 0:4.0:2]) + # step as float. + assert_raises(IndexError, lambda: a[::1.0]) + assert_raises(IndexError, lambda: a[0:, :2:2.0]) + assert_raises(IndexError, lambda: a[1::4.0, :0]) + assert_raises(IndexError, lambda: a[::5.0,:]) + assert_raises(IndexError, lambda: a[:, 0:4:2.0]) + # mixed. + assert_raises(IndexError, lambda: a[1.0:2:2.0]) + assert_raises(IndexError, lambda: a[1.0::2.0]) + assert_raises(IndexError, lambda: a[0:, :2.0:2.0]) + assert_raises(IndexError, lambda: a[1.0:1:4.0, :0]) + assert_raises(IndexError, lambda: a[1.0:5.0:5.0,:]) + assert_raises(IndexError, lambda: a[:, 0.4:4.0:2.0]) + # should still get the DeprecationWarning if step = 0. + assert_raises(IndexError, lambda: a[::0.0]) + + def test_index_no_array_to_index(self): + # No non-scalar arrays. + a = np.array([[[1]]]) + + assert_raises(IndexError, lambda: a[a:a:a]) + def test_none_index(self): # `None` index adds newaxis a = np.array([1, 2, 3]) @@ -32,19 +99,9 @@ class TestIndexing(TestCase): a = np.array(0) assert_(isinstance(a[()], np.int_)) - # Regression, it needs to fall through integer and fancy indexing - # cases, so need the with statement to ignore the non-integer error. - with warnings.catch_warnings(): - warnings.filterwarnings('ignore', '', DeprecationWarning) - a = np.array([1.]) - assert_(isinstance(a[0.], np.float_)) - - a = np.array([np.array(1)], dtype=object) - assert_(isinstance(a[0.], np.ndarray)) - def test_same_kind_index_casting(self): - # Indexes should be cast with same-kind and not safe, even if - # that is somewhat unsafe. So test various different code paths. + # Indexes should be cast with same-kind and not safe, even if that + # is somewhat unsafe. So test various different code paths. index = np.arange(5) u_index = index.astype(np.uintp) arr = np.arange(10) @@ -82,7 +139,8 @@ class TestIndexing(TestCase): [4, 5, 6], [7, 8, 9]]) assert_equal(a[...], a) - assert_(a[...].base is a) # `a[...]` was `a` in numpy <1.9.) + # `a[...]` was `a` in numpy <1.9. + assert_(a[...].base is a) # Slicing with ellipsis can skip an # arbitrary number of dimensions @@ -109,9 +167,9 @@ class TestIndexing(TestCase): assert_equal(a[-1], [7, 8, 9]) # Index out of bounds produces IndexError - assert_raises(IndexError, a.__getitem__, 1<<30) + assert_raises(IndexError, a.__getitem__, 1 << 30) # Index overflow produces IndexError - assert_raises(IndexError, a.__getitem__, 1<<64) + assert_raises(IndexError, a.__getitem__, 1 << 64) def test_single_bool_index(self): # Single boolean index @@ -133,7 +191,6 @@ class TestIndexing(TestCase): #assert_equal(a[np.array(True)], a[None]) #assert_equal(a[np.array(False), a[None][0:0]]) - def test_boolean_indexing_onedim(self): # Indexing a 2-dimensional array with # boolean array of length one @@ -144,11 +201,11 @@ class TestIndexing(TestCase): a[b] = 1. assert_equal(a, [[1., 1., 1.]]) - def test_boolean_assignment_value_mismatch(self): # A boolean assignment should fail when the shape of the values # cannot be broadcast to the subscription. (see also gh-3458) a = np.arange(4) + def f(a, v): a[a > -1] = v @@ -156,7 +213,6 @@ class TestIndexing(TestCase): assert_raises(ValueError, f, a, [1, 2, 3]) assert_raises(ValueError, f, a[:1], [1, 2, 3]) - def test_boolean_indexing_twodim(self): # Indexing a 2-dimensional array with # 2-dimensional boolean array @@ -176,7 +232,6 @@ class TestIndexing(TestCase): [4, 0, 6], [0, 8, 0]]) - def test_reverse_strides_and_subspace_bufferinit(self): # This tests that the strides are not reversed for simple and # subspace fancy indexing. @@ -203,7 +258,6 @@ class TestIndexing(TestCase): a = np.arange(20).reshape(-1, 2) - def test_uncontiguous_subspace_assignment(self): # During development there was a bug activating a skip logic # based on ndim instead of size. @@ -215,13 +269,11 @@ class TestIndexing(TestCase): assert_equal(a, b) - def test_too_many_fancy_indices_special_case(self): # Just documents behaviour, this is a small limitation. - a = np.ones((1,) * 32) # 32 is NPY_MAXDIMS + a = np.ones((1,) * 32) # 32 is NPY_MAXDIMS assert_raises(IndexError, a.__getitem__, (np.array([0]),) * 32) - def test_scalar_array_bool(self): # Numpy bools can be used as boolean index (python ones as of yet not) a = np.array(1) @@ -235,7 +287,6 @@ class TestIndexing(TestCase): # #assert_(not np.may_share_memory(a, a[True, :])) - def test_everything_returns_views(self): # Before `...` would return a itself. a = np.arange(5) @@ -244,13 +295,11 @@ class TestIndexing(TestCase): assert_(a is not a[...]) assert_(a is not a[:]) - def test_broaderrors_indexing(self): a = np.zeros((5, 5)) assert_raises(IndexError, a.__getitem__, ([0, 1], [0, 1, 2])) assert_raises(IndexError, a.__setitem__, ([0, 1], [0, 1, 2]), 0) - def test_trivial_fancy_out_of_bounds(self): a = np.zeros(5) ind = np.ones(20, dtype=np.intp) @@ -262,7 +311,6 @@ class TestIndexing(TestCase): assert_raises(IndexError, a.__getitem__, ind) assert_raises(IndexError, a.__setitem__, ind, 0) - def test_nonbaseclass_values(self): class SubClass(np.ndarray): def __array_finalize__(self, old): @@ -284,7 +332,6 @@ class TestIndexing(TestCase): a[...] = s assert_((a == 1).all()) - def test_subclass_writeable(self): d = np.rec.array([('NGC1001', 11), ('NGC1002', 1.), ('NGC1003', 1.)], dtype=[('target', 'S20'), ('V_mag', '>f4')]) @@ -295,7 +342,6 @@ class TestIndexing(TestCase): assert_(d[...].flags.writeable) assert_(d[0].flags.writeable) - def test_memory_order(self): # This is not necessary to preserve. Memory layouts for # more complex indices are not as simple. @@ -307,7 +353,6 @@ class TestIndexing(TestCase): a = a.reshape(-1, 1) assert_(a[b, 0].flags.f_contiguous) - def test_scalar_return_type(self): # Full scalar indices should return scalars and object # arrays should not call PyArray_Return on their items @@ -315,6 +360,7 @@ class TestIndexing(TestCase): # The most basic valid indexing def __index__(self): return 0 + z = Zero() class ArrayLike(object): @@ -341,7 +387,6 @@ class TestIndexing(TestCase): assert_(isinstance(a[z, np.array(0)], np.ndarray)) assert_(isinstance(a[z, ArrayLike()], np.ndarray)) - def test_small_regressions(self): # Reference count of intp for index checks a = np.array([0]) @@ -409,6 +454,26 @@ class TestIndexing(TestCase): arr = np.arange(10) assert_array_equal(arr[SequenceLike()], arr[SequenceLike(),]) + # also test that field indexing does not segfault + # for a similar reason, by indexing a structured array + arr = np.zeros((1,), dtype=[('f1', 'i8'), ('f2', 'i8')]) + assert_array_equal(arr[SequenceLike()], arr[SequenceLike(),]) + + def test_indexing_array_weird_strides(self): + # See also gh-6221 + # the shapes used here come from the issue and create the correct + # size for the iterator buffering size. + x = np.ones(10) + x2 = np.ones((10, 2)) + ind = np.arange(10)[:, None, None, None] + ind = np.broadcast_to(ind, (10, 55, 4, 4)) + + # single advanced index case + assert_array_equal(x[ind], x[ind.copy()]) + # higher dimensional advanced index + zind = np.zeros(4, dtype=np.intp) + assert_array_equal(x2[ind, zind], x2[ind.copy(), zind]) + class TestFieldIndexing(TestCase): def test_scalar_return_type(self): @@ -424,7 +489,6 @@ class TestBroadcastedAssignments(TestCase): a[ind] = val return a - def test_prepending_ones(self): a = np.zeros((3, 2)) @@ -435,7 +499,6 @@ class TestBroadcastedAssignments(TestCase): # Fancy without subspace (with broadcasting) a[[[0], [1], [2]], [0, 1]] = np.ones((1, 3, 2)) - def test_prepend_not_one(self): assign = self.assign s_ = np.s_ @@ -453,7 +516,6 @@ class TestBroadcastedAssignments(TestCase): assert_raises(DeprecationWarning, assign, a, s_[[[1], [2]],], np.ones((2,2,1))) - def test_simple_broadcasting_errors(self): assign = self.assign s_ = np.s_ @@ -467,7 +529,6 @@ class TestBroadcastedAssignments(TestCase): assert_raises(ValueError, assign, a, s_[[0], :], np.zeros((2, 1))) - def test_index_is_larger(self): # Simple case of fancy index broadcasting of the index. a = np.zeros((5, 5)) @@ -475,7 +536,6 @@ class TestBroadcastedAssignments(TestCase): assert_((a[:3, :3] == [2, 3, 4]).all()) - def test_broadcast_subspace(self): a = np.zeros((100, 100)) v = np.arange(100)[:,None] @@ -496,7 +556,6 @@ class TestSubclasses(TestCase): assert_(isinstance(s[[0, 1, 2]], SubClass)) assert_(isinstance(s[s > 0], SubClass)) - def test_matrix_fancy(self): # The matrix class messes with the shape. While this is always # weird (getitem is not used, it does not have setitem nor knows @@ -510,7 +569,6 @@ class TestSubclasses(TestCase): x = np.asmatrix(np.arange(50).reshape(5,10)) assert_equal(x[:2, np.array(-1)], x[:2, -1].T) - def test_finalize_gets_full_info(self): # Array finalize should be called on the filled array. class SubClass(np.ndarray): @@ -531,6 +589,27 @@ class TestSubclasses(TestCase): assert_array_equal(new_s.finalize_status, new_s) assert_array_equal(new_s.old, s) +class TestFancingIndexingCast(TestCase): + def test_boolean_index_cast_assign(self): + # Setup the boolean index and float arrays. + shape = (8, 63) + bool_index = np.zeros(shape).astype(bool) + bool_index[0, 1] = True + zero_array = np.zeros(shape) + + # Assigning float is fine. + zero_array[bool_index] = np.array([1]) + assert_equal(zero_array[0, 1], 1) + + # Fancy indexing works, although we get a cast warning. + assert_warns(np.ComplexWarning, + zero_array.__setitem__, ([0], [1]), np.array([2 + 1j])) + assert_equal(zero_array[0, 1], 2) # No complex part + + # Cast complex to float, throwing away the imaginary portion. + assert_warns(np.ComplexWarning, + zero_array.__setitem__, bool_index, np.array([1j])) + assert_equal(zero_array[0, 1], 0) class TestFancyIndexingEquivalence(TestCase): def test_object_assign(self): @@ -595,6 +674,7 @@ class TestMultiIndexingAutomated(TestCase): is only one error. For multiple errors, what gets raised will usually not be the same one. They are *not* tested. """ + def setUp(self): self.a = np.arange(np.prod([3, 1, 5, 6])).reshape(3, 1, 5, 6) self.b = np.empty((3, 0, 5, 6)) @@ -612,19 +692,19 @@ class TestMultiIndexingAutomated(TestCase): slice(4, -1, -2), slice(None, None, -3), # Some Fancy indexes: - np.empty((0, 1, 1), dtype=np.intp), # empty and can be broadcast + np.empty((0, 1, 1), dtype=np.intp), # empty and can be broadcast np.array([0, 1, -2]), np.array([[2], [0], [1]]), np.array([[0, -1], [0, 1]], dtype=np.dtype('intp').newbyteorder()), np.array([2, -1], dtype=np.int8), - np.zeros([1]*31, dtype=int), # trigger too large array. - np.array([0., 1.])] # invalid datatype + np.zeros([1]*31, dtype=int), # trigger too large array. + np.array([0., 1.])] # invalid datatype # Some simpler indices that still cover a bit more - self.simple_indices = [Ellipsis, None, -1, [1], np.array([True]), 'skip'] + self.simple_indices = [Ellipsis, None, -1, [1], np.array([True]), + 'skip'] # Very simple ones to fill the rest: self.fill_indices = [slice(None, None), 0] - def _get_multi_index(self, arr, indices): """Mimic multi dimensional indexing. @@ -666,7 +746,7 @@ class TestMultiIndexingAutomated(TestCase): # We need to handle Ellipsis and make arrays from indices, also # check if this is fancy indexing (set no_copy). ndim = 0 - ellipsis_pos = None # define here mostly to replace all but first. + ellipsis_pos = None # define here mostly to replace all but first. for i, indx in enumerate(in_indices): if indx is None: continue @@ -681,7 +761,7 @@ class TestMultiIndexingAutomated(TestCase): if indx is Ellipsis: if ellipsis_pos is None: ellipsis_pos = i - continue # do not increment ndim counter + continue # do not increment ndim counter raise IndexError if isinstance(indx, slice): ndim += 1 @@ -695,24 +775,27 @@ class TestMultiIndexingAutomated(TestCase): indx = np.array(indx, dtype=np.intp) in_indices[i] = indx elif indx.dtype.kind != 'b' and indx.dtype.kind != 'i': - raise IndexError('arrays used as indices must be of integer (or boolean) type') + raise IndexError('arrays used as indices must be of ' + 'integer (or boolean) type') if indx.ndim != 0: no_copy = False ndim += 1 fancy_dim += 1 if arr.ndim - ndim < 0: - # we can't take more dimensions then we have, not even for 0-d arrays. - # since a[()] makes sense, but not a[(),]. We will raise an error - # later on, unless a broadcasting error occurs first. + # we can't take more dimensions then we have, not even for 0-d + # arrays. since a[()] makes sense, but not a[(),]. We will + # raise an error later on, unless a broadcasting error occurs + # first. raise IndexError - if ndim == 0 and not None in in_indices: + if ndim == 0 and None not in in_indices: # Well we have no indexes or one Ellipsis. This is legal. return arr.copy(), no_copy if ellipsis_pos is not None: - in_indices[ellipsis_pos:ellipsis_pos+1] = [slice(None, None)] * (arr.ndim - ndim) + in_indices[ellipsis_pos:ellipsis_pos+1] = ([slice(None, None)] * + (arr.ndim - ndim)) for ax, indx in enumerate(in_indices): if isinstance(indx, slice): @@ -726,14 +809,9 @@ class TestMultiIndexingAutomated(TestCase): arr = arr.reshape((arr.shape[:ax] + (1,) + arr.shape[ax:])) continue if isinstance(indx, np.ndarray) and indx.dtype == bool: - # This may be open for improvement in numpy. - # numpy should probably cast boolean lists to boolean indices - # instead of intp! - - # Numpy supports for a boolean index with - # non-matching shape as long as the True values are not - # out of bounds. Numpy maybe should maybe not allow this, - # (at least not array that are larger then the original one). + if indx.shape != arr.shape[ax:ax+indx.ndim]: + raise IndexError + try: flat_indx = np.ravel_multi_index(np.nonzero(indx), arr.shape[ax:ax+indx.ndim], mode='raise') @@ -760,21 +838,23 @@ class TestMultiIndexingAutomated(TestCase): if indx >= arr.shape[ax] or indx < -arr.shape[ax]: raise IndexError if indx.ndim == 0: - # The index is a scalar. This used to be two fold, but if fancy - # indexing was active, the check was done later, possibly - # after broadcasting it away (1.7. or earlier). Now it is always - # done. + # The index is a scalar. This used to be two fold, but if + # fancy indexing was active, the check was done later, + # possibly after broadcasting it away (1.7. or earlier). + # Now it is always done. if indx >= arr.shape[ax] or indx < - arr.shape[ax]: raise IndexError - if len(indices) > 0 and indices[-1][0] == 'f' and ax != ellipsis_pos: + if (len(indices) > 0 and + indices[-1][0] == 'f' and + ax != ellipsis_pos): # NOTE: There could still have been a 0-sized Ellipsis # between them. Checked that with ellipsis_pos. indices[-1].append(indx) else: # We have a fancy index that is not after an existing one. - # NOTE: A 0-d array triggers this as well, while - # one may expect it to not trigger it, since a scalar - # would not be considered fancy indexing. + # NOTE: A 0-d array triggers this as well, while one may + # expect it to not trigger it, since a scalar would not be + # considered fancy indexing. num_fancy += 1 indices.append(['f', indx]) @@ -795,7 +875,7 @@ class TestMultiIndexingAutomated(TestCase): for ax in range(ai, ai + len(indx[1:])): fancy_axes.append(ax) axes.remove(ax) - ai += len(indx) - 1 # axis we are at + ai += len(indx) - 1 # axis we are at indices = new_indices # and now we need to transpose arr: arr = arr.transpose(*(fancy_axes + axes)) @@ -816,7 +896,7 @@ class TestMultiIndexingAutomated(TestCase): # Check if broadcasting works if len(indx[1:]) != 1: - res = np.broadcast(*indx[1:]) # raises ValueError... + res = np.broadcast(*indx[1:]) # raises ValueError... else: res = indx[1] # unfortunately the indices might be out of bounds. So check @@ -835,13 +915,15 @@ class TestMultiIndexingAutomated(TestCase): # Work around for a crash or IndexError with 'wrap' # in some 0-sized cases. try: - mi = np.ravel_multi_index(indx[1:], orig_slice, mode='raise') + mi = np.ravel_multi_index(indx[1:], orig_slice, + mode='raise') except: # This happens with 0-sized orig_slice (sometimes?) # here it is a ValueError, but indexing gives a: raise IndexError('invalid index into 0-sized') else: - mi = np.ravel_multi_index(indx[1:], orig_slice, mode='wrap') + mi = np.ravel_multi_index(indx[1:], orig_slice, + mode='wrap') else: # Maybe never happens... raise ValueError @@ -858,7 +940,6 @@ class TestMultiIndexingAutomated(TestCase): return arr, no_copy - def _check_multi_index(self, arr, index): """Check a multi index item getting and simple setting. @@ -872,7 +953,7 @@ class TestMultiIndexingAutomated(TestCase): # Test item getting try: mimic_get, no_copy = self._get_multi_index(arr, index) - except Exception as e: + except Exception: prev_refcount = sys.getrefcount(arr) assert_raises(Exception, arr.__getitem__, index) assert_raises(Exception, arr.__setitem__, index, 0) @@ -881,7 +962,6 @@ class TestMultiIndexingAutomated(TestCase): self._compare_index_result(arr, index, mimic_get, no_copy) - def _check_single_index(self, arr, index): """Check a single index item getting and simple setting. @@ -895,7 +975,7 @@ class TestMultiIndexingAutomated(TestCase): """ try: mimic_get, no_copy = self._get_multi_index(arr, (index,)) - except Exception as e: + except Exception: prev_refcount = sys.getrefcount(arr) assert_raises(Exception, arr.__getitem__, index) assert_raises(Exception, arr.__setitem__, index, 0) @@ -904,7 +984,6 @@ class TestMultiIndexingAutomated(TestCase): self._compare_index_result(arr, index, mimic_get, no_copy) - def _compare_index_result(self, arr, index, mimic_get, no_copy): """Compare mimicked result to indexing result. """ @@ -926,7 +1005,7 @@ class TestMultiIndexingAutomated(TestCase): b = arr.copy() b[index] = mimic_get + 1000 if b.size == 0: - return # nothing to compare here... + return # nothing to compare here... if no_copy and indexed_arr.ndim != 0: # change indexed_arr in-place to manipulate original: indexed_arr += 1000 @@ -936,7 +1015,6 @@ class TestMultiIndexingAutomated(TestCase): arr.flat[indexed_arr.ravel()] += 1000 assert_array_equal(arr, b) - def test_boolean(self): a = np.array(5) assert_equal(a[np.array(True)], 5) @@ -947,10 +1025,12 @@ class TestMultiIndexingAutomated(TestCase): # it is aligned to the left. This is probably correct for # consistency with arr[boolean_array,] also no broadcasting # is done at all - self._check_multi_index(self.a, (np.zeros_like(self.a, dtype=bool),)) - self._check_multi_index(self.a, (np.zeros_like(self.a, dtype=bool)[..., 0],)) - self._check_multi_index(self.a, (np.zeros_like(self.a, dtype=bool)[None, ...],)) - + self._check_multi_index( + self.a, (np.zeros_like(self.a, dtype=bool),)) + self._check_multi_index( + self.a, (np.zeros_like(self.a, dtype=bool)[..., 0],)) + self._check_multi_index( + self.a, (np.zeros_like(self.a, dtype=bool)[None, ...],)) def test_multidim(self): # Automatically test combinations with complex indexes on 2nd (or 1st) @@ -959,12 +1039,17 @@ class TestMultiIndexingAutomated(TestCase): # This is so that np.array(True) is not accepted in a full integer # index, when running the file separately. warnings.filterwarnings('error', '', DeprecationWarning) + warnings.filterwarnings('error', '', np.VisibleDeprecationWarning) + + def isskip(idx): + return isinstance(idx, str) and idx == "skip" + for simple_pos in [0, 2, 3]: tocheck = [self.fill_indices, self.complex_indices, self.fill_indices, self.fill_indices] tocheck[simple_pos] = self.simple_indices for index in product(*tocheck): - index = tuple(i for i in index if i != 'skip') + index = tuple(i for i in index if not isskip(i)) self._check_multi_index(self.a, index) self._check_multi_index(self.b, index) @@ -977,14 +1062,126 @@ class TestMultiIndexingAutomated(TestCase): assert_raises(IndexError, self.a.__getitem__, (0, 0, [1], 0, 0)) assert_raises(IndexError, self.a.__setitem__, (0, 0, [1], 0, 0), 0) - def test_1d(self): a = np.arange(10) with warnings.catch_warnings(): - warnings.filterwarnings('error', '', DeprecationWarning) + warnings.filterwarnings('error', '', np.VisibleDeprecationWarning) for index in self.complex_indices: self._check_single_index(a, index) +class TestFloatNonIntegerArgument(TestCase): + """ + These test that ``TypeError`` is raised when you try to use + non-integers as arguments to for indexing and slicing e.g. ``a[0.0:5]`` + and ``a[0.5]``, or other functions like ``array.reshape(1., -1)``. + + """ + def test_valid_indexing(self): + # These should raise no errors. + a = np.array([[[5]]]) + + a[np.array([0])] + a[[0, 0]] + a[:, [0, 0]] + a[:, 0,:] + a[:,:,:] + + def test_valid_slicing(self): + # These should raise no errors. + a = np.array([[[5]]]) + + a[::] + a[0:] + a[:2] + a[0:2] + a[::2] + a[1::2] + a[:2:2] + a[1:2:2] + + def test_non_integer_argument_errors(self): + a = np.array([[5]]) + + assert_raises(TypeError, np.reshape, a, (1., 1., -1)) + assert_raises(TypeError, np.reshape, a, (np.array(1.), -1)) + assert_raises(TypeError, np.take, a, [0], 1.) + assert_raises(TypeError, np.take, a, [0], np.float64(1.)) + + def test_non_integer_sequence_multiplication(self): + # Numpy scalar sequence multiply should not work with non-integers + def mult(a, b): + return a * b + + assert_raises(TypeError, mult, [1], np.float_(3)) + # following should be OK + mult([1], np.int_(3)) + + def test_reduce_axis_float_index(self): + d = np.zeros((3,3,3)) + assert_raises(TypeError, np.min, d, 0.5) + assert_raises(TypeError, np.min, d, (0.5, 1)) + assert_raises(TypeError, np.min, d, (1, 2.2)) + assert_raises(TypeError, np.min, d, (.2, 1.2)) + + +class TestBooleanArgumentErrors(TestCase): + """Using a boolean as integer argument/indexing is an error. + + """ + def test_bool_as_int_argument(self): + a = np.array([[[1]]]) + + assert_raises(TypeError, np.reshape, a, (True, -1)) + assert_raises(TypeError, np.reshape, a, (np.bool_(True), -1)) + # Note that operator.index(np.array(True)) does not work, a boolean + # array is thus also deprecated, but not with the same message: + assert_raises(TypeError, operator.index, np.array(True)) + assert_raises(TypeError, np.take, args=(a, [0], False)) + assert_raises(IndexError, lambda: a[False:True:True]) + assert_raises(IndexError, lambda: a[False, 0]) + assert_raises(IndexError, lambda: a[False, 0, 0]) + + +class TestArrayToIndexDeprecation(TestCase): + """Creating an an index from array not 0-D is an error. + + """ + def test_array_to_index_error(self): + # so no exception is expected. The raising is effectively tested above. + a = np.array([[[1]]]) + + assert_raises(TypeError, operator.index, np.array([1])) + assert_raises(TypeError, np.reshape, a, (a, -1)) + assert_raises(TypeError, np.take, a, [0], a) + + +class TestNonIntegerArrayLike(TestCase): + """Tests that array_likes only valid if can safely cast to integer. + + For instance, lists give IndexError when they cannot be safely cast to + an integer. + + """ + def test_basic(self): + a = np.arange(10) + + assert_raises(IndexError, a.__getitem__, [0.5, 1.5]) + assert_raises(IndexError, a.__getitem__, (['1', '2'],)) + + # The following is valid + a.__getitem__([]) + + +class TestMultipleEllipsisError(TestCase): + """An index can only have a single ellipsis. + + """ + def test_basic(self): + a = np.arange(10) + assert_raises(IndexError, lambda: a[..., ...]) + assert_raises(IndexError, a.__getitem__, ((Ellipsis,) * 2,)) + assert_raises(IndexError, a.__getitem__, ((Ellipsis,) * 3,)) + class TestCApiAccess(TestCase): def test_getitem(self): diff --git a/numpy/core/tests/test_item_selection.py b/numpy/core/tests/test_item_selection.py index d8e9e6fd0..f3e7701d4 100644 --- a/numpy/core/tests/test_item_selection.py +++ b/numpy/core/tests/test_item_selection.py @@ -1,8 +1,12 @@ from __future__ import division, absolute_import, print_function +import sys + import numpy as np -from numpy.testing import * -import sys, warnings +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_raises, + assert_array_equal +) class TestTake(TestCase): @@ -45,7 +49,6 @@ class TestTake(TestCase): res = ta.take(index_array, mode=mode, axis=1) assert_(res.shape == (2,) + index_array.shape) - def test_refcounting(self): objects = [object() for i in range(10)] for mode in ('raise', 'clip', 'wrap'): diff --git a/numpy/core/tests/test_longdouble.py b/numpy/core/tests/test_longdouble.py new file mode 100644 index 000000000..fcc79ecbc --- /dev/null +++ b/numpy/core/tests/test_longdouble.py @@ -0,0 +1,228 @@ +from __future__ import division, absolute_import, print_function + +import locale +from tempfile import NamedTemporaryFile + +import numpy as np +from numpy.testing import ( + run_module_suite, assert_, assert_equal, dec, assert_raises, + assert_array_equal, TestCase +) +from numpy.compat import sixu +from test_print import in_foreign_locale + +longdouble_longer_than_double = (np.finfo(np.longdouble).eps + < np.finfo(np.double).eps) + + +_o = 1 + np.finfo(np.longdouble).eps +string_to_longdouble_inaccurate = (_o != np.longdouble(repr(_o))) +del _o + + +def test_scalar_extraction(): + """Confirm that extracting a value doesn't convert to python float""" + o = 1 + np.finfo(np.longdouble).eps + a = np.array([o, o, o]) + assert_equal(a[1], o) + + +# Conversions string -> long double + + +def test_repr_roundtrip(): + o = 1 + np.finfo(np.longdouble).eps + assert_equal(np.longdouble(repr(o)), o, + "repr was %s" % repr(o)) + + +def test_unicode(): + np.longdouble(sixu("1.2")) + + +def test_string(): + np.longdouble("1.2") + + +def test_bytes(): + np.longdouble(b"1.2") + + +@in_foreign_locale +def test_fromstring_foreign(): + f = 1.234 + a = np.fromstring(repr(f), dtype=float, sep=" ") + assert_equal(a[0], f) + + +@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +def test_repr_roundtrip_bytes(): + o = 1 + np.finfo(np.longdouble).eps + assert_equal(np.longdouble(repr(o).encode("ascii")), o) + + +@in_foreign_locale +def test_repr_roundtrip_foreign(): + o = 1.5 + assert_equal(o, np.longdouble(repr(o))) + + +def test_bogus_string(): + assert_raises(ValueError, np.longdouble, "spam") + assert_raises(ValueError, np.longdouble, "1.0 flub") + + +@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +def test_fromstring(): + o = 1 + np.finfo(np.longdouble).eps + s = (" " + repr(o))*5 + a = np.array([o]*5) + assert_equal(np.fromstring(s, sep=" ", dtype=np.longdouble), a, + err_msg="reading '%s'" % s) + + +@in_foreign_locale +def test_fromstring_best_effort_float(): + assert_equal(np.fromstring("1,234", dtype=float, sep=" "), + np.array([1.])) + + +@in_foreign_locale +def test_fromstring_best_effort(): + assert_equal(np.fromstring("1,234", dtype=np.longdouble, sep=" "), + np.array([1.])) + + +def test_fromstring_bogus(): + assert_equal(np.fromstring("1. 2. 3. flop 4.", dtype=float, sep=" "), + np.array([1., 2., 3.])) + + +def test_fromstring_empty(): + assert_equal(np.fromstring("xxxxx", sep="x"), + np.array([])) + + +def test_fromstring_missing(): + assert_equal(np.fromstring("1xx3x4x5x6", sep="x"), + np.array([1])) + + +class FileBased(TestCase): + def setUp(self): + self.o = 1 + np.finfo(np.longdouble).eps + self.f = NamedTemporaryFile(mode="wt") + + def tearDown(self): + self.f.close() + del self.f + + def test_fromfile_bogus(self): + self.f.write("1. 2. 3. flop 4.\n") + self.f.flush() + F = open(self.f.name, "rt") + try: + assert_equal(np.fromfile(F, dtype=float, sep=" "), + np.array([1., 2., 3.])) + finally: + F.close() + + @dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") + def test_fromfile(self): + for i in range(5): + self.f.write(repr(self.o) + "\n") + self.f.flush() + a = np.array([self.o]*5) + F = open(self.f.name, "rt") + b = np.fromfile(F, + dtype=np.longdouble, + sep="\n") + F.close() + F = open(self.f.name, "rt") + s = F.read() + F.close() + assert_equal(b, a, err_msg="decoded %s as %s" % (repr(s), repr(b))) + + @dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") + def test_genfromtxt(self): + for i in range(5): + self.f.write(repr(self.o) + "\n") + self.f.flush() + a = np.array([self.o]*5) + assert_equal(np.genfromtxt(self.f.name, dtype=np.longdouble), a) + + @dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") + def test_loadtxt(self): + for i in range(5): + self.f.write(repr(self.o) + "\n") + self.f.flush() + a = np.array([self.o]*5) + assert_equal(np.loadtxt(self.f.name, dtype=np.longdouble), a) + + @dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") + def test_tofile_roundtrip(self): + a = np.array([self.o]*3) + a.tofile(self.f.name, sep=" ") + F = open(self.f.name, "rt") + try: + assert_equal(np.fromfile(F, dtype=np.longdouble, sep=" "), + a) + finally: + F.close() + + +@in_foreign_locale +def test_fromstring_foreign(): + s = "1.234" + a = np.fromstring(s, dtype=np.longdouble, sep=" ") + assert_equal(a[0], np.longdouble(s)) + + +@in_foreign_locale +def test_fromstring_foreign_sep(): + a = np.array([1, 2, 3, 4]) + b = np.fromstring("1,2,3,4,", dtype=np.longdouble, sep=",") + assert_array_equal(a, b) + + +@in_foreign_locale +def test_fromstring_foreign_value(): + b = np.fromstring("1,234", dtype=np.longdouble, sep=" ") + assert_array_equal(b[0], 1) + + +# Conversions long double -> string + + +def test_repr_exact(): + o = 1 + np.finfo(np.longdouble).eps + assert_(repr(o) != '1') + + +@dec.knownfailureif(longdouble_longer_than_double, "BUG #2376") +@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +def test_format(): + o = 1 + np.finfo(np.longdouble).eps + assert_("{0:.40g}".format(o) != '1') + + +@dec.knownfailureif(longdouble_longer_than_double, "BUG #2376") +@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +def test_percent(): + o = 1 + np.finfo(np.longdouble).eps + assert_("%.40g" % o != '1') + + +@dec.knownfailureif(longdouble_longer_than_double, "array repr problem") +@dec.knownfailureif(string_to_longdouble_inaccurate, "Need strtold_l") +def test_array_repr(): + o = 1 + np.finfo(np.longdouble).eps + a = np.array([o]) + b = np.array([1], dtype=np.longdouble) + if not np.all(a != b): + raise ValueError("precision loss creating arrays") + assert_(repr(a) != repr(b)) + + +if __name__ == "__main__": + run_module_suite() diff --git a/numpy/core/tests/test_machar.py b/numpy/core/tests/test_machar.py index 8d858c28b..d8fc537aa 100644 --- a/numpy/core/tests/test_machar.py +++ b/numpy/core/tests/test_machar.py @@ -1,24 +1,23 @@ from __future__ import division, absolute_import, print_function -from numpy.testing import * - from numpy.core.machar import MachAr import numpy.core.numerictypes as ntypes from numpy import errstate, array +from numpy.testing import TestCase, run_module_suite class TestMachAr(TestCase): def _run_machar_highprec(self): - # Instanciate MachAr instance with high enough precision to cause + # Instantiate MachAr instance with high enough precision to cause # underflow try: hiprec = ntypes.float96 - machar = MachAr(lambda v:array([v], hiprec)) + MachAr(lambda v:array([v], hiprec)) except AttributeError: - "Skipping test: no nyptes.float96 available on this platform." + "Skipping test: no ntypes.float96 available on this platform." def test_underlow(self): - """Regression testing for #759: instanciating MachAr for dtype = - np.float96 raises spurious warning.""" + # Regression test for #759: + # instanciating MachAr for dtype = np.float96 raises spurious warning. with errstate(all='raise'): try: self._run_machar_highprec() diff --git a/numpy/core/tests/test_mem_overlap.py b/numpy/core/tests/test_mem_overlap.py new file mode 100644 index 000000000..728cc675d --- /dev/null +++ b/numpy/core/tests/test_mem_overlap.py @@ -0,0 +1,486 @@ +from __future__ import division, absolute_import, print_function + +import sys +import itertools + +import numpy as np +from numpy.testing import run_module_suite, assert_, assert_raises, assert_equal + +from numpy.core.multiarray_tests import solve_diophantine, internal_overlap +from numpy.lib.stride_tricks import as_strided +from numpy.compat import long + +if sys.version_info[0] >= 3: + xrange = range + + +ndims = 2 +size = 10 +shape = tuple([size] * ndims) + +MAY_SHARE_BOUNDS = 0 +MAY_SHARE_EXACT = -1 + + +def _indices_for_nelems(nelems): + """Returns slices of length nelems, from start onwards, in direction sign.""" + + if nelems == 0: + return [size // 2] # int index + + res = [] + for step in (1, 2): + for sign in (-1, 1): + start = size // 2 - nelems * step * sign // 2 + stop = start + nelems * step * sign + res.append(slice(start, stop, step * sign)) + + return res + + +def _indices_for_axis(): + """Returns (src, dst) pairs of indices.""" + + res = [] + for nelems in (0, 2, 3): + ind = _indices_for_nelems(nelems) + + # no itertools.product available in Py2.4 + res.extend([(a, b) for a in ind for b in ind]) # all assignments of size "nelems" + + return res + + +def _indices(ndims): + """Returns ((axis0_src, axis0_dst), (axis1_src, axis1_dst), ... ) index pairs.""" + + ind = _indices_for_axis() + + # no itertools.product available in Py2.4 + + res = [[]] + for i in range(ndims): + newres = [] + for elem in ind: + for others in res: + newres.append([elem] + others) + res = newres + + return res + + +def _check_assignment(srcidx, dstidx): + """Check assignment arr[dstidx] = arr[srcidx] works.""" + + arr = np.arange(np.product(shape)).reshape(shape) + + cpy = arr.copy() + + cpy[dstidx] = arr[srcidx] + arr[dstidx] = arr[srcidx] + + assert np.all(arr == cpy), 'assigning arr[%s] = arr[%s]' % (dstidx, srcidx) + + +def test_overlapping_assignments(): + """Test automatically generated assignments which overlap in memory.""" + + inds = _indices(ndims) + + for ind in inds: + srcidx = tuple([a[0] for a in ind]) + dstidx = tuple([a[1] for a in ind]) + + yield _check_assignment, srcidx, dstidx + + +def test_diophantine_fuzz(): + # Fuzz test the diophantine solver + rng = np.random.RandomState(1234) + + max_int = np.iinfo(np.intp).max + + for ndim in range(10): + feasible_count = 0 + infeasible_count = 0 + + min_count = 500//(ndim + 1) + + numbers = [] + while min(feasible_count, infeasible_count) < min_count: + # Ensure big and small integer problems + A_max = 1 + rng.randint(0, 11)**6 + U_max = rng.randint(0, 11)**6 + + A_max = min(max_int, A_max) + U_max = min(max_int-1, U_max) + + A = tuple(rng.randint(1, A_max+1) for j in range(ndim)) + U = tuple(rng.randint(0, U_max+2) for j in range(ndim)) + + b_ub = min(max_int-2, sum(a*ub for a, ub in zip(A, U))) + b = rng.randint(-1, b_ub+2) + + if ndim == 0 and feasible_count < min_count: + b = 0 + + X = solve_diophantine(A, U, b) + + if X is None: + # Check the simplified decision problem agrees + X_simplified = solve_diophantine(A, U, b, simplify=1) + assert X_simplified is None, (A, U, b, X_simplified) + + # Check no solution exists (provided the problem is + # small enough so that brute force checking doesn't + # take too long) + try: + ranges = tuple(xrange(0, a*ub+1, a) for a, ub in zip(A, U)) + except OverflowError: + # xrange on 32-bit Python 2 may overflow + continue + + size = 1 + for r in ranges: + size *= len(r) + if size < 100000: + assert_(not any(sum(w) == b for w in itertools.product(*ranges))) + infeasible_count += 1 + else: + # Check the simplified decision problem agrees + X_simplified = solve_diophantine(A, U, b, simplify=1) + assert X_simplified is not None, (A, U, b, X_simplified) + + # Check validity + assert_(sum(a*x for a, x in zip(A, X)) == b) + assert_(all(0 <= x <= ub for x, ub in zip(X, U))) + feasible_count += 1 + + +def test_diophantine_overflow(): + # Smoke test integer overflow detection + max_intp = np.iinfo(np.intp).max + max_int64 = np.iinfo(np.int64).max + + if max_int64 <= max_intp: + # Check that the algorithm works internally in 128-bit; + # solving this problem requires large intermediate numbers + A = (max_int64//2, max_int64//2 - 10) + U = (max_int64//2, max_int64//2 - 10) + b = 2*(max_int64//2) - 10 + + assert_equal(solve_diophantine(A, U, b), (1, 1)) + + +def check_may_share_memory_exact(a, b): + got = np.may_share_memory(a, b, max_work=MAY_SHARE_EXACT) + + assert_equal(np.may_share_memory(a, b), + np.may_share_memory(a, b, max_work=MAY_SHARE_BOUNDS)) + + a.fill(0) + b.fill(0) + a.fill(1) + exact = b.any() + + err_msg = "" + if got != exact: + err_msg = " " + "\n ".join([ + "base_a - base_b = %r" % (a.__array_interface__['data'][0] - b.__array_interface__['data'][0],), + "shape_a = %r" % (a.shape,), + "shape_b = %r" % (b.shape,), + "strides_a = %r" % (a.strides,), + "strides_b = %r" % (b.strides,), + "size_a = %r" % (a.size,), + "size_b = %r" % (b.size,) + ]) + + assert_equal(got, exact, err_msg=err_msg) + + +def test_may_share_memory_manual(): + # Manual test cases for may_share_memory + + # Base arrays + xs0 = [ + np.zeros([13, 21, 23, 22], dtype=np.int8), + np.zeros([13, 21, 23*2, 22], dtype=np.int8)[:,:,::2,:] + ] + + # Generate all negative stride combinations + xs = [] + for x in xs0: + for ss in itertools.product(*(([slice(None), slice(None, None, -1)],)*4)): + xp = x[ss] + xs.append(xp) + + for x in xs: + # The default is a simple extent check + assert_(np.may_share_memory(x[:,0,:], x[:,1,:])) + assert_(np.may_share_memory(x[:,0,:], x[:,1,:], max_work=None)) + + # Exact checks + check_may_share_memory_exact(x[:,0,:], x[:,1,:]) + check_may_share_memory_exact(x[:,::7], x[:,3::3]) + + try: + xp = x.ravel() + if xp.flags.owndata: + continue + xp = xp.view(np.int16) + except ValueError: + continue + + # 0-size arrays cannot overlap + check_may_share_memory_exact(x.ravel()[6:6], + xp.reshape(13, 21, 23, 11)[:,::7]) + + # Test itemsize is dealt with + check_may_share_memory_exact(x[:,::7], + xp.reshape(13, 21, 23, 11)) + check_may_share_memory_exact(x[:,::7], + xp.reshape(13, 21, 23, 11)[:,3::3]) + check_may_share_memory_exact(x.ravel()[6:7], + xp.reshape(13, 21, 23, 11)[:,::7]) + + # Check unit size + x = np.zeros([1], dtype=np.int8) + check_may_share_memory_exact(x, x) + check_may_share_memory_exact(x, x.copy()) + + +def check_may_share_memory_easy_fuzz(get_max_work, same_steps, min_count): + # Check that overlap problems with common strides are solved with + # little work. + x = np.zeros([17,34,71,97], dtype=np.int16) + + rng = np.random.RandomState(1234) + + def random_slice(n, step): + start = rng.randint(0, n+1) + stop = rng.randint(start, n+1) + if rng.randint(0, 2) == 0: + stop, start = start, stop + step *= -1 + return slice(start, stop, step) + + feasible = 0 + infeasible = 0 + + while min(feasible, infeasible) < min_count: + steps = tuple(rng.randint(1, 11) if rng.randint(0, 5) == 0 else 1 + for j in range(x.ndim)) + if same_steps: + steps2 = steps + else: + steps2 = tuple(rng.randint(1, 11) if rng.randint(0, 5) == 0 else 1 + for j in range(x.ndim)) + + t1 = np.arange(x.ndim) + rng.shuffle(t1) + + t2 = np.arange(x.ndim) + rng.shuffle(t2) + + s1 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps)) + s2 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps2)) + a = x[s1].transpose(t1) + b = x[s2].transpose(t2) + + bounds_overlap = np.may_share_memory(a, b) + may_share_answer = np.may_share_memory(a, b) + easy_answer = np.may_share_memory(a, b, max_work=get_max_work(a, b)) + exact_answer = np.may_share_memory(a, b, max_work=MAY_SHARE_EXACT) + + if easy_answer != exact_answer: + # assert_equal is slow... + assert_equal(easy_answer, exact_answer, err_msg=repr((s1, s2))) + + if may_share_answer != bounds_overlap: + assert_equal(may_share_answer, bounds_overlap, + err_msg=repr((s1, s2))) + + if bounds_overlap: + if exact_answer: + feasible += 1 + else: + infeasible += 1 + + +def test_may_share_memory_easy_fuzz(): + # Check that overlap problems with common strides are always + # solved with little work. + + check_may_share_memory_easy_fuzz(get_max_work=lambda a, b: 1, + same_steps=True, + min_count=2000) + + +def test_may_share_memory_harder_fuzz(): + # Overlap problems with not necessarily common strides take more + # work. + # + # The work bound below can't be reduced much. Harder problems can + # also exist but not be detected here, as the set of problems + # comes from RNG. + + check_may_share_memory_easy_fuzz(get_max_work=lambda a, b: max(a.size, b.size)//2, + same_steps=False, + min_count=2000) + + +def test_shares_memory_api(): + x = np.zeros([4, 5, 6], dtype=np.int8) + + assert_equal(np.shares_memory(x, x), True) + assert_equal(np.shares_memory(x, x.copy()), False) + + a = x[:,::2,::3] + b = x[:,::3,::2] + assert_equal(np.shares_memory(a, b), True) + assert_equal(np.shares_memory(a, b, max_work=None), True) + assert_raises(np.TooHardError, np.shares_memory, a, b, max_work=1) + assert_raises(np.TooHardError, np.shares_memory, a, b, max_work=long(1)) + + +def test_internal_overlap_diophantine(): + def check(A, U, exists=None): + X = solve_diophantine(A, U, 0, require_ub_nontrivial=1) + + if exists is None: + exists = (X is not None) + + if X is not None: + assert_(sum(a*x for a, x in zip(A, X)) == sum(a*u//2 for a, u in zip(A, U))) + assert_(all(0 <= x <= u for x, u in zip(X, U))) + assert_(any(x != u//2 for x, u in zip(X, U))) + + if exists: + assert_(X is not None, repr(X)) + else: + assert_(X is None, repr(X)) + + # Smoke tests + check((3, 2), (2*2, 3*2), exists=True) + check((3*2, 2), (15*2, (3-1)*2), exists=False) + + +def test_internal_overlap_slices(): + # Slicing an array never generates internal overlap + + x = np.zeros([17,34,71,97], dtype=np.int16) + + rng = np.random.RandomState(1234) + + def random_slice(n, step): + start = rng.randint(0, n+1) + stop = rng.randint(start, n+1) + if rng.randint(0, 2) == 0: + stop, start = start, stop + step *= -1 + return slice(start, stop, step) + + cases = 0 + min_count = 5000 + + while cases < min_count: + steps = tuple(rng.randint(1, 11) if rng.randint(0, 5) == 0 else 1 + for j in range(x.ndim)) + t1 = np.arange(x.ndim) + rng.shuffle(t1) + s1 = tuple(random_slice(p, s) for p, s in zip(x.shape, steps)) + a = x[s1].transpose(t1) + + assert not internal_overlap(a) + cases += 1 + + +def check_internal_overlap(a, manual_expected=None): + got = internal_overlap(a) + + # Brute-force check + m = set() + ranges = tuple(xrange(n) for n in a.shape) + for v in itertools.product(*ranges): + offset = sum(s*w for s, w in zip(a.strides, v)) + if offset in m: + expected = True + break + else: + m.add(offset) + else: + expected = False + + # Compare + if got != expected: + assert_equal(got, expected, err_msg=repr((a.strides, a.shape))) + if manual_expected is not None and expected != manual_expected: + assert_equal(expected, manual_expected) + return got + + +def test_internal_overlap_manual(): + # Stride tricks can construct arrays with internal overlap + + # We don't care about memory bounds, the array is not + # read/write accessed + x = np.arange(1).astype(np.int8) + + # Check low-dimensional special cases + + check_internal_overlap(x, False) # 1-dim + check_internal_overlap(x.reshape([]), False) # 0-dim + + a = as_strided(x, strides=(3, 4), shape=(4, 4)) + check_internal_overlap(a, False) + + a = as_strided(x, strides=(3, 4), shape=(5, 4)) + check_internal_overlap(a, True) + + a = as_strided(x, strides=(0,), shape=(0,)) + check_internal_overlap(a, False) + + a = as_strided(x, strides=(0,), shape=(1,)) + check_internal_overlap(a, False) + + a = as_strided(x, strides=(0,), shape=(2,)) + check_internal_overlap(a, True) + + a = as_strided(x, strides=(0, -9993), shape=(87, 22)) + check_internal_overlap(a, True) + + a = as_strided(x, strides=(0, -9993), shape=(1, 22)) + check_internal_overlap(a, False) + + a = as_strided(x, strides=(0, -9993), shape=(0, 22)) + check_internal_overlap(a, False) + + +def test_internal_overlap_fuzz(): + # Fuzz check; the brute-force check is fairly slow + + x = np.arange(1).astype(np.int8) + + overlap = 0 + no_overlap = 0 + min_count = 100 + + rng = np.random.RandomState(1234) + + while min(overlap, no_overlap) < min_count: + ndim = rng.randint(1, 4) + + strides = tuple(rng.randint(-1000, 1000) for j in range(ndim)) + shape = tuple(rng.randint(1, 30) for j in range(ndim)) + + a = as_strided(x, strides=strides, shape=shape) + result = check_internal_overlap(a) + + if result: + overlap += 1 + else: + no_overlap += 1 + + +if __name__ == "__main__": + run_module_suite() diff --git a/numpy/core/tests/test_memmap.py b/numpy/core/tests/test_memmap.py index b364f5eb9..1585586ca 100644 --- a/numpy/core/tests/test_memmap.py +++ b/numpy/core/tests/test_memmap.py @@ -1,13 +1,16 @@ from __future__ import division, absolute_import, print_function import sys -from tempfile import NamedTemporaryFile, TemporaryFile, mktemp, mkdtemp import os import shutil +from tempfile import NamedTemporaryFile, TemporaryFile, mktemp, mkdtemp from numpy import memmap from numpy import arange, allclose, asarray -from numpy.testing import * +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_array_equal, + dec +) class TestMemmap(TestCase): def setUp(self): @@ -27,7 +30,7 @@ class TestMemmap(TestCase): fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', shape=self.shape) fp[:] = self.data[:] - del fp # Test __del__ machinery, which handles cleanup + del fp # Test __del__ machinery, which handles cleanup # Read data back from file newfp = memmap(self.tmpfp, dtype=self.dtype, mode='r', @@ -73,7 +76,7 @@ class TestMemmap(TestCase): shape=self.shape) self.assertEqual(fp.filename, self.tmpfp.name) - @dec.knownfailureif(sys.platform=='gnu0', "This test is known to fail on hurd") + @dec.knownfailureif(sys.platform == 'gnu0', "This test is known to fail on hurd") def test_flush(self): fp = memmap(self.tmpfp, dtype=self.dtype, mode='w+', shape=self.shape) diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index eab512eea..57cc745a6 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -3,11 +3,12 @@ from __future__ import division, absolute_import, print_function import collections import tempfile import sys -import os import shutil import warnings import operator import io +import itertools +import ctypes if sys.version_info[0] >= 3: import builtins else: @@ -17,20 +18,19 @@ from decimal import Decimal import numpy as np from nose import SkipTest -from numpy.core import * -from numpy.compat import asbytes, getexception, strchar, sixu +from numpy.compat import asbytes, getexception, strchar, unicode, sixu from test_print import in_foreign_locale from numpy.core.multiarray_tests import ( - test_neighborhood_iterator, test_neighborhood_iterator_oob, - test_pydatamem_seteventhook_start, test_pydatamem_seteventhook_end, - test_inplace_increment, get_buffer_info, test_as_c_array - ) + test_neighborhood_iterator, test_neighborhood_iterator_oob, + test_pydatamem_seteventhook_start, test_pydatamem_seteventhook_end, + test_inplace_increment, get_buffer_info, test_as_c_array + ) from numpy.testing import ( - TestCase, run_module_suite, assert_, assert_raises, - assert_equal, assert_almost_equal, assert_array_equal, - assert_array_almost_equal, assert_allclose, - assert_array_less, runstring, dec - ) + TestCase, run_module_suite, assert_, assert_raises, + assert_equal, assert_almost_equal, assert_array_equal, + assert_array_almost_equal, assert_allclose, + assert_array_less, runstring, dec + ) # Need to test an object that does not fully implement math interface from datetime import timedelta @@ -47,7 +47,7 @@ else: class TestFlags(TestCase): def setUp(self): - self.a = arange(10) + self.a = np.arange(10) def test_writeable(self): mydict = locals() @@ -69,6 +69,17 @@ class TestFlags(TestCase): assert_equal(self.a.flags.aligned, True) assert_equal(self.a.flags.updateifcopy, False) + def test_string_align(self): + a = np.zeros(4, dtype=np.dtype('|S4')) + assert_(a.flags.aligned) + # not power of two are accessed bytewise and thus considered aligned + a = np.zeros(5, dtype=np.dtype('|S4')) + assert_(a.flags.aligned) + + def test_void_align(self): + a = np.zeros(4, dtype=np.dtype([("a", "i4"), ("b", "i4")])) + assert_(a.flags.aligned) + class TestHash(TestCase): # see #3793 def test_int(self): @@ -92,9 +103,9 @@ class TestHash(TestCase): class TestAttributes(TestCase): def setUp(self): - self.one = arange(10) - self.two = arange(20).reshape(4, 5) - self.three = arange(60, dtype=float64).reshape(2, 5, 6) + self.one = np.arange(10) + self.two = np.arange(20).reshape(4, 5) + self.three = np.arange(60, dtype=np.float64).reshape(2, 5, 6) def test_attributes(self): assert_equal(self.one.shape, (10,)) @@ -115,11 +126,11 @@ class TestAttributes(TestCase): assert_equal(self.two.size, 20) assert_equal(self.two.nbytes, 20*num) assert_equal(self.two.itemsize, self.two.dtype.itemsize) - assert_equal(self.two.base, arange(20)) + assert_equal(self.two.base, np.arange(20)) def test_dtypeattr(self): - assert_equal(self.one.dtype, dtype(int_)) - assert_equal(self.three.dtype, dtype(float_)) + assert_equal(self.one.dtype, np.dtype(np.int_)) + assert_equal(self.three.dtype, np.dtype(np.float_)) assert_equal(self.one.dtype.char, 'l') assert_equal(self.three.dtype.char, 'd') self.assertTrue(self.three.dtype.str[0] in '<>') @@ -144,38 +155,44 @@ class TestAttributes(TestCase): def test_stridesattr(self): x = self.one + def make_array(size, offset, strides): - return ndarray(size, buffer=x, dtype=int, + return np.ndarray(size, buffer=x, dtype=int, offset=offset*x.itemsize, strides=strides*x.itemsize) - assert_equal(make_array(4, 4, -1), array([4, 3, 2, 1])) + + assert_equal(make_array(4, 4, -1), np.array([4, 3, 2, 1])) self.assertRaises(ValueError, make_array, 4, 4, -2) self.assertRaises(ValueError, make_array, 4, 2, -1) self.assertRaises(ValueError, make_array, 8, 3, 1) assert_equal(make_array(8, 3, 0), np.array([3]*8)) # Check behavior reported in gh-2503: - self.assertRaises(ValueError, make_array, (2, 3), 5, array([-2, -3])) + self.assertRaises(ValueError, make_array, (2, 3), 5, np.array([-2, -3])) make_array(0, 0, 10) def test_set_stridesattr(self): x = self.one + def make_array(size, offset, strides): try: - r = ndarray([size], dtype=int, buffer=x, offset=offset*x.itemsize) + r = np.ndarray([size], dtype=int, buffer=x, offset=offset*x.itemsize) except: raise RuntimeError(getexception()) - r.strides = strides=strides*x.itemsize + r.strides = strides = strides*x.itemsize return r - assert_equal(make_array(4, 4, -1), array([4, 3, 2, 1])) - assert_equal(make_array(7, 3, 1), array([3, 4, 5, 6, 7, 8, 9])) + + assert_equal(make_array(4, 4, -1), np.array([4, 3, 2, 1])) + assert_equal(make_array(7, 3, 1), np.array([3, 4, 5, 6, 7, 8, 9])) self.assertRaises(ValueError, make_array, 4, 4, -2) self.assertRaises(ValueError, make_array, 4, 2, -1) self.assertRaises(RuntimeError, make_array, 8, 3, 1) # Check that the true extent of the array is used. # Test relies on as_strided base not exposing a buffer. - x = np.lib.stride_tricks.as_strided(arange(1), (10, 10), (0, 0)) + x = np.lib.stride_tricks.as_strided(np.arange(1), (10, 10), (0, 0)) + def set_strides(arr, strides): arr.strides = strides + self.assertRaises(ValueError, set_strides, x, (10*x.itemsize, x.itemsize)) # Test for offset calculations: @@ -188,15 +205,15 @@ class TestAttributes(TestCase): def test_fill(self): for t in "?bhilqpBHILQPfdgFDGO": - x = empty((3, 2, 1), t) - y = empty((3, 2, 1), t) + x = np.empty((3, 2, 1), t) + y = np.empty((3, 2, 1), t) x.fill(1) y[...] = 1 assert_equal(x, y) def test_fill_max_uint64(self): - x = empty((3, 2, 1), dtype=uint64) - y = empty((3, 2, 1), dtype=uint64) + x = np.empty((3, 2, 1), dtype=np.uint64) + y = np.empty((3, 2, 1), dtype=np.uint64) value = 2**64 - 1 y[...] = value x.fill(value) @@ -204,7 +221,7 @@ class TestAttributes(TestCase): def test_fill_struct_array(self): # Filling from a scalar - x = array([(0, 0.0), (1, 1.0)], dtype='i4,f8') + x = np.array([(0, 0.0), (1, 1.0)], dtype='i4,f8') x.fill(x[0]) assert_equal(x['f1'][1], x['f1'][0]) # Filling from a tuple that can be converted @@ -314,8 +331,10 @@ class TestAssignment(TestCase): a[...] = np.arange(6)[::-1].reshape(1, 2, 3) assert_equal(a, [[5, 4, 3], [2, 1, 0]]) # The other type of broadcasting would require a reduction operation. + def assign(a, b): a[...] = b + assert_raises(ValueError, assign, a, np.arange(12).reshape(2, 2, 3)) def test_assignment_errors(self): @@ -323,32 +342,34 @@ class TestAssignment(TestCase): class C: pass a = np.zeros(1) + def assign(v): a[0] = v + assert_raises((AttributeError, TypeError), assign, C()) assert_raises(ValueError, assign, [1]) class TestDtypedescr(TestCase): def test_construction(self): - d1 = dtype('i4') - assert_equal(d1, dtype(int32)) - d2 = dtype('f8') - assert_equal(d2, dtype(float64)) + d1 = np.dtype('i4') + assert_equal(d1, np.dtype(np.int32)) + d2 = np.dtype('f8') + assert_equal(d2, np.dtype(np.float64)) def test_byteorders(self): - self.assertNotEqual(dtype('<i4'), dtype('>i4')) - self.assertNotEqual(dtype([('a', '<i4')]), dtype([('a', '>i4')])) + self.assertNotEqual(np.dtype('<i4'), np.dtype('>i4')) + self.assertNotEqual(np.dtype([('a', '<i4')]), np.dtype([('a', '>i4')])) class TestZeroRank(TestCase): def setUp(self): - self.d = array(0), array('x', object) + self.d = np.array(0), np.array('x', object) def test_ellipsis_subscript(self): a, b = self.d self.assertEqual(a[...], 0) self.assertEqual(b[...], 'x') - self.assertTrue(a[...].base is a) # `a[...] is a` in numpy <1.9. - self.assertTrue(b[...].base is b) # `b[...] is b` in numpy <1.9. + self.assertTrue(a[...].base is a) # `a[...] is a` in numpy <1.9. + self.assertTrue(b[...].base is b) # `b[...] is b` in numpy <1.9. def test_empty_subscript(self): a, b = self.d @@ -361,8 +382,8 @@ class TestZeroRank(TestCase): a, b = self.d self.assertRaises(IndexError, lambda x: x[0], a) self.assertRaises(IndexError, lambda x: x[0], b) - self.assertRaises(IndexError, lambda x: x[array([], int)], a) - self.assertRaises(IndexError, lambda x: x[array([], int)], b) + self.assertRaises(IndexError, lambda x: x[np.array([], int)], a) + self.assertRaises(IndexError, lambda x: x[np.array([], int)], b) def test_ellipsis_subscript_assignment(self): a, b = self.d @@ -380,45 +401,50 @@ class TestZeroRank(TestCase): def test_invalid_subscript_assignment(self): a, b = self.d + def assign(x, i, v): x[i] = v + self.assertRaises(IndexError, assign, a, 0, 42) self.assertRaises(IndexError, assign, b, 0, '') self.assertRaises(ValueError, assign, a, (), '') def test_newaxis(self): a, b = self.d - self.assertEqual(a[newaxis].shape, (1,)) - self.assertEqual(a[..., newaxis].shape, (1,)) - self.assertEqual(a[newaxis, ...].shape, (1,)) - self.assertEqual(a[..., newaxis].shape, (1,)) - self.assertEqual(a[newaxis, ..., newaxis].shape, (1, 1)) - self.assertEqual(a[..., newaxis, newaxis].shape, (1, 1)) - self.assertEqual(a[newaxis, newaxis, ...].shape, (1, 1)) - self.assertEqual(a[(newaxis,)*10].shape, (1,)*10) + self.assertEqual(a[np.newaxis].shape, (1,)) + self.assertEqual(a[..., np.newaxis].shape, (1,)) + self.assertEqual(a[np.newaxis, ...].shape, (1,)) + self.assertEqual(a[..., np.newaxis].shape, (1,)) + self.assertEqual(a[np.newaxis, ..., np.newaxis].shape, (1, 1)) + self.assertEqual(a[..., np.newaxis, np.newaxis].shape, (1, 1)) + self.assertEqual(a[np.newaxis, np.newaxis, ...].shape, (1, 1)) + self.assertEqual(a[(np.newaxis,)*10].shape, (1,)*10) def test_invalid_newaxis(self): a, b = self.d - def subscript(x, i): x[i] - self.assertRaises(IndexError, subscript, a, (newaxis, 0)) - self.assertRaises(IndexError, subscript, a, (newaxis,)*50) + + def subscript(x, i): + x[i] + + self.assertRaises(IndexError, subscript, a, (np.newaxis, 0)) + self.assertRaises(IndexError, subscript, a, (np.newaxis,)*50) def test_constructor(self): - x = ndarray(()) + x = np.ndarray(()) x[()] = 5 self.assertEqual(x[()], 5) - y = ndarray((), buffer=x) + y = np.ndarray((), buffer=x) y[()] = 6 self.assertEqual(x[()], 6) def test_output(self): - x = array(2) - self.assertRaises(ValueError, add, x, [1], x) + x = np.array(2) + self.assertRaises(ValueError, np.add, x, [1], x) class TestScalarIndexing(TestCase): def setUp(self): - self.d = array([0, 1])[0] + self.d = np.array([0, 1])[0] def test_ellipsis_subscript(self): a = self.d @@ -433,30 +459,35 @@ class TestScalarIndexing(TestCase): def test_invalid_subscript(self): a = self.d self.assertRaises(IndexError, lambda x: x[0], a) - self.assertRaises(IndexError, lambda x: x[array([], int)], a) + self.assertRaises(IndexError, lambda x: x[np.array([], int)], a) def test_invalid_subscript_assignment(self): a = self.d + def assign(x, i, v): x[i] = v + self.assertRaises(TypeError, assign, a, 0, 42) def test_newaxis(self): a = self.d - self.assertEqual(a[newaxis].shape, (1,)) - self.assertEqual(a[..., newaxis].shape, (1,)) - self.assertEqual(a[newaxis, ...].shape, (1,)) - self.assertEqual(a[..., newaxis].shape, (1,)) - self.assertEqual(a[newaxis, ..., newaxis].shape, (1, 1)) - self.assertEqual(a[..., newaxis, newaxis].shape, (1, 1)) - self.assertEqual(a[newaxis, newaxis, ...].shape, (1, 1)) - self.assertEqual(a[(newaxis,)*10].shape, (1,)*10) + self.assertEqual(a[np.newaxis].shape, (1,)) + self.assertEqual(a[..., np.newaxis].shape, (1,)) + self.assertEqual(a[np.newaxis, ...].shape, (1,)) + self.assertEqual(a[..., np.newaxis].shape, (1,)) + self.assertEqual(a[np.newaxis, ..., np.newaxis].shape, (1, 1)) + self.assertEqual(a[..., np.newaxis, np.newaxis].shape, (1, 1)) + self.assertEqual(a[np.newaxis, np.newaxis, ...].shape, (1, 1)) + self.assertEqual(a[(np.newaxis,)*10].shape, (1,)*10) def test_invalid_newaxis(self): a = self.d - def subscript(x, i): x[i] - self.assertRaises(IndexError, subscript, a, (newaxis, 0)) - self.assertRaises(IndexError, subscript, a, (newaxis,)*50) + + def subscript(x, i): + x[i] + + self.assertRaises(IndexError, subscript, a, (np.newaxis, 0)) + self.assertRaises(IndexError, subscript, a, (np.newaxis,)*50) def test_overlapping_assignment(self): # With positive strides @@ -511,15 +542,16 @@ class TestCreation(TestCase): class x(object): def __array__(self, dtype=None): pass - self.assertRaises(ValueError, array, x()) - def test_from_string(self) : + self.assertRaises(ValueError, np.array, x()) + + def test_from_string(self): types = np.typecodes['AllInteger'] + np.typecodes['Float'] nstr = ['123', '123'] - result = array([123, 123], dtype=int) - for type in types : + result = np.array([123, 123], dtype=int) + for type in types: msg = 'String conversion for %s' % type - assert_equal(array(nstr, dtype=type), result, err_msg=msg) + assert_equal(np.array(nstr, dtype=type), result, err_msg=msg) def test_void(self): arr = np.array([], dtype='V') @@ -562,7 +594,7 @@ class TestCreation(TestCase): assert_equal(np.count_nonzero(d), 0) def test_zeros_obj_obj(self): - d = zeros(10, dtype=[('k', object, 2)]) + d = np.zeros(10, dtype=[('k', object, 2)]) assert_array_equal(d['k'], 0) def test_zeros_like_like_zeros(self): @@ -570,34 +602,34 @@ class TestCreation(TestCase): for c in np.typecodes['All']: if c == 'V': continue - d = zeros((3,3), dtype=c) - assert_array_equal(zeros_like(d), d) - assert_equal(zeros_like(d).dtype, d.dtype) + d = np.zeros((3,3), dtype=c) + assert_array_equal(np.zeros_like(d), d) + assert_equal(np.zeros_like(d).dtype, d.dtype) # explicitly check some special cases - d = zeros((3,3), dtype='S5') - assert_array_equal(zeros_like(d), d) - assert_equal(zeros_like(d).dtype, d.dtype) - d = zeros((3,3), dtype='U5') - assert_array_equal(zeros_like(d), d) - assert_equal(zeros_like(d).dtype, d.dtype) - - d = zeros((3,3), dtype='<i4') - assert_array_equal(zeros_like(d), d) - assert_equal(zeros_like(d).dtype, d.dtype) - d = zeros((3,3), dtype='>i4') - assert_array_equal(zeros_like(d), d) - assert_equal(zeros_like(d).dtype, d.dtype) - - d = zeros((3,3), dtype='<M8[s]') - assert_array_equal(zeros_like(d), d) - assert_equal(zeros_like(d).dtype, d.dtype) - d = zeros((3,3), dtype='>M8[s]') - assert_array_equal(zeros_like(d), d) - assert_equal(zeros_like(d).dtype, d.dtype) - - d = zeros((3,3), dtype='f4,f4') - assert_array_equal(zeros_like(d), d) - assert_equal(zeros_like(d).dtype, d.dtype) + d = np.zeros((3,3), dtype='S5') + assert_array_equal(np.zeros_like(d), d) + assert_equal(np.zeros_like(d).dtype, d.dtype) + d = np.zeros((3,3), dtype='U5') + assert_array_equal(np.zeros_like(d), d) + assert_equal(np.zeros_like(d).dtype, d.dtype) + + d = np.zeros((3,3), dtype='<i4') + assert_array_equal(np.zeros_like(d), d) + assert_equal(np.zeros_like(d).dtype, d.dtype) + d = np.zeros((3,3), dtype='>i4') + assert_array_equal(np.zeros_like(d), d) + assert_equal(np.zeros_like(d).dtype, d.dtype) + + d = np.zeros((3,3), dtype='<M8[s]') + assert_array_equal(np.zeros_like(d), d) + assert_equal(np.zeros_like(d).dtype, d.dtype) + d = np.zeros((3,3), dtype='>M8[s]') + assert_array_equal(np.zeros_like(d), d) + assert_equal(np.zeros_like(d).dtype, d.dtype) + + d = np.zeros((3,3), dtype='f4,f4') + assert_array_equal(np.zeros_like(d), d) + assert_equal(np.zeros_like(d).dtype, d.dtype) def test_empty_unicode(self): # don't throw decode errors on garbage memory @@ -686,51 +718,61 @@ class TestStructured(TestCase): [([1, 2, 3], 'a', [[1, 2], [3, 4]]), ([3, 3, 3], 'b', [[0, 0], [0, 0]])], dtype=[('a', ('f4', 3)), ('b', np.object), ('c', ('i4', (2, 2)))]) b = a.copy() - assert_equal(a==b, [True, True]) - assert_equal(a!=b, [False, False]) + assert_equal(a == b, [True, True]) + assert_equal(a != b, [False, False]) b[1].b = 'c' - assert_equal(a==b, [True, False]) - assert_equal(a!=b, [False, True]) + assert_equal(a == b, [True, False]) + assert_equal(a != b, [False, True]) for i in range(3): b[0].a = a[0].a b[0].a[i] = 5 - assert_equal(a==b, [False, False]) - assert_equal(a!=b, [True, True]) + assert_equal(a == b, [False, False]) + assert_equal(a != b, [True, True]) for i in range(2): for j in range(2): b = a.copy() b[0].c[i, j] = 10 - assert_equal(a==b, [False, True]) - assert_equal(a!=b, [True, False]) + assert_equal(a == b, [False, True]) + assert_equal(a != b, [True, False]) # Check that broadcasting with a subarray works a = np.array([[(0,)], [(1,)]], dtype=[('a', 'f8')]) b = np.array([(0,), (0,), (1,)], dtype=[('a', 'f8')]) - assert_equal(a==b, [[True, True, False], [False, False, True]]) - assert_equal(b==a, [[True, True, False], [False, False, True]]) + assert_equal(a == b, [[True, True, False], [False, False, True]]) + assert_equal(b == a, [[True, True, False], [False, False, True]]) a = np.array([[(0,)], [(1,)]], dtype=[('a', 'f8', (1,))]) b = np.array([(0,), (0,), (1,)], dtype=[('a', 'f8', (1,))]) - assert_equal(a==b, [[True, True, False], [False, False, True]]) - assert_equal(b==a, [[True, True, False], [False, False, True]]) + assert_equal(a == b, [[True, True, False], [False, False, True]]) + assert_equal(b == a, [[True, True, False], [False, False, True]]) a = np.array([[([0, 0],)], [([1, 1],)]], dtype=[('a', 'f8', (2,))]) b = np.array([([0, 0],), ([0, 1],), ([1, 1],)], dtype=[('a', 'f8', (2,))]) - assert_equal(a==b, [[True, False, False], [False, False, True]]) - assert_equal(b==a, [[True, False, False], [False, False, True]]) + assert_equal(a == b, [[True, False, False], [False, False, True]]) + assert_equal(b == a, [[True, False, False], [False, False, True]]) # Check that broadcasting Fortran-style arrays with a subarray work a = np.array([[([0, 0],)], [([1, 1],)]], dtype=[('a', 'f8', (2,))], order='F') b = np.array([([0, 0],), ([0, 1],), ([1, 1],)], dtype=[('a', 'f8', (2,))]) - assert_equal(a==b, [[True, False, False], [False, False, True]]) - assert_equal(b==a, [[True, False, False], [False, False, True]]) + assert_equal(a == b, [[True, False, False], [False, False, True]]) + assert_equal(b == a, [[True, False, False], [False, False, True]]) # Check that incompatible sub-array shapes don't result to broadcasting x = np.zeros((1,), dtype=[('a', ('f4', (1, 2))), ('b', 'i1')]) y = np.zeros((1,), dtype=[('a', ('f4', (2,))), ('b', 'i1')]) - assert_equal(x == y, False) + # This comparison invokes deprecated behaviour, and will probably + # start raising an error eventually. What we really care about in this + # test is just that it doesn't return True. + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning) + assert_equal(x == y, False) x = np.zeros((1,), dtype=[('a', ('f4', (2, 1))), ('b', 'i1')]) y = np.zeros((1,), dtype=[('a', ('f4', (2,))), ('b', 'i1')]) - assert_equal(x == y, False) + # This comparison invokes deprecated behaviour, and will probably + # start raising an error eventually. What we really care about in this + # test is just that it doesn't return True. + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning) + assert_equal(x == y, False) # Check that structured arrays that are different only in # byte-order work @@ -797,20 +839,53 @@ class TestStructured(TestCase): t = [('a', '>i4'), ('b', '<f8'), ('c', 'i4')] assert_(not np.can_cast(a.dtype, t, casting=casting)) + def test_objview(self): + # https://github.com/numpy/numpy/issues/3286 + a = np.array([], dtype=[('a', 'f'), ('b', 'f'), ('c', 'O')]) + a[['a', 'b']] # TypeError? + + # https://github.com/numpy/numpy/issues/3253 + dat2 = np.zeros(3, [('A', 'i'), ('B', '|O')]) + dat2[['B', 'A']] # TypeError? + + def test_setfield(self): + # https://github.com/numpy/numpy/issues/3126 + struct_dt = np.dtype([('elem', 'i4', 5),]) + dt = np.dtype([('field', 'i4', 10),('struct', struct_dt)]) + x = np.zeros(1, dt) + x[0]['field'] = np.ones(10, dtype='i4') + x[0]['struct'] = np.ones(1, dtype=struct_dt) + assert_equal(x[0]['field'], np.ones(10, dtype='i4')) + + def test_setfield_object(self): + # make sure object field assignment with ndarray value + # on void scalar mimics setitem behavior + b = np.zeros(1, dtype=[('x', 'O')]) + # next line should work identically to b['x'][0] = np.arange(3) + b[0]['x'] = np.arange(3) + assert_equal(b[0]['x'], np.arange(3)) + + #check that broadcasting check still works + c = np.zeros(1, dtype=[('x', 'O', 5)]) + + def testassign(): + c[0]['x'] = np.arange(3) + + assert_raises(ValueError, testassign) class TestBool(TestCase): def test_test_interning(self): - a0 = bool_(0) - b0 = bool_(False) + a0 = np.bool_(0) + b0 = np.bool_(False) self.assertTrue(a0 is b0) - a1 = bool_(1) - b1 = bool_(True) + a1 = np.bool_(1) + b1 = np.bool_(True) self.assertTrue(a1 is b1) - self.assertTrue(array([True])[0] is a1) - self.assertTrue(array(True)[()] is a1) + self.assertTrue(np.array([True])[0] is a1) + self.assertTrue(np.array(True)[()] is a1) def test_sum(self): - d = np.ones(101, dtype=np.bool); + d = np.ones(101, dtype=np.bool) assert_equal(d.sum(), d.size) assert_equal(d[::2].sum(), d[::2].size) assert_equal(d[::-2].sum(), d[::-2].size) @@ -857,14 +932,25 @@ class TestBool(TestCase): self.assertEqual(np.count_nonzero(a), builtins.sum(a.tolist())) class TestMethods(TestCase): - def test_test_round(self): - assert_equal(array([1.2, 1.5]).round(), [1, 2]) - assert_equal(array(1.5).round(), 2) - assert_equal(array([12.2, 15.5]).round(-1), [10, 20]) - assert_equal(array([12.15, 15.51]).round(1), [12.2, 15.5]) + def test_round(self): + def check_round(arr, expected, *round_args): + assert_equal(arr.round(*round_args), expected) + # With output array + out = np.zeros_like(arr) + res = arr.round(*round_args, out=out) + assert_equal(out, expected) + assert_equal(out, res) + + check_round(np.array([1.2, 1.5]), [1, 2]) + check_round(np.array(1.5), 2) + check_round(np.array([12.2, 15.5]), [10, 20], -1) + check_round(np.array([12.15, 15.51]), [12.2, 15.5], 1) + # Complex rounding + check_round(np.array([4.5 + 1.5j]), [4 + 2j]) + check_round(np.array([12.5 + 15.5j]), [10 + 20j], -1) def test_transpose(self): - a = array([[1, 2], [3, 4]]) + a = np.array([[1, 2], [3, 4]]) assert_equal(a.transpose(), [[1, 3], [2, 4]]) self.assertRaises(ValueError, lambda: a.transpose(0)) self.assertRaises(ValueError, lambda: a.transpose(0, 0)) @@ -879,14 +965,14 @@ class TestMethods(TestCase): # check doubles msg = "Test real sort order with nans" a = np.array([np.nan, 1, 0]) - b = sort(a) + b = np.sort(a) assert_equal(b, a[::-1], msg) # check complex msg = "Test complex sort order with nans" a = np.zeros(9, dtype=np.complex128) a.real += [np.nan, np.nan, np.nan, 1, 0, 1, 1, 0, 0] a.imag += [np.nan, 1, 0, np.nan, np.nan, 1, 0, 1, 0] - b = sort(a) + b = np.sort(a) assert_equal(b, a[::-1], msg) # all c scalar sorts use the same code with different types @@ -896,12 +982,12 @@ class TestMethods(TestCase): # sort for small arrays. a = np.arange(101) b = a[::-1].copy() - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "scalar sort, kind=%s" % kind - c = a.copy(); + c = a.copy() c.sort(kind=kind) assert_equal(c, a, msg) - c = b.copy(); + c = b.copy() c.sort(kind=kind) assert_equal(c, a, msg) @@ -909,30 +995,29 @@ class TestMethods(TestCase): # but the compare function differs. ai = a*1j + 1 bi = b*1j + 1 - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "complex sort, real part == 1, kind=%s" % kind - c = ai.copy(); + c = ai.copy() c.sort(kind=kind) assert_equal(c, ai, msg) - c = bi.copy(); + c = bi.copy() c.sort(kind=kind) assert_equal(c, ai, msg) ai = a + 1j bi = b + 1j - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "complex sort, imag part == 1, kind=%s" % kind - c = ai.copy(); + c = ai.copy() c.sort(kind=kind) assert_equal(c, ai, msg) - c = bi.copy(); + c = bi.copy() c.sort(kind=kind) assert_equal(c, ai, msg) # test sorting of complex arrays requiring byte-swapping, gh-5441 for endianess in '<>': for dt in np.typecodes['Complex']: - dtype = '{0}{1}'.format(endianess, dt) - arr = np.array([1+3.j, 2+2.j, 3+1.j], dtype=dt) + arr = np.array([1+3.j, 2+2.j, 3+1.j], dtype=endianess + dt) c = arr.copy() c.sort() msg = 'byte-swapped complex sort, dtype={0}'.format(dt) @@ -942,12 +1027,12 @@ class TestMethods(TestCase): s = 'aaaaaaaa' a = np.array([s + chr(i) for i in range(101)]) b = a[::-1].copy() - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "string sort, kind=%s" % kind - c = a.copy(); + c = a.copy() c.sort(kind=kind) assert_equal(c, a, msg) - c = b.copy(); + c = b.copy() c.sort(kind=kind) assert_equal(c, a, msg) @@ -955,12 +1040,12 @@ class TestMethods(TestCase): s = 'aaaaaaaa' a = np.array([s + chr(i) for i in range(101)], dtype=np.unicode) b = a[::-1].copy() - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "unicode sort, kind=%s" % kind - c = a.copy(); + c = a.copy() c.sort(kind=kind) assert_equal(c, a, msg) - c = b.copy(); + c = b.copy() c.sort(kind=kind) assert_equal(c, a, msg) @@ -968,49 +1053,49 @@ class TestMethods(TestCase): a = np.empty((101,), dtype=np.object) a[:] = list(range(101)) b = a[::-1] - for kind in ['q', 'h', 'm'] : + for kind in ['q', 'h', 'm']: msg = "object sort, kind=%s" % kind - c = a.copy(); + c = a.copy() c.sort(kind=kind) assert_equal(c, a, msg) - c = b.copy(); + c = b.copy() c.sort(kind=kind) assert_equal(c, a, msg) # test record array sorts. dt = np.dtype([('f', float), ('i', int)]) - a = array([(i, i) for i in range(101)], dtype = dt) + a = np.array([(i, i) for i in range(101)], dtype=dt) b = a[::-1] - for kind in ['q', 'h', 'm'] : + for kind in ['q', 'h', 'm']: msg = "object sort, kind=%s" % kind - c = a.copy(); + c = a.copy() c.sort(kind=kind) assert_equal(c, a, msg) - c = b.copy(); + c = b.copy() c.sort(kind=kind) assert_equal(c, a, msg) # test datetime64 sorts. a = np.arange(0, 101, dtype='datetime64[D]') b = a[::-1] - for kind in ['q', 'h', 'm'] : + for kind in ['q', 'h', 'm']: msg = "datetime64 sort, kind=%s" % kind - c = a.copy(); + c = a.copy() c.sort(kind=kind) assert_equal(c, a, msg) - c = b.copy(); + c = b.copy() c.sort(kind=kind) assert_equal(c, a, msg) # test timedelta64 sorts. a = np.arange(0, 101, dtype='timedelta64[D]') b = a[::-1] - for kind in ['q', 'h', 'm'] : + for kind in ['q', 'h', 'm']: msg = "timedelta64 sort, kind=%s" % kind - c = a.copy(); + c = a.copy() c.sort(kind=kind) assert_equal(c, a, msg) - c = b.copy(); + c = b.copy() c.sort(kind=kind) assert_equal(c, a, msg) @@ -1065,25 +1150,25 @@ class TestMethods(TestCase): def test_sort_order(self): # Test sorting an array with fields - x1=np.array([21, 32, 14]) - x2=np.array(['my', 'first', 'name']) - x3=np.array([3.1, 4.5, 6.2]) - r=np.rec.fromarrays([x1, x2, x3], names='id,word,number') + x1 = np.array([21, 32, 14]) + x2 = np.array(['my', 'first', 'name']) + x3 = np.array([3.1, 4.5, 6.2]) + r = np.rec.fromarrays([x1, x2, x3], names='id,word,number') r.sort(order=['id']) - assert_equal(r.id, array([14, 21, 32])) - assert_equal(r.word, array(['name', 'my', 'first'])) - assert_equal(r.number, array([6.2, 3.1, 4.5])) + assert_equal(r.id, np.array([14, 21, 32])) + assert_equal(r.word, np.array(['name', 'my', 'first'])) + assert_equal(r.number, np.array([6.2, 3.1, 4.5])) r.sort(order=['word']) - assert_equal(r.id, array([32, 21, 14])) - assert_equal(r.word, array(['first', 'my', 'name'])) - assert_equal(r.number, array([4.5, 3.1, 6.2])) + assert_equal(r.id, np.array([32, 21, 14])) + assert_equal(r.word, np.array(['first', 'my', 'name'])) + assert_equal(r.number, np.array([4.5, 3.1, 6.2])) r.sort(order=['number']) - assert_equal(r.id, array([21, 32, 14])) - assert_equal(r.word, array(['my', 'first', 'name'])) - assert_equal(r.number, array([3.1, 4.5, 6.2])) + assert_equal(r.id, np.array([21, 32, 14])) + assert_equal(r.word, np.array(['my', 'first', 'name'])) + assert_equal(r.number, np.array([3.1, 4.5, 6.2])) if sys.byteorder == 'little': strtype = '>i2' @@ -1091,7 +1176,7 @@ class TestMethods(TestCase): strtype = '<i2' mydtype = [('name', strchar + '5'), ('col2', strtype)] r = np.array([('a', 1), ('b', 255), ('c', 3), ('d', 258)], - dtype= mydtype) + dtype=mydtype) r.sort(order='col2') assert_equal(r['col2'], [1, 3, 255, 258]) assert_equal(r, np.array([('a', 1), ('c', 3), ('b', 255), ('d', 258)], @@ -1105,7 +1190,7 @@ class TestMethods(TestCase): # sort for small arrays. a = np.arange(101) b = a[::-1].copy() - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "scalar argsort, kind=%s" % kind assert_equal(a.copy().argsort(kind=kind), a, msg) assert_equal(b.copy().argsort(kind=kind), b, msg) @@ -1114,13 +1199,13 @@ class TestMethods(TestCase): # but the compare fuction differs. ai = a*1j + 1 bi = b*1j + 1 - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "complex argsort, kind=%s" % kind assert_equal(ai.copy().argsort(kind=kind), a, msg) assert_equal(bi.copy().argsort(kind=kind), b, msg) ai = a + 1j bi = b + 1j - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "complex argsort, kind=%s" % kind assert_equal(ai.copy().argsort(kind=kind), a, msg) assert_equal(bi.copy().argsort(kind=kind), b, msg) @@ -1128,8 +1213,7 @@ class TestMethods(TestCase): # test argsort of complex arrays requiring byte-swapping, gh-5441 for endianess in '<>': for dt in np.typecodes['Complex']: - dtype = '{0}{1}'.format(endianess, dt) - arr = np.array([1+3.j, 2+2.j, 3+1.j], dtype=dt) + arr = np.array([1+3.j, 2+2.j, 3+1.j], dtype=endianess + dt) msg = 'byte-swapped complex argsort, dtype={0}'.format(dt) assert_equal(arr.argsort(), np.arange(len(arr), dtype=np.intp), msg) @@ -1140,7 +1224,7 @@ class TestMethods(TestCase): b = a[::-1].copy() r = np.arange(101) rr = r[::-1] - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "string argsort, kind=%s" % kind assert_equal(a.copy().argsort(kind=kind), r, msg) assert_equal(b.copy().argsort(kind=kind), rr, msg) @@ -1151,7 +1235,7 @@ class TestMethods(TestCase): b = a[::-1] r = np.arange(101) rr = r[::-1] - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "unicode argsort, kind=%s" % kind assert_equal(a.copy().argsort(kind=kind), r, msg) assert_equal(b.copy().argsort(kind=kind), rr, msg) @@ -1162,18 +1246,18 @@ class TestMethods(TestCase): b = a[::-1] r = np.arange(101) rr = r[::-1] - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "object argsort, kind=%s" % kind assert_equal(a.copy().argsort(kind=kind), r, msg) assert_equal(b.copy().argsort(kind=kind), rr, msg) # test structured array argsorts. dt = np.dtype([('f', float), ('i', int)]) - a = array([(i, i) for i in range(101)], dtype = dt) + a = np.array([(i, i) for i in range(101)], dtype=dt) b = a[::-1] r = np.arange(101) rr = r[::-1] - for kind in ['q', 'm', 'h'] : + for kind in ['q', 'm', 'h']: msg = "structured array argsort, kind=%s" % kind assert_equal(a.copy().argsort(kind=kind), r, msg) assert_equal(b.copy().argsort(kind=kind), rr, msg) @@ -1183,7 +1267,7 @@ class TestMethods(TestCase): b = a[::-1] r = np.arange(101) rr = r[::-1] - for kind in ['q', 'h', 'm'] : + for kind in ['q', 'h', 'm']: msg = "datetime64 argsort, kind=%s" % kind assert_equal(a.copy().argsort(kind=kind), r, msg) assert_equal(b.copy().argsort(kind=kind), rr, msg) @@ -1193,7 +1277,7 @@ class TestMethods(TestCase): b = a[::-1] r = np.arange(101) rr = r[::-1] - for kind in ['q', 'h', 'm'] : + for kind in ['q', 'h', 'm']: msg = "timedelta64 argsort, kind=%s" % kind assert_equal(a.copy().argsort(kind=kind), r, msg) assert_equal(b.copy().argsort(kind=kind), rr, msg) @@ -1220,7 +1304,6 @@ class TestMethods(TestCase): assert_equal(np.argsort(a, axis=None), np.zeros_like(a.ravel(), dtype=np.intp), msg) - # check that stable argsorts are stable r = np.arange(100) # scalars @@ -1335,7 +1418,6 @@ class TestMethods(TestCase): b = a.searchsorted(a, 'r') assert_equal(b, out + 1) - def test_searchsorted_unicode(self): # Test searchsorted on unicode strings. @@ -1445,6 +1527,18 @@ class TestMethods(TestCase): b = a.searchsorted(a, 'r', s) assert_equal(b, out + 1) + def test_searchsorted_return_type(self): + # Functions returning indices should always return base ndarrays + class A(np.ndarray): + pass + a = np.arange(5).view(A) + b = np.arange(1, 3).view(A) + s = np.arange(5).view(A) + assert_(not isinstance(a.searchsorted(b, 'l'), A)) + assert_(not isinstance(a.searchsorted(b, 'r'), A)) + assert_(not isinstance(a.searchsorted(b, 'l', s), A)) + assert_(not isinstance(a.searchsorted(b, 'r', s), A)) + def test_argpartition_out_of_range(self): # Test out of range values in kth raise an error, gh-5469 d = np.arange(10) @@ -1583,7 +1677,8 @@ class TestMethods(TestCase): assert_equal(np.partition(x, mid)[mid], mid) # max - d = np.ones(10); d[1] = 4; + d = np.ones(10) + d[1] = 4 assert_equal(np.partition(d, (2, -1))[-1], 4) assert_equal(np.partition(d, (2, -1))[2], 1) assert_equal(d[np.argpartition(d, (2, -1))][-1], 4) @@ -1697,7 +1792,6 @@ class TestMethods(TestCase): dc.partition(i, axis=1, kind=k) assert_equal(dc, np.partition(d1, i, axis=1, kind=k)) - def assert_partitioned(self, d, kth): prev = 0 for k in np.sort(kth): @@ -1706,7 +1800,6 @@ class TestMethods(TestCase): msg="kth %d, %r not greater equal %d" % (k, d[k:], d[k])) prev = k + 1 - def test_partition_iterative(self): d = np.arange(17) kth = (0, 1, 2, 429, 231) @@ -1775,9 +1868,8 @@ class TestMethods(TestCase): for i in range(d0.shape[1]): self.assert_partitioned(p[:, i], kth) - def test_partition_cdtype(self): - d = array([('Galahad', 1.7, 38), ('Arthur', 1.8, 41), + d = np.array([('Galahad', 1.7, 38), ('Arthur', 1.8, 41), ('Lancelot', 1.9, 38)], dtype=[('name', '|S10'), ('height', '<f8'), ('age', '<i4')]) @@ -1794,7 +1886,7 @@ class TestMethods(TestCase): assert_equal(d[np.argpartition(d, k, order=['age', 'height'])][k], tgt[k]) - d = array(['Galahad', 'Arthur', 'zebra', 'Lancelot']) + d = np.array(['Galahad', 'Arthur', 'zebra', 'Lancelot']) tgt = np.sort(d) assert_array_equal(np.partition(d, range(d.size)), tgt) for k in range(d.size): @@ -1809,16 +1901,16 @@ class TestMethods(TestCase): def test_partition_fuzz(self): # a few rounds of random data testing - for j in range(10, 30): - for i in range(1, j - 2): - d = np.arange(j) - np.random.shuffle(d) - d = d % np.random.randint(2, 30) - idx = np.random.randint(d.size) - kth = [0, idx, i, i + 1] - tgt = np.sort(d)[kth] - assert_array_equal(np.partition(d, kth)[kth], tgt, - err_msg="data: %r\n kth: %r" % (d, kth)) + for j in range(10, 30): + for i in range(1, j - 2): + d = np.arange(j) + np.random.shuffle(d) + d = d % np.random.randint(2, 30) + idx = np.random.randint(d.size) + kth = [0, idx, i, i + 1] + tgt = np.sort(d)[kth] + assert_array_equal(np.partition(d, kth)[kth], tgt, + err_msg="data: %r\n kth: %r" % (d, kth)) def test_argpartition_gh5524(self): # A test for functionality of argpartition on lists. @@ -1983,41 +2075,37 @@ class TestMethods(TestCase): assert_equal(a.ravel(order='K'), [2, 3, 0, 1]) assert_(a.ravel(order='K').flags.owndata) + # Test simple 1-d copy behaviour: + a = np.arange(10)[::2] + assert_(a.ravel('K').flags.owndata) + assert_(a.ravel('C').flags.owndata) + assert_(a.ravel('F').flags.owndata) + # Not contiguous and 1-sized axis with non matching stride a = np.arange(2**3 * 2)[::2] a = a.reshape(2, 1, 2, 2).swapaxes(-1, -2) strides = list(a.strides) strides[1] = 123 a.strides = strides - assert_(np.may_share_memory(a.ravel(order='K'), a)) + assert_(a.ravel(order='K').flags.owndata) assert_equal(a.ravel('K'), np.arange(0, 15, 2)) - # General case of possible ravel that is not contiguous but - # works and includes a 1-sized axis with non matching stride - a = a.swapaxes(-1, -2) # swap back to C-order - assert_(np.may_share_memory(a.ravel(order='C'), a)) - assert_(np.may_share_memory(a.ravel(order='K'), a)) - - a = a.T # swap all to Fortran order - assert_(np.may_share_memory(a.ravel(order='F'), a)) + # contiguous and 1-sized axis with non matching stride works: + a = np.arange(2**3) + a = a.reshape(2, 1, 2, 2).swapaxes(-1, -2) + strides = list(a.strides) + strides[1] = 123 + a.strides = strides assert_(np.may_share_memory(a.ravel(order='K'), a)) + assert_equal(a.ravel(order='K'), np.arange(2**3)) - # Test negative strides: + # Test negative strides (not very interesting since non-contiguous): a = np.arange(4)[::-1].reshape(2, 2) - assert_(np.may_share_memory(a.ravel(order='C'), a)) - assert_(np.may_share_memory(a.ravel(order='K'), a)) + assert_(a.ravel(order='C').flags.owndata) + assert_(a.ravel(order='K').flags.owndata) assert_equal(a.ravel('C'), [3, 2, 1, 0]) assert_equal(a.ravel('K'), [3, 2, 1, 0]) - # Test keeporder with weirdly strided 1-sized dims (1-d first stride) - a = np.arange(8)[::2].reshape(1, 2, 2, 1) # neither C, nor F order - strides = list(a.strides) - strides[0] = -12 - strides[-1] = 0 - a.strides = strides - assert_(np.may_share_memory(a.ravel(order='K'), a)) - assert_equal(a.ravel('K'), a.ravel('C')) - # 1-element tidy strides test (NPY_RELAXED_STRIDES_CHECKING): a = np.array([[1]]) a.strides = (123, 432) @@ -2033,7 +2121,7 @@ class TestMethods(TestCase): assert_equal(a.ravel(order), [0]) assert_(np.may_share_memory(a.ravel(order), a)) - #Test that certain non-inplace ravels work right (mostly) for 'K': + # Test that certain non-inplace ravels work right (mostly) for 'K': b = np.arange(2**4 * 2)[::2].reshape(2, 2, 2, 2) a = b[..., ::2] assert_equal(a.ravel('K'), [0, 4, 8, 12, 16, 20, 24, 28]) @@ -2047,6 +2135,22 @@ class TestMethods(TestCase): assert_equal(a.ravel('A'), [0, 2, 4, 6, 8, 10, 12, 14]) assert_equal(a.ravel('F'), [0, 8, 4, 12, 2, 10, 6, 14]) + def test_ravel_subclass(self): + class ArraySubclass(np.ndarray): + pass + + a = np.arange(10).view(ArraySubclass) + assert_(isinstance(a.ravel('C'), ArraySubclass)) + assert_(isinstance(a.ravel('F'), ArraySubclass)) + assert_(isinstance(a.ravel('A'), ArraySubclass)) + assert_(isinstance(a.ravel('K'), ArraySubclass)) + + a = np.arange(10)[::2].view(ArraySubclass) + assert_(isinstance(a.ravel('C'), ArraySubclass)) + assert_(isinstance(a.ravel('F'), ArraySubclass)) + assert_(isinstance(a.ravel('A'), ArraySubclass)) + assert_(isinstance(a.ravel('K'), ArraySubclass)) + def test_swapaxes(self): a = np.arange(1*2*3*4).reshape(1, 2, 3, 4).copy() idx = np.indices(a.shape) @@ -2204,10 +2308,10 @@ class TestBinop(object): '__ne__': ('__ne__', np.not_equal, False), } - class OtherNdarraySubclass(ndarray): + class OtherNdarraySubclass(np.ndarray): pass - class OtherNdarraySubclassWithOverride(ndarray): + class OtherNdarraySubclassWithOverride(np.ndarray): def __numpy_ufunc__(self, *a, **kw): raise AssertionError(("__numpy_ufunc__ %r %r shouldn't have " "been called!") % (a, kw)) @@ -2239,7 +2343,7 @@ class TestBinop(object): return "rop" if ndsubclass: - bases = (ndarray,) + bases = (np.ndarray,) else: bases = (object,) @@ -2299,22 +2403,28 @@ class TestBinop(object): def test_ufunc_override_rop_simple(self): # Check parts of the binary op overriding behavior in an # explicit test case that is easier to understand. - class SomeClass(object): def __numpy_ufunc__(self, *a, **kw): return "ufunc" + def __mul__(self, other): return 123 + def __rmul__(self, other): return 321 + + def __rsub__(self, other): + return "no subs for me" + def __gt__(self, other): return "yep" + def __lt__(self, other): return "nope" - class SomeClass2(SomeClass, ndarray): + class SomeClass2(SomeClass, np.ndarray): def __numpy_ufunc__(self, ufunc, method, i, inputs, **kw): - if ufunc is np.multiply: + if ufunc is np.multiply or ufunc is np.bitwise_and: return "ufunc" else: inputs = list(inputs) @@ -2324,28 +2434,47 @@ class TestBinop(object): if 'out' in kw: return r else: - x = SomeClass2(r.shape, dtype=r.dtype) + x = self.__class__(r.shape, dtype=r.dtype) x[...] = r return x + class SomeClass3(SomeClass2): + def __rsub__(self, other): + return "sub for me" + arr = np.array([0]) obj = SomeClass() obj2 = SomeClass2((1,), dtype=np.int_) obj2[0] = 9 + obj3 = SomeClass3((1,), dtype=np.int_) + obj3[0] = 4 + # obj is first, so should get to define outcome. assert_equal(obj * arr, 123) + # obj is second, but has __numpy_ufunc__ and defines __rmul__. assert_equal(arr * obj, 321) + # obj is second, but has __numpy_ufunc__ and defines __rsub__. + assert_equal(arr - obj, "no subs for me") + # obj is second, but has __numpy_ufunc__ and defines __lt__. assert_equal(arr > obj, "nope") + # obj is second, but has __numpy_ufunc__ and defines __gt__. assert_equal(arr < obj, "yep") + # Called as a ufunc, obj.__numpy_ufunc__ is used. assert_equal(np.multiply(arr, obj), "ufunc") + # obj is second, but has __numpy_ufunc__ and defines __rmul__. arr *= obj assert_equal(arr, 321) + # obj2 is an ndarray subclass, so CPython takes care of the same rules. assert_equal(obj2 * arr, 123) assert_equal(arr * obj2, 321) + assert_equal(arr - obj2, "no subs for me") assert_equal(arr > obj2, "nope") assert_equal(arr < obj2, "yep") + # Called as a ufunc, obj2.__numpy_ufunc__ is called. assert_equal(np.multiply(arr, obj2), "ufunc") + # Also when the method is not overridden. + assert_equal(arr & obj2, "ufunc") arr *= obj2 assert_equal(arr, 321) @@ -2354,6 +2483,27 @@ class TestBinop(object): assert_equal(obj2.sum(), 42) assert_(isinstance(obj2, SomeClass2)) + # Obj3 is subclass that defines __rsub__. CPython calls it. + assert_equal(arr - obj3, "sub for me") + assert_equal(obj2 - obj3, "sub for me") + # obj3 is a subclass that defines __rmul__. CPython calls it. + assert_equal(arr * obj3, 321) + # But not here, since obj3.__rmul__ is obj2.__rmul__. + assert_equal(obj2 * obj3, 123) + # And of course, here obj3.__mul__ should be called. + assert_equal(obj3 * obj2, 123) + # obj3 defines __numpy_ufunc__ but obj3.__radd__ is obj2.__radd__. + # (and both are just ndarray.__radd__); see #4815. + res = obj2 + obj3 + assert_equal(res, 46) + assert_(isinstance(res, SomeClass2)) + # Since obj3 is a subclass, it should have precedence, like CPython + # would give, even though obj2 has __numpy_ufunc__ and __radd__. + # See gh-4815 and gh-5747. + res = obj3 + obj2 + assert_equal(res, 46) + assert_(isinstance(res, SomeClass3)) + def test_ufunc_override_normalize_signature(self): # gh-5674 class SomeClass(object): @@ -2383,22 +2533,22 @@ class TestCAPI(TestCase): class TestSubscripting(TestCase): def test_test_zero_rank(self): - x = array([1, 2, 3]) + x = np.array([1, 2, 3]) self.assertTrue(isinstance(x[0], np.int_)) if sys.version_info[0] < 3: self.assertTrue(isinstance(x[0], int)) - self.assertTrue(type(x[0, ...]) is ndarray) + self.assertTrue(type(x[0, ...]) is np.ndarray) class TestPickling(TestCase): def test_roundtrip(self): import pickle - carray = array([[2, 9], [7, 0], [3, 8]]) + carray = np.array([[2, 9], [7, 0], [3, 8]]) DATA = [ carray, - transpose(carray), - array([('xxx', 1, 2.0)], dtype=[('a', (str, 3)), ('b', int), - ('c', float)]) + np.transpose(carray), + np.array([('xxx', 1, 2.0)], dtype=[('a', (str, 3)), ('b', int), + ('c', float)]) ] for a in DATA: @@ -2406,21 +2556,21 @@ class TestPickling(TestCase): def _loads(self, obj): if sys.version_info[0] >= 3: - return loads(obj, encoding='latin1') + return np.loads(obj, encoding='latin1') else: - return loads(obj) + return np.loads(obj) # version 0 pickles, using protocol=2 to pickle # version 0 doesn't have a version field def test_version0_int8(self): s = '\x80\x02cnumpy.core._internal\n_reconstruct\nq\x01cnumpy\nndarray\nq\x02K\x00\x85U\x01b\x87Rq\x03(K\x04\x85cnumpy\ndtype\nq\x04U\x02i1K\x00K\x01\x87Rq\x05(U\x01|NNJ\xff\xff\xff\xffJ\xff\xff\xff\xfftb\x89U\x04\x01\x02\x03\x04tb.' - a = array([1, 2, 3, 4], dtype=int8) + a = np.array([1, 2, 3, 4], dtype=np.int8) p = self._loads(asbytes(s)) assert_equal(a, p) def test_version0_float32(self): s = '\x80\x02cnumpy.core._internal\n_reconstruct\nq\x01cnumpy\nndarray\nq\x02K\x00\x85U\x01b\x87Rq\x03(K\x04\x85cnumpy\ndtype\nq\x04U\x02f4K\x00K\x01\x87Rq\x05(U\x01<NNJ\xff\xff\xff\xffJ\xff\xff\xff\xfftb\x89U\x10\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@tb.' - a = array([1.0, 2.0, 3.0, 4.0], dtype=float32) + a = np.array([1.0, 2.0, 3.0, 4.0], dtype=np.float32) p = self._loads(asbytes(s)) assert_equal(a, p) @@ -2433,19 +2583,19 @@ class TestPickling(TestCase): # version 1 pickles, using protocol=2 to pickle def test_version1_int8(self): s = '\x80\x02cnumpy.core._internal\n_reconstruct\nq\x01cnumpy\nndarray\nq\x02K\x00\x85U\x01b\x87Rq\x03(K\x01K\x04\x85cnumpy\ndtype\nq\x04U\x02i1K\x00K\x01\x87Rq\x05(K\x01U\x01|NNJ\xff\xff\xff\xffJ\xff\xff\xff\xfftb\x89U\x04\x01\x02\x03\x04tb.' - a = array([1, 2, 3, 4], dtype=int8) + a = np.array([1, 2, 3, 4], dtype=np.int8) p = self._loads(asbytes(s)) assert_equal(a, p) def test_version1_float32(self): s = '\x80\x02cnumpy.core._internal\n_reconstruct\nq\x01cnumpy\nndarray\nq\x02K\x00\x85U\x01b\x87Rq\x03(K\x01K\x04\x85cnumpy\ndtype\nq\x04U\x02f4K\x00K\x01\x87Rq\x05(K\x01U\x01<NNJ\xff\xff\xff\xffJ\xff\xff\xff\xfftb\x89U\x10\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@tb.' - a = array([1.0, 2.0, 3.0, 4.0], dtype=float32) + a = np.array([1.0, 2.0, 3.0, 4.0], dtype=np.float32) p = self._loads(asbytes(s)) assert_equal(a, p) def test_version1_object(self): s = '\x80\x02cnumpy.core._internal\n_reconstruct\nq\x01cnumpy\nndarray\nq\x02K\x00\x85U\x01b\x87Rq\x03(K\x01K\x02\x85cnumpy\ndtype\nq\x04U\x02O8K\x00K\x01\x87Rq\x05(K\x01U\x01|NNJ\xff\xff\xff\xffJ\xff\xff\xff\xfftb\x89]q\x06(}q\x07U\x01aK\x01s}q\x08U\x01bK\x02setb.' - a = array([{'a':1}, {'b':2}]) + a = np.array([{'a':1}, {'b':2}]) p = self._loads(asbytes(s)) assert_equal(a, p) @@ -2458,62 +2608,62 @@ class TestPickling(TestCase): class TestFancyIndexing(TestCase): def test_list(self): - x = ones((1, 1)) + x = np.ones((1, 1)) x[:, [0]] = 2.0 - assert_array_equal(x, array([[2.0]])) + assert_array_equal(x, np.array([[2.0]])) - x = ones((1, 1, 1)) + x = np.ones((1, 1, 1)) x[:,:, [0]] = 2.0 - assert_array_equal(x, array([[[2.0]]])) + assert_array_equal(x, np.array([[[2.0]]])) def test_tuple(self): - x = ones((1, 1)) + x = np.ones((1, 1)) x[:, (0,)] = 2.0 - assert_array_equal(x, array([[2.0]])) - x = ones((1, 1, 1)) + assert_array_equal(x, np.array([[2.0]])) + x = np.ones((1, 1, 1)) x[:,:, (0,)] = 2.0 - assert_array_equal(x, array([[[2.0]]])) + assert_array_equal(x, np.array([[[2.0]]])) def test_mask(self): - x = array([1, 2, 3, 4]) - m = array([0, 1], bool) - assert_array_equal(x[m], array([2])) + x = np.array([1, 2, 3, 4]) + m = np.array([0, 1, 0, 0], bool) + assert_array_equal(x[m], np.array([2])) def test_mask2(self): - x = array([[1, 2, 3, 4], [5, 6, 7, 8]]) - m = array([0, 1], bool) - m2 = array([[0, 1], [1, 0]], bool) - m3 = array([[0, 1]], bool) - assert_array_equal(x[m], array([[5, 6, 7, 8]])) - assert_array_equal(x[m2], array([2, 5])) - assert_array_equal(x[m3], array([2])) + x = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) + m = np.array([0, 1], bool) + m2 = np.array([[0, 1, 0, 0], [1, 0, 0, 0]], bool) + m3 = np.array([[0, 1, 0, 0], [0, 0, 0, 0]], bool) + assert_array_equal(x[m], np.array([[5, 6, 7, 8]])) + assert_array_equal(x[m2], np.array([2, 5])) + assert_array_equal(x[m3], np.array([2])) def test_assign_mask(self): - x = array([1, 2, 3, 4]) - m = array([0, 1], bool) + x = np.array([1, 2, 3, 4]) + m = np.array([0, 1, 0, 0], bool) x[m] = 5 - assert_array_equal(x, array([1, 5, 3, 4])) + assert_array_equal(x, np.array([1, 5, 3, 4])) def test_assign_mask2(self): - xorig = array([[1, 2, 3, 4], [5, 6, 7, 8]]) - m = array([0, 1], bool) - m2 = array([[0, 1], [1, 0]], bool) - m3 = array([[0, 1]], bool) + xorig = np.array([[1, 2, 3, 4], [5, 6, 7, 8]]) + m = np.array([0, 1], bool) + m2 = np.array([[0, 1, 0, 0], [1, 0, 0, 0]], bool) + m3 = np.array([[0, 1, 0, 0], [0, 0, 0, 0]], bool) x = xorig.copy() x[m] = 10 - assert_array_equal(x, array([[1, 2, 3, 4], [10, 10, 10, 10]])) + assert_array_equal(x, np.array([[1, 2, 3, 4], [10, 10, 10, 10]])) x = xorig.copy() x[m2] = 10 - assert_array_equal(x, array([[1, 10, 3, 4], [10, 6, 7, 8]])) + assert_array_equal(x, np.array([[1, 10, 3, 4], [10, 6, 7, 8]])) x = xorig.copy() x[m3] = 10 - assert_array_equal(x, array([[1, 10, 3, 4], [5, 6, 7, 8]])) + assert_array_equal(x, np.array([[1, 10, 3, 4], [5, 6, 7, 8]])) class TestStringCompare(TestCase): def test_string(self): - g1 = array(["This", "is", "example"]) - g2 = array(["This", "was", "example"]) + g1 = np.array(["This", "is", "example"]) + g2 = np.array(["This", "was", "example"]) assert_array_equal(g1 == g2, [g1[i] == g2[i] for i in [0, 1, 2]]) assert_array_equal(g1 != g2, [g1[i] != g2[i] for i in [0, 1, 2]]) assert_array_equal(g1 <= g2, [g1[i] <= g2[i] for i in [0, 1, 2]]) @@ -2522,7 +2672,7 @@ class TestStringCompare(TestCase): assert_array_equal(g1 > g2, [g1[i] > g2[i] for i in [0, 1, 2]]) def test_mixed(self): - g1 = array(["spam", "spa", "spammer", "and eggs"]) + g1 = np.array(["spam", "spa", "spammer", "and eggs"]) g2 = "spam" assert_array_equal(g1 == g2, [x == g2 for x in g1]) assert_array_equal(g1 != g2, [x != g2 for x in g1]) @@ -2531,10 +2681,9 @@ class TestStringCompare(TestCase): assert_array_equal(g1 <= g2, [x <= g2 for x in g1]) assert_array_equal(g1 >= g2, [x >= g2 for x in g1]) - def test_unicode(self): - g1 = array([sixu("This"), sixu("is"), sixu("example")]) - g2 = array([sixu("This"), sixu("was"), sixu("example")]) + g1 = np.array([sixu("This"), sixu("is"), sixu("example")]) + g2 = np.array([sixu("This"), sixu("was"), sixu("example")]) assert_array_equal(g1 == g2, [g1[i] == g2[i] for i in [0, 1, 2]]) assert_array_equal(g1 != g2, [g1[i] != g2[i] for i in [0, 1, 2]]) assert_array_equal(g1 <= g2, [g1[i] <= g2[i] for i in [0, 1, 2]]) @@ -2576,12 +2725,24 @@ class TestArgmax(TestCase): np.datetime64('2015-11-20T12:20:59'), np.datetime64('1932-09-23T10:10:13'), np.datetime64('2014-10-10T03:50:30')], 3), + # Assorted tests with NaTs + ([np.datetime64('NaT'), + np.datetime64('NaT'), + np.datetime64('2010-01-03T05:14:12'), + np.datetime64('NaT'), + np.datetime64('2015-09-23T10:10:13'), + np.datetime64('1932-10-10T03:50:30')], 4), ([np.datetime64('2059-03-14T12:43:12'), np.datetime64('1996-09-21T14:43:15'), - np.datetime64('2001-10-15T04:10:32'), + np.datetime64('NaT'), np.datetime64('2022-12-25T16:02:16'), np.datetime64('1963-10-04T03:14:12'), np.datetime64('2013-05-08T18:15:23')], 0), + ([np.timedelta64(2, 's'), + np.timedelta64(1, 's'), + np.timedelta64('NaT', 's'), + np.timedelta64(3, 's')], 3), + ([np.timedelta64('NaT', 's')] * 3, 0), ([timedelta(days=5, seconds=14), timedelta(days=2, seconds=35), timedelta(days=-1, seconds=23)], 0), @@ -2608,12 +2769,12 @@ class TestArgmax(TestCase): aargmax = a.argmax(i) axes = list(range(a.ndim)) axes.remove(i) - assert_(all(amax == aargmax.choose(*a.transpose(i,*axes)))) + assert_(np.all(amax == aargmax.choose(*a.transpose(i,*axes)))) def test_combinations(self): for arr, pos in self.nan_arr: - assert_equal(np.argmax(arr), pos, err_msg="%r"%arr) - assert_equal(arr[np.argmax(arr)], np.max(arr), err_msg="%r"%arr) + assert_equal(np.argmax(arr), pos, err_msg="%r" % arr) + assert_equal(arr[np.argmax(arr)], np.max(arr), err_msg="%r" % arr) def test_output_shape(self): # see also gh-616 @@ -2643,17 +2804,27 @@ class TestArgmax(TestCase): a = np.random.normal(size=(2,3)) #check positional args - out1 = zeros(2, dtype=int) - out2 = zeros(2, dtype=int) + out1 = np.zeros(2, dtype=int) + out2 = np.zeros(2, dtype=int) assert_equal(a.argmax(1, out1), np.argmax(a, 1, out2)) assert_equal(out1, out2) #check keyword args - out1 = zeros(3, dtype=int) - out2 = zeros(3, dtype=int) + out1 = np.zeros(3, dtype=int) + out2 = np.zeros(3, dtype=int) assert_equal(a.argmax(out=out1, axis=0), np.argmax(a, out=out2, axis=0)) assert_equal(out1, out2) + def test_object_argmax_with_NULLs(self): + # See gh-6032 + a = np.empty(4, dtype='O') + ctypes.memset(a.ctypes.data, 0, a.nbytes) + assert_equal(a.argmax(), 0) + a[3] = 10 + assert_equal(a.argmax(), 3) + a[1] = 30 + assert_equal(a.argmax(), 1) + class TestArgmin(TestCase): @@ -2688,12 +2859,24 @@ class TestArgmin(TestCase): np.datetime64('2014-11-20T12:20:59'), np.datetime64('2015-09-23T10:10:13'), np.datetime64('1932-10-10T03:50:30')], 5), + # Assorted tests with NaTs + ([np.datetime64('NaT'), + np.datetime64('NaT'), + np.datetime64('2010-01-03T05:14:12'), + np.datetime64('NaT'), + np.datetime64('2015-09-23T10:10:13'), + np.datetime64('1932-10-10T03:50:30')], 5), ([np.datetime64('2059-03-14T12:43:12'), np.datetime64('1996-09-21T14:43:15'), - np.datetime64('2001-10-15T04:10:32'), + np.datetime64('NaT'), np.datetime64('2022-12-25T16:02:16'), np.datetime64('1963-10-04T03:14:12'), np.datetime64('2013-05-08T18:15:23')], 4), + ([np.timedelta64(2, 's'), + np.timedelta64(1, 's'), + np.timedelta64('NaT', 's'), + np.timedelta64(3, 's')], 1), + ([np.timedelta64('NaT', 's')] * 3, 0), ([timedelta(days=5, seconds=14), timedelta(days=2, seconds=35), timedelta(days=-1, seconds=23)], 2), @@ -2720,12 +2903,12 @@ class TestArgmin(TestCase): aargmin = a.argmin(i) axes = list(range(a.ndim)) axes.remove(i) - assert_(all(amin == aargmin.choose(*a.transpose(i,*axes)))) + assert_(np.all(amin == aargmin.choose(*a.transpose(i,*axes)))) def test_combinations(self): for arr, pos in self.nan_arr: - assert_equal(np.argmin(arr), pos, err_msg="%r"%arr) - assert_equal(arr[np.argmin(arr)], np.min(arr), err_msg="%r"%arr) + assert_equal(np.argmin(arr), pos, err_msg="%r" % arr) + assert_equal(arr[np.argmin(arr)], np.min(arr), err_msg="%r" % arr) def test_minimum_signed_integers(self): @@ -2769,19 +2952,30 @@ class TestArgmin(TestCase): a = np.random.normal(size=(2,3)) #check positional args - out1 = zeros(2, dtype=int) - out2 = ones(2, dtype=int) + out1 = np.zeros(2, dtype=int) + out2 = np.ones(2, dtype=int) assert_equal(a.argmin(1, out1), np.argmin(a, 1, out2)) assert_equal(out1, out2) #check keyword args - out1 = zeros(3, dtype=int) - out2 = ones(3, dtype=int) + out1 = np.zeros(3, dtype=int) + out2 = np.ones(3, dtype=int) assert_equal(a.argmin(out=out1, axis=0), np.argmin(a, out=out2, axis=0)) assert_equal(out1, out2) + def test_object_argmin_with_NULLs(self): + # See gh-6032 + a = np.empty(4, dtype='O') + ctypes.memset(a.ctypes.data, 0, a.nbytes) + assert_equal(a.argmin(), 0) + a[3] = 30 + assert_equal(a.argmin(), 3) + a[1] = 10 + assert_equal(a.argmin(), 1) + class TestMinMax(TestCase): + def test_scalar(self): assert_raises(ValueError, np.amax, 1, 1) assert_raises(ValueError, np.amin, 1, 1) @@ -2795,10 +2989,25 @@ class TestMinMax(TestCase): assert_raises(ValueError, np.amax, [1, 2, 3], 1000) assert_equal(np.amax([[1, 2, 3]], axis=1), 3) + def test_datetime(self): + # NaTs are ignored + for dtype in ('m8[s]', 'm8[Y]'): + a = np.arange(10).astype(dtype) + a[3] = 'NaT' + assert_equal(np.amin(a), a[0]) + assert_equal(np.amax(a), a[9]) + a[0] = 'NaT' + assert_equal(np.amin(a), a[1]) + assert_equal(np.amax(a), a[9]) + a.fill('NaT') + assert_equal(np.amin(a), a[0]) + assert_equal(np.amax(a), a[0]) + + class TestNewaxis(TestCase): def test_basic(self): - sk = array([0, -0.1, 0.1]) - res = 250*sk[:, newaxis] + sk = np.array([0, -0.1, 0.1]) + res = 250*sk[:, np.newaxis] assert_almost_equal(res.ravel(), 250*sk) @@ -2807,9 +3016,9 @@ class TestClip(TestCase): assert_(np.all(x >= cmin)) assert_(np.all(x <= cmax)) - def _clip_type(self,type_group,array_max, - clip_min,clip_max,inplace=False, - expected_min=None,expected_max=None): + def _clip_type(self, type_group, array_max, + clip_min, clip_max, inplace=False, + expected_min=None, expected_max=None): if expected_min is None: expected_min = clip_min if expected_max is None: @@ -2831,26 +3040,32 @@ class TestClip(TestCase): x = x.clip(clip_min, clip_max) byteorder = '=' - if x.dtype.byteorder == '|': byteorder = '|' + if x.dtype.byteorder == '|': + byteorder = '|' assert_equal(x.dtype.byteorder, byteorder) self._check_range(x, expected_min, expected_max) return x def test_basic(self): for inplace in [False, True]: - self._clip_type('float', 1024, -12.8, 100.2, inplace=inplace) - self._clip_type('float', 1024, 0, 0, inplace=inplace) + self._clip_type( + 'float', 1024, -12.8, 100.2, inplace=inplace) + self._clip_type( + 'float', 1024, 0, 0, inplace=inplace) - self._clip_type('int', 1024, -120, 100.5, inplace=inplace) - self._clip_type('int', 1024, 0, 0, inplace=inplace) + self._clip_type( + 'int', 1024, -120, 100.5, inplace=inplace) + self._clip_type( + 'int', 1024, 0, 0, inplace=inplace) - x = self._clip_type('uint', 1024, -120, 100, expected_min=0, - inplace=inplace) - x = self._clip_type('uint', 1024, 0, 0, inplace=inplace) + self._clip_type( + 'uint', 1024, 0, 0, inplace=inplace) + self._clip_type( + 'uint', 1024, -120, 100, inplace=inplace, expected_min=0) def test_record_array(self): rec = np.array([(-5, 2.0, 3.0), (5.0, 4.0, 3.0)], - dtype=[('x', '<f8'), ('y', '<f8'), ('z', '<f8')]) + dtype=[('x', '<f8'), ('y', '<f8'), ('z', '<f8')]) y = rec['x'].clip(-0.3, 0.5) self._check_range(y, -0.3, 0.5) @@ -3000,7 +3215,7 @@ class TestIO(object): shape = (2, 4, 3) rand = np.random.random self.x = rand(shape) + rand(shape).astype(np.complex)*1j - self.x[0,:, 1] = [nan, inf, -inf, nan] + self.x[0,:, 1] = [np.nan, np.inf, -np.inf, np.nan] self.dtype = self.x.dtype self.tempdir = tempfile.mkdtemp() self.filename = tempfile.mktemp(dir=self.tempdir) @@ -3015,26 +3230,26 @@ class TestIO(object): def test_uint64_fromstring(self): d = np.fromstring("9923372036854775807 104783749223640", - dtype=np.uint64, sep=' '); + dtype=np.uint64, sep=' ') e = np.array([9923372036854775807, 104783749223640], dtype=np.uint64) assert_array_equal(d, e) def test_int64_fromstring(self): d = np.fromstring("-25041670086757 104783749223640", - dtype=np.int64, sep=' '); + dtype=np.int64, sep=' ') e = np.array([-25041670086757, 104783749223640], dtype=np.int64) assert_array_equal(d, e) def test_empty_files_binary(self): f = open(self.filename, 'w') f.close() - y = fromfile(self.filename) + y = np.fromfile(self.filename) assert_(y.size == 0, "Array not empty") def test_empty_files_text(self): f = open(self.filename, 'w') f.close() - y = fromfile(self.filename, sep=" ") + y = np.fromfile(self.filename, sep=" ") assert_(y.size == 0, "Array not empty") def test_roundtrip_file(self): @@ -3119,7 +3334,7 @@ class TestIO(object): f = open(self.filename, 'r+b') f.read(2) - f.seek(0, 1) # seek between read&write required by ANSI C + f.seek(0, 1) # seek between read&write required by ANSI C np.array([0], dtype=np.float64).tofile(f) pos = f.tell() f.close() @@ -3136,13 +3351,16 @@ class TestIO(object): assert_array_equal(y, value) def test_nan(self): - self._check_from("nan +nan -nan NaN nan(foo) +NaN(BAR) -NAN(q_u_u_x_)", - [nan, nan, nan, nan, nan, nan, nan], - sep=' ') + self._check_from( + "nan +nan -nan NaN nan(foo) +NaN(BAR) -NAN(q_u_u_x_)", + [np.nan, np.nan, np.nan, np.nan, np.nan, np.nan, np.nan], + sep=' ') def test_inf(self): - self._check_from("inf +inf -inf infinity -Infinity iNfInItY -inF", - [inf, inf, -inf, inf, -inf, inf, -inf], sep=' ') + self._check_from( + "inf +inf -inf infinity -Infinity iNfInItY -inF", + [np.inf, np.inf, -np.inf, np.inf, -np.inf, np.inf, -np.inf], + sep=' ') def test_numbers(self): self._check_from("1.234 -1.234 .3 .3e55 -123133.1231e+133", @@ -3150,10 +3368,10 @@ class TestIO(object): def test_binary(self): self._check_from('\x00\x00\x80?\x00\x00\x00@\x00\x00@@\x00\x00\x80@', - array([1, 2, 3, 4]), + np.array([1, 2, 3, 4]), dtype='<f4') - @dec.slow # takes > 1 minute on mechanical hard drive + @dec.slow # takes > 1 minute on mechanical hard drive def test_big_binary(self): """Test workarounds for 32-bit limited fwrite, fseek, and ftell calls in windows. These normally would hang doing something like this. @@ -3226,7 +3444,9 @@ class TestIO(object): f = open(self.filename, 'r') s = f.read() f.close() - assert_equal(s, '1.51,2.0,3.51,4.0') + #assert_equal(s, '1.51,2.0,3.51,4.0') + y = np.array([float(p) for p in s.split(',')]) + assert_array_equal(x,y) def test_tofile_format(self): x = np.array([1.51, 2, 3.51, 4], dtype=float) @@ -3267,7 +3487,7 @@ class TestFromBuffer(object): class TestFlat(TestCase): def setUp(self): - a0 = arange(20.0) + a0 = np.arange(20.0) a = a0.reshape(4, 5) a0.shape = (4, 5) a.flags.writeable = False @@ -3323,6 +3543,7 @@ class TestResize(TestCase): x = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]]) y = x self.assertRaises(ValueError, x.resize, (5, 1)) + del y # avoid pyflakes unused variable warning. def test_int_shape(self): x = np.eye(3) @@ -3355,7 +3576,7 @@ class TestResize(TestCase): def test_obj_obj(self): # check memory is initialized on resize, gh-4857 - a = ones(10, dtype=[('k', object, 2)]) + a = np.ones(10, dtype=[('k', object, 2)]) a.resize(15,) assert_equal(a.shape, (15,)) assert_array_equal(a['k'][-5:], 0) @@ -3368,6 +3589,13 @@ class TestRecord(TestCase): dt.names = ['p', 'q'] assert_equal(dt.names, ['p', 'q']) + def test_multiple_field_name_occurrence(self): + def test_assign(): + dtype = np.dtype([("A", "f8"), ("B", "f8"), ("A", "f8")]) + + # Error raised when multiple fields have the same name + assert_raises(ValueError, test_assign) + if sys.version_info[0] >= 3: def test_bytes_fields(self): # Bytes are not allowed in field names and not recognized in titles @@ -3379,10 +3607,20 @@ class TestRecord(TestCase): assert_raises(ValueError, dt.__getitem__, asbytes('a')) x = np.array([(1,), (2,), (3,)], dtype=dt) - assert_raises(ValueError, x.__getitem__, asbytes('a')) + assert_raises(IndexError, x.__getitem__, asbytes('a')) y = x[0] assert_raises(IndexError, y.__getitem__, asbytes('a')) + + def test_multiple_field_name_unicode(self): + def test_assign_unicode(): + dt = np.dtype([("\u20B9", "f8"), + ("B", "f8"), + ("\u20B9", "f8")]) + + # Error raised when multiple fields have the same name(unicode included) + assert_raises(ValueError, test_assign_unicode) + else: def test_unicode_field_titles(self): # Unicode field titles are added to field dict on Py2 @@ -3412,8 +3650,8 @@ class TestRecord(TestCase): if is_py3: funcs = (str,) # byte string indexing fails gracefully - assert_raises(ValueError, a.__setitem__, asbytes('f1'), 1) - assert_raises(ValueError, a.__getitem__, asbytes('f1')) + assert_raises(IndexError, a.__setitem__, asbytes('f1'), 1) + assert_raises(IndexError, a.__getitem__, asbytes('f1')) assert_raises(IndexError, a['f1'].__setitem__, asbytes('sf1'), 1) assert_raises(IndexError, a['f1'].__getitem__, asbytes('sf1')) else: @@ -3447,7 +3685,7 @@ class TestRecord(TestCase): # view of subfield view/copy assert_equal(b[['f1', 'f2']][0].view(('i4', 2)).tolist(), (2, 3)) assert_equal(b[['f2', 'f1']][0].view(('i4', 2)).tolist(), (3, 2)) - view_dtype=[('f1', 'i4'), ('f3', [('', 'i4')])] + view_dtype = [('f1', 'i4'), ('f3', [('', 'i4')])] assert_equal(b[['f1', 'f3']][0].view(view_dtype).tolist(), (2, (1,))) # non-ascii unicode field indexing is well behaved if not is_py3: @@ -3459,7 +3697,7 @@ class TestRecord(TestCase): def test_field_names_deprecation(self): - def collect_warning_types(f, *args, **kwargs): + def collect_warnings(f, *args, **kwargs): with warnings.catch_warnings(record=True) as log: warnings.simplefilter("always") f(*args, **kwargs) @@ -3480,20 +3718,19 @@ class TestRecord(TestCase): # All the different functions raise a warning, but not an error, and # 'a' is not modified: - assert_equal(collect_warning_types(a[['f1', 'f2']].__setitem__, 0, (10, 20)), + assert_equal(collect_warnings(a[['f1', 'f2']].__setitem__, 0, (10, 20)), [FutureWarning]) assert_equal(a, b) # Views also warn subset = a[['f1', 'f2']] subset_view = subset.view() - assert_equal(collect_warning_types(subset_view['f1'].__setitem__, 0, 10), + assert_equal(collect_warnings(subset_view['f1'].__setitem__, 0, 10), [FutureWarning]) # But the write goes through: assert_equal(subset['f1'][0], 10) - # Only one warning per multiple field indexing, though (even if there are - # multiple views involved): - assert_equal(collect_warning_types(subset['f1'].__setitem__, 0, 10), - []) + # Only one warning per multiple field indexing, though (even if there + # are multiple views involved): + assert_equal(collect_warnings(subset['f1'].__setitem__, 0, 10), []) def test_record_hash(self): a = np.array([(1, 2), (1, 2)], dtype='i1,i2') @@ -3511,10 +3748,18 @@ class TestRecord(TestCase): a = np.array([(1, 2), (1, 2)], dtype='i1,i2') self.assertRaises(TypeError, hash, a[0]) + def test_empty_structure_creation(self): + # make sure these do not raise errors (gh-5631) + np.array([()], dtype={'names': [], 'formats': [], + 'offsets': [], 'itemsize': 12}) + np.array([(), (), (), (), ()], dtype={'names': [], 'formats': [], + 'offsets': [], 'itemsize': 12}) + class TestView(TestCase): def test_basic(self): - x = np.array([(1, 2, 3, 4), (5, 6, 7, 8)], dtype=[('r', np.int8), ('g', np.int8), - ('b', np.int8), ('a', np.int8)]) + x = np.array([(1, 2, 3, 4), (5, 6, 7, 8)], + dtype=[('r', np.int8), ('g', np.int8), + ('b', np.int8), ('a', np.int8)]) # We must be specific about the endianness here: y = x.view(dtype='<i4') # ... and again without the keyword. @@ -3616,26 +3861,25 @@ class TestStats(TestCase): assert_(res is tgt) def test_dtype_from_dtype(self): - icodes = np.typecodes['AllInteger'] - fcodes = np.typecodes['AllFloat'] mat = np.eye(3) # stats for integer types - # fixme: + # FIXME: # this needs definition as there are lots places along the line # where type casting may take place. + #for f in self.funcs: - #for c in icodes: - #tgt = np.dtype(c).type - #res = f(mat, axis=1, dtype=c).dtype.type - #assert_(res is tgt) - ## scalar case - #res = f(mat, axis=None, dtype=c).dtype.type - #assert_(res is tgt) + # for c in np.typecodes['AllInteger']: + # tgt = np.dtype(c).type + # res = f(mat, axis=1, dtype=c).dtype.type + # assert_(res is tgt) + # # scalar case + # res = f(mat, axis=None, dtype=c).dtype.type + # assert_(res is tgt) # stats for float types for f in self.funcs: - for c in fcodes: + for c in np.typecodes['AllFloat']: tgt = np.dtype(c).type res = f(mat, axis=1, dtype=c).dtype.type assert_(res is tgt) @@ -3709,7 +3953,6 @@ class TestStats(TestCase): res = _std(mat, axis=axis) assert_almost_equal(res, tgt) - def test_subclass(self): class TestArray(np.ndarray): def __new__(cls, data, info): @@ -3717,6 +3960,7 @@ class TestStats(TestCase): result = result.view(cls) result.info = info return result + def __array_finalize__(self, obj): self.info = getattr(obj, "info", '') @@ -3756,8 +4000,8 @@ class TestVdot(TestCase): assert_equal(np.vdot(b, b), True) def test_vdot_array_order(self): - a = array([[1, 2], [3, 4]], order='C') - b = array([[1, 2], [3, 4]], order='F') + a = np.array([[1, 2], [3, 4]], order='C') + b = np.array([[1, 2], [3, 4]], order='F') res = np.vdot(a, a) # integer arrays are exact @@ -3765,8 +4009,163 @@ class TestVdot(TestCase): assert_equal(np.vdot(b, a), res) assert_equal(np.vdot(b, b), res) + def test_vdot_uncontiguous(self): + for size in [2, 1000]: + # Different sizes match different branches in vdot. + a = np.zeros((size, 2, 2)) + b = np.zeros((size, 2, 2)) + a[:, 0, 0] = np.arange(size) + b[:, 0, 0] = np.arange(size) + 1 + # Make a and b uncontiguous: + a = a[..., 0] + b = b[..., 0] + + assert_equal(np.vdot(a, b), + np.vdot(a.flatten(), b.flatten())) + assert_equal(np.vdot(a, b.copy()), + np.vdot(a.flatten(), b.flatten())) + assert_equal(np.vdot(a.copy(), b), + np.vdot(a.flatten(), b.flatten())) + assert_equal(np.vdot(a.copy('F'), b), + np.vdot(a.flatten(), b.flatten())) + assert_equal(np.vdot(a, b.copy('F')), + np.vdot(a.flatten(), b.flatten())) + class TestDot(TestCase): + def setUp(self): + np.random.seed(128) + self.A = np.random.rand(4, 2) + self.b1 = np.random.rand(2, 1) + self.b2 = np.random.rand(2) + self.b3 = np.random.rand(1, 2) + self.b4 = np.random.rand(4) + self.N = 7 + + def test_dotmatmat(self): + A = self.A + res = np.dot(A.transpose(), A) + tgt = np.array([[1.45046013, 0.86323640], + [0.86323640, 0.84934569]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotmatvec(self): + A, b1 = self.A, self.b1 + res = np.dot(A, b1) + tgt = np.array([[0.32114320], [0.04889721], + [0.15696029], [0.33612621]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotmatvec2(self): + A, b2 = self.A, self.b2 + res = np.dot(A, b2) + tgt = np.array([0.29677940, 0.04518649, 0.14468333, 0.31039293]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecmat(self): + A, b4 = self.A, self.b4 + res = np.dot(b4, A) + tgt = np.array([1.23495091, 1.12222648]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecmat2(self): + b3, A = self.b3, self.A + res = np.dot(b3, A.transpose()) + tgt = np.array([[0.58793804, 0.08957460, 0.30605758, 0.62716383]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecmat3(self): + A, b4 = self.A, self.b4 + res = np.dot(A.transpose(), b4) + tgt = np.array([1.23495091, 1.12222648]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecvecouter(self): + b1, b3 = self.b1, self.b3 + res = np.dot(b1, b3) + tgt = np.array([[0.20128610, 0.08400440], [0.07190947, 0.03001058]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecvecinner(self): + b1, b3 = self.b1, self.b3 + res = np.dot(b3, b1) + tgt = np.array([[ 0.23129668]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotcolumnvect1(self): + b1 = np.ones((3, 1)) + b2 = [5.3] + res = np.dot(b1, b2) + tgt = np.array([5.3, 5.3, 5.3]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotcolumnvect2(self): + b1 = np.ones((3, 1)).transpose() + b2 = [6.2] + res = np.dot(b2, b1) + tgt = np.array([6.2, 6.2, 6.2]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecscalar(self): + np.random.seed(100) + b1 = np.random.rand(1, 1) + b2 = np.random.rand(1, 4) + res = np.dot(b1, b2) + tgt = np.array([[0.15126730, 0.23068496, 0.45905553, 0.00256425]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_dotvecscalar2(self): + np.random.seed(100) + b1 = np.random.rand(4, 1) + b2 = np.random.rand(1, 1) + res = np.dot(b1, b2) + tgt = np.array([[0.00256425],[0.00131359],[0.00200324],[ 0.00398638]]) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_all(self): + dims = [(), (1,), (1, 1)] + dout = [(), (1,), (1, 1), (1,), (), (1,), (1, 1), (1,), (1, 1)] + for dim, (dim1, dim2) in zip(dout, itertools.product(dims, dims)): + b1 = np.zeros(dim1) + b2 = np.zeros(dim2) + res = np.dot(b1, b2) + tgt = np.zeros(dim) + assert_(res.shape == tgt.shape) + assert_almost_equal(res, tgt, decimal=self.N) + + def test_vecobject(self): + class Vec(object): + def __init__(self, sequence=None): + if sequence is None: + sequence = [] + self.array = np.array(sequence) + + def __add__(self, other): + out = Vec() + out.array = self.array + other.array + return out + + def __sub__(self, other): + out = Vec() + out.array = self.array - other.array + return out + + def __mul__(self, other): # with scalar + out = Vec(self.array.copy()) + out.array *= other + return out + + def __rmul__(self, other): + return self*other + + U_non_cont = np.transpose([[1., 1.], [1., 2.]]) + U_cont = np.ascontiguousarray(U_non_cont) + x = np.array([Vec([1., 0.]), Vec([0., 1.])]) + zeros = np.array([Vec([0., 0.]), Vec([0., 0.])]) + zeros_test = np.dot(U_cont, x) - np.dot(U_non_cont, x) + assert_equal(zeros[0].array, zeros_test[0].array) + assert_equal(zeros[1].array, zeros_test[1].array) + def test_dot_2args(self): from numpy.core.multiarray import dot @@ -3792,8 +4191,8 @@ class TestDot(TestCase): assert_array_equal(r2, r) assert_(r is dot(f, v, out=r)) - v = v[:, 0].copy() # v.shape == (16,) - r = r[:, 0].copy() # r.shape == (1024,) + v = v[:, 0].copy() # v.shape == (16,) + r = r[:, 0].copy() # r.shape == (1024,) r2 = dot(f, v) assert_(r is dot(f, v, r)) assert_array_equal(r2, r) @@ -3829,8 +4228,8 @@ class TestDot(TestCase): assert_raises(ValueError, dot, f, v, r) def test_dot_array_order(self): - a = array([[1, 2], [3, 4]], order='C') - b = array([[1, 2], [3, 4]], order='F') + a = np.array([[1, 2], [3, 4]], order='C') + b = np.array([[1, 2], [3, 4]], order='F') res = np.dot(a, a) # integer arrays are exact @@ -3863,6 +4262,367 @@ class TestDot(TestCase): assert_raises(TypeError, np.dot, b, c) assert_raises(TypeError, c.dot, b) + def test_accelerate_framework_sgemv_fix(self): + + def aligned_array(shape, align, dtype, order='C'): + d = dtype(0) + N = np.prod(shape) + tmp = np.zeros(N * d.nbytes + align, dtype=np.uint8) + address = tmp.__array_interface__["data"][0] + for offset in range(align): + if (address + offset) % align == 0: + break + tmp = tmp[offset:offset+N*d.nbytes].view(dtype=dtype) + return tmp.reshape(shape, order=order) + + def as_aligned(arr, align, dtype, order='C'): + aligned = aligned_array(arr.shape, align, dtype, order) + aligned[:] = arr[:] + return aligned + + def assert_dot_close(A, X, desired): + assert_allclose(np.dot(A, X), desired, rtol=1e-5, atol=1e-7) + + m = aligned_array(100, 15, np.float32) + s = aligned_array((100, 100), 15, np.float32) + np.dot(s, m) # this will always segfault if the bug is present + + testdata = itertools.product((15,32), (10000,), (200,89), ('C','F')) + for align, m, n, a_order in testdata: + # Calculation in double precision + A_d = np.random.rand(m, n) + X_d = np.random.rand(n) + desired = np.dot(A_d, X_d) + # Calculation with aligned single precision + A_f = as_aligned(A_d, align, np.float32, order=a_order) + X_f = as_aligned(X_d, align, np.float32) + assert_dot_close(A_f, X_f, desired) + # Strided A rows + A_d_2 = A_d[::2] + desired = np.dot(A_d_2, X_d) + A_f_2 = A_f[::2] + assert_dot_close(A_f_2, X_f, desired) + # Strided A columns, strided X vector + A_d_22 = A_d_2[:, ::2] + X_d_2 = X_d[::2] + desired = np.dot(A_d_22, X_d_2) + A_f_22 = A_f_2[:, ::2] + X_f_2 = X_f[::2] + assert_dot_close(A_f_22, X_f_2, desired) + # Check the strides are as expected + if a_order == 'F': + assert_equal(A_f_22.strides, (8, 8 * m)) + else: + assert_equal(A_f_22.strides, (8 * n, 8)) + assert_equal(X_f_2.strides, (8,)) + # Strides in A rows + cols only + X_f_2c = as_aligned(X_f_2, align, np.float32) + assert_dot_close(A_f_22, X_f_2c, desired) + # Strides just in A cols + A_d_12 = A_d[:, ::2] + desired = np.dot(A_d_12, X_d_2) + A_f_12 = A_f[:, ::2] + assert_dot_close(A_f_12, X_f_2c, desired) + # Strides in A cols and X + assert_dot_close(A_f_12, X_f_2, desired) + + +class MatmulCommon(): + """Common tests for '@' operator and numpy.matmul. + + Do not derive from TestCase to avoid nose running it. + + """ + # Should work with these types. Will want to add + # "O" at some point + types = "?bhilqBHILQefdgFDG" + + def test_exceptions(self): + dims = [ + ((1,), (2,)), # mismatched vector vector + ((2, 1,), (2,)), # mismatched matrix vector + ((2,), (1, 2)), # mismatched vector matrix + ((1, 2), (3, 1)), # mismatched matrix matrix + ((1,), ()), # vector scalar + ((), (1)), # scalar vector + ((1, 1), ()), # matrix scalar + ((), (1, 1)), # scalar matrix + ((2, 2, 1), (3, 1, 2)), # cannot broadcast + ] + + for dt, (dm1, dm2) in itertools.product(self.types, dims): + a = np.ones(dm1, dtype=dt) + b = np.ones(dm2, dtype=dt) + assert_raises(ValueError, self.matmul, a, b) + + def test_shapes(self): + dims = [ + ((1, 1), (2, 1, 1)), # broadcast first argument + ((2, 1, 1), (1, 1)), # broadcast second argument + ((2, 1, 1), (2, 1, 1)), # matrix stack sizes match + ] + + for dt, (dm1, dm2) in itertools.product(self.types, dims): + a = np.ones(dm1, dtype=dt) + b = np.ones(dm2, dtype=dt) + res = self.matmul(a, b) + assert_(res.shape == (2, 1, 1)) + + # vector vector returns scalars. + for dt in self.types: + a = np.ones((2,), dtype=dt) + b = np.ones((2,), dtype=dt) + c = self.matmul(a, b) + assert_(np.array(c).shape == ()) + + def test_result_types(self): + mat = np.ones((1,1)) + vec = np.ones((1,)) + for dt in self.types: + m = mat.astype(dt) + v = vec.astype(dt) + for arg in [(m, v), (v, m), (m, m)]: + res = self.matmul(*arg) + assert_(res.dtype == dt) + + # vector vector returns scalars + res = self.matmul(v, v) + assert_(type(res) is np.dtype(dt).type) + + def test_vector_vector_values(self): + vec = np.array([1, 2]) + tgt = 5 + for dt in self.types[1:]: + v1 = vec.astype(dt) + res = self.matmul(v1, v1) + assert_equal(res, tgt) + + # boolean type + vec = np.array([True, True], dtype='?') + res = self.matmul(vec, vec) + assert_equal(res, True) + + def test_vector_matrix_values(self): + vec = np.array([1, 2]) + mat1 = np.array([[1, 2], [3, 4]]) + mat2 = np.stack([mat1]*2, axis=0) + tgt1 = np.array([7, 10]) + tgt2 = np.stack([tgt1]*2, axis=0) + for dt in self.types[1:]: + v = vec.astype(dt) + m1 = mat1.astype(dt) + m2 = mat2.astype(dt) + res = self.matmul(v, m1) + assert_equal(res, tgt1) + res = self.matmul(v, m2) + assert_equal(res, tgt2) + + # boolean type + vec = np.array([True, False]) + mat1 = np.array([[True, False], [False, True]]) + mat2 = np.stack([mat1]*2, axis=0) + tgt1 = np.array([True, False]) + tgt2 = np.stack([tgt1]*2, axis=0) + + res = self.matmul(vec, mat1) + assert_equal(res, tgt1) + res = self.matmul(vec, mat2) + assert_equal(res, tgt2) + + def test_matrix_vector_values(self): + vec = np.array([1, 2]) + mat1 = np.array([[1, 2], [3, 4]]) + mat2 = np.stack([mat1]*2, axis=0) + tgt1 = np.array([5, 11]) + tgt2 = np.stack([tgt1]*2, axis=0) + for dt in self.types[1:]: + v = vec.astype(dt) + m1 = mat1.astype(dt) + m2 = mat2.astype(dt) + res = self.matmul(m1, v) + assert_equal(res, tgt1) + res = self.matmul(m2, v) + assert_equal(res, tgt2) + + # boolean type + vec = np.array([True, False]) + mat1 = np.array([[True, False], [False, True]]) + mat2 = np.stack([mat1]*2, axis=0) + tgt1 = np.array([True, False]) + tgt2 = np.stack([tgt1]*2, axis=0) + + res = self.matmul(vec, mat1) + assert_equal(res, tgt1) + res = self.matmul(vec, mat2) + assert_equal(res, tgt2) + + def test_matrix_matrix_values(self): + mat1 = np.array([[1, 2], [3, 4]]) + mat2 = np.array([[1, 0], [1, 1]]) + mat12 = np.stack([mat1, mat2], axis=0) + mat21 = np.stack([mat2, mat1], axis=0) + tgt11 = np.array([[7, 10], [15, 22]]) + tgt12 = np.array([[3, 2], [7, 4]]) + tgt21 = np.array([[1, 2], [4, 6]]) + tgt12_21 = np.stack([tgt12, tgt21], axis=0) + tgt11_12 = np.stack((tgt11, tgt12), axis=0) + tgt11_21 = np.stack((tgt11, tgt21), axis=0) + for dt in self.types[1:]: + m1 = mat1.astype(dt) + m2 = mat2.astype(dt) + m12 = mat12.astype(dt) + m21 = mat21.astype(dt) + + # matrix @ matrix + res = self.matmul(m1, m2) + assert_equal(res, tgt12) + res = self.matmul(m2, m1) + assert_equal(res, tgt21) + + # stacked @ matrix + res = self.matmul(m12, m1) + assert_equal(res, tgt11_21) + + # matrix @ stacked + res = self.matmul(m1, m12) + assert_equal(res, tgt11_12) + + # stacked @ stacked + res = self.matmul(m12, m21) + assert_equal(res, tgt12_21) + + # boolean type + m1 = np.array([[1, 1], [0, 0]], dtype=np.bool_) + m2 = np.array([[1, 0], [1, 1]], dtype=np.bool_) + m12 = np.stack([m1, m2], axis=0) + m21 = np.stack([m2, m1], axis=0) + tgt11 = m1 + tgt12 = m1 + tgt21 = np.array([[1, 1], [1, 1]], dtype=np.bool_) + tgt12_21 = np.stack([tgt12, tgt21], axis=0) + tgt11_12 = np.stack((tgt11, tgt12), axis=0) + tgt11_21 = np.stack((tgt11, tgt21), axis=0) + + # matrix @ matrix + res = self.matmul(m1, m2) + assert_equal(res, tgt12) + res = self.matmul(m2, m1) + assert_equal(res, tgt21) + + # stacked @ matrix + res = self.matmul(m12, m1) + assert_equal(res, tgt11_21) + + # matrix @ stacked + res = self.matmul(m1, m12) + assert_equal(res, tgt11_12) + + # stacked @ stacked + res = self.matmul(m12, m21) + assert_equal(res, tgt12_21) + + def test_numpy_ufunc_override(self): + + class A(np.ndarray): + def __new__(cls, *args, **kwargs): + return np.array(*args, **kwargs).view(cls) + + def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs): + return "A" + + class B(np.ndarray): + def __new__(cls, *args, **kwargs): + return np.array(*args, **kwargs).view(cls) + + def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs): + return NotImplemented + + a = A([1, 2]) + b = B([1, 2]) + c = np.ones(2) + assert_equal(self.matmul(a, b), "A") + assert_equal(self.matmul(b, a), "A") + assert_raises(TypeError, self.matmul, b, c) + + +class TestMatmul(MatmulCommon, TestCase): + matmul = np.matmul + + def test_out_arg(self): + a = np.ones((2, 2), dtype=np.float) + b = np.ones((2, 2), dtype=np.float) + tgt = np.full((2,2), 2, dtype=np.float) + + # test as positional argument + msg = "out positional argument" + out = np.zeros((2, 2), dtype=np.float) + self.matmul(a, b, out) + assert_array_equal(out, tgt, err_msg=msg) + + # test as keyword argument + msg = "out keyword argument" + out = np.zeros((2, 2), dtype=np.float) + self.matmul(a, b, out=out) + assert_array_equal(out, tgt, err_msg=msg) + + # test out with not allowed type cast (safe casting) + # einsum and cblas raise different error types, so + # use Exception. + msg = "out argument with illegal cast" + out = np.zeros((2, 2), dtype=np.int32) + assert_raises(Exception, self.matmul, a, b, out=out) + + # skip following tests for now, cblas does not allow non-contiguous + # outputs and consistency with dot would require same type, + # dimensions, subtype, and c_contiguous. + + # test out with allowed type cast + # msg = "out argument with allowed cast" + # out = np.zeros((2, 2), dtype=np.complex128) + # self.matmul(a, b, out=out) + # assert_array_equal(out, tgt, err_msg=msg) + + # test out non-contiguous + # msg = "out argument with non-contiguous layout" + # c = np.zeros((2, 2, 2), dtype=np.float) + # self.matmul(a, b, out=c[..., 0]) + # assert_array_equal(c, tgt, err_msg=msg) + + +if sys.version_info[:2] >= (3, 5): + class TestMatmulOperator(MatmulCommon, TestCase): + import operator + matmul = operator.matmul + + def test_array_priority_override(self): + + class A(object): + __array_priority__ = 1000 + + def __matmul__(self, other): + return "A" + + def __rmatmul__(self, other): + return "A" + + a = A() + b = np.ones(2) + assert_equal(self.matmul(a, b), "A") + assert_equal(self.matmul(b, a), "A") + + def test_matmul_inplace(): + # It would be nice to support in-place matmul eventually, but for now + # we don't have a working implementation, so better just to error out + # and nudge people to writing "a = a @ b". + a = np.eye(3) + b = np.eye(3) + assert_raises(TypeError, a.__imatmul__, b) + import operator + assert_raises(TypeError, operator.imatmul, a, b) + # we avoid writing the token `exec` so as not to crash python 2's + # parser + exec_ = getattr(builtins, "exec") + assert_raises(TypeError, exec_, "a @= b", globals(), locals()) class TestInner(TestCase): @@ -3877,8 +4637,8 @@ class TestInner(TestCase): # Ticket 844. # Inner product of a vector with itself segfaults or give # meaningless result - a = zeros(shape = (1, 80), dtype = float64) - p = inner(a, a) + a = np.zeros(shape=(1, 80), dtype=np.float64) + p = np.inner(a, a) assert_almost_equal(p, 0, decimal=14) @@ -3903,10 +4663,10 @@ class TestSummarization(TestCase): class TestChoose(TestCase): def setUp(self): - self.x = 2*ones((3,), dtype=int) - self.y = 3*ones((3,), dtype=int) - self.x2 = 2*ones((2, 3), dtype=int) - self.y2 = 3*ones((2, 3), dtype=int) + self.x = 2*np.ones((3,), dtype=int) + self.y = 3*np.ones((3,), dtype=int) + self.x2 = 2*np.ones((2, 3), dtype=int) + self.y2 = 3*np.ones((2, 3), dtype=int) self.ind = [0, 0, 1] def test_basic(self): @@ -4253,6 +5013,7 @@ class TestPEP3118Dtype(object): # Trailing padding should be included, *and*, the item size # should match the alignment if in aligned mode align = np.dtype('i').alignment + def VV(n): return 'V%d' % (align*(1 + (n-1)//align)) @@ -4296,6 +5057,7 @@ class TestPEP3118Dtype(object): def test_intra_padding(self): # Natively aligned sub-arrays may require some internal padding align = np.dtype('i').alignment + def VV(n): return 'V%d' % (align*(1 + (n-1)//align)) @@ -4349,7 +5111,7 @@ class TestNewBufferProtocol(object): ('n', 'V3'), ('o', '?'), ('p', np.half), - ] + ] x = np.array( [(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, asbytes('aaaa'), 'bbbb', asbytes('xxx'), True, 1.0)], @@ -4392,14 +5154,14 @@ class TestNewBufferProtocol(object): half_list = [ 1.0, -2.0, - 6.5504 * 10**4, # (max half precision) - 2**-14, # ~= 6.10352 * 10**-5 (minimum positive normal) - 2**-24, # ~= 5.96046 * 10**-8 (minimum strictly positive subnormal) + 6.5504 * 10**4, # (max half precision) + 2**-14, # ~= 6.10352 * 10**-5 (minimum positive normal) + 2**-24, # ~= 5.96046 * 10**-8 (minimum strictly positive subnormal) 0.0, -0.0, float('+inf'), float('-inf'), - 0.333251953125, # ~= 1/3 + 0.333251953125, # ~= 1/3 ] x = np.array(half_list, dtype='>e') @@ -4486,7 +5248,7 @@ class TestNewBufferProtocol(object): ('n', 'V3'), ('o', '?'), ('p', np.half), - ] + ] x = np.array( [(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, asbytes('aaaa'), 'bbbb', asbytes(' '), True, 1.0)], @@ -4496,8 +5258,8 @@ class TestNewBufferProtocol(object): assert_equal(y.ndim, 1) assert_equal(y.suboffsets, EMPTY) - sz = sum([dtype(b).itemsize for a, b in dt]) - if dtype('l').itemsize == 4: + sz = sum([np.dtype(b).itemsize for a, b in dt]) + if np.dtype('l').itemsize == 4: assert_equal(y.format, 'T{b:a:=h:b:i:c:l:d:q:dx:B:e:@H:f:=I:g:L:h:Q:hx:f:i:d:j:^g:k:=Zf:ix:Zd:jx:^Zg:kx:4s:l:=4w:m:3x:n:?:o:@e:p:}') else: assert_equal(y.format, 'T{b:a:=h:b:i:c:q:d:q:dx:B:e:@H:f:=I:g:Q:h:Q:hx:f:i:d:j:^g:k:=Zf:ix:Zd:jx:^Zg:kx:4s:l:=4w:m:3x:n:?:o:@e:p:}') @@ -4547,6 +5309,7 @@ class TestNewBufferProtocol(object): c = np.asarray(b) count_2 = sys.getrefcount(np.core._internal) assert_equal(count_1, count_2) + del c # avoid pyflakes unused variable warning. def test_padded_struct_array(self): dt1 = np.dtype( @@ -4598,11 +5361,10 @@ class TestArrayAttributeDeletion(object): def test_multiarray_writable_attributes_deletion(self): """ticket #2046, should not seqfault, raise AttributeError""" a = np.ones(2) - attr = ['shape', 'strides', 'data', 'dtype', 'real', 'imag', 'flat'] + attr = ['shape', 'strides', 'data', 'dtype', 'real', 'imag', 'flat'] for s in attr: assert_raises(AttributeError, delattr, a, s) - def test_multiarray_not_writable_attributes_deletion(self): a = np.ones(2) attr = ["ndim", "flags", "itemsize", "size", "nbytes", "base", @@ -4611,14 +5373,12 @@ class TestArrayAttributeDeletion(object): for s in attr: assert_raises(AttributeError, delattr, a, s) - def test_multiarray_flags_writable_attribute_deletion(self): a = np.ones(2).flags attr = ['updateifcopy', 'aligned', 'writeable'] for s in attr: assert_raises(AttributeError, delattr, a, s) - def test_multiarray_flags_not_writable_attribute_deletion(self): a = np.ones(2).flags attr = ["contiguous", "c_contiguous", "f_contiguous", "fortran", @@ -4633,12 +5393,15 @@ def test_array_interface(): class Foo(object): def __init__(self, value): self.value = value - self.iface = {'typestr' : '=f8'} + self.iface = {'typestr': '=f8'} + def __float__(self): return float(self.value) + @property def __array_interface__(self): return self.iface + f = Foo(0.5) assert_equal(np.array(f), 0.5) assert_equal(np.array([f]), [0.5]) @@ -4691,21 +5454,21 @@ class TestMapIter(TestCase): # The actual tests are within the C code in # multiarray/multiarray_tests.c.src - a = arange(12).reshape((3, 4)).astype(float) + a = np.arange(12).reshape((3, 4)).astype(float) index = ([1, 1, 2, 0], [0, 0, 2, 3]) vals = [50, 50, 30, 16] test_inplace_increment(a, index, vals) - assert_equal(a, [[ 0., 1., 2., 19.,], - [ 104., 5., 6., 7.,], - [ 8., 9., 40., 11.,]]) + assert_equal(a, [[0.00, 1., 2.0, 19.], + [104., 5., 6.0, 7.0], + [8.00, 9., 40., 11.]]) - b = arange(6).astype(float) - index = (array([1, 2, 0]),) + b = np.arange(6).astype(float) + index = (np.array([1, 2, 0]),) vals = [50, 4, 100.1] test_inplace_increment(b, index, vals) - assert_equal(b, [ 100.1, 51., 6., 3., 4., 5. ]) + assert_equal(b, [100.1, 51., 6., 3., 4., 5.]) class TestAsCArray(TestCase): @@ -4725,153 +5488,6 @@ class TestAsCArray(TestCase): assert_equal(array[1, 2, 3], from_c) -class PriorityNdarray(): - __array_priority__ = 1000 - - def __init__(self, array): - self.array = array - - def __lt__(self, array): - if isinstance(array, PriorityNdarray): - array = array.array - return PriorityNdarray(self.array < array) - - def __gt__(self, array): - if isinstance(array, PriorityNdarray): - array = array.array - return PriorityNdarray(self.array > array) - - def __le__(self, array): - if isinstance(array, PriorityNdarray): - array = array.array - return PriorityNdarray(self.array <= array) - - def __ge__(self, array): - if isinstance(array, PriorityNdarray): - array = array.array - return PriorityNdarray(self.array >= array) - - def __eq__(self, array): - if isinstance(array, PriorityNdarray): - array = array.array - return PriorityNdarray(self.array == array) - - def __ne__(self, array): - if isinstance(array, PriorityNdarray): - array = array.array - return PriorityNdarray(self.array != array) - - -class TestArrayPriority(TestCase): - def test_lt(self): - l = np.asarray([0., -1., 1.], dtype=dtype) - r = np.asarray([0., 1., -1.], dtype=dtype) - lp = PriorityNdarray(l) - rp = PriorityNdarray(r) - res1 = l < r - res2 = l < rp - res3 = lp < r - res4 = lp < rp - - assert_array_equal(res1, res2.array) - assert_array_equal(res1, res3.array) - assert_array_equal(res1, res4.array) - assert_(isinstance(res1, np.ndarray)) - assert_(isinstance(res2, PriorityNdarray)) - assert_(isinstance(res3, PriorityNdarray)) - assert_(isinstance(res4, PriorityNdarray)) - - def test_gt(self): - l = np.asarray([0., -1., 1.], dtype=dtype) - r = np.asarray([0., 1., -1.], dtype=dtype) - lp = PriorityNdarray(l) - rp = PriorityNdarray(r) - res1 = l > r - res2 = l > rp - res3 = lp > r - res4 = lp > rp - - assert_array_equal(res1, res2.array) - assert_array_equal(res1, res3.array) - assert_array_equal(res1, res4.array) - assert_(isinstance(res1, np.ndarray)) - assert_(isinstance(res2, PriorityNdarray)) - assert_(isinstance(res3, PriorityNdarray)) - assert_(isinstance(res4, PriorityNdarray)) - - def test_le(self): - l = np.asarray([0., -1., 1.], dtype=dtype) - r = np.asarray([0., 1., -1.], dtype=dtype) - lp = PriorityNdarray(l) - rp = PriorityNdarray(r) - res1 = l <= r - res2 = l <= rp - res3 = lp <= r - res4 = lp <= rp - - assert_array_equal(res1, res2.array) - assert_array_equal(res1, res3.array) - assert_array_equal(res1, res4.array) - assert_(isinstance(res1, np.ndarray)) - assert_(isinstance(res2, PriorityNdarray)) - assert_(isinstance(res3, PriorityNdarray)) - assert_(isinstance(res4, PriorityNdarray)) - - def test_ge(self): - l = np.asarray([0., -1., 1.], dtype=dtype) - r = np.asarray([0., 1., -1.], dtype=dtype) - lp = PriorityNdarray(l) - rp = PriorityNdarray(r) - res1 = l >= r - res2 = l >= rp - res3 = lp >= r - res4 = lp >= rp - - assert_array_equal(res1, res2.array) - assert_array_equal(res1, res3.array) - assert_array_equal(res1, res4.array) - assert_(isinstance(res1, np.ndarray)) - assert_(isinstance(res2, PriorityNdarray)) - assert_(isinstance(res3, PriorityNdarray)) - assert_(isinstance(res4, PriorityNdarray)) - - def test_eq(self): - l = np.asarray([0., -1., 1.], dtype=dtype) - r = np.asarray([0., 1., -1.], dtype=dtype) - lp = PriorityNdarray(l) - rp = PriorityNdarray(r) - res1 = l == r - res2 = l == rp - res3 = lp == r - res4 = lp == rp - - assert_array_equal(res1, res2.array) - assert_array_equal(res1, res3.array) - assert_array_equal(res1, res4.array) - assert_(isinstance(res1, np.ndarray)) - assert_(isinstance(res2, PriorityNdarray)) - assert_(isinstance(res3, PriorityNdarray)) - assert_(isinstance(res4, PriorityNdarray)) - - def test_ne(self): - l = np.asarray([0., -1., 1.], dtype=dtype) - r = np.asarray([0., 1., -1.], dtype=dtype) - lp = PriorityNdarray(l) - rp = PriorityNdarray(r) - res1 = l != r - res2 = l != rp - res3 = lp != r - res4 = lp != rp - - assert_array_equal(res1, res2.array) - assert_array_equal(res1, res3.array) - assert_array_equal(res1, res4.array) - assert_(isinstance(res1, np.ndarray)) - assert_(isinstance(res2, PriorityNdarray)) - assert_(isinstance(res3, PriorityNdarray)) - assert_(isinstance(res4, PriorityNdarray)) - - class TestConversion(TestCase): def test_array_scalar_relational_operation(self): #All integer @@ -4957,7 +5573,7 @@ class TestWhere(TestCase): nan = float('NaN') e = np.array(['5z', '0l', nan, 'Wz', nan, nan, 'Xq', 'cs', nan, nan, 'QN', nan, nan, 'Fd', nan, nan, 'kp', nan, '36', 'i1'], - dtype=object); + dtype=object) m = np.array([0,0,1,0,1,1,0,0,1,1,0,1,1,0,1,1,0,1,0,0], dtype=bool) r = e[:] @@ -4971,15 +5587,15 @@ class TestWhere(TestCase): assert_array_equal(np.where(m, e, e), e) # minimal dtype result with NaN scalar (e.g required by pandas) - d = np.array([1., 2.], dtype=np.float32) - e = float('NaN') + d = np.array([1., 2.], dtype=np.float32) + e = float('NaN') assert_equal(np.where(True, d, e).dtype, np.float32) - e = float('Infinity') + e = float('Infinity') assert_equal(np.where(True, d, e).dtype, np.float32) - e = float('-Infinity') + e = float('-Infinity') assert_equal(np.where(True, d, e).dtype, np.float32) # also check upcast - e = float(1e150) + e = float(1e150) assert_equal(np.where(True, d, e).dtype, np.float64) def test_ndim(self): @@ -5000,7 +5616,7 @@ class TestWhere(TestCase): c = np.array([False, True, False, False, False, False, True, False, False, False, True, False]) a = np.uint32(1) - b = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.], + b = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.], dtype=np.float64) r = np.array([5., 1., 3., 2., -1., -4., 1., -10., 10., 1., 1., 3.], dtype=np.float64) @@ -5026,7 +5642,7 @@ class TestWhere(TestCase): r = np.array([5., 1., 3., 2., -1., -4., 1., -10., 10., 1., 1., 3.], dtype=np.float64) a = np.ones(1, dtype='>i4') - b = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.], + b = np.array([5., 0., 3., 2., -1., -4., 0., -10., 10., 1., 0., 3.], dtype=np.float64) assert_equal(np.where(c, a, b), r) @@ -5108,10 +5724,223 @@ class TestSizeOf(TestCase): class TestHashing(TestCase): + def test_arrays_not_hashable(self): + x = np.ones(3) + assert_raises(TypeError, hash, x) + def test_collections_hashable(self): x = np.array([]) self.assertFalse(isinstance(x, collections.Hashable)) +from numpy.core._internal import _view_is_safe + +class TestObjViewSafetyFuncs(TestCase): + def test_view_safety(self): + psize = np.dtype('p').itemsize + + # creates dtype but with extra character code - for missing 'p' fields + def mtype(s): + n, offset, fields = 0, 0, [] + for c in s.split(','): # subarrays won't work + if c != '-': + fields.append(('f{0}'.format(n), c, offset)) + n += 1 + offset += np.dtype(c).itemsize if c != '-' else psize + + names, formats, offsets = zip(*fields) + return np.dtype({'names': names, 'formats': formats, + 'offsets': offsets, 'itemsize': offset}) + + # test nonequal itemsizes with objects: + # these should succeed: + _view_is_safe(np.dtype('O,p,O,p'), np.dtype('O,p,O,p,O,p')) + _view_is_safe(np.dtype('O,O'), np.dtype('O,O,O')) + # these should fail: + assert_raises(TypeError, _view_is_safe, np.dtype('O,O,p'), np.dtype('O,O')) + assert_raises(TypeError, _view_is_safe, np.dtype('O,O,p'), np.dtype('O,p')) + assert_raises(TypeError, _view_is_safe, np.dtype('O,O,p'), np.dtype('p,O')) + + # test nonequal itemsizes with missing fields: + # these should succeed: + _view_is_safe(mtype('-,p,-,p'), mtype('-,p,-,p,-,p')) + _view_is_safe(np.dtype('p,p'), np.dtype('p,p,p')) + # these should fail: + assert_raises(TypeError, _view_is_safe, mtype('p,p,-'), mtype('p,p')) + assert_raises(TypeError, _view_is_safe, mtype('p,p,-'), mtype('p,-')) + assert_raises(TypeError, _view_is_safe, mtype('p,p,-'), mtype('-,p')) + + # scans through positions at which we can view a type + def scanView(d1, otype): + goodpos = [] + for shift in range(d1.itemsize - np.dtype(otype).itemsize+1): + d2 = np.dtype({'names': ['f0'], 'formats': [otype], + 'offsets': [shift], 'itemsize': d1.itemsize}) + try: + _view_is_safe(d1, d2) + except TypeError: + pass + else: + goodpos.append(shift) + return goodpos + + # test partial overlap with object field + assert_equal(scanView(np.dtype('p,O,p,p,O,O'), 'p'), + [0] + list(range(2*psize, 3*psize+1))) + assert_equal(scanView(np.dtype('p,O,p,p,O,O'), 'O'), + [psize, 4*psize, 5*psize]) + + # test partial overlap with missing field + assert_equal(scanView(mtype('p,-,p,p,-,-'), 'p'), + [0] + list(range(2*psize, 3*psize+1))) + + # test nested structures with objects: + nestedO = np.dtype([('f0', 'p'), ('f1', 'p,O,p')]) + assert_equal(scanView(nestedO, 'p'), list(range(psize+1)) + [3*psize]) + assert_equal(scanView(nestedO, 'O'), [2*psize]) + + # test nested structures with missing fields: + nestedM = np.dtype([('f0', 'p'), ('f1', mtype('p,-,p'))]) + assert_equal(scanView(nestedM, 'p'), list(range(psize+1)) + [3*psize]) + + # test subarrays with objects + subarrayO = np.dtype('p,(2,3)O,p') + assert_equal(scanView(subarrayO, 'p'), [0, 7*psize]) + assert_equal(scanView(subarrayO, 'O'), + list(range(psize, 6*psize+1, psize))) + + #test dtype with overlapping fields + overlapped = np.dtype({'names': ['f0', 'f1', 'f2', 'f3'], + 'formats': ['p', 'p', 'p', 'p'], + 'offsets': [0, 1, 3*psize-1, 3*psize], + 'itemsize': 4*psize}) + assert_equal(scanView(overlapped, 'p'), [0, 1, 3*psize-1, 3*psize]) + + +class TestArrayPriority(TestCase): + # This will go away when __array_priority__ is settled, meanwhile + # it serves to check unintended changes. + op = operator + binary_ops = [ + op.pow, op.add, op.sub, op.mul, op.floordiv, op.truediv, op.mod, + op.and_, op.or_, op.xor, op.lshift, op.rshift, op.mod, op.gt, + op.ge, op.lt, op.le, op.ne, op.eq + ] + + if sys.version_info[0] < 3: + binary_ops.append(op.div) + + class Foo(np.ndarray): + __array_priority__ = 100. + + def __new__(cls, *args, **kwargs): + return np.array(*args, **kwargs).view(cls) + + class Bar(np.ndarray): + __array_priority__ = 101. + + def __new__(cls, *args, **kwargs): + return np.array(*args, **kwargs).view(cls) + + class Other(object): + __array_priority__ = 1000. + + def _all(self, other): + return self.__class__() + + __add__ = __radd__ = _all + __sub__ = __rsub__ = _all + __mul__ = __rmul__ = _all + __pow__ = __rpow__ = _all + __div__ = __rdiv__ = _all + __mod__ = __rmod__ = _all + __truediv__ = __rtruediv__ = _all + __floordiv__ = __rfloordiv__ = _all + __and__ = __rand__ = _all + __xor__ = __rxor__ = _all + __or__ = __ror__ = _all + __lshift__ = __rlshift__ = _all + __rshift__ = __rrshift__ = _all + __eq__ = _all + __ne__ = _all + __gt__ = _all + __ge__ = _all + __lt__ = _all + __le__ = _all + + def test_ndarray_subclass(self): + a = np.array([1, 2]) + b = self.Bar([1, 2]) + for f in self.binary_ops: + msg = repr(f) + assert_(isinstance(f(a, b), self.Bar), msg) + assert_(isinstance(f(b, a), self.Bar), msg) + + def test_ndarray_other(self): + a = np.array([1, 2]) + b = self.Other() + for f in self.binary_ops: + msg = repr(f) + assert_(isinstance(f(a, b), self.Other), msg) + assert_(isinstance(f(b, a), self.Other), msg) + + def test_subclass_subclass(self): + a = self.Foo([1, 2]) + b = self.Bar([1, 2]) + for f in self.binary_ops: + msg = repr(f) + assert_(isinstance(f(a, b), self.Bar), msg) + assert_(isinstance(f(b, a), self.Bar), msg) + + def test_subclass_other(self): + a = self.Foo([1, 2]) + b = self.Other() + for f in self.binary_ops: + msg = repr(f) + assert_(isinstance(f(a, b), self.Other), msg) + assert_(isinstance(f(b, a), self.Other), msg) + + +class TestBytestringArrayNonzero(TestCase): + + def test_empty_bstring_array_is_falsey(self): + self.assertFalse(np.array([''], dtype=np.str)) + + def test_whitespace_bstring_array_is_falsey(self): + a = np.array(['spam'], dtype=np.str) + a[0] = ' \0\0' + self.assertFalse(a) + + def test_all_null_bstring_array_is_falsey(self): + a = np.array(['spam'], dtype=np.str) + a[0] = '\0\0\0\0' + self.assertFalse(a) + + def test_null_inside_bstring_array_is_truthy(self): + a = np.array(['spam'], dtype=np.str) + a[0] = ' \0 \0' + self.assertTrue(a) + + +class TestUnicodeArrayNonzero(TestCase): + + def test_empty_ustring_array_is_falsey(self): + self.assertFalse(np.array([''], dtype=np.unicode)) + + def test_whitespace_ustring_array_is_falsey(self): + a = np.array(['eggs'], dtype=np.unicode) + a[0] = ' \0\0' + self.assertFalse(a) + + def test_all_null_ustring_array_is_falsey(self): + a = np.array(['eggs'], dtype=np.unicode) + a[0] = '\0\0\0\0' + self.assertFalse(a) + + def test_null_inside_ustring_array_is_truthy(self): + a = np.array(['eggs'], dtype=np.unicode) + a[0] = ' \0 \0' + self.assertTrue(a) + if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_multiarray_assignment.py b/numpy/core/tests/test_multiarray_assignment.py deleted file mode 100644 index 86e1b125e..000000000 --- a/numpy/core/tests/test_multiarray_assignment.py +++ /dev/null @@ -1,84 +0,0 @@ -from __future__ import division, absolute_import, print_function - -import numpy as np -from numpy.testing import run_module_suite - -ndims = 2 -size = 10 -shape = tuple([size] * ndims) - - -def _indices_for_nelems(nelems): - """Returns slices of length nelems, from start onwards, in direction sign.""" - - if nelems == 0: - return [size // 2] # int index - - res = [] - for step in (1, 2): - for sign in (-1, 1): - start = size // 2 - nelems * step * sign // 2 - stop = start + nelems * step * sign - res.append(slice(start, stop, step * sign)) - - return res - - -def _indices_for_axis(): - """Returns (src, dst) pairs of indices.""" - - res = [] - for nelems in (0, 2, 3): - ind = _indices_for_nelems(nelems) - - # no itertools.product available in Py2.4 - res.extend([(a, b) for a in ind for b in ind]) # all assignments of size "nelems" - - return res - - -def _indices(ndims): - """Returns ((axis0_src, axis0_dst), (axis1_src, axis1_dst), ... ) index pairs.""" - - ind = _indices_for_axis() - - # no itertools.product available in Py2.4 - - res = [[]] - for i in range(ndims): - newres = [] - for elem in ind: - for others in res: - newres.append([elem] + others) - res = newres - - return res - - -def _check_assignment(srcidx, dstidx): - """Check assignment arr[dstidx] = arr[srcidx] works.""" - - arr = np.arange(np.product(shape)).reshape(shape) - - cpy = arr.copy() - - cpy[dstidx] = arr[srcidx] - arr[dstidx] = arr[srcidx] - - assert np.all(arr == cpy), 'assigning arr[%s] = arr[%s]' % (dstidx, srcidx) - - -def test_overlapping_assignments(): - """Test automatically generated assignments which overlap in memory.""" - - inds = _indices(ndims) - - for ind in inds: - srcidx = tuple([a[0] for a in ind]) - dstidx = tuple([a[1] for a in ind]) - - yield _check_assignment, srcidx, dstidx - - -if __name__ == "__main__": - run_module_suite() diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py index dbf2cfaae..ed0197991 100644 --- a/numpy/core/tests/test_nditer.py +++ b/numpy/core/tests/test_nditer.py @@ -1,12 +1,16 @@ from __future__ import division, absolute_import, print_function -import sys, warnings +import sys +import warnings import numpy as np from numpy import array, arange, nditer, all from numpy.compat import asbytes, sixu -from numpy.testing import * from numpy.core.multiarray_tests import test_nditer_too_large +from numpy.testing import ( + run_module_suite, assert_, assert_equal, assert_array_equal, + assert_raises, dec + ) def iter_multi_index(i): @@ -69,6 +73,8 @@ def test_iter_refcount(): assert_equal(sys.getrefcount(a), rc_a) assert_equal(sys.getrefcount(dt), rc_dt) + del it2 # avoid pyflakes unused variable warning + def test_iter_best_order(): # The iterator should always find the iteration order # with increasing memory addresses @@ -80,7 +86,7 @@ def test_iter_best_order(): for dirs in range(2**len(shape)): dirs_index = [slice(None)]*len(shape) for bit in range(len(shape)): - if ((2**bit)&dirs): + if ((2**bit) & dirs): dirs_index[bit] = slice(None, None, -1) dirs_index = tuple(dirs_index) @@ -106,7 +112,7 @@ def test_iter_c_order(): for dirs in range(2**len(shape)): dirs_index = [slice(None)]*len(shape) for bit in range(len(shape)): - if ((2**bit)&dirs): + if ((2**bit) & dirs): dirs_index[bit] = slice(None, None, -1) dirs_index = tuple(dirs_index) @@ -133,7 +139,7 @@ def test_iter_f_order(): for dirs in range(2**len(shape)): dirs_index = [slice(None)]*len(shape) for bit in range(len(shape)): - if ((2**bit)&dirs): + if ((2**bit) & dirs): dirs_index[bit] = slice(None, None, -1) dirs_index = tuple(dirs_index) @@ -160,7 +166,7 @@ def test_iter_c_or_f_order(): for dirs in range(2**len(shape)): dirs_index = [slice(None)]*len(shape) for bit in range(len(shape)): - if ((2**bit)&dirs): + if ((2**bit) & dirs): dirs_index[bit] = slice(None, None, -1) dirs_index = tuple(dirs_index) @@ -423,7 +429,7 @@ def test_iter_no_inner_full_coalesce(): for dirs in range(2**len(shape)): dirs_index = [slice(None)]*len(shape) for bit in range(len(shape)): - if ((2**bit)&dirs): + if ((2**bit) & dirs): dirs_index[bit] = slice(None, None, -1) dirs_index = tuple(dirs_index) @@ -631,12 +637,12 @@ def test_iter_broadcasting_errors(): # Verify that the error message mentions the right shapes try: - i = nditer([arange(2).reshape(1, 2, 1), - arange(3).reshape(1, 3), - arange(6).reshape(2, 3)], - [], - [['readonly'], ['readonly'], ['writeonly', 'no_broadcast']]) - assert_(False, 'Should have raised a broadcast error') + nditer([arange(2).reshape(1, 2, 1), + arange(3).reshape(1, 3), + arange(6).reshape(2, 3)], + [], + [['readonly'], ['readonly'], ['writeonly', 'no_broadcast']]) + raise AssertionError('Should have raised a broadcast error') except ValueError as e: msg = str(e) # The message should contain the shape of the 3rd operand @@ -647,11 +653,12 @@ def test_iter_broadcasting_errors(): 'Message "%s" doesn\'t contain broadcast shape (1,2,3)' % msg) try: - i = nditer([arange(6).reshape(2, 3), arange(2)], [], - [['readonly'], ['readonly']], - op_axes=[[0, 1], [0, np.newaxis]], - itershape=(4, 3)) - assert_(False, 'Should have raised a broadcast error') + nditer([arange(6).reshape(2, 3), arange(2)], + [], + [['readonly'], ['readonly']], + op_axes=[[0, 1], [0, np.newaxis]], + itershape=(4, 3)) + raise AssertionError('Should have raised a broadcast error') except ValueError as e: msg = str(e) # The message should contain "shape->remappedshape" for each operand @@ -665,10 +672,10 @@ def test_iter_broadcasting_errors(): 'Message "%s" doesn\'t contain itershape parameter (4,3)' % msg) try: - i = nditer([np.zeros((2, 1, 1)), np.zeros((2,))], - [], - [['writeonly', 'no_broadcast'], ['readonly']]) - assert_(False, 'Should have raised a broadcast error') + nditer([np.zeros((2, 1, 1)), np.zeros((2,))], + [], + [['writeonly', 'no_broadcast'], ['readonly']]) + raise AssertionError('Should have raised a broadcast error') except ValueError as e: msg = str(e) # The message should contain the shape of the bad operand @@ -731,14 +738,18 @@ def test_iter_flags_errors(): # Index available only with an index flag assert_raises(ValueError, lambda i:i.index, i) # GotoCoords and GotoIndex incompatible with buffering or no_inner + def assign_multi_index(i): i.multi_index = (0,) + def assign_index(i): i.index = 0 + def assign_iterindex(i): - i.iterindex = 0; + i.iterindex = 0 + def assign_iterrange(i): - i.iterrange = (0, 1); + i.iterrange = (0, 1) i = nditer(arange(6), ['external_loop']) assert_raises(ValueError, assign_multi_index, i) assert_raises(ValueError, assign_index, i) @@ -798,11 +809,11 @@ def test_iter_nbo_align_contig(): # Without 'aligned', shouldn't copy i = nditer(a, [], [['readonly']]) assert_(not i.operands[0].flags.aligned) - assert_equal(i.operands[0], a); + assert_equal(i.operands[0], a) # With 'aligned', should make a copy i = nditer(a, [], [['readwrite', 'updateifcopy', 'aligned']]) assert_(i.operands[0].flags.aligned) - assert_equal(i.operands[0], a); + assert_equal(i.operands[0], a) i.operands[0][:] = 3 i = None assert_equal(a, [3]*6) @@ -812,7 +823,7 @@ def test_iter_nbo_align_contig(): # If it is contiguous, shouldn't copy i = nditer(a[:6], [], [['readonly']]) assert_(i.operands[0].flags.contiguous) - assert_equal(i.operands[0], a[:6]); + assert_equal(i.operands[0], a[:6]) # If it isn't contiguous, should buffer i = nditer(a[::2], ['buffered', 'external_loop'], [['readonly', 'contig']], @@ -996,7 +1007,7 @@ def test_iter_object_arrays_basic(): assert_equal(sys.getrefcount(obj), rc) i = nditer(a, ['refs_ok'], ['readonly']) - vals = [x[()] for x in i] + vals = [x_[()] for x_ in i] assert_equal(np.array(vals, dtype='O'), a) vals, i, x = [None]*3 assert_equal(sys.getrefcount(obj), rc) @@ -1004,7 +1015,7 @@ def test_iter_object_arrays_basic(): i = nditer(a.reshape(2, 2).T, ['refs_ok', 'buffered'], ['readonly'], order='C') assert_(i.iterationneedsapi) - vals = [x[()] for x in i] + vals = [x_[()] for x_ in i] assert_equal(np.array(vals, dtype='O'), a.reshape(2, 2).ravel(order='F')) vals, i, x = [None]*3 assert_equal(sys.getrefcount(obj), rc) @@ -1063,41 +1074,41 @@ def test_iter_common_dtype(): ['common_dtype'], [['readonly', 'copy']]*2, casting='safe') - assert_equal(i.dtypes[0], np.dtype('f8')); - assert_equal(i.dtypes[1], np.dtype('f8')); + assert_equal(i.dtypes[0], np.dtype('f8')) + assert_equal(i.dtypes[1], np.dtype('f8')) i = nditer([array([3], dtype='i4'), array([0], dtype='f4')], ['common_dtype'], [['readonly', 'copy']]*2, casting='safe') - assert_equal(i.dtypes[0], np.dtype('f8')); - assert_equal(i.dtypes[1], np.dtype('f8')); + assert_equal(i.dtypes[0], np.dtype('f8')) + assert_equal(i.dtypes[1], np.dtype('f8')) i = nditer([array([3], dtype='f4'), array(0, dtype='f8')], ['common_dtype'], [['readonly', 'copy']]*2, casting='same_kind') - assert_equal(i.dtypes[0], np.dtype('f4')); - assert_equal(i.dtypes[1], np.dtype('f4')); + assert_equal(i.dtypes[0], np.dtype('f4')) + assert_equal(i.dtypes[1], np.dtype('f4')) i = nditer([array([3], dtype='u4'), array(0, dtype='i4')], ['common_dtype'], [['readonly', 'copy']]*2, casting='safe') - assert_equal(i.dtypes[0], np.dtype('u4')); - assert_equal(i.dtypes[1], np.dtype('u4')); + assert_equal(i.dtypes[0], np.dtype('u4')) + assert_equal(i.dtypes[1], np.dtype('u4')) i = nditer([array([3], dtype='u4'), array(-12, dtype='i4')], ['common_dtype'], [['readonly', 'copy']]*2, casting='safe') - assert_equal(i.dtypes[0], np.dtype('i8')); - assert_equal(i.dtypes[1], np.dtype('i8')); + assert_equal(i.dtypes[0], np.dtype('i8')) + assert_equal(i.dtypes[1], np.dtype('i8')) i = nditer([array([3], dtype='u4'), array(-12, dtype='i4'), array([2j], dtype='c8'), array([9], dtype='f8')], ['common_dtype'], [['readonly', 'copy']]*4, casting='safe') - assert_equal(i.dtypes[0], np.dtype('c16')); - assert_equal(i.dtypes[1], np.dtype('c16')); - assert_equal(i.dtypes[2], np.dtype('c16')); - assert_equal(i.dtypes[3], np.dtype('c16')); + assert_equal(i.dtypes[0], np.dtype('c16')) + assert_equal(i.dtypes[1], np.dtype('c16')) + assert_equal(i.dtypes[2], np.dtype('c16')) + assert_equal(i.dtypes[3], np.dtype('c16')) assert_equal(i.value, (3, -12, 2j, 9)) # When allocating outputs, other outputs aren't factored in @@ -1106,9 +1117,9 @@ def test_iter_common_dtype(): ['writeonly', 'allocate'], ['writeonly']], casting='safe') - assert_equal(i.dtypes[0], np.dtype('i4')); - assert_equal(i.dtypes[1], np.dtype('i4')); - assert_equal(i.dtypes[2], np.dtype('c16')); + assert_equal(i.dtypes[0], np.dtype('i4')) + assert_equal(i.dtypes[1], np.dtype('i4')) + assert_equal(i.dtypes[2], np.dtype('c16')) # But, if common data types are requested, they are i = nditer([array([3], dtype='i4'), None, array([2j], dtype='c16')], ['common_dtype'], @@ -1116,9 +1127,9 @@ def test_iter_common_dtype(): ['writeonly', 'allocate'], ['writeonly']], casting='safe') - assert_equal(i.dtypes[0], np.dtype('c16')); - assert_equal(i.dtypes[1], np.dtype('c16')); - assert_equal(i.dtypes[2], np.dtype('c16')); + assert_equal(i.dtypes[0], np.dtype('c16')) + assert_equal(i.dtypes[1], np.dtype('c16')) + assert_equal(i.dtypes[2], np.dtype('c16')) def test_iter_op_axes(): # Check that custom axes work @@ -1126,10 +1137,10 @@ def test_iter_op_axes(): # Reverse the axes a = arange(6).reshape(2, 3) i = nditer([a, a.T], [], [['readonly']]*2, op_axes=[[0, 1], [1, 0]]) - assert_(all([x==y for (x, y) in i])) + assert_(all([x == y for (x, y) in i])) a = arange(24).reshape(2, 3, 4) i = nditer([a.T, a], [], [['readonly']]*2, op_axes=[[2, 1, 0], None]) - assert_(all([x==y for (x, y) in i])) + assert_(all([x == y for (x, y) in i])) # Broadcast 1D to any dimension a = arange(1, 31).reshape(2, 3, 5) @@ -1285,7 +1296,7 @@ def test_iter_allocate_output_opaxes(): a = arange(24, dtype='i4').reshape(2, 3, 4) i = nditer([None, a], [], [['writeonly', 'allocate'], ['readonly']], op_dtypes=[np.dtype('u4'), None], - op_axes=[[1, 2, 0], None]); + op_axes=[[1, 2, 0], None]) assert_equal(i.operands[0].shape, (4, 2, 3)) assert_equal(i.operands[0].strides, (4, 48, 16)) assert_equal(i.operands[0].dtype, np.dtype('u4')) @@ -1295,19 +1306,19 @@ def test_iter_allocate_output_types_promotion(): i = nditer([array([3], dtype='f4'), array([0], dtype='f8'), None], [], [['readonly']]*2+[['writeonly', 'allocate']]) - assert_equal(i.dtypes[2], np.dtype('f8')); + assert_equal(i.dtypes[2], np.dtype('f8')) i = nditer([array([3], dtype='i4'), array([0], dtype='f4'), None], [], [['readonly']]*2+[['writeonly', 'allocate']]) - assert_equal(i.dtypes[2], np.dtype('f8')); + assert_equal(i.dtypes[2], np.dtype('f8')) i = nditer([array([3], dtype='f4'), array(0, dtype='f8'), None], [], [['readonly']]*2+[['writeonly', 'allocate']]) - assert_equal(i.dtypes[2], np.dtype('f4')); + assert_equal(i.dtypes[2], np.dtype('f4')) i = nditer([array([3], dtype='u4'), array(0, dtype='i4'), None], [], [['readonly']]*2+[['writeonly', 'allocate']]) - assert_equal(i.dtypes[2], np.dtype('u4')); + assert_equal(i.dtypes[2], np.dtype('u4')) i = nditer([array([3], dtype='u4'), array(-12, dtype='i4'), None], [], [['readonly']]*2+[['writeonly', 'allocate']]) - assert_equal(i.dtypes[2], np.dtype('i8')); + assert_equal(i.dtypes[2], np.dtype('i8')) def test_iter_allocate_output_types_byte_order(): # Verify the rules for byte order changes @@ -1316,11 +1327,11 @@ def test_iter_allocate_output_types_byte_order(): a = array([3], dtype='u4').newbyteorder() i = nditer([a, None], [], [['readonly'], ['writeonly', 'allocate']]) - assert_equal(i.dtypes[0], i.dtypes[1]); + assert_equal(i.dtypes[0], i.dtypes[1]) # With two or more inputs, the output type is in native byte order i = nditer([a, a, None], [], [['readonly'], ['readonly'], ['writeonly', 'allocate']]) - assert_(i.dtypes[0] != i.dtypes[2]); + assert_(i.dtypes[0] != i.dtypes[2]) assert_equal(i.dtypes[0].newbyteorder('='), i.dtypes[2]) def test_iter_allocate_output_types_scalar(): @@ -1564,6 +1575,7 @@ def test_iter_buffering_delayed_alloc(): assert_raises(ValueError, lambda i:i.multi_index, i) assert_raises(ValueError, lambda i:i[0], i) assert_raises(ValueError, lambda i:i[0:2], i) + def assign_iter(i): i[0] = 0 assert_raises(ValueError, assign_iter, i) @@ -1715,7 +1727,7 @@ def test_iter_buffered_cast_structured_type(): i = nditer(a, ['buffered', 'refs_ok'], ['readonly'], casting='unsafe', op_dtypes='i4') - assert_equal([x[()] for x in i], [5, 8]) + assert_equal([x_[()] for x_ in i], [5, 8]) # struct type -> struct type (field-wise copy) sdt1 = [('a', 'f4'), ('b', 'i8'), ('d', 'O')] @@ -1725,9 +1737,9 @@ def test_iter_buffered_cast_structured_type(): casting='unsafe', op_dtypes=sdt2) assert_equal(i[0].dtype, np.dtype(sdt2)) - assert_equal([np.array(x) for x in i], - [np.array((3, 1, 2), dtype=sdt2), - np.array((6, 4, 5), dtype=sdt2)]) + assert_equal([np.array(x_) for x_ in i], + [np.array((3, 1, 2), dtype=sdt2), + np.array((6, 4, 5), dtype=sdt2)]) # struct type -> struct type (field gets discarded) sdt1 = [('a', 'f4'), ('b', 'i8'), ('d', 'O')] @@ -1966,45 +1978,45 @@ def test_iter_buffering_badwriteback(): a = np.arange(6).reshape(2, 3, 1) b = np.arange(12).reshape(2, 3, 2) assert_raises(ValueError, nditer, [a, b], - ['buffered', 'external_loop'], - [['readwrite'], ['writeonly']], - order='C') + ['buffered', 'external_loop'], + [['readwrite'], ['writeonly']], + order='C') # But if a is readonly, it's fine - i = nditer([a, b], ['buffered', 'external_loop'], - [['readonly'], ['writeonly']], - order='C') + nditer([a, b], ['buffered', 'external_loop'], + [['readonly'], ['writeonly']], + order='C') # If a has just one element, it's fine too (constant 0 stride, a reduction) a = np.arange(1).reshape(1, 1, 1) - i = nditer([a, b], ['buffered', 'external_loop', 'reduce_ok'], - [['readwrite'], ['writeonly']], - order='C') + nditer([a, b], ['buffered', 'external_loop', 'reduce_ok'], + [['readwrite'], ['writeonly']], + order='C') # check that it fails on other dimensions too a = np.arange(6).reshape(1, 3, 2) assert_raises(ValueError, nditer, [a, b], - ['buffered', 'external_loop'], - [['readwrite'], ['writeonly']], - order='C') + ['buffered', 'external_loop'], + [['readwrite'], ['writeonly']], + order='C') a = np.arange(4).reshape(2, 1, 2) assert_raises(ValueError, nditer, [a, b], - ['buffered', 'external_loop'], - [['readwrite'], ['writeonly']], - order='C') + ['buffered', 'external_loop'], + [['readwrite'], ['writeonly']], + order='C') def test_iter_buffering_string(): # Safe casting disallows shrinking strings a = np.array(['abc', 'a', 'abcd'], dtype=np.bytes_) - assert_equal(a.dtype, np.dtype('S4')); + assert_equal(a.dtype, np.dtype('S4')) assert_raises(TypeError, nditer, a, ['buffered'], ['readonly'], - op_dtypes='S2') + op_dtypes='S2') i = nditer(a, ['buffered'], ['readonly'], op_dtypes='S6') assert_equal(i[0], asbytes('abc')) assert_equal(i[0].dtype, np.dtype('S6')) a = np.array(['abc', 'a', 'abcd'], dtype=np.unicode) - assert_equal(a.dtype, np.dtype('U4')); + assert_equal(a.dtype, np.dtype('U4')) assert_raises(TypeError, nditer, a, ['buffered'], ['readonly'], op_dtypes='U2') i = nditer(a, ['buffered'], ['readonly'], op_dtypes='U6') @@ -2076,12 +2088,13 @@ def test_iter_no_broadcast(): b = np.arange(6).reshape(2, 3, 1) c = np.arange(12).reshape(3, 4) - i = nditer([a, b, c], [], - [['readonly', 'no_broadcast'], ['readonly'], ['readonly']]) + nditer([a, b, c], [], + [['readonly', 'no_broadcast'], + ['readonly'], ['readonly']]) assert_raises(ValueError, nditer, [a, b, c], [], - [['readonly'], ['readonly', 'no_broadcast'], ['readonly']]) + [['readonly'], ['readonly', 'no_broadcast'], ['readonly']]) assert_raises(ValueError, nditer, [a, b, c], [], - [['readonly'], ['readonly'], ['readonly', 'no_broadcast']]) + [['readonly'], ['readonly'], ['readonly', 'no_broadcast']]) def test_iter_nested_iters_basic(): # Test nested iteration basic usage @@ -2232,7 +2245,7 @@ def test_iter_nested_iters_dtype_copy(): for y in j: y[...] += 1 assert_equal(a, [[0, 1, 2], [3, 4, 5]]) - i, j, x, y = (None,)*4 # force the updateifcopy + i, j, x, y = (None,)*4 # force the updateifcopy assert_equal(a, [[1, 2, 3], [4, 5, 6]]) def test_iter_nested_iters_dtype_buffered(): @@ -2363,7 +2376,7 @@ def test_iter_buffering_reduction_reuse_reduce_loops(): b = np.zeros((1, 7)) it = np.nditer([a, b], flags=['reduce_ok', 'external_loop', 'buffered'], op_flags=[['readonly'], ['readwrite']], - buffersize = 5) + buffersize=5) bufsizes = [] for x, y in it: diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index 9f0fb47e5..2fa8593b9 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -1,241 +1,115 @@ from __future__ import division, absolute_import, print_function import sys -import platform -from decimal import Decimal import warnings import itertools import platform +from decimal import Decimal import numpy as np -from numpy.core import * from numpy.core import umath from numpy.random import rand, randint, randn -from numpy.testing import * -from numpy.core.multiarray import dot as dot_ - - -class Vec(object): - def __init__(self,sequence=None): - if sequence is None: - sequence=[] - self.array=array(sequence) - def __add__(self, other): - out=Vec() - out.array=self.array+other.array - return out - def __sub__(self, other): - out=Vec() - out.array=self.array-other.array - return out - def __mul__(self, other): # with scalar - out=Vec(self.array.copy()) - out.array*=other - return out - def __rmul__(self, other): - return self*other - - -class TestDot(TestCase): - def setUp(self): - self.A = rand(10, 8) - self.b1 = rand(8, 1) - self.b2 = rand(8) - self.b3 = rand(1, 8) - self.b4 = rand(10) - self.N = 14 - - def test_matmat(self): - A = self.A - c1 = dot(A.transpose(), A) - c2 = dot_(A.transpose(), A) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_matvec(self): - A, b1 = self.A, self.b1 - c1 = dot(A, b1) - c2 = dot_(A, b1) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_matvec2(self): - A, b2 = self.A, self.b2 - c1 = dot(A, b2) - c2 = dot_(A, b2) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_vecmat(self): - A, b4 = self.A, self.b4 - c1 = dot(b4, A) - c2 = dot_(b4, A) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_vecmat2(self): - b3, A = self.b3, self.A - c1 = dot(b3, A.transpose()) - c2 = dot_(b3, A.transpose()) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_vecmat3(self): - A, b4 = self.A, self.b4 - c1 = dot(A.transpose(), b4) - c2 = dot_(A.transpose(), b4) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_vecvecouter(self): - b1, b3 = self.b1, self.b3 - c1 = dot(b1, b3) - c2 = dot_(b1, b3) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_vecvecinner(self): - b1, b3 = self.b1, self.b3 - c1 = dot(b3, b1) - c2 = dot_(b3, b1) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_columnvect1(self): - b1 = ones((3, 1)) - b2 = [5.3] - c1 = dot(b1, b2) - c2 = dot_(b1, b2) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_columnvect2(self): - b1 = ones((3, 1)).transpose() - b2 = [6.2] - c1 = dot(b2, b1) - c2 = dot_(b2, b1) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_vecscalar(self): - b1 = rand(1, 1) - b2 = rand(1, 8) - c1 = dot(b1, b2) - c2 = dot_(b1, b2) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_vecscalar2(self): - b1 = rand(8, 1) - b2 = rand(1, 1) - c1 = dot(b1, b2) - c2 = dot_(b1, b2) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_all(self): - dims = [(), (1,), (1, 1)] - for dim1 in dims: - for dim2 in dims: - arg1 = rand(*dim1) - arg2 = rand(*dim2) - c1 = dot(arg1, arg2) - c2 = dot_(arg1, arg2) - assert_(c1.shape == c2.shape) - assert_almost_equal(c1, c2, decimal=self.N) - - def test_vecobject(self): - U_non_cont = transpose([[1., 1.], [1., 2.]]) - U_cont = ascontiguousarray(U_non_cont) - x = array([Vec([1., 0.]), Vec([0., 1.])]) - zeros = array([Vec([0., 0.]), Vec([0., 0.])]) - zeros_test = dot(U_cont, x) - dot(U_non_cont, x) - assert_equal(zeros[0].array, zeros_test[0].array) - assert_equal(zeros[1].array, zeros_test[1].array) +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_raises, + assert_array_equal, assert_almost_equal, assert_array_almost_equal, dec +) class TestResize(TestCase): def test_copies(self): - A = array([[1, 2], [3, 4]]) - Ar1 = array([[1, 2, 3, 4], [1, 2, 3, 4]]) - assert_equal(resize(A, (2, 4)), Ar1) + A = np.array([[1, 2], [3, 4]]) + Ar1 = np.array([[1, 2, 3, 4], [1, 2, 3, 4]]) + assert_equal(np.resize(A, (2, 4)), Ar1) - Ar2 = array([[1, 2], [3, 4], [1, 2], [3, 4]]) - assert_equal(resize(A, (4, 2)), Ar2) + Ar2 = np.array([[1, 2], [3, 4], [1, 2], [3, 4]]) + assert_equal(np.resize(A, (4, 2)), Ar2) - Ar3 = array([[1, 2, 3], [4, 1, 2], [3, 4, 1], [2, 3, 4]]) - assert_equal(resize(A, (4, 3)), Ar3) + Ar3 = np.array([[1, 2, 3], [4, 1, 2], [3, 4, 1], [2, 3, 4]]) + assert_equal(np.resize(A, (4, 3)), Ar3) def test_zeroresize(self): - A = array([[1, 2], [3, 4]]) - Ar = resize(A, (0,)) - assert_equal(Ar, array([])) + A = np.array([[1, 2], [3, 4]]) + Ar = np.resize(A, (0,)) + assert_equal(Ar, np.array([])) + class TestNonarrayArgs(TestCase): # check that non-array arguments to functions wrap them in arrays def test_squeeze(self): A = [[[1, 1, 1], [2, 2, 2], [3, 3, 3]]] - assert_(squeeze(A).shape == (3, 3)) + assert_(np.squeeze(A).shape == (3, 3)) def test_cumproduct(self): A = [[1, 2, 3], [4, 5, 6]] - assert_(all(cumproduct(A) == array([1, 2, 6, 24, 120, 720]))) + assert_(np.all(np.cumproduct(A) == np.array([1, 2, 6, 24, 120, 720]))) def test_size(self): A = [[1, 2, 3], [4, 5, 6]] - assert_(size(A) == 6) - assert_(size(A, 0) == 2) - assert_(size(A, 1) == 3) + assert_(np.size(A) == 6) + assert_(np.size(A, 0) == 2) + assert_(np.size(A, 1) == 3) def test_mean(self): A = [[1, 2, 3], [4, 5, 6]] - assert_(mean(A) == 3.5) - assert_(all(mean(A, 0) == array([2.5, 3.5, 4.5]))) - assert_(all(mean(A, 1) == array([2., 5.]))) + assert_(np.mean(A) == 3.5) + assert_(np.all(np.mean(A, 0) == np.array([2.5, 3.5, 4.5]))) + assert_(np.all(np.mean(A, 1) == np.array([2., 5.]))) with warnings.catch_warnings(record=True) as w: warnings.filterwarnings('always', '', RuntimeWarning) - assert_(isnan(mean([]))) + assert_(np.isnan(np.mean([]))) assert_(w[0].category is RuntimeWarning) def test_std(self): A = [[1, 2, 3], [4, 5, 6]] - assert_almost_equal(std(A), 1.707825127659933) - assert_almost_equal(std(A, 0), array([1.5, 1.5, 1.5])) - assert_almost_equal(std(A, 1), array([0.81649658, 0.81649658])) + assert_almost_equal(np.std(A), 1.707825127659933) + assert_almost_equal(np.std(A, 0), np.array([1.5, 1.5, 1.5])) + assert_almost_equal(np.std(A, 1), np.array([0.81649658, 0.81649658])) with warnings.catch_warnings(record=True) as w: warnings.filterwarnings('always', '', RuntimeWarning) - assert_(isnan(std([]))) + assert_(np.isnan(np.std([]))) assert_(w[0].category is RuntimeWarning) def test_var(self): A = [[1, 2, 3], [4, 5, 6]] - assert_almost_equal(var(A), 2.9166666666666665) - assert_almost_equal(var(A, 0), array([2.25, 2.25, 2.25])) - assert_almost_equal(var(A, 1), array([0.66666667, 0.66666667])) + assert_almost_equal(np.var(A), 2.9166666666666665) + assert_almost_equal(np.var(A, 0), np.array([2.25, 2.25, 2.25])) + assert_almost_equal(np.var(A, 1), np.array([0.66666667, 0.66666667])) with warnings.catch_warnings(record=True) as w: warnings.filterwarnings('always', '', RuntimeWarning) - assert_(isnan(var([]))) + assert_(np.isnan(np.var([]))) assert_(w[0].category is RuntimeWarning) class TestBoolScalar(TestCase): def test_logical(self): - f = False_ - t = True_ + f = np.False_ + t = np.True_ s = "xyz" self.assertTrue((t and s) is s) self.assertTrue((f and s) is f) def test_bitwise_or(self): - f = False_ - t = True_ + f = np.False_ + t = np.True_ self.assertTrue((t | t) is t) self.assertTrue((f | t) is t) self.assertTrue((t | f) is t) self.assertTrue((f | f) is f) def test_bitwise_and(self): - f = False_ - t = True_ + f = np.False_ + t = np.True_ self.assertTrue((t & t) is t) self.assertTrue((f & t) is f) self.assertTrue((t & f) is f) self.assertTrue((f & f) is f) def test_bitwise_xor(self): - f = False_ - t = True_ + f = np.False_ + t = np.True_ self.assertTrue((t ^ t) is f) self.assertTrue((f ^ t) is t) self.assertTrue((t ^ f) is t) @@ -245,9 +119,9 @@ class TestBoolScalar(TestCase): class TestBoolArray(TestCase): def setUp(self): # offset for simd tests - self.t = array([True] * 41, dtype=np.bool)[1::] - self.f = array([False] * 41, dtype=np.bool)[1::] - self.o = array([False] * 42, dtype=np.bool)[2::] + self.t = np.array([True] * 41, dtype=np.bool)[1::] + self.f = np.array([False] * 41, dtype=np.bool)[1::] + self.o = np.array([False] * 42, dtype=np.bool)[2::] self.nm = self.f.copy() self.im = self.t.copy() self.nm[3] = True @@ -266,19 +140,19 @@ class TestBoolArray(TestCase): self.assertFalse(self.im.all()) # check bad element in all positions for i in range(256 - 7): - d = array([False] * 256, dtype=np.bool)[7::] + d = np.array([False] * 256, dtype=np.bool)[7::] d[i] = True self.assertTrue(np.any(d)) - e = array([True] * 256, dtype=np.bool)[7::] + e = np.array([True] * 256, dtype=np.bool)[7::] e[i] = False self.assertFalse(np.all(e)) assert_array_equal(e, ~d) # big array test for blocked libc loops for i in list(range(9, 6000, 507)) + [7764, 90021, -10]: - d = array([False] * 100043, dtype=np.bool) + d = np.array([False] * 100043, dtype=np.bool) d[i] = True self.assertTrue(np.any(d), msg="%r" % i) - e = array([True] * 100043, dtype=np.bool) + e = np.array([True] * 100043, dtype=np.bool) e[i] = False self.assertFalse(np.all(e), msg="%r" % i) @@ -331,10 +205,10 @@ class TestBoolArray(TestCase): class TestBoolCmp(TestCase): def setUp(self): - self.f = ones(256, dtype=np.float32) - self.ef = ones(self.f.size, dtype=np.bool) - self.d = ones(128, dtype=np.float64) - self.ed = ones(self.d.size, dtype=np.bool) + self.f = np.ones(256, dtype=np.float32) + self.ef = np.ones(self.f.size, dtype=np.bool) + self.d = np.ones(128, dtype=np.float64) + self.ed = np.ones(self.d.size, dtype=np.bool) # generate values for all permutation of 256bit simd vectors s = 0 for i in range(32): @@ -399,7 +273,7 @@ class TestBoolCmp(TestCase): class TestSeterr(TestCase): def test_default(self): - err = geterr() + err = np.geterr() self.assertEqual(err, dict( divide='warn', invalid='warn', @@ -409,28 +283,28 @@ class TestSeterr(TestCase): def test_set(self): with np.errstate(): - err = seterr() - old = seterr(divide='print') + err = np.seterr() + old = np.seterr(divide='print') self.assertTrue(err == old) - new = seterr() + new = np.seterr() self.assertTrue(new['divide'] == 'print') - seterr(over='raise') - self.assertTrue(geterr()['over'] == 'raise') + np.seterr(over='raise') + self.assertTrue(np.geterr()['over'] == 'raise') self.assertTrue(new['divide'] == 'print') - seterr(**old) - self.assertTrue(geterr() == old) + np.seterr(**old) + self.assertTrue(np.geterr() == old) @dec.skipif(platform.machine() == "armv5tel", "See gh-413.") def test_divide_err(self): - with errstate(divide='raise'): + with np.errstate(divide='raise'): try: - array([1.]) / array([0.]) + np.array([1.]) / np.array([0.]) except FloatingPointError: pass else: self.fail() - seterr(divide='ignore') - array([1.]) / array([0.]) + np.seterr(divide='ignore') + np.array([1.]) / np.array([0.]) def test_errobj(self): olderrobj = np.geterrobj() @@ -438,9 +312,9 @@ class TestSeterr(TestCase): try: with warnings.catch_warnings(record=True) as w: warnings.simplefilter("always") - with errstate(divide='warn'): + with np.errstate(divide='warn'): np.seterrobj([20000, 1, None]) - array([1.]) / array([0.]) + np.array([1.]) / np.array([0.]) self.assertEqual(len(w), 1) def log_err(*args): @@ -449,13 +323,13 @@ class TestSeterr(TestCase): assert (len(extobj_err) == 2) assert ("divide" in extobj_err[0]) - with errstate(divide='ignore'): + with np.errstate(divide='ignore'): np.seterrobj([20000, 3, log_err]) - array([1.]) / array([0.]) + np.array([1.]) / np.array([0.]) self.assertEqual(self.called, 1) np.seterrobj(olderrobj) - with errstate(divide='ignore'): + with np.errstate(divide='ignore'): np.divide(1., 0., extobj=[20000, 3, log_err]) self.assertEqual(self.called, 2) finally: @@ -499,10 +373,10 @@ class TestFloatExceptions(TestCase): # the operation raises the floating point exception specified by #`fpeerr`. Tests all variants with 0-d array scalars as well. - self.assert_raises_fpe(fpeerr, flop, sc1, sc2); - self.assert_raises_fpe(fpeerr, flop, sc1[()], sc2); - self.assert_raises_fpe(fpeerr, flop, sc1, sc2[()]); - self.assert_raises_fpe(fpeerr, flop, sc1[()], sc2[()]); + self.assert_raises_fpe(fpeerr, flop, sc1, sc2) + self.assert_raises_fpe(fpeerr, flop, sc1[()], sc2) + self.assert_raises_fpe(fpeerr, flop, sc1, sc2[()]) + self.assert_raises_fpe(fpeerr, flop, sc1[()], sc2[()]) @dec.knownfailureif(True, "See ticket #2350") def test_floating_exceptions(self): @@ -582,76 +456,81 @@ class TestTypes(TestCase): def check_promotion_cases(self, promote_func): #Tests that the scalars get coerced correctly. b = np.bool_(0) - i8, i16, i32, i64 = int8(0), int16(0), int32(0), int64(0) - u8, u16, u32, u64 = uint8(0), uint16(0), uint32(0), uint64(0) - f32, f64, fld = float32(0), float64(0), longdouble(0) - c64, c128, cld = complex64(0), complex128(0), clongdouble(0) + i8, i16, i32, i64 = np.int8(0), np.int16(0), np.int32(0), np.int64(0) + u8, u16, u32, u64 = np.uint8(0), np.uint16(0), np.uint32(0), np.uint64(0) + f32, f64, fld = np.float32(0), np.float64(0), np.longdouble(0) + c64, c128, cld = np.complex64(0), np.complex128(0), np.clongdouble(0) # coercion within the same kind - assert_equal(promote_func(i8, i16), np.dtype(int16)) - assert_equal(promote_func(i32, i8), np.dtype(int32)) - assert_equal(promote_func(i16, i64), np.dtype(int64)) - assert_equal(promote_func(u8, u32), np.dtype(uint32)) - assert_equal(promote_func(f32, f64), np.dtype(float64)) - assert_equal(promote_func(fld, f32), np.dtype(longdouble)) - assert_equal(promote_func(f64, fld), np.dtype(longdouble)) - assert_equal(promote_func(c128, c64), np.dtype(complex128)) - assert_equal(promote_func(cld, c128), np.dtype(clongdouble)) - assert_equal(promote_func(c64, fld), np.dtype(clongdouble)) + assert_equal(promote_func(i8, i16), np.dtype(np.int16)) + assert_equal(promote_func(i32, i8), np.dtype(np.int32)) + assert_equal(promote_func(i16, i64), np.dtype(np.int64)) + assert_equal(promote_func(u8, u32), np.dtype(np.uint32)) + assert_equal(promote_func(f32, f64), np.dtype(np.float64)) + assert_equal(promote_func(fld, f32), np.dtype(np.longdouble)) + assert_equal(promote_func(f64, fld), np.dtype(np.longdouble)) + assert_equal(promote_func(c128, c64), np.dtype(np.complex128)) + assert_equal(promote_func(cld, c128), np.dtype(np.clongdouble)) + assert_equal(promote_func(c64, fld), np.dtype(np.clongdouble)) # coercion between kinds - assert_equal(promote_func(b, i32), np.dtype(int32)) - assert_equal(promote_func(b, u8), np.dtype(uint8)) - assert_equal(promote_func(i8, u8), np.dtype(int16)) - assert_equal(promote_func(u8, i32), np.dtype(int32)) - assert_equal(promote_func(i64, u32), np.dtype(int64)) - assert_equal(promote_func(u64, i32), np.dtype(float64)) - assert_equal(promote_func(i32, f32), np.dtype(float64)) - assert_equal(promote_func(i64, f32), np.dtype(float64)) - assert_equal(promote_func(f32, i16), np.dtype(float32)) - assert_equal(promote_func(f32, u32), np.dtype(float64)) - assert_equal(promote_func(f32, c64), np.dtype(complex64)) - assert_equal(promote_func(c128, f32), np.dtype(complex128)) - assert_equal(promote_func(cld, f64), np.dtype(clongdouble)) + assert_equal(promote_func(b, i32), np.dtype(np.int32)) + assert_equal(promote_func(b, u8), np.dtype(np.uint8)) + assert_equal(promote_func(i8, u8), np.dtype(np.int16)) + assert_equal(promote_func(u8, i32), np.dtype(np.int32)) + assert_equal(promote_func(i64, u32), np.dtype(np.int64)) + assert_equal(promote_func(u64, i32), np.dtype(np.float64)) + assert_equal(promote_func(i32, f32), np.dtype(np.float64)) + assert_equal(promote_func(i64, f32), np.dtype(np.float64)) + assert_equal(promote_func(f32, i16), np.dtype(np.float32)) + assert_equal(promote_func(f32, u32), np.dtype(np.float64)) + assert_equal(promote_func(f32, c64), np.dtype(np.complex64)) + assert_equal(promote_func(c128, f32), np.dtype(np.complex128)) + assert_equal(promote_func(cld, f64), np.dtype(np.clongdouble)) # coercion between scalars and 1-D arrays - assert_equal(promote_func(array([b]), i8), np.dtype(int8)) - assert_equal(promote_func(array([b]), u8), np.dtype(uint8)) - assert_equal(promote_func(array([b]), i32), np.dtype(int32)) - assert_equal(promote_func(array([b]), u32), np.dtype(uint32)) - assert_equal(promote_func(array([i8]), i64), np.dtype(int8)) - assert_equal(promote_func(u64, array([i32])), np.dtype(int32)) - assert_equal(promote_func(i64, array([u32])), np.dtype(uint32)) - assert_equal(promote_func(int32(-1), array([u64])), np.dtype(float64)) - assert_equal(promote_func(f64, array([f32])), np.dtype(float32)) - assert_equal(promote_func(fld, array([f32])), np.dtype(float32)) - assert_equal(promote_func(array([f64]), fld), np.dtype(float64)) - assert_equal(promote_func(fld, array([c64])), np.dtype(complex64)) - assert_equal(promote_func(c64, array([f64])), np.dtype(complex128)) - assert_equal(promote_func(complex64(3j), array([f64])), - np.dtype(complex128)) + assert_equal(promote_func(np.array([b]), i8), np.dtype(np.int8)) + assert_equal(promote_func(np.array([b]), u8), np.dtype(np.uint8)) + assert_equal(promote_func(np.array([b]), i32), np.dtype(np.int32)) + assert_equal(promote_func(np.array([b]), u32), np.dtype(np.uint32)) + assert_equal(promote_func(np.array([i8]), i64), np.dtype(np.int8)) + assert_equal(promote_func(u64, np.array([i32])), np.dtype(np.int32)) + assert_equal(promote_func(i64, np.array([u32])), np.dtype(np.uint32)) + assert_equal(promote_func(np.int32(-1), np.array([u64])), + np.dtype(np.float64)) + assert_equal(promote_func(f64, np.array([f32])), np.dtype(np.float32)) + assert_equal(promote_func(fld, np.array([f32])), np.dtype(np.float32)) + assert_equal(promote_func(np.array([f64]), fld), np.dtype(np.float64)) + assert_equal(promote_func(fld, np.array([c64])), + np.dtype(np.complex64)) + assert_equal(promote_func(c64, np.array([f64])), + np.dtype(np.complex128)) + assert_equal(promote_func(np.complex64(3j), np.array([f64])), + np.dtype(np.complex128)) # coercion between scalars and 1-D arrays, where # the scalar has greater kind than the array - assert_equal(promote_func(array([b]), f64), np.dtype(float64)) - assert_equal(promote_func(array([b]), i64), np.dtype(int64)) - assert_equal(promote_func(array([b]), u64), np.dtype(uint64)) - assert_equal(promote_func(array([i8]), f64), np.dtype(float64)) - assert_equal(promote_func(array([u16]), f64), np.dtype(float64)) + assert_equal(promote_func(np.array([b]), f64), np.dtype(np.float64)) + assert_equal(promote_func(np.array([b]), i64), np.dtype(np.int64)) + assert_equal(promote_func(np.array([b]), u64), np.dtype(np.uint64)) + assert_equal(promote_func(np.array([i8]), f64), np.dtype(np.float64)) + assert_equal(promote_func(np.array([u16]), f64), np.dtype(np.float64)) # uint and int are treated as the same "kind" for # the purposes of array-scalar promotion. - assert_equal(promote_func(array([u16]), i32), np.dtype(uint16)) + assert_equal(promote_func(np.array([u16]), i32), np.dtype(np.uint16)) # float and complex are treated as the same "kind" for # the purposes of array-scalar promotion, so that you can do # (0j + float32array) to get a complex64 array instead of # a complex128 array. - assert_equal(promote_func(array([f32]), c128), np.dtype(complex64)) + assert_equal(promote_func(np.array([f32]), c128), + np.dtype(np.complex64)) def test_coercion(self): def res_type(a, b): return np.add(a, b).dtype + self.check_promotion_cases(res_type) # Use-case: float/complex scalar * bool/int8 array @@ -835,7 +714,8 @@ class TestTypes(TestCase): # Custom exception class to test exception propagation in fromiter -class NIterError(Exception): pass +class NIterError(Exception): + pass class TestFromiter(TestCase): @@ -844,28 +724,28 @@ class TestFromiter(TestCase): yield x**2 def test_types(self): - ai32 = fromiter(self.makegen(), int32) - ai64 = fromiter(self.makegen(), int64) - af = fromiter(self.makegen(), float) - self.assertTrue(ai32.dtype == dtype(int32)) - self.assertTrue(ai64.dtype == dtype(int64)) - self.assertTrue(af.dtype == dtype(float)) + ai32 = np.fromiter(self.makegen(), np.int32) + ai64 = np.fromiter(self.makegen(), np.int64) + af = np.fromiter(self.makegen(), float) + self.assertTrue(ai32.dtype == np.dtype(np.int32)) + self.assertTrue(ai64.dtype == np.dtype(np.int64)) + self.assertTrue(af.dtype == np.dtype(float)) def test_lengths(self): - expected = array(list(self.makegen())) - a = fromiter(self.makegen(), int) - a20 = fromiter(self.makegen(), int, 20) + expected = np.array(list(self.makegen())) + a = np.fromiter(self.makegen(), int) + a20 = np.fromiter(self.makegen(), int, 20) self.assertTrue(len(a) == len(expected)) self.assertTrue(len(a20) == 20) - self.assertRaises(ValueError, fromiter, + self.assertRaises(ValueError, np.fromiter, self.makegen(), int, len(expected) + 10) def test_values(self): - expected = array(list(self.makegen())) - a = fromiter(self.makegen(), int) - a20 = fromiter(self.makegen(), int, 20) - self.assertTrue(alltrue(a == expected, axis=0)) - self.assertTrue(alltrue(a20 == expected[:20], axis=0)) + expected = np.array(list(self.makegen())) + a = np.fromiter(self.makegen(), int) + a20 = np.fromiter(self.makegen(), int, 20) + self.assertTrue(np.alltrue(a == expected, axis=0)) + self.assertTrue(np.alltrue(a20 == expected[:20], axis=0)) def load_data(self, n, eindex): # Utility method for the issue 2592 tests. @@ -891,24 +771,24 @@ class TestFromiter(TestCase): class TestNonzero(TestCase): def test_nonzero_trivial(self): - assert_equal(np.count_nonzero(array([])), 0) - assert_equal(np.count_nonzero(array([], dtype='?')), 0) - assert_equal(np.nonzero(array([])), ([],)) + assert_equal(np.count_nonzero(np.array([])), 0) + assert_equal(np.count_nonzero(np.array([], dtype='?')), 0) + assert_equal(np.nonzero(np.array([])), ([],)) - assert_equal(np.count_nonzero(array(0)), 0) - assert_equal(np.count_nonzero(array(0, dtype='?')), 0) - assert_equal(np.nonzero(array(0)), ([],)) - assert_equal(np.count_nonzero(array(1)), 1) - assert_equal(np.count_nonzero(array(1, dtype='?')), 1) - assert_equal(np.nonzero(array(1)), ([0],)) + assert_equal(np.count_nonzero(np.array(0)), 0) + assert_equal(np.count_nonzero(np.array(0, dtype='?')), 0) + assert_equal(np.nonzero(np.array(0)), ([],)) + assert_equal(np.count_nonzero(np.array(1)), 1) + assert_equal(np.count_nonzero(np.array(1, dtype='?')), 1) + assert_equal(np.nonzero(np.array(1)), ([0],)) def test_nonzero_onedim(self): - x = array([1, 0, 2, -1, 0, 0, 8]) + x = np.array([1, 0, 2, -1, 0, 0, 8]) assert_equal(np.count_nonzero(x), 4) assert_equal(np.count_nonzero(x), 4) assert_equal(np.nonzero(x), ([0, 2, 3, 6],)) - x = array([(1, 2), (0, 0), (1, 1), (-1, 3), (0, 7)], + x = np.array([(1, 2), (0, 0), (1, 1), (-1, 3), (0, 7)], dtype=[('a', 'i4'), ('b', 'i2')]) assert_equal(np.count_nonzero(x['a']), 3) assert_equal(np.count_nonzero(x['b']), 4) @@ -916,7 +796,7 @@ class TestNonzero(TestCase): assert_equal(np.nonzero(x['b']), ([0, 2, 3, 4],)) def test_nonzero_twodim(self): - x = array([[0, 1, 0], [2, 0, 3]]) + x = np.array([[0, 1, 0], [2, 0, 3]]) assert_equal(np.count_nonzero(x), 3) assert_equal(np.nonzero(x), ([0, 1, 1], [1, 0, 2])) @@ -924,7 +804,7 @@ class TestNonzero(TestCase): assert_equal(np.count_nonzero(x), 3) assert_equal(np.nonzero(x), ([0, 1, 2], [0, 1, 2])) - x = array([[(0, 1), (0, 0), (1, 11)], + x = np.array([[(0, 1), (0, 0), (1, 11)], [(1, 1), (1, 0), (0, 0)], [(0, 0), (1, 5), (0, 1)]], dtype=[('a', 'f4'), ('b', 'u1')]) assert_equal(np.count_nonzero(x['a']), 4) @@ -949,7 +829,20 @@ class TestNonzero(TestCase): c[10 + i:20 + i] = True c[20 + i*2] = True assert_equal(np.nonzero(c)[0], - np.concatenate((np.arange(10 +i, 20 + i), [20 +i*2]))) + np.concatenate((np.arange(10 + i, 20 + i), [20 + i*2]))) + + def test_return_type(self): + class C(np.ndarray): + pass + + for view in (C, np.ndarray): + for nd in range(1, 4): + shape = tuple(range(2, 2+nd)) + x = np.arange(np.prod(shape)).reshape(shape).view(view) + for nzx in (np.nonzero(x), x.nonzero()): + for nzx_i in nzx: + assert_(type(nzx_i) is np.ndarray) + assert_(nzx_i.flags.writeable) class TestIndex(TestCase): @@ -959,7 +852,7 @@ class TestIndex(TestCase): g1 = randint(0, 5, size=15) g2 = randint(0, 8, size=15) V[g1, g2] = -V[g1, g2] - assert_((array([a[0][V>0], a[1][V>0], a[2][V>0]]) == a[:, V>0]).all()) + assert_((np.array([a[0][V > 0], a[1][V > 0], a[2][V > 0]]) == a[:, V > 0]).all()) def test_boolean_edgecase(self): a = np.array([], dtype='int32') @@ -971,78 +864,80 @@ class TestIndex(TestCase): class TestBinaryRepr(TestCase): def test_zero(self): - assert_equal(binary_repr(0), '0') + assert_equal(np.binary_repr(0), '0') def test_large(self): - assert_equal(binary_repr(10736848), '101000111101010011010000') + assert_equal(np.binary_repr(10736848), '101000111101010011010000') def test_negative(self): - assert_equal(binary_repr(-1), '-1') - assert_equal(binary_repr(-1, width=8), '11111111') + assert_equal(np.binary_repr(-1), '-1') + assert_equal(np.binary_repr(-1, width=8), '11111111') + class TestBaseRepr(TestCase): def test_base3(self): - assert_equal(base_repr(3**5, 3), '100000') + assert_equal(np.base_repr(3**5, 3), '100000') def test_positive(self): - assert_equal(base_repr(12, 10), '12') - assert_equal(base_repr(12, 10, 4), '000012') - assert_equal(base_repr(12, 4), '30') - assert_equal(base_repr(3731624803700888, 36), '10QR0ROFCEW') + assert_equal(np.base_repr(12, 10), '12') + assert_equal(np.base_repr(12, 10, 4), '000012') + assert_equal(np.base_repr(12, 4), '30') + assert_equal(np.base_repr(3731624803700888, 36), '10QR0ROFCEW') def test_negative(self): - assert_equal(base_repr(-12, 10), '-12') - assert_equal(base_repr(-12, 10, 4), '-000012') - assert_equal(base_repr(-12, 4), '-30') + assert_equal(np.base_repr(-12, 10), '-12') + assert_equal(np.base_repr(-12, 10, 4), '-000012') + assert_equal(np.base_repr(-12, 4), '-30') class TestArrayComparisons(TestCase): def test_array_equal(self): - res = array_equal(array([1, 2]), array([1, 2])) + res = np.array_equal(np.array([1, 2]), np.array([1, 2])) assert_(res) assert_(type(res) is bool) - res = array_equal(array([1, 2]), array([1, 2, 3])) + res = np.array_equal(np.array([1, 2]), np.array([1, 2, 3])) assert_(not res) assert_(type(res) is bool) - res = array_equal(array([1, 2]), array([3, 4])) + res = np.array_equal(np.array([1, 2]), np.array([3, 4])) assert_(not res) assert_(type(res) is bool) - res = array_equal(array([1, 2]), array([1, 3])) + res = np.array_equal(np.array([1, 2]), np.array([1, 3])) assert_(not res) assert_(type(res) is bool) - res = array_equal(array(['a'], dtype='S1'), array(['a'], dtype='S1')) + res = np.array_equal(np.array(['a'], dtype='S1'), np.array(['a'], dtype='S1')) assert_(res) assert_(type(res) is bool) - res = array_equal(array([('a', 1)], dtype='S1,u4'), array([('a', 1)], dtype='S1,u4')) + res = np.array_equal(np.array([('a', 1)], dtype='S1,u4'), + np.array([('a', 1)], dtype='S1,u4')) assert_(res) assert_(type(res) is bool) def test_array_equiv(self): - res = array_equiv(array([1, 2]), array([1, 2])) + res = np.array_equiv(np.array([1, 2]), np.array([1, 2])) assert_(res) assert_(type(res) is bool) - res = array_equiv(array([1, 2]), array([1, 2, 3])) + res = np.array_equiv(np.array([1, 2]), np.array([1, 2, 3])) assert_(not res) assert_(type(res) is bool) - res = array_equiv(array([1, 2]), array([3, 4])) + res = np.array_equiv(np.array([1, 2]), np.array([3, 4])) assert_(not res) assert_(type(res) is bool) - res = array_equiv(array([1, 2]), array([1, 3])) + res = np.array_equiv(np.array([1, 2]), np.array([1, 3])) assert_(not res) assert_(type(res) is bool) - res = array_equiv(array([1, 1]), array([1])) + res = np.array_equiv(np.array([1, 1]), np.array([1])) assert_(res) assert_(type(res) is bool) - res = array_equiv(array([1, 1]), array([[1], [1]])) + res = np.array_equiv(np.array([1, 1]), np.array([[1], [1]])) assert_(res) assert_(type(res) is bool) - res = array_equiv(array([1, 2]), array([2])) + res = np.array_equiv(np.array([1, 2]), np.array([2])) assert_(not res) assert_(type(res) is bool) - res = array_equiv(array([1, 2]), array([[1], [2]])) + res = np.array_equiv(np.array([1, 2]), np.array([[1], [2]])) assert_(not res) assert_(type(res) is bool) - res = array_equiv(array([1, 2]), array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) + res = np.array_equiv(np.array([1, 2]), np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])) assert_(not res) assert_(type(res) is bool) @@ -1077,7 +972,7 @@ class TestClip(TestCase): def clip(self, a, m, M, out=None): # use slow-clip - selector = less(a, m)+2*greater(a, M) + selector = np.less(a, m) + 2*np.greater(a, M) return selector.choose((a, m, M), out=out) # Handy functions @@ -1085,13 +980,13 @@ class TestClip(TestCase): return randn(n, m) def _generate_data_complex(self, n, m): - return randn(n, m) + 1.j *rand(n, m) + return randn(n, m) + 1.j * rand(n, m) def _generate_flt_data(self, n, m): - return (randn(n, m)).astype(float32) + return (randn(n, m)).astype(np.float32) def _neg_byteorder(self, a): - a = asarray(a) + a = np.asarray(a) if sys.byteorder == 'little': a = a.astype(a.dtype.newbyteorder('>')) else: @@ -1105,74 +1000,74 @@ class TestClip(TestCase): return data def _generate_int_data(self, n, m): - return (10 * rand(n, m)).astype(int64) + return (10 * rand(n, m)).astype(np.int64) def _generate_int32_data(self, n, m): - return (10 * rand(n, m)).astype(int32) + return (10 * rand(n, m)).astype(np.int32) # Now the real test cases def test_simple_double(self): #Test native double input with scalar min/max. - a = self._generate_data(self.nr, self.nc) - m = 0.1 - M = 0.6 - ac = self.fastclip(a, m, M) + a = self._generate_data(self.nr, self.nc) + m = 0.1 + M = 0.6 + ac = self.fastclip(a, m, M) act = self.clip(a, m, M) assert_array_strict_equal(ac, act) def test_simple_int(self): #Test native int input with scalar min/max. - a = self._generate_int_data(self.nr, self.nc) - a = a.astype(int) - m = -2 - M = 4 - ac = self.fastclip(a, m, M) + a = self._generate_int_data(self.nr, self.nc) + a = a.astype(int) + m = -2 + M = 4 + ac = self.fastclip(a, m, M) act = self.clip(a, m, M) assert_array_strict_equal(ac, act) def test_array_double(self): #Test native double input with array min/max. - a = self._generate_data(self.nr, self.nc) - m = zeros(a.shape) - M = m + 0.5 - ac = self.fastclip(a, m, M) + a = self._generate_data(self.nr, self.nc) + m = np.zeros(a.shape) + M = m + 0.5 + ac = self.fastclip(a, m, M) act = self.clip(a, m, M) assert_array_strict_equal(ac, act) def test_simple_nonnative(self): #Test non native double input with scalar min/max. #Test native double input with non native double scalar min/max. - a = self._generate_non_native_data(self.nr, self.nc) - m = -0.5 - M = 0.6 - ac = self.fastclip(a, m, M) + a = self._generate_non_native_data(self.nr, self.nc) + m = -0.5 + M = 0.6 + ac = self.fastclip(a, m, M) act = self.clip(a, m, M) assert_array_equal(ac, act) #Test native double input with non native double scalar min/max. - a = self._generate_data(self.nr, self.nc) - m = -0.5 - M = self._neg_byteorder(0.6) + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = self._neg_byteorder(0.6) assert_(not M.dtype.isnative) - ac = self.fastclip(a, m, M) + ac = self.fastclip(a, m, M) act = self.clip(a, m, M) assert_array_equal(ac, act) def test_simple_complex(self): #Test native complex input with native double scalar min/max. #Test native input with complex double scalar min/max. - a = 3 * self._generate_data_complex(self.nr, self.nc) - m = -0.5 - M = 1. - ac = self.fastclip(a, m, M) + a = 3 * self._generate_data_complex(self.nr, self.nc) + m = -0.5 + M = 1. + ac = self.fastclip(a, m, M) act = self.clip(a, m, M) assert_array_strict_equal(ac, act) #Test native input with complex double scalar min/max. - a = 3 * self._generate_data(self.nr, self.nc) - m = -0.5 + 1.j - M = 1. + 2.j - ac = self.fastclip(a, m, M) + a = 3 * self._generate_data(self.nr, self.nc) + m = -0.5 + 1.j + M = 1. + 2.j + ac = self.fastclip(a, m, M) act = self.clip(a, m, M) assert_array_strict_equal(ac, act) @@ -1190,31 +1085,31 @@ class TestClip(TestCase): def test_clip_non_contig(self): #Test clip for non contiguous native input and native scalar min/max. - a = self._generate_data(self.nr * 2, self.nc * 3) - a = a[::2, ::3] + a = self._generate_data(self.nr * 2, self.nc * 3) + a = a[::2, ::3] assert_(not a.flags['F_CONTIGUOUS']) assert_(not a.flags['C_CONTIGUOUS']) - ac = self.fastclip(a, -1.6, 1.7) + ac = self.fastclip(a, -1.6, 1.7) act = self.clip(a, -1.6, 1.7) assert_array_strict_equal(ac, act) def test_simple_out(self): #Test native double input with scalar min/max. - a = self._generate_data(self.nr, self.nc) - m = -0.5 - M = 0.6 - ac = zeros(a.shape) - act = zeros(a.shape) + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = 0.6 + ac = np.zeros(a.shape) + act = np.zeros(a.shape) self.fastclip(a, m, M, ac) self.clip(a, m, M, act) assert_array_strict_equal(ac, act) def test_simple_int32_inout(self): #Test native int32 input with double min/max and int32 out. - a = self._generate_int32_data(self.nr, self.nc) - m = float64(0) - M = float64(2) - ac = zeros(a.shape, dtype = int32) + a = self._generate_int32_data(self.nr, self.nc) + m = np.float64(0) + M = np.float64(2) + ac = np.zeros(a.shape, dtype=np.int32) act = ac.copy() self.fastclip(a, m, M, ac) self.clip(a, m, M, act) @@ -1222,10 +1117,10 @@ class TestClip(TestCase): def test_simple_int64_out(self): #Test native int32 input with int32 scalar min/max and int64 out. - a = self._generate_int32_data(self.nr, self.nc) - m = int32(-1) - M = int32(1) - ac = zeros(a.shape, dtype = int64) + a = self._generate_int32_data(self.nr, self.nc) + m = np.int32(-1) + M = np.int32(1) + ac = np.zeros(a.shape, dtype=np.int64) act = ac.copy() self.fastclip(a, m, M, ac) self.clip(a, m, M, act) @@ -1233,10 +1128,10 @@ class TestClip(TestCase): def test_simple_int64_inout(self): #Test native int32 input with double array min/max and int32 out. - a = self._generate_int32_data(self.nr, self.nc) - m = zeros(a.shape, float64) - M = float64(1) - ac = zeros(a.shape, dtype = int32) + a = self._generate_int32_data(self.nr, self.nc) + m = np.zeros(a.shape, np.float64) + M = np.float64(1) + ac = np.zeros(a.shape, dtype=np.int32) act = ac.copy() self.fastclip(a, m, M, ac) self.clip(a, m, M, act) @@ -1244,10 +1139,10 @@ class TestClip(TestCase): def test_simple_int32_out(self): #Test native double input with scalar min/max and int out. - a = self._generate_data(self.nr, self.nc) - m = -1.0 - M = 2.0 - ac = zeros(a.shape, dtype = int32) + a = self._generate_data(self.nr, self.nc) + m = -1.0 + M = 2.0 + ac = np.zeros(a.shape, dtype=np.int32) act = ac.copy() self.fastclip(a, m, M, ac) self.clip(a, m, M, act) @@ -1255,175 +1150,175 @@ class TestClip(TestCase): def test_simple_inplace_01(self): #Test native double input with array min/max in-place. - a = self._generate_data(self.nr, self.nc) - ac = a.copy() - m = zeros(a.shape) - M = 1.0 + a = self._generate_data(self.nr, self.nc) + ac = a.copy() + m = np.zeros(a.shape) + M = 1.0 self.fastclip(a, m, M, a) self.clip(a, m, M, ac) assert_array_strict_equal(a, ac) def test_simple_inplace_02(self): #Test native double input with scalar min/max in-place. - a = self._generate_data(self.nr, self.nc) - ac = a.copy() - m = -0.5 - M = 0.6 + a = self._generate_data(self.nr, self.nc) + ac = a.copy() + m = -0.5 + M = 0.6 self.fastclip(a, m, M, a) self.clip(a, m, M, ac) assert_array_strict_equal(a, ac) def test_noncontig_inplace(self): #Test non contiguous double input with double scalar min/max in-place. - a = self._generate_data(self.nr * 2, self.nc * 3) - a = a[::2, ::3] + a = self._generate_data(self.nr * 2, self.nc * 3) + a = a[::2, ::3] assert_(not a.flags['F_CONTIGUOUS']) assert_(not a.flags['C_CONTIGUOUS']) - ac = a.copy() - m = -0.5 - M = 0.6 + ac = a.copy() + m = -0.5 + M = 0.6 self.fastclip(a, m, M, a) self.clip(a, m, M, ac) assert_array_equal(a, ac) def test_type_cast_01(self): #Test native double input with scalar min/max. - a = self._generate_data(self.nr, self.nc) - m = -0.5 - M = 0.6 - ac = self.fastclip(a, m, M) + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = 0.6 + ac = self.fastclip(a, m, M) act = self.clip(a, m, M) assert_array_strict_equal(ac, act) def test_type_cast_02(self): #Test native int32 input with int32 scalar min/max. - a = self._generate_int_data(self.nr, self.nc) - a = a.astype(int32) - m = -2 - M = 4 - ac = self.fastclip(a, m, M) + a = self._generate_int_data(self.nr, self.nc) + a = a.astype(np.int32) + m = -2 + M = 4 + ac = self.fastclip(a, m, M) act = self.clip(a, m, M) assert_array_strict_equal(ac, act) def test_type_cast_03(self): #Test native int32 input with float64 scalar min/max. - a = self._generate_int32_data(self.nr, self.nc) - m = -2 - M = 4 - ac = self.fastclip(a, float64(m), float64(M)) - act = self.clip(a, float64(m), float64(M)) + a = self._generate_int32_data(self.nr, self.nc) + m = -2 + M = 4 + ac = self.fastclip(a, np.float64(m), np.float64(M)) + act = self.clip(a, np.float64(m), np.float64(M)) assert_array_strict_equal(ac, act) def test_type_cast_04(self): #Test native int32 input with float32 scalar min/max. - a = self._generate_int32_data(self.nr, self.nc) - m = float32(-2) - M = float32(4) + a = self._generate_int32_data(self.nr, self.nc) + m = np.float32(-2) + M = np.float32(4) act = self.fastclip(a, m, M) - ac = self.clip(a, m, M) + ac = self.clip(a, m, M) assert_array_strict_equal(ac, act) def test_type_cast_05(self): #Test native int32 with double arrays min/max. - a = self._generate_int_data(self.nr, self.nc) - m = -0.5 - M = 1. - ac = self.fastclip(a, m * zeros(a.shape), M) - act = self.clip(a, m * zeros(a.shape), M) + a = self._generate_int_data(self.nr, self.nc) + m = -0.5 + M = 1. + ac = self.fastclip(a, m * np.zeros(a.shape), M) + act = self.clip(a, m * np.zeros(a.shape), M) assert_array_strict_equal(ac, act) def test_type_cast_06(self): #Test native with NON native scalar min/max. - a = self._generate_data(self.nr, self.nc) - m = 0.5 + a = self._generate_data(self.nr, self.nc) + m = 0.5 m_s = self._neg_byteorder(m) - M = 1. + M = 1. act = self.clip(a, m_s, M) - ac = self.fastclip(a, m_s, M) + ac = self.fastclip(a, m_s, M) assert_array_strict_equal(ac, act) def test_type_cast_07(self): #Test NON native with native array min/max. - a = self._generate_data(self.nr, self.nc) - m = -0.5 * ones(a.shape) - M = 1. + a = self._generate_data(self.nr, self.nc) + m = -0.5 * np.ones(a.shape) + M = 1. a_s = self._neg_byteorder(a) assert_(not a_s.dtype.isnative) act = a_s.clip(m, M) - ac = self.fastclip(a_s, m, M) + ac = self.fastclip(a_s, m, M) assert_array_strict_equal(ac, act) def test_type_cast_08(self): #Test NON native with native scalar min/max. - a = self._generate_data(self.nr, self.nc) - m = -0.5 - M = 1. + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = 1. a_s = self._neg_byteorder(a) assert_(not a_s.dtype.isnative) - ac = self.fastclip(a_s, m, M) + ac = self.fastclip(a_s, m, M) act = a_s.clip(m, M) assert_array_strict_equal(ac, act) def test_type_cast_09(self): #Test native with NON native array min/max. - a = self._generate_data(self.nr, self.nc) - m = -0.5 * ones(a.shape) - M = 1. + a = self._generate_data(self.nr, self.nc) + m = -0.5 * np.ones(a.shape) + M = 1. m_s = self._neg_byteorder(m) assert_(not m_s.dtype.isnative) - ac = self.fastclip(a, m_s, M) + ac = self.fastclip(a, m_s, M) act = self.clip(a, m_s, M) assert_array_strict_equal(ac, act) def test_type_cast_10(self): #Test native int32 with float min/max and float out for output argument. - a = self._generate_int_data(self.nr, self.nc) - b = zeros(a.shape, dtype = float32) - m = float32(-0.5) - M = float32(1) - act = self.clip(a, m, M, out = b) - ac = self.fastclip(a, m, M, out = b) + a = self._generate_int_data(self.nr, self.nc) + b = np.zeros(a.shape, dtype=np.float32) + m = np.float32(-0.5) + M = np.float32(1) + act = self.clip(a, m, M, out=b) + ac = self.fastclip(a, m, M, out=b) assert_array_strict_equal(ac, act) def test_type_cast_11(self): #Test non native with native scalar, min/max, out non native - a = self._generate_non_native_data(self.nr, self.nc) - b = a.copy() - b = b.astype(b.dtype.newbyteorder('>')) - bt = b.copy() - m = -0.5 - M = 1. - self.fastclip(a, m, M, out = b) - self.clip(a, m, M, out = bt) + a = self._generate_non_native_data(self.nr, self.nc) + b = a.copy() + b = b.astype(b.dtype.newbyteorder('>')) + bt = b.copy() + m = -0.5 + M = 1. + self.fastclip(a, m, M, out=b) + self.clip(a, m, M, out=bt) assert_array_strict_equal(b, bt) def test_type_cast_12(self): #Test native int32 input and min/max and float out - a = self._generate_int_data(self.nr, self.nc) - b = zeros(a.shape, dtype = float32) - m = int32(0) - M = int32(1) - act = self.clip(a, m, M, out = b) - ac = self.fastclip(a, m, M, out = b) + a = self._generate_int_data(self.nr, self.nc) + b = np.zeros(a.shape, dtype=np.float32) + m = np.int32(0) + M = np.int32(1) + act = self.clip(a, m, M, out=b) + ac = self.fastclip(a, m, M, out=b) assert_array_strict_equal(ac, act) def test_clip_with_out_simple(self): #Test native double input with scalar min/max - a = self._generate_data(self.nr, self.nc) - m = -0.5 - M = 0.6 - ac = zeros(a.shape) - act = zeros(a.shape) + a = self._generate_data(self.nr, self.nc) + m = -0.5 + M = 0.6 + ac = np.zeros(a.shape) + act = np.zeros(a.shape) self.fastclip(a, m, M, ac) self.clip(a, m, M, act) assert_array_strict_equal(ac, act) def test_clip_with_out_simple2(self): #Test native int32 input with double min/max and int32 out - a = self._generate_int32_data(self.nr, self.nc) - m = float64(0) - M = float64(2) - ac = zeros(a.shape, dtype = int32) + a = self._generate_int32_data(self.nr, self.nc) + m = np.float64(0) + M = np.float64(2) + ac = np.zeros(a.shape, dtype=np.int32) act = ac.copy() self.fastclip(a, m, M, ac) self.clip(a, m, M, act) @@ -1431,10 +1326,10 @@ class TestClip(TestCase): def test_clip_with_out_simple_int32(self): #Test native int32 input with int32 scalar min/max and int64 out - a = self._generate_int32_data(self.nr, self.nc) - m = int32(-1) - M = int32(1) - ac = zeros(a.shape, dtype = int64) + a = self._generate_int32_data(self.nr, self.nc) + m = np.int32(-1) + M = np.int32(1) + ac = np.zeros(a.shape, dtype=np.int64) act = ac.copy() self.fastclip(a, m, M, ac) self.clip(a, m, M, act) @@ -1442,10 +1337,10 @@ class TestClip(TestCase): def test_clip_with_out_array_int32(self): #Test native int32 input with double array min/max and int32 out - a = self._generate_int32_data(self.nr, self.nc) - m = zeros(a.shape, float64) - M = float64(1) - ac = zeros(a.shape, dtype = int32) + a = self._generate_int32_data(self.nr, self.nc) + m = np.zeros(a.shape, np.float64) + M = np.float64(1) + ac = np.zeros(a.shape, dtype=np.int32) act = ac.copy() self.fastclip(a, m, M, ac) self.clip(a, m, M, act) @@ -1453,10 +1348,10 @@ class TestClip(TestCase): def test_clip_with_out_array_outint32(self): #Test native double input with scalar min/max and int out - a = self._generate_data(self.nr, self.nc) - m = -1.0 - M = 2.0 - ac = zeros(a.shape, dtype = int32) + a = self._generate_data(self.nr, self.nc) + m = -1.0 + M = 2.0 + ac = np.zeros(a.shape, dtype=np.int32) act = ac.copy() self.fastclip(a, m, M, ac) self.clip(a, m, M, act) @@ -1464,20 +1359,20 @@ class TestClip(TestCase): def test_clip_inplace_array(self): #Test native double input with array min/max - a = self._generate_data(self.nr, self.nc) - ac = a.copy() - m = zeros(a.shape) - M = 1.0 + a = self._generate_data(self.nr, self.nc) + ac = a.copy() + m = np.zeros(a.shape) + M = 1.0 self.fastclip(a, m, M, a) self.clip(a, m, M, ac) assert_array_strict_equal(a, ac) def test_clip_inplace_simple(self): #Test native double input with scalar min/max - a = self._generate_data(self.nr, self.nc) - ac = a.copy() - m = -0.5 - M = 0.6 + a = self._generate_data(self.nr, self.nc) + ac = a.copy() + m = -0.5 + M = 0.6 self.fastclip(a, m, M, a) self.clip(a, m, M, ac) assert_array_strict_equal(a, ac) @@ -1488,7 +1383,7 @@ class TestClip(TestCase): ac = a.copy() m = -0.5 M = 0.6 - a2 = clip(a, m, M, out=a) + a2 = np.clip(a, m, M, out=a) self.clip(a, m, M, ac) assert_array_strict_equal(a2, ac) self.assertTrue(a2 is a) @@ -1513,15 +1408,15 @@ class TestAllclose(object): np.seterr(**self.olderr) def tst_allclose(self, x, y): - assert_(allclose(x, y), "%s and %s not close" % (x, y)) + assert_(np.allclose(x, y), "%s and %s not close" % (x, y)) def tst_not_allclose(self, x, y): - assert_(not allclose(x, y), "%s and %s shouldn't be close" % (x, y)) + assert_(not np.allclose(x, y), "%s and %s shouldn't be close" % (x, y)) def test_ip_allclose(self): #Parametric test factory. - arr = array([100, 1000]) - aran = arange(125).reshape((5, 5, 5)) + arr = np.array([100, 1000]) + aran = np.arange(125).reshape((5, 5, 5)) atol = self.atol rtol = self.rtol @@ -1532,51 +1427,49 @@ class TestAllclose(object): (arr, arr + arr*rtol), (arr, arr + arr*rtol + atol*2), (aran, aran + aran*rtol), - (inf, inf), - (inf, [inf])] + (np.inf, np.inf), + (np.inf, [np.inf])] for (x, y) in data: yield (self.tst_allclose, x, y) def test_ip_not_allclose(self): #Parametric test factory. - aran = arange(125).reshape((5, 5, 5)) + aran = np.arange(125).reshape((5, 5, 5)) atol = self.atol rtol = self.rtol - data = [([inf, 0], [1, inf]), - ([inf, 0], [1, 0]), - ([inf, inf], [1, inf]), - ([inf, inf], [1, 0]), - ([-inf, 0], [inf, 0]), - ([nan, 0], [nan, 0]), + data = [([np.inf, 0], [1, np.inf]), + ([np.inf, 0], [1, 0]), + ([np.inf, np.inf], [1, np.inf]), + ([np.inf, np.inf], [1, 0]), + ([-np.inf, 0], [np.inf, 0]), + ([np.nan, 0], [np.nan, 0]), ([atol*2], [0]), ([1], [1+rtol+atol*2]), (aran, aran + aran*atol + atol*2), - (array([inf, 1]), array([0, inf]))] + (np.array([np.inf, 1]), np.array([0, np.inf]))] for (x, y) in data: yield (self.tst_not_allclose, x, y) def test_no_parameter_modification(self): - x = array([inf, 1]) - y = array([0, inf]) - allclose(x, y) - assert_array_equal(x, array([inf, 1])) - assert_array_equal(y, array([0, inf])) - + x = np.array([np.inf, 1]) + y = np.array([0, np.inf]) + np.allclose(x, y) + assert_array_equal(x, np.array([np.inf, 1])) + assert_array_equal(y, np.array([0, np.inf])) def test_min_int(self): # Could make problems because of abs(min_int) == min_int min_int = np.iinfo(np.int_).min a = np.array([min_int], dtype=np.int_) - assert_(allclose(a, a)) - + assert_(np.allclose(a, a)) def test_equalnan(self): x = np.array([1.0, np.nan]) - assert_(allclose(x, x, equal_nan=True)) + assert_(np.allclose(x, x, equal_nan=True)) class TestIsclose(object): @@ -1586,8 +1479,8 @@ class TestIsclose(object): def setup(self): atol = self.atol rtol = self.rtol - arr = array([100, 1000]) - aran = arange(125).reshape((5, 5, 5)) + arr = np.array([100, 1000]) + aran = np.arange(125).reshape((5, 5, 5)) self.all_close_tests = [ ([1, 0], [1, 0]), @@ -1596,28 +1489,28 @@ class TestIsclose(object): (arr, arr + arr*rtol), (arr, arr + arr*rtol + atol), (aran, aran + aran*rtol), - (inf, inf), - (inf, [inf]), - ([inf, -inf], [inf, -inf]), + (np.inf, np.inf), + (np.inf, [np.inf]), + ([np.inf, -np.inf], [np.inf, -np.inf]), ] self.none_close_tests = [ - ([inf, 0], [1, inf]), - ([inf, -inf], [1, 0]), - ([inf, inf], [1, -inf]), - ([inf, inf], [1, 0]), - ([nan, 0], [nan, -inf]), + ([np.inf, 0], [1, np.inf]), + ([np.inf, -np.inf], [1, 0]), + ([np.inf, np.inf], [1, -np.inf]), + ([np.inf, np.inf], [1, 0]), + ([np.nan, 0], [np.nan, -np.inf]), ([atol*2], [0]), ([1], [1 + rtol + atol*2]), (aran, aran + rtol*1.1*aran + atol*1.1), - (array([inf, 1]), array([0, inf])), + (np.array([np.inf, 1]), np.array([0, np.inf])), ] self.some_close_tests = [ - ([inf, 0], [inf, atol*2]), - ([atol, 1, 1e6*(1 + 2*rtol) + atol], [0, nan, 1e6]), - (arange(3), [0, 1, 2.1]), - (nan, [nan, nan, nan]), - ([0], [atol, inf, -inf, nan]), - (0, [atol, inf, -inf, nan]), + ([np.inf, 0], [np.inf, atol*2]), + ([atol, 1, 1e6*(1 + 2*rtol) + atol], [0, np.nan, 1e6]), + (np.arange(3), [0, 1, 2.1]), + (np.nan, [np.nan, np.nan, np.nan]), + ([0], [atol, np.inf, -np.inf, np.nan]), + (0, [atol, np.inf, -np.inf, np.nan]), ] self.some_close_results = [ [True, False], @@ -1633,18 +1526,18 @@ class TestIsclose(object): tests = self.some_close_tests results = self.some_close_results for (x, y), result in zip(tests, results): - yield (assert_array_equal, isclose(x, y), result) + yield (assert_array_equal, np.isclose(x, y), result) def tst_all_isclose(self, x, y): - assert_(all(isclose(x, y)), "%s and %s not close" % (x, y)) + assert_(np.all(np.isclose(x, y)), "%s and %s not close" % (x, y)) def tst_none_isclose(self, x, y): msg = "%s and %s shouldn't be close" - assert_(not any(isclose(x, y)), msg % (x, y)) + assert_(not np.any(np.isclose(x, y)), msg % (x, y)) def tst_isclose_allclose(self, x, y): msg = "isclose.all() and allclose aren't same for %s and %s" - assert_array_equal(isclose(x, y).all(), allclose(x, y), msg % (x, y)) + assert_array_equal(np.isclose(x, y).all(), np.allclose(x, y), msg % (x, y)) def test_ip_all_isclose(self): self.setup() @@ -1664,70 +1557,70 @@ class TestIsclose(object): yield (self.tst_isclose_allclose, x, y) def test_equal_nan(self): - assert_array_equal(isclose(nan, nan, equal_nan=True), [True]) - arr = array([1.0, nan]) - assert_array_equal(isclose(arr, arr, equal_nan=True), [True, True]) + assert_array_equal(np.isclose(np.nan, np.nan, equal_nan=True), [True]) + arr = np.array([1.0, np.nan]) + assert_array_equal(np.isclose(arr, arr, equal_nan=True), [True, True]) def test_masked_arrays(self): # Make sure to test the output type when arguments are interchanged. x = np.ma.masked_where([True, True, False], np.arange(3)) - assert_(type(x) is type(isclose(2, x))) - assert_(type(x) is type(isclose(x, 2))) + assert_(type(x) is type(np.isclose(2, x))) + assert_(type(x) is type(np.isclose(x, 2))) - x = np.ma.masked_where([True, True, False], [nan, inf, nan]) - assert_(type(x) is type(isclose(inf, x))) - assert_(type(x) is type(isclose(x, inf))) + x = np.ma.masked_where([True, True, False], [np.nan, np.inf, np.nan]) + assert_(type(x) is type(np.isclose(np.inf, x))) + assert_(type(x) is type(np.isclose(x, np.inf))) - x = np.ma.masked_where([True, True, False], [nan, nan, nan]) - y = isclose(nan, x, equal_nan=True) + x = np.ma.masked_where([True, True, False], [np.nan, np.nan, np.nan]) + y = np.isclose(np.nan, x, equal_nan=True) assert_(type(x) is type(y)) # Ensure that the mask isn't modified... assert_array_equal([True, True, False], y.mask) - y = isclose(x, nan, equal_nan=True) + y = np.isclose(x, np.nan, equal_nan=True) assert_(type(x) is type(y)) # Ensure that the mask isn't modified... assert_array_equal([True, True, False], y.mask) - x = np.ma.masked_where([True, True, False], [nan, nan, nan]) - y = isclose(x, x, equal_nan=True) + x = np.ma.masked_where([True, True, False], [np.nan, np.nan, np.nan]) + y = np.isclose(x, x, equal_nan=True) assert_(type(x) is type(y)) # Ensure that the mask isn't modified... assert_array_equal([True, True, False], y.mask) def test_scalar_return(self): - assert_(isscalar(isclose(1, 1))) + assert_(np.isscalar(np.isclose(1, 1))) def test_no_parameter_modification(self): - x = array([inf, 1]) - y = array([0, inf]) - isclose(x, y) - assert_array_equal(x, array([inf, 1])) - assert_array_equal(y, array([0, inf])) + x = np.array([np.inf, 1]) + y = np.array([0, np.inf]) + np.isclose(x, y) + assert_array_equal(x, np.array([np.inf, 1])) + assert_array_equal(y, np.array([0, np.inf])) class TestStdVar(TestCase): def setUp(self): - self.A = array([1, -1, 1, -1]) + self.A = np.array([1, -1, 1, -1]) self.real_var = 1 def test_basic(self): - assert_almost_equal(var(self.A), self.real_var) - assert_almost_equal(std(self.A)**2, self.real_var) + assert_almost_equal(np.var(self.A), self.real_var) + assert_almost_equal(np.std(self.A)**2, self.real_var) def test_scalars(self): - assert_equal(var(1), 0) - assert_equal(std(1), 0) + assert_equal(np.var(1), 0) + assert_equal(np.std(1), 0) def test_ddof1(self): - assert_almost_equal(var(self.A, ddof=1), + assert_almost_equal(np.var(self.A, ddof=1), self.real_var*len(self.A)/float(len(self.A)-1)) - assert_almost_equal(std(self.A, ddof=1)**2, + assert_almost_equal(np.std(self.A, ddof=1)**2, self.real_var*len(self.A)/float(len(self.A)-1)) def test_ddof2(self): - assert_almost_equal(var(self.A, ddof=2), + assert_almost_equal(np.var(self.A, ddof=2), self.real_var*len(self.A)/float(len(self.A)-2)) - assert_almost_equal(std(self.A, ddof=2)**2, + assert_almost_equal(np.std(self.A, ddof=2)**2, self.real_var*len(self.A)/float(len(self.A)-2)) def test_out_scalar(self): @@ -1746,14 +1639,14 @@ class TestStdVar(TestCase): class TestStdVarComplex(TestCase): def test_basic(self): - A = array([1, 1.j, -1, -1.j]) + A = np.array([1, 1.j, -1, -1.j]) real_var = 1 - assert_almost_equal(var(A), real_var) - assert_almost_equal(std(A)**2, real_var) + assert_almost_equal(np.var(A), real_var) + assert_almost_equal(np.std(A)**2, real_var) def test_scalars(self): - assert_equal(var(1j), 0) - assert_equal(std(1j), 0) + assert_equal(np.var(1j), 0) + assert_equal(np.std(1j), 0) class TestCreationFuncs(TestCase): @@ -1781,7 +1674,7 @@ class TestCreationFuncs(TestCase): shape = ndims * [size] try: dtype = np.dtype('{0}{1}'.format(type, bytes)) - except TypeError: # dtype combination does not exist + except TypeError: # dtype combination does not exist continue else: # do not fill void type @@ -1828,33 +1721,32 @@ class TestCreationFuncs(TestCase): assert_(sys.getrefcount(dim) == beg) - class TestLikeFuncs(TestCase): '''Test ones_like, zeros_like, empty_like and full_like''' def setUp(self): self.data = [ # Array scalars - (array(3.), None), - (array(3), 'f8'), + (np.array(3.), None), + (np.array(3), 'f8'), # 1D arrays - (arange(6, dtype='f4'), None), - (arange(6), 'c16'), + (np.arange(6, dtype='f4'), None), + (np.arange(6), 'c16'), # 2D C-layout arrays - (arange(6).reshape(2, 3), None), - (arange(6).reshape(3, 2), 'i1'), + (np.arange(6).reshape(2, 3), None), + (np.arange(6).reshape(3, 2), 'i1'), # 2D F-layout arrays - (arange(6).reshape((2, 3), order='F'), None), - (arange(6).reshape((3, 2), order='F'), 'i1'), + (np.arange(6).reshape((2, 3), order='F'), None), + (np.arange(6).reshape((3, 2), order='F'), 'i1'), # 3D C-layout arrays - (arange(24).reshape(2, 3, 4), None), - (arange(24).reshape(4, 3, 2), 'f4'), + (np.arange(24).reshape(2, 3, 4), None), + (np.arange(24).reshape(4, 3, 2), 'f4'), # 3D F-layout arrays - (arange(24).reshape((2, 3, 4), order='F'), None), - (arange(24).reshape((4, 3, 2), order='F'), 'f4'), + (np.arange(24).reshape((2, 3, 4), order='F'), None), + (np.arange(24).reshape((4, 3, 2), order='F'), 'f4'), # 3D non-C/F-layout arrays - (arange(24).reshape(2, 3, 4).swapaxes(0, 1), None), - (arange(24).reshape(4, 3, 2).swapaxes(0, 1), '?'), + (np.arange(24).reshape(2, 3, 4).swapaxes(0, 1), None), + (np.arange(24).reshape(4, 3, 2).swapaxes(0, 1), '?'), ] def compare_array_value(self, dz, value, fill_value): @@ -1865,9 +1757,9 @@ class TestLikeFuncs(TestCase): except OverflowError: pass else: - assert_(all(dz == z)) + assert_(np.all(dz == z)) else: - assert_(all(dz == value)) + assert_(np.all(dz == value)) def check_like_function(self, like_function, value, fill_value=False): if fill_value: @@ -1878,8 +1770,8 @@ class TestLikeFuncs(TestCase): # default (K) order, dtype dz = like_function(d, dtype=dtype, **fill_kwarg) assert_equal(dz.shape, d.shape) - assert_equal(array(dz.strides)*d.dtype.itemsize, - array(d.strides)*dz.dtype.itemsize) + assert_equal(np.array(dz.strides)*d.dtype.itemsize, + np.array(d.strides)*dz.dtype.itemsize) assert_equal(d.flags.c_contiguous, dz.flags.c_contiguous) assert_equal(d.flags.f_contiguous, dz.flags.f_contiguous) if dtype is None: @@ -1946,7 +1838,7 @@ class TestLikeFuncs(TestCase): self.check_like_function(np.full_like, 123.456, True) self.check_like_function(np.full_like, np.inf, True) -class _TestCorrelate(TestCase): +class TestCorrelate(TestCase): def _setup(self, dt): self.x = np.array([1, 2, 3, 4, 5], dtype=dt) self.xs = np.arange(1, 20)[::3] @@ -1961,24 +1853,24 @@ class _TestCorrelate(TestCase): def test_float(self): self._setup(np.float) - z = np.correlate(self.x, self.y, 'full', old_behavior=self.old_behavior) + z = np.correlate(self.x, self.y, 'full') assert_array_almost_equal(z, self.z1) - z = np.correlate(self.x, self.y[:-1], 'full', old_behavior=self.old_behavior) + z = np.correlate(self.x, self.y[:-1], 'full') assert_array_almost_equal(z, self.z1_4) - z = np.correlate(self.y, self.x, 'full', old_behavior=self.old_behavior) + z = np.correlate(self.y, self.x, 'full') assert_array_almost_equal(z, self.z2) - z = np.correlate(self.x[::-1], self.y, 'full', old_behavior=self.old_behavior) + z = np.correlate(self.x[::-1], self.y, 'full') assert_array_almost_equal(z, self.z1r) - z = np.correlate(self.y, self.x[::-1], 'full', old_behavior=self.old_behavior) + z = np.correlate(self.y, self.x[::-1], 'full') assert_array_almost_equal(z, self.z2r) - z = np.correlate(self.xs, self.y, 'full', old_behavior=self.old_behavior) + z = np.correlate(self.xs, self.y, 'full') assert_array_almost_equal(z, self.zs) def test_object(self): self._setup(Decimal) - z = np.correlate(self.x, self.y, 'full', old_behavior=self.old_behavior) + z = np.correlate(self.x, self.y, 'full') assert_array_almost_equal(z, self.z1) - z = np.correlate(self.y, self.x, 'full', old_behavior=self.old_behavior) + z = np.correlate(self.y, self.x, 'full') assert_array_almost_equal(z, self.z2) def test_no_overwrite(self): @@ -1988,45 +1880,15 @@ class _TestCorrelate(TestCase): assert_array_equal(d, np.ones(100)) assert_array_equal(k, np.ones(3)) -class TestCorrelate(_TestCorrelate): - old_behavior = True - def _setup(self, dt): - # correlate uses an unconventional definition so that correlate(a, b) - # == correlate(b, a), so force the corresponding outputs to be the same - # as well - _TestCorrelate._setup(self, dt) - self.z2 = self.z1 - self.z2r = self.z1r - - @dec.deprecated() - def test_complex(self): - x = np.array([1, 2, 3, 4+1j], dtype=np.complex) - y = np.array([-1, -2j, 3+1j], dtype=np.complex) - r_z = np.array([3+1j, 6, 8-1j, 9+1j, -1-8j, -4-1j], dtype=np.complex) - z = np.correlate(x, y, 'full', old_behavior=self.old_behavior) - assert_array_almost_equal(z, r_z) - - @dec.deprecated() - def test_float(self): - _TestCorrelate.test_float(self) - - @dec.deprecated() - def test_object(self): - _TestCorrelate.test_object(self) - -class TestCorrelateNew(_TestCorrelate): - old_behavior = False def test_complex(self): x = np.array([1, 2, 3, 4+1j], dtype=np.complex) y = np.array([-1, -2j, 3+1j], dtype=np.complex) r_z = np.array([3-1j, 6, 8+1j, 11+5j, -5+8j, -4-1j], dtype=np.complex) - #z = np.acorrelate(x, y, 'full') - #assert_array_almost_equal(z, r_z) - r_z = r_z[::-1].conjugate() - z = np.correlate(y, x, 'full', old_behavior=self.old_behavior) + z = np.correlate(y, x, mode='full') assert_array_almost_equal(z, r_z) + class TestConvolve(TestCase): def test_object(self): d = [1.] * 100 @@ -2105,36 +1967,36 @@ class TestRollaxis(TestCase): (3, 4): (1, 2, 3, 4)} def test_exceptions(self): - a = arange(1*2*3*4).reshape(1, 2, 3, 4) - assert_raises(ValueError, rollaxis, a, -5, 0) - assert_raises(ValueError, rollaxis, a, 0, -5) - assert_raises(ValueError, rollaxis, a, 4, 0) - assert_raises(ValueError, rollaxis, a, 0, 5) + a = np.arange(1*2*3*4).reshape(1, 2, 3, 4) + assert_raises(ValueError, np.rollaxis, a, -5, 0) + assert_raises(ValueError, np.rollaxis, a, 0, -5) + assert_raises(ValueError, np.rollaxis, a, 4, 0) + assert_raises(ValueError, np.rollaxis, a, 0, 5) def test_results(self): - a = arange(1*2*3*4).reshape(1, 2, 3, 4).copy() + a = np.arange(1*2*3*4).reshape(1, 2, 3, 4).copy() aind = np.indices(a.shape) assert_(a.flags['OWNDATA']) for (i, j) in self.tgtshape: # positive axis, positive start - res = rollaxis(a, axis=i, start=j) - i0, i1, i2, i3 = aind[np.array(res.shape) - 1] + res = np.rollaxis(a, axis=i, start=j) + i0, i1, i2, i3 = aind[np.array(res.shape) - 1] assert_(np.all(res[i0, i1, i2, i3] == a)) assert_(res.shape == self.tgtshape[(i, j)], str((i,j))) assert_(not res.flags['OWNDATA']) # negative axis, positive start ip = i + 1 - res = rollaxis(a, axis=-ip, start=j) - i0, i1, i2, i3 = aind[np.array(res.shape) - 1] + res = np.rollaxis(a, axis=-ip, start=j) + i0, i1, i2, i3 = aind[np.array(res.shape) - 1] assert_(np.all(res[i0, i1, i2, i3] == a)) assert_(res.shape == self.tgtshape[(4 - ip, j)]) assert_(not res.flags['OWNDATA']) # positive axis, negative start jp = j + 1 if j < 4 else j - res = rollaxis(a, axis=i, start=-jp) - i0, i1, i2, i3 = aind[np.array(res.shape) - 1] + res = np.rollaxis(a, axis=i, start=-jp) + i0, i1, i2, i3 = aind[np.array(res.shape) - 1] assert_(np.all(res[i0, i1, i2, i3] == a)) assert_(res.shape == self.tgtshape[(i, 4 - jp)]) assert_(not res.flags['OWNDATA']) @@ -2142,8 +2004,8 @@ class TestRollaxis(TestCase): # negative axis, negative start ip = i + 1 jp = j + 1 if j < 4 else j - res = rollaxis(a, axis=-ip, start=-jp) - i0, i1, i2, i3 = aind[np.array(res.shape) - 1] + res = np.rollaxis(a, axis=-ip, start=-jp) + i0, i1, i2, i3 = aind[np.array(res.shape) - 1] assert_(np.all(res[i0, i1, i2, i3] == a)) assert_(res.shape == self.tgtshape[(4 - ip, 4 - jp)]) assert_(not res.flags['OWNDATA']) @@ -2172,7 +2034,7 @@ class TestCross(TestCase): u = [1, 2, 3] v = [4, 5, 6] z = np.array([-3, 6, -3]) - cp = cross(u, v) + cp = np.cross(u, v) assert_equal(cp, z) cp = np.cross(v, u) assert_equal(cp, -z) @@ -2221,6 +2083,11 @@ class TestCross(TestCase): assert_equal(np.cross(u, v, axisa=1, axisc=2).shape, (10, 5, 3, 7)) assert_raises(ValueError, np.cross, u, v, axisa=-5, axisb=2) assert_raises(ValueError, np.cross, u, v, axisa=1, axisb=-4) + # gh-5885 + u = np.ones((3, 4, 2)) + for axisc in range(-2, 2): + assert_equal(np.cross(u, u, axisc=axisc).shape, (3, 4)) + def test_outer_out_param(): arr1 = np.ones((5,)) @@ -2232,6 +2099,7 @@ def test_outer_out_param(): assert_equal(res1, out1) assert_equal(np.outer(arr2, arr3, out2), out2) + class TestRequire(object): flag_names = ['C', 'C_CONTIGUOUS', 'CONTIGUOUS', 'F', 'F_CONTIGUOUS', 'FORTRAN', @@ -2290,7 +2158,7 @@ class TestRequire(object): assert_raises(ValueError, np.require, a, None, ['C', 'F']) def test_ensure_array(self): - class ArraySubclass(ndarray): + class ArraySubclass(np.ndarray): pass a = ArraySubclass((2,2)) @@ -2298,7 +2166,7 @@ class TestRequire(object): assert_(type(b) is np.ndarray) def test_preserve_subtype(self): - class ArraySubclass(ndarray): + class ArraySubclass(np.ndarray): pass for flag in self.flag_names: @@ -2306,5 +2174,31 @@ class TestRequire(object): yield self.set_and_check_flag, flag, None, a +class TestBroadcast(TestCase): + def test_broadcast_in_args(self): + # gh-5881 + arrs = [np.empty((6, 7)), np.empty((5, 6, 1)), np.empty((7,)), + np.empty((5, 1, 7))] + mits = [np.broadcast(*arrs), + np.broadcast(np.broadcast(*arrs[:2]), np.broadcast(*arrs[2:])), + np.broadcast(arrs[0], np.broadcast(*arrs[1:-1]), arrs[-1])] + for mit in mits: + assert_equal(mit.shape, (5, 6, 7)) + assert_equal(mit.nd, 3) + assert_equal(mit.numiter, 4) + for a, ia in zip(arrs, mit.iters): + assert_(a is ia.base) + + def test_number_of_arguments(self): + arr = np.empty((5,)) + for j in range(35): + arrs = [arr] * j + if j < 2 or j > 32: + assert_raises(ValueError, np.broadcast, *arrs) + else: + mit = np.broadcast(*arrs) + assert_equal(mit.numiter, j) + + if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_numerictypes.py b/numpy/core/tests/test_numerictypes.py index 077e94475..a7bbe0192 100644 --- a/numpy/core/tests/test_numerictypes.py +++ b/numpy/core/tests/test_numerictypes.py @@ -1,9 +1,12 @@ from __future__ import division, absolute_import, print_function import sys -from numpy.testing import * -from numpy.compat import asbytes, asunicode + import numpy as np +from numpy.compat import asbytes, asunicode +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal +) # This is the structure of the table used for plain objects: # @@ -91,7 +94,7 @@ def normalize_descr(descr): l.append(j) out.append((item[0], l)) else: - raise ValueError("Expected a str or list and got %s" % \ + raise ValueError("Expected a str or list and got %s" % (type(item))) return out @@ -238,7 +241,6 @@ class test_read_values_plain_multiple(read_values_plain, TestCase): class read_values_nested(object): """Check the reading of values in heterogeneous arrays (nested)""" - def test_access_top_fields(self): """Check reading the top fields of a nested array""" h = np.array(self._buffer, dtype=self._descr) @@ -256,7 +258,6 @@ class read_values_nested(object): assert_equal(h['z'], np.array([self._buffer[0][5], self._buffer[1][5]], dtype='u1')) - def test_nested1_acessors(self): """Check reading the nested fields of a nested array (1st level)""" h = np.array(self._buffer, dtype=self._descr) @@ -346,26 +347,33 @@ class TestCommonType(TestCase): def test_scalar_loses1(self): res = np.find_common_type(['f4', 'f4', 'i2'], ['f8']) assert_(res == 'f4') + def test_scalar_loses2(self): res = np.find_common_type(['f4', 'f4'], ['i8']) assert_(res == 'f4') + def test_scalar_wins(self): res = np.find_common_type(['f4', 'f4', 'i2'], ['c8']) assert_(res == 'c8') + def test_scalar_wins2(self): res = np.find_common_type(['u4', 'i4', 'i4'], ['f4']) assert_(res == 'f8') - def test_scalar_wins3(self): # doesn't go up to 'f16' on purpose + + def test_scalar_wins3(self): # doesn't go up to 'f16' on purpose res = np.find_common_type(['u8', 'i8', 'i8'], ['f8']) assert_(res == 'f8') class TestMultipleFields(TestCase): def setUp(self): self.ary = np.array([(1, 2, 3, 4), (5, 6, 7, 8)], dtype='i4,f4,i2,c8') + def _bad_call(self): return self.ary['f0', 'f1'] + def test_no_tuple(self): self.assertRaises(IndexError, self._bad_call) + def test_return(self): res = self.ary[['f0', 'f2']].tolist() assert_(res == [(1, 3), (5, 7)]) diff --git a/numpy/core/tests/test_print.py b/numpy/core/tests/test_print.py index 487b5de7d..f595cbe44 100644 --- a/numpy/core/tests/test_print.py +++ b/numpy/core/tests/test_print.py @@ -1,11 +1,14 @@ from __future__ import division, absolute_import, print_function -import numpy as np -from numpy.testing import * +import sys +import locale import nose -import locale -import sys +import numpy as np +from numpy.testing import ( + run_module_suite, assert_, assert_equal +) + if sys.version_info[0] >= 3: from io import StringIO @@ -16,7 +19,7 @@ _REF = {np.inf: 'inf', -np.inf: '-inf', np.nan: 'nan'} def check_float_type(tp): - for x in [0, 1, -1, 1e20] : + for x in [0, 1, -1, 1e20]: assert_equal(str(tp(x)), str(float(x)), err_msg='Failed str formatting for type %s' % tp) @@ -36,7 +39,7 @@ def test_float_types(): python float precision. """ - for t in [np.float32, np.double, np.longdouble] : + for t in [np.float32, np.double, np.longdouble]: yield check_float_type, t def check_nan_inf_float(tp): @@ -52,11 +55,11 @@ def test_nan_inf_float(): python float precision. """ - for t in [np.float32, np.double, np.longdouble] : + for t in [np.float32, np.double, np.longdouble]: yield check_nan_inf_float, t def check_complex_type(tp): - for x in [0, 1, -1, 1e20] : + for x in [0, 1, -1, 1e20]: assert_equal(str(tp(x)), str(complex(x)), err_msg='Failed str formatting for type %s' % tp) assert_equal(str(tp(x*1j)), str(complex(x*1j)), @@ -80,7 +83,7 @@ def test_complex_types(): python float precision. """ - for t in [np.complex64, np.cdouble, np.clongdouble] : + for t in [np.complex64, np.cdouble, np.clongdouble]: yield check_complex_type, t def test_complex_inf_nan(): @@ -160,12 +163,12 @@ def check_complex_type_print(tp): def test_float_type_print(): """Check formatting when using print """ - for t in [np.float32, np.double, np.longdouble] : + for t in [np.float32, np.double, np.longdouble]: yield check_float_type_print, t def test_complex_type_print(): """Check formatting when using print """ - for t in [np.complex64, np.cdouble, np.clongdouble] : + for t in [np.complex64, np.cdouble, np.clongdouble]: yield check_complex_type_print, t def test_scalar_format(): diff --git a/numpy/core/tests/test_records.py b/numpy/core/tests/test_records.py index a7895a30a..7a18f295b 100644 --- a/numpy/core/tests/test_records.py +++ b/numpy/core/tests/test_records.py @@ -1,14 +1,16 @@ from __future__ import division, absolute_import, print_function import sys -from os import path -import numpy as np -from numpy.testing import * -from numpy.compat import asbytes, asunicode - -import warnings import collections import pickle +from os import path + +import numpy as np +from numpy.compat import asbytes +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_array_equal, + assert_array_almost_equal, assert_raises + ) class TestFromrecords(TestCase): @@ -53,10 +55,11 @@ class TestFromrecords(TestCase): filename = path.join(data_dir, 'recarray_from_file.fits') fd = open(filename, 'rb') fd.seek(2880 * 2) - r = np.rec.fromfile(fd, formats='f8,i4,a5', shape=3, byteorder='big') + r1 = np.rec.fromfile(fd, formats='f8,i4,a5', shape=3, byteorder='big') fd.seek(2880 * 2) - r = np.rec.array(fd, formats='f8,i4,a5', shape=3, byteorder='big') + r2 = np.rec.array(fd, formats='f8,i4,a5', shape=3, byteorder='big') fd.close() + assert_equal(r1, r2) def test_recarray_from_obj(self): count = 10 @@ -88,13 +91,50 @@ class TestFromrecords(TestCase): assert_equal(recordarr, recordarr_r) assert_equal(type(recarr_r), np.recarray) - assert_equal(recarr_r.dtype.type, np.void) + assert_equal(recarr_r.dtype.type, np.record) assert_equal(recarr, recarr_r) assert_equal(type(recordview_r), np.ndarray) assert_equal(recordview.dtype.type, np.record) assert_equal(recordview, recordview_r) + def test_recarray_views(self): + a = np.array([(1,'ABC'), (2, "DEF")], + dtype=[('foo', int), ('bar', 'S4')]) + b = np.array([1,2,3,4,5], dtype=np.int64) + + #check that np.rec.array gives right dtypes + assert_equal(np.rec.array(a).dtype.type, np.record) + assert_equal(type(np.rec.array(a)), np.recarray) + assert_equal(np.rec.array(b).dtype.type, np.int64) + assert_equal(type(np.rec.array(b)), np.recarray) + + #check that viewing as recarray does the same + assert_equal(a.view(np.recarray).dtype.type, np.record) + assert_equal(type(a.view(np.recarray)), np.recarray) + assert_equal(b.view(np.recarray).dtype.type, np.int64) + assert_equal(type(b.view(np.recarray)), np.recarray) + + #check that view to non-structured dtype preserves type=np.recarray + r = np.rec.array(np.ones(4, dtype="f4,i4")) + rv = r.view('f8').view('f4,i4') + assert_equal(type(rv), np.recarray) + assert_equal(rv.dtype.type, np.record) + + #check that we can undo the view + arrs = [np.ones(4, dtype='f4,i4'), np.ones(4, dtype='f8')] + for arr in arrs: + rec = np.rec.array(arr) + # recommended way to view as an ndarray: + arr2 = rec.view(rec.dtype.fields or rec.dtype, np.ndarray) + assert_equal(arr2.dtype.type, arr.dtype.type) + assert_equal(type(arr2), type(arr)) + + def test_recarray_repr(self): + # make sure non-structured dtypes also show up as rec.array + a = np.array(np.ones(4, dtype='f8')) + assert_(repr(np.rec.array(a)).startswith('rec.array')) + def test_recarray_from_names(self): ra = np.rec.array([ (1, 'abc', 3.7000002861022949, 0), @@ -149,19 +189,32 @@ class TestFromrecords(TestCase): assert_equal(a.foo[0] == a.foo[1], False) def test_recarray_returntypes(self): - a = np.rec.array([('abc ', (1,1), 1), ('abc', (2,3), 1)], + qux_fields = {'C': (np.dtype('S5'), 0), 'D': (np.dtype('S5'), 6)} + a = np.rec.array([('abc ', (1,1), 1, ('abcde', 'fgehi')), + ('abc', (2,3), 1, ('abcde', 'jklmn'))], dtype=[('foo', 'S4'), ('bar', [('A', int), ('B', int)]), - ('baz', int)]) + ('baz', int), ('qux', qux_fields)]) assert_equal(type(a.foo), np.ndarray) assert_equal(type(a['foo']), np.ndarray) assert_equal(type(a.bar), np.recarray) assert_equal(type(a['bar']), np.recarray) assert_equal(a.bar.dtype.type, np.record) + assert_equal(type(a['qux']), np.recarray) + assert_equal(a.qux.dtype.type, np.record) + assert_equal(dict(a.qux.dtype.fields), qux_fields) assert_equal(type(a.baz), np.ndarray) assert_equal(type(a['baz']), np.ndarray) assert_equal(type(a[0].bar), np.record) + assert_equal(type(a[0]['bar']), np.record) assert_equal(a[0].bar.A, 1) + assert_equal(a[0].bar['A'], 1) + assert_equal(a[0]['bar'].A, 1) + assert_equal(a[0]['bar']['A'], 1) + assert_equal(a[0].qux.D, asbytes('fgehi')) + assert_equal(a[0].qux['D'], asbytes('fgehi')) + assert_equal(a[0]['qux'].D, asbytes('fgehi')) + assert_equal(a[0]['qux']['D'], asbytes('fgehi')) class TestRecord(TestCase): @@ -185,8 +238,10 @@ class TestRecord(TestCase): def test_invalid_assignment(self): a = self.data + def assign_invalid_column(x): x[0].col5 = 1 + self.assertRaises(AttributeError, assign_invalid_column, a) def test_out_of_order_fields(self): @@ -206,6 +261,26 @@ class TestRecord(TestCase): assert_equal(a, pickle.loads(pickle.dumps(a))) assert_equal(a[0], pickle.loads(pickle.dumps(a[0]))) + def test_objview_record(self): + # https://github.com/numpy/numpy/issues/2599 + dt = np.dtype([('foo', 'i8'), ('bar', 'O')]) + r = np.zeros((1,3), dtype=dt).view(np.recarray) + r.foo = np.array([1, 2, 3]) # TypeError? + + # https://github.com/numpy/numpy/issues/3256 + ra = np.recarray((2,), dtype=[('x', object), ('y', float), ('z', int)]) + ra[['x','y']] # TypeError? + + def test_record_scalar_setitem(self): + # https://github.com/numpy/numpy/issues/3561 + rec = np.recarray(1, dtype=[('x', float, 5)]) + rec[0].x = 1 + assert_equal(rec[0].x, np.ones(5)) + + def test_missing_field(self): + # https://github.com/numpy/numpy/issues/4806 + arr = np.zeros((3,), dtype=[('x', int), ('y', int)]) + assert_raises(ValueError, lambda: arr[['nofield']]) def test_find_duplicate(): l1 = [1, 2, 3, 4, 5, 6] diff --git a/numpy/core/tests/test_regression.py b/numpy/core/tests/test_regression.py index fa2f52a23..3aba71463 100644 --- a/numpy/core/tests/test_regression.py +++ b/numpy/core/tests/test_regression.py @@ -5,7 +5,6 @@ import pickle import sys import platform import gc -import copy import warnings import tempfile from os import path @@ -25,16 +24,16 @@ rlevel = 1 class TestRegression(TestCase): def test_invalid_round(self,level=rlevel): - """Ticket #3""" + # Ticket #3 v = 4.7599999999999998 assert_array_equal(np.array([v]), np.array(v)) def test_mem_empty(self,level=rlevel): - """Ticket #7""" + # Ticket #7 np.empty((1,), dtype=[('x', np.int64)]) def test_pickle_transposed(self,level=rlevel): - """Ticket #16""" + # Ticket #16 a = np.transpose(np.array([[2, 9], [7, 0], [3, 8]])) f = BytesIO() pickle.dump(a, f) @@ -44,43 +43,44 @@ class TestRegression(TestCase): assert_array_equal(a, b) def test_typeNA(self,level=rlevel): - """Ticket #31""" + # Ticket #31 assert_equal(np.typeNA[np.int64], 'Int64') assert_equal(np.typeNA[np.uint64], 'UInt64') def test_dtype_names(self,level=rlevel): - """Ticket #35""" - dt = np.dtype([(('name', 'label'), np.int32, 3)]) + # Ticket #35 + # Should succeed + np.dtype([(('name', 'label'), np.int32, 3)]) def test_reduce(self,level=rlevel): - """Ticket #40""" + # Ticket #40 assert_almost_equal(np.add.reduce([1., .5], dtype=None), 1.5) def test_zeros_order(self,level=rlevel): - """Ticket #43""" + # Ticket #43 np.zeros([3], int, 'C') np.zeros([3], order='C') np.zeros([3], int, order='C') def test_asarray_with_order(self,level=rlevel): - """Check that nothing is done when order='F' and array C/F-contiguous""" + # Check that nothing is done when order='F' and array C/F-contiguous a = np.ones(2) assert_(a is np.asarray(a, order='F')) def test_ravel_with_order(self,level=rlevel): - """Check that ravel works when order='F' and array C/F-contiguous""" + # Check that ravel works when order='F' and array C/F-contiguous a = np.ones(2) assert_(not a.ravel('F').flags.owndata) def test_sort_bigendian(self,level=rlevel): - """Ticket #47""" + # Ticket #47 a = np.linspace(0, 10, 11) c = a.astype(np.dtype('<f8')) c.sort() assert_array_almost_equal(c, a) def test_negative_nd_indexing(self,level=rlevel): - """Ticket #49""" + # Ticket #49 c = np.arange(125).reshape((5, 5, 5)) origidx = np.array([-1, 0, 1]) idx = np.array(origidx) @@ -88,7 +88,7 @@ class TestRegression(TestCase): assert_array_equal(idx, origidx) def test_char_dump(self,level=rlevel): - """Ticket #50""" + # Ticket #50 f = BytesIO() ca = np.char.array(np.arange(1000, 1010), itemsize=4) ca.dump(f) @@ -97,60 +97,66 @@ class TestRegression(TestCase): f.close() def test_noncontiguous_fill(self,level=rlevel): - """Ticket #58.""" + # Ticket #58. a = np.zeros((5, 3)) b = a[:, :2,] + def rs(): b.shape = (10,) + self.assertRaises(AttributeError, rs) def test_bool(self,level=rlevel): - """Ticket #60""" - x = np.bool_(1) + # Ticket #60 + np.bool_(1) # Should succeed def test_indexing1(self,level=rlevel): - """Ticket #64""" + # Ticket #64 descr = [('x', [('y', [('z', 'c16', (2,)),]),]),] buffer = ((([6j, 4j],),),) h = np.array(buffer, dtype=descr) h['x']['y']['z'] def test_indexing2(self,level=rlevel): - """Ticket #65""" + # Ticket #65 descr = [('x', 'i4', (2,))] buffer = ([3, 2],) h = np.array(buffer, dtype=descr) h['x'] def test_round(self,level=rlevel): - """Ticket #67""" + # Ticket #67 x = np.array([1+2j]) assert_almost_equal(x**(-1), [1/(1+2j)]) def test_scalar_compare(self,level=rlevel): - """Ticket #72""" + # Trac Ticket #72 + # https://github.com/numpy/numpy/issues/565 a = np.array(['test', 'auto']) assert_array_equal(a == 'auto', np.array([False, True])) self.assertTrue(a[1] == 'auto') self.assertTrue(a[0] != 'auto') b = np.linspace(0, 10, 11) - self.assertTrue(b != 'auto') + # This should return true for now, but will eventually raise an error: + with warnings.catch_warnings(): + warnings.filterwarnings("ignore", category=DeprecationWarning) + self.assertTrue(b != 'auto') self.assertTrue(b[0] != 'auto') def test_unicode_swapping(self,level=rlevel): - """Ticket #79""" + # Ticket #79 ulen = 1 ucs_value = sixu('\U0010FFFF') ua = np.array([[[ucs_value*ulen]*2]*3]*4, dtype='U%s' % ulen) - ua2 = ua.newbyteorder() + ua.newbyteorder() # Should succeed. def test_object_array_fill(self,level=rlevel): - """Ticket #86""" + # Ticket #86 x = np.zeros(1, 'O') x.fill([]) def test_mem_dtype_align(self,level=rlevel): - """Ticket #93""" + # Ticket #93 self.assertRaises(TypeError, np.dtype, {'names':['a'],'formats':['foo']}, align=1) @@ -160,7 +166,7 @@ class TestRegression(TestCase): "numpy.intp('0xff', 16) not supported on Py3, " "as it does not inherit from Python int") def test_intp(self,level=rlevel): - """Ticket #99""" + # Ticket #99 i_width = np.int_(0).nbytes*2 - 1 np.intp('0x' + 'f'*i_width, 16) self.assertRaises(OverflowError, np.intp, '0x' + 'f'*(i_width+1), 16) @@ -169,20 +175,20 @@ class TestRegression(TestCase): assert_equal(1024, np.intp(1024)) def test_endian_bool_indexing(self,level=rlevel): - """Ticket #105""" + # Ticket #105 a = np.arange(10., dtype='>f8') b = np.arange(10., dtype='<f8') - xa = np.where((a>2) & (a<6)) - xb = np.where((b>2) & (b<6)) - ya = ((a>2) & (a<6)) - yb = ((b>2) & (b<6)) + xa = np.where((a > 2) & (a < 6)) + xb = np.where((b > 2) & (b < 6)) + ya = ((a > 2) & (a < 6)) + yb = ((b > 2) & (b < 6)) assert_array_almost_equal(xa, ya.nonzero()) assert_array_almost_equal(xb, yb.nonzero()) assert_(np.all(a[ya] > 0.5)) assert_(np.all(b[yb] > 0.5)) def test_endian_where(self,level=rlevel): - """GitHub issue #369""" + # GitHub issue #369 net = np.zeros(3, dtype='>f4') net[1] = 0.00458849 net[2] = 0.605202 @@ -192,7 +198,7 @@ class TestRegression(TestCase): assert_array_almost_equal(test, correct) def test_endian_recarray(self,level=rlevel): - """Ticket #2185""" + # Ticket #2185 dt = np.dtype([ ('head', '>u4'), ('data', '>u4', 2), @@ -208,7 +214,7 @@ class TestRegression(TestCase): assert_(buf[0]['head'] == 1) def test_mem_dot(self,level=rlevel): - """Ticket #106""" + # Ticket #106 x = np.random.randn(0, 1) y = np.random.randn(10, 1) # Dummy array to detect bad memory access: @@ -222,48 +228,39 @@ class TestRegression(TestCase): assert_equal(_z, np.ones(10)) def test_arange_endian(self,level=rlevel): - """Ticket #111""" + # Ticket #111 ref = np.arange(10) x = np.arange(10, dtype='<f8') assert_array_equal(ref, x) x = np.arange(10, dtype='>f8') assert_array_equal(ref, x) -# Longfloat support is not consistent enough across -# platforms for this test to be meaningful. -# def test_longfloat_repr(self,level=rlevel): -# """Ticket #112""" -# if np.longfloat(0).itemsize > 8: -# a = np.exp(np.array([1000],dtype=np.longfloat)) -# assert_(str(a)[1:9] == str(a[0])[:8]) - def test_argmax(self,level=rlevel): - """Ticket #119""" + # Ticket #119 a = np.random.normal(0, 1, (4, 5, 6, 7, 8)) for i in range(a.ndim): - aargmax = a.argmax(i) + a.argmax(i) # Should succeed def test_mem_divmod(self,level=rlevel): - """Ticket #126""" + # Ticket #126 for i in range(10): divmod(np.array([i])[0], 10) - def test_hstack_invalid_dims(self,level=rlevel): - """Ticket #128""" + # Ticket #128 x = np.arange(9).reshape((3, 3)) y = np.array([0, 0, 0]) self.assertRaises(ValueError, np.hstack, (x, y)) def test_squeeze_type(self,level=rlevel): - """Ticket #133""" + # Ticket #133 a = np.array([3]) b = np.array(3) assert_(type(a.squeeze()) is np.ndarray) assert_(type(b.squeeze()) is np.ndarray) def test_add_identity(self,level=rlevel): - """Ticket #143""" + # Ticket #143 assert_equal(0, np.add.identity) def test_numpy_float_python_long_addition(self): @@ -272,11 +269,11 @@ class TestRegression(TestCase): assert_equal(a, 23. + 2**135) def test_binary_repr_0(self,level=rlevel): - """Ticket #151""" + # Ticket #151 assert_equal('0', np.binary_repr(0)) def test_rec_iterate(self,level=rlevel): - """Ticket #160""" + # Ticket #160 descr = np.dtype([('i', int), ('f', float), ('s', '|S3')]) x = np.rec.array([(1, 1.1, '1.0'), (2, 2.2, '2.0')], dtype=descr) @@ -284,19 +281,19 @@ class TestRegression(TestCase): [i for i in x[0]] def test_unicode_string_comparison(self,level=rlevel): - """Ticket #190""" + # Ticket #190 a = np.array('hello', np.unicode_) b = np.array('world') a == b def test_tobytes_FORTRANORDER_discontiguous(self,level=rlevel): - """Fix in r2836""" + # Fix in r2836 # Create non-contiguous Fortran ordered array x = np.array(np.random.rand(3, 3), order='F')[:, :2] assert_array_almost_equal(x.ravel(), np.fromstring(x.tobytes())) def test_flat_assignment(self,level=rlevel): - """Correct behaviour of ticket #194""" + # Correct behaviour of ticket #194 x = np.empty((3, 1)) x.flat = np.arange(3) assert_array_almost_equal(x, [[0], [1], [2]]) @@ -304,10 +301,15 @@ class TestRegression(TestCase): assert_array_almost_equal(x, [[0], [1], [2]]) def test_broadcast_flat_assignment(self,level=rlevel): - """Ticket #194""" + # Ticket #194 x = np.empty((3, 1)) - def bfa(): x[:] = np.arange(3) - def bfb(): x[:] = np.arange(3, dtype=float) + + def bfa(): + x[:] = np.arange(3) + + def bfb(): + x[:] = np.arange(3, dtype=float) + self.assertRaises(ValueError, bfa) self.assertRaises(ValueError, bfb) @@ -317,15 +319,17 @@ class TestRegression(TestCase): a = np.arange(10) b = np.ones(10, dtype=bool) r = np.arange(10) + def assign(a, b, c): a[b] = c + assert_raises(ValueError, assign, a, b, np.nan) - a[b] = np.array(np.nan) # but not this. + a[b] = np.array(np.nan) # but not this. assert_raises(ValueError, assign, a, r, np.nan) a[r] = np.array(np.nan) def test_unpickle_dtype_with_object(self,level=rlevel): - """Implemented in r2840""" + # Implemented in r2840 dt = np.dtype([('x', int), ('y', np.object_), ('z', 'O')]) f = BytesIO() pickle.dump(dt, f) @@ -335,7 +339,7 @@ class TestRegression(TestCase): assert_equal(dt, dt_) def test_mem_array_creation_invalid_specification(self,level=rlevel): - """Ticket #196""" + # Ticket #196 dt = np.dtype([('x', int), ('y', np.object_)]) # Wrong way self.assertRaises(ValueError, np.array, [1, 'object'], dt) @@ -343,7 +347,7 @@ class TestRegression(TestCase): np.array([(1, 'object')], dt) def test_recarray_single_element(self,level=rlevel): - """Ticket #202""" + # Ticket #202 a = np.array([1, 2, 3], dtype=np.int32) b = a.copy() r = np.rec.array(a, shape=1, formats=['3i4'], names=['d']) @@ -351,20 +355,23 @@ class TestRegression(TestCase): assert_equal(a, r[0][0]) def test_zero_sized_array_indexing(self,level=rlevel): - """Ticket #205""" + # Ticket #205 tmp = np.array([]) - def index_tmp(): tmp[np.array(10)] + + def index_tmp(): + tmp[np.array(10)] + self.assertRaises(IndexError, index_tmp) def test_chararray_rstrip(self,level=rlevel): - """Ticket #222""" + # Ticket #222 x = np.chararray((1,), 5) x[0] = asbytes('a ') x = x.rstrip() assert_equal(x[0], asbytes('a')) def test_object_array_shape(self,level=rlevel): - """Ticket #239""" + # Ticket #239 assert_equal(np.array([[1, 2], 3, 4], dtype=object).shape, (3,)) assert_equal(np.array([[1, 2], [3, 4]], dtype=object).shape, (2, 2)) assert_equal(np.array([(1, 2), (3, 4)], dtype=object).shape, (2, 2)) @@ -373,19 +380,20 @@ class TestRegression(TestCase): assert_equal(np.array([[3, 4], [5, 6], None], dtype=object).shape, (3,)) def test_mem_around(self,level=rlevel): - """Ticket #243""" + # Ticket #243 x = np.zeros((1,)) y = [0] decimal = 6 np.around(abs(x-y), decimal) <= 10.0**(-decimal) def test_character_array_strip(self,level=rlevel): - """Ticket #246""" + # Ticket #246 x = np.char.array(("x", "x ", "x ")) - for c in x: assert_equal(c, "x") + for c in x: + assert_equal(c, "x") def test_lexsort(self,level=rlevel): - """Lexsort memory error""" + # Lexsort memory error v = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) assert_equal(np.lexsort(v), 0) @@ -394,6 +402,7 @@ class TestRegression(TestCase): class BuggySequence(object): def __len__(self): return 4 + def __getitem__(self, key): raise KeyError @@ -436,22 +445,22 @@ class TestRegression(TestCase): assert_(isinstance(name, str)) def test_pickle_dtype(self,level=rlevel): - """Ticket #251""" + # Ticket #251 pickle.dumps(np.float) def test_swap_real(self, level=rlevel): - """Ticket #265""" + # Ticket #265 assert_equal(np.arange(4, dtype='>c8').imag.max(), 0.0) assert_equal(np.arange(4, dtype='<c8').imag.max(), 0.0) assert_equal(np.arange(4, dtype='>c8').real.max(), 3.0) assert_equal(np.arange(4, dtype='<c8').real.max(), 3.0) def test_object_array_from_list(self, level=rlevel): - """Ticket #270""" - a = np.array([1, 'A', None]) + # Ticket #270 + np.array([1, 'A', None]) # Should succeed def test_multiple_assign(self, level=rlevel): - """Ticket #273""" + # Ticket #273 a = np.zeros((3, 1), int) a[[1, 2]] = 1 @@ -467,7 +476,7 @@ class TestRegression(TestCase): def test_method_args(self, level=rlevel): # Make sure methods and functions have same default axis # keyword and arguments - funcs1= ['argmax', 'argmin', 'sum', ('product', 'prod'), + funcs1 = ['argmax', 'argmin', 'sum', ('product', 'prod'), ('sometrue', 'any'), ('alltrue', 'all'), 'cumsum', ('cumproduct', 'cumprod'), 'ptp', 'cumprod', 'prod', 'std', 'var', 'mean', @@ -507,17 +516,17 @@ class TestRegression(TestCase): assert_(abs(res1-res2).max() < 1e-8, func) def test_mem_lexsort_strings(self, level=rlevel): - """Ticket #298""" + # Ticket #298 lst = ['abc', 'cde', 'fgh'] np.lexsort((lst,)) def test_fancy_index(self, level=rlevel): - """Ticket #302""" + # Ticket #302 x = np.array([1, 2])[np.array([0])] assert_equal(x.shape, (1,)) def test_recarray_copy(self, level=rlevel): - """Ticket #312""" + # Ticket #312 dt = [('x', np.int16), ('y', np.float64)] ra = np.array([(1, 2.3)], dtype=dt) rb = np.rec.array(ra, dtype=dt) @@ -525,7 +534,7 @@ class TestRegression(TestCase): assert_(ra['x'] != rb['x']) def test_rec_fromarray(self, level=rlevel): - """Ticket #322""" + # Ticket #322 x1 = np.array([[1, 2], [3, 4], [5, 6]]) x2 = np.array(['a', 'dd', 'xyz']) x3 = np.array([1.1, 2, 3]) @@ -537,52 +546,52 @@ class TestRegression(TestCase): assert_equal(x.flat[2], (1, 2, 3)) def test_ndmin_float64(self, level=rlevel): - """Ticket #324""" + # Ticket #324 x = np.array([1, 2, 3], dtype=np.float64) assert_equal(np.array(x, dtype=np.float32, ndmin=2).ndim, 2) assert_equal(np.array(x, dtype=np.float64, ndmin=2).ndim, 2) def test_ndmin_order(self, level=rlevel): - """Issue #465 and related checks""" + # Issue #465 and related checks assert_(np.array([1, 2], order='C', ndmin=3).flags.c_contiguous) assert_(np.array([1, 2], order='F', ndmin=3).flags.f_contiguous) assert_(np.array(np.ones((2, 2), order='F'), ndmin=3).flags.f_contiguous) assert_(np.array(np.ones((2, 2), order='C'), ndmin=3).flags.c_contiguous) def test_mem_axis_minimization(self, level=rlevel): - """Ticket #327""" + # Ticket #327 data = np.arange(5) data = np.add.outer(data, data) def test_mem_float_imag(self, level=rlevel): - """Ticket #330""" + # Ticket #330 np.float64(1.0).imag def test_dtype_tuple(self, level=rlevel): - """Ticket #334""" + # Ticket #334 assert_(np.dtype('i4') == np.dtype(('i4', ()))) def test_dtype_posttuple(self, level=rlevel): - """Ticket #335""" + # Ticket #335 np.dtype([('col1', '()i4')]) def test_numeric_carray_compare(self, level=rlevel): - """Ticket #341""" + # Ticket #341 assert_equal(np.array(['X'], 'c'), asbytes('X')) def test_string_array_size(self, level=rlevel): - """Ticket #342""" + # Ticket #342 self.assertRaises(ValueError, np.array, [['X'], ['X', 'X', 'X']], '|S1') def test_dtype_repr(self, level=rlevel): - """Ticket #344""" - dt1=np.dtype(('uint32', 2)) - dt2=np.dtype(('uint32', (2,))) + # Ticket #344 + dt1 = np.dtype(('uint32', 2)) + dt2 = np.dtype(('uint32', (2,))) assert_equal(dt1.__repr__(), dt2.__repr__()) def test_reshape_order(self, level=rlevel): - """Make sure reshape order works.""" + # Make sure reshape order works. a = np.arange(6).reshape(2, 3, order='F') assert_equal(a, [[0, 2, 4], [1, 3, 5]]) a = np.array([[1, 2], [3, 4], [5, 6], [7, 8]]) @@ -590,13 +599,13 @@ class TestRegression(TestCase): assert_equal(b.reshape(2, 2, order='F'), [[2, 6], [4, 8]]) def test_reshape_zero_strides(self, level=rlevel): - """Issue #380, test reshaping of zero strided arrays""" + # Issue #380, test reshaping of zero strided arrays a = np.ones(1) a = np.lib.stride_tricks.as_strided(a, shape=(5,), strides=(0,)) assert_(a.reshape(5, 1).strides[0] == 0) def test_reshape_zero_size(self, level=rlevel): - """GitHub Issue #2700, setting shape failed for 0-sized arrays""" + # GitHub Issue #2700, setting shape failed for 0-sized arrays a = np.ones((0, 2)) a.shape = (-1, 2) @@ -605,7 +614,7 @@ class TestRegression(TestCase): @dec.skipif(np.ones(1).strides[0] == np.iinfo(np.intp).max) def test_reshape_trailing_ones_strides(self): # GitHub issue gh-2949, bad strides for trailing ones of new shape - a = np.zeros(12, dtype=np.int32)[::2] # not contiguous + a = np.zeros(12, dtype=np.int32)[::2] # not contiguous strides_c = (16, 8, 8, 8) strides_f = (8, 24, 48, 48) assert_equal(a.reshape(3, 2, 1, 1).strides, strides_c) @@ -613,22 +622,22 @@ class TestRegression(TestCase): assert_equal(np.array(0, dtype=np.int32).reshape(1, 1).strides, (4, 4)) def test_repeat_discont(self, level=rlevel): - """Ticket #352""" + # Ticket #352 a = np.arange(12).reshape(4, 3)[:, 2] assert_equal(a.repeat(3), [2, 2, 2, 5, 5, 5, 8, 8, 8, 11, 11, 11]) def test_array_index(self, level=rlevel): - """Make sure optimization is not called in this case.""" + # Make sure optimization is not called in this case. a = np.array([1, 2, 3]) a2 = np.array([[1, 2, 3]]) - assert_equal(a[np.where(a==3)], a2[np.where(a2==3)]) + assert_equal(a[np.where(a == 3)], a2[np.where(a2 == 3)]) def test_object_argmax(self, level=rlevel): a = np.array([1, 2, 3], dtype=object) assert_(a.argmax() == 2) def test_recarray_fields(self, level=rlevel): - """Ticket #372""" + # Ticket #372 dt0 = np.dtype([('f0', 'i4'), ('f1', 'i4')]) dt1 = np.dtype([('f0', 'i8'), ('f1', 'i8')]) for a in [np.array([(1, 2), (3, 4)], "i4,i4"), @@ -639,14 +648,14 @@ class TestRegression(TestCase): assert_(a.dtype in [dt0, dt1]) def test_random_shuffle(self, level=rlevel): - """Ticket #374""" + # Ticket #374 a = np.arange(5).reshape((5, 1)) b = a.copy() np.random.shuffle(b) assert_equal(np.sort(b, axis=0), a) def test_refcount_vdot(self, level=rlevel): - """Changeset #3443""" + # Changeset #3443 _assert_valid_refcount(np.vdot) def test_startswith(self, level=rlevel): @@ -654,7 +663,7 @@ class TestRegression(TestCase): assert_equal(ca.startswith('H'), [True, False]) def test_noncommutative_reduce_accumulate(self, level=rlevel): - """Ticket #413""" + # Ticket #413 tosubtract = np.arange(5) todivide = np.array([2.0, 0.5, 0.25]) assert_equal(np.subtract.reduce(tosubtract), -10) @@ -665,28 +674,28 @@ class TestRegression(TestCase): np.array([2., 4., 16.])) def test_convolve_empty(self, level=rlevel): - """Convolve should raise an error for empty input array.""" + # Convolve should raise an error for empty input array. self.assertRaises(ValueError, np.convolve, [], [1]) self.assertRaises(ValueError, np.convolve, [1], []) def test_multidim_byteswap(self, level=rlevel): - """Ticket #449""" - r=np.array([(1, (0, 1, 2))], dtype="i2,3i2") + # Ticket #449 + r = np.array([(1, (0, 1, 2))], dtype="i2,3i2") assert_array_equal(r.byteswap(), np.array([(256, (0, 256, 512))], r.dtype)) def test_string_NULL(self, level=rlevel): - """Changeset 3557""" + # Changeset 3557 assert_equal(np.array("a\x00\x0b\x0c\x00").item(), 'a\x00\x0b\x0c') def test_junk_in_string_fields_of_recarray(self, level=rlevel): - """Ticket #483""" + # Ticket #483 r = np.array([[asbytes('abc')]], dtype=[('var1', '|S20')]) assert_(asbytes(r['var1'][0][0]) == asbytes('abc')) def test_take_output(self, level=rlevel): - """Ensure that 'take' honours output parameter.""" + # Ensure that 'take' honours output parameter. x = np.arange(12).reshape((3, 4)) a = np.take(x, [0, 2], axis=1) b = np.zeros_like(a) @@ -705,13 +714,13 @@ class TestRegression(TestCase): assert_(ref_d == sys.getrefcount(d)) def test_array_str_64bit(self, level=rlevel): - """Ticket #501""" + # Ticket #501 s = np.array([1, np.nan], dtype=np.float64) with np.errstate(all='raise'): - sstr = np.array_str(s) + np.array_str(s) # Should succeed def test_frompyfunc_endian(self, level=rlevel): - """Ticket #503""" + # Ticket #503 from math import radians uradians = np.frompyfunc(radians, 1, 1) big_endian = np.array([83.4, 83.5], dtype='>f8') @@ -720,33 +729,33 @@ class TestRegression(TestCase): uradians(little_endian).astype(float)) def test_mem_string_arr(self, level=rlevel): - """Ticket #514""" + # Ticket #514 s = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" t = [] - np.hstack((t, s )) + np.hstack((t, s)) def test_arr_transpose(self, level=rlevel): - """Ticket #516""" + # Ticket #516 x = np.random.rand(*(2,)*16) - y = x.transpose(list(range(16))) + x.transpose(list(range(16))) # Should succeed def test_string_mergesort(self, level=rlevel): - """Ticket #540""" + # Ticket #540 x = np.array(['a']*32) assert_array_equal(x.argsort(kind='m'), np.arange(32)) def test_argmax_byteorder(self, level=rlevel): - """Ticket #546""" + # Ticket #546 a = np.arange(3, dtype='>f') assert_(a[a.argmax()] == a.max()) def test_rand_seed(self, level=rlevel): - """Ticket #555""" + # Ticket #555 for l in np.arange(4): np.random.seed(l) def test_mem_deallocation_leak(self, level=rlevel): - """Ticket #562""" + # Ticket #562 a = np.zeros(5, dtype=float) b = np.array(a, dtype=float) del a, b @@ -756,7 +765,7 @@ class TestRegression(TestCase): self.assertRaises(ValueError, np.fromiter, [['12', ''], ['13', '']], str) def test_dot_negative_stride(self, level=rlevel): - """Ticket #588""" + # Ticket #588 x = np.array([[1, 5, 25, 125., 625]]) y = np.array([[20.], [160.], [640.], [1280.], [1024.]]) z = y[::-1].copy() @@ -771,38 +780,46 @@ class TestRegression(TestCase): x = np.ones([484, 286]) y = np.zeros([484, 286]) x |= y + self.assertRaises(TypeError, rs) def test_unicode_scalar(self, level=rlevel): - """Ticket #600""" + # Ticket #600 x = np.array(["DROND", "DROND1"], dtype="U6") el = x[1] new = pickle.loads(pickle.dumps(el)) assert_equal(new, el) def test_arange_non_native_dtype(self, level=rlevel): - """Ticket #616""" + # Ticket #616 for T in ('>f4', '<f4'): dt = np.dtype(T) assert_equal(np.arange(0, dtype=dt).dtype, dt) assert_equal(np.arange(0.5, dtype=dt).dtype, dt) assert_equal(np.arange(5, dtype=dt).dtype, dt) - def test_bool_indexing_invalid_nr_elements(self, level=rlevel): + def test_bool_flat_indexing_invalid_nr_elements(self, level=rlevel): s = np.ones(10, dtype=float) x = np.array((15,), dtype=float) - def ia(x, s, v): x[(s>0)]=v + + def ia(x, s, v): + x[(s > 0)] = v + # After removing deprecation, the following are ValueErrors. # This might seem odd as compared to the value error below. This # is due to the fact that the new code always uses "nonzero" logic # and the boolean special case is not taken. - self.assertRaises(IndexError, ia, x, s, np.zeros(9, dtype=float)) - self.assertRaises(IndexError, ia, x, s, np.zeros(11, dtype=float)) + with warnings.catch_warnings(): + warnings.simplefilter('ignore', DeprecationWarning) + warnings.simplefilter('ignore', np.VisibleDeprecationWarning) + self.assertRaises(IndexError, ia, x, s, np.zeros(9, dtype=float)) + self.assertRaises(IndexError, ia, x, s, np.zeros(11, dtype=float)) # Old special case (different code path): self.assertRaises(ValueError, ia, x.flat, s, np.zeros(9, dtype=float)) + self.assertRaises(ValueError, ia, x.flat, s, np.zeros(11, dtype=float)) def test_mem_scalar_indexing(self, level=rlevel): - """Ticket #603""" + # Ticket #603 x = np.array([0], dtype=float) index = np.array(0, dtype=np.int32) x[index] @@ -820,28 +837,28 @@ class TestRegression(TestCase): assert_equal(x.searchsorted(y), [3, 3]) def test_string_argsort_with_zeros(self, level=rlevel): - """Check argsort for strings containing zeros.""" + # Check argsort for strings containing zeros. x = np.fromstring("\x00\x02\x00\x01", dtype="|S2") assert_array_equal(x.argsort(kind='m'), np.array([1, 0])) assert_array_equal(x.argsort(kind='q'), np.array([1, 0])) def test_string_sort_with_zeros(self, level=rlevel): - """Check sort for strings containing zeros.""" + # Check sort for strings containing zeros. x = np.fromstring("\x00\x02\x00\x01", dtype="|S2") y = np.fromstring("\x00\x01\x00\x02", dtype="|S2") assert_array_equal(np.sort(x, kind="q"), y) def test_copy_detection_zero_dim(self, level=rlevel): - """Ticket #658""" + # Ticket #658 np.indices((0, 3, 4)).T.reshape(-1, 3) def test_flat_byteorder(self, level=rlevel): - """Ticket #657""" + # Ticket #657 x = np.arange(10) assert_array_equal(x.astype('>i4'), x.astype('<i4').flat[:]) assert_array_equal(x.astype('>i4').flat[:], x.astype('<i4')) - def test_uint64_from_negative(self, level=rlevel) : + def test_uint64_from_negative(self, level=rlevel): assert_equal(np.uint64(-2), np.uint64(18446744073709551614)) def test_sign_bit(self, level=rlevel): @@ -854,7 +871,7 @@ class TestRegression(TestCase): assert_equal(x.flat[0].dtype, x[0].dtype) def test_copy_detection_corner_case(self, level=rlevel): - """Ticket #658""" + # Ticket #658 np.indices((0, 3, 4)).T.reshape(-1, 3) # Cannot test if NPY_RELAXED_STRIDES_CHECKING changes the strides. @@ -862,13 +879,13 @@ class TestRegression(TestCase): # 0-sized reshape itself is tested elsewhere. @dec.skipif(np.ones(1).strides[0] == np.iinfo(np.intp).max) def test_copy_detection_corner_case2(self, level=rlevel): - """Ticket #771: strides are not set correctly when reshaping 0-sized - arrays""" + # Ticket #771: strides are not set correctly when reshaping 0-sized + # arrays b = np.indices((0, 3, 4)).T.reshape(-1, 3) assert_equal(b.strides, (3 * b.itemsize, b.itemsize)) def test_object_array_refcounting(self, level=rlevel): - """Ticket #633""" + # Ticket #633 if not hasattr(sys, 'getrefcount'): return @@ -903,7 +920,7 @@ class TestRegression(TestCase): # -- 1-d -> 2-d broadcast slice assignment - arr = np.zeros((5, 2), dtype=np.object_) + arr = np.zeros((5, 2), dtype=np.object_) arr0 = np.zeros(2, dtype=np.object_) arr0[0] = a @@ -922,7 +939,7 @@ class TestRegression(TestCase): # -- 2-d copying + flattening - arr = np.zeros((5, 2), dtype=np.object_) + arr = np.zeros((5, 2), dtype=np.object_) arr[:, 0] = a arr[:, 1] = b @@ -953,43 +970,47 @@ class TestRegression(TestCase): assert_(cnt(a) == cnt0_a + 5) assert_(cnt(b) == cnt0_b + 5) - arr3 = np.concatenate((arr1, arr2)) + tmp = np.concatenate((arr1, arr2)) assert_(cnt(a) == cnt0_a + 5 + 5) assert_(cnt(b) == cnt0_b + 5 + 5) - arr3 = arr1.repeat(3, axis=0) + tmp = arr1.repeat(3, axis=0) assert_(cnt(a) == cnt0_a + 5 + 3*5) - arr3 = arr1.take([1, 2, 3], axis=0) + tmp = arr1.take([1, 2, 3], axis=0) assert_(cnt(a) == cnt0_a + 5 + 3) x = np.array([[0], [1], [0], [1], [1]], int) - arr3 = x.choose(arr1, arr2) + tmp = x.choose(arr1, arr2) assert_(cnt(a) == cnt0_a + 5 + 2) assert_(cnt(b) == cnt0_b + 5 + 3) + del tmp # Avoid pyflakes unused variable warning + def test_mem_custom_float_to_array(self, level=rlevel): - """Ticket 702""" + # Ticket 702 class MyFloat(object): def __float__(self): return 1.0 tmp = np.atleast_1d([MyFloat()]) - tmp2 = tmp.astype(float) + tmp.astype(float) # Should succeed def test_object_array_refcount_self_assign(self, level=rlevel): - """Ticket #711""" + # Ticket #711 class VictimObject(object): deleted = False + def __del__(self): self.deleted = True + d = VictimObject() arr = np.zeros(5, dtype=np.object_) arr[:] = d del d - arr[:] = arr # refcount of 'd' might hit zero here + arr[:] = arr # refcount of 'd' might hit zero here assert_(not arr[0].deleted) - arr[:] = arr # trying to induce a segfault by doing it again... + arr[:] = arr # trying to induce a segfault by doing it again... assert_(not arr[0].deleted) def test_mem_fromiter_invalid_dtype_string(self, level=rlevel): @@ -998,18 +1019,18 @@ class TestRegression(TestCase): np.fromiter, [xi for xi in x], dtype='S') def test_reduce_big_object_array(self, level=rlevel): - """Ticket #713""" + # Ticket #713 oldsize = np.setbufsize(10*16) a = np.array([None]*161, object) assert_(not np.any(a)) np.setbufsize(oldsize) def test_mem_0d_array_index(self, level=rlevel): - """Ticket #714""" + # Ticket #714 np.zeros(10)[np.array(0)] def test_floats_from_string(self, level=rlevel): - """Ticket #640, floats from string""" + # Ticket #640, floats from string fsingle = np.single('1.234') fdouble = np.double('1.234') flongdouble = np.longdouble('1.234') @@ -1018,9 +1039,8 @@ class TestRegression(TestCase): assert_almost_equal(flongdouble, 1.234) def test_nonnative_endian_fill(self, level=rlevel): - """ Non-native endian arrays were incorrectly filled with scalars before - r5034. - """ + # Non-native endian arrays were incorrectly filled with scalars + # before r5034. if sys.byteorder == 'little': dtype = np.dtype('>i4') else: @@ -1030,7 +1050,7 @@ class TestRegression(TestCase): assert_equal(x, np.array([1], dtype=dtype)) def test_dot_alignment_sse2(self, level=rlevel): - """Test for ticket #551, changeset r5140""" + # Test for ticket #551, changeset r5140 x = np.zeros((30, 40)) y = pickle.loads(pickle.dumps(x)) # y is now typically not aligned on a 8-byte boundary @@ -1039,7 +1059,7 @@ class TestRegression(TestCase): np.dot(z, y) def test_astype_copy(self, level=rlevel): - """Ticket #788, changeset r5155""" + # Ticket #788, changeset r5155 # The test data file was generated by scipy.io.savemat. # The dtype is float64, but the isbuiltin attribute is 0. data_dir = path.join(path.dirname(__file__), 'data') @@ -1057,14 +1077,13 @@ class TestRegression(TestCase): xpd.__array_interface__['data'][0])) def test_compress_small_type(self, level=rlevel): - """Ticket #789, changeset 5217. - """ + # Ticket #789, changeset 5217. # compress with out argument segfaulted if cannot cast safely import numpy as np a = np.array([[1, 2], [3, 4]]) - b = np.zeros((2, 1), dtype = np.single) + b = np.zeros((2, 1), dtype=np.single) try: - a.compress([True, False], axis = 1, out = b) + a.compress([True, False], axis=1, out=b) raise AssertionError("compress with an out which cannot be " "safely casted should not return " "successfully") @@ -1072,16 +1091,17 @@ class TestRegression(TestCase): pass def test_attributes(self, level=rlevel): - """Ticket #791 - """ + # Ticket #791 class TestArray(np.ndarray): def __new__(cls, data, info): result = np.array(data) result = result.view(cls) result.info = info return result + def __array_finalize__(self, obj): self.info = getattr(obj, 'info', '') + dat = TestArray([[1, 2, 3, 4], [5, 6, 7, 8]], 'jubba') assert_(dat.info == 'jubba') dat.resize((4, 2)) @@ -1122,8 +1142,6 @@ class TestRegression(TestCase): assert_(dat.mean(1).info == 'jubba') assert_(dat.min(1).info == 'jubba') assert_(dat.newbyteorder().info == 'jubba') - assert_(dat.nonzero()[0].info == 'jubba') - assert_(dat.nonzero()[1].info == 'jubba') assert_(dat.prod(1).info == 'jubba') assert_(dat.ptp(1).info == 'jubba') assert_(dat.ravel().info == 'jubba') @@ -1140,10 +1158,12 @@ class TestRegression(TestCase): assert_(dat.T.info == 'jubba') assert_(dat.var(1).info == 'jubba') assert_(dat.view(TestArray).info == 'jubba') + # These methods do not preserve subclasses + assert_(type(dat.nonzero()[0]) is np.ndarray) + assert_(type(dat.nonzero()[1]) is np.ndarray) def test_recarray_tolist(self, level=rlevel): - """Ticket #793, changeset r5215 - """ + # Ticket #793, changeset r5215 # Comparisons fail for NaN, so we can't use random memory # for the test. buf = np.zeros(40, dtype=np.int8) @@ -1162,11 +1182,11 @@ class TestRegression(TestCase): b = np.array(asbytes_nested(['1', '2', '3'])) assert_equal(a, b) - def test_unaligned_unicode_access(self, level=rlevel) : - """Ticket #825""" - for i in range(1, 9) : - msg = 'unicode offset: %d chars'%i - t = np.dtype([('a', 'S%d'%i), ('b', 'U2')]) + def test_unaligned_unicode_access(self, level=rlevel): + # Ticket #825 + for i in range(1, 9): + msg = 'unicode offset: %d chars' % i + t = np.dtype([('a', 'S%d' % i), ('b', 'U2')]) x = np.array([(asbytes('a'), sixu('b'))], dtype=t) if sys.version_info[0] >= 3: assert_equal(str(x), "[(b'a', 'b')]", err_msg=msg) @@ -1174,7 +1194,7 @@ class TestRegression(TestCase): assert_equal(str(x), "[('a', u'b')]", err_msg=msg) def test_sign_for_complex_nan(self, level=rlevel): - """Ticket 794.""" + # Ticket 794. with np.errstate(invalid='ignore'): C = np.array([-np.inf, -2+1j, 0, 2-1j, np.inf, np.nan]) have = np.sign(C) @@ -1182,7 +1202,7 @@ class TestRegression(TestCase): assert_equal(have, want) def test_for_equal_names(self, level=rlevel): - """Ticket #674""" + # Ticket #674 dt = np.dtype([('foo', float), ('bar', float)]) a = np.zeros(10, dt) b = list(a.dtype.names) @@ -1192,7 +1212,7 @@ class TestRegression(TestCase): assert_(a.dtype.names[1] == "bar") def test_for_object_scalar_creation(self, level=rlevel): - """Ticket #816""" + # Ticket #816 a = np.object_() b = np.object_(3) b2 = np.object_(3.0) @@ -1206,7 +1226,7 @@ class TestRegression(TestCase): assert_(d.dtype == object) def test_array_resize_method_system_error(self): - """Ticket #840 - order should be an invalid keyword.""" + # Ticket #840 - order should be an invalid keyword. x = np.array([[0, 1], [2, 3]]) self.assertRaises(TypeError, x.resize, (2, 2), order='C') @@ -1220,7 +1240,7 @@ class TestRegression(TestCase): self.assertRaises(ValueError, lambda: np.array([1], ndmin=33)) def test_errobj_reference_leak(self, level=rlevel): - """Ticket #955""" + # Ticket #955 with np.errstate(all="ignore"): z = int(0) p = np.int32(-1) @@ -1233,7 +1253,7 @@ class TestRegression(TestCase): assert_(n_before >= n_after, (n_before, n_after)) def test_void_scalar_with_titles(self, level=rlevel): - """No ticket""" + # No ticket data = [('john', 4), ('mary', 5)] dtype1 = [(('source:yy', 'name'), 'O'), (('source:xx', 'id'), int)] arr = np.array(data, dtype=dtype1) @@ -1264,7 +1284,7 @@ class TestRegression(TestCase): assert_(pickle.loads(pickle.dumps(test_record)) == test_record) def test_blasdot_uninitialized_memory(self): - """Ticket #950""" + # Ticket #950 for m in [0, 1, 2]: for n in [0, 1, 2]: for k in range(3): @@ -1280,7 +1300,7 @@ class TestRegression(TestCase): assert_(z.shape == (m, n)) def test_zeros(self): - """Regression test for #1061.""" + # Regression test for #1061. # Set a size which cannot fit into a 64 bits signed integer sz = 2 ** 64 good = 'Maximum allowed dimension exceeded' @@ -1293,12 +1313,12 @@ class TestRegression(TestCase): self.fail("Got exception of type %s instead of ValueError" % type(e)) def test_huge_arange(self): - """Regression test for #1062.""" + # Regression test for #1062. # Set a size which cannot fit into a 64 bits signed integer sz = 2 ** 64 good = 'Maximum allowed size exceeded' try: - a = np.arange(sz) + np.arange(sz) self.assertTrue(np.size == sz) except ValueError as e: if not str(e) == good: @@ -1307,15 +1327,15 @@ class TestRegression(TestCase): self.fail("Got exception of type %s instead of ValueError" % type(e)) def test_fromiter_bytes(self): - """Ticket #1058""" + # Ticket #1058 a = np.fromiter(list(range(10)), dtype='b') b = np.fromiter(list(range(10)), dtype='B') assert_(np.alltrue(a == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))) assert_(np.alltrue(b == np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))) def test_array_from_sequence_scalar_array(self): - """Ticket #1078: segfaults when creating an array with a sequence of 0d - arrays.""" + # Ticket #1078: segfaults when creating an array with a sequence of + # 0d arrays. a = np.array((np.ones(2), np.array(2))) assert_equal(a.shape, (2,)) assert_equal(a.dtype, np.dtype(object)) @@ -1329,32 +1349,32 @@ class TestRegression(TestCase): assert_equal(a[1], np.array(1)) def test_array_from_sequence_scalar_array2(self): - """Ticket #1081: weird array with strange input...""" + # Ticket #1081: weird array with strange input... t = np.array([np.array([]), np.array(0, object)]) assert_equal(t.shape, (2,)) assert_equal(t.dtype, np.dtype(object)) def test_array_too_big(self): - """Ticket #1080.""" + # Ticket #1080. assert_raises(ValueError, np.zeros, [975]*7, np.int8) assert_raises(ValueError, np.zeros, [26244]*5, np.int8) def test_dtype_keyerrors_(self): - """Ticket #1106.""" + # Ticket #1106. dt = np.dtype([('f1', np.uint)]) assert_raises(KeyError, dt.__getitem__, "f2") assert_raises(IndexError, dt.__getitem__, 1) assert_raises(ValueError, dt.__getitem__, 0.0) def test_lexsort_buffer_length(self): - """Ticket #1217, don't segfault.""" + # Ticket #1217, don't segfault. a = np.ones(100, dtype=np.int8) b = np.ones(100, dtype=np.int32) i = np.lexsort((a[::-1], b)) assert_equal(i, np.arange(100, dtype=np.int)) def test_object_array_to_fixed_string(self): - """Ticket #1235.""" + # Ticket #1235. a = np.array(['abcdefgh', 'ijklmnop'], dtype=np.object_) b = np.array(a, dtype=(np.str_, 8)) assert_equal(a, b) @@ -1367,14 +1387,11 @@ class TestRegression(TestCase): assert_equal(a, e) def test_unicode_to_string_cast(self): - """Ticket #1240.""" - a = np.array( - [ [sixu('abc'), sixu('\u03a3')], - [sixu('asdf'), sixu('erw')] - ], dtype='U') - def fail(): - b = np.array(a, 'S4') - self.assertRaises(UnicodeEncodeError, fail) + # Ticket #1240. + a = np.array([[sixu('abc'), sixu('\u03a3')], + [sixu('asdf'), sixu('erw')]], + dtype='U') + self.assertRaises(UnicodeEncodeError, np.array, a, 'S4') def test_mixed_string_unicode_array_creation(self): a = np.array(['1234', sixu('123')]) @@ -1389,28 +1406,28 @@ class TestRegression(TestCase): assert_(a.itemsize == 16) def test_misaligned_objects_segfault(self): - """Ticket #1198 and #1267""" + # Ticket #1198 and #1267 a1 = np.zeros((10,), dtype='O,c') a2 = np.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'], 'S10') a1['f0'] = a2 - r = repr(a1) + repr(a1) np.argmax(a1['f0']) a1['f0'][1] = "FOO" a1['f0'] = "FOO" - a3 = np.array(a1['f0'], dtype='S') + np.array(a1['f0'], dtype='S') np.nonzero(a1['f0']) a1.sort() - a4 = copy.deepcopy(a1) + copy.deepcopy(a1) def test_misaligned_scalars_segfault(self): - """Ticket #1267""" + # Ticket #1267 s1 = np.array(('a', 'Foo'), dtype='c,O') s2 = np.array(('b', 'Bar'), dtype='c,O') s1['f1'] = s2['f1'] s1['f1'] = 'Baz' def test_misaligned_dot_product_objects(self): - """Ticket #1267""" + # Ticket #1267 # This didn't require a fix, but it's worth testing anyway, because # it may fail if .dot stops enforcing the arrays to be BEHAVED a = np.array([[(1, 'a'), (0, 'a')], [(0, 'a'), (1, 'a')]], dtype='O,c') @@ -1418,10 +1435,10 @@ class TestRegression(TestCase): np.dot(a['f0'], b['f0']) def test_byteswap_complex_scalar(self): - """Ticket #1259 and gh-441""" + # Ticket #1259 and gh-441 for dtype in [np.dtype('<'+t) for t in np.typecodes['Complex']]: z = np.array([2.2-1.1j], dtype) - x = z[0] # always native-endian + x = z[0] # always native-endian y = x.byteswap() if x.dtype.byteorder == z.dtype.byteorder: # little-endian machine @@ -1434,7 +1451,7 @@ class TestRegression(TestCase): assert_equal(x.imag, y.imag.byteswap()) def test_structured_arrays_with_objects1(self): - """Ticket #1299""" + # Ticket #1299 stra = 'aaaa' strb = 'bbbb' x = np.array([[(0, stra), (1, strb)]], 'i8,O') @@ -1442,7 +1459,7 @@ class TestRegression(TestCase): assert_(x[0, 1] == x[0, 0]) def test_structured_arrays_with_objects2(self): - """Ticket #1299 second test""" + # Ticket #1299 second test stra = 'aaaa' strb = 'bbbb' numb = sys.getrefcount(strb) @@ -1453,13 +1470,12 @@ class TestRegression(TestCase): assert_(sys.getrefcount(stra) == numa + 2) def test_duplicate_title_and_name(self): - """Ticket #1254""" - def func(): - x = np.dtype([(('a', 'a'), 'i'), ('b', 'i')]) - self.assertRaises(ValueError, func) + # Ticket #1254 + dtspec = [(('a', 'a'), 'i'), ('b', 'i')] + self.assertRaises(ValueError, np.dtype, dtspec) def test_signed_integer_division_overflow(self): - """Ticket #1317.""" + # Ticket #1317. def test_type(t): min = np.array([np.iinfo(t).min]) min //= -1 @@ -1510,7 +1526,7 @@ class TestRegression(TestCase): c = a.astype(y) try: np.dot(b, c) - except TypeError as e: + except TypeError: failures.append((x, y)) if failures: raise AssertionError("Failures: %r" % failures) @@ -1543,8 +1559,9 @@ class TestRegression(TestCase): class Subclass(np.ndarray): def __new__(cls, i): return np.ones((i,)).view(cls) + x = Subclass(5) - x[(0,)] = 2 # shouldn't raise an exception + x[(0,)] = 2 # shouldn't raise an exception assert_equal(x[0], 2) def test_ufunc_no_unnecessary_views(self): @@ -1610,7 +1627,7 @@ class TestRegression(TestCase): assert_equal(complex(x), 1+2j) def test_complex_boolean_cast(self): - """Ticket #2218""" + # Ticket #2218 for tp in [np.csingle, np.cdouble, np.clongdouble]: x = np.array([0, 0+0.5j, 0.5+0j], dtype=tp) assert_equal(x.astype(bool), np.array([0, 1, 1], dtype=bool)) @@ -1624,7 +1641,7 @@ class TestRegression(TestCase): def test_duplicate_field_names_assign(self): ra = np.fromiter(((i*3, i*2) for i in range(10)), dtype='i8,f8') ra.dtype.names = ('f1', 'f2') - rep = repr(ra) # should not cause a segmentation fault + repr(ra) # should not cause a segmentation fault assert_raises(ValueError, setattr, ra.dtype, 'names', ('f1', 'f1')) def test_eq_string_and_object_array(self): @@ -1639,7 +1656,7 @@ class TestRegression(TestCase): a.dtype = np.float32 assert_equal(a.nonzero()[0], [1]) a = a.byteswap().newbyteorder() - assert_equal(a.nonzero()[0], [1]) # [0] if nonzero() ignores swap + assert_equal(a.nonzero()[0], [1]) # [0] if nonzero() ignores swap def test_find_common_type_boolean(self): # Ticket #1695 @@ -1651,16 +1668,14 @@ class TestRegression(TestCase): assert_equal(a, [1.]) def test_array_side_effect(self): - assert_equal(np.dtype('S10').itemsize, 10) - - A = np.array([['abc', 2], ['long ', '0123456789']], dtype=np.string_) - - # This was throwing an exception because in ctors.c, - # discover_itemsize was calling PyObject_Length without checking - # the return code. This failed to get the length of the number 2, - # and the exception hung around until something checked + # The second use of itemsize was throwing an exception because in + # ctors.c, discover_itemsize was calling PyObject_Length without + # checking the return code. This failed to get the length of the + # number 2, and the exception hung around until something checked # PyErr_Occurred() and returned an error. assert_equal(np.dtype('S10').itemsize, 10) + np.array([['abc', 2], ['long ', '0123456789']], dtype=np.string_) + assert_equal(np.dtype('S10').itemsize, 10) def test_any_float(self): # all and any for floats @@ -1687,7 +1702,7 @@ class TestRegression(TestCase): assert_(np.array(np.float32(1.0)).flags.f_contiguous) def test_squeeze_contiguous(self): - """Similar to GitHub issue #387""" + # Similar to GitHub issue #387 a = np.zeros((1, 2)).squeeze() b = np.zeros((2, 2, 2), order='F')[:,:, ::2].squeeze() assert_(a.flags.c_contiguous) @@ -1695,7 +1710,7 @@ class TestRegression(TestCase): assert_(b.flags.f_contiguous) def test_reduce_contiguous(self): - """GitHub issue #387""" + # GitHub issue #387 a = np.add.reduce(np.zeros((2, 1, 2)), (0, 1)) b = np.add.reduce(np.zeros((2, 1, 2)), 1) assert_(a.flags.c_contiguous) @@ -1731,7 +1746,7 @@ class TestRegression(TestCase): a = np.array(object(), dtype=object) np.copyto(a, a) assert_equal(sys.getrefcount(a[()]), 2) - a[()].__class__ # will segfault if object was deleted + a[()].__class__ # will segfault if object was deleted def test_zerosize_accumulate(self): "Ticket #1733" @@ -1739,10 +1754,9 @@ class TestRegression(TestCase): assert_equal(np.add.accumulate(x[:-1, 0]), []) def test_objectarray_setfield(self): - # Setfield directly manipulates the raw array data, - # so is invalid for object arrays. + # Setfield should not overwrite Object fields with non-Object data x = np.array([1, 2, 3], dtype=object) - assert_raises(RuntimeError, x.setfield, 4, np.int32, 0) + assert_raises(TypeError, x.setfield, 4, np.int32, 0) def test_setting_rank0_string(self): "Ticket #1736" @@ -1771,24 +1785,24 @@ class TestRegression(TestCase): assert_equal(b.dtype, np.dtype('S5')) def test_ticket_1756(self): - """Ticket #1756 """ + # Ticket #1756 s = asbytes('0123456789abcdef') a = np.array([s]*5) for i in range(1, 17): - a1 = np.array(a, "|S%d"%i) + a1 = np.array(a, "|S%d" % i) a2 = np.array([s[:i]]*5) assert_equal(a1, a2) def test_fields_strides(self): "Ticket #1760" - r=np.fromstring('abcdefghijklmnop'*4*3, dtype='i4,(2,3)u2') + r = np.fromstring('abcdefghijklmnop'*4*3, dtype='i4,(2,3)u2') assert_equal(r[0:3:2]['f1'], r['f1'][0:3:2]) assert_equal(r[0:3:2]['f1'][0], r[0:3:2][0]['f1']) assert_equal(r[0:3:2]['f1'][0][()], r[0:3:2][0]['f1'][()]) assert_equal(r[0:3:2]['f1'][0].strides, r[0:3:2][0]['f1'].strides) def test_alignment_update(self): - """Check that alignment flag is updated on stride setting""" + # Check that alignment flag is updated on stride setting a = np.arange(10) assert_(a.flags.aligned) a.strides = 3 @@ -1809,7 +1823,7 @@ class TestRegression(TestCase): def test_ticket_1608(self): "x.flat shouldn't modify data" x = np.array([[1, 2], [3, 4]]).T - y = np.array(x.flat) + np.array(x.flat) assert_equal(x, [[1, 3], [2, 4]]) def test_pickle_string_overwrite(self): @@ -1937,7 +1951,7 @@ class TestRegression(TestCase): def test_ufunc_reduce_memoryleak(self): a = np.arange(6) acnt = sys.getrefcount(a) - res = np.add.reduce(a) + np.add.reduce(a) assert_equal(sys.getrefcount(a), acnt) def test_search_sorted_invalid_arguments(self): @@ -2081,6 +2095,7 @@ class TestRegression(TestCase): # dummy class where __array__ throws exception class Foo(object): __array_priority__ = 1002 + def __array__(self,*args,**kwargs): raise Exception() @@ -2099,6 +2114,7 @@ class TestRegression(TestCase): class Foo(np.ndarray): def __eq__(self, other): return "OK" + x = np.array([1,2,3]).view(Foo) assert_equal(10 == x, "OK") assert_equal(np.int32(10) == x, "OK") @@ -2125,6 +2141,37 @@ class TestRegression(TestCase): for axis in chain(range(-a.ndim, a.ndim), [None]): assert_equal(a.repeat(2, axis=axis), a.repeat([2], axis=axis)) + def test_frompyfunc_nout_0(self): + # gh-2014 + + def f(x): + x[0], x[-1] = x[-1], x[0] + + uf = np.frompyfunc(f, 1, 0) + a = np.array([[1, 2, 3], [4, 5], [6, 7, 8, 9]]) + assert_equal(uf(a), ()) + assert_array_equal(a, [[3, 2, 1], [5, 4], [9, 7, 8, 6]]) + + def test_leak_in_structured_dtype_comparison(self): + # gh-6250 + recordtype = np.dtype([('a', np.float64), + ('b', np.int32), + ('d', (np.str, 5))]) + + # Simple case + a = np.zeros(2, dtype=recordtype) + for i in range(100): + a == a + assert_(sys.getrefcount(a) < 10) + + # The case in the bug report. + before = sys.getrefcount(a) + u, v = a[0], a[1] + u == v + del u, v + gc.collect() + after = sys.getrefcount(a) + assert_equal(before, after) if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_scalarinherit.py b/numpy/core/tests/test_scalarinherit.py index 6f394196c..a2ca3e458 100644 --- a/numpy/core/tests/test_scalarinherit.py +++ b/numpy/core/tests/test_scalarinherit.py @@ -7,14 +7,20 @@ import numpy as np from numpy.testing import TestCase, run_module_suite -class A(object): pass -class B(A, np.float64): pass +class A(object): + pass +class B(A, np.float64): + pass -class C(B): pass -class D(C, B): pass +class C(B): + pass +class D(C, B): + pass -class B0(np.float64, A): pass -class C0(B0): pass +class B0(np.float64, A): + pass +class C0(B0): + pass class TestInherit(TestCase): def test_init(self): @@ -24,6 +30,7 @@ class TestInherit(TestCase): assert str(y) == '2.0' z = D(3.0) assert str(z) == '3.0' + def test_init2(self): x = B0(1.0) assert str(x) == '1.0' diff --git a/numpy/core/tests/test_scalarmath.py b/numpy/core/tests/test_scalarmath.py index 3ba3beff9..6dd9aa455 100644 --- a/numpy/core/tests/test_scalarmath.py +++ b/numpy/core/tests/test_scalarmath.py @@ -1,16 +1,22 @@ from __future__ import division, absolute_import, print_function import sys -import platform -from numpy.testing import * -from numpy.testing.utils import _gen_alignment_data + import numpy as np +from numpy.testing.utils import _gen_alignment_data +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_raises, + assert_almost_equal +) types = [np.bool_, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, np.int_, np.uint, np.longlong, np.ulonglong, np.single, np.double, np.longdouble, np.csingle, np.cdouble, np.clongdouble] +floating_types = np.floating.__subclasses__() + + # This compares scalarmath against ufuncs. class TestTypes(TestCase): @@ -112,6 +118,7 @@ class TestPower(TestCase): assert_(b == 6765201, msg) else: assert_almost_equal(b, 6765201, err_msg=msg) + def test_mixed_types(self): typelist = [np.int8, np.int16, np.float16, np.float32, np.float64, np.int8, @@ -175,11 +182,11 @@ class TestConversion(TestCase): assert_(res == tgt) def test_int_raise_behaviour(self): - def Overflow_error_func(dtype): - res = np.typeDict[dtype](np.iinfo(dtype).max + 1) + def overflow_error_func(dtype): + np.typeDict[dtype](np.iinfo(dtype).max + 1) for code in 'lLqQ': - assert_raises(OverflowError, Overflow_error_func, code) + assert_raises(OverflowError, overflow_error_func, code) def test_longdouble_int(self): # gh-627 @@ -189,7 +196,7 @@ class TestConversion(TestCase): assert_raises(OverflowError, x.__int__) def test_numpy_scalar_relational_operators(self): - #All integer + # All integer for dt1 in np.typecodes['AllInteger']: assert_(1 > np.array(0, dtype=dt1)[()], "type %s failed" % (dt1,)) assert_(not 1 < np.array(0, dtype=dt1)[()], "type %s failed" % (dt1,)) @@ -241,7 +248,7 @@ class TestConversion(TestCase): class TestRepr(object): def _test_type_repr(self, t): - finfo=np.finfo(t) + finfo = np.finfo(t) last_fraction_bit_idx = finfo.nexp + finfo.nmant last_exponent_bit_idx = finfo.nexp storage_bytes = np.dtype(t).itemsize*8 @@ -252,11 +259,11 @@ class TestRepr(object): if which == 'small denorm': byte = last_fraction_bit_idx // 8 bytebit = 7-(last_fraction_bit_idx % 8) - constr[byte] = 1<<bytebit + constr[byte] = 1 << bytebit elif which == 'small norm': byte = last_exponent_bit_idx // 8 bytebit = 7-(last_exponent_bit_idx % 8) - constr[byte] = 1<<bytebit + constr[byte] = 1 << bytebit else: raise ValueError('hmm') val = constr.view(t)[0] @@ -284,5 +291,26 @@ class TestSizeOf(TestCase): assert_raises(TypeError, d.__sizeof__, "a") +class TestAbs(TestCase): + + def _test_abs_func(self, absfunc): + for tp in floating_types: + x = tp(-1.5) + assert_equal(absfunc(x), 1.5) + x = tp(0.0) + res = absfunc(x) + # assert_equal() checks zero signedness + assert_equal(res, 0.0) + x = tp(-0.0) + res = absfunc(x) + assert_equal(res, 0.0) + + def test_builtin_abs(self): + self._test_abs_func(abs) + + def test_numpy_abs(self): + self._test_abs_func(np.abs) + + if __name__ == "__main__": run_module_suite() diff --git a/numpy/core/tests/test_shape_base.py b/numpy/core/tests/test_shape_base.py index f1f5311c9..cba083875 100644 --- a/numpy/core/tests/test_shape_base.py +++ b/numpy/core/tests/test_shape_base.py @@ -1,12 +1,11 @@ from __future__ import division, absolute_import, print_function -import warnings import numpy as np -from numpy.testing import (TestCase, assert_, assert_raises, assert_array_equal, - assert_equal, run_module_suite) -from numpy.core import (array, arange, atleast_1d, atleast_2d, atleast_3d, - vstack, hstack, newaxis, concatenate) from numpy.compat import long +from numpy.core import (array, arange, atleast_1d, atleast_2d, atleast_3d, + vstack, hstack, newaxis, concatenate, stack) +from numpy.testing import (TestCase, assert_, assert_raises, assert_array_equal, + assert_equal, run_module_suite, assert_raises_regex) class TestAtleast1d(TestCase): def test_0D_array(self): @@ -124,21 +123,21 @@ class TestHstack(TestCase): def test_0D_array(self): a = array(1) b = array(2) - res=hstack([a, b]) + res = hstack([a, b]) desired = array([1, 2]) assert_array_equal(res, desired) def test_1D_array(self): a = array([1]) b = array([2]) - res=hstack([a, b]) + res = hstack([a, b]) desired = array([1, 2]) assert_array_equal(res, desired) def test_2D_array(self): a = array([[1], [2]]) b = array([[1], [2]]) - res=hstack([a, b]) + res = hstack([a, b]) desired = array([[1, 1], [2, 2]]) assert_array_equal(res, desired) @@ -147,103 +146,173 @@ class TestVstack(TestCase): def test_0D_array(self): a = array(1) b = array(2) - res=vstack([a, b]) + res = vstack([a, b]) desired = array([[1], [2]]) assert_array_equal(res, desired) def test_1D_array(self): a = array([1]) b = array([2]) - res=vstack([a, b]) + res = vstack([a, b]) desired = array([[1], [2]]) assert_array_equal(res, desired) def test_2D_array(self): a = array([[1], [2]]) b = array([[1], [2]]) - res=vstack([a, b]) + res = vstack([a, b]) desired = array([[1], [2], [1], [2]]) assert_array_equal(res, desired) def test_2D_array2(self): a = array([1, 2]) b = array([1, 2]) - res=vstack([a, b]) + res = vstack([a, b]) desired = array([[1, 2], [1, 2]]) assert_array_equal(res, desired) -def test_concatenate_axis_None(): - a = np.arange(4, dtype=np.float64).reshape((2, 2)) - b = list(range(3)) - c = ['x'] - r = np.concatenate((a, a), axis=None) - assert_equal(r.dtype, a.dtype) - assert_equal(r.ndim, 1) - r = np.concatenate((a, b), axis=None) - assert_equal(r.size, a.size + len(b)) - assert_equal(r.dtype, a.dtype) - r = np.concatenate((a, b, c), axis=None) - d = array(['0.0', '1.0', '2.0', '3.0', - '0', '1', '2', 'x']) - assert_array_equal(r, d) - - -def test_concatenate(): - # Test concatenate function - # No arrays raise ValueError - assert_raises(ValueError, concatenate, ()) - # Scalars cannot be concatenated - assert_raises(ValueError, concatenate, (0,)) - assert_raises(ValueError, concatenate, (array(0),)) - # One sequence returns unmodified (but as array) - r4 = list(range(4)) - assert_array_equal(concatenate((r4,)), r4) - # Any sequence - assert_array_equal(concatenate((tuple(r4),)), r4) - assert_array_equal(concatenate((array(r4),)), r4) - # 1D default concatenation - r3 = list(range(3)) - assert_array_equal(concatenate((r4, r3)), r4 + r3) - # Mixed sequence types - assert_array_equal(concatenate((tuple(r4), r3)), r4 + r3) - assert_array_equal(concatenate((array(r4), r3)), r4 + r3) - # Explicit axis specification - assert_array_equal(concatenate((r4, r3), 0), r4 + r3) - # Including negative - assert_array_equal(concatenate((r4, r3), -1), r4 + r3) - # 2D - a23 = array([[10, 11, 12], [13, 14, 15]]) - a13 = array([[0, 1, 2]]) - res = array([[10, 11, 12], [13, 14, 15], [0, 1, 2]]) - assert_array_equal(concatenate((a23, a13)), res) - assert_array_equal(concatenate((a23, a13), 0), res) - assert_array_equal(concatenate((a23.T, a13.T), 1), res.T) - assert_array_equal(concatenate((a23.T, a13.T), -1), res.T) - # Arrays much match shape - assert_raises(ValueError, concatenate, (a23.T, a13.T), 0) - # 3D - res = arange(2 * 3 * 7).reshape((2, 3, 7)) - a0 = res[..., :4] - a1 = res[..., 4:6] - a2 = res[..., 6:] - assert_array_equal(concatenate((a0, a1, a2), 2), res) - assert_array_equal(concatenate((a0, a1, a2), -1), res) - assert_array_equal(concatenate((a0.T, a1.T, a2.T), 0), res.T) - - -def test_concatenate_sloppy0(): - # Versions of numpy < 1.7.0 ignored axis argument value for 1D arrays. We - # allow this for now, but in due course we will raise an error - r4 = list(range(4)) - r3 = list(range(3)) - assert_array_equal(concatenate((r4, r3), 0), r4 + r3) - with warnings.catch_warnings(): - warnings.simplefilter('ignore', DeprecationWarning) - assert_array_equal(concatenate((r4, r3), -10), r4 + r3) - assert_array_equal(concatenate((r4, r3), 10), r4 + r3) - # Confirm DeprecationWarning raised - warnings.simplefilter('error', DeprecationWarning) - assert_raises(DeprecationWarning, concatenate, (r4, r3), 10) + +class TestConcatenate(TestCase): + def test_exceptions(self): + # test axis must be in bounds + for ndim in [1, 2, 3]: + a = np.ones((1,)*ndim) + np.concatenate((a, a), axis=0) # OK + assert_raises(IndexError, np.concatenate, (a, a), axis=ndim) + assert_raises(IndexError, np.concatenate, (a, a), axis=-(ndim + 1)) + + # Scalars cannot be concatenated + assert_raises(ValueError, concatenate, (0,)) + assert_raises(ValueError, concatenate, (np.array(0),)) + + # test shapes must match except for concatenation axis + a = np.ones((1, 2, 3)) + b = np.ones((2, 2, 3)) + axis = list(range(3)) + for i in range(3): + np.concatenate((a, b), axis=axis[0]) # OK + assert_raises(ValueError, np.concatenate, (a, b), axis=axis[1]) + assert_raises(ValueError, np.concatenate, (a, b), axis=axis[2]) + a = np.rollaxis(a, -1) + b = np.rollaxis(b, -1) + axis.append(axis.pop(0)) + + # No arrays to concatenate raises ValueError + assert_raises(ValueError, concatenate, ()) + + def test_concatenate_axis_None(self): + a = np.arange(4, dtype=np.float64).reshape((2, 2)) + b = list(range(3)) + c = ['x'] + r = np.concatenate((a, a), axis=None) + assert_equal(r.dtype, a.dtype) + assert_equal(r.ndim, 1) + r = np.concatenate((a, b), axis=None) + assert_equal(r.size, a.size + len(b)) + assert_equal(r.dtype, a.dtype) + r = np.concatenate((a, b, c), axis=None) + d = array(['0.0', '1.0', '2.0', '3.0', + '0', '1', '2', 'x']) + assert_array_equal(r, d) + + def test_large_concatenate_axis_None(self): + # When no axis is given, concatenate uses flattened versions. + # This also had a bug with many arrays (see gh-5979). + x = np.arange(1, 100) + r = np.concatenate(x, None) + assert_array_equal(x, r) + + # This should probably be deprecated: + r = np.concatenate(x, 100) # axis is >= MAXDIMS + assert_array_equal(x, r) + + def test_concatenate(self): + # Test concatenate function + # One sequence returns unmodified (but as array) + r4 = list(range(4)) + assert_array_equal(concatenate((r4,)), r4) + # Any sequence + assert_array_equal(concatenate((tuple(r4),)), r4) + assert_array_equal(concatenate((array(r4),)), r4) + # 1D default concatenation + r3 = list(range(3)) + assert_array_equal(concatenate((r4, r3)), r4 + r3) + # Mixed sequence types + assert_array_equal(concatenate((tuple(r4), r3)), r4 + r3) + assert_array_equal(concatenate((array(r4), r3)), r4 + r3) + # Explicit axis specification + assert_array_equal(concatenate((r4, r3), 0), r4 + r3) + # Including negative + assert_array_equal(concatenate((r4, r3), -1), r4 + r3) + # 2D + a23 = array([[10, 11, 12], [13, 14, 15]]) + a13 = array([[0, 1, 2]]) + res = array([[10, 11, 12], [13, 14, 15], [0, 1, 2]]) + assert_array_equal(concatenate((a23, a13)), res) + assert_array_equal(concatenate((a23, a13), 0), res) + assert_array_equal(concatenate((a23.T, a13.T), 1), res.T) + assert_array_equal(concatenate((a23.T, a13.T), -1), res.T) + # Arrays much match shape + assert_raises(ValueError, concatenate, (a23.T, a13.T), 0) + # 3D + res = arange(2 * 3 * 7).reshape((2, 3, 7)) + a0 = res[..., :4] + a1 = res[..., 4:6] + a2 = res[..., 6:] + assert_array_equal(concatenate((a0, a1, a2), 2), res) + assert_array_equal(concatenate((a0, a1, a2), -1), res) + assert_array_equal(concatenate((a0.T, a1.T, a2.T), 0), res.T) + + +def test_stack(): + # 0d input + for input_ in [(1, 2, 3), + [np.int32(1), np.int32(2), np.int32(3)], + [np.array(1), np.array(2), np.array(3)]]: + assert_array_equal(stack(input_), [1, 2, 3]) + # 1d input examples + a = np.array([1, 2, 3]) + b = np.array([4, 5, 6]) + r1 = array([[1, 2, 3], [4, 5, 6]]) + assert_array_equal(np.stack((a, b)), r1) + assert_array_equal(np.stack((a, b), axis=1), r1.T) + # all input types + assert_array_equal(np.stack(list([a, b])), r1) + assert_array_equal(np.stack(array([a, b])), r1) + # all shapes for 1d input + arrays = [np.random.randn(3) for _ in range(10)] + axes = [0, 1, -1, -2] + expected_shapes = [(10, 3), (3, 10), (3, 10), (10, 3)] + for axis, expected_shape in zip(axes, expected_shapes): + assert_equal(np.stack(arrays, axis).shape, expected_shape) + assert_raises_regex(IndexError, 'out of bounds', stack, arrays, axis=2) + assert_raises_regex(IndexError, 'out of bounds', stack, arrays, axis=-3) + # all shapes for 2d input + arrays = [np.random.randn(3, 4) for _ in range(10)] + axes = [0, 1, 2, -1, -2, -3] + expected_shapes = [(10, 3, 4), (3, 10, 4), (3, 4, 10), + (3, 4, 10), (3, 10, 4), (10, 3, 4)] + for axis, expected_shape in zip(axes, expected_shapes): + assert_equal(np.stack(arrays, axis).shape, expected_shape) + # empty arrays + assert stack([[], [], []]).shape == (3, 0) + assert stack([[], [], []], axis=1).shape == (0, 3) + # edge cases + assert_raises_regex(ValueError, 'need at least one array', stack, []) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [1, np.arange(3)]) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [np.arange(3), 1]) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [np.arange(3), 1], axis=1) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [np.zeros((3, 3)), np.zeros(3)], axis=1) + assert_raises_regex(ValueError, 'must have the same shape', + stack, [np.arange(2), np.arange(3)]) + # np.matrix + m = np.matrix([[1, 2], [3, 4]]) + assert_raises_regex(ValueError, 'shape too large to be a matrix', + stack, [m, m]) if __name__ == "__main__": diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index 699a1b2ea..934d91e7c 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -1,13 +1,15 @@ from __future__ import division, absolute_import, print_function -import sys - import numpy as np -from numpy.testing import * import numpy.core.umath_tests as umt import numpy.core.operand_flag_tests as opflag_tests from numpy.compat import asbytes from numpy.core.test_rational import rational, test_add, test_add_rationals +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_raises, + assert_array_equal, assert_almost_equal, assert_array_almost_equal, + assert_no_warnings +) class TestUfuncKwargs(TestCase): @@ -47,13 +49,13 @@ class TestUfunc(TestCase): "(S'numpy.core.umath'\np1\nS'cos'\np2\ntp3\nRp4\n.") assert pickle.loads(astring) is np.cos - def test_reduceat_shifting_sum(self) : + def test_reduceat_shifting_sum(self): L = 6 x = np.arange(L) idx = np.array(list(zip(np.arange(L - 2), np.arange(L - 2) + 2))).ravel() assert_array_equal(np.add.reduceat(x, idx)[::2], [1, 3, 5, 7]) - def test_generic_loops(self) : + def test_generic_loops(self): """Test generic loops. The loops to be tested are: @@ -107,7 +109,7 @@ class TestUfunc(TestCase): """ fone = np.exp - ftwo = lambda x, y : x**y + ftwo = lambda x, y: x**y fone_val = 1 ftwo_val = 1 # check unary PyUFunc_f_f. @@ -162,9 +164,10 @@ class TestUfunc(TestCase): # class to use in testing object method loops class foo(object): - def conjugate(self) : + def conjugate(self): return np.bool_(1) - def logical_xor(self, obj) : + + def logical_xor(self, obj): return np.bool_(1) # check unary PyUFunc_O_O @@ -174,7 +177,7 @@ class TestUfunc(TestCase): # check unary PyUFunc_O_O_method msg = "PyUFunc_O_O_method" x = np.zeros(10, dtype=np.object)[0::2] - for i in range(len(x)) : + for i in range(len(x)): x[i] = foo() assert_(np.all(np.conjugate(x) == True), msg) @@ -185,14 +188,14 @@ class TestUfunc(TestCase): # check binary PyUFunc_OO_O_method msg = "PyUFunc_OO_O_method" x = np.zeros(10, dtype=np.object)[0::2] - for i in range(len(x)) : + for i in range(len(x)): x[i] = foo() assert_(np.all(np.logical_xor(x, x)), msg) # check PyUFunc_On_Om # fixme -- I don't know how to do this yet - def test_all_ufunc(self) : + def test_all_ufunc(self): """Try to check presence and results of all ufuncs. The list of ufuncs comes from generate_umath.py and is as follows: @@ -275,7 +278,6 @@ class TestUfunc(TestCase): """ pass - def test_signature(self): # the arguments to test_signature are: nin, nout, core_signature # pass @@ -286,30 +288,39 @@ class TestUfunc(TestCase): # in the following calls, a ValueError should be raised because # of error in core signature + # FIXME These should be using assert_raises + # error: extra parenthesis msg = "core_sig: extra parenthesis" try: ret = umt.test_signature(2, 1, "((i)),(i)->()") assert_equal(ret, None, err_msg=msg) - except ValueError: None + except ValueError: + pass + # error: parenthesis matching msg = "core_sig: parenthesis matching" try: ret = umt.test_signature(2, 1, "(i),)i(->()") assert_equal(ret, None, err_msg=msg) - except ValueError: None + except ValueError: + pass + # error: incomplete signature. letters outside of parenthesis are ignored msg = "core_sig: incomplete signature" try: ret = umt.test_signature(2, 1, "(i),->()") assert_equal(ret, None, err_msg=msg) - except ValueError: None + except ValueError: + pass + # error: incomplete signature. 2 output arguments are specified msg = "core_sig: incomplete signature" try: ret = umt.test_signature(2, 2, "(i),(i)->()") assert_equal(ret, None, err_msg=msg) - except ValueError: None + except ValueError: + pass # more complicated names for variables assert_equal(umt.test_signature(2, 1, "(i1,i2),(J_1)->(_kAB)"), 1) @@ -342,6 +353,16 @@ class TestUfunc(TestCase): np.add(a, 0.5, sig=('i4', 'i4', 'i4'), out=b, casting='unsafe') assert_equal(b, [0, 0, 1]) + def test_true_divide(self): + # True_divide has a non uniform signature, see #3484. + # This also tests type_tuple_type_resolver. + a = np.full(5, 12.5) + b = np.full(5, 10.0) + tgt = np.full(5, 1.25) + assert_almost_equal(np.true_divide(a, b, dtype=np.float64), tgt) + assert_almost_equal(np.true_divide(a, b, dtype=np.float32), tgt) + assert_raises(TypeError, np.true_divide, a, b, dtype=np.int) + def test_sum_stability(self): a = np.ones(500, dtype=np.float32) assert_almost_equal((a / 10.).sum() - a.size / 10., 0, 4) @@ -376,7 +397,7 @@ class TestUfunc(TestCase): for dt in (np.complex64, np.complex128, np.clongdouble): for v in (0, 1, 2, 7, 8, 9, 15, 16, 19, 127, 128, 1024, 1235): - tgt = dt(v * (v + 1) / 2) - dt((v * (v + 1) / 2) *1j) + tgt = dt(v * (v + 1) / 2) - dt((v * (v + 1) / 2) * 1j) d = np.empty(v, dtype=dt) d.real = np.arange(1, v + 1) d.imag = -np.arange(1, v + 1) @@ -427,20 +448,23 @@ class TestUfunc(TestCase): def test_type_cast(self): msg = "type cast" a = np.arange(6, dtype='short').reshape((2, 3)) - assert_array_equal(umt.inner1d(a, a), np.sum(a*a, axis=-1), err_msg=msg) + assert_array_equal(umt.inner1d(a, a), np.sum(a*a, axis=-1), + err_msg=msg) msg = "type cast on one argument" a = np.arange(6).reshape((2, 3)) - b = a+0.1 - assert_array_almost_equal(umt.inner1d(a, a), np.sum(a*a, axis=-1), - err_msg=msg) + b = a + 0.1 + assert_array_almost_equal(umt.inner1d(a, b), np.sum(a*b, axis=-1), + err_msg=msg) def test_endian(self): msg = "big endian" a = np.arange(6, dtype='>i4').reshape((2, 3)) - assert_array_equal(umt.inner1d(a, a), np.sum(a*a, axis=-1), err_msg=msg) + assert_array_equal(umt.inner1d(a, a), np.sum(a*a, axis=-1), + err_msg=msg) msg = "little endian" a = np.arange(6, dtype='<i4').reshape((2, 3)) - assert_array_equal(umt.inner1d(a, a), np.sum(a*a, axis=-1), err_msg=msg) + assert_array_equal(umt.inner1d(a, a), np.sum(a*a, axis=-1), + err_msg=msg) # Output should always be native-endian Ba = np.arange(1, dtype='>f8') @@ -520,8 +544,8 @@ class TestUfunc(TestCase): self.compare_matrix_multiply_results(np.double) def compare_matrix_multiply_results(self, tp): - d1 = np.array(rand(2, 3, 4), dtype=tp) - d2 = np.array(rand(2, 3, 4), dtype=tp) + d1 = np.array(np.random.rand(2, 3, 4), dtype=tp) + d2 = np.array(np.random.rand(2, 3, 4), dtype=tp) msg = "matrix multiply on type %s" % d1.dtype.name def permute_n(n): @@ -560,15 +584,15 @@ class TestUfunc(TestCase): for s2 in slice_3: a1 = d1.transpose(p1)[s1] a2 = d2.transpose(p2)[s2] - ref = ref and a1.base != None - ref = ref and a2.base != None + ref = ref and a1.base is not None + ref = ref and a2.base is not None if (a1.shape[-1] == a2.shape[-2] and broadcastable(a1.shape[0], a2.shape[0])): assert_array_almost_equal( umt.matrix_multiply(a1, a2), np.sum(a2[..., np.newaxis].swapaxes(-3, -1) * a1[..., np.newaxis,:], axis=-1), - err_msg = msg+' %s %s' % (str(a1.shape), + err_msg=msg + ' %s %s' % (str(a1.shape), str(a2.shape))) assert_equal(ref, True, err_msg="reference check") @@ -817,10 +841,13 @@ class TestUfunc(TestCase): # make sure that error we get an error in exactly those cases where we # expect one, and assumes the calculations themselves are done # correctly. + def ok(f, *args, **kwargs): f(*args, **kwargs) + def err(f, *args, **kwargs): assert_raises(ValueError, f, *args, **kwargs) + def t(expect, func, n, m): expect(func, np.zeros((n, m)), axis=1) expect(func, np.zeros((m, n)), axis=0) @@ -829,7 +856,7 @@ class TestUfunc(TestCase): expect(func, np.zeros((n, m // 2, m // 2)), axis=(1, 2)) expect(func, np.zeros((m // 2, n, m // 2)), axis=(0, 2)) expect(func, np.zeros((m // 3, m // 3, m // 3, - n // 2, n //2)), + n // 2, n // 2)), axis=(0, 1, 2)) # Check what happens if the inner (resp. outer) dimensions are a # mix of zero and non-zero: @@ -838,6 +865,7 @@ class TestUfunc(TestCase): expect(func, np.zeros((m, 10, n)), axis=0) expect(func, np.zeros((10, m, n)), axis=1) expect(func, np.zeros((10, n, m)), axis=2) + # np.maximum is just an arbitrary ufunc with no reduction identity assert_equal(np.maximum.identity, None) t(ok, np.maximum.reduce, 30, 30) @@ -875,8 +903,10 @@ class TestUfunc(TestCase): assert_array_equal(assert_no_warnings(np.add, a, 1.1), [2.1, 3.1, 4.1]) assert_raises(TypeError, np.add, a, 1.1, out=a) + def add_inplace(a, b): a += b + assert_raises(TypeError, add_inplace, a, 1.1) # Make sure that explicitly overriding the exception is allowed: assert_no_warnings(np.add, a, 1.1, out=a, casting="unsafe") @@ -921,16 +951,17 @@ class TestUfunc(TestCase): def test_custom_ufunc(self): a = np.array([rational(1, 2), rational(1, 3), rational(1, 4)], - dtype=rational); + dtype=rational) b = np.array([rational(1, 2), rational(1, 3), rational(1, 4)], - dtype=rational); + dtype=rational) result = test_add_rationals(a, b) expected = np.array([rational(1), rational(2, 3), rational(1, 2)], - dtype=rational); - assert_equal(result, expected); + dtype=rational) + assert_equal(result, expected) def test_custom_array_like(self): + class MyThing(object): __array_priority__ = 1000 @@ -1001,15 +1032,15 @@ class TestUfunc(TestCase): b = np.array([100, 200, 300]) np.add.at(a, (slice(None), [1, 2, 1], slice(None)), b) assert_equal(a, - [[[0, 1, 2 ], + [[[0, 1, 2], [203, 404, 605], [106, 207, 308]], - [[9, 10, 11 ], + [[9, 10, 11], [212, 413, 614], [115, 216, 317]], - [[18, 19, 20 ], + [[18, 19, 20], [221, 422, 623], [124, 225, 326]]]) @@ -1147,14 +1178,49 @@ class TestUfunc(TestCase): out=None) # invalid keyord + assert_raises(TypeError, f, d, axis=0, dtype=None, invalid=0) + assert_raises(TypeError, f, d, invalid=0) assert_raises(TypeError, f, d, 0, keepdims=True, invalid="invalid", out=None) - assert_raises(TypeError, f, d, invalid=0) assert_raises(TypeError, f, d, axis=0, dtype=None, keepdims=True, out=None, invalid=0) assert_raises(TypeError, f, d, axis=0, dtype=None, out=None, invalid=0) - assert_raises(TypeError, f, d, axis=0, dtype=None, invalid=0) + + def test_structured_equal(self): + # https://github.com/numpy/numpy/issues/4855 + + class MyA(np.ndarray): + def __numpy_ufunc__(self, ufunc, method, i, inputs, **kwargs): + return getattr(ufunc, method)(*(input.view(np.ndarray) + for input in inputs), **kwargs) + a = np.arange(12.).reshape(4,3) + ra = a.view(dtype=('f8,f8,f8')).squeeze() + mra = ra.view(MyA) + + target = np.array([ True, False, False, False], dtype=bool) + assert_equal(np.all(target == (mra == ra[0])), True) + + def test_NotImplemented_not_returned(self): + # See gh-5964 and gh-2091. Some of these functions are not operator + # related and were fixed for other reasons in the past. + binary_funcs = [ + np.power, np.add, np.subtract, np.multiply, np.divide, + np.true_divide, np.floor_divide, np.bitwise_and, np.bitwise_or, + np.bitwise_xor, np.left_shift, np.right_shift, np.fmax, + np.fmin, np.fmod, np.hypot, np.logaddexp, np.logaddexp2, + np.logical_and, np.logical_or, np.logical_xor, np.maximum, + np.minimum, np.mod + ] + + # These functions still return NotImplemented. Will be fixed in + # future. + # bad = [np.greater, np.greater_equal, np.less, np.less_equal, np.not_equal] + + a = np.array('1') + b = 1 + for f in binary_funcs: + assert_raises(TypeError, f, a, b) if __name__ == "__main__": diff --git a/numpy/core/tests/test_umath.py b/numpy/core/tests/test_umath.py index e8eee8090..033fac37d 100644 --- a/numpy/core/tests/test_umath.py +++ b/numpy/core/tests/test_umath.py @@ -4,10 +4,14 @@ import sys import platform import warnings -from numpy.testing import * from numpy.testing.utils import _gen_alignment_data import numpy.core.umath as ncu import numpy as np +from numpy.testing import ( + TestCase, run_module_suite, assert_, assert_equal, assert_raises, + assert_array_equal, assert_almost_equal, assert_array_almost_equal, + dec, assert_allclose, assert_no_warnings +) def on_powerpc(): @@ -28,11 +32,9 @@ class TestConstants(TestCase): def test_pi(self): assert_allclose(ncu.pi, 3.141592653589793, 1e-15) - def test_e(self): assert_allclose(ncu.e, 2.718281828459045, 1e-15) - def test_euler_gamma(self): assert_allclose(ncu.euler_gamma, 0.5772156649015329, 1e-15) @@ -89,12 +91,13 @@ class TestOut(TestCase): assert_raises(ValueError, np.add, a, 2, out=o, subok=subok) assert_raises(ValueError, np.add, a, 2, out=(o,), subok=subok) - def test_out_wrap_subok(self): class ArrayWrap(np.ndarray): __array_priority__ = 10 + def __new__(cls, arr): return np.asarray(arr).view(cls).copy() + def __array_wrap__(self, arr, context): return arr.view(type(self)) @@ -260,7 +263,6 @@ class TestPower(TestCase): np.sqrt(inp, out=out) assert_equal(out, exp, err_msg=msg) - def test_power_complex(self): x = np.array([1+2j, 2+3j, 3+4j]) assert_equal(x**0, [1., 1., 1.]) @@ -277,7 +279,7 @@ class TestPower(TestCase): norm = 1./((x**14)[0]) assert_almost_equal(x**14 * norm, [i * norm for i in [-76443+16124j, 23161315+58317492j, - 5583548873 + 2465133864j]]) + 5583548873 + 2465133864j]]) # Ticket #836 def assert_complex_equal(x, y): @@ -295,8 +297,9 @@ class TestPower(TestCase): # ticket #1271 zero = np.array([0j]) one = np.array([1+0j]) - cinf = np.array([complex(np.inf, 0)]) cnan = np.array([complex(np.nan, np.nan)]) + # FIXME cinf not tested. + #cinf = np.array([complex(np.inf, 0)]) def assert_complex_equal(x, y): x, y = np.asarray(x), np.asarray(y) @@ -327,10 +330,10 @@ class TestPower(TestCase): class TestLog2(TestCase): - def test_log2_values(self) : + def test_log2_values(self): x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - for dt in ['f', 'd', 'g'] : + for dt in ['f', 'd', 'g']: xf = np.array(x, dtype=dt) yf = np.array(y, dtype=dt) assert_almost_equal(np.log2(xf), yf) @@ -358,10 +361,10 @@ class TestLog2(TestCase): class TestExp2(TestCase): - def test_exp2_values(self) : + def test_exp2_values(self): x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - for dt in ['f', 'd', 'g'] : + for dt in ['f', 'd', 'g']: xf = np.array(x, dtype=dt) yf = np.array(y, dtype=dt) assert_almost_equal(np.exp2(yf), xf) @@ -369,33 +372,33 @@ class TestExp2(TestCase): class TestLogAddExp2(_FilterInvalids): # Need test for intermediate precisions - def test_logaddexp2_values(self) : + def test_logaddexp2_values(self): x = [1, 2, 3, 4, 5] y = [5, 4, 3, 2, 1] z = [6, 6, 6, 6, 6] - for dt, dec in zip(['f', 'd', 'g'], [6, 15, 15]) : + for dt, dec_ in zip(['f', 'd', 'g'], [6, 15, 15]): xf = np.log2(np.array(x, dtype=dt)) yf = np.log2(np.array(y, dtype=dt)) zf = np.log2(np.array(z, dtype=dt)) - assert_almost_equal(np.logaddexp2(xf, yf), zf, decimal=dec) + assert_almost_equal(np.logaddexp2(xf, yf), zf, decimal=dec_) - def test_logaddexp2_range(self) : + def test_logaddexp2_range(self): x = [1000000, -1000000, 1000200, -1000200] y = [1000200, -1000200, 1000000, -1000000] z = [1000200, -1000000, 1000200, -1000000] - for dt in ['f', 'd', 'g'] : + for dt in ['f', 'd', 'g']: logxf = np.array(x, dtype=dt) logyf = np.array(y, dtype=dt) logzf = np.array(z, dtype=dt) assert_almost_equal(np.logaddexp2(logxf, logyf), logzf) - def test_inf(self) : + def test_inf(self): inf = np.inf x = [inf, -inf, inf, -inf, inf, 1, -inf, 1] y = [inf, inf, -inf, -inf, 1, inf, 1, -inf] z = [inf, inf, inf, -inf, inf, inf, 1, 1] with np.errstate(invalid='raise'): - for dt in ['f', 'd', 'g'] : + for dt in ['f', 'd', 'g']: logxf = np.array(x, dtype=dt) logyf = np.array(y, dtype=dt) logzf = np.array(z, dtype=dt) @@ -410,10 +413,10 @@ class TestLogAddExp2(_FilterInvalids): class TestLog(TestCase): - def test_log_values(self) : + def test_log_values(self): x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - for dt in ['f', 'd', 'g'] : + for dt in ['f', 'd', 'g']: log2_ = 0.69314718055994530943 xf = np.array(x, dtype=dt) yf = np.array(y, dtype=dt)*log2_ @@ -421,10 +424,10 @@ class TestLog(TestCase): class TestExp(TestCase): - def test_exp_values(self) : + def test_exp_values(self): x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024] y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - for dt in ['f', 'd', 'g'] : + for dt in ['f', 'd', 'g']: log2_ = 0.69314718055994530943 xf = np.array(x, dtype=dt) yf = np.array(y, dtype=dt)*log2_ @@ -432,33 +435,33 @@ class TestExp(TestCase): class TestLogAddExp(_FilterInvalids): - def test_logaddexp_values(self) : + def test_logaddexp_values(self): x = [1, 2, 3, 4, 5] y = [5, 4, 3, 2, 1] z = [6, 6, 6, 6, 6] - for dt, dec in zip(['f', 'd', 'g'], [6, 15, 15]) : + for dt, dec_ in zip(['f', 'd', 'g'], [6, 15, 15]): xf = np.log(np.array(x, dtype=dt)) yf = np.log(np.array(y, dtype=dt)) zf = np.log(np.array(z, dtype=dt)) - assert_almost_equal(np.logaddexp(xf, yf), zf, decimal=dec) + assert_almost_equal(np.logaddexp(xf, yf), zf, decimal=dec_) - def test_logaddexp_range(self) : + def test_logaddexp_range(self): x = [1000000, -1000000, 1000200, -1000200] y = [1000200, -1000200, 1000000, -1000000] z = [1000200, -1000000, 1000200, -1000000] - for dt in ['f', 'd', 'g'] : + for dt in ['f', 'd', 'g']: logxf = np.array(x, dtype=dt) logyf = np.array(y, dtype=dt) logzf = np.array(z, dtype=dt) assert_almost_equal(np.logaddexp(logxf, logyf), logzf) - def test_inf(self) : + def test_inf(self): inf = np.inf x = [inf, -inf, inf, -inf, inf, 1, -inf, 1] y = [inf, inf, -inf, -inf, 1, inf, 1, -inf] z = [inf, inf, inf, -inf, inf, inf, 1, 1] with np.errstate(invalid='raise'): - for dt in ['f', 'd', 'g'] : + for dt in ['f', 'd', 'g']: logxf = np.array(x, dtype=dt) logyf = np.array(y, dtype=dt) logzf = np.array(z, dtype=dt) @@ -681,7 +684,7 @@ class TestMaximum(_FilterInvalids): nan = np.nan arg1 = np.array([0, nan, nan]) arg2 = np.array([nan, 0, nan]) - out = np.array([nan, nan, nan]) + out = np.array([nan, nan, nan]) assert_equal(np.maximum(arg1, arg2), out) def test_object_nans(self): @@ -697,10 +700,10 @@ class TestMaximum(_FilterInvalids): def test_complex_nans(self): nan = np.nan - for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)] : + for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)]: arg1 = np.array([0, cnan, cnan], dtype=np.complex) arg2 = np.array([cnan, 0, cnan], dtype=np.complex) - out = np.array([nan, nan, nan], dtype=np.complex) + out = np.array([nan, nan, nan], dtype=np.complex) assert_equal(np.maximum(arg1, arg2), out) def test_object_array(self): @@ -739,7 +742,7 @@ class TestMinimum(_FilterInvalids): nan = np.nan arg1 = np.array([0, nan, nan]) arg2 = np.array([nan, 0, nan]) - out = np.array([nan, nan, nan]) + out = np.array([nan, nan, nan]) assert_equal(np.minimum(arg1, arg2), out) def test_object_nans(self): @@ -755,10 +758,10 @@ class TestMinimum(_FilterInvalids): def test_complex_nans(self): nan = np.nan - for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)] : + for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)]: arg1 = np.array([0, cnan, cnan], dtype=np.complex) arg2 = np.array([cnan, 0, cnan], dtype=np.complex) - out = np.array([nan, nan, nan], dtype=np.complex) + out = np.array([nan, nan, nan], dtype=np.complex) assert_equal(np.minimum(arg1, arg2), out) def test_object_array(self): @@ -797,15 +800,15 @@ class TestFmax(_FilterInvalids): nan = np.nan arg1 = np.array([0, nan, nan]) arg2 = np.array([nan, 0, nan]) - out = np.array([0, 0, nan]) + out = np.array([0, 0, nan]) assert_equal(np.fmax(arg1, arg2), out) def test_complex_nans(self): nan = np.nan - for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)] : + for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)]: arg1 = np.array([0, cnan, cnan], dtype=np.complex) arg2 = np.array([cnan, 0, cnan], dtype=np.complex) - out = np.array([0, 0, nan], dtype=np.complex) + out = np.array([0, 0, nan], dtype=np.complex) assert_equal(np.fmax(arg1, arg2), out) @@ -839,15 +842,15 @@ class TestFmin(_FilterInvalids): nan = np.nan arg1 = np.array([0, nan, nan]) arg2 = np.array([nan, 0, nan]) - out = np.array([0, 0, nan]) + out = np.array([0, 0, nan]) assert_equal(np.fmin(arg1, arg2), out) def test_complex_nans(self): nan = np.nan - for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)] : + for cnan in [complex(nan, 0), complex(0, nan), complex(nan, nan)]: arg1 = np.array([0, cnan, cnan], dtype=np.complex) arg2 = np.array([cnan, 0, cnan], dtype=np.complex) - out = np.array([0, 0, nan], dtype=np.complex) + out = np.array([0, 0, nan], dtype=np.complex) assert_equal(np.fmin(arg1, arg2), out) @@ -1005,14 +1008,17 @@ class TestAbsoluteNegative(TestCase): class TestSpecialMethods(TestCase): def test_wrap(self): + class with_wrap(object): def __array__(self): return np.zeros(1) + def __array_wrap__(self, arr, context): r = with_wrap() r.arr = arr r.context = context return r + a = with_wrap() x = ncu.minimum(a, a) assert_equal(x.arr, np.zeros(1)) @@ -1025,12 +1031,16 @@ class TestSpecialMethods(TestCase): def test_wrap_with_iterable(self): # test fix for bug #1026: + class with_wrap(np.ndarray): __array_priority__ = 10 + def __new__(cls): return np.asarray(1).view(cls).copy() + def __array_wrap__(self, arr, context): return arr.view(type(self)) + a = with_wrap() x = ncu.multiply(a, (1, 2, 3)) self.assertTrue(isinstance(x, with_wrap)) @@ -1038,40 +1048,51 @@ class TestSpecialMethods(TestCase): def test_priority_with_scalar(self): # test fix for bug #826: + class A(np.ndarray): __array_priority__ = 10 + def __new__(cls): return np.asarray(1.0, 'float64').view(cls).copy() + a = A() x = np.float64(1)*a self.assertTrue(isinstance(x, A)) assert_array_equal(x, np.array(1)) def test_old_wrap(self): + class with_wrap(object): def __array__(self): return np.zeros(1) + def __array_wrap__(self, arr): r = with_wrap() r.arr = arr return r + a = with_wrap() x = ncu.minimum(a, a) assert_equal(x.arr, np.zeros(1)) def test_priority(self): + class A(object): def __array__(self): return np.zeros(1) + def __array_wrap__(self, arr, context): r = type(self)() r.arr = arr r.context = context return r + class B(A): __array_priority__ = 20. + class C(A): __array_priority__ = 40. + x = np.zeros(1) a = A() b = B() @@ -1098,47 +1119,61 @@ class TestSpecialMethods(TestCase): self.assertTrue(type(ncu.exp(c) is C)) def test_failing_wrap(self): + class A(object): def __array__(self): return np.zeros(1) + def __array_wrap__(self, arr, context): raise RuntimeError + a = A() self.assertRaises(RuntimeError, ncu.maximum, a, a) def test_default_prepare(self): + class with_wrap(object): __array_priority__ = 10 + def __array__(self): return np.zeros(1) + def __array_wrap__(self, arr, context): return arr + a = with_wrap() x = ncu.minimum(a, a) assert_equal(x, np.zeros(1)) assert_equal(type(x), np.ndarray) def test_prepare(self): + class with_prepare(np.ndarray): __array_priority__ = 10 + def __array_prepare__(self, arr, context): # make sure we can return a new return np.array(arr).view(type=with_prepare) + a = np.array(1).view(type=with_prepare) x = np.add(a, a) assert_equal(x, np.array(2)) assert_equal(type(x), with_prepare) def test_failing_prepare(self): + class A(object): def __array__(self): return np.zeros(1) + def __array_prepare__(self, arr, context=None): raise RuntimeError + a = A() self.assertRaises(RuntimeError, ncu.maximum, a, a) def test_array_with_context(self): + class A(object): def __array__(self, dtype=None, context=None): func, args, i = context @@ -1146,12 +1181,15 @@ class TestSpecialMethods(TestCase): self.args = args self.i = i return np.zeros(1) + class B(object): def __array__(self, dtype=None): return np.zeros(1, dtype) + class C(object): def __array__(self): return np.zeros(1) + a = A() ncu.maximum(np.zeros(1), a) self.assertTrue(a.func is ncu.maximum) @@ -1162,14 +1200,13 @@ class TestSpecialMethods(TestCase): assert_equal(ncu.maximum(a, C()), 0) def test_ufunc_override(self): + class A(object): def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs): return self, func, method, pos, inputs, kwargs a = A() - b = np.matrix([1]) - c = np.array([1]) res0 = np.multiply(a, b) res1 = np.dot(a, b) @@ -1220,8 +1257,6 @@ class TestSpecialMethods(TestCase): def __numpy_ufunc__(self, func, method, pos, inputs, **kwargs): return NotImplemented - - a = A() a_sub = ASub() b = B() @@ -1229,7 +1264,7 @@ class TestSpecialMethods(TestCase): c_sub = CSub() # Standard - res = np.multiply(a, a_sub) + res = np.multiply(a, a_sub) assert_equal(res, "ASub") res = np.multiply(a_sub, b) assert_equal(res, "ASub") @@ -1281,6 +1316,7 @@ class TestSpecialMethods(TestCase): assert_raises(TypeError, four_mul_ufunc, 1, c, c_sub, c) def test_ufunc_override_methods(self): + class A(object): def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs): return self, ufunc, method, pos, inputs, kwargs @@ -1384,11 +1420,11 @@ class TestSpecialMethods(TestCase): assert_equal(res[4], (a, [4, 2], 'b0')) def test_ufunc_override_out(self): + class A(object): def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs): return kwargs - class B(object): def __numpy_ufunc__(self, ufunc, method, pos, inputs, **kwargs): return kwargs @@ -1418,9 +1454,11 @@ class TestSpecialMethods(TestCase): assert_equal(res7['out'][1], 'out1') def test_ufunc_override_exception(self): + class A(object): def __numpy_ufunc__(self, *a, **kwargs): raise ValueError("oops") + a = A() for func in [np.divide, np.dot]: assert_raises(ValueError, func, a, a) @@ -1445,23 +1483,23 @@ class TestComplexFunctions(object): def test_it(self): for f in self.funcs: - if f is np.arccosh : + if f is np.arccosh: x = 1.5 - else : + else: x = .5 fr = f(x) fz = f(np.complex(x)) - assert_almost_equal(fz.real, fr, err_msg='real part %s'%f) - assert_almost_equal(fz.imag, 0., err_msg='imag part %s'%f) + assert_almost_equal(fz.real, fr, err_msg='real part %s' % f) + assert_almost_equal(fz.imag, 0., err_msg='imag part %s' % f) - def test_precisions_consistent(self) : + def test_precisions_consistent(self): z = 1 + 1j - for f in self.funcs : + for f in self.funcs: fcf = f(np.csingle(z)) - fcd = f(np.cdouble(z)) + fcd = f(np.cdouble(z)) fcl = f(np.clongdouble(z)) - assert_almost_equal(fcf, fcd, decimal=6, err_msg='fch-fcd %s'%f) - assert_almost_equal(fcl, fcd, decimal=15, err_msg='fch-fcl %s'%f) + assert_almost_equal(fcf, fcd, decimal=6, err_msg='fch-fcd %s' % f) + assert_almost_equal(fcl, fcd, decimal=15, err_msg='fch-fcl %s' % f) def test_branch_cuts(self): # check branch cuts and continuity on them @@ -1473,7 +1511,7 @@ class TestComplexFunctions(object): yield _check_branch_cut, np.arcsin, [ -2, 2], [1j, 1j], 1, -1, True yield _check_branch_cut, np.arccos, [ -2, 2], [1j, 1j], 1, -1, True - yield _check_branch_cut, np.arctan, [0-2j, 2j], [1, 1 ], -1, 1, True + yield _check_branch_cut, np.arctan, [0-2j, 2j], [1, 1], -1, 1, True yield _check_branch_cut, np.arcsinh, [0-2j, 2j], [1, 1], -1, 1, True yield _check_branch_cut, np.arccosh, [ -1, 0.5], [1j, 1j], 1, -1, True @@ -1484,7 +1522,7 @@ class TestComplexFunctions(object): yield _check_branch_cut, np.arccos, [0-2j, 2j], [ 1, 1], 1, 1 yield _check_branch_cut, np.arctan, [ -2, 2], [1j, 1j], 1, 1 - yield _check_branch_cut, np.arcsinh, [ -2, 2, 0], [1j, 1j, 1 ], 1, 1 + yield _check_branch_cut, np.arcsinh, [ -2, 2, 0], [1j, 1j, 1], 1, 1 yield _check_branch_cut, np.arccosh, [0-2j, 2j, 2], [1, 1, 1j], 1, 1 yield _check_branch_cut, np.arctanh, [0-2j, 2j, 0], [1, 1, 1j], 1, 1 @@ -1498,7 +1536,7 @@ class TestComplexFunctions(object): yield _check_branch_cut, np.arcsin, [ -2, 2], [1j, 1j], 1, -1, True, np.complex64 yield _check_branch_cut, np.arccos, [ -2, 2], [1j, 1j], 1, -1, True, np.complex64 - yield _check_branch_cut, np.arctan, [0-2j, 2j], [1, 1 ], -1, 1, True, np.complex64 + yield _check_branch_cut, np.arctan, [0-2j, 2j], [1, 1], -1, 1, True, np.complex64 yield _check_branch_cut, np.arcsinh, [0-2j, 2j], [1, 1], -1, 1, True, np.complex64 yield _check_branch_cut, np.arccosh, [ -1, 0.5], [1j, 1j], 1, -1, True, np.complex64 @@ -1509,12 +1547,12 @@ class TestComplexFunctions(object): yield _check_branch_cut, np.arccos, [0-2j, 2j], [ 1, 1], 1, 1, False, np.complex64 yield _check_branch_cut, np.arctan, [ -2, 2], [1j, 1j], 1, 1, False, np.complex64 - yield _check_branch_cut, np.arcsinh, [ -2, 2, 0], [1j, 1j, 1 ], 1, 1, False, np.complex64 + yield _check_branch_cut, np.arcsinh, [ -2, 2, 0], [1j, 1j, 1], 1, 1, False, np.complex64 yield _check_branch_cut, np.arccosh, [0-2j, 2j, 2], [1, 1, 1j], 1, 1, False, np.complex64 yield _check_branch_cut, np.arctanh, [0-2j, 2j, 0], [1, 1, 1j], 1, 1, False, np.complex64 def test_against_cmath(self): - import cmath, sys + import cmath points = [-1-1j, -1+1j, +1-1j, +1+1j] name_map = {'arcsin': 'asin', 'arccos': 'acos', 'arctan': 'atan', @@ -1530,7 +1568,7 @@ class TestComplexFunctions(object): for p in points: a = complex(func(np.complex_(p))) b = cfunc(p) - assert_(abs(a - b) < atol, "%s %s: %s; cmath: %s"%(fname, p, a, b)) + assert_(abs(a - b) < atol, "%s %s: %s; cmath: %s" % (fname, p, a, b)) def check_loss_of_precision(self, dtype): """Check loss of precision in complex arc* functions""" @@ -1631,7 +1669,7 @@ class TestAttributes(TestCase): add = ncu.add assert_equal(add.__name__, 'add') assert_(add.__doc__.startswith('add(x1, x2[, out])\n\n')) - self.assertTrue(add.ntypes >= 18) # don't fail if types added + self.assertTrue(add.ntypes >= 18) # don't fail if types added self.assertTrue('ii->i' in add.types) assert_equal(add.nin, 2) assert_equal(add.nout, 1) @@ -1639,12 +1677,15 @@ class TestAttributes(TestCase): class TestSubclass(TestCase): + def test_subclass_op(self): + class simple(np.ndarray): def __new__(subtype, shape): self = np.ndarray.__new__(subtype, shape, dtype=object) self.fill(0) return self + a = simple((3, 4)) assert_equal(a+a, a) @@ -1680,7 +1721,7 @@ def _check_branch_cut(f, x0, dx, re_sign=1, im_sign=-1, sig_zero_ok=False, atol = np.float32(1e-2) else: scale = np.finfo(dtype).eps * 1e3 - atol = 1e-4 + atol = 1e-4 y0 = f(x0) yp = f(x0 + dx*scale*np.absolute(x0)/np.absolute(dx)) @@ -1702,7 +1743,6 @@ def _check_branch_cut(f, x0, dx, re_sign=1, im_sign=-1, sig_zero_ok=False, assert_(np.all(np.absolute(y0[jr].real - ym.real*re_sign) < atol), (y0[jr], ym)) assert_(np.all(np.absolute(y0[jr].imag - ym.imag*im_sign) < atol), (y0[jr], ym)) - if np.any(ji): x = x0[ji] x.imag = np.NZERO @@ -1791,9 +1831,9 @@ def test_spacing_gfortran(): 6.10351563E-05, 9.76562500E-04] - for dt, dec in zip([np.float32, np.float64], (10, 20)): + for dt, dec_ in zip([np.float32, np.float64], (10, 20)): x = np.array([1e-5, 1, 1000, 10500], dtype=dt) - assert_array_almost_equal(np.spacing(x), ref[dt], decimal=dec) + assert_array_almost_equal(np.spacing(x), ref[dt], decimal=dec_) def test_nextafter_vs_spacing(): # XXX: spacing does not handle long double yet @@ -1830,7 +1870,7 @@ def test_reduceat(): # This is when the error occurs. # test no buffer - res = np.setbufsize(32) + np.setbufsize(32) h1 = np.add.reduceat(a['value'], indx) np.setbufsize(np.UFUNC_BUFSIZE_DEFAULT) assert_array_almost_equal(h1, h2) diff --git a/numpy/core/tests/test_umath_complex.py b/numpy/core/tests/test_umath_complex.py index 4f3da4397..536ad398a 100644 --- a/numpy/core/tests/test_umath_complex.py +++ b/numpy/core/tests/test_umath_complex.py @@ -3,9 +3,12 @@ from __future__ import division, absolute_import, print_function import sys import platform -from numpy.testing import * -import numpy.core.umath as ncu import numpy as np +import numpy.core.umath as ncu +from numpy.testing import ( + TestCase, run_module_suite, assert_equal, assert_array_equal, + assert_almost_equal, dec +) # TODO: branch cuts (use Pauli code) # TODO: conj 'symmetry' @@ -59,17 +62,11 @@ class TestCexp(object): yield check, f, np.inf, 0, np.inf, 0 # cexp(-inf + yi) is +0 * (cos(y) + i sin(y)) for finite y - ref = np.complex(np.cos(1.), np.sin(1.)) yield check, f, -np.inf, 1, np.PZERO, np.PZERO - - ref = np.complex(np.cos(np.pi * 0.75), np.sin(np.pi * 0.75)) yield check, f, -np.inf, 0.75 * np.pi, np.NZERO, np.PZERO # cexp(inf + yi) is +inf * (cos(y) + i sin(y)) for finite y - ref = np.complex(np.cos(1.), np.sin(1.)) yield check, f, np.inf, 1, np.inf, np.inf - - ref = np.complex(np.cos(np.pi * 0.75), np.sin(np.pi * 0.75)) yield check, f, np.inf, 0.75 * np.pi, -np.inf, np.inf # cexp(-inf + inf i) is +-0 +- 0i (signs unspecified) @@ -78,7 +75,7 @@ class TestCexp(object): with np.errstate(invalid='ignore'): z = f(np.array(np.complex(-np.inf, np.inf))) if z.real != 0 or z.imag != 0: - raise AssertionError(msgform %(z.real, z.imag)) + raise AssertionError(msgform % (z.real, z.imag)) yield _check_ninf_inf, None @@ -127,6 +124,9 @@ class TestCexp(object): def test_special_values2(self): # XXX: most implementations get it wrong here (including glibc <= 2.10) # cexp(nan + 0i) is nan + 0i + check = check_complex_value + f = np.exp + yield check, f, np.nan, 0, np.nan, 0 class TestClog(TestCase): @@ -271,7 +271,7 @@ class TestClog(TestCase): ya = np.array(yl, dtype=np.complex) with np.errstate(divide='ignore'): for i in range(len(xa)): - assert_almost_equal(np.log(np.conj(xa[i])), np.conj(np.log(xa[i]))) + assert_almost_equal(np.log(xa[i].conj()), ya[i].conj()) class TestCsqrt(object): @@ -287,6 +287,7 @@ class TestCsqrt(object): def test_simple_conjugate(self): ref = np.conj(np.sqrt(np.complex(1, 1))) + def f(z): return np.sqrt(np.conj(z)) yield check_complex_value, f, 1, 1, ref.real, ref.imag, False @@ -296,12 +297,11 @@ class TestCsqrt(object): @platform_skip def test_special_values(self): + # C99: Sec G 6.4.2 + check = check_complex_value f = np.sqrt - # C99: Sec G 6.4.2 - x, y = [], [] - # csqrt(+-0 + 0i) is 0 + 0i yield check, f, np.PZERO, 0, 0, 0 yield check, f, np.NZERO, 0, 0, 0 @@ -443,6 +443,7 @@ class TestCabs(object): # cabs(conj(z)) == conj(cabs(z)) (= cabs(z)) def f(a): return np.abs(np.conj(a)) + def g(a, b): return np.abs(np.complex(a, b)) diff --git a/numpy/core/tests/test_unicode.py b/numpy/core/tests/test_unicode.py index d184b3a9f..7a421a5fb 100644 --- a/numpy/core/tests/test_unicode.py +++ b/numpy/core/tests/test_unicode.py @@ -2,14 +2,15 @@ from __future__ import division, absolute_import, print_function import sys -from numpy.testing import * -from numpy.core import * -from numpy.compat import asbytes, sixu +import numpy as np +from numpy.compat import asbytes, unicode, sixu +from numpy.testing import TestCase, run_module_suite, assert_equal # Guess the UCS length for this python interpreter if sys.version_info[:2] >= (3, 3): # Python 3.3 uses a flexible string representation ucs4 = False + def buffer_length(arr): if isinstance(arr, unicode): arr = str(arr) @@ -18,10 +19,12 @@ if sys.version_info[:2] >= (3, 3): if v.shape is None: return len(v) * v.itemsize else: - return prod(v.shape) * v.itemsize + return np.prod(v.shape) * v.itemsize elif sys.version_info[0] >= 3: import array as _array + ucs4 = (_array.array('u').itemsize == 4) + def buffer_length(arr): if isinstance(arr, unicode): return _array.array('u').itemsize * len(arr) @@ -29,14 +32,15 @@ elif sys.version_info[0] >= 3: if v.shape is None: return len(v) * v.itemsize else: - return prod(v.shape) * v.itemsize + return np.prod(v.shape) * v.itemsize else: if len(buffer(sixu('u'))) == 4: ucs4 = True else: ucs4 = False + def buffer_length(arr): - if isinstance(arr, ndarray): + if isinstance(arr, np.ndarray): return len(arr.data) return len(buffer(arr)) @@ -72,19 +76,19 @@ class create_zeros(object): self.assertTrue(buffer_length(ua_scalar) == 0) def test_zeros0D(self): - """Check creation of 0-dimensional objects""" - ua = zeros((), dtype='U%s' % self.ulen) + # Check creation of 0-dimensional objects + ua = np.zeros((), dtype='U%s' % self.ulen) self.content_check(ua, ua[()], 4*self.ulen) def test_zerosSD(self): - """Check creation of single-dimensional objects""" - ua = zeros((2,), dtype='U%s' % self.ulen) + # Check creation of single-dimensional objects + ua = np.zeros((2,), dtype='U%s' % self.ulen) self.content_check(ua, ua[0], 4*self.ulen*2) self.content_check(ua, ua[1], 4*self.ulen*2) def test_zerosMD(self): - """Check creation of multi-dimensional objects""" - ua = zeros((2, 3, 4), dtype='U%s' % self.ulen) + # Check creation of multi-dimensional objects + ua = np.zeros((2, 3, 4), dtype='U%s' % self.ulen) self.content_check(ua, ua[0, 0, 0], 4*self.ulen*2*3*4) self.content_check(ua, ua[-1, -1, -1], 4*self.ulen*2*3*4) @@ -116,8 +120,8 @@ class create_values(object): # Small check that data in array element is ok self.assertTrue(ua_scalar == self.ucs_value*self.ulen) # Encode to UTF-8 and double check - self.assertTrue(ua_scalar.encode('utf-8') == \ - (self.ucs_value*self.ulen).encode('utf-8')) + self.assertTrue(ua_scalar.encode('utf-8') == + (self.ucs_value*self.ulen).encode('utf-8')) # Check buffer lengths for scalars if ucs4: self.assertTrue(buffer_length(ua_scalar) == 4*self.ulen) @@ -132,19 +136,19 @@ class create_values(object): self.assertTrue(buffer_length(ua_scalar) == 2*self.ulen) def test_values0D(self): - """Check creation of 0-dimensional objects with values""" - ua = array(self.ucs_value*self.ulen, dtype='U%s' % self.ulen) + # Check creation of 0-dimensional objects with values + ua = np.array(self.ucs_value*self.ulen, dtype='U%s' % self.ulen) self.content_check(ua, ua[()], 4*self.ulen) def test_valuesSD(self): - """Check creation of single-dimensional objects with values""" - ua = array([self.ucs_value*self.ulen]*2, dtype='U%s' % self.ulen) + # Check creation of single-dimensional objects with values + ua = np.array([self.ucs_value*self.ulen]*2, dtype='U%s' % self.ulen) self.content_check(ua, ua[0], 4*self.ulen*2) self.content_check(ua, ua[1], 4*self.ulen*2) def test_valuesMD(self): - """Check creation of multi-dimensional objects with values""" - ua = array([[[self.ucs_value*self.ulen]*2]*3]*4, dtype='U%s' % self.ulen) + # Check creation of multi-dimensional objects with values + ua = np.array([[[self.ucs_value*self.ulen]*2]*3]*4, dtype='U%s' % self.ulen) self.content_check(ua, ua[0, 0, 0], 4*self.ulen*2*3*4) self.content_check(ua, ua[-1, -1, -1], 4*self.ulen*2*3*4) @@ -201,8 +205,8 @@ class assign_values(object): # Small check that data in array element is ok self.assertTrue(ua_scalar == self.ucs_value*self.ulen) # Encode to UTF-8 and double check - self.assertTrue(ua_scalar.encode('utf-8') == \ - (self.ucs_value*self.ulen).encode('utf-8')) + self.assertTrue(ua_scalar.encode('utf-8') == + (self.ucs_value*self.ulen).encode('utf-8')) # Check buffer lengths for scalars if ucs4: self.assertTrue(buffer_length(ua_scalar) == 4*self.ulen) @@ -217,22 +221,22 @@ class assign_values(object): self.assertTrue(buffer_length(ua_scalar) == 2*self.ulen) def test_values0D(self): - """Check assignment of 0-dimensional objects with values""" - ua = zeros((), dtype='U%s' % self.ulen) + # Check assignment of 0-dimensional objects with values + ua = np.zeros((), dtype='U%s' % self.ulen) ua[()] = self.ucs_value*self.ulen self.content_check(ua, ua[()], 4*self.ulen) def test_valuesSD(self): - """Check assignment of single-dimensional objects with values""" - ua = zeros((2,), dtype='U%s' % self.ulen) + # Check assignment of single-dimensional objects with values + ua = np.zeros((2,), dtype='U%s' % self.ulen) ua[0] = self.ucs_value*self.ulen self.content_check(ua, ua[0], 4*self.ulen*2) ua[1] = self.ucs_value*self.ulen self.content_check(ua, ua[1], 4*self.ulen*2) def test_valuesMD(self): - """Check assignment of multi-dimensional objects with values""" - ua = zeros((2, 3, 4), dtype='U%s' % self.ulen) + # Check assignment of multi-dimensional objects with values + ua = np.zeros((2, 3, 4), dtype='U%s' % self.ulen) ua[0, 0, 0] = self.ucs_value*self.ulen self.content_check(ua, ua[0, 0, 0], 4*self.ulen*2*3*4) ua[-1, -1, -1] = self.ucs_value*self.ulen @@ -275,7 +279,6 @@ class test_assign_values_1009_ucs4(assign_values, TestCase): ucs_value = ucs4_value - ############################################################ # Byteorder tests ############################################################ @@ -284,8 +287,8 @@ class byteorder_values: """Check the byteorder of unicode arrays in round-trip conversions""" def test_values0D(self): - """Check byteorder of 0-dimensional objects""" - ua = array(self.ucs_value*self.ulen, dtype='U%s' % self.ulen) + # Check byteorder of 0-dimensional objects + ua = np.array(self.ucs_value*self.ulen, dtype='U%s' % self.ulen) ua2 = ua.newbyteorder() # This changes the interpretation of the data region (but not the # actual data), therefore the returned scalars are not @@ -296,8 +299,8 @@ class byteorder_values: assert_equal(ua, ua3) def test_valuesSD(self): - """Check byteorder of single-dimensional objects""" - ua = array([self.ucs_value*self.ulen]*2, dtype='U%s' % self.ulen) + # Check byteorder of single-dimensional objects + ua = np.array([self.ucs_value*self.ulen]*2, dtype='U%s' % self.ulen) ua2 = ua.newbyteorder() self.assertTrue(ua[0] != ua2[0]) self.assertTrue(ua[-1] != ua2[-1]) @@ -306,8 +309,8 @@ class byteorder_values: assert_equal(ua, ua3) def test_valuesMD(self): - """Check byteorder of multi-dimensional objects""" - ua = array([[[self.ucs_value*self.ulen]*2]*3]*4, + # Check byteorder of multi-dimensional objects + ua = np.array([[[self.ucs_value*self.ulen]*2]*3]*4, dtype='U%s' % self.ulen) ua2 = ua.newbyteorder() self.assertTrue(ua[0, 0, 0] != ua2[0, 0, 0]) |