diff options
| author | czgdp1807 <gdp.1807@gmail.com> | 2021-09-03 12:17:26 +0530 |
|---|---|---|
| committer | czgdp1807 <gdp.1807@gmail.com> | 2021-09-03 12:17:26 +0530 |
| commit | 781d0a7ac61ce007e65abcd4e30f2181e729ae61 (patch) | |
| tree | f45f38a246bcefbca9ca8a08bd8ba55cbc6cdb15 /numpy/core | |
| parent | b341e4c3249817d2e14ddf71aa850a8a896b9303 (diff) | |
| parent | 2ae1e068710174dc57b5ba5ad688517608efcf26 (diff) | |
| download | numpy-781d0a7ac61ce007e65abcd4e30f2181e729ae61.tar.gz | |
resolved conflicts
Diffstat (limited to 'numpy/core')
50 files changed, 577 insertions, 347 deletions
diff --git a/numpy/core/_add_newdocs.py b/numpy/core/_add_newdocs.py index 759a91d27..06f2a6376 100644 --- a/numpy/core/_add_newdocs.py +++ b/numpy/core/_add_newdocs.py @@ -3252,7 +3252,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('dumps', a.dumps() Returns the pickle of the array as a string. - pickle.loads or numpy.loads will convert the string back to an array. + pickle.loads will convert the string back to an array. Parameters ---------- diff --git a/numpy/core/_add_newdocs_scalars.py b/numpy/core/_add_newdocs_scalars.py index 602b1db6e..8773d6c96 100644 --- a/numpy/core/_add_newdocs_scalars.py +++ b/numpy/core/_add_newdocs_scalars.py @@ -205,12 +205,12 @@ add_newdoc_for_scalar_type('bytes_', ['string_'], add_newdoc_for_scalar_type('void', [], r""" Either an opaque sequence of bytes, or a structure. - + >>> np.void(b'abcd') void(b'\x61\x62\x63\x64') - + Structured `void` scalars can only be constructed via extraction from :ref:`structured_arrays`: - + >>> arr = np.array((1, 2), dtype=[('x', np.int8), ('y', np.int8)]) >>> arr[()] (1, 2) # looks like a tuple, but is `np.void` @@ -226,20 +226,36 @@ add_newdoc_for_scalar_type('datetime64', [], >>> np.datetime64(10, 'Y') numpy.datetime64('1980') >>> np.datetime64('1980', 'Y') - numpy.datetime64('1980') + numpy.datetime64('1980') >>> np.datetime64(10, 'D') numpy.datetime64('1970-01-11') - + See :ref:`arrays.datetime` for more information. """) add_newdoc_for_scalar_type('timedelta64', [], """ A timedelta stored as a 64-bit integer. - + See :ref:`arrays.datetime` for more information. """) +add_newdoc('numpy.core.numerictypes', "integer", ('is_integer', + """ + integer.is_integer() -> bool + + Return ``True`` if the number is finite with integral value. + + .. versionadded:: 1.22 + + Examples + -------- + >>> np.int64(-2).is_integer() + True + >>> np.uint32(5).is_integer() + True + """)) + # TODO: work out how to put this on the base class, np.floating for float_name in ('half', 'single', 'double', 'longdouble'): add_newdoc('numpy.core.numerictypes', float_name, ('as_integer_ratio', @@ -257,3 +273,20 @@ for float_name in ('half', 'single', 'double', 'longdouble'): >>> np.{ftype}(-.25).as_integer_ratio() (-1, 4) """.format(ftype=float_name))) + + add_newdoc('numpy.core.numerictypes', float_name, ('is_integer', + f""" + {float_name}.is_integer() -> bool + + Return ``True`` if the floating point number is finite with integral + value, and ``False`` otherwise. + + .. versionadded:: 1.22 + + Examples + -------- + >>> np.{float_name}(-2.0).is_integer() + True + >>> np.{float_name}(3.2).is_integer() + False + """)) diff --git a/numpy/core/_asarray.pyi b/numpy/core/_asarray.pyi index 1928cfe12..fee9b7b6e 100644 --- a/numpy/core/_asarray.pyi +++ b/numpy/core/_asarray.pyi @@ -1,14 +1,8 @@ -import sys -from typing import TypeVar, Union, Iterable, overload +from typing import TypeVar, Union, Iterable, overload, Literal from numpy import ndarray from numpy.typing import ArrayLike, DTypeLike -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - _ArrayType = TypeVar("_ArrayType", bound=ndarray) _Requirements = Literal[ diff --git a/numpy/core/_type_aliases.py b/numpy/core/_type_aliases.py index 67addef48..3765a0d34 100644 --- a/numpy/core/_type_aliases.py +++ b/numpy/core/_type_aliases.py @@ -115,15 +115,6 @@ def _add_aliases(): # add forward, reverse, and string mapping to numarray sctypeDict[char] = info.type - # Add deprecated numeric-style type aliases manually, at some point - # we may want to deprecate the lower case "bytes0" version as well. - for name in ["Bytes0", "Datetime64", "Str0", "Uint32", "Uint64"]: - if english_lower(name) not in allTypes: - # Only one of Uint32 or Uint64, aliases of `np.uintp`, was (and is) defined, note that this - # is not UInt32/UInt64 (capital i), which is removed. - continue - allTypes[name] = allTypes[english_lower(name)] - sctypeDict[name] = sctypeDict[english_lower(name)] _add_aliases() diff --git a/numpy/core/_type_aliases.pyi b/numpy/core/_type_aliases.pyi index 6a1099cd3..c10d072f9 100644 --- a/numpy/core/_type_aliases.pyi +++ b/numpy/core/_type_aliases.pyi @@ -1,13 +1,7 @@ -import sys -from typing import Dict, Union, Type, List +from typing import Dict, Union, Type, List, TypedDict from numpy import generic, signedinteger, unsignedinteger, floating, complexfloating -if sys.version_info >= (3, 8): - from typing import TypedDict -else: - from typing_extensions import TypedDict - class _SCTypes(TypedDict): int: List[Type[signedinteger]] uint: List[Type[unsignedinteger]] diff --git a/numpy/core/_ufunc_config.pyi b/numpy/core/_ufunc_config.pyi index e90f1c510..9c8cc8ab6 100644 --- a/numpy/core/_ufunc_config.pyi +++ b/numpy/core/_ufunc_config.pyi @@ -1,16 +1,10 @@ -import sys -from typing import Optional, Union, Callable, Any - -if sys.version_info >= (3, 8): - from typing import Literal, Protocol, TypedDict -else: - from typing_extensions import Literal, Protocol, TypedDict +from typing import Optional, Union, Callable, Any, Literal, Protocol, TypedDict _ErrKind = Literal["ignore", "warn", "raise", "call", "print", "log"] _ErrFunc = Callable[[str, int], Any] class _SupportsWrite(Protocol): - def write(self, __msg: str) -> Any: ... + def write(self, msg: str, /) -> Any: ... class _ErrDict(TypedDict): divide: _ErrKind diff --git a/numpy/core/arrayprint.pyi b/numpy/core/arrayprint.pyi index ac2b6f5a8..df22efed6 100644 --- a/numpy/core/arrayprint.pyi +++ b/numpy/core/arrayprint.pyi @@ -1,6 +1,5 @@ -import sys from types import TracebackType -from typing import Any, Optional, Callable, Union, Type +from typing import Any, Optional, Callable, Union, Type, Literal, TypedDict, SupportsIndex # Using a private class is by no means ideal, but it is simply a consquence # of a `contextlib.context` returning an instance of aformentioned class @@ -23,11 +22,6 @@ from numpy import ( ) from numpy.typing import ArrayLike, _CharLike_co, _FloatLike_co -if sys.version_info > (3, 8): - from typing import Literal, TypedDict, SupportsIndex -else: - from typing_extensions import Literal, TypedDict, SupportsIndex - _FloatMode = Literal["fixed", "unique", "maxprec", "maxprec_equal"] class _FormatDict(TypedDict, total=False): diff --git a/numpy/core/code_generators/generate_umath.py b/numpy/core/code_generators/generate_umath.py index 1b6917ebc..4891e8f23 100644 --- a/numpy/core/code_generators/generate_umath.py +++ b/numpy/core/code_generators/generate_umath.py @@ -489,7 +489,6 @@ defdict = { 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(nodatetime_or_obj, out='?', simd=[('avx2', ints)]), TD(O, f='npy_ObjectLogicalAnd'), - TD(O, f='npy_ObjectLogicalAnd', out='?'), ), 'logical_not': Ufunc(1, 1, None, @@ -497,7 +496,6 @@ defdict = { None, TD(nodatetime_or_obj, out='?', simd=[('avx2', ints)]), TD(O, f='npy_ObjectLogicalNot'), - TD(O, f='npy_ObjectLogicalNot', out='?'), ), 'logical_or': Ufunc(2, 1, False_, @@ -505,13 +503,13 @@ defdict = { 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(nodatetime_or_obj, out='?', simd=[('avx2', ints)]), TD(O, f='npy_ObjectLogicalOr'), - TD(O, f='npy_ObjectLogicalOr', out='?'), ), 'logical_xor': Ufunc(2, 1, False_, docstrings.get('numpy.core.umath.logical_xor'), 'PyUFunc_SimpleBinaryComparisonTypeResolver', TD(nodatetime_or_obj, out='?'), + # TODO: using obj.logical_xor() seems pretty much useless: TD(P, f='logical_xor'), ), 'maximum': diff --git a/numpy/core/einsumfunc.pyi b/numpy/core/einsumfunc.pyi index 2457e8719..52025d502 100644 --- a/numpy/core/einsumfunc.pyi +++ b/numpy/core/einsumfunc.pyi @@ -1,5 +1,4 @@ -import sys -from typing import List, TypeVar, Optional, Any, overload, Union, Tuple, Sequence +from typing import List, TypeVar, Optional, Any, overload, Union, Tuple, Sequence, Literal from numpy import ( ndarray, @@ -26,11 +25,6 @@ from numpy.typing import ( _DTypeLikeComplex_co, ) -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - _ArrayType = TypeVar( "_ArrayType", bound=ndarray[Any, dtype[Union[bool_, number[Any]]]], @@ -52,7 +46,8 @@ __all__: List[str] # Something like `is_scalar = bool(__subscripts.partition("->")[-1])` @overload def einsum( - __subscripts: str, + subscripts: str, + /, *operands: _ArrayLikeBool_co, out: None = ..., dtype: Optional[_DTypeLikeBool] = ..., @@ -62,7 +57,8 @@ def einsum( ) -> Any: ... @overload def einsum( - __subscripts: str, + subscripts: str, + /, *operands: _ArrayLikeUInt_co, out: None = ..., dtype: Optional[_DTypeLikeUInt] = ..., @@ -72,7 +68,8 @@ def einsum( ) -> Any: ... @overload def einsum( - __subscripts: str, + subscripts: str, + /, *operands: _ArrayLikeInt_co, out: None = ..., dtype: Optional[_DTypeLikeInt] = ..., @@ -82,7 +79,8 @@ def einsum( ) -> Any: ... @overload def einsum( - __subscripts: str, + subscripts: str, + /, *operands: _ArrayLikeFloat_co, out: None = ..., dtype: Optional[_DTypeLikeFloat] = ..., @@ -92,7 +90,8 @@ def einsum( ) -> Any: ... @overload def einsum( - __subscripts: str, + subscripts: str, + /, *operands: _ArrayLikeComplex_co, out: None = ..., dtype: Optional[_DTypeLikeComplex] = ..., @@ -102,7 +101,8 @@ def einsum( ) -> Any: ... @overload def einsum( - __subscripts: str, + subscripts: str, + /, *operands: Any, casting: _CastingUnsafe, dtype: Optional[_DTypeLikeComplex_co] = ..., @@ -112,7 +112,8 @@ def einsum( ) -> Any: ... @overload def einsum( - __subscripts: str, + subscripts: str, + /, *operands: _ArrayLikeComplex_co, out: _ArrayType, dtype: Optional[_DTypeLikeComplex_co] = ..., @@ -122,7 +123,8 @@ def einsum( ) -> _ArrayType: ... @overload def einsum( - __subscripts: str, + subscripts: str, + /, *operands: Any, out: _ArrayType, casting: _CastingUnsafe, @@ -136,7 +138,8 @@ def einsum( # NOTE: In practice the list consists of a `str` (first element) # and a variable number of integer tuples. def einsum_path( - __subscripts: str, + subscripts: str, + /, *operands: _ArrayLikeComplex_co, optimize: _OptimizeKind = ..., ) -> Tuple[List[Any], str]: ... diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py index 764377bc9..5ecb1e666 100644 --- a/numpy/core/fromnumeric.py +++ b/numpy/core/fromnumeric.py @@ -3320,18 +3320,15 @@ def around(a, decimals=0, out=None): ---------- .. [1] "Lecture Notes on the Status of IEEE 754", William Kahan, https://people.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF - .. [2] "How Futile are Mindless Assessments of - Roundoff in Floating-Point Computation?", William Kahan, - https://people.eecs.berkeley.edu/~wkahan/Mindless.pdf Examples -------- >>> np.around([0.37, 1.64]) - array([0., 2.]) + array([0., 2.]) >>> np.around([0.37, 1.64], decimals=1) - array([0.4, 1.6]) + array([0.4, 1.6]) >>> np.around([.5, 1.5, 2.5, 3.5, 4.5]) # rounds to nearest even value - array([0., 2., 2., 4., 4.]) + array([0., 2., 2., 4., 4.]) >>> np.around([1,2,3,11], decimals=1) # ndarray of ints is returned array([ 1, 2, 3, 11]) >>> np.around([1,2,3,11], decimals=-1) diff --git a/numpy/core/fromnumeric.pyi b/numpy/core/fromnumeric.pyi index 45057e4b1..3cbe1d5c5 100644 --- a/numpy/core/fromnumeric.pyi +++ b/numpy/core/fromnumeric.pyi @@ -1,6 +1,5 @@ -import sys import datetime as dt -from typing import Optional, Union, Sequence, Tuple, Any, overload, TypeVar +from typing import Optional, Union, Sequence, Tuple, Any, overload, TypeVar, Literal from numpy import ( ndarray, @@ -26,11 +25,6 @@ from numpy.typing import ( _NumberLike_co, ) -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - # Various annotations for scalars # While dt.datetime and dt.timedelta are not technically part of NumPy, diff --git a/numpy/core/function_base.pyi b/numpy/core/function_base.pyi index b5d6ca6ab..c35629aa7 100644 --- a/numpy/core/function_base.pyi +++ b/numpy/core/function_base.pyi @@ -1,14 +1,8 @@ -import sys -from typing import overload, Tuple, Union, Sequence, Any +from typing import overload, Tuple, Union, Sequence, Any, SupportsIndex, Literal from numpy import ndarray from numpy.typing import ArrayLike, DTypeLike, _SupportsArray, _NumberLike_co -if sys.version_info >= (3, 8): - from typing import SupportsIndex, Literal -else: - from typing_extensions import SupportsIndex, Literal - # TODO: wait for support for recursive types _ArrayLikeNested = Sequence[Sequence[Any]] _ArrayLikeNumber = Union[ diff --git a/numpy/core/include/numpy/npy_cpu.h b/numpy/core/include/numpy/npy_cpu.h index bc1fad72f..e975b0105 100644 --- a/numpy/core/include/numpy/npy_cpu.h +++ b/numpy/core/include/numpy/npy_cpu.h @@ -18,6 +18,7 @@ * NPY_CPU_ARCEL * NPY_CPU_ARCEB * NPY_CPU_RISCV64 + * NPY_CPU_LOONGARCH * NPY_CPU_WASM */ #ifndef _NPY_CPUARCH_H_ @@ -103,6 +104,8 @@ #define NPY_CPU_ARCEB #elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 64 #define NPY_CPU_RISCV64 +#elif defined(__loongarch__) + #define NPY_CPU_LOONGARCH #elif defined(__EMSCRIPTEN__) /* __EMSCRIPTEN__ is defined by emscripten: an LLVM-to-Web compiler */ #define NPY_CPU_WASM diff --git a/numpy/core/include/numpy/npy_endian.h b/numpy/core/include/numpy/npy_endian.h index aa367a002..620595bec 100644 --- a/numpy/core/include/numpy/npy_endian.h +++ b/numpy/core/include/numpy/npy_endian.h @@ -49,6 +49,7 @@ || defined(NPY_CPU_PPC64LE) \ || defined(NPY_CPU_ARCEL) \ || defined(NPY_CPU_RISCV64) \ + || defined(NPY_CPU_LOONGARCH) \ || defined(NPY_CPU_WASM) #define NPY_BYTE_ORDER NPY_LITTLE_ENDIAN #elif defined(NPY_CPU_PPC) \ diff --git a/numpy/core/include/numpy/npy_math.h b/numpy/core/include/numpy/npy_math.h index f32e298f0..e9a6a30d2 100644 --- a/numpy/core/include/numpy/npy_math.h +++ b/numpy/core/include/numpy/npy_math.h @@ -391,7 +391,7 @@ NPY_INPLACE npy_longdouble npy_heavisidel(npy_longdouble x, npy_longdouble h0); union { \ ctype z; \ type a[2]; \ - } z1;; \ + } z1; \ \ z1.a[0] = (x); \ z1.a[1] = (y); \ diff --git a/numpy/core/multiarray.pyi b/numpy/core/multiarray.pyi index 7ae831b53..97e9c3498 100644 --- a/numpy/core/multiarray.pyi +++ b/numpy/core/multiarray.pyi @@ -1,12 +1,11 @@ # TODO: Sort out any and all missing functions in this namespace import os -import sys import datetime as dt from typing import ( + Literal as L, Any, Callable, - IO, Iterable, Optional, overload, @@ -16,6 +15,10 @@ from typing import ( Union, Sequence, Tuple, + SupportsIndex, + final, + Final, + Protocol, ) from numpy import ( @@ -47,6 +50,7 @@ from numpy import ( _CastingKind, _ModeKind, _SupportsBuffer, + _IOProtocol, ) from numpy.typing import ( @@ -78,15 +82,6 @@ from numpy.typing import ( _TD64Like_co, ) -from numpy.array_api import ( - _CopyMode -) - -if sys.version_info >= (3, 8): - from typing import SupportsIndex, final, Final, Literal as L -else: - from typing_extensions import SupportsIndex, final, Final, Literal as L - _SCT = TypeVar("_SCT", bound=generic) _ArrayType = TypeVar("_ArrayType", bound=NDArray[Any]) @@ -312,7 +307,8 @@ def ravel_multi_index( @overload def concatenate( # type: ignore[misc] - __arrays: _ArrayLike[_SCT], + arrays: _ArrayLike[_SCT], + /, axis: Optional[SupportsIndex] = ..., out: None = ..., *, @@ -321,7 +317,8 @@ def concatenate( # type: ignore[misc] ) -> NDArray[_SCT]: ... @overload def concatenate( # type: ignore[misc] - __arrays: ArrayLike, + arrays: ArrayLike, + /, axis: Optional[SupportsIndex] = ..., out: None = ..., *, @@ -330,7 +327,8 @@ def concatenate( # type: ignore[misc] ) -> NDArray[Any]: ... @overload def concatenate( # type: ignore[misc] - __arrays: ArrayLike, + arrays: ArrayLike, + /, axis: Optional[SupportsIndex] = ..., out: None = ..., *, @@ -339,7 +337,8 @@ def concatenate( # type: ignore[misc] ) -> NDArray[_SCT]: ... @overload def concatenate( # type: ignore[misc] - __arrays: ArrayLike, + arrays: ArrayLike, + /, axis: Optional[SupportsIndex] = ..., out: None = ..., *, @@ -348,7 +347,8 @@ def concatenate( # type: ignore[misc] ) -> NDArray[Any]: ... @overload def concatenate( - __arrays: ArrayLike, + arrays: ArrayLike, + /, axis: Optional[SupportsIndex] = ..., out: _ArrayType = ..., *, @@ -357,19 +357,22 @@ def concatenate( ) -> _ArrayType: ... def inner( - __a: ArrayLike, - __b: ArrayLike, + a: ArrayLike, + b: ArrayLike, + /, ) -> Any: ... @overload def where( - __condition: ArrayLike, + condition: ArrayLike, + /, ) -> Tuple[NDArray[intp], ...]: ... @overload def where( - __condition: ArrayLike, - __x: ArrayLike, - __y: ArrayLike, + condition: ArrayLike, + x: ArrayLike, + y: ArrayLike, + /, ) -> NDArray[Any]: ... def lexsort( @@ -384,7 +387,7 @@ def can_cast( ) -> bool: ... def min_scalar_type( - __a: ArrayLike, + a: ArrayLike, /, ) -> dtype[Any]: ... def result_type( @@ -397,24 +400,25 @@ def dot(a: ArrayLike, b: ArrayLike, out: None = ...) -> Any: ... def dot(a: ArrayLike, b: ArrayLike, out: _ArrayType) -> _ArrayType: ... @overload -def vdot(__a: _ArrayLikeBool_co, __b: _ArrayLikeBool_co) -> bool_: ... # type: ignore[misc] +def vdot(a: _ArrayLikeBool_co, b: _ArrayLikeBool_co, /) -> bool_: ... # type: ignore[misc] @overload -def vdot(__a: _ArrayLikeUInt_co, __b: _ArrayLikeUInt_co) -> unsignedinteger[Any]: ... # type: ignore[misc] +def vdot(a: _ArrayLikeUInt_co, b: _ArrayLikeUInt_co, /) -> unsignedinteger[Any]: ... # type: ignore[misc] @overload -def vdot(__a: _ArrayLikeInt_co, __b: _ArrayLikeInt_co) -> signedinteger[Any]: ... # type: ignore[misc] +def vdot(a: _ArrayLikeInt_co, b: _ArrayLikeInt_co, /) -> signedinteger[Any]: ... # type: ignore[misc] @overload -def vdot(__a: _ArrayLikeFloat_co, __b: _ArrayLikeFloat_co) -> floating[Any]: ... # type: ignore[misc] +def vdot(a: _ArrayLikeFloat_co, b: _ArrayLikeFloat_co, /) -> floating[Any]: ... # type: ignore[misc] @overload -def vdot(__a: _ArrayLikeComplex_co, __b: _ArrayLikeComplex_co) -> complexfloating[Any, Any]: ... # type: ignore[misc] +def vdot(a: _ArrayLikeComplex_co, b: _ArrayLikeComplex_co, /) -> complexfloating[Any, Any]: ... # type: ignore[misc] @overload -def vdot(__a: _ArrayLikeTD64_co, __b: _ArrayLikeTD64_co) -> timedelta64: ... +def vdot(a: _ArrayLikeTD64_co, b: _ArrayLikeTD64_co, /) -> timedelta64: ... @overload -def vdot(__a: _ArrayLikeObject_co, __b: Any) -> Any: ... +def vdot(a: _ArrayLikeObject_co, b: Any, /) -> Any: ... @overload -def vdot(__a: Any, __b: _ArrayLikeObject_co) -> Any: ... +def vdot(a: Any, b: _ArrayLikeObject_co, /) -> Any: ... def bincount( - __x: ArrayLike, + x: ArrayLike, + /, weights: Optional[ArrayLike] = ..., minlength: SupportsIndex = ..., ) -> NDArray[intp]: ... @@ -433,27 +437,31 @@ def putmask( ) -> None: ... def packbits( - __a: _ArrayLikeInt_co, + a: _ArrayLikeInt_co, + /, axis: Optional[SupportsIndex] = ..., bitorder: L["big", "little"] = ..., ) -> NDArray[uint8]: ... def unpackbits( - __a: _ArrayLike[uint8], + a: _ArrayLike[uint8], + /, axis: Optional[SupportsIndex] = ..., count: Optional[SupportsIndex] = ..., bitorder: L["big", "little"] = ..., ) -> NDArray[uint8]: ... def shares_memory( - __a: object, - __b: object, + a: object, + b: object, + /, max_work: Optional[int] = ..., ) -> bool: ... def may_share_memory( - __a: object, - __b: object, + a: object, + b: object, + /, max_work: Optional[int] = ..., ) -> bool: ... @@ -592,7 +600,7 @@ def asfortranarray( # In practice `List[Any]` is list with an int, int and a valid # `np.seterrcall()` object def geterrobj() -> List[Any]: ... -def seterrobj(__errobj: List[Any]) -> None: ... +def seterrobj(errobj: List[Any], /) -> None: ... def promote_types(__type1: DTypeLike, __type2: DTypeLike) -> dtype[Any]: ... @@ -626,7 +634,7 @@ def fromstring( ) -> NDArray[Any]: ... def frompyfunc( - __func: Callable[..., Any], + func: Callable[..., Any], /, nin: SupportsIndex, nout: SupportsIndex, *, @@ -635,7 +643,7 @@ def frompyfunc( @overload def fromfile( - file: str | bytes | os.PathLike[Any] | IO[Any], + file: str | bytes | os.PathLike[Any] | _IOProtocol, dtype: None = ..., count: SupportsIndex = ..., sep: str = ..., @@ -645,7 +653,7 @@ def fromfile( ) -> NDArray[float64]: ... @overload def fromfile( - file: str | bytes | os.PathLike[Any] | IO[Any], + file: str | bytes | os.PathLike[Any] | _IOProtocol, dtype: _DTypeLike[_SCT], count: SupportsIndex = ..., sep: str = ..., @@ -655,7 +663,7 @@ def fromfile( ) -> NDArray[_SCT]: ... @overload def fromfile( - file: str | bytes | os.PathLike[Any] | IO[Any], + file: str | bytes | os.PathLike[Any] | _IOProtocol, dtype: DTypeLike, count: SupportsIndex = ..., sep: str = ..., @@ -711,8 +719,8 @@ def frombuffer( @overload def arange( # type: ignore[misc] - __stop: _IntLike_co, - *, + stop: _IntLike_co, + /, *, dtype: None = ..., like: ArrayLike = ..., ) -> NDArray[signedinteger[Any]]: ... @@ -727,8 +735,8 @@ def arange( # type: ignore[misc] ) -> NDArray[signedinteger[Any]]: ... @overload def arange( # type: ignore[misc] - __stop: _FloatLike_co, - *, + stop: _FloatLike_co, + /, *, dtype: None = ..., like: ArrayLike = ..., ) -> NDArray[floating[Any]]: ... @@ -743,8 +751,8 @@ def arange( # type: ignore[misc] ) -> NDArray[floating[Any]]: ... @overload def arange( - __stop: _TD64Like_co, - *, + stop: _TD64Like_co, + /, *, dtype: None = ..., like: ArrayLike = ..., ) -> NDArray[timedelta64]: ... @@ -768,8 +776,8 @@ def arange( # both start and stop must always be specified for datetime64 ) -> NDArray[datetime64]: ... @overload def arange( - __stop: Any, - *, + stop: Any, + /, *, dtype: _DTypeLike[_SCT], like: ArrayLike = ..., ) -> NDArray[_SCT]: ... @@ -784,7 +792,7 @@ def arange( ) -> NDArray[_SCT]: ... @overload def arange( - __stop: Any, + stop: Any, /, *, dtype: DTypeLike, like: ArrayLike = ..., @@ -800,7 +808,7 @@ def arange( ) -> NDArray[Any]: ... def datetime_data( - __dtype: str | _DTypeLike[datetime64] | _DTypeLike[timedelta64], + dtype: str | _DTypeLike[datetime64] | _DTypeLike[timedelta64], /, ) -> Tuple[str, int]: ... # The datetime functions perform unsafe casts to `datetime64[D]`, @@ -951,7 +959,7 @@ def compare_chararrays( rstrip: bool, ) -> NDArray[bool_]: ... -def add_docstring(__obj: Callable[..., Any], __docstring: str) -> None: ... +def add_docstring(obj: Callable[..., Any], docstring: str, /) -> None: ... _GetItemKeys = L[ "C", "CONTIGUOUS", "C_CONTIGUOUS", diff --git a/numpy/core/numeric.pyi b/numpy/core/numeric.pyi index 3c2b553ec..54ab4b7c8 100644 --- a/numpy/core/numeric.pyi +++ b/numpy/core/numeric.pyi @@ -1,4 +1,3 @@ -import sys from typing import ( Any, Optional, @@ -10,16 +9,12 @@ from typing import ( overload, TypeVar, Iterable, + Literal, ) from numpy import ndarray, generic, dtype, bool_, signedinteger, _OrderKACF, _OrderCF from numpy.typing import ArrayLike, DTypeLike, _ShapeLike -if sys.version_info >= (3, 8): - from typing import Literal -else: - from typing_extensions import Literal - _T = TypeVar("_T") _ArrayType = TypeVar("_ArrayType", bound=ndarray) diff --git a/numpy/core/numerictypes.pyi b/numpy/core/numerictypes.pyi index e99e1c500..1d3ff773b 100644 --- a/numpy/core/numerictypes.pyi +++ b/numpy/core/numerictypes.pyi @@ -1,6 +1,7 @@ import sys import types from typing import ( + Literal as L, Type, Union, Tuple, @@ -10,6 +11,8 @@ from typing import ( Dict, List, Iterable, + Protocol, + TypedDict, ) from numpy import ( @@ -49,11 +52,6 @@ from numpy.core._type_aliases import ( from numpy.typing import DTypeLike, ArrayLike, _SupportsDType -if sys.version_info >= (3, 8): - from typing import Literal as L, Protocol, TypedDict -else: - from typing_extensions import Literal as L, Protocol, TypedDict - _T = TypeVar("_T") _SCT = TypeVar("_SCT", bound=generic) @@ -86,8 +84,8 @@ class _typedict(Dict[Type[generic], _T]): if sys.version_info >= (3, 10): _TypeTuple = Union[ Type[Any], - types.Union, - Tuple[Union[Type[Any], types.Union, Tuple[Any, ...]], ...], + types.UnionType, + Tuple[Union[Type[Any], types.UnionType, Tuple[Any, ...]], ...], ] else: _TypeTuple = Union[ diff --git a/numpy/core/overrides.py b/numpy/core/overrides.py index 70085d896..e1fdd06f2 100644 --- a/numpy/core/overrides.py +++ b/numpy/core/overrides.py @@ -126,18 +126,6 @@ def set_module(module): return decorator - -# Call textwrap.dedent here instead of in the function so as to avoid -# calling dedent multiple times on the same text -_wrapped_func_source = textwrap.dedent(""" - @functools.wraps(implementation) - def {name}(*args, **kwargs): - relevant_args = dispatcher(*args, **kwargs) - return implement_array_function( - implementation, {name}, relevant_args, args, kwargs) - """) - - def array_function_dispatch(dispatcher, module=None, verify=True, docs_from_dispatcher=False): """Decorator for adding dispatch with the __array_function__ protocol. @@ -187,25 +175,15 @@ def array_function_dispatch(dispatcher, module=None, verify=True, if docs_from_dispatcher: add_docstring(implementation, dispatcher.__doc__) - # Equivalently, we could define this function directly instead of using - # exec. This version has the advantage of giving the helper function a - # more interpettable name. Otherwise, the original function does not - # show up at all in many cases, e.g., if it's written in C or if the - # dispatcher gets an invalid keyword argument. - source = _wrapped_func_source.format(name=implementation.__name__) - - source_object = compile( - source, filename='<__array_function__ internals>', mode='exec') - scope = { - 'implementation': implementation, - 'dispatcher': dispatcher, - 'functools': functools, - 'implement_array_function': implement_array_function, - } - exec(source_object, scope) - - public_api = scope[implementation.__name__] + @functools.wraps(implementation) + def public_api(*args, **kwargs): + relevant_args = dispatcher(*args, **kwargs) + return implement_array_function( + implementation, public_api, relevant_args, args, kwargs) + public_api.__code__ = public_api.__code__.replace( + co_name=implementation.__name__, + co_filename='<__array_function__ internals>') if module is not None: public_api.__module__ = module diff --git a/numpy/core/records.py b/numpy/core/records.py index b3474ad01..fd5f1ab39 100644 --- a/numpy/core/records.py +++ b/numpy/core/records.py @@ -664,17 +664,17 @@ def fromarrays(arrayList, dtype=None, shape=None, formats=None, if nn > 0: shape = shape[:-nn] + _array = recarray(shape, descr) + + # populate the record array (makes a copy) for k, obj in enumerate(arrayList): nn = descr[k].ndim testshape = obj.shape[:obj.ndim - nn] + name = _names[k] if testshape != shape: - raise ValueError("array-shape mismatch in array %d" % k) + raise ValueError(f'array-shape mismatch in array {k} ("{name}")') - _array = recarray(shape, descr) - - # populate the record array (makes a copy) - for i in range(len(arrayList)): - _array[_names[i]] = arrayList[i] + _array[name] = obj return _array @@ -939,7 +939,7 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None, _array = recarray(shape, descr) nbytesread = fd.readinto(_array.data) if nbytesread != nbytes: - raise IOError("Didn't read as many bytes as expected") + raise OSError("Didn't read as many bytes as expected") return _array diff --git a/numpy/core/setup.py b/numpy/core/setup.py index c20320910..ba7d83787 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -381,9 +381,9 @@ def check_mathlib(config_cmd): mathlibs = libs break else: - raise EnvironmentError("math library missing; rerun " - "setup.py after setting the " - "MATHLIB env variable") + raise RuntimeError( + "math library missing; rerun setup.py after setting the " + "MATHLIB env variable") return mathlibs def visibility_define(config): diff --git a/numpy/core/shape_base.pyi b/numpy/core/shape_base.pyi index 9aaeceed7..d7914697d 100644 --- a/numpy/core/shape_base.pyi +++ b/numpy/core/shape_base.pyi @@ -1,14 +1,8 @@ -import sys -from typing import TypeVar, overload, List, Sequence, Any +from typing import TypeVar, overload, List, Sequence, Any, SupportsIndex from numpy import generic, dtype from numpy.typing import ArrayLike, NDArray, _NestedSequence, _SupportsArray -if sys.version_info >= (3, 8): - from typing import SupportsIndex -else: - from typing_extensions import SupportsIndex - _SCT = TypeVar("_SCT", bound=generic) _ArrayType = TypeVar("_ArrayType", bound=NDArray[Any]) @@ -17,23 +11,23 @@ _ArrayLike = _NestedSequence[_SupportsArray[dtype[_SCT]]] __all__: List[str] @overload -def atleast_1d(__arys: _ArrayLike[_SCT]) -> NDArray[_SCT]: ... +def atleast_1d(arys: _ArrayLike[_SCT], /) -> NDArray[_SCT]: ... @overload -def atleast_1d(__arys: ArrayLike) -> NDArray[Any]: ... +def atleast_1d(arys: ArrayLike, /) -> NDArray[Any]: ... @overload def atleast_1d(*arys: ArrayLike) -> List[NDArray[Any]]: ... @overload -def atleast_2d(__arys: _ArrayLike[_SCT]) -> NDArray[_SCT]: ... +def atleast_2d(arys: _ArrayLike[_SCT], /) -> NDArray[_SCT]: ... @overload -def atleast_2d(__arys: ArrayLike) -> NDArray[Any]: ... +def atleast_2d(arys: ArrayLike, /) -> NDArray[Any]: ... @overload def atleast_2d(*arys: ArrayLike) -> List[NDArray[Any]]: ... @overload -def atleast_3d(__arys: _ArrayLike[_SCT]) -> NDArray[_SCT]: ... +def atleast_3d(arys: _ArrayLike[_SCT], /) -> NDArray[_SCT]: ... @overload -def atleast_3d(__arys: ArrayLike) -> NDArray[Any]: ... +def atleast_3d(arys: ArrayLike, /) -> NDArray[Any]: ... @overload def atleast_3d(*arys: ArrayLike) -> List[NDArray[Any]]: ... diff --git a/numpy/core/src/common/npy_cpu_dispatch.h b/numpy/core/src/common/npy_cpu_dispatch.h index c8411104a..09e00badf 100644 --- a/numpy/core/src/common/npy_cpu_dispatch.h +++ b/numpy/core/src/common/npy_cpu_dispatch.h @@ -57,7 +57,7 @@ * avoid linking duplications due to the nature of the dispatch-able sources. * * Example: - * @targets baseline avx avx512_skx vsx3 asimdhp // configration statments + * @targets baseline avx avx512_skx vsx3 asimdhp // configuration statements * * void NPY_CPU_DISPATCH_CURFX(dispatch_me)(const int *src, int *dst) * { @@ -180,7 +180,7 @@ * Macro NPY_CPU_DISPATCH_DECLARE_XB(LEFT, ...) * * Same as `NPY_CPU_DISPATCH_DECLARE` but exclude the baseline declaration even - * if it was provided within the configration statments. + * if it was provided within the configuration statements. */ #define NPY_CPU_DISPATCH_DECLARE_XB(...) \ NPY__CPU_DISPATCH_CALL(NPY_CPU_DISPATCH_DECLARE_CHK_, NPY_CPU_DISPATCH_DECLARE_CB_, __VA_ARGS__) @@ -196,7 +196,7 @@ * Example: * Assume we have a dispatch-able source exporting the following function: * - * @targets baseline avx2 avx512_skx // configration statments + * @targets baseline avx2 avx512_skx // configration statements * * void NPY_CPU_DISPATCH_CURFX(dispatch_me)(const int *src, int *dst) * { @@ -238,7 +238,7 @@ * Macro NPY_CPU_DISPATCH_CALL_XB(LEFT, ...) * * Same as `NPY_CPU_DISPATCH_DECLARE` but exclude the baseline declaration even - * if it was provided within the configration statements. + * if it was provided within the configuration statements. * Returns void. */ #define NPY_CPU_DISPATCH_CALL_XB_CB_(TESTED_FEATURES, TARGET_NAME, LEFT, ...) \ diff --git a/numpy/core/src/common/simd/avx2/arithmetic.h b/numpy/core/src/common/simd/avx2/arithmetic.h index e1b170863..ad9688338 100644 --- a/numpy/core/src/common/simd/avx2/arithmetic.h +++ b/numpy/core/src/common/simd/avx2/arithmetic.h @@ -284,7 +284,7 @@ NPY_FINLINE npy_uint32 npyv_sum_u32(npyv_u32 a) { __m256i s0 = _mm256_hadd_epi32(a, a); s0 = _mm256_hadd_epi32(s0, s0); - __m128i s1 = _mm256_extracti128_si256(s0, 1);; + __m128i s1 = _mm256_extracti128_si256(s0, 1); s1 = _mm_add_epi32(_mm256_castsi256_si128(s0), s1); return _mm_cvtsi128_si32(s1); } diff --git a/numpy/core/src/multiarray/alloc.c b/numpy/core/src/multiarray/alloc.c index 887deff53..e74056736 100644 --- a/numpy/core/src/multiarray/alloc.c +++ b/numpy/core/src/multiarray/alloc.c @@ -3,11 +3,6 @@ #include "structmember.h" #include <pymem.h> -/* public api in 3.7 */ -#if PY_VERSION_HEX < 0x03070000 -#define PyTraceMalloc_Track _PyTraceMalloc_Track -#define PyTraceMalloc_Untrack _PyTraceMalloc_Untrack -#endif #define NPY_NO_DEPRECATED_API NPY_API_VERSION #define _MULTIARRAYMODULE diff --git a/numpy/core/src/multiarray/convert.c b/numpy/core/src/multiarray/convert.c index 29a2bb0e8..2ad8d6d0e 100644 --- a/numpy/core/src/multiarray/convert.c +++ b/numpy/core/src/multiarray/convert.c @@ -61,7 +61,7 @@ npy_fallocate(npy_intp nbytes, FILE * fp) * early exit on no space, other errors will also get found during fwrite */ if (r == -1 && errno == ENOSPC) { - PyErr_Format(PyExc_IOError, "Not enough free space to write " + PyErr_Format(PyExc_OSError, "Not enough free space to write " "%"NPY_INTP_FMT" bytes", nbytes); return -1; } @@ -138,7 +138,7 @@ PyArray_ToFile(PyArrayObject *self, FILE *fp, char *sep, char *format) if (n3 == 0) { /* binary data */ if (PyDataType_FLAGCHK(PyArray_DESCR(self), NPY_LIST_PICKLE)) { - PyErr_SetString(PyExc_IOError, + PyErr_SetString(PyExc_OSError, "cannot write object arrays to a file in binary mode"); return -1; } @@ -182,7 +182,7 @@ PyArray_ToFile(PyArrayObject *self, FILE *fp, char *sep, char *format) #endif NPY_END_ALLOW_THREADS; if (n < size) { - PyErr_Format(PyExc_IOError, + PyErr_Format(PyExc_OSError, "%ld requested and %ld written", (long) size, (long) n); return -1; @@ -198,7 +198,7 @@ PyArray_ToFile(PyArrayObject *self, FILE *fp, char *sep, char *format) (size_t) PyArray_DESCR(self)->elsize, 1, fp) < 1) { NPY_END_THREADS; - PyErr_Format(PyExc_IOError, + PyErr_Format(PyExc_OSError, "problem writing element %" NPY_INTP_FMT " to file", it->index); Py_DECREF(it); @@ -266,7 +266,7 @@ PyArray_ToFile(PyArrayObject *self, FILE *fp, char *sep, char *format) NPY_END_ALLOW_THREADS; Py_DECREF(byteobj); if (n < n2) { - PyErr_Format(PyExc_IOError, + PyErr_Format(PyExc_OSError, "problem writing element %" NPY_INTP_FMT " to file", it->index); Py_DECREF(strobj); @@ -276,7 +276,7 @@ PyArray_ToFile(PyArrayObject *self, FILE *fp, char *sep, char *format) /* write separator for all but last one */ if (it->index != it->size-1) { if (fwrite(sep, 1, n3, fp) < n3) { - PyErr_Format(PyExc_IOError, + PyErr_Format(PyExc_OSError, "problem writing separator to file"); Py_DECREF(strobj); Py_DECREF(it); diff --git a/numpy/core/src/multiarray/convert_datatype.c b/numpy/core/src/multiarray/convert_datatype.c index e3b25d076..45b03a6f3 100644 --- a/numpy/core/src/multiarray/convert_datatype.c +++ b/numpy/core/src/multiarray/convert_datatype.c @@ -449,7 +449,7 @@ PyArray_GetCastSafety( /** * Check whether a cast is safe, see also `PyArray_GetCastSafety` for - * a similiar function. Unlike GetCastSafety, this function checks the + * a similar function. Unlike GetCastSafety, this function checks the * `castingimpl->casting` when available. This allows for two things: * * 1. It avoids calling `resolve_descriptors` in some cases. diff --git a/numpy/core/src/multiarray/ctors.c b/numpy/core/src/multiarray/ctors.c index 1449ddcef..deab7d2a1 100644 --- a/numpy/core/src/multiarray/ctors.c +++ b/numpy/core/src/multiarray/ctors.c @@ -3340,7 +3340,7 @@ array_fromfile_binary(FILE *fp, PyArray_Descr *dtype, npy_intp num, size_t *nrea fail = 1; } if (fail) { - PyErr_SetString(PyExc_IOError, + PyErr_SetString(PyExc_OSError, "could not seek in file"); return NULL; } diff --git a/numpy/core/src/multiarray/descriptor.c b/numpy/core/src/multiarray/descriptor.c index 50964dab8..90453e38f 100644 --- a/numpy/core/src/multiarray/descriptor.c +++ b/numpy/core/src/multiarray/descriptor.c @@ -1723,22 +1723,6 @@ _convert_from_str(PyObject *obj, int align) goto fail; } - /* Check for a deprecated Numeric-style typecode */ - /* `Uint` has deliberately weird uppercasing */ - char *dep_tps[] = {"Bytes", "Datetime64", "Str", "Uint"}; - int ndep_tps = sizeof(dep_tps) / sizeof(dep_tps[0]); - for (int i = 0; i < ndep_tps; ++i) { - char *dep_tp = dep_tps[i]; - - if (strncmp(type, dep_tp, strlen(dep_tp)) == 0) { - /* Deprecated 2020-06-09, NumPy 1.20 */ - if (DEPRECATE("Numeric-style type codes are " - "deprecated and will result in " - "an error in the future.") < 0) { - goto fail; - } - } - } /* * Probably only ever dispatches to `_convert_from_type`, but who * knows what users are injecting into `np.typeDict`. diff --git a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src index e533e4932..e38873746 100644 --- a/numpy/core/src/multiarray/lowlevel_strided_loops.c.src +++ b/numpy/core/src/multiarray/lowlevel_strided_loops.c.src @@ -819,6 +819,10 @@ NPY_NO_EXPORT PyArrayMethod_StridedLoop * # define _CONVERT_FN(x) npy_floatbits_to_halfbits(x) # elif @is_double1@ # define _CONVERT_FN(x) npy_doublebits_to_halfbits(x) +# elif @is_half1@ +# define _CONVERT_FN(x) (x) +# elif @is_bool1@ +# define _CONVERT_FN(x) npy_float_to_half((float)(x!=0)) # else # define _CONVERT_FN(x) npy_float_to_half((float)x) # endif diff --git a/numpy/core/src/multiarray/multiarraymodule.c b/numpy/core/src/multiarray/multiarraymodule.c index 2ca642d76..d33c7060b 100644 --- a/numpy/core/src/multiarray/multiarraymodule.c +++ b/numpy/core/src/multiarray/multiarraymodule.c @@ -2284,7 +2284,7 @@ array_fromfile(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *keywds) return NULL; } if (npy_fseek(fp, offset, SEEK_CUR) != 0) { - PyErr_SetFromErrno(PyExc_IOError); + PyErr_SetFromErrno(PyExc_OSError); goto cleanup; } if (type == NULL) { diff --git a/numpy/core/src/multiarray/scalartypes.c.src b/numpy/core/src/multiarray/scalartypes.c.src index 40f736125..740ec8cc2 100644 --- a/numpy/core/src/multiarray/scalartypes.c.src +++ b/numpy/core/src/multiarray/scalartypes.c.src @@ -1908,6 +1908,39 @@ error: } /**end repeat**/ +/**begin repeat + * #name = half, float, double, longdouble# + * #Name = Half, Float, Double, LongDouble# + * #is_half = 1,0,0,0# + * #c = f, f, , l# + */ +static PyObject * +@name@_is_integer(PyObject *self) +{ +#if @is_half@ + npy_double val = npy_half_to_double(PyArrayScalar_VAL(self, @Name@)); +#else + npy_@name@ val = PyArrayScalar_VAL(self, @Name@); +#endif + PyObject *ret; + + if (npy_isnan(val)) { + Py_RETURN_FALSE; + } + if (!npy_isfinite(val)) { + Py_RETURN_FALSE; + } + + ret = (npy_floor@c@(val) == val) ? Py_True : Py_False; + Py_INCREF(ret); + return ret; +} +/**end repeat**/ + +static PyObject * +integer_is_integer(PyObject *self) { + Py_RETURN_TRUE; +} /* * need to fill in doc-strings for these methods on import -- copy from @@ -2167,7 +2200,7 @@ static PyMethodDef @name@type_methods[] = { /**end repeat**/ /**begin repeat - * #name = integer,floating, complexfloating# + * #name = floating, complexfloating# */ static PyMethodDef @name@type_methods[] = { /* Hook for the round() builtin */ @@ -2178,6 +2211,17 @@ static PyMethodDef @name@type_methods[] = { }; /**end repeat**/ +static PyMethodDef integertype_methods[] = { + /* Hook for the round() builtin */ + {"__round__", + (PyCFunction)integertype_dunder_round, + METH_VARARGS | METH_KEYWORDS, NULL}, + {"is_integer", + (PyCFunction)integer_is_integer, + METH_NOARGS, NULL}, + {NULL, NULL, 0, NULL} /* sentinel */ +}; + /**begin repeat * #name = half,float,double,longdouble# */ @@ -2185,6 +2229,9 @@ static PyMethodDef @name@type_methods[] = { {"as_integer_ratio", (PyCFunction)@name@_as_integer_ratio, METH_NOARGS, NULL}, + {"is_integer", + (PyCFunction)@name@_is_integer, + METH_NOARGS, NULL}, {NULL, NULL, 0, NULL} }; /**end repeat**/ diff --git a/numpy/core/src/umath/_scaled_float_dtype.c b/numpy/core/src/umath/_scaled_float_dtype.c index 599774cce..cbea378f0 100644 --- a/numpy/core/src/umath/_scaled_float_dtype.c +++ b/numpy/core/src/umath/_scaled_float_dtype.c @@ -464,9 +464,6 @@ init_casts(void) * 2. Addition, which needs to use the common instance, and runs into * cast safety subtleties since we will implement it without an additional * cast. - * - * NOTE: When first writing this, promotion did not exist for new-style loops, - * if it exists, we could use promotion to implement double * sfloat. */ static int multiply_sfloats(PyArrayMethod_Context *NPY_UNUSED(context), @@ -591,7 +588,8 @@ add_sfloats_resolve_descriptors( static int -add_loop(const char *ufunc_name, PyBoundArrayMethodObject *bmeth) +add_loop(const char *ufunc_name, + PyArray_DTypeMeta *dtypes[3], PyObject *meth_or_promoter) { PyObject *mod = PyImport_ImportModule("numpy"); if (mod == NULL) { @@ -605,13 +603,12 @@ add_loop(const char *ufunc_name, PyBoundArrayMethodObject *bmeth) "numpy.%s was not a ufunc!", ufunc_name); return -1; } - PyObject *dtype_tup = PyArray_TupleFromItems( - 3, (PyObject **)bmeth->dtypes, 0); + PyObject *dtype_tup = PyArray_TupleFromItems(3, (PyObject **)dtypes, 1); if (dtype_tup == NULL) { Py_DECREF(ufunc); return -1; } - PyObject *info = PyTuple_Pack(2, dtype_tup, bmeth->method); + PyObject *info = PyTuple_Pack(2, dtype_tup, meth_or_promoter); Py_DECREF(dtype_tup); if (info == NULL) { Py_DECREF(ufunc); @@ -624,6 +621,28 @@ add_loop(const char *ufunc_name, PyBoundArrayMethodObject *bmeth) } + +/* + * We add some very basic promoters to allow multiplying normal and scaled + */ +static int +promote_to_sfloat(PyUFuncObject *NPY_UNUSED(ufunc), + PyArray_DTypeMeta *const NPY_UNUSED(dtypes[3]), + PyArray_DTypeMeta *const signature[3], + PyArray_DTypeMeta *new_dtypes[3]) +{ + for (int i = 0; i < 3; i++) { + PyArray_DTypeMeta *new = &PyArray_SFloatDType; + if (signature[i] != NULL) { + new = signature[i]; + } + Py_INCREF(new); + new_dtypes[i] = new; + } + return 0; +} + + /* * Add new ufunc loops (this is somewhat clumsy as of writing it, but should * get less so with the introduction of public API). @@ -650,7 +669,8 @@ init_ufuncs(void) { if (bmeth == NULL) { return -1; } - int res = add_loop("multiply", bmeth); + int res = add_loop("multiply", + bmeth->dtypes, (PyObject *)bmeth->method); Py_DECREF(bmeth); if (res < 0) { return -1; @@ -667,11 +687,40 @@ init_ufuncs(void) { if (bmeth == NULL) { return -1; } - res = add_loop("add", bmeth); + res = add_loop("add", + bmeth->dtypes, (PyObject *)bmeth->method); Py_DECREF(bmeth); if (res < 0) { return -1; } + + /* + * Add a promoter for both directions of multiply with double. + */ + PyArray_DTypeMeta *double_DType = PyArray_DTypeFromTypeNum(NPY_DOUBLE); + Py_DECREF(double_DType); /* immortal anyway */ + + PyArray_DTypeMeta *promoter_dtypes[3] = { + &PyArray_SFloatDType, double_DType, NULL}; + + PyObject *promoter = PyCapsule_New( + &promote_to_sfloat, "numpy._ufunc_promoter", NULL); + if (promoter == NULL) { + return -1; + } + res = add_loop("multiply", promoter_dtypes, promoter); + if (res < 0) { + Py_DECREF(promoter); + return -1; + } + promoter_dtypes[0] = double_DType; + promoter_dtypes[1] = &PyArray_SFloatDType; + res = add_loop("multiply", promoter_dtypes, promoter); + Py_DECREF(promoter); + if (res < 0) { + return -1; + } + return 0; } diff --git a/numpy/core/src/umath/dispatching.c b/numpy/core/src/umath/dispatching.c index b1c5ccb6b..b97441b13 100644 --- a/numpy/core/src/umath/dispatching.c +++ b/numpy/core/src/umath/dispatching.c @@ -97,8 +97,9 @@ PyUFunc_AddLoop(PyUFuncObject *ufunc, PyObject *info, int ignore_duplicate) return -1; } } - if (!PyObject_TypeCheck(PyTuple_GET_ITEM(info, 1), &PyArrayMethod_Type)) { - /* Must also accept promoters in the future. */ + PyObject *meth_or_promoter = PyTuple_GET_ITEM(info, 1); + if (!PyObject_TypeCheck(meth_or_promoter, &PyArrayMethod_Type) + && !PyCapsule_IsValid(meth_or_promoter, "numpy._ufunc_promoter")) { PyErr_SetString(PyExc_TypeError, "Second argument to info must be an ArrayMethod or promoter"); return -1; @@ -354,15 +355,68 @@ resolve_implementation_info(PyUFuncObject *ufunc, * those defined by the `signature` unmodified). */ static PyObject * -call_promoter_and_recurse( - PyUFuncObject *NPY_UNUSED(ufunc), PyObject *NPY_UNUSED(promoter), - PyArray_DTypeMeta *NPY_UNUSED(op_dtypes[]), - PyArray_DTypeMeta *NPY_UNUSED(signature[]), - PyArrayObject *const NPY_UNUSED(operands[])) +call_promoter_and_recurse(PyUFuncObject *ufunc, PyObject *promoter, + PyArray_DTypeMeta *op_dtypes[], PyArray_DTypeMeta *signature[], + PyArrayObject *const operands[]) { - PyErr_SetString(PyExc_NotImplementedError, - "Internal NumPy error, promoters are not used/implemented yet."); - return NULL; + int nargs = ufunc->nargs; + PyObject *resolved_info = NULL; + + int promoter_result; + PyArray_DTypeMeta *new_op_dtypes[NPY_MAXARGS]; + + if (PyCapsule_CheckExact(promoter)) { + /* We could also go the other way and wrap up the python function... */ + promoter_function *promoter_function = PyCapsule_GetPointer(promoter, + "numpy._ufunc_promoter"); + if (promoter_function == NULL) { + return NULL; + } + promoter_result = promoter_function(ufunc, + op_dtypes, signature, new_op_dtypes); + } + else { + PyErr_SetString(PyExc_NotImplementedError, + "Calling python functions for promotion is not implemented."); + return NULL; + } + if (promoter_result < 0) { + return NULL; + } + /* + * If none of the dtypes changes, we would recurse infinitely, abort. + * (Of course it is nevertheless possible to recurse infinitely.) + */ + int dtypes_changed = 0; + for (int i = 0; i < nargs; i++) { + if (new_op_dtypes[i] != op_dtypes[i]) { + dtypes_changed = 1; + break; + } + } + if (!dtypes_changed) { + goto finish; + } + + /* + * Do a recursive call, the promotion function has to ensure that the + * new tuple is strictly more precise (thus guaranteeing eventual finishing) + */ + if (Py_EnterRecursiveCall(" during ufunc promotion.") != 0) { + goto finish; + } + /* TODO: The caching logic here may need revising: */ + resolved_info = promote_and_get_info_and_ufuncimpl(ufunc, + operands, signature, new_op_dtypes, + /* no legacy promotion */ NPY_FALSE, /* cache */ NPY_TRUE); + + Py_LeaveRecursiveCall(); + + finish: + for (int i = 0; i < nargs; i++) { + Py_XDECREF(new_op_dtypes[i]); + } + return resolved_info; } diff --git a/numpy/core/src/umath/dispatching.h b/numpy/core/src/umath/dispatching.h index b01bc79fa..8d116873c 100644 --- a/numpy/core/src/umath/dispatching.h +++ b/numpy/core/src/umath/dispatching.h @@ -7,6 +7,10 @@ #include "array_method.h" +typedef int promoter_function(PyUFuncObject *ufunc, + PyArray_DTypeMeta *op_dtypes[], PyArray_DTypeMeta *signature[], + PyArray_DTypeMeta *new_op_dtypes[]); + NPY_NO_EXPORT int PyUFunc_AddLoop(PyUFuncObject *ufunc, PyObject *info, int ignore_duplicate); diff --git a/numpy/core/src/umath/legacy_array_method.c b/numpy/core/src/umath/legacy_array_method.c index a5e123baa..4351f1d25 100644 --- a/numpy/core/src/umath/legacy_array_method.c +++ b/numpy/core/src/umath/legacy_array_method.c @@ -142,7 +142,7 @@ simple_legacy_resolve_descriptors( } } - return NPY_SAFE_CASTING; + return NPY_NO_CASTING; fail: for (int i = 0; i < nin + nout; i++) { @@ -244,7 +244,7 @@ PyArray_NewLegacyWrappingArrayMethod(PyUFuncObject *ufunc, .dtypes = signature, .flags = flags, .slots = slots, - .casting = NPY_EQUIV_CASTING, + .casting = NPY_NO_CASTING, }; PyBoundArrayMethodObject *bound_res = PyArrayMethod_FromSpec_int(&spec, 1); diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index b1afa69a7..8df439aca 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -1340,7 +1340,7 @@ TIMEDELTA_mq_m_divide(char **args, npy_intp const *dimensions, npy_intp const *s *((npy_timedelta *)op1) = NPY_DATETIME_NAT; } else { - *((npy_timedelta *)op1) = libdivide_s64_do(in1, &fast_d);; + *((npy_timedelta *)op1) = libdivide_s64_do(in1, &fast_d); } } } diff --git a/numpy/core/src/umath/loops_exponent_log.dispatch.c.src b/numpy/core/src/umath/loops_exponent_log.dispatch.c.src index b17643d23..cc0fd19bb 100644 --- a/numpy/core/src/umath/loops_exponent_log.dispatch.c.src +++ b/numpy/core/src/umath/loops_exponent_log.dispatch.c.src @@ -800,7 +800,7 @@ AVX512F_exp_DOUBLE(npy_double * op, q = _mm512_fmadd_pd(q, r, mA2); q = _mm512_fmadd_pd(q, r, mA1); q = _mm512_mul_pd(q, r); - __m512d p = _mm512_fmadd_pd(r, q, r2);; + __m512d p = _mm512_fmadd_pd(r, q, r2); p = _mm512_add_pd(r1, p); /* Get 2^(j/32) from lookup table */ diff --git a/numpy/core/src/umath/ufunc_object.c b/numpy/core/src/umath/ufunc_object.c index bed303a86..ebc6bf02a 100644 --- a/numpy/core/src/umath/ufunc_object.c +++ b/numpy/core/src/umath/ufunc_object.c @@ -4286,7 +4286,8 @@ _get_dtype(PyObject *dtype_obj) { else if (NPY_UNLIKELY(out->singleton != descr)) { /* This does not warn about `metadata`, but units is important. */ if (!PyArray_EquivTypes(out->singleton, descr)) { - PyErr_Format(PyExc_TypeError, + /* Deprecated NumPy 1.21.2 (was an accidental error in 1.21) */ + if (DEPRECATE( "The `dtype` and `signature` arguments to " "ufuncs only select the general DType and not details " "such as the byte order or time unit (with rare " @@ -4296,9 +4297,11 @@ _get_dtype(PyObject *dtype_obj) { "In rare cases where the time unit was preserved, " "either cast the inputs or provide an output array. " "In the future NumPy may transition to allow providing " - "`dtype=` to denote the outputs `dtype` as well"); - Py_DECREF(descr); - return NULL; + "`dtype=` to denote the outputs `dtype` as well. " + "(Deprecated NumPy 1.21)") < 0) { + Py_DECREF(descr); + return NULL; + } } } Py_INCREF(out); diff --git a/numpy/core/tests/test_casting_unittests.py b/numpy/core/tests/test_casting_unittests.py index 3f67f1832..a13e807e2 100644 --- a/numpy/core/tests/test_casting_unittests.py +++ b/numpy/core/tests/test_casting_unittests.py @@ -695,6 +695,13 @@ class TestCasting: expected = arr_normal.astype(dtype) except TypeError: with pytest.raises(TypeError): - arr_NULLs.astype(dtype) + arr_NULLs.astype(dtype), else: assert_array_equal(expected, arr_NULLs.astype(dtype)) + + def test_float_to_bool(self): + # test case corresponding to gh-19514 + # simple test for casting bool_ to float16 + res = np.array([0, 3, -7], dtype=np.int8).view(bool) + expected = [0, 1, 1] + assert_array_equal(res, expected) diff --git a/numpy/core/tests/test_custom_dtypes.py b/numpy/core/tests/test_custom_dtypes.py index 3ec2363b9..5eb82bc93 100644 --- a/numpy/core/tests/test_custom_dtypes.py +++ b/numpy/core/tests/test_custom_dtypes.py @@ -101,6 +101,18 @@ class TestSFloat: expected_view = a.view(np.float64) * b.view(np.float64) assert_array_equal(res.view(np.float64), expected_view) + def test_basic_multiply_promotion(self): + float_a = np.array([1., 2., 3.]) + b = self._get_array(2.) + + res1 = float_a * b + res2 = b * float_a + # one factor is one, so we get the factor of b: + assert res1.dtype == res2.dtype == b.dtype + expected_view = float_a * b.view(np.float64) + assert_array_equal(res1.view(np.float64), expected_view) + assert_array_equal(res2.view(np.float64), expected_view) + def test_basic_addition(self): a = self._get_array(2.) b = self._get_array(4.) diff --git a/numpy/core/tests/test_datetime.py b/numpy/core/tests/test_datetime.py index b4146eadf..5a490646e 100644 --- a/numpy/core/tests/test_datetime.py +++ b/numpy/core/tests/test_datetime.py @@ -152,7 +152,7 @@ class TestDateTime: expected = np.arange(size) arr = np.tile(np.datetime64('NaT'), size) assert_equal(np.argsort(arr, kind='mergesort'), expected) - + @pytest.mark.parametrize("size", [ 3, 21, 217, 1000]) def test_timedelta_nat_argsort_stability(self, size): @@ -1373,13 +1373,13 @@ class TestDateTime: assert_equal(tda / 0.5, tdc) assert_equal((tda / 0.5).dtype, np.dtype('m8[h]')) # m8 / m8 - assert_equal(tda / tdb, 6.0 / 9.0) - assert_equal(np.divide(tda, tdb), 6.0 / 9.0) - assert_equal(np.true_divide(tda, tdb), 6.0 / 9.0) - assert_equal(tdb / tda, 9.0 / 6.0) + assert_equal(tda / tdb, 6 / 9) + assert_equal(np.divide(tda, tdb), 6 / 9) + assert_equal(np.true_divide(tda, tdb), 6 / 9) + assert_equal(tdb / tda, 9 / 6) assert_equal((tda / tdb).dtype, np.dtype('f8')) - assert_equal(tda / tdd, 60.0) - assert_equal(tdd / tda, 1.0 / 60.0) + assert_equal(tda / tdd, 60) + assert_equal(tdd / tda, 1 / 60) # int / m8 assert_raises(TypeError, np.divide, 2, tdb) diff --git a/numpy/core/tests/test_deprecations.py b/numpy/core/tests/test_deprecations.py index 42e632e4a..44c76e0b8 100644 --- a/numpy/core/tests/test_deprecations.py +++ b/numpy/core/tests/test_deprecations.py @@ -314,21 +314,6 @@ class TestBinaryReprInsufficientWidthParameterForRepresentation(_DeprecationTest self.assert_deprecated(np.binary_repr, args=args, kwargs=kwargs) -class TestNumericStyleTypecodes(_DeprecationTestCase): - """ - Most numeric style typecodes were previously deprecated (and removed) - in 1.20. This also deprecates the remaining ones. - """ - # 2020-06-09, NumPy 1.20 - def test_all_dtypes(self): - deprecated_types = ['Bytes0', 'Datetime64', 'Str0'] - # Depending on intp size, either Uint32 or Uint64 is defined: - deprecated_types.append(f"U{np.dtype(np.intp).name}") - for dt in deprecated_types: - self.assert_deprecated(np.dtype, exceptions=(TypeError,), - args=(dt,)) - - class TestDTypeAttributeIsDTypeDeprecation(_DeprecationTestCase): # Deprecated 2021-01-05, NumPy 1.21 message = r".*`.dtype` attribute" @@ -1174,3 +1159,36 @@ class TestCtypesGetter(_DeprecationTestCase): ) def test_not_deprecated(self, name: str) -> None: self.assert_not_deprecated(lambda: getattr(self.ctypes, name)) + + +class TestUFuncForcedDTypeWarning(_DeprecationTestCase): + message = "The `dtype` and `signature` arguments to ufuncs only select the" + + def test_not_deprecated(self): + import pickle + # does not warn (test relies on bad pickling behaviour, simply remove + # it if the `assert int64 is not int64_2` should start failing. + int64 = np.dtype("int64") + int64_2 = pickle.loads(pickle.dumps(int64)) + assert int64 is not int64_2 + self.assert_not_deprecated(lambda: np.add(3, 4, dtype=int64_2)) + + def test_deprecation(self): + int64 = np.dtype("int64") + self.assert_deprecated(lambda: np.add(3, 5, dtype=int64.newbyteorder())) + self.assert_deprecated(lambda: np.add(3, 5, dtype="m8[ns]")) + + def test_behaviour(self): + int64 = np.dtype("int64") + arr = np.arange(10, dtype="m8[s]") + + with pytest.warns(DeprecationWarning, match=self.message): + np.add(3, 5, dtype=int64.newbyteorder()) + with pytest.warns(DeprecationWarning, match=self.message): + np.add(3, 5, dtype="m8[ns]") # previously used the "ns" + with pytest.warns(DeprecationWarning, match=self.message): + np.add(arr, arr, dtype="m8[ns]") # never preserved the "ns" + with pytest.warns(DeprecationWarning, match=self.message): + np.maximum(arr, arr, dtype="m8[ns]") # previously used the "ns" + with pytest.warns(DeprecationWarning, match=self.message): + np.maximum.reduce(arr, dtype="m8[ns]") # never preserved the "ns" diff --git a/numpy/core/tests/test_dtype.py b/numpy/core/tests/test_dtype.py index 4f52268f5..23269f01b 100644 --- a/numpy/core/tests/test_dtype.py +++ b/numpy/core/tests/test_dtype.py @@ -109,9 +109,12 @@ class TestBuiltin: operation(np.dtype(np.int32), 7) @pytest.mark.parametrize("dtype", - ['Bool', 'Complex32', 'Complex64', 'Float16', 'Float32', 'Float64', - 'Int8', 'Int16', 'Int32', 'Int64', 'Object0', 'Timedelta64', - 'UInt8', 'UInt16', 'UInt32', 'UInt64', 'Void0', + ['Bool', 'Bytes0', 'Complex32', 'Complex64', + 'Datetime64', 'Float16', 'Float32', 'Float64', + 'Int8', 'Int16', 'Int32', 'Int64', + 'Object0', 'Str0', 'Timedelta64', + 'UInt8', 'UInt16', 'Uint32', 'UInt32', + 'Uint64', 'UInt64', 'Void0', "Float128", "Complex128"]) def test_numeric_style_types_are_invalid(self, dtype): with assert_raises(TypeError): diff --git a/numpy/core/tests/test_multiarray.py b/numpy/core/tests/test_multiarray.py index 9c56df2ba..8f8043c30 100644 --- a/numpy/core/tests/test_multiarray.py +++ b/numpy/core/tests/test_multiarray.py @@ -4885,9 +4885,9 @@ class TestIO: # this should probably be supported as a file # but for now test for proper errors b = io.BytesIO() - assert_raises(IOError, np.fromfile, b, np.uint8, 80) + assert_raises(OSError, np.fromfile, b, np.uint8, 80) d = np.ones(7) - assert_raises(IOError, lambda x: x.tofile(b), d) + assert_raises(OSError, lambda x: x.tofile(b), d) def test_bool_fromstring(self): v = np.array([True, False, True, False], dtype=np.bool_) @@ -4970,12 +4970,12 @@ class TestIO: x.tofile(tmp_filename) def fail(*args, **kwargs): - raise IOError('Can not tell or seek') + raise OSError('Can not tell or seek') with io.open(tmp_filename, 'rb', buffering=0) as f: f.seek = fail f.tell = fail - assert_raises(IOError, np.fromfile, f, dtype=x.dtype) + assert_raises(OSError, np.fromfile, f, dtype=x.dtype) def test_io_open_unbuffered_fromfile(self, x, tmp_filename): # gh-6632 @@ -5284,12 +5284,12 @@ class TestIO: def test_tofile_cleanup(self, tmp_filename): x = np.zeros((10), dtype=object) with open(tmp_filename, 'wb') as f: - assert_raises(IOError, lambda: x.tofile(f, sep='')) + assert_raises(OSError, lambda: x.tofile(f, sep='')) # Dup-ed file handle should be closed or remove will fail on Windows OS os.remove(tmp_filename) # Also make sure that we close the Python handle - assert_raises(IOError, lambda: x.tofile(tmp_filename)) + assert_raises(OSError, lambda: x.tofile(tmp_filename)) os.remove(tmp_filename) def test_fromfile_subarray_binary(self, tmp_filename): diff --git a/numpy/core/tests/test_numeric.py b/numpy/core/tests/test_numeric.py index e2d648a3c..19de0a8aa 100644 --- a/numpy/core/tests/test_numeric.py +++ b/numpy/core/tests/test_numeric.py @@ -2381,7 +2381,7 @@ class TestClip: shape=in_shapes[1], elements={"allow_nan": False})) # Then calculate our result and expected result and check that they're - # equal! See gh-12519 and gh-19457 for discussion deciding on this + # equal! See gh-12519 and gh-19457 for discussion deciding on this # property and the result_type argument. result = np.clip(arr, amin, amax) t = np.result_type(arr, amin, amax) @@ -2637,15 +2637,15 @@ class TestStdVar: def test_ddof1(self): assert_almost_equal(np.var(self.A, ddof=1), - self.real_var*len(self.A)/float(len(self.A)-1)) + self.real_var * len(self.A) / (len(self.A) - 1)) assert_almost_equal(np.std(self.A, ddof=1)**2, - self.real_var*len(self.A)/float(len(self.A)-1)) + self.real_var*len(self.A) / (len(self.A) - 1)) def test_ddof2(self): assert_almost_equal(np.var(self.A, ddof=2), - self.real_var*len(self.A)/float(len(self.A)-2)) + self.real_var * len(self.A) / (len(self.A) - 2)) assert_almost_equal(np.std(self.A, ddof=2)**2, - self.real_var*len(self.A)/float(len(self.A)-2)) + self.real_var * len(self.A) / (len(self.A) - 2)) def test_out_scalar(self): d = np.arange(10) diff --git a/numpy/core/tests/test_scalar_methods.py b/numpy/core/tests/test_scalar_methods.py index 3693bba59..94b2dd3c9 100644 --- a/numpy/core/tests/test_scalar_methods.py +++ b/numpy/core/tests/test_scalar_methods.py @@ -102,3 +102,29 @@ class TestAsIntegerRatio: pytest.skip("longdouble too small on this platform") assert_equal(nf / df, f, "{}/{}".format(n, d)) + + +class TestIsInteger: + @pytest.mark.parametrize("str_value", ["inf", "nan"]) + @pytest.mark.parametrize("code", np.typecodes["Float"]) + def test_special(self, code: str, str_value: str) -> None: + cls = np.dtype(code).type + value = cls(str_value) + assert not value.is_integer() + + @pytest.mark.parametrize( + "code", np.typecodes["Float"] + np.typecodes["AllInteger"] + ) + def test_true(self, code: str) -> None: + float_array = np.arange(-5, 5).astype(code) + for value in float_array: + assert value.is_integer() + + @pytest.mark.parametrize("code", np.typecodes["Float"]) + def test_false(self, code: str) -> None: + float_array = np.arange(-5, 5).astype(code) + float_array *= 1.1 + for value in float_array: + if value == 0: + continue + assert not value.is_integer() diff --git a/numpy/core/tests/test_simd.py b/numpy/core/tests/test_simd.py index ea5bbe103..f0c60953b 100644 --- a/numpy/core/tests/test_simd.py +++ b/numpy/core/tests/test_simd.py @@ -850,7 +850,7 @@ class _SIMD_ALL(_Test_Utility): return safe_neg = lambda x: -x-1 if -x > int_max else -x - # test round divison for signed integers + # test round division for signed integers for x, d in itertools.product(rdata, divisors): d_neg = safe_neg(d) data = self._data(x) diff --git a/numpy/core/tests/test_ufunc.py b/numpy/core/tests/test_ufunc.py index dab11d948..c3ea10d93 100644 --- a/numpy/core/tests/test_ufunc.py +++ b/numpy/core/tests/test_ufunc.py @@ -388,6 +388,24 @@ class TestUfunc: assert_equal(ixs, (0, 0, 0, 1, 2)) assert_equal(flags, (self.can_ignore, self.size_inferred, 0)) assert_equal(sizes, (3, -1, 9)) + + def test_signature9(self): + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 1, 1, "( 3) -> ( )") + assert_equal(enabled, 1) + assert_equal(num_dims, (1, 0)) + assert_equal(ixs, (0,)) + assert_equal(flags, (0,)) + assert_equal(sizes, (3,)) + + def test_signature10(self): + enabled, num_dims, ixs, flags, sizes = umt.test_signature( + 3, 1, "( 3? ) , (3? , 3?) ,(n )-> ( 9)") + assert_equal(enabled, 1) + assert_equal(num_dims, (1, 2, 1, 1)) + assert_equal(ixs, (0, 0, 0, 1, 2)) + assert_equal(flags, (self.can_ignore, self.size_inferred, 0)) + assert_equal(sizes, (3, -1, 9)) def test_signature_failure_extra_parenthesis(self): with assert_raises(ValueError): @@ -518,26 +536,36 @@ class TestUfunc: np.add(arr, arr, dtype="m") np.maximum(arr, arr, dtype="m") - def test_forced_dtype_warning(self): - # does not warn (test relies on bad pickling behaviour, simply remove - # it if the `assert int64 is not int64_2` should start failing. - int64 = np.dtype("int64") - int64_2 = pickle.loads(pickle.dumps(int64)) - assert int64 is not int64_2 - np.add(3, 4, dtype=int64_2) + @pytest.mark.parametrize("ufunc", [np.add, np.sqrt]) + def test_cast_safety(self, ufunc): + """Basic test for the safest casts, because ufuncs inner loops can + indicate a cast-safety as well (which is normally always "no"). + """ + def call_ufunc(arr, **kwargs): + return ufunc(*(arr,) * ufunc.nin, **kwargs) + + arr = np.array([1., 2., 3.], dtype=np.float32) + arr_bs = arr.astype(arr.dtype.newbyteorder()) + expected = call_ufunc(arr) + # Normally, a "no" cast: + res = call_ufunc(arr, casting="no") + assert_array_equal(expected, res) + # Byte-swapping is not allowed with "no" though: + with pytest.raises(TypeError): + call_ufunc(arr_bs, casting="no") - arr = np.arange(10, dtype="m8[s]") - msg = "The `dtype` and `signature` arguments to ufuncs only select the" - with pytest.raises(TypeError, match=msg): - np.add(3, 5, dtype=int64.newbyteorder()) - with pytest.raises(TypeError, match=msg): - np.add(3, 5, dtype="m8[ns]") # previously used the "ns" - with pytest.raises(TypeError, match=msg): - np.add(arr, arr, dtype="m8[ns]") # never preserved the "ns" - with pytest.raises(TypeError, match=msg): - np.maximum(arr, arr, dtype="m8[ns]") # previously used the "ns" - with pytest.raises(TypeError, match=msg): - np.maximum.reduce(arr, dtype="m8[ns]") # never preserved the "ns" + # But is allowed with "equiv": + res = call_ufunc(arr_bs, casting="equiv") + assert_array_equal(expected, res) + + # Casting to float64 is safe, but not equiv: + with pytest.raises(TypeError): + call_ufunc(arr_bs, dtype=np.float64, casting="equiv") + + # but it is safe cast: + res = call_ufunc(arr_bs, dtype=np.float64, casting="safe") + expected = call_ufunc(arr.astype(np.float64)) # upcast + assert_array_equal(expected, res) def test_true_divide(self): a = np.array(10) @@ -2049,6 +2077,27 @@ class TestUfunc: assert_raises(TypeError, f, a, b) assert_raises(TypeError, f, c, a) + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or]) # logical_xor object loop is bad + @pytest.mark.parametrize("signature", + [(None, None, object), (object, None, None), + (None, object, None)]) + def test_logical_ufuncs_object_signatures(self, ufunc, signature): + a = np.array([True, None, False], dtype=object) + res = ufunc(a, a, signature=signature) + assert res.dtype == object + + @pytest.mark.parametrize("ufunc", + [np.logical_and, np.logical_or, np.logical_xor]) + @pytest.mark.parametrize("signature", + [(bool, None, object), (object, None, bool), + (None, object, bool)]) + def test_logical_ufuncs_mixed_object_signatures(self, ufunc, signature): + # Most mixed signatures fail (except those with bool out, e.g. `OO->?`) + a = np.array([True, None, False]) + with pytest.raises(TypeError): + ufunc(a, a, signature=signature) + def test_reduce_noncontig_output(self): # Check that reduction deals with non-contiguous output arrays # appropriately. diff --git a/numpy/core/tests/test_umath_complex.py b/numpy/core/tests/test_umath_complex.py index c051cd61b..af5bbe59e 100644 --- a/numpy/core/tests/test_umath_complex.py +++ b/numpy/core/tests/test_umath_complex.py @@ -134,8 +134,7 @@ class TestClog: x = np.array([1+0j, 1+2j]) y_r = np.log(np.abs(x)) + 1j * np.angle(x) y = np.log(x) - for i in range(len(x)): - assert_almost_equal(y[i], y_r[i]) + assert_almost_equal(y, y_r) @platform_skip @pytest.mark.skipif(platform.machine() == "armv5tel", reason="See gh-413.") @@ -365,18 +364,24 @@ class TestCpow: x = np.array([1+1j, 0+2j, 1+2j, np.inf, np.nan]) y_r = x ** 2 y = np.power(x, 2) - for i in range(len(x)): - assert_almost_equal(y[i], y_r[i]) + assert_almost_equal(y, y_r) def test_scalar(self): x = np.array([1, 1j, 2, 2.5+.37j, np.inf, np.nan]) y = np.array([1, 1j, -0.5+1.5j, -0.5+1.5j, 2, 3]) lx = list(range(len(x))) - # Compute the values for complex type in python - p_r = [complex(x[i]) ** complex(y[i]) for i in lx] - # Substitute a result allowed by C99 standard - p_r[4] = complex(np.inf, np.nan) - # Do the same with numpy complex scalars + + # Hardcode the expected `builtins.complex` values, + # as complex exponentiation is broken as of bpo-44698 + p_r = [ + 1+0j, + 0.20787957635076193+0j, + 0.35812203996480685+0.6097119028618724j, + 0.12659112128185032+0.48847676699581527j, + complex(np.inf, np.nan), + complex(np.nan, np.nan), + ] + n_r = [x[i] ** y[i] for i in lx] for i in lx: assert_almost_equal(n_r[i], p_r[i], err_msg='Loop %d\n' % i) @@ -385,11 +390,18 @@ class TestCpow: x = np.array([1, 1j, 2, 2.5+.37j, np.inf, np.nan]) y = np.array([1, 1j, -0.5+1.5j, -0.5+1.5j, 2, 3]) lx = list(range(len(x))) - # Compute the values for complex type in python - p_r = [complex(x[i]) ** complex(y[i]) for i in lx] - # Substitute a result allowed by C99 standard - p_r[4] = complex(np.inf, np.nan) - # Do the same with numpy arrays + + # Hardcode the expected `builtins.complex` values, + # as complex exponentiation is broken as of bpo-44698 + p_r = [ + 1+0j, + 0.20787957635076193+0j, + 0.35812203996480685+0.6097119028618724j, + 0.12659112128185032+0.48847676699581527j, + complex(np.inf, np.nan), + complex(np.nan, np.nan), + ] + n_r = x ** y for i in lx: assert_almost_equal(n_r[i], p_r[i], err_msg='Loop %d\n' % i) @@ -405,8 +417,7 @@ class TestCabs: x = np.array([1+1j, 0+2j, 1+2j, np.inf, np.nan]) y_r = np.array([np.sqrt(2.), 2, np.sqrt(5), np.inf, np.nan]) y = np.abs(x) - for i in range(len(x)): - assert_almost_equal(y[i], y_r[i]) + assert_almost_equal(y, y_r) def test_fabs(self): # Test that np.abs(x +- 0j) == np.abs(x) (as mandated by C99 for cabs) @@ -452,9 +463,10 @@ class TestCabs: return np.abs(complex(a, b)) xa = np.array(x, dtype=complex) - for i in range(len(xa)): - ref = g(x[i], y[i]) - check_real_value(f, x[i], y[i], ref) + assert len(xa) == len(x) == len(y) + for xi, yi in zip(x, y): + ref = g(xi, yi) + check_real_value(f, xi, yi, ref) class TestCarg: def test_simple(self): @@ -583,7 +595,7 @@ class TestComplexAbsoluteMixedDTypes: @pytest.mark.parametrize("stride", [-4,-3,-2,-1,1,2,3,4]) @pytest.mark.parametrize("astype", [np.complex64, np.complex128]) @pytest.mark.parametrize("func", ['abs', 'square', 'conjugate']) - + def test_array(self, stride, astype, func): dtype = [('template_id', '<i8'), ('bank_chisq','<f4'), ('bank_chisq_dof','<i8'), ('chisq', '<f4'), ('chisq_dof','<i8'), @@ -602,9 +614,9 @@ class TestComplexAbsoluteMixedDTypes: myfunc = getattr(np, func) a = vec['mycomplex'] g = myfunc(a[::stride]) - + b = vec['mycomplex'].copy() h = myfunc(b[::stride]) - + assert_array_max_ulp(h.real, g.real, 1) assert_array_max_ulp(h.imag, g.imag, 1) |
