summaryrefslogtreecommitdiff
path: root/numpy
diff options
context:
space:
mode:
Diffstat (limited to 'numpy')
-rw-r--r--numpy/__init__.py9
-rw-r--r--numpy/core/fromnumeric.py3
-rw-r--r--numpy/core/include/numpy/npy_math.h185
-rw-r--r--numpy/core/setup.py36
-rw-r--r--numpy/core/setup_common.py55
-rw-r--r--numpy/core/src/multiarray/nditer_constr.c96
-rw-r--r--numpy/core/src/npymath/ieee754.cpp12
-rw-r--r--numpy/core/src/npymath/npy_math_internal.h.src53
-rw-r--r--numpy/core/src/umath/loops.c.src12
-rw-r--r--numpy/core/tests/test_nditer.py29
-rw-r--r--numpy/lib/function_base.py10
-rw-r--r--numpy/lib/recfunctions.py2
-rw-r--r--numpy/lib/tests/test_function_base.py11
-rw-r--r--numpy/lib/tests/test_recfunctions.py9
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')]