diff options
Diffstat (limited to 'numpy')
| -rw-r--r-- | numpy/__init__.py | 9 | ||||
| -rw-r--r-- | numpy/core/fromnumeric.py | 3 | ||||
| -rw-r--r-- | numpy/core/include/numpy/npy_math.h | 185 | ||||
| -rw-r--r-- | numpy/core/setup.py | 36 | ||||
| -rw-r--r-- | numpy/core/setup_common.py | 55 | ||||
| -rw-r--r-- | numpy/core/src/multiarray/nditer_constr.c | 96 | ||||
| -rw-r--r-- | numpy/core/src/npymath/ieee754.cpp | 12 | ||||
| -rw-r--r-- | numpy/core/src/npymath/npy_math_internal.h.src | 53 | ||||
| -rw-r--r-- | numpy/core/src/umath/loops.c.src | 12 | ||||
| -rw-r--r-- | numpy/core/tests/test_nditer.py | 29 | ||||
| -rw-r--r-- | numpy/lib/function_base.py | 10 | ||||
| -rw-r--r-- | numpy/lib/recfunctions.py | 2 | ||||
| -rw-r--r-- | numpy/lib/tests/test_function_base.py | 11 | ||||
| -rw-r--r-- | numpy/lib/tests/test_recfunctions.py | 9 |
14 files changed, 258 insertions, 264 deletions
diff --git a/numpy/__init__.py b/numpy/__init__.py index 3260046d6..22c90677e 100644 --- a/numpy/__init__.py +++ b/numpy/__init__.py @@ -85,10 +85,11 @@ __version__ Viewing documentation using IPython ----------------------------------- -Start IPython with the NumPy profile (``ipython -p numpy``), which will -import `numpy` under the alias ``np``. Then, use the ``cpaste`` command to -paste examples into the shell. To see which functions are available in -`numpy`, type ``np.<TAB>`` (where ``<TAB>`` refers to the TAB key), or use + +Start IPython and import `numpy` usually under the alias ``np``: `import +numpy as np`. Then, directly past or use the ``%cpaste`` magic to paste +examples into the shell. To see which functions are available in `numpy`, +type ``np.<TAB>`` (where ``<TAB>`` refers to the TAB key), or use ``np.*cos*?<ENTER>`` (where ``<ENTER>`` refers to the ENTER key) to narrow down the list. To view the docstring for a function, use ``np.cos?<ENTER>`` (to view the docstring) and ``np.cos??<ENTER>`` (to view diff --git a/numpy/core/fromnumeric.py b/numpy/core/fromnumeric.py index 89d731e32..ca9d55cb7 100644 --- a/numpy/core/fromnumeric.py +++ b/numpy/core/fromnumeric.py @@ -3274,12 +3274,13 @@ def around(a, decimals=0, out=None): See Also -------- ndarray.round : equivalent method - ceil, fix, floor, rint, trunc Notes ----- + `~numpy.round` is often used as an alias for `~numpy.around`. + For values exactly halfway between rounded decimal values, NumPy rounds to the nearest even value. Thus 1.5 and 2.5 round to 2.0, -0.5 and 0.5 round to 0.0, etc. diff --git a/numpy/core/include/numpy/npy_math.h b/numpy/core/include/numpy/npy_math.h index 6a86e25a8..27e1ddad0 100644 --- a/numpy/core/include/numpy/npy_math.h +++ b/numpy/core/include/numpy/npy_math.h @@ -159,48 +159,46 @@ NPY_INPLACE uint8_t npy_popcountl(npy_long a); NPY_INPLACE uint8_t npy_popcountll(npy_longlong a); /* - * C99 double math funcs + * C99 double math funcs that need fixups or are blocklist-able */ NPY_INPLACE double npy_sin(double x); NPY_INPLACE double npy_cos(double x); NPY_INPLACE double npy_tan(double x); -NPY_INPLACE double npy_sinh(double x); -NPY_INPLACE double npy_cosh(double x); -NPY_INPLACE double npy_tanh(double x); - -NPY_INPLACE double npy_asin(double x); -NPY_INPLACE double npy_acos(double x); -NPY_INPLACE double npy_atan(double x); - -NPY_INPLACE double npy_log(double x); -NPY_INPLACE double npy_log10(double x); -NPY_INPLACE double npy_exp(double x); -NPY_INPLACE double npy_sqrt(double x); -NPY_INPLACE double npy_cbrt(double x); - -NPY_INPLACE double npy_fabs(double x); -NPY_INPLACE double npy_ceil(double x); -NPY_INPLACE double npy_fmod(double x, double y); -NPY_INPLACE double npy_floor(double x); - -NPY_INPLACE double npy_expm1(double x); -NPY_INPLACE double npy_log1p(double x); NPY_INPLACE double npy_hypot(double x, double y); -NPY_INPLACE double npy_acosh(double x); -NPY_INPLACE double npy_asinh(double xx); -NPY_INPLACE double npy_atanh(double x); -NPY_INPLACE double npy_rint(double x); -NPY_INPLACE double npy_trunc(double x); -NPY_INPLACE double npy_exp2(double x); NPY_INPLACE double npy_log2(double x); - NPY_INPLACE double npy_atan2(double x, double y); -NPY_INPLACE double npy_pow(double x, double y); -NPY_INPLACE double npy_modf(double x, double* y); -NPY_INPLACE double npy_frexp(double x, int* y); -NPY_INPLACE double npy_ldexp(double n, int y); -NPY_INPLACE double npy_copysign(double x, double y); +/* Mandatory C99 double math funcs, no blocklisting or fixups */ +/* defined for legacy reasons, should be deprecated at some point */ +#define npy_sinh sinh +#define npy_cosh cosh +#define npy_tanh tanh +#define npy_asin asin +#define npy_acos acos +#define npy_atan atan +#define npy_log log +#define npy_log10 log10 +#define npy_cbrt cbrt +#define npy_fabs fabs +#define npy_ceil ceil +#define npy_fmod fmod +#define npy_floor floor +#define npy_expm1 expm1 +#define npy_log1p log1p +#define npy_acosh acosh +#define npy_asinh asinh +#define npy_atanh atanh +#define npy_rint rint +#define npy_trunc trunc +#define npy_exp2 exp2 +#define npy_frexp frexp +#define npy_ldexp ldexp +#define npy_copysign copysign +#define npy_exp exp +#define npy_sqrt sqrt +#define npy_pow pow +#define npy_modf modf + double npy_nextafter(double x, double y); double npy_spacing(double x); @@ -260,88 +258,91 @@ double npy_spacing(double x); #endif /* - * float C99 math functions + * float C99 math funcs that need fixups or are blocklist-able */ NPY_INPLACE float npy_sinf(float x); NPY_INPLACE float npy_cosf(float x); NPY_INPLACE float npy_tanf(float x); -NPY_INPLACE float npy_sinhf(float x); -NPY_INPLACE float npy_coshf(float x); -NPY_INPLACE float npy_tanhf(float x); -NPY_INPLACE float npy_fabsf(float x); -NPY_INPLACE float npy_floorf(float x); -NPY_INPLACE float npy_ceilf(float x); -NPY_INPLACE float npy_rintf(float x); -NPY_INPLACE float npy_truncf(float x); -NPY_INPLACE float npy_sqrtf(float x); -NPY_INPLACE float npy_cbrtf(float x); -NPY_INPLACE float npy_log10f(float x); -NPY_INPLACE float npy_logf(float x); NPY_INPLACE float npy_expf(float x); -NPY_INPLACE float npy_expm1f(float x); -NPY_INPLACE float npy_asinf(float x); -NPY_INPLACE float npy_acosf(float x); -NPY_INPLACE float npy_atanf(float x); -NPY_INPLACE float npy_asinhf(float x); -NPY_INPLACE float npy_acoshf(float x); -NPY_INPLACE float npy_atanhf(float x); -NPY_INPLACE float npy_log1pf(float x); -NPY_INPLACE float npy_exp2f(float x); +NPY_INPLACE float npy_sqrtf(float x); +NPY_INPLACE float npy_hypotf(float x, float y); NPY_INPLACE float npy_log2f(float x); - NPY_INPLACE float npy_atan2f(float x, float y); -NPY_INPLACE float npy_hypotf(float x, float y); NPY_INPLACE float npy_powf(float x, float y); -NPY_INPLACE float npy_fmodf(float x, float y); - NPY_INPLACE float npy_modff(float x, float* y); -NPY_INPLACE float npy_frexpf(float x, int* y); -NPY_INPLACE float npy_ldexpf(float x, int y); -NPY_INPLACE float npy_copysignf(float x, float y); +/* Mandatory C99 float math funcs, no blocklisting or fixups */ +/* defined for legacy reasons, should be deprecated at some point */ + +#define npy_sinhf sinhf +#define npy_coshf coshf +#define npy_tanhf tanhf +#define npy_asinf asinf +#define npy_acosf acosf +#define npy_atanf atanf +#define npy_logf logf +#define npy_log10f log10f +#define npy_cbrtf cbrtf +#define npy_fabsf fabsf +#define npy_ceilf ceilf +#define npy_fmodf fmodf +#define npy_floorf floorf +#define npy_expm1f expm1f +#define npy_log1pf log1pf +#define npy_asinhf asinhf +#define npy_acoshf acoshf +#define npy_atanhf atanhf +#define npy_rintf rintf +#define npy_truncf truncf +#define npy_exp2f exp2f +#define npy_frexpf frexpf +#define npy_ldexpf ldexpf +#define npy_copysignf copysignf + float npy_nextafterf(float x, float y); float npy_spacingf(float x); /* - * long double C99 math functions + * long double C99 double math funcs that need fixups or are blocklist-able */ NPY_INPLACE npy_longdouble npy_sinl(npy_longdouble x); NPY_INPLACE npy_longdouble npy_cosl(npy_longdouble x); NPY_INPLACE npy_longdouble npy_tanl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_sinhl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_coshl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_tanhl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_fabsl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_floorl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_ceill(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_rintl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_truncl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_sqrtl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_cbrtl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_log10l(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_logl(npy_longdouble x); NPY_INPLACE npy_longdouble npy_expl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_expm1l(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_asinl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_acosl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_atanl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_asinhl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_acoshl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_atanhl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_log1pl(npy_longdouble x); -NPY_INPLACE npy_longdouble npy_exp2l(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_sqrtl(npy_longdouble x); +NPY_INPLACE npy_longdouble npy_hypotl(npy_longdouble x, npy_longdouble y); NPY_INPLACE npy_longdouble npy_log2l(npy_longdouble x); - NPY_INPLACE npy_longdouble npy_atan2l(npy_longdouble x, npy_longdouble y); -NPY_INPLACE npy_longdouble npy_hypotl(npy_longdouble x, npy_longdouble y); NPY_INPLACE npy_longdouble npy_powl(npy_longdouble x, npy_longdouble y); -NPY_INPLACE npy_longdouble npy_fmodl(npy_longdouble x, npy_longdouble y); - NPY_INPLACE npy_longdouble npy_modfl(npy_longdouble x, npy_longdouble* y); -NPY_INPLACE npy_longdouble npy_frexpl(npy_longdouble x, int* y); -NPY_INPLACE npy_longdouble npy_ldexpl(npy_longdouble x, int y); -NPY_INPLACE npy_longdouble npy_copysignl(npy_longdouble x, npy_longdouble y); +/* Mandatory C99 double math funcs, no blocklisting or fixups */ +/* defined for legacy reasons, should be deprecated at some point */ +#define npy_sinhl sinhl +#define npy_coshl coshl +#define npy_tanhl tanhl +#define npy_fabsl fabsl +#define npy_floorl floorl +#define npy_ceill ceill +#define npy_rintl rintl +#define npy_truncl truncl +#define npy_cbrtl cbrtl +#define npy_log10l log10l +#define npy_logl logl +#define npy_expm1l expm1l +#define npy_asinl asinl +#define npy_acosl acosl +#define npy_atanl atanl +#define npy_asinhl asinhl +#define npy_acoshl acoshl +#define npy_atanhl atanhl +#define npy_log1pl log1pl +#define npy_exp2l exp2l +#define npy_fmodl fmodl +#define npy_frexpl frexpl +#define npy_ldexpl ldexpl +#define npy_copysignl copysignl + npy_longdouble npy_nextafterl(npy_longdouble x, npy_longdouble y); npy_longdouble npy_spacingl(npy_longdouble x); diff --git a/numpy/core/setup.py b/numpy/core/setup.py index 17dc8438e..10b8c093e 100644 --- a/numpy/core/setup.py +++ b/numpy/core/setup.py @@ -177,6 +177,16 @@ def check_math_capabilities(config, ext, moredefs, mathlibs): else: return 1 + # GH-14787: Work around GCC<8.4 bug when compiling with AVX512 + # support on Windows-based platforms + def check_gh14787(fn): + if fn == 'attribute_target_avx512f': + if (sys.platform in ('win32', 'cygwin') and + config.check_compiler_gcc() and + not config.check_gcc_version_at_least(8, 4)): + ext.extra_compile_args.extend( + ['-ffixed-xmm%s' % n for n in range(16, 32)]) + #use_msvc = config.check_decl("_MSC_VER") if not check_funcs_once(MANDATORY_FUNCS, add_to_moredefs=False): raise SystemError("One of the required function to build numpy is not" @@ -227,19 +237,19 @@ def check_math_capabilities(config, ext, moredefs, mathlibs): for dec, fn in OPTIONAL_FUNCTION_ATTRIBUTES: if config.check_gcc_function_attribute(dec, fn): moredefs.append((fname2def(fn), 1)) - if fn == 'attribute_target_avx512f': - # GH-14787: Work around GCC<8.4 bug when compiling with AVX512 - # support on Windows-based platforms - if (sys.platform in ('win32', 'cygwin') and - config.check_compiler_gcc() and - not config.check_gcc_version_at_least(8, 4)): - ext.extra_compile_args.extend( - ['-ffixed-xmm%s' % n for n in range(16, 32)]) - - for dec, fn, code, header in OPTIONAL_FUNCTION_ATTRIBUTES_WITH_INTRINSICS: - if config.check_gcc_function_attribute_with_intrinsics(dec, fn, code, - header): - moredefs.append((fname2def(fn), 1)) + check_gh14787(fn) + + platform = sysconfig.get_platform() + if ("x86_64" in platform): + for dec, fn in OPTIONAL_FUNCTION_ATTRIBUTES_AVX: + if config.check_gcc_function_attribute(dec, fn): + moredefs.append((fname2def(fn), 1)) + check_gh14787(fn) + for dec, fn, code, header in ( + OPTIONAL_FUNCTION_ATTRIBUTES_WITH_INTRINSICS_AVX): + if config.check_gcc_function_attribute_with_intrinsics( + dec, fn, code, header): + moredefs.append((fname2def(fn), 1)) for fn in OPTIONAL_VARIABLE_ATTRIBUTES: if config.check_gcc_variable_attribute(fn): diff --git a/numpy/core/setup_common.py b/numpy/core/setup_common.py index a8497fe75..085c0baf5 100644 --- a/numpy/core/setup_common.py +++ b/numpy/core/setup_common.py @@ -122,6 +122,8 @@ for file in [ set_sig(line) # Mandatory functions: if not found, fail the build +# Some of these can still be blocklisted if the C99 implementation +# is buggy, see numpy/core/src/common/npy_config.h MANDATORY_FUNCS = [ "sin", "cos", "tan", "sinh", "cosh", "tanh", "fabs", "floor", "ceil", "sqrt", "log10", "log", "exp", "asin", @@ -209,16 +211,18 @@ OPTIONAL_FUNCTION_ATTRIBUTES = [('__attribute__((optimize("unroll-loops")))', 'attribute_optimize_opt_2'), ('__attribute__((nonnull (1)))', 'attribute_nonnull'), - ('__attribute__((target ("avx")))', - 'attribute_target_avx'), - ('__attribute__((target ("avx2")))', - 'attribute_target_avx2'), - ('__attribute__((target ("avx512f")))', - 'attribute_target_avx512f'), - ('__attribute__((target ("avx512f,avx512dq,avx512bw,avx512vl,avx512cd")))', - 'attribute_target_avx512_skx'), ] +OPTIONAL_FUNCTION_ATTRIBUTES_AVX = [('__attribute__((target ("avx")))', + 'attribute_target_avx'), + ('__attribute__((target ("avx2")))', + 'attribute_target_avx2'), + ('__attribute__((target ("avx512f")))', + 'attribute_target_avx512f'), + ('__attribute__((target ("avx512f,avx512dq,avx512bw,avx512vl,avx512cd")))', + 'attribute_target_avx512_skx'), + ] + # function attributes with intrinsics # To ensure your compiler can compile avx intrinsics with just the attributes # gcc 4.8.4 support attributes but not with intrisics @@ -227,23 +231,24 @@ OPTIONAL_FUNCTION_ATTRIBUTES = [('__attribute__((optimize("unroll-loops")))', # The _mm512_castps_si512 instruction is specific check for AVX-512F support # in gcc-4.9 which is missing a subset of intrinsics. See # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61878 -OPTIONAL_FUNCTION_ATTRIBUTES_WITH_INTRINSICS = [('__attribute__((target("avx2,fma")))', - 'attribute_target_avx2_with_intrinsics', - '__m256 temp = _mm256_set1_ps(1.0); temp = \ - _mm256_fmadd_ps(temp, temp, temp)', - 'immintrin.h'), - ('__attribute__((target("avx512f")))', - 'attribute_target_avx512f_with_intrinsics', - '__m512i temp = _mm512_castps_si512(_mm512_set1_ps(1.0))', - 'immintrin.h'), - ('__attribute__((target ("avx512f,avx512dq,avx512bw,avx512vl,avx512cd")))', - 'attribute_target_avx512_skx_with_intrinsics', - '__mmask8 temp = _mm512_fpclass_pd_mask(_mm512_set1_pd(1.0), 0x01);\ - __m512i unused_temp = \ - _mm512_castps_si512(_mm512_set1_ps(1.0));\ - _mm_mask_storeu_epi8(NULL, 0xFF, _mm_broadcastmb_epi64(temp))', - 'immintrin.h'), - ] +OPTIONAL_FUNCTION_ATTRIBUTES_WITH_INTRINSICS_AVX = [ + ('__attribute__((target("avx2,fma")))', + 'attribute_target_avx2_with_intrinsics', + '__m256 temp = _mm256_set1_ps(1.0); temp = \ + _mm256_fmadd_ps(temp, temp, temp)', + 'immintrin.h'), + ('__attribute__((target("avx512f")))', + 'attribute_target_avx512f_with_intrinsics', + '__m512i temp = _mm512_castps_si512(_mm512_set1_ps(1.0))', + 'immintrin.h'), + ('__attribute__((target ("avx512f,avx512dq,avx512bw,avx512vl,avx512cd")))', + 'attribute_target_avx512_skx_with_intrinsics', + '__mmask8 temp = _mm512_fpclass_pd_mask(_mm512_set1_pd(1.0), 0x01);\ + __m512i unused_temp = \ + _mm512_castps_si512(_mm512_set1_ps(1.0));\ + _mm_mask_storeu_epi8(NULL, 0xFF, _mm_broadcastmb_epi64(temp))', + 'immintrin.h'), + ] def fname2def(name): return "HAVE_%s" % name.upper() diff --git a/numpy/core/src/multiarray/nditer_constr.c b/numpy/core/src/multiarray/nditer_constr.c index 9134e9f04..93d2bc961 100644 --- a/numpy/core/src/multiarray/nditer_constr.c +++ b/numpy/core/src/multiarray/nditer_constr.c @@ -1394,9 +1394,9 @@ check_mask_for_writemasked_reduction(NpyIter *iter, int iop) static int npyiter_check_reduce_ok_and_set_flags( NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itflags, - int dim) { + int iop, int maskop, int dim) { /* If it's writeable, this means a reduction */ - if (*op_itflags & NPY_OP_ITFLAG_WRITE) { + if (op_itflags[iop] & NPY_OP_ITFLAG_WRITE) { if (!(flags & NPY_ITER_REDUCE_OK)) { PyErr_Format(PyExc_ValueError, "output operand requires a reduction along dimension %d, " @@ -1404,17 +1404,35 @@ npyiter_check_reduce_ok_and_set_flags( "does not match the expected output shape.", dim); return 0; } - if (!(*op_itflags & NPY_OP_ITFLAG_READ)) { + if (!(op_itflags[iop] & NPY_OP_ITFLAG_READ)) { PyErr_SetString(PyExc_ValueError, "output operand requires a reduction, but is flagged as " "write-only, not read-write"); return 0; } + /* + * The ARRAYMASK can't be a reduction, because + * it would be possible to write back to the + * array once when the ARRAYMASK says 'True', + * then have the reduction on the ARRAYMASK + * later flip to 'False', indicating that the + * write back should never have been done, + * and violating the strict masking semantics + */ + if (iop == maskop) { + PyErr_SetString(PyExc_ValueError, + "output operand requires a " + "reduction, but is flagged as " + "the ARRAYMASK operand which " + "is not permitted to be the " + "result of a reduction"); + return 0; + } NPY_IT_DBG_PRINT("Iterator: Indicating that a reduction is" "occurring\n"); NIT_ITFLAGS(iter) |= NPY_ITFLAG_REDUCE; - *op_itflags |= NPY_OP_ITFLAG_REDUCE; + op_itflags[iop] |= NPY_OP_ITFLAG_REDUCE; } return 1; } @@ -1597,42 +1615,9 @@ npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itf goto operand_different_than_broadcast; } /* If it's writeable, this means a reduction */ - if (op_itflags[iop] & NPY_OP_ITFLAG_WRITE) { - if (!(flags & NPY_ITER_REDUCE_OK)) { - PyErr_SetString(PyExc_ValueError, - "output operand requires a " - "reduction, but reduction is " - "not enabled"); - return 0; - } - if (!(op_itflags[iop] & NPY_OP_ITFLAG_READ)) { - PyErr_SetString(PyExc_ValueError, - "output operand requires a " - "reduction, but is flagged as " - "write-only, not read-write"); - return 0; - } - /* - * The ARRAYMASK can't be a reduction, because - * it would be possible to write back to the - * array once when the ARRAYMASK says 'True', - * then have the reduction on the ARRAYMASK - * later flip to 'False', indicating that the - * write back should never have been done, - * and violating the strict masking semantics - */ - if (iop == maskop) { - PyErr_SetString(PyExc_ValueError, - "output operand requires a " - "reduction, but is flagged as " - "the ARRAYMASK operand which " - "is not permitted to be the " - "result of a reduction"); - return 0; - } - - NIT_ITFLAGS(iter) |= NPY_ITFLAG_REDUCE; - op_itflags[iop] |= NPY_OP_ITFLAG_REDUCE; + if (!npyiter_check_reduce_ok_and_set_flags( + iter, flags, op_itflags, iop, maskop, idim)) { + return 0; } } else { @@ -1681,7 +1666,7 @@ npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itf goto operand_different_than_broadcast; } if (!npyiter_check_reduce_ok_and_set_flags( - iter, flags, &op_itflags[iop], i)) { + iter, flags, op_itflags, iop, maskop, i)) { return 0; } } @@ -1691,8 +1676,14 @@ npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itf } else { strides[iop] = 0; + /* + * If deleting this axis produces a reduction, but + * reduction wasn't enabled, throw an error. + * NOTE: We currently always allow new-axis if the iteration + * size is 1 (thus allowing broadcasting sometimes). + */ if (!npyiter_check_reduce_ok_and_set_flags( - iter, flags, &op_itflags[iop], i)) { + iter, flags, op_itflags, iop, maskop, i)) { return 0; } } @@ -2529,6 +2520,11 @@ npyiter_new_temp_array(NpyIter *iter, PyTypeObject *subtype, i = npyiter_undo_iter_axis_perm(idim, ndim, perm, NULL); i = npyiter_get_op_axis(op_axes[i], &reduction_axis); + /* + * If i < 0, this is a new axis (the operand does not have it) + * so we can ignore it here. The iterator setup will have + * ensured already that a potential reduction/broadcast is valid. + */ if (i >= 0) { NPY_IT_DBG_PRINT3("Iterator: Setting allocated stride %d " "for iterator dimension %d to %d\n", (int)i, @@ -2559,22 +2555,6 @@ npyiter_new_temp_array(NpyIter *iter, PyTypeObject *subtype, stride *= shape[i]; } } - else { - if (shape == NULL) { - /* - * If deleting this axis produces a reduction, but - * reduction wasn't enabled, throw an error. - * NOTE: We currently always allow new-axis if the iteration - * size is 1 (thus allowing broadcasting sometimes). - */ - if (!reduction_axis && NAD_SHAPE(axisdata) != 1) { - if (!npyiter_check_reduce_ok_and_set_flags( - iter, flags, op_itflags, i)) { - return NULL; - } - } - } - } } } else { diff --git a/numpy/core/src/npymath/ieee754.cpp b/numpy/core/src/npymath/ieee754.cpp index 3eb89d1d8..ebc1dbeba 100644 --- a/numpy/core/src/npymath/ieee754.cpp +++ b/numpy/core/src/npymath/ieee754.cpp @@ -9,18 +9,6 @@ #include "npy_math_common.h" #include "npy_math_private.h" -#ifndef HAVE_COPYSIGN -double -npy_copysign(double x, double y) -{ - npy_uint32 hx, hy; - GET_HIGH_WORD(hx, x); - GET_HIGH_WORD(hy, y); - SET_HIGH_WORD(x, (hx & 0x7fffffff) | (hy & 0x80000000)); - return x; -} -#endif - /* The below code is provided for compilers which do not yet provide C11 compatibility (gcc 4.5 and older) diff --git a/numpy/core/src/npymath/npy_math_internal.h.src b/numpy/core/src/npymath/npy_math_internal.h.src index 52aaa7102..6e84a905e 100644 --- a/numpy/core/src/npymath/npy_math_internal.h.src +++ b/numpy/core/src/npymath/npy_math_internal.h.src @@ -87,27 +87,6 @@ static const npy_uint64 MAGIC64[] = {0x5555555555555555ull, 0x3333333333333333ul ***************************************************************************** */ -/* The double variant for these functions are never blocked */ - -NPY_INPLACE double npy_exp(double x){ - return exp(x); -} - -NPY_INPLACE double npy_pow(double x, double y) -{ - return pow(x, y); -} - -NPY_INPLACE double npy_sqrt(double x) -{ - return sqrt(x); -} - -NPY_INPLACE double npy_modf(double x, double *iptr) -{ - return modf(x, iptr); -} - /* The following functions can be blocked, even for doubles */ /* Original code by Konrad Hinsen. */ @@ -320,9 +299,8 @@ NPY_INPLACE double npy_hypot(double x, double y) #endif /**begin repeat1 - * #kind = sin,cos,tan,sinh,cosh,tanh,fabs,floor,ceil,rint,trunc,log10, - * log,expm1,asin,acos,atan,asinh,acosh,atanh,log1p,exp2# - * #TRIG_WORKAROUND = WORKAROUND_APPLE_TRIG_BUG*3, 0*19# + * #kind = sin,cos,tan# + * #TRIG_WORKAROUND = WORKAROUND_APPLE_TRIG_BUG*3# */ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) { @@ -338,33 +316,6 @@ NPY_INPLACE @type@ npy_@kind@@c@(@type@ x) #undef WORKAROUND_APPLE_TRIG_BUG -/* C99 mandatory */ - -/**begin repeat1 - * #kind = fmod,copysign# - * #KIND = FMOD,COPYSIGN# - */ -NPY_INPLACE @type@ npy_@kind@@c@(@type@ x, @type@ y) -{ - return NPY__FP_SFX(@kind@)(x, y); -} -/**end repeat1**/ - -NPY_INPLACE @type@ npy_ldexp@c@(@type@ x, int exp) -{ - return NPY__FP_SFX(ldexp)(x, exp); -} - -NPY_INPLACE @type@ npy_frexp@c@(@type@ x, int* exp) -{ - return NPY__FP_SFX(frexp)(x, exp); -} - -NPY_INPLACE @type@ npy_cbrt@c@(@type@ x) -{ - return NPY__FP_SFX(cbrt)(x); -} - /**end repeat**/ /* Blocklist-able C99 functions */ diff --git a/numpy/core/src/umath/loops.c.src b/numpy/core/src/umath/loops.c.src index e5104db81..fe5aa9374 100644 --- a/numpy/core/src/umath/loops.c.src +++ b/numpy/core/src/umath/loops.c.src @@ -571,7 +571,6 @@ NPY_NO_EXPORT void /**begin repeat1 * #isa = , _avx2# - * #ISA = , AVX2# * #CHK = 1, defined(HAVE_ATTRIBUTE_TARGET_AVX2)# * #ATTR = , NPY_GCC_TARGET_AVX2# */ @@ -658,6 +657,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void #define INT_left_shift_needs_clear_floatstatus #define UINT_left_shift_needs_clear_floatstatus +#if @CHK@ NPY_NO_EXPORT NPY_GCC_OPT_3 void @TYPE@_left_shift@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) @@ -670,10 +670,12 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 void npy_clear_floatstatus_barrier((char*)dimensions); #endif } +#endif #undef INT_left_shift_needs_clear_floatstatus #undef UINT_left_shift_needs_clear_floatstatus +#if @CHK@ NPY_NO_EXPORT #ifndef NPY_DO_NOT_OPTIMIZE_@TYPE@_right_shift NPY_GCC_OPT_3 @@ -684,7 +686,7 @@ void { BINARY_LOOP_FAST(@type@, @type@, *out = npy_rshift@c@(in1, in2)); } - +#endif /**begin repeat2 * #kind = logical_and, logical_or# @@ -1448,7 +1450,10 @@ NPY_NO_EXPORT void /**begin repeat2 * #ISA = , _avx512_skx# * #isa = simd, avx512_skx# + * #CHK = 1, defined(HAVE_ATTRIBUTE_TARGET_AVX512_SKX)# **/ + +#if @CHK@ NPY_NO_EXPORT void @TYPE@_@kind@@ISA@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) { @@ -1460,6 +1465,7 @@ NPY_NO_EXPORT void } npy_clear_floatstatus_barrier((char*)dimensions); } +#endif /**end repeat2**/ /**end repeat1**/ @@ -2289,7 +2295,7 @@ NPY_NO_EXPORT void } } -#if @SIMD@ +#if @SIMD@ && defined(HAVE_ATTRIBUTE_TARGET_AVX512F) /**begin repeat1 * arithmetic * #kind = conjugate, square, absolute# diff --git a/numpy/core/tests/test_nditer.py b/numpy/core/tests/test_nditer.py index 473ea9754..f64d18edd 100644 --- a/numpy/core/tests/test_nditer.py +++ b/numpy/core/tests/test_nditer.py @@ -2738,6 +2738,7 @@ def test_iter_writemasked_badinput(): op_dtypes=['f4', None], casting='same_kind') + def _is_buffered(iterator): try: iterator.itviews @@ -2813,6 +2814,34 @@ def test_iter_writemasked(a): # were copied back assert_equal(a, np.broadcast_to([3, 3, 2.5] * reps, shape)) + +@pytest.mark.parametrize(["mask", "mask_axes"], [ + # Allocated operand (only broadcasts with -1) + (None, [-1, 0]), + # Reduction along the first dimension (with and without op_axes) + (np.zeros((1, 4), dtype="bool"), [0, 1]), + (np.zeros((1, 4), dtype="bool"), None), + # Test 0-D and -1 op_axes + (np.zeros(4, dtype="bool"), [-1, 0]), + (np.zeros((), dtype="bool"), [-1, -1]), + (np.zeros((), dtype="bool"), None)]) +def test_iter_writemasked_broadcast_error(mask, mask_axes): + # This assumes that a readwrite mask makes sense. This is likely not the + # case and should simply be deprecated. + arr = np.zeros((3, 4)) + itflags = ["reduce_ok"] + mask_flags = ["arraymask", "readwrite", "allocate"] + a_flags = ["writeonly", "writemasked"] + if mask_axes is None: + op_axes = None + else: + op_axes = [mask_axes, [0, 1]] + + with assert_raises(ValueError): + np.nditer((mask, arr), flags=itflags, op_flags=[mask_flags, a_flags], + op_axes=op_axes) + + def test_iter_writemasked_decref(): # force casting (to make it interesting) by using a structured dtype. arr = np.arange(10000).astype(">i,O") diff --git a/numpy/lib/function_base.py b/numpy/lib/function_base.py index a0c94114a..6065dd0d3 100644 --- a/numpy/lib/function_base.py +++ b/numpy/lib/function_base.py @@ -3648,6 +3648,10 @@ def msort(a): """ Return a copy of an array sorted along the first axis. + .. deprecated:: 1.24 + + msort is deprecated, use ``np.sort(a, axis=0)`` instead. + Parameters ---------- a : array_like @@ -3674,6 +3678,12 @@ def msort(a): [3, 4]]) """ + # 2022-10-20 1.24 + warnings.warn( + "msort is deprecated, use np.sort(a, axis=0) instead", + DeprecationWarning, + stacklevel=3, + ) b = array(a, subok=True, copy=True) b.sort(0) return b diff --git a/numpy/lib/recfunctions.py b/numpy/lib/recfunctions.py index 74a8f8969..6afcf1b7f 100644 --- a/numpy/lib/recfunctions.py +++ b/numpy/lib/recfunctions.py @@ -1057,6 +1057,8 @@ def unstructured_to_structured(arr, dtype=None, names=None, align=False, else: if names is not None: raise ValueError("don't supply both dtype and names") + # if dtype is the args of np.dtype, construct it + dtype = np.dtype(dtype) # sanity check of the input dtype fields = _get_fields_and_offsets(dtype) if len(fields) == 0: diff --git a/numpy/lib/tests/test_function_base.py b/numpy/lib/tests/test_function_base.py index 277843222..e407fc78c 100644 --- a/numpy/lib/tests/test_function_base.py +++ b/numpy/lib/tests/test_function_base.py @@ -2427,11 +2427,12 @@ class TestMsort: A = np.array([[0.44567325, 0.79115165, 0.54900530], [0.36844147, 0.37325583, 0.96098397], [0.64864341, 0.52929049, 0.39172155]]) - assert_almost_equal( - msort(A), - np.array([[0.36844147, 0.37325583, 0.39172155], - [0.44567325, 0.52929049, 0.54900530], - [0.64864341, 0.79115165, 0.96098397]])) + with pytest.warns(DeprecationWarning, match="msort is deprecated"): + assert_almost_equal( + msort(A), + np.array([[0.36844147, 0.37325583, 0.39172155], + [0.44567325, 0.52929049, 0.54900530], + [0.64864341, 0.79115165, 0.96098397]])) class TestMeshgrid: diff --git a/numpy/lib/tests/test_recfunctions.py b/numpy/lib/tests/test_recfunctions.py index 9b2506a7c..d8385f8be 100644 --- a/numpy/lib/tests/test_recfunctions.py +++ b/numpy/lib/tests/test_recfunctions.py @@ -318,6 +318,15 @@ class TestRecFunctions: assert_raises(NotImplementedError, unstructured_to_structured, np.zeros((3,0), dtype=np.int32)) + def test_unstructured_to_structured(self): + # test if dtype is the args of np.dtype + a = np.zeros((20, 2)) + test_dtype_args = [('x', float), ('y', float)] + test_dtype = np.dtype(test_dtype_args) + field1 = unstructured_to_structured(a, dtype=test_dtype_args) # now + field2 = unstructured_to_structured(a, dtype=test_dtype) # before + assert_equal(field1, field2) + def test_field_assignment_by_name(self): a = np.ones(2, dtype=[('a', 'i4'), ('b', 'f8'), ('c', 'u1')]) newdt = [('b', 'f4'), ('c', 'u1')] |
