Imported Upstream version 1.19.0 upstream/1.19.0
authorDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 31 Dec 2020 00:51:59 +0000 (09:51 +0900)
committerDongHun Kwak <dh0128.kwak@samsung.com>
Thu, 31 Dec 2020 00:51:59 +0000 (09:51 +0900)
750 files changed:
.circleci/config.yml
.gitignore
.mailmap
.travis.yml
INSTALL.rst.txt
LICENSE.txt
README.md
azure-pipelines.yml
azure-steps-windows.yml
benchmarks/README.rst
benchmarks/asv.conf.json
benchmarks/benchmarks/__init__.py
benchmarks/benchmarks/bench_app.py
benchmarks/benchmarks/bench_array_coercion.py [new file with mode: 0644]
benchmarks/benchmarks/bench_avx.py
benchmarks/benchmarks/bench_core.py
benchmarks/benchmarks/bench_function_base.py
benchmarks/benchmarks/bench_import.py
benchmarks/benchmarks/bench_indexing.py
benchmarks/benchmarks/bench_io.py
benchmarks/benchmarks/bench_itemselection.py [new file with mode: 0644]
benchmarks/benchmarks/bench_lib.py
benchmarks/benchmarks/bench_linalg.py
benchmarks/benchmarks/bench_ma.py
benchmarks/benchmarks/bench_overrides.py
benchmarks/benchmarks/bench_random.py
benchmarks/benchmarks/bench_records.py
benchmarks/benchmarks/bench_reduce.py
benchmarks/benchmarks/bench_shape_base.py
benchmarks/benchmarks/bench_ufunc.py
benchmarks/benchmarks/common.py
doc/DISTUTILS.rst.txt
doc/HOWTO_RELEASE.rst.txt
doc/Makefile
doc/Py3K.rst.txt
doc/RELEASE_WALKTHROUGH.rst.txt
doc/TESTS.rst.txt
doc/cdoc/Doxyfile
doc/cdoc/Makefile
doc/cdoc/numpyfilter.py
doc/changelog/1.12.0-changelog.rst
doc/changelog/1.15.0-changelog.rst
doc/changelog/1.16.5-changelog.rst
doc/changelog/1.17.0-changelog.rst
doc/changelog/1.18.5-changelog.rst [deleted file]
doc/changelog/1.19.0-changelog.rst [new file with mode: 0644]
doc/example.py
doc/neps/Makefile
doc/neps/_static/nep-0040_dtype-hierarchy.png [new file with mode: 0644]
doc/neps/_static/nep-0041-mindmap.svg [new file with mode: 0644]
doc/neps/conf.py
doc/neps/nep-0000.rst
doc/neps/nep-0010-new-iterator-ufunc.rst
doc/neps/nep-0012-missing-data.rst
doc/neps/nep-0021-advanced-indexing.rst
doc/neps/nep-0023-backwards-compatibility.rst
doc/neps/nep-0028-website-redesign.rst
doc/neps/nep-0030-duck-array-protocol.rst
doc/neps/nep-0034-infer-dtype-is-object.rst [new file with mode: 0644]
doc/neps/nep-0034.rst [deleted file]
doc/neps/nep-0035-array-creation-dispatch-with-array-function.rst [new file with mode: 0644]
doc/neps/nep-0037-array-module.rst [new file with mode: 0644]
doc/neps/nep-0038-SIMD-optimizations.rst [new file with mode: 0644]
doc/neps/nep-0040-legacy-datatype-impl.rst [new file with mode: 0644]
doc/neps/nep-0041-improved-dtype-support.rst [new file with mode: 0644]
doc/neps/nep-0044-restructuring-numpy-docs.rst [new file with mode: 0644]
doc/neps/scope.rst
doc/neps/tools/build_index.py
doc/postprocess.py
doc/release/upcoming_changes/template.rst
doc/source/_templates/indexcontent.html
doc/source/conf.py
doc/source/contents.rst
doc/source/dev/conduct/code_of_conduct.rst
doc/source/dev/development_environment.rst
doc/source/dev/development_workflow.rst
doc/source/dev/governance/governance.rst
doc/source/dev/governance/people.rst
doc/source/dev/howto-docs.rst [new file with mode: 0644]
doc/source/dev/index.rst
doc/source/dev/underthehood.rst [new file with mode: 0644]
doc/source/docs/howto_build_docs.rst
doc/source/f2py/advanced.rst
doc/source/f2py/allocarr_session.dat
doc/source/f2py/array_session.dat
doc/source/f2py/calculate.f
doc/source/f2py/calculate_session.dat
doc/source/f2py/callback.f
doc/source/f2py/callback_session.dat
doc/source/f2py/common_session.dat
doc/source/f2py/extcallback_session.dat
doc/source/f2py/f2py.getting-started.rst [new file with mode: 0644]
doc/source/f2py/ftype_session.dat
doc/source/f2py/getting-started.rst [deleted file]
doc/source/f2py/index.rst
doc/source/f2py/moddata_session.dat
doc/source/f2py/python-usage.rst
doc/source/f2py/scalar_session.dat
doc/source/f2py/setup_example.py
doc/source/f2py/signature-file.rst
doc/source/f2py/spam_session.dat
doc/source/f2py/string_session.dat
doc/source/f2py/usage.rst
doc/source/reference/arrays.classes.rst
doc/source/reference/arrays.datetime.rst
doc/source/reference/arrays.dtypes.rst
doc/source/reference/arrays.indexing.rst
doc/source/reference/arrays.ndarray.rst
doc/source/reference/arrays.nditer.cython.rst [new file with mode: 0644]
doc/source/reference/arrays.nditer.rst
doc/source/reference/c-api/array.rst
doc/source/reference/c-api/coremath.rst
doc/source/reference/c-api/index.rst
doc/source/reference/c-api/types-and-structures.rst
doc/source/reference/c-api/ufunc.rst
doc/source/reference/distutils.rst
doc/source/reference/global_state.rst [new file with mode: 0644]
doc/source/reference/index.rst
doc/source/reference/internals.rst
doc/source/reference/maskedarray.baseclass.rst
doc/source/reference/random/extending.rst
doc/source/reference/random/index.rst
doc/source/reference/random/legacy.rst
doc/source/reference/random/multithreading.rst
doc/source/reference/random/new-or-different.rst
doc/source/reference/random/performance.rst
doc/source/reference/routines.array-manipulation.rst
doc/source/reference/routines.io.rst
doc/source/reference/routines.linalg.rst
doc/source/reference/routines.ma.rst
doc/source/reference/routines.other.rst
doc/source/reference/routines.polynomials.chebyshev.rst
doc/source/reference/routines.polynomials.classes.rst
doc/source/reference/routines.polynomials.hermite.rst
doc/source/reference/routines.polynomials.hermite_e.rst
doc/source/reference/routines.polynomials.laguerre.rst
doc/source/reference/routines.polynomials.legendre.rst
doc/source/reference/routines.polynomials.package.rst
doc/source/reference/routines.polynomials.polynomial.rst
doc/source/reference/routines.polynomials.rst
doc/source/reference/ufuncs.rst
doc/source/release.rst
doc/source/release/1.13.0-notes.rst
doc/source/release/1.14.0-notes.rst
doc/source/release/1.16.5-notes.rst
doc/source/release/1.17.0-notes.rst
doc/source/release/1.18.0-notes.rst
doc/source/release/1.18.4-notes.rst
doc/source/release/1.18.5-notes.rst [deleted file]
doc/source/release/1.19.0-notes.rst [new file with mode: 0644]
doc/source/user/absolute_beginners.rst [new file with mode: 0644]
doc/source/user/basics.broadcasting.rst
doc/source/user/building.rst
doc/source/user/c-info.beyond-basics.rst
doc/source/user/c-info.how-to-extend.rst
doc/source/user/c-info.python-as-glue.rst
doc/source/user/c-info.ufunc-tutorial.rst
doc/source/user/explanations_index.rst [new file with mode: 0644]
doc/source/user/howtos_index.rst [new file with mode: 0644]
doc/source/user/images/np_MSE_explanation.png [new file with mode: 0644]
doc/source/user/images/np_MSE_explanation2.png [new file with mode: 0644]
doc/source/user/images/np_MSE_formula.png [new file with mode: 0644]
doc/source/user/images/np_MSE_implementation.png [new file with mode: 0644]
doc/source/user/images/np_aggregation.png [new file with mode: 0644]
doc/source/user/images/np_array.png [new file with mode: 0644]
doc/source/user/images/np_array_data_ones.png [new file with mode: 0644]
doc/source/user/images/np_array_dataones.png [new file with mode: 0644]
doc/source/user/images/np_create_array.png [new file with mode: 0644]
doc/source/user/images/np_create_matrix.png [new file with mode: 0644]
doc/source/user/images/np_data_plus_ones.png [new file with mode: 0644]
doc/source/user/images/np_indexing.png [new file with mode: 0644]
doc/source/user/images/np_matrix_aggregation.png [new file with mode: 0644]
doc/source/user/images/np_matrix_aggregation_row.png [new file with mode: 0644]
doc/source/user/images/np_matrix_arithmetic.png [new file with mode: 0644]
doc/source/user/images/np_matrix_broadcasting.png [new file with mode: 0644]
doc/source/user/images/np_matrix_indexing.png [new file with mode: 0644]
doc/source/user/images/np_mse_viz1.png [new file with mode: 0644]
doc/source/user/images/np_mse_viz2.png [new file with mode: 0644]
doc/source/user/images/np_multiply_broadcasting.png [new file with mode: 0644]
doc/source/user/images/np_ones_zeros_matrix.png [new file with mode: 0644]
doc/source/user/images/np_ones_zeros_random.png [new file with mode: 0644]
doc/source/user/images/np_pandas.png [new file with mode: 0644]
doc/source/user/images/np_readcsv.png [new file with mode: 0644]
doc/source/user/images/np_reshape.png [new file with mode: 0644]
doc/source/user/images/np_sub_mult_divide.png [new file with mode: 0644]
doc/source/user/images/np_transposing_reshaping.png [new file with mode: 0644]
doc/source/user/index.rst
doc/source/user/ionumpy.rst [new file with mode: 0644]
doc/source/user/numpy-for-matlab-users.rst
doc/source/user/plot_approx.py [new file with mode: 0644]
doc/source/user/plot_face.py [new file with mode: 0644]
doc/source/user/plot_final.py [new file with mode: 0644]
doc/source/user/plot_gray.py [new file with mode: 0644]
doc/source/user/plot_gray_svd.py [new file with mode: 0644]
doc/source/user/plot_reconstructed.py [new file with mode: 0644]
doc/source/user/plots/matplotlib1.py [new file with mode: 0644]
doc/source/user/plots/matplotlib2.py [new file with mode: 0644]
doc/source/user/plots/matplotlib3.py [new file with mode: 0644]
doc/source/user/quickstart.rst
doc/source/user/troubleshooting-importerror.rst
doc/source/user/tutorial-svd.rst [new file with mode: 0644]
doc/source/user/tutorials_index.rst [new file with mode: 0644]
doc/source/user/whatisnumpy.rst
doc/summarize.py [deleted file]
doc_requirements.txt [new file with mode: 0644]
numpy/__init__.pxd
numpy/__init__.py
numpy/_build_utils/__init__.py
numpy/_build_utils/apple_accelerate.py
numpy/_globals.py
numpy/_pytesttester.py
numpy/compat/__init__.py
numpy/compat/_inspect.py
numpy/compat/py3k.py
numpy/compat/setup.py
numpy/compat/tests/test_compat.py
numpy/conftest.py
numpy/core/__init__.py
numpy/core/_add_newdocs.py
numpy/core/_asarray.py
numpy/core/_dtype.py
numpy/core/_dtype_ctypes.py
numpy/core/_exceptions.py
numpy/core/_internal.py
numpy/core/_methods.py
numpy/core/_type_aliases.py
numpy/core/_ufunc_config.py
numpy/core/arrayprint.py
numpy/core/code_generators/__init__.py
numpy/core/code_generators/cversions.txt
numpy/core/code_generators/genapi.py
numpy/core/code_generators/generate_numpy_api.py
numpy/core/code_generators/generate_ufunc_api.py
numpy/core/code_generators/generate_umath.py
numpy/core/code_generators/numpy_api.py
numpy/core/code_generators/ufunc_docstrings.py
numpy/core/cversions.py
numpy/core/defchararray.py
numpy/core/einsumfunc.py
numpy/core/fromnumeric.py
numpy/core/function_base.py
numpy/core/getlimits.py
numpy/core/include/numpy/arrayscalars.h
numpy/core/include/numpy/ndarrayobject.h
numpy/core/include/numpy/ndarraytypes.h
numpy/core/include/numpy/npy_1_7_deprecated_api.h
numpy/core/include/numpy/npy_3kcompat.h
numpy/core/include/numpy/npy_common.h
numpy/core/include/numpy/npy_math.h
numpy/core/include/numpy/numpyconfig.h
numpy/core/include/numpy/ufuncobject.h
numpy/core/machar.py
numpy/core/memmap.py
numpy/core/multiarray.py
numpy/core/numeric.py
numpy/core/numerictypes.py
numpy/core/records.py
numpy/core/setup.py
numpy/core/setup_common.py
numpy/core/shape_base.py
numpy/core/src/common/array_assign.c
numpy/core/src/common/array_assign.h
numpy/core/src/common/get_attr_string.h
numpy/core/src/common/lowlevel_strided_loops.h
numpy/core/src/common/mem_overlap.c
numpy/core/src/common/npy_config.h
numpy/core/src/common/npy_cpu_features.c.src [new file with mode: 0644]
numpy/core/src/common/npy_cpu_features.h [new file with mode: 0644]
numpy/core/src/common/npy_longdouble.c
numpy/core/src/common/numpyos.c
numpy/core/src/common/ucsnarrow.c
numpy/core/src/common/ucsnarrow.h
numpy/core/src/common/ufunc_override.c
numpy/core/src/dummymodule.c
numpy/core/src/multiarray/_datetime.h
numpy/core/src/multiarray/_multiarray_tests.c.src
numpy/core/src/multiarray/alloc.c
numpy/core/src/multiarray/alloc.h
numpy/core/src/multiarray/array_assign_array.c
numpy/core/src/multiarray/array_assign_scalar.c
numpy/core/src/multiarray/arrayobject.c
numpy/core/src/multiarray/arraytypes.c.src
numpy/core/src/multiarray/buffer.c
numpy/core/src/multiarray/calculation.c
numpy/core/src/multiarray/common.c
numpy/core/src/multiarray/common.h
numpy/core/src/multiarray/compiled_base.c
numpy/core/src/multiarray/conversion_utils.c
numpy/core/src/multiarray/conversion_utils.h
numpy/core/src/multiarray/convert.c
numpy/core/src/multiarray/convert_datatype.c
numpy/core/src/multiarray/convert_datatype.h
numpy/core/src/multiarray/ctors.c
numpy/core/src/multiarray/ctors.h
numpy/core/src/multiarray/datetime.c
numpy/core/src/multiarray/datetime_busday.c
numpy/core/src/multiarray/datetime_busdaycal.c
numpy/core/src/multiarray/datetime_strings.c
numpy/core/src/multiarray/datetime_strings.h
numpy/core/src/multiarray/descriptor.c
numpy/core/src/multiarray/descriptor.h
numpy/core/src/multiarray/dragon4.c
numpy/core/src/multiarray/dtype_transfer.c
numpy/core/src/multiarray/einsum.c.src
numpy/core/src/multiarray/flagsobject.c
numpy/core/src/multiarray/getset.c
numpy/core/src/multiarray/item_selection.c
numpy/core/src/multiarray/item_selection.h
numpy/core/src/multiarray/iterators.c
numpy/core/src/multiarray/lowlevel_strided_loops.c.src
numpy/core/src/multiarray/mapping.c
numpy/core/src/multiarray/methods.c
numpy/core/src/multiarray/methods.h
numpy/core/src/multiarray/multiarraymodule.c
numpy/core/src/multiarray/nditer_constr.c
numpy/core/src/multiarray/nditer_pywrap.c
numpy/core/src/multiarray/npy_buffer.h
numpy/core/src/multiarray/number.c
numpy/core/src/multiarray/refcount.c
numpy/core/src/multiarray/scalarapi.c
numpy/core/src/multiarray/scalartypes.c.src
numpy/core/src/multiarray/scalartypes.h
numpy/core/src/multiarray/shape.c
numpy/core/src/multiarray/shape.h
numpy/core/src/multiarray/strfuncs.c
numpy/core/src/multiarray/strfuncs.h
numpy/core/src/multiarray/typeinfo.c
numpy/core/src/multiarray/usertypes.c
numpy/core/src/npymath/halffloat.c
numpy/core/src/umath/_operand_flag_tests.c.src
numpy/core/src/umath/_rational_tests.c.src
numpy/core/src/umath/_struct_ufunc_tests.c.src
numpy/core/src/umath/_umath_tests.c.src
numpy/core/src/umath/clip.c.src
numpy/core/src/umath/clip.h.src
numpy/core/src/umath/cpuid.c [deleted file]
numpy/core/src/umath/cpuid.h [deleted file]
numpy/core/src/umath/extobj.c
numpy/core/src/umath/fast_loop_macros.h
numpy/core/src/umath/funcs.inc.src
numpy/core/src/umath/loops.c.src
numpy/core/src/umath/loops.h.src
numpy/core/src/umath/matmul.c.src
numpy/core/src/umath/matmul.h.src
numpy/core/src/umath/npy_simd_data.h [new file with mode: 0644]
numpy/core/src/umath/override.c
numpy/core/src/umath/reduction.c
numpy/core/src/umath/reduction.h
numpy/core/src/umath/scalarmath.c.src
numpy/core/src/umath/simd.inc.src
numpy/core/src/umath/ufunc_object.c
numpy/core/src/umath/ufunc_type_resolution.c
numpy/core/src/umath/ufunc_type_resolution.h
numpy/core/src/umath/umathmodule.c
numpy/core/tests/_locales.py
numpy/core/tests/data/umath-validation-set-cos
numpy/core/tests/data/umath-validation-set-exp
numpy/core/tests/data/umath-validation-set-sin
numpy/core/tests/test_abc.py
numpy/core/tests/test_api.py
numpy/core/tests/test_arrayprint.py
numpy/core/tests/test_conversion_utils.py [new file with mode: 0644]
numpy/core/tests/test_cpu_features.py [new file with mode: 0644]
numpy/core/tests/test_datetime.py
numpy/core/tests/test_defchararray.py
numpy/core/tests/test_deprecations.py
numpy/core/tests/test_dtype.py
numpy/core/tests/test_einsum.py
numpy/core/tests/test_errstate.py
numpy/core/tests/test_extint128.py
numpy/core/tests/test_function_base.py
numpy/core/tests/test_getlimits.py
numpy/core/tests/test_half.py
numpy/core/tests/test_indexerrors.py
numpy/core/tests/test_indexing.py
numpy/core/tests/test_issue14735.py [deleted file]
numpy/core/tests/test_item_selection.py
numpy/core/tests/test_longdouble.py
numpy/core/tests/test_machar.py
numpy/core/tests/test_mem_overlap.py
numpy/core/tests/test_memmap.py
numpy/core/tests/test_multiarray.py
numpy/core/tests/test_nditer.py
numpy/core/tests/test_numeric.py
numpy/core/tests/test_numerictypes.py
numpy/core/tests/test_overrides.py
numpy/core/tests/test_print.py
numpy/core/tests/test_protocols.py [new file with mode: 0644]
numpy/core/tests/test_records.py
numpy/core/tests/test_regression.py
numpy/core/tests/test_scalar_ctors.py
numpy/core/tests/test_scalar_methods.py
numpy/core/tests/test_scalarbuffer.py
numpy/core/tests/test_scalarinherit.py
numpy/core/tests/test_scalarmath.py
numpy/core/tests/test_scalarprint.py
numpy/core/tests/test_shape_base.py
numpy/core/tests/test_ufunc.py
numpy/core/tests/test_umath.py
numpy/core/tests/test_umath_accuracy.py
numpy/core/tests/test_umath_complex.py
numpy/core/tests/test_unicode.py
numpy/core/umath.py
numpy/core/umath_tests.py
numpy/ctypeslib.py
numpy/distutils/__init__.py
numpy/distutils/ccompiler.py
numpy/distutils/command/__init__.py
numpy/distutils/command/autodist.py
numpy/distutils/command/bdist_rpm.py
numpy/distutils/command/build.py
numpy/distutils/command/build_clib.py
numpy/distutils/command/build_ext.py
numpy/distutils/command/build_py.py
numpy/distutils/command/build_scripts.py
numpy/distutils/command/build_src.py
numpy/distutils/command/config.py
numpy/distutils/command/config_compiler.py
numpy/distutils/command/develop.py
numpy/distutils/command/egg_info.py
numpy/distutils/command/install.py
numpy/distutils/command/install_clib.py
numpy/distutils/command/install_data.py
numpy/distutils/command/install_headers.py
numpy/distutils/command/sdist.py
numpy/distutils/compat.py [deleted file]
numpy/distutils/conv_template.py
numpy/distutils/core.py
numpy/distutils/cpuinfo.py
numpy/distutils/exec_command.py
numpy/distutils/extension.py
numpy/distutils/fcompiler/__init__.py
numpy/distutils/fcompiler/absoft.py
numpy/distutils/fcompiler/compaq.py
numpy/distutils/fcompiler/environment.py
numpy/distutils/fcompiler/g95.py
numpy/distutils/fcompiler/gnu.py
numpy/distutils/fcompiler/hpux.py
numpy/distutils/fcompiler/ibm.py
numpy/distutils/fcompiler/intel.py
numpy/distutils/fcompiler/lahey.py
numpy/distutils/fcompiler/mips.py
numpy/distutils/fcompiler/nag.py
numpy/distutils/fcompiler/none.py
numpy/distutils/fcompiler/pathf95.py
numpy/distutils/fcompiler/pg.py
numpy/distutils/fcompiler/sun.py
numpy/distutils/fcompiler/vast.py
numpy/distutils/from_template.py
numpy/distutils/intelccompiler.py
numpy/distutils/lib2def.py
numpy/distutils/line_endings.py
numpy/distutils/log.py
numpy/distutils/mingw32ccompiler.py
numpy/distutils/misc_util.py
numpy/distutils/msvc9compiler.py
numpy/distutils/msvccompiler.py
numpy/distutils/npy_pkg_config.py
numpy/distutils/numpy_distribution.py
numpy/distutils/pathccompiler.py
numpy/distutils/setup.py
numpy/distutils/system_info.py
numpy/distutils/tests/test_exec_command.py
numpy/distutils/tests/test_fcompiler.py
numpy/distutils/tests/test_fcompiler_gnu.py
numpy/distutils/tests/test_fcompiler_intel.py
numpy/distutils/tests/test_fcompiler_nagfor.py
numpy/distutils/tests/test_misc_util.py
numpy/distutils/tests/test_npy_pkg_config.py
numpy/distutils/tests/test_shell_utils.py
numpy/distutils/tests/test_system_info.py
numpy/distutils/unixccompiler.py
numpy/doc/__init__.py
numpy/doc/basics.py
numpy/doc/broadcasting.py
numpy/doc/byteswapping.py
numpy/doc/constants.py
numpy/doc/creation.py
numpy/doc/dispatch.py
numpy/doc/glossary.py
numpy/doc/indexing.py
numpy/doc/internals.py
numpy/doc/misc.py
numpy/doc/structured_arrays.py
numpy/doc/subclassing.py
numpy/doc/ufuncs.py
numpy/dual.py
numpy/f2py/__init__.py
numpy/f2py/__main__.py
numpy/f2py/__version__.py
numpy/f2py/auxfuncs.py
numpy/f2py/capi_maps.py
numpy/f2py/cb_rules.py
numpy/f2py/cfuncs.py
numpy/f2py/common_rules.py
numpy/f2py/crackfortran.py
numpy/f2py/diagnose.py
numpy/f2py/f2py2e.py
numpy/f2py/f2py_testing.py
numpy/f2py/f90mod_rules.py
numpy/f2py/func2subr.py
numpy/f2py/rules.py
numpy/f2py/setup.py
numpy/f2py/src/fortranobject.c
numpy/f2py/src/fortranobject.h
numpy/f2py/tests/src/array_from_pyobj/wrapmodule.c
numpy/f2py/tests/test_array_from_pyobj.py
numpy/f2py/tests/test_assumed_shape.py
numpy/f2py/tests/test_block_docstring.py
numpy/f2py/tests/test_callback.py
numpy/f2py/tests/test_common.py
numpy/f2py/tests/test_compile_function.py
numpy/f2py/tests/test_crackfortran.py [new file with mode: 0644]
numpy/f2py/tests/test_kind.py
numpy/f2py/tests/test_mixed.py
numpy/f2py/tests/test_parameter.py
numpy/f2py/tests/test_quoted_character.py
numpy/f2py/tests/test_regression.py
numpy/f2py/tests/test_return_character.py
numpy/f2py/tests/test_return_complex.py
numpy/f2py/tests/test_return_integer.py
numpy/f2py/tests/test_return_logical.py
numpy/f2py/tests/test_return_real.py
numpy/f2py/tests/test_semicolon_split.py
numpy/f2py/tests/test_size.py
numpy/f2py/tests/test_string.py
numpy/f2py/tests/util.py
numpy/f2py/use_rules.py
numpy/fft/__init__.py
numpy/fft/_pocketfft.c
numpy/fft/_pocketfft.py
numpy/fft/helper.py
numpy/fft/setup.py
numpy/fft/tests/test_helper.py
numpy/fft/tests/test_pocketfft.py
numpy/lib/__init__.py
numpy/lib/_datasource.py
numpy/lib/_iotools.py
numpy/lib/_version.py
numpy/lib/arraypad.py
numpy/lib/arraysetops.py
numpy/lib/arrayterator.py
numpy/lib/financial.py
numpy/lib/format.py
numpy/lib/function_base.py
numpy/lib/histograms.py
numpy/lib/index_tricks.py
numpy/lib/mixins.py
numpy/lib/nanfunctions.py
numpy/lib/npyio.py
numpy/lib/polynomial.py
numpy/lib/recfunctions.py
numpy/lib/scimath.py
numpy/lib/setup.py
numpy/lib/shape_base.py
numpy/lib/stride_tricks.py
numpy/lib/tests/test__datasource.py
numpy/lib/tests/test__iotools.py
numpy/lib/tests/test__version.py
numpy/lib/tests/test_arraypad.py
numpy/lib/tests/test_arraysetops.py
numpy/lib/tests/test_arrayterator.py
numpy/lib/tests/test_financial.py
numpy/lib/tests/test_format.py
numpy/lib/tests/test_function_base.py
numpy/lib/tests/test_histograms.py
numpy/lib/tests/test_index_tricks.py
numpy/lib/tests/test_io.py
numpy/lib/tests/test_mixins.py
numpy/lib/tests/test_nanfunctions.py
numpy/lib/tests/test_packbits.py
numpy/lib/tests/test_polynomial.py
numpy/lib/tests/test_recfunctions.py
numpy/lib/tests/test_regression.py
numpy/lib/tests/test_shape_base.py
numpy/lib/tests/test_stride_tricks.py
numpy/lib/tests/test_twodim_base.py
numpy/lib/tests/test_type_check.py
numpy/lib/tests/test_ufunclike.py
numpy/lib/tests/test_utils.py
numpy/lib/twodim_base.py
numpy/lib/type_check.py
numpy/lib/ufunclike.py
numpy/lib/user_array.py
numpy/lib/utils.py
numpy/linalg/__init__.py
numpy/linalg/lapack_lite/README.rst
numpy/linalg/lapack_lite/clapack_scrub.py
numpy/linalg/lapack_lite/f2c.c
numpy/linalg/lapack_lite/f2c.h
numpy/linalg/lapack_lite/f2c_blas.c
numpy/linalg/lapack_lite/f2c_c_lapack.c
numpy/linalg/lapack_lite/f2c_config.c
numpy/linalg/lapack_lite/f2c_d_lapack.c
numpy/linalg/lapack_lite/f2c_lapack.c
numpy/linalg/lapack_lite/f2c_s_lapack.c
numpy/linalg/lapack_lite/f2c_z_lapack.c
numpy/linalg/lapack_lite/fortran.py
numpy/linalg/lapack_lite/lapack_lite_names.h [new file with mode: 0644]
numpy/linalg/lapack_lite/make_lite.py
numpy/linalg/lapack_lite/python_xerbla.c
numpy/linalg/lapack_litemodule.c
numpy/linalg/linalg.py
numpy/linalg/setup.py
numpy/linalg/tests/test_build.py
numpy/linalg/tests/test_deprecations.py
numpy/linalg/tests/test_linalg.py
numpy/linalg/tests/test_regression.py
numpy/linalg/umath_linalg.c.src
numpy/ma/README.rst [new file with mode: 0644]
numpy/ma/README.txt [deleted file]
numpy/ma/__init__.py
numpy/ma/bench.py
numpy/ma/core.py
numpy/ma/extras.py
numpy/ma/mrecords.py
numpy/ma/setup.py
numpy/ma/tests/test_core.py
numpy/ma/tests/test_deprecations.py
numpy/ma/tests/test_extras.py
numpy/ma/tests/test_mrecords.py
numpy/ma/tests/test_old_ma.py
numpy/ma/tests/test_regression.py
numpy/ma/tests/test_subclassing.py
numpy/ma/testutils.py
numpy/ma/timer_comparison.py
numpy/matlib.py
numpy/matrixlib/__init__.py
numpy/matrixlib/defmatrix.py
numpy/matrixlib/setup.py
numpy/matrixlib/tests/test_defmatrix.py
numpy/matrixlib/tests/test_interaction.py
numpy/matrixlib/tests/test_masked_matrix.py
numpy/matrixlib/tests/test_matrix_linalg.py
numpy/matrixlib/tests/test_multiarray.py
numpy/matrixlib/tests/test_numeric.py
numpy/matrixlib/tests/test_regression.py
numpy/polynomial/__init__.py
numpy/polynomial/_polybase.py
numpy/polynomial/chebyshev.py
numpy/polynomial/hermite.py
numpy/polynomial/hermite_e.py
numpy/polynomial/laguerre.py
numpy/polynomial/legendre.py
numpy/polynomial/polynomial.py
numpy/polynomial/polyutils.py
numpy/polynomial/setup.py
numpy/polynomial/tests/test_chebyshev.py
numpy/polynomial/tests/test_classes.py
numpy/polynomial/tests/test_hermite.py
numpy/polynomial/tests/test_hermite_e.py
numpy/polynomial/tests/test_laguerre.py
numpy/polynomial/tests/test_legendre.py
numpy/polynomial/tests/test_polynomial.py
numpy/polynomial/tests/test_polyutils.py
numpy/polynomial/tests/test_printing.py
numpy/random/__init__.pxd
numpy/random/__init__.py
numpy/random/_bit_generator.pxd [deleted file]
numpy/random/_bit_generator.pyx [deleted file]
numpy/random/_bounded_integers.pyx.in
numpy/random/_common.pyx
numpy/random/_examples/cython/extending.pyx
numpy/random/_examples/cython/extending_distributions.pyx
numpy/random/_examples/cython/setup.py
numpy/random/_generator.pyx
numpy/random/_mt19937.pyx
numpy/random/_pcg64.pyx
numpy/random/bit_generator.pxd [new file with mode: 0644]
numpy/random/bit_generator.pyx [new file with mode: 0644]
numpy/random/c_distributions.pxd [new file with mode: 0644]
numpy/random/mtrand.pyx
numpy/random/setup.py
numpy/random/src/distributions/random_mvhg_count.c
numpy/random/src/distributions/random_mvhg_marginals.c
numpy/random/src/mt19937/mt19937-jump.c
numpy/random/src/mt19937/mt19937-jump.h
numpy/random/src/mt19937/mt19937-poly.h [deleted file]
numpy/random/src/mt19937/mt19937.c
numpy/random/src/philox/philox-benchmark.c
numpy/random/tests/test_direct.py
numpy/random/tests/test_extending.py
numpy/random/tests/test_generator_mt19937.py
numpy/random/tests/test_generator_mt19937_regressions.py
numpy/random/tests/test_random.py
numpy/random/tests/test_randomstate.py
numpy/random/tests/test_randomstate_regression.py
numpy/random/tests/test_regression.py
numpy/random/tests/test_seed_sequence.py
numpy/random/tests/test_smoke.py
numpy/setup.py
numpy/testing/__init__.py
numpy/testing/_private/decorators.py
numpy/testing/_private/noseclasses.py
numpy/testing/_private/nosetester.py
numpy/testing/_private/parameterized.py
numpy/testing/_private/utils.py
numpy/testing/print_coercion_tables.py
numpy/testing/setup.py
numpy/testing/tests/test_decorators.py
numpy/testing/tests/test_doctesting.py
numpy/testing/tests/test_utils.py
numpy/testing/utils.py
numpy/tests/test_ctypeslib.py
numpy/tests/test_matlib.py
numpy/tests/test_numpy_version.py
numpy/tests/test_public_api.py
numpy/tests/test_reloading.py
numpy/tests/test_scripts.py
numpy/tests/test_warnings.py
pavement.py
pytest.ini
runtests.py
setup.py
shippable.yml
site.cfg.example
test_requirements.txt
tools/allocation_tracking/alloc_hook.pyx
tools/allocation_tracking/setup.py
tools/allocation_tracking/track_allocations.py
tools/c_coverage/c_coverage_report.py
tools/changelog.py
tools/ci/push_docs_to_repo.py
tools/ci/test_all_newsfragments_used.py
tools/commitstats.py
tools/cythonize.py
tools/download-wheels.py [new file with mode: 0644]
tools/find_deprecated_escaped_characters.py
tools/npy_tempita/__init__.py
tools/npy_tempita/_looper.py
tools/npy_tempita/compat3.py
tools/openblas_support.py
tools/pypy-test.sh
tools/refguide_check.py
tools/swig/numpy.i
tools/swig/pyfragments.swg
tools/swig/test/Array2.cxx
tools/swig/test/Array2.h
tools/swig/test/setup.py
tools/swig/test/testArray.py
tools/swig/test/testFarray.py
tools/swig/test/testFlat.py
tools/swig/test/testFortran.py
tools/swig/test/testMatrix.py
tools/swig/test/testSuperTensor.py
tools/swig/test/testTensor.py
tools/swig/test/testVector.py
tools/travis-before-install.sh
tools/travis-test.sh
tox.ini

index 772c3fbfda54d5c0b708185f651b2f84781d1453..c3d4352e82a0a333575c4a00e961110b060c0600 100644 (file)
@@ -21,7 +21,7 @@ jobs:
             python3 -m venv venv
             ln -s $(which python3) venv/bin/python3.6
             . venv/bin/activate
-            pip install cython sphinx==2.2.0 matplotlib ipython
+            pip install cython sphinx==2.3.1 matplotlib ipython
             sudo apt-get update
             sudo apt-get install -y graphviz texlive-fonts-recommended texlive-latex-recommended texlive-latex-extra texlive-generic-extra latexmk texlive-xetex
 
@@ -33,6 +33,7 @@ jobs:
             pip install cython
             pip install .
             pip install scipy
+            pip install pandas
 
       - run:
           name: create release notes
@@ -42,12 +43,19 @@ jobs:
             VERSION=$(python -c "import setup; print(setup.VERSION)")
             towncrier --version $VERSION --yes
             ./tools/ci/test_all_newsfragments_used.py
+
+      - run:
+          name: run doctests on documentation
+          command: |
+            . venv/bin/activate
+            (cd doc ; git submodule update --init)
+            python tools/refguide_check.py --rst
+
       - run:
           name: build devdocs
           command: |
             . venv/bin/activate
             cd doc
-            git submodule update --init
             SPHINXOPTS=-q make -e html
 
       - run:
index 2ad02b56017a09dfbcdfe526158e739cbaf6abcb..a203abd5b178de27f7ff13636acb266ff34c1007 100644 (file)
@@ -125,6 +125,7 @@ numpy/core/include/numpy/multiarray_api.txt
 numpy/core/include/numpy/ufunc_api.txt
 numpy/core/lib/
 numpy/core/src/common/npy_binsearch.h
+numpy/core/src/common/npy_cpu_features.c
 numpy/core/src/common/npy_partition.h
 numpy/core/src/common/npy_sort.h
 numpy/core/src/common/templ_common.h
@@ -178,3 +179,17 @@ numpy/random/legacy/*.c
 numpy/random/_mtrand/randint_helpers.pxi
 numpy/random/bounded_integers.pyx
 numpy/random/bounded_integers.pxd
+tools/swig/test/Array_wrap.cxx
+tools/swig/test/Farray_wrap.cxx
+tools/swig/test/Farray.py
+tools/swig/test/Flat_wrap.cxx
+tools/swig/test/Flat.py
+tools/swig/test/Fortran_wrap.cxx
+tools/swig/test/Fortran.py
+tools/swig/test/Matrix_wrap.cxx
+tools/swig/test/Matrix.py
+tools/swig/test/Tensor_wrap.cxx
+tools/swig/test/Tensor.py
+tools/swig/test/Vector.py
+tools/swig/test/Vector_wrap.cxx
+tools/swig/test/Array.py
index 836f2f81c4d5cc131d36bbb70645fb7feefc9d0c..6a700941b75271632cd3d80e208fd064fb78beab 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -32,6 +32,7 @@ Amir Sarabadani <ladsgroup@gmail.com> amir <ladsgroup@gmail.com>
 Anatoly Techtonik <techtonik@gmail.com> anatoly techtonik <techtonik@gmail.com>
 Andras Deak <deak.andris@gmail.com> adeak <adeak@users.noreply.github.com>
 Andrea Pattori <andrea.pattori@gmail.com> patto90 <andrea.pattori@gmail.com>
+Andrea Sangalli <and-sang@outlook.com> and-sang <53617841+and-sang@users.noreply.github.com>
 Andrei Kucharavy <ank@andreikucharavy.com> chiffa <ank@andreikucharavy.com>
 Anne Archibald <peridot.faceted@gmail.com> aarchiba <peridot.faceted@gmail.com>
 Anne Archibald <peridot.faceted@gmail.com> Anne Archibald <archibald@astron.nl>
@@ -55,6 +56,7 @@ Bob Eldering <eldering@jive.eu> bobeldering <eldering@jive.eu>
 Brett R Murphy <bmurphy@enthought.com> brettrmurphy <bmurphy@enthought.com>
 Bryan Van de Ven <bryanv@continuum.io> Bryan Van de Ven <bryan@Laptop-3.local>
 Bryan Van de Ven <bryanv@continuum.io> Bryan Van de Ven <bryan@laptop.local>
+Bui Duc Minh <buiducminh287@gmail.com> Mibu287 <41239569+Mibu287@users.noreply.github.com>
 Carl Kleffner <cmkleffner@gmail.com> carlkl <cmkleffner@gmail.com>
 Chris Burns <chris.burns@localhost> chris.burns <chris.burns@localhost>
 Chris Kerr <debdepba@dasganma.tk> Chris Kerr <cjk34@cam.ac.uk>
@@ -63,6 +65,7 @@ Christopher Hanley <chanley@gmail.com> chanley <chanley@gmail.com>
 Christoph Gohlke <cgohlke@uci.edu> cgholke <?@?>
 Christoph Gohlke <cgohlke@uci.edu> cgohlke <cgohlke@uci.edu>
 Christoph Gohlke <cgohlke@uci.edu> Christolph Gohlke <cgohlke@uci.edu>
+Chunlin Fang <fangchunlin@huawei.com> Qiyu8 <fangchunlin@huawei.com>
 Colin Snyder <47012605+colinsnyder@users.noreply.github.com> colinsnyder <47012605+colinsnyder@users.noreply.github.com>
 Daniel B Allan <daniel.b.allan@gmail.com> danielballan <daniel.b.allan@gmail.com>
 Daniel da Silva <mail@danieldasilva.org> Daniel da Silva <daniel@meltingwax.net>
@@ -83,9 +86,12 @@ Derek Homeier <derek@astro.physik.uni-goettingen.de> Derek Homeir <derek@astro.p
 Derek Homeier <derek@astro.physik.uni-goettingen.de> Derek Homier <derek@astro.physik.uni-goettingen.de>
 Derrick Williams <myutat@gmail.com> derrick <myutat@gmail.com>
 Dmitriy Shalyga <zuko3d@gmail.com> zuko3d <zuko3d@gmail.com>
+Dustan Levenstein <dlevenstein@gmail.com> dustanlevenstein <43019642+dustanlevenstein@users.noreply.github.com>
 Ed Schofield <edschofield@localhost> edschofield <edschofield@localhost>
 Egor Zindy <ezindy@gmail.com> zindy <ezindy@gmail.com>
 Endolith <endolith@gmail.com>
+Erik M. Bray <erik.bray@lri.fr> E. M. Bray <erik.bray@lri.fr>
+Erik M. Bray <erik.bray@lri.fr> Erik Bray <erik.m.bray@gmail.com>
 Eric Fode <ericfode@gmail.com> Eric Fode <ericfode@linuxlaptop.(none)>
 Eric Quintero <eric.antonio.quintero@gmail.com> e-q <eric.antonio.quintero@gmail.com>
 Ernest N. Mamikonyan <ernest.mamikonyan@gmail.com> mamikony <ernest.mamikonyan@sig.com>
@@ -111,6 +117,7 @@ Hanno Klemm <hanno.klemm@maerskoil.com> hklemm <hanno.klemm@maerskoil.com>
 Hemil Desai <desai38@purdue.edu> hemildesai <desai38@purdue.edu>
 Hiroyuki V. Yamazaki <hiroyuki.vincent.yamazaki@gmail.com> hvy <hiroyuki.vincent.yamazaki@gmail.com>
 Gerhard Hobler <gerhard.hobler@tuwien.ac.at> hobler <gerhard.hobler@tuwien.ac.at>
+Guillaume Peillex <guillaume.peillex@gmail.com> hippo91 <guillaume.peillex@gmail.com>
 Irvin Probst <irvin.probst@ensta-bretagne.fr> I--P <irvin.probst@ensta-bretagne.fr>
 Jaime Fernandez <jaime.frio@gmail.com> Jaime Fernandez <jaime.fernandez@hp.com>
 Jaime Fernandez <jaime.frio@gmail.com> jaimefrio <jaime.frio@gmail.com>
@@ -129,6 +136,7 @@ Johannes Hampp <johannes.hampp@zeu.uni-giessen.de> euronion <42553970+euronion@u
 Johannes Schönberger <hannesschoenberger@gmail.com> Johannes Schönberger <jschoenberger@demuc.de>
 Johann Faouzi <johann.faouzi@gmail.com> johann.faouzi <johann.faouzi@icm-institute.org>
 John Darbyshire <24256554+attack68@users.noreply.github.com> attack68 <24256554+attack68@users.noreply.github.com>
+John Kirkham <kirkhamj@janelia.hhmi.org> jakirkham <jakirkham@gmail.com>
 Joseph Fox-Rabinovitz <jfoxrabinovitz@gmail.com> Joseph Fox-Rabinovitz <joseph.r.fox-rabinovitz@nasa.gov>
 Joseph Fox-Rabinovitz <jfoxrabinovitz@gmail.com> Joseph Fox-Rabinovitz <madphysicist@users.noreply.github.com>
 Joseph Fox-Rabinovitz <jfoxrabinovitz@gmail.com>  Mad Physicist <madphysicist@users.noreply.github.com>
@@ -138,6 +146,7 @@ Julian Taylor <juliantaylor108@gmail.com> Julian Taylor <juliantaylor108@googlem
 Julien Lhermitte <jrmlhermitte@gmail.com> Julien Lhermitte <lhermitte@bnl.gov>
 Julien Schueller <julien.schueller@gmail.com> jschueller <julien.schueller@gmail.com>
 Justus Magin <keewis@posteo.de> keewis <keewis@users.noreply.github.com>
+Justus Magin <keewis@posteo.de> Keewis <keewis@posteo.de>
 Kai Striega <kaistriega@gmail.com> kai <kaistriega@gmail.com>
 Kai Striega <kaistriega@gmail.com> kai-striega <kaistriega@gmail.com>
 Kai Striega <kaistriega@gmail.com> kai-striega <kaistriega+github@gmail.com>
@@ -155,6 +164,7 @@ Luke Zoltan Kelley <lkelley@cfa.harvard.edu> lzkelley <lkelley@cfa.harvard.edu>
 Magdalena Proszewska <magdalena.proszewska@gmail.com> mpro <magdalena.proszewska@gmail.com>
 Magdalena Proszewska <magdalena.proszewska@gmail.com> mproszewska <38814059+mproszewska@users.noreply.github.com>
 Manoj Kumar <manojkumarsivaraj334@gmail.com> MechCoder <manojkumarsivaraj334@gmail.com>
+Marcin Podhajski <podhajskimarcin@gmail.com> m-podhajski <36967358+m-podhajski@users.noreply.github.com>
 Mark DePristo <mdepristo@synapdx.com> markdepristo <mdepristo@synapdx.com>
 Mark Weissman <mw9050@gmail.com> m-d-w <mw9050@gmail.com>
 Mark Wiebe <mwwiebe@gmail.com> Mark <mwwiebe@gmail.com>
@@ -164,16 +174,21 @@ Mark Wiebe <mwwiebe@gmail.com> Mark Wiebe <mwiebe@georg.(none)>
 Martin Goodson <martingoodson@gmail.com> martingoodson <martingoodson@gmail.com>
 Martin Reinecke <martin@mpa-garching.mpg.de> mreineck <martin@mpa-garching.mpg.de>
 Martin Teichmann <martin.teichmann@xfel.eu> Martin Teichmann <lkb.teichmann@gmail.com>
+Matt Hancock <not.matt.hancock@gmail.com> matt <mhancock743@gmail.com>
 Martino Sorbaro <martino.sorbaro@ed.ac.uk> martinosorb <martino.sorbaro@ed.ac.uk>
 Mattheus Ueckermann <empeeu@yahoo.com> empeeu <empeeu@yahoo.com>
 Matthew Harrigan <harrigan.matthew@gmail.com> MattHarrigan <harrigan.matthew@gmail.com>
 Matti Picus <matti.picus@gmail.com> mattip <matti.picus@gmail.com>
+Maximilian Konrad <maximilianlukaskonrad@hotmail.de> MLK97 <maximilianlukaskonrad@hotmail.de>
+Melissa Weber Mendonça <melissawm@gmail.com> Melissa Weber Mendonca <melissawm@gmail.com>
+Melissa Weber Mendonça <melissawm@gmail.com> melissawm <melissawm@gmail.com>
 Michael Behrisch <oss@behrisch.de> behrisch <behrisch@users.sourceforge.net>
 Michael Droettboom <mdboom@gmail.com> mdroe <mdroe@localhost>
 Michael  K. Tran  <trankmichael@gmail.com> mtran <trankmichael@gmail.com>
 Michael Martin <mmartin4242@gmail.com> mmartin <mmartin4242@gmail.com>
 Michael Schnaitter <schnaitterm@knights.ucf.edu> schnaitterm <schnaitterm@users.noreply.github.com>
 Muhammad Kasim <firman.kasim@gmail.com> mfkasim91 <firman.kasim@gmail.com>
+Masashi Kishimoto <drehbleistift@gmail.com> kishimoto-banana <drehbleistift@gmail.com>
 Nathaniel J. Smith <njs@pobox.com> njsmith <njs@pobox.com>
 Naveen Arunachalam <notatroll.troll@gmail.com> naveenarun <notatroll.troll@gmail.com>
 Nicolas Scheffer <nicolas.scheffer@sri.com> Nicolas Scheffer <scheffer@speech.sri.com>
@@ -190,7 +205,9 @@ Peter J Cock <p.j.a.cock@googlemail.com> peterjc <p.j.a.cock@googlemail.com>
 Phil Elson <pelson.pub@gmail.com>
 Pierre GM <pierregmcode@gmail.com> pierregm <pierregmcode@gmail.com>
 Pierre GM <pierregmcode@gmail.com> pierregm <pierregm@localhost>
+Piotr GaiÅ„ski <dociebieaniuszlem@gmail.com> panpiort8 <dociebieaniuszlem@gmail.com>
 Prabhu Ramachandran <prabhu@localhost> prabhu <prabhu@localhost>
+Przemyslaw Bartosik <sendthenote@gmail.com> przemb <sendthenote@gmail.com>
 Ralf Gommers <ralf.gommers@gmail.com> Ralf Gommers <ralf.gommers@googlemail.com>
 Ralf Gommers <ralf.gommers@gmail.com> rgommers <ralf.gommers@googlemail.com>
 Rehas Sachdeva <aquannie@gmail.com> rehassachdeva <aquannie@gmail.com>
@@ -211,6 +228,7 @@ Sebastian Berg <sebastian@sipsolutions.net> seberg <sebastian@sipsolutions.net>
 Shekhar Prasad Rajak <shekharrajak@live.com> shekharrajak <shekharrajak@live.com>
 Shota Kawabuchi <shota.kawabuchi+GitHub@gmail.com> skwbc <shota.kawabuchi+GitHub@gmail.com>
 Siavash Eliasi <siavashserver@gmail.com> siavashserver <siavashserver@gmail.com>
+Simon Gasse <simon.gasse@gmail.com> sgasse <sgasse@users.noreply.github.com>
 Søren Rasmussen <soren.rasmussen@alexandra.dk> sorenrasmussenai <47032123+sorenrasmussenai@users.noreply.github.com>
 Stefan van der Walt <stefanv@berkeley.edu> Stefan van der Walt <sjvdwalt@gmail.com>
 Stefan van der Walt <stefanv@berkeley.edu> Stefan van der Walt <stefan@sun.ac.za>
@@ -228,6 +246,7 @@ Tony LaTorre <tlatorre@uchicago.edu> tlatorre <tlatorre@uchicago.edu>
 Travis Oliphant <travis@continuum.io> Travis E. Oliphant <teoliphant@gmail.com>
 Travis Oliphant <travis@continuum.io> Travis Oliphant <oliphant@enthought.com>
 Valentin Haenel <valentin@haenel.co> Valentin Haenel <valentin.haenel@gmx.de>
+Rakesh Vasudevan <rakesh.nvasudev@gmail.com> vrakesh <rakesh.nvasudev@gmail.com>
 Vrinda Narayan <talk2vrinda@gmail.com> vrindaaa <48102157+vrindaaa@users.noreply.github.com>
 Warren Weckesser <warren.weckesser@enthought.com> Warren Weckesser <warren.weckesser@gmail.com>
 Weitang Li <liwt31@163.com> wtli@Dirac <liwt31@163.com>
@@ -237,6 +256,7 @@ Wim Glenn <wim.glenn@melbourneit.com.au> wim glenn <wim.glenn@melbourneit.com.au
 Wojtek Ruszczewski <git@wr.waw.pl> wrwrwr <git@wr.waw.pl>
 Yuji Kanagawa <yuji.kngw.80s.revive@gmail.com> kngwyu <yuji.kngw.80s.revive@gmail.com>
 Yury Kirienko <yury.kirienko@gmail.com> kirienko <yury.kirienko@gmail.com>
+Zac Hatfield-Dodds <zac.hatfield.dodds@gmail.com> Zac-HD <zac.hatfield.dodds@gmail.com>
 Zixu Zhao <zixu.zhao.tireless@gmail.com> ZZhaoTireless <zixu.zhao.tireless@gmail.com>
 Ziyan Zhou <ziyan.zhou@mujin.co.jp> Ziyan <ziyan.zhou@mujin.co.jp>
 Zieji Pohz <poh.ziji@gmail.com> jpoh <poh.zijie@gmail.com>
index 65e55eb6df83e9d63f1cdc6bd6130c7cdaedb582..e019495fb85258fdf2b69b3cc9ca8d8dec5820f1 100644 (file)
@@ -2,7 +2,8 @@
 #   http://lint.travis-ci.org/
 language: python
 group: travis_latest
-dist: xenial
+os: linux
+dist: bionic
 
 # Travis whitelists the installable packages, additions can be requested
 #   https://github.com/travis-ci/apt-package-whitelist
@@ -10,6 +11,8 @@ addons:
   apt:
     packages: &common_packages
       - gfortran
+      - libgfortran5
+      - libgfortran3
       - libatlas-base-dev
       # Speedup builds, particularly when USE_CHROOT=1
       - eatmydata
@@ -18,8 +21,6 @@ cache:
   directories:
     - $HOME/.cache/pip
 
-stage: Comprehensive tests
-
 stages:
     # Do the style check and a single test job, don't proceed if it fails
     - name: Initial tests
@@ -28,7 +29,6 @@ stages:
 
 env:
   global:
-    - OpenBLAS_version=0.3.7
     - WHEELHOUSE_UPLOADER_USERNAME=travis.numpy
     # The following is generated with the command:
     # travis encrypt -r numpy/numpy WHEELHOUSE_UPLOADER_SECRET=tH3AP1KeY
@@ -37,18 +37,18 @@ env:
                iFWt9Ka92CaqYdU7nqfWp9VImSndPmssjmCXJ1v1IjZPAM\
                ahp7Qnm0rWRmA0z9SomuRUQOJQ6s684vU="
 
-matrix:
+jobs:
   include:
     # Do all python versions without environment variables set
     - stage: Initial tests
       python: 3.8
 
-    - python: 3.5
-    - python: 3.6
+    - stage: Comprehensive tests
+      python: 3.6
     - python: 3.7
+    - python: 3.9-dev
 
     - python: 3.6
-      dist: bionic
       env: USE_DEBUG=1
       addons:
         apt:
@@ -87,6 +87,8 @@ matrix:
           packages:
             - gfortran
             - eatmydata
+            - libgfortran5
+            - libgfortran3
 
     - python: 3.7
       env: USE_WHEEL=1 NPY_RELAXED_STRIDES_DEBUG=1
@@ -104,7 +106,7 @@ matrix:
       os: linux
       arch: ppc64le
       env:
-       # use ppc64le OpenBLAS build, not system ATLAS
+       # use OpenBLAS build, not system ATLAS
        - DOWNLOAD_OPENBLAS=1
        - ATLAS=None
 
@@ -112,10 +114,21 @@ matrix:
       os: linux
       arch: s390x
       env:
-       # use s390x OpenBLAS build, not system ATLAS
+       # use OpenBLAS build, not system ATLAS
+       - DOWNLOAD_OPENBLAS=1
+       - NPY_USE_BLAS_ILP64=1
+       - ATLAS=None
+
+    - python: 3.7
+      os: linux
+      arch: aarch64
+      env:
+       # use OpenBLAS build, not system ATLAS
+       - DOWNLOAD_OPENBLAS=1
        - ATLAS=None
 
 
+
 before_install:
   - ./tools/travis-before-install.sh
 
index 50cd7ab1fe96707549126452bbe9f84324e0398c..2b92267514f6a08114b2fad779a6e267365d4b14 100644 (file)
@@ -14,7 +14,7 @@ Prerequisites
 
 Building NumPy requires the following installed software:
 
-1) Python__ 3.5.x or newer.
+1) Python__ 3.6.x or newer.
 
    Please note that the Python development headers also need to be installed,
    e.g., on Debian/Ubuntu one needs to install both `python3` and
@@ -26,8 +26,13 @@ Building NumPy requires the following installed software:
 
    This is required for testing NumPy, but not for using it.
 
+4) Hypothesis__ (optional) 5.3.0 or later
+
+   This is required for testing NumPy, but not for using it.
+
 Python__ http://www.python.org
 pytest__ http://pytest.readthedocs.io
+Hypothesis__ https://hypothesis.readthedocs.io/en/latest/
 
 
 .. note::
index 5eae3201a70c2be97770d15f669c23ac861a3aca..8ce64521862e44a1a147025270a3ee799e865d7e 100644 (file)
@@ -1,4 +1,4 @@
-Copyright (c) 2005-2019, NumPy Developers.
+Copyright (c) 2005-2020, NumPy Developers.
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
index ae92b6309edde2bdf3e1e6a839e1d28c6b0d1819..276261a9f242640f00d426ae50d79a624f98095e 100644 (file)
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
 NumPy is the fundamental package needed for scientific computing with Python.
 
 - **Website:** https://www.numpy.org
-- **Documentation:** https://docs.scipy.org/
+- **Documentation:** https://numpy.org/doc
 - **Mailing list:** https://mail.python.org/mailman/listinfo/numpy-discussion
 - **Source code:** https://github.com/numpy/numpy
 - **Contributing:** https://www.numpy.org/devdocs/dev/index.html
index 77837275df15a1c25862c63cb26aa350f260d865..564f5d8e89a898a23302f0cf94e42a952fc08a6f 100644 (file)
@@ -5,10 +5,11 @@ trigger:
     include:
       - master
       - maintenance/*
-variables:
-  # OpenBLAS_version should be updated
-  # to match numpy-wheels repo
-  OpenBLAS_version: 0.3.7
+
+pr:
+  branches:
+    include:
+    - '*'  # must quote since "*" is a YAML reserved character; we want a string
 
 stages:
 - stage: InitialTests
@@ -28,34 +29,32 @@ stages:
 
 - stage: ComprehensiveTests
   jobs:
-  - job: Linux_Python_36_32bit_full_with_asserts
+  - job: Linux_Python_38_32bit_full_with_asserts
     pool:
-      vmImage: 'ubuntu-16.04'
+      vmImage: 'ubuntu-18.04'
     steps:
     - script: |
-            docker pull i386/ubuntu:bionic
-            docker run -v $(pwd):/numpy i386/ubuntu:bionic /bin/bash -c "cd numpy && \
-            apt-get -y update && \
-            apt-get -y install python3.6-dev python3-pip locales python3-certifi && \
-            locale-gen fr_FR && update-locale && \
-            apt-get -y install gfortran-5 wget && \
+            docker pull quay.io/pypa/manylinux2010_i686
+            docker run -v $(pwd):/numpy -e CFLAGS="-msse2 -std=c99 -UNDEBUG" \
+            -e F77=gfortran-5 -e F90=gfortran-5 quay.io/pypa/manylinux2010_i686 \
+            /bin/bash -xc "cd numpy && \
+            /opt/python/cp38-cp38/bin/python -mvenv venv &&\
+            source venv/bin/activate && \
             target=\$(python3 tools/openblas_support.py) && \
-            ls -lR \$target && \
             cp -r \$target/lib/* /usr/lib && \
             cp \$target/include/* /usr/include && \
-            python3 -m pip install --user --upgrade pip setuptools && \
-            python3 -m pip install --user -r test_requirements.txt && \
-            python3 -m pip install . && \
-            F77=gfortran-5 F90=gfortran-5 \
-            CFLAGS=-UNDEBUG python3 runtests.py -n --debug-info --mode=full -- -rsx --junitxml=junit/test-results.xml && \
-            python3 tools/openblas_support.py --check_version $(OpenBLAS_version)"
-      displayName: 'Run 32-bit Ubuntu Docker Build / Tests'
+            python3 -m pip install -r test_requirements.txt && \
+            echo CFLAGS \$CFLAGS && \
+            python3 -m pip install -v . && \
+            python3 runtests.py -n --debug-info --mode=full -- -rsx --junitxml=junit/test-results.xml && \
+            python3 tools/openblas_support.py --check_version"
+      displayName: 'Run 32-bit manylinux2010 Docker Build / Tests'
     - task: PublishTestResults@2
       condition: succeededOrFailed()
       inputs:
         testResultsFiles: '**/test-*.xml'
         failTaskOnFailedTests: true
-        testRunTitle: 'Publish test results for Python 3.6-32 bit full Linux'
+        testRunTitle: 'Publish test results for Python 3.8-32 bit full Linux'
   - job: macOS
     pool:
       # NOTE: at time of writing, there is a danger
@@ -67,13 +66,20 @@ stages:
       # they will patch this issue
       vmImage: macOS-10.14
     strategy:
-      maxParallel: 2
+      maxParallel: 3
       matrix:
           Python36:
             PYTHON_VERSION: '3.6'
+            USE_OPENBLAS: '1'
           Python36-ILP64:
             PYTHON_VERSION: '3.6'
             NPY_USE_BLAS_ILP64: '1'
+            USE_OPENBLAS: '1'
+            USE_XCODE_10: '1'
+          Accelerate:
+            PYTHON_VERSION: '3.6'
+            USE_OPENBLAS: '0'
+
     steps:
     # the @0 refers to the (major) version of the *task* on Microsoft's
     # end, not the order in the build matrix nor anything to do
@@ -83,10 +89,11 @@ stages:
         versionSpec: $(PYTHON_VERSION)
         addToPath: true
         architecture: 'x64'
-    # NOTE: do we have a compelling reason to use older / newer
-    # versions of Xcode toolchain for testing?
-    - script: /bin/bash -c "sudo xcode-select -s /Applications/Xcode_10.app/Contents/Developer"
-      displayName: 'select Xcode version'
+    - script: |
+        set -xe
+        [ -n "$USE_XCODE_10" ] && /bin/bash -c "sudo xcode-select -s /Applications/Xcode_10.app/Contents/Developer"
+        clang --version
+      displayName: 'report clang version'
     # NOTE: might be better if we could avoid installing
     # two C compilers, but with homebrew looks like we're
     # now stuck getting the full gcc toolchain instead of
@@ -114,7 +121,6 @@ stages:
     # primarily on file size / name details
     - script: |
         set -xe
-        python -m pip install urllib3
         target=$(python tools/openblas_support.py)
         ls -lR $target
         # manually link to appropriate system paths
@@ -122,6 +128,7 @@ stages:
         cp $target/include/* /usr/local/include/
         otool -L /usr/local/lib/libopenblas*
       displayName: 'install pre-built openblas'
+      condition: eq(variables['USE_OPENBLAS'], '1')
     - script: python -m pip install --upgrade pip setuptools wheel
       displayName: 'Install tools'
     - script: |
@@ -140,16 +147,40 @@ stages:
         ATLAS: None
         ACCELERATE: None
         CC: /usr/bin/clang
+      condition: eq(variables['USE_OPENBLAS'], '1')
+    - script: python setup.py build -j 4 build_ext --inplace install
+      displayName: 'Build NumPy without OpenBLAS'
+      env:
+        BLAS: None
+        LAPACK: None
+        ATLAS: None
+        CC: /usr/bin/clang
+      condition: eq(variables['USE_OPENBLAS'], '0')
     # wait until after dev build of NumPy to pip
     # install matplotlib to avoid pip install of older numpy
     - script: python -m pip install matplotlib
       displayName: 'Install matplotlib before refguide run'
     - script: python runtests.py -g --refguide-check
       displayName: 'Run Refuide Check'
+      condition: eq(variables['USE_OPENBLAS'], '1')
     - script: python runtests.py -n --mode=full -- -rsx --junitxml=junit/test-results.xml
       displayName: 'Run Full NumPy Test Suite'
-    - bash: python tools/openblas_support.py --check_version $(OpenBLAS_version)
+      condition: eq(variables['USE_OPENBLAS'], '1')
+    - bash: python tools/openblas_support.py --check_version
       displayName: 'Verify OpenBLAS version'
+      condition: eq(variables['USE_OPENBLAS'], '1')
+    # import doesn't work when in numpy src directory , so do a pip dev install of build lib to test
+    - script: |
+        #!/bin/bash -v
+        set +e
+        python -c "import numpy as np" > test_output.log 2>&1
+        check_output_code=$?
+        cat test_output.log
+        grep "buggy Accelerate backend"  test_output.log
+        check_message=$?
+        if [ $check_output_code == 1 ] && [ $check_message == 0 ]; then exit 0; else exit 1;fi
+      displayName: "Check if numpy import fails with accelerate"
+      condition: eq(variables['USE_OPENBLAS'], '0')
     - task: PublishTestResults@2
       condition: succeededOrFailed()
       inputs:
@@ -177,11 +208,6 @@ stages:
             PYTHON_ARCH: 'x86'
             TEST_MODE: fast
             BITS: 32
-          Python35-64bit-full:
-            PYTHON_VERSION: '3.5'
-            PYTHON_ARCH: 'x64'
-            TEST_MODE: full
-            BITS: 64
           Python36-64bit-full:
             PYTHON_VERSION: '3.6'
             PYTHON_ARCH: 'x64'
@@ -203,7 +229,7 @@ stages:
     - template: azure-steps-windows.yml
   - job: Linux_PyPy3
     pool:
-      vmIMage: 'ubuntu-16.04'
+      vmIMage: 'ubuntu-18.04'
     steps:
     - script: source tools/pypy-test.sh
       displayName: 'Run PyPy3 Build / Tests'
index 46b8c1ff9b31987c791de5d63f3d0bb09a2dc7d4..c39faddf9fd45fc498753644007b88e588c0db5a 100644 (file)
@@ -14,7 +14,7 @@ steps:
     # to $PYTHON_EXE's directory since that is on a different drive which
     # mingw does not like. Instead copy it to a directory and set OPENBLAS,
     # since OPENBLAS will be picked up by the openblas discovery
-    python -m pip  install urllib3
+    python -m pip  install
     $target = $(python tools/openblas_support.py)
     mkdir openblas
     echo Copying $target to openblas/openblas$env:OPENBLAS_SUFFIX.a
index b67994ce08e6433da44afaba8d4f3a326df7a11a..f56c253399adf00f44c753bac794edba5086f518 100644 (file)
@@ -16,19 +16,50 @@ unless told otherwise. Some of the benchmarking features in
 ``runtests.py``. To run the benchmarks, you do not need to install a
 development version of NumPy to your current Python environment.
 
-Run a benchmark against currently checked out NumPy version (don't
-record the result)::
+Before beginning, ensure that *airspeed velocity* is installed.
+By default, `asv` ships with support for anaconda and virtualenv::
+
+    pip install asv
+    pip install virtualenv
+
+After contributing new benchmarks, you should test them locally
+before submitting a pull request.
+
+To run all benchmarks, navigate to the root NumPy directory at
+the command line and execute::
+
+    python runtests.py --bench
+
+where ``--bench`` activates the benchmark suite instead of the
+test suite. This builds NumPy and runs  all available benchmarks
+defined in ``benchmarks/``. (Note: this could take a while. Each
+benchmark is run multiple times to measure the distribution in
+execution times.)
+
+To run benchmarks from a particular benchmark module, such as
+``bench_core.py``, simply append the filename without the extension::
 
     python runtests.py --bench bench_core
 
-Compare change in benchmark results to another version::
+To run a benchmark defined in a class, such as ``Mandelbrot``
+from ``bench_avx.py``::
+
+    python runtests.py --bench bench_avx.Mandelbrot
+
+Compare change in benchmark results to another version/commit/branch::
 
     python runtests.py --bench-compare v1.6.2 bench_core
+    python runtests.py --bench-compare 8bf4e9b bench_core
+    python runtests.py --bench-compare master bench_core
 
-Run ASV commands (record results and generate HTML)::
+All of the commands above display the results in plain text in
+the console, and the results are not saved for comparison with
+future commits. For greater control, a graphical view, and to
+have results saved for future comparison you can run ASV commands
+(record results and generate HTML)::
 
     cd benchmarks
-    asv run --skip-existing-commits --steps 10 ALL
+    asv run -n -e --python=same
     asv publish
     asv preview
 
index b3c7f9f20e6a2e505c8ae8ac17baf4c404653572..d9222d49572a5feabbce8b4b57e98aca091a4a07 100644 (file)
@@ -15,7 +15,7 @@
 
     // List of branches to benchmark. If not provided, defaults to "master"
     // (for git) or "tip" (for mercurial).
-    "branches": ["master"],
+    "branches": ["HEAD"],
 
     // The DVCS being used.  If not set, it will be automatically
     // determined from "repo" by looking at the protocol in the URL
@@ -42,7 +42,6 @@
     // list indicates to just test against the default (latest)
     // version.
     "matrix": {
-       "six": [],
         "Cython": [],
     },
 
index e8a859ff4784ce57dd7297ea99f8cc3852d61ba3..e4193cf0582fc150f03646dbec76d0930622bdc6 100644 (file)
@@ -1,3 +1 @@
-from __future__ import absolute_import, division, print_function
-
 from . import common
index ccf6e4c4af85570266aa6b4ea45cdd98e19dee98..bee95c2011725764e80b3d36e940ebd4cd34a0ac 100644 (file)
@@ -1,11 +1,7 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark
 
 import numpy as np
 
-from six.moves import xrange
-
 
 class LaplaceInplace(Benchmark):
     params = ['inplace', 'normal']
@@ -61,7 +57,7 @@ class MaxesOfDots(Benchmark):
         ntime = 200
 
         self.arrays = [np.random.normal(size=(ntime, nfeat))
-                       for i in xrange(nsubj)]
+                       for i in range(nsubj)]
 
     def maxes_of_dots(self, arrays):
         """
diff --git a/benchmarks/benchmarks/bench_array_coercion.py b/benchmarks/benchmarks/bench_array_coercion.py
new file mode 100644 (file)
index 0000000..2bae4c0
--- /dev/null
@@ -0,0 +1,57 @@
+from __future__ import absolute_import, division, print_function
+
+from .common import Benchmark
+
+import numpy as np
+
+
+class ArrayCoercionSmall(Benchmark):
+    # More detailed benchmarks for array coercion,
+    # some basic benchmarks are in `bench_core.py`.
+    params = [[range(3), [1], 1, np.array([5], dtype=np.int64), np.int64(5)]]
+    param_names = ['array_like']
+    int64 = np.dtype(np.int64)
+
+    def time_array_invalid_kwarg(self, array_like):
+        try:
+            np.array(array_like, ndmin="not-integer")
+        except TypeError:
+            pass
+
+    def time_array(self, array_like):
+        np.array(array_like)
+
+    def time_array_dtype_not_kwargs(self, array_like):
+        np.array(array_like, self.int64)
+
+    def time_array_no_copy(self, array_like):
+        np.array(array_like, copy=False)
+
+    def time_array_subok(self, array_like):
+        np.array(array_like, subok=True)
+
+    def time_array_all_kwargs(self, array_like):
+        np.array(array_like, dtype=self.int64, copy=False, order="F",
+                 subok=False, ndmin=2)
+
+    def time_asarray(self, array_like):
+        np.asarray(array_like)
+
+    def time_asarray_dtype(self, array_like):
+        np.array(array_like, dtype=self.int64)
+
+    def time_asarray_dtype(self, array_like):
+        np.array(array_like, dtype=self.int64, order="F")
+
+    def time_asanyarray(self, array_like):
+        np.asarray(array_like)
+
+    def time_asanyarray_dtype(self, array_like):
+        np.array(array_like, dtype=self.int64)
+
+    def time_asanyarray_dtype(self, array_like):
+        np.array(array_like, dtype=self.int64, order="F")
+
+    def time_ascontiguousarray(self, array_like):
+        np.ascontiguousarray(array_like)
+
index f7b524e43ba0a7960ba6c714bee793bb1e7e3d7e..2a128b3ffbad0ae389c7041f53d07e8b0792da29 100644 (file)
@@ -1,10 +1,12 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark
 
 import numpy as np
 
-avx_ufuncs = ['sqrt',
+avx_ufuncs = ['sin',
+              'cos',
+              'exp',
+              'log',
+              'sqrt',
               'absolute',
               'reciprocal',
               'square',
@@ -32,3 +34,126 @@ class AVX_UFunc(Benchmark):
     def time_ufunc(self, ufuncname, stride, dtype):
         self.f(self.arr[::stride])
 
+avx_bfuncs = ['maximum',
+              'minimum']
+
+class AVX_BFunc(Benchmark):
+
+    params = [avx_bfuncs, dtype, stride]
+    param_names = ['avx_based_bfunc', 'dtype', 'stride']
+    timeout = 10
+
+    def setup(self, ufuncname, dtype, stride):
+        np.seterr(all='ignore')
+        try:
+            self.f = getattr(np, ufuncname)
+        except AttributeError:
+            raise NotImplementedError()
+        N = 10000
+        self.arr1 = np.array(np.random.rand(stride*N), dtype=dtype)
+        self.arr2 = np.array(np.random.rand(stride*N), dtype=dtype)
+
+    def time_ufunc(self, ufuncname, dtype, stride):
+        self.f(self.arr1[::stride], self.arr2[::stride])
+
+cmplx_bfuncs = ['add',
+                'subtract',
+                'multiply',
+                'divide']
+cmplxstride = [1, 2, 4]
+cmplxdtype  = ['F', 'D']
+
+class AVX_cmplx_arithmetic(Benchmark):
+    params = [cmplx_bfuncs, cmplxstride, cmplxdtype]
+    param_names = ['bfunc', 'stride', 'dtype']
+    timeout = 10
+
+    def setup(self, bfuncname, stride, dtype):
+        np.seterr(all='ignore')
+        try:
+            self.f = getattr(np, bfuncname)
+        except AttributeError:
+            raise NotImplementedError()
+        N = 10000
+        self.arr1 = np.ones(stride*N, dtype)
+        self.arr2 = np.ones(stride*N, dtype)
+
+    def time_ufunc(self, bfuncname, stride, dtype):
+        self.f(self.arr1[::stride], self.arr2[::stride])
+
+cmplx_ufuncs = ['reciprocal',
+                'absolute',
+                'square',
+                'conjugate']
+
+class AVX_cmplx_funcs(Benchmark):
+    params = [cmplx_ufuncs, cmplxstride, cmplxdtype]
+    param_names = ['bfunc', 'stride', 'dtype']
+    timeout = 10
+
+    def setup(self, bfuncname, stride, dtype):
+        np.seterr(all='ignore')
+        try:
+            self.f = getattr(np, bfuncname)
+        except AttributeError:
+            raise NotImplementedError()
+        N = 10000
+        self.arr1 = np.ones(stride*N, dtype)
+
+    def time_ufunc(self, bfuncname, stride, dtype):
+        self.f(self.arr1[::stride])
+
+class Mandelbrot(Benchmark):
+    def f(self,z):
+        return np.abs(z) < 4.0
+
+    def g(self,z,c):
+        return np.sum(np.multiply(z,z) + c)
+
+    def mandelbrot_numpy(self, c, maxiter):
+        output = np.zeros(c.shape, np.int)
+        z = np.empty(c.shape, np.complex64)
+        for it in range(maxiter):
+            notdone = self.f(z)
+            output[notdone] = it
+            z[notdone] = self.g(z[notdone],c[notdone])
+        output[output == maxiter-1] = 0
+        return output
+
+    def mandelbrot_set(self,xmin,xmax,ymin,ymax,width,height,maxiter):
+        r1 = np.linspace(xmin, xmax, width, dtype=np.float32)
+        r2 = np.linspace(ymin, ymax, height, dtype=np.float32)
+        c = r1 + r2[:,None]*1j
+        n3 = self.mandelbrot_numpy(c,maxiter)
+        return (r1,r2,n3.T)
+
+    def time_mandel(self):
+        self.mandelbrot_set(-0.74877,-0.74872,0.06505,0.06510,1000,1000,2048)
+
+class LogisticRegression(Benchmark):
+    param_names = ['dtype']
+    params = [np.float32, np.float64]
+
+    timeout = 1000
+    def train(self, max_epoch):
+        for epoch in range(max_epoch):
+            z = np.matmul(self.X_train, self.W)
+            A = 1 / (1 + np.exp(-z)) # sigmoid(z)
+            loss = -np.mean(self.Y_train * np.log(A) + (1-self.Y_train) * np.log(1-A))
+            dz = A - self.Y_train
+            dw = (1/self.size) * np.matmul(self.X_train.T, dz)
+            self.W = self.W - self.alpha*dw
+
+    def setup(self, dtype):
+        np.random.seed(42)
+        self.size = 250
+        features = 16
+        self.X_train = np.random.rand(self.size,features).astype(dtype)
+        self.Y_train = np.random.choice(2,self.size).astype(dtype)
+        # Initialize weights
+        self.W = np.zeros((features,1), dtype=dtype)
+        self.b = np.zeros((1,1), dtype=dtype)
+        self.alpha = 0.1
+
+    def time_train(self, dtype):
+        self.train(1000)
index f7ce61b8f9ca7c39f9cd11ba95f4aebca5908afc..060d0f7db614b81b9e29d042a48c9e8f9e72772a 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark
 
 import numpy as np
@@ -182,3 +180,14 @@ class UnpackBits(Benchmark):
 class Indices(Benchmark):
     def time_indices(self):
         np.indices((1000, 500))
+
+class VarComplex(Benchmark):
+    params = [10**n for n in range(1, 9)]
+    def setup(self, n):
+        self.arr = np.random.randn(n) + 1j * np.random.randn(n)
+
+    def teardown(self, n):
+        del self.arr
+
+    def time_var(self, n):
+        self.arr.var()
index 2170c4fc4cd51ae1df6000c4a6b20da38a699a3f..b1e59274986c76bd9e859873c42d2243c21b3316 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark
 
 import numpy as np
@@ -106,7 +104,7 @@ def memoize(f):
     return f
 
 
-class SortGenerator(object):
+class SortGenerator:
     # The size of the unsorted area in the "random unsorted area"
     # benchmarks
     AREA_SIZE = 100
index 83edecafebeaf9143433dd7373c85da6401cb236..4b6ecbc7bbb1ed414e3cb0ad67da5d653458774a 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from subprocess import call
 from sys import executable
 from timeit import default_timer
index a62a2050e28343e8e625c949dead3ec4fa732c4d..9ee0d1fb575d61abb4825e967b04fe41b780fcf3 100644 (file)
@@ -1,11 +1,7 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark, get_squares_, get_indexes_, get_indexes_rand_
 
 from os.path import join as pjoin
 import shutil
-import sys
-import six
 from numpy import memmap, float32, array
 import numpy as np
 from tempfile import mkdtemp
@@ -25,13 +21,10 @@ class Indexing(Benchmark):
               'indexes_': get_indexes_(),
               'indexes_rand_': get_indexes_rand_()}
 
-        if sys.version_info[0] >= 3:
-            code = "def run():\n    for a in squares_.values(): a[%s]%s"
-        else:
-            code = "def run():\n    for a in squares_.itervalues(): a[%s]%s"
+        code = "def run():\n    for a in squares_.values(): a[%s]%s"
         code = code % (sel, op)
 
-        six.exec_(code, ns)
+        exec(code, ns)
         self.func = ns['run']
 
     def time_op(self, indexes, sel, op):
index 439cd422f5fc8f123dbdc66a58a022d7ed8cb5e8..d5ce9a271cba17cd2b04e160164f4addc3014a9a 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark, get_squares
 
 import numpy as np
diff --git a/benchmarks/benchmarks/bench_itemselection.py b/benchmarks/benchmarks/bench_itemselection.py
new file mode 100644 (file)
index 0000000..27fc49e
--- /dev/null
@@ -0,0 +1,45 @@
+from __future__ import absolute_import, division, print_function
+
+from .common import Benchmark, TYPES1
+
+import numpy as np
+
+
+class Take(Benchmark):
+    params = [
+        [(1000, 1), (1000, 2), (2, 1000, 1), (1000, 3)],
+        ["raise", "wrap", "clip"],
+        TYPES1]
+    param_names = ["shape", "mode", "dtype"]
+
+    def setup(self, shape, mode, dtype):
+        self.arr = np.ones(shape, dtype)
+        self.indices = np.arange(1000)
+
+    def time_contiguous(self, shape, mode, dtype):
+        self.arr.take(self.indices, axis=-2, mode=mode)
+
+
+class PutMask(Benchmark):
+    params = [
+        [True, False],
+        TYPES1]
+    param_names = ["values_is_scalar", "dtype"]
+
+    def setup(self, values_is_scalar, dtype):
+        if values_is_scalar:
+            self.vals = np.array(1., dtype=dtype)
+        else:
+            self.vals = np.ones(1000, dtype=dtype)
+
+        self.arr = np.ones(1000, dtype=dtype)
+
+        self.dense_mask = np.ones(1000, dtype="bool")
+        self.sparse_mask = np.zeros(1000, dtype="bool")
+
+    def time_dense(self, values_is_scalar, dtype):
+        np.putmask(self.arr, self.dense_mask, self.vals)
+
+    def time_sparse(self, values_is_scalar, dtype):
+        np.putmask(self.arr, self.sparse_mask, self.vals)
+
index f65a96dadd3a1ebbf928b379867ebfa0b8f61f86..c22ceaa5e42fb2ab389bfd078276c52aaa3968bb 100644 (file)
@@ -1,8 +1,6 @@
 """Benchmarks for `numpy.lib`."""
 
 
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark
 
 import numpy as np
index 5c44162a23cfeafabc7b939614c891a7a1316e44..3abbe36705c6c5f35d49fca927796ada03ba27f0 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark, get_squares_, get_indexes_rand, TYPES1
 
 import numpy as np
index aff78df0a5aa49c6e7afee93832873bf660a327f..b214c0b86519776275ac79df22fd46825ccbec96 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark
 
 import numpy as np
index 58572d07d05066112e56bc41cca6af956e2b65fe..e449517851ecf1f4d3146c099d5f9cce906ff35b 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark
 
 try:
@@ -35,7 +33,7 @@ def mock_concatenate(arrays, axis=0, out=None):
     pass
 
 
-class DuckArray(object):
+class DuckArray:
     def __array_function__(self, func, types, args, kwargs):
         pass
 
index c52b463e57976a8ec3bce5dab8cd50766d4b2a6f..9482eb04de97777831ddc9df324acb9abdbda39e 100644 (file)
@@ -1,11 +1,7 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark
 
 import numpy as np
 
-from numpy.random import RandomState
-
 try:
     from numpy.random import Generator
 except ImportError:
index 41a6dd775bb44a443843a24f6c48b91a881e1f96..2d9c104d2904da061bd72bebd5a05f782e3c6852 100644 (file)
@@ -1,6 +1,3 @@
-from __future__ import absolute_import, division, print_function
-import os
-
 from .common import Benchmark
 
 import numpy as np
index 0043d5357575a3e47bb73d355eb0a3062f7281b4..76c573a51963c96a768ed78065b65733c2cec7b6 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark, TYPES1, get_squares
 
 import numpy as np
index 187b923cd27aeb2e11a6b590c36440c4eadf0064..0c7dc4e728eca11bec37fa09c44d44bf03a3e2cd 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark
 
 import numpy as np
index 62e70782d1f70cc58c4d4a9cfe42165b75f6015e..9f45a72575ff88edd85b6465a9f32ececcb396fb 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 from .common import Benchmark, get_squares_
 
 import numpy as np
@@ -152,7 +150,7 @@ class Scalar(Benchmark):
         (self.y + self.z)
 
 
-class ArgPack(object):
+class ArgPack:
     __slots__ = ['args', 'kwargs']
     def __init__(self, *args, **kwargs):
         self.args = args
index 18a09fd405519488d0276f22dbc41851ecf2fbe9..3fd81a1648d041425118656510c1c1e3bad0eb28 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 import numpy
 import random
 
@@ -112,5 +110,5 @@ def get_indexes_rand_():
     return indexes_rand_
 
 
-class Benchmark(object):
+class Benchmark:
     goal_time = 0.25
index bcef82500ba443cd569d5d7fc3a5c84682c6e229..15073f75472beed633f3733371c7a63b1c923697 100644 (file)
@@ -59,7 +59,7 @@ SciPy pure Python package example
 
 Below is an example of a minimal ``setup.py`` file for a pure SciPy package::
 
-  #!/usr/bin/env python
+  #!/usr/bin/env python3
   def configuration(parent_package='',top_path=None):
       from numpy.distutils.misc_util import Configuration
       config = Configuration('mypackage',parent_package,top_path)
@@ -345,7 +345,7 @@ expression, '<...>' will be replaced first with item1, and then with
 item2, and so forth until N repeats are accomplished. Once a named
 repeat specification has been introduced, the same repeat rule may be
 used **in the current block** by referring only to the name
-(i.e. <rule1>.
+(i.e. <rule1>).
 
 
 Short repeat rule
@@ -577,9 +577,6 @@ The header of a typical SciPy ``__init__.py`` is::
   Package docstring, typically with a brief description and function listing.
   """
 
-  # py3k related imports
-  from __future__ import division, print_function, absolute_import
-
   # import functions into module namespace
   from .subpackage import *
   ...
index ff56c6d787ebfae9beeab616f7d5b8a9e3348a14..6af8d9ca6dddaa7ad5c407ffcc29cddf1600b9a4 100644 (file)
@@ -3,101 +3,112 @@ NumPy.
 
 Current build and release info
 ==============================
-
 The current info on building and releasing NumPy and SciPy is scattered in
 several places. It should be summarized in one place, updated, and where
 necessary described in more detail. The sections below list all places where
 useful info can be found.
 
+
 Source tree
 -----------
-* INSTALL.rst.txt
-* release.sh
-* pavement.py
+- INSTALL.rst.txt
+- release.sh
+- pavement.py
+
 
 NumPy Docs
 ----------
-* https://github.com/numpy/numpy/blob/master/doc/HOWTO_RELEASE.rst.txt
-* http://projects.scipy.org/numpy/wiki/MicrosoftToolchainSupport (dead link)
+- https://github.com/numpy/numpy/blob/master/doc/HOWTO_RELEASE.rst.txt
+- http://projects.scipy.org/numpy/wiki/MicrosoftToolchainSupport (dead link)
+
 
 SciPy.org wiki
 --------------
-* https://www.scipy.org/Installing_SciPy and links on that page.
-* http://new.scipy.org/building/windows.html (dead link)
+- https://www.scipy.org/Installing_SciPy and links on that page.
+- http://new.scipy.org/building/windows.html (dead link)
+
 
 Doc wiki
 --------
-* http://docs.scipy.org/numpy/docs/numpy-docs/user/install.rst/ (dead link)
+- http://docs.scipy.org/numpy/docs/numpy-docs/user/install.rst/ (dead link)
+
 
 Release Scripts
 ---------------
-* https://github.com/numpy/numpy-vendor
+- https://github.com/numpy/numpy-vendor
+
 
 Supported platforms and versions
 ================================
-
-Python 2.7 and >=3.4 are the currently supported versions when building from
-source.  We test NumPy against all these versions every time we merge code to
-master.  Binary installers may be available for a subset of these versions (see
-below).
+`NEP 29`_ outlines which Python versions are supported; For the first half of
+2020, this will be Python >= 3.6. We test NumPy against all these versions
+every time we merge code to master.  Binary installers may be available for a
+subset of these versions (see below).
 
 OS X
 ----
-
-Python 2.7 and >=3.4 are the versions for which we provide binary installers.
-OS X versions >= 10.6 are supported.  We build binary wheels for OSX that are
-compatible with Python.org Python, system Python, homebrew and macports - see
-this `OSX wheel building summary
+OS X versions >= 10.9 are supported, for Python version support see `NEP 29`_.
+We build binary wheels for OSX that are compatible with Python.org Python,
+system Python, homebrew and macports - see this `OSX wheel building summary
 <https://github.com/MacPython/wiki/wiki/Spinning-wheels>`_ for details.
 
+
 Windows
 -------
+We build 32- and 64-bit wheels on Windows. Windows 7, 8 and 10 are supported.
+We build NumPy using the `mingw-w64 toolchain`_ on Appveyor.
 
-We build 32- and 64-bit wheels for Python 2.7, 3.4, 3.5 on Windows. Windows
-XP, Vista, 7, 8 and 10 are supported.  We build NumPy using the MSVC compilers
-on Appveyor, but we are hoping to update to a `mingw-w64 toolchain
-<https://mingwpy.github.io>`_.  The Windows wheels use ATLAS for BLAS / LAPACK.
 
 Linux
 -----
-
 We build and ship `manylinux1 <https://www.python.org/dev/peps/pep-0513>`_
 wheels for NumPy.  Many Linux distributions include their own binary builds
 of NumPy.
 
+
 BSD / Solaris
 -------------
-
 No binaries are provided, but successful builds on Solaris and BSD have been
 reported.
 
+
 Tool chain
 ==========
-
 We build all our wheels on cloud infrastructure - so this list of compilers is
 for information and debugging builds locally.  See the ``.travis.yml`` and
 ``appveyor.yml`` scripts in the `numpy wheels`_ repo for the definitive source
 of the build recipes. Packages that are available using pip are noted.
 
+
 Compilers
 ---------
-
 The same gcc version is used as the one with which Python itself is built on
 each platform. At the moment this means:
 
-* OS X builds on travis currently use `clang`.  It appears that binary wheels
+- OS X builds on travis currently use `clang`.  It appears that binary wheels
   for OSX >= 10.6 can be safely built from the travis-ci OSX 10.9 VMs
   when building against the Python from the Python.org installers;
-* Windows builds use the MSVC version corresponding to the Python being built
-  against;
-* Manylinux1 wheels use the gcc provided on the Manylinux docker images.
+- Windows builds use the `mingw-w64 toolchain`_;
+- Manylinux1 wheels use the gcc provided on the Manylinux docker images.
 
 You will need Cython for building the binaries.  Cython compiles the ``.pyx``
 files in the NumPy distribution to ``.c`` files.
 
+.. _mingw-w64 toolchain : https://mingwpy.github.io
+.. _NEP 29 : https://numpy.org/neps/nep-0029-deprecation_policy.html
+
+OpenBLAS
+------------
+All the wheels link to a version of OpenBLAS_ supplied via the openblas-libs_ repo.
+The shared object (or DLL) is shipped with in the wheel, renamed to prevent name
+collisions with other OpenBLAS shared objects that may exist in the filesystem.
+
+.. _OpenBLAS: https://github.com/xianyi/OpenBLAS
+.. _openblas-libs: https://github.com/MacPython/openblas-libs
+
+
 Building source archives and wheels
 -----------------------------------
-
 You will need write permission for numpy-wheels in order to trigger wheel
 builds.
 
@@ -111,37 +122,36 @@ builds.
 
 Building docs
 -------------
-
 Building the documents requires a number of latex ``.sty`` files. Install them
 all to avoid aggravation.
 
-* Sphinx (pip)
-* numpydoc (pip)
-* Matplotlib
-* Texlive (or MikTeX on Windows)
+- Sphinx (pip)
+- numpydoc (pip)
+- Matplotlib
+- Texlive (or MikTeX on Windows)
+
 
 Uploading to PyPI
 -----------------
+- terryfy `<https://github.com/MacPython/terryfy>`_ (clone).
+- beautifulsoup4 (pip)
+- delocate (pip)
+- auditwheel (pip)
+- twine (pip)
 
-* terryfy `<https://github.com/MacPython/terryfy>`_ (clone).
-* beautifulsoup4 (pip)
-* delocate (pip)
-* auditwheel (pip)
-* twine (pip)
 
 Generating author/pr lists
 --------------------------
-
 You will need a personal access token
 `<https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/>`_
 so that scripts can access the github NumPy repository.
 
-* gitpython (pip)
-* pygithub (pip)
+- gitpython (pip)
+- pygithub (pip)
+
 
 Virtualenv
 ----------
-
 Virtualenv is a very useful tool to keep several versions of packages around.
 It is also used in the Paver script to build the docs.
 
@@ -151,27 +161,28 @@ What is released
 
 Wheels
 ------
+We currently support Python 3.6-3.8 on Windows, OSX, and Linux
 
-* Windows wheels for Python 2.7, 3.4, 3.5, for 32- and 64-bit, built using
-  Appveyor;
-* Dual architecture OSX wheels built via travis-ci;
-* 32- and 64-bit Manylinux1 wheels built via travis-ci.
+* Windows: 32-bit and 64-bit wheels built using Appveyor;
+* OSX: x64_86 OSX wheels built using travis-ci;
+* Linux: 32-bit and 64-bit Manylinux1 wheels built using travis-ci.
 
 See the `numpy wheels`_ building repository for more detail.
 
 .. _numpy wheels : https://github.com/MacPython/numpy-wheels
 
+
 Other
 -----
+- Release Notes
+- Changelog
 
-* Release Notes
-* Changelog
 
 Source distribution
 -------------------
-
 We build source releases in both .zip and .tar.gz formats.
 
+
 Release process
 ===============
 
@@ -184,6 +195,7 @@ After a date is set, create a new maintenance/x.y.z branch, add new empty
 release notes for the next version in the master branch and update the Trac
 Milestones.
 
+
 Make sure current branch builds a package correctly
 ---------------------------------------------------
 ::
@@ -199,6 +211,7 @@ best to read the pavement.py script.
 .. note:: The following steps are repeated for the beta(s), release
    candidates(s) and the final release.
 
+
 Check deprecations
 ------------------
 Before the release branch is made, it should be checked that all deprecated
@@ -246,6 +259,7 @@ There are three steps to the process.
 The C ABI version number in numpy/core/setup_common.py should only be
 updated for a major release.
 
+
 Check the release notes
 -----------------------
 Use `towncrier`_ to build the release note and
@@ -270,6 +284,7 @@ following:
 
 .. _towncrier: https://github.com/hawkowl/towncrier
 
+
 Update the release status and create a release "tag"
 ----------------------------------------------------
 Identify the commit hash of the release, e.g. 1b2e1d63ff.
@@ -327,12 +342,6 @@ to public keyservers, with a command such as::
 
     gpg --send-keys <yourkeyid>
 
-Apply patch to fix bogus strides
---------------------------------
-NPY_RELAXED_STRIDE_CHECKING was made the default in NumPy 1.10.0 and bogus
-strides are used in the development branch to smoke out problems. The
-`patch <https://github.com/numpy/numpy/pull/5996>`_ should be updated if
-necessary and applied to the release branch to rationalize the strides.
 
 Update the version of the master branch
 ---------------------------------------
@@ -342,44 +351,39 @@ Increment the release number in setup.py. Release candidates should have "rc1"
 Also create a new version hash in cversions.txt and a corresponding version
 define NPY_x_y_API_VERSION in numpyconfig.h
 
-Trigger the wheel builds on travis-ci and Appveyor
---------------------------------------------------
 
-See the `numpy wheels` repository.
+Trigger the wheel builds
+------------------------
+See the `MacPython/numpy wheels` repository.
 
 In that repository edit the files:
 
-* ``.travis.yml``;
-* ``appveyor.yml``.
+- ``azure/posix.yml``
+- ``azure/windows.yml``.
 
 In both cases, set the ``BUILD_COMMIT`` variable to the current release tag -
-e.g. ``v1.11.1``.
-
-Make sure that the release tag has been pushed.
+e.g. ``v1.19.0``::
 
-Trigger a build by doing a commit of your edits to ``.travis.yml`` and
-``appveyor.yml`` to the repository::
+    $ gvim azure/posix.yml azure/windows.yml
+    $ git commit -a
+    $ git push upstream HEAD
 
-    cd /path/to/numpy-wheels
-    # Edit .travis.yml, appveyor.yml
-    git commit
-    git push
-
-The wheels, once built, appear at a Rackspace container pointed at by:
+Make sure that the release tag has been pushed.
 
-* http://wheels.scipy.org
-* https://3f23b170c54c2533c070-1c8a9b3114517dc5fe17b7c3f8c63a43.ssl.cf2.rackcdn.com
+Trigger a build by pushing a commit of your edits to the repository. Note that
+you can do this on a branch, but it must be pushed upstream to the
+``MacPython/numpy-wheels`` repository to trigger uploads since only
+that repo has the appropriate tokens to allow uploads.
 
-The HTTP address may update first, and you should wait 15 minutes after the
-build finishes before fetching the binaries.
+The wheels, once built, appear at https://anaconda.org/multibuild-wheels-staging/numpy
 
 Make the release
 ----------------
-
 Build the changelog and notes for upload with::
 
     paver write_release
 
+
 Build and archive documentation
 -------------------------------
 Do::
@@ -395,13 +399,13 @@ create an archive of the documentation in the numpy/doc repo::
     make merge-doc
     # Now edit the ``index.html`` file in the repo to reflect the new content,
     # and commit the changes
-    git -C dist/merge commit -a "Add documentation for <version>"
+    git -C build/merge commit -am "Add documentation for <version>"
     # Push to numpy/doc repo
-    git -C push
+    git -C build/merge push
+
 
 Update PyPI
 -----------
-
 The wheels and source should be uploaded to PyPI.
 
 You should upload the wheels first, and the source formats last, to make sure
@@ -413,7 +417,7 @@ https://github.com/MacPython/terryfy.  Here is the recommended incantation for
 downloading all the Windows, Manylinux, OSX wheels and uploading to PyPI. ::
 
     NPY_WHLS=~/wheelhouse   # local directory to cache wheel downloads
-    CDN_URL=https://3f23b170c54c2533c070-1c8a9b3114517dc5fe17b7c3f8c63a43.ssl.cf2.rackcdn.com
+    CDN_URL=https://anaconda.org/multibuild-wheels-staging/numpy/files
     wheel-uploader -u $CDN_URL -w $NPY_WHLS -v -s -t win numpy 1.11.1rc1
     wheel-uploader -u $CDN_URL -w warehouse -v -s -t macosx numpy 1.11.1rc1
     wheel-uploader -u $CDN_URL -w warehouse -v -s -t manylinux1 numpy 1.11.1rc1
@@ -438,9 +442,9 @@ interface.
 
 .. _push-tag-and-commit:
 
+
 Push the release tag and commit
 -------------------------------
-
 Finally, now you are confident this tag correctly defines the source code that
 you released you can push the tag and release commit up to github::
 
@@ -450,18 +454,18 @@ you released you can push the tag and release commit up to github::
 where ``upstream`` points to the main https://github.com/numpy/numpy.git
 repository.
 
+
 Update scipy.org
 ----------------
-
 A release announcement with a link to the download site should be placed in the
 sidebar of the front page of scipy.org.
 
 The scipy.org should be a PR at https://github.com/scipy/scipy.org. The file
 that needs modification is ``www/index.rst``. Search for ``News``.
 
+
 Announce to the lists
 ---------------------
-
 The release should be announced on the mailing lists of
 NumPy and SciPy, to python-announce, and possibly also those of
 Matplotlib, IPython and/or Pygame.
@@ -470,12 +474,13 @@ During the beta/RC phase, an explicit request for testing the binaries with
 several other libraries (SciPy/Matplotlib/Pygame) should be posted on the
 mailing list.
 
+
 Announce to Linux Weekly News
 -----------------------------
-
 Email the editor of LWN to let them know of the release.  Directions at:
 https://lwn.net/op/FAQ.lwn#contact
 
+
 After the final release
 -----------------------
 After the final release is announced, a few administrative tasks are left to be
index 3c32cb811943f84cdf935d661e5fa3b80c46548a..31bd96a9c35090afbbf421a0db523bc36eaf0f45 100644 (file)
@@ -103,11 +103,11 @@ dist: build/dist.tar.gz
 build/dist.tar.gz:
        make $(DIST_VARS) real-dist
 
-real-dist: dist-build html-build html-scipyorg
+real-dist: dist-build html-build
        test -d build/latex || make latex-build
        make -C build/latex all-pdf
        -rm -rf build/dist
-       cp -r build/html-scipyorg build/dist
+       cp -r build/html build/dist
        cd build/html && zip -9r ../dist/numpy-html.zip .
        cp build/latex/numpy-ref.pdf build/dist
        cp build/latex/numpy-user.pdf build/dist
@@ -158,7 +158,7 @@ endif
        @# the instructions in doc/HOWTO_RELEASE.rst.txt
        @echo " "
        @echo New documentation archive added to ./build/merge.
-       @echo Now add/modify the appropiate section after
+       @echo Now add/modify the appropriate section after
        @echo "    <!-- insert here -->"
        @echo in build/merge/index.html,
        @echo then \"git commit\", \"git push\"
@@ -217,7 +217,7 @@ latex-build: generate
        mkdir -p build/latex build/doctrees
        $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) build/latex $(FILES)
        $(PYTHON) postprocess.py tex build/latex/*.tex
-       perl -pi -e 's/\t(latex.*|pdflatex) (.*)/\t-$$1 -interaction batchmode $$2/' build/latex/Makefile
+       perl -pi -e 's/LATEXOPTS =/LATEXOPTS ?= --halt-on-error/' build/latex/Makefile
        @echo
        @echo "Build finished; the LaTeX files are in build/latex."
        @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
index b23536ca535c15c535d241f946ee79cf05e779ba..cde0394ddab6a2ec5fe6a75024d9d9b18c0e1dff 100644 (file)
@@ -355,9 +355,7 @@ The Py2/Py3 compatible structure definition looks like::
        (binaryfunc)0,               /*nb_true_divide*/
        0,                           /*nb_inplace_floor_divide*/
        0,                           /*nb_inplace_true_divide*/
-    #if PY_VERSION_HEX >= 0x02050000
        (unaryfunc)NULL,             /*nb_index*/
-    #endif
     };
 
 
@@ -394,14 +392,6 @@ There are a couple of places that need further attention:
   In some cases, this returns a buffer object on Python 2. On Python 3,
   there is no stand-alone buffer object, so we return a byte array instead.
 
-- multiarray.int_asbuffer
-
-  Converts an integer to a void* pointer -- in Python.
-
-  Should we just remove this for Py3? It doesn't seem like it is used
-  anywhere, and it doesn't sound very useful.
-
-
 The Py2/Py3 compatible PyBufferMethods definition looks like::
 
     NPY_NO_EXPORT PyBufferProcs array_as_buffer = {
@@ -428,10 +418,6 @@ The Py2/Py3 compatible PyBufferMethods definition looks like::
 
    Produce PEP 3118 format strings for array scalar objects.
 
-.. todo::
-
-   Figure out what to do with int_asbuffer
-
 .. todo::
 
    There's stuff to clean up in numarray/_capi.c
index 0a761e350b434aac54c4963f864b90511784054d..0ff9ff93352a21ea3f2344cfd48a5d540bfd6e0d 100644 (file)
@@ -1,7 +1,10 @@
-This file contains a walkthrough of the NumPy 1.14.5 release on Linux.
+This file contains a walkthrough of the NumPy 1.14.5 release on Linux, modified
+for building on azure and uploading to anaconda.org
 The commands can be copied into the command line, but be sure to
 replace 1.14.5 by the correct version.
 
+This should be read together with the general directions in `releasing`.
+
 
 Release  Walkthrough
 ====================
@@ -65,7 +68,6 @@ Edit pavement.py and setup.py as detailed in HOWTO_RELEASE::
 
 Sanity check::
 
-    $ python runtests.py -m "full"  # NumPy < 1.17 only
     $ python3 runtests.py -m "full"
 
 Push this release directly onto the end of the maintenance branch. This
@@ -91,7 +93,7 @@ Build wheels
 ------------
 
 Trigger the wheels build by pointing the numpy-wheels repository at this
-commit. This can take a while. The numpy-wheels repository is cloned from
+commit. This can take up to an hour. The numpy-wheels repository is cloned from
 `<https://github.com/MacPython/numpy-wheels>`_. Start with a pull as the repo
 may have been accessed and changed by someone else and a push will fail::
 
@@ -100,25 +102,26 @@ may have been accessed and changed by someone else and a push will fail::
     $ git branch <new version>  # only when starting new numpy version
     $ git checkout v1.14.x  # v1.14.x already existed for the 1.14.4 release
 
-Edit the ``.travis.yml`` and ``.appveyor.yml`` files to make sure they have the
-correct version, and put in the commit hash for the ``REL`` commit created
-above for ``BUILD_COMMIT``, see the _example from `v1.14.3`::
+Edit the ``azure/posix.yml`` and ``azure/windows.yml`` files to make sure they
+have the correct version, and put in the commit hash for the ``REL`` commit
+created above for ``BUILD_COMMIT``, see an _example::
 
-    $ gvim .travis.yml .appveyor.yml
+    $ gvim azure/posix.yml azure/windows.yml
     $ git commit -a
     $ git push upstream HEAD
 
 Now wait. If you get nervous at the amount of time taken -- the builds can take
-several hours-- you can check the build progress by following the links
-provided at `<https://github.com/MacPython/numpy-wheels>`_ to check the travis
-and appveyor build status. Check if all the needed wheels have been built and
-uploaded before proceeding. There should currently be 22 of them at
-`<https://wheels.scipy.org>`_, 4 for Mac, 8 for Windows, and 10 for Linux.
-Note that sometimes builds, like tests, fail for unrelated reasons and you will
-need to restart them.
+a while -- you can check the build progress by following the links
+provided at `<https://github.com/MacPython/numpy-wheels>`_ to check the 
+build status. Check if all the needed wheels have been built and
+uploaded before proceeding. There should currently be 21 of them at
+`<https://anaconda.org/multibuild-wheels-staging/numpy/files>`_, 3 for Mac, 6
+for Windows, and 12 for Linux.
 
-.. example_: https://github.com/MacPython/numpy-wheels/commit/fed9c04629c155e7804282eb803d81097244598d
+.. example_: https://github.com/MacPython/numpy-wheels/pull/80/commits/cbf4af4
 
+Note that sometimes builds, like tests, fail for unrelated reasons and
+you will need to restart them.
 
 Download wheels
 ---------------
@@ -132,7 +135,7 @@ upload later using ``twine``::
 
     $ cd ../terryfy
     $ git pull upstream master
-    $ CDN_URL=https://3f23b170c54c2533c070-1c8a9b3114517dc5fe17b7c3f8c63a43.ssl.cf2.rackcdn.com
+    $ CDN_URL=https://anaconda.org/multibuild-wheels-staging/numpy/files
     $ NPY_WHLS=../numpy/release/installers
     $ ./wheel-uploader -u $CDN_URL -n -v -w $NPY_WHLS -t win numpy 1.14.5
     $ ./wheel-uploader -u $CDN_URL -n -v -w $NPY_WHLS -t manylinux1 numpy 1.14.5
@@ -182,9 +185,9 @@ Add another ``REL`` commit to the numpy maintenance branch, which resets the
 
 Create release notes for next release and edit them to set the version::
 
-    $ cp doc/release/template.rst doc/release/1.14.6-notes.rst
-    $ gvim doc/release/1.14.6-notes.rst
-    $ git add doc/release/1.14.6-notes.rst
+    $ cp doc/source/release/template.rst doc/source/release/1.14.6-notes.rst
+    $ gvim doc/source/release/1.14.6-notes.rst
+    $ git add doc/source/release/1.14.6-notes.rst
 
 Add new release notes to the documentation release list::
 
@@ -295,6 +298,15 @@ python-announce-list is BCC so that replies will not be sent to that list.
 Post-Release Tasks
 ------------------
 
-Forward port the documentation changes ``doc/release/1.14.5-notes.rst``,
-``doc/changelog/1.14.5-changelog.rst`` and add the release note to
-``doc/source/release.rst``.
+Checkout master and forward port the documentation changes::
+
+    $ git checkout -b update-after-1.14.5-release
+    $ git checkout maintenance/1.14.x doc/source/release/1.14.5-notes.rst
+    $ git checkout maintenance/1.14.x doc/changelog/1.14.5-changelog.rst
+    $ gvim doc/source/release.rst  # Add link to new notes
+    $ git add doc/changelog/1.14.5-changelog.rst doc/source/release/1.14.5-notes.rst
+    $ git status  # check status before commit
+    $ git commit -a -m"REL: Update master after 1.14.5 release."
+    $ git push origin HEAD
+
+Go to github and make a PR.
index 14cb28df8cefe93bdc41bcf380831905987a31c7..af47fe99c4db7fad3a2da9d33a58406d0cd8375b 100644 (file)
@@ -119,7 +119,7 @@ that makes it hard to identify the test from the output of running the test
 suite with ``verbose=2`` (or similar verbosity setting).  Use plain comments
 (``#``) if necessary.
 
-Labeling tests 
+Labeling tests
 --------------
 
 As an alternative to ``pytest.mark.<label>``, there are a number of labels you
@@ -174,7 +174,7 @@ name; thus::
       print 'doing teardown'
 
 
-  class TestMe(object):
+  class TestMe:
       def setup():
           """Class-level setup"""
           print 'doing setup'
@@ -256,7 +256,7 @@ section of your setup.py::
   ...
   def configuration(parent_package='', top_path=None):
       ...
-      config.add_data_dir('tests')
+      config.add_subpackage('tests')
       return config
   ...
 
@@ -360,7 +360,17 @@ deterministic by setting the random number seed before generating it.  Use
 either Python's ``random.seed(some_number)`` or NumPy's
 ``numpy.random.seed(some_number)``, depending on the source of random numbers.
 
+Alternatively, you can use `Hypothesis`_ to generate arbitrary data.
+Hypothesis manages both Python's and Numpy's random seeds for you, and
+provides a very concise and powerful way to describe data (including
+``hypothesis.extra.numpy``, e.g. for a set of mutually-broadcastable shapes).
+
+The advantages over random generation include tools to replay and share
+failures without requiring a fixed seed, reporting *minimal* examples for
+each failure, and better-than-naive-random techniques for triggering bugs.
+
 
 .. _nose: https://nose.readthedocs.io/en/latest/
 .. _pytest: https://pytest.readthedocs.io
 .. _parameterization: https://docs.pytest.org/en/latest/parametrize.html
+.. _Hypothesis: https://hypothesis.readthedocs.io/en/latest/
index 886a3440e25a060a8d76a2d90d07e7a0ae896ca8..c9c386e4ebcd32577553c90978a303d1a8de0760 100644 (file)
-# Doxyfile 1.6.3
-
-# This file describes the settings to be used by the documentation system
-# doxygen (www.doxygen.org) for a project
-#
-# All text after a hash (#) is considered a comment and will be ignored
-# The format is:
-#       TAG = value [value, ...]
-# For lists items can also be appended using:
-#       TAG += value [value, ...]
-# Values that contain spaces should be placed between quotes (" ")
-
-#---------------------------------------------------------------------------
-# Project related configuration options
-#---------------------------------------------------------------------------
-
-# This tag specifies the encoding used for all characters in the config file 
-# that follow. The default is UTF-8 which is also the encoding used for all 
-# text before the first occurrence of this tag. Doxygen uses libiconv (or the 
-# iconv built into libc) for the transcoding. See 
-# https://www.gnu.org/software/libiconv for the list of possible encodings.
-
-DOXYFILE_ENCODING      = UTF-8
-
-# The PROJECT_NAME tag is a single word (or a sequence of words surrounded 
-# by quotes) that should identify the project.
-
+# Doxyfile for NumPy C API
+# See http://www.doxygen.nl/manual/config.html
 PROJECT_NAME           = numpy
-
-# The PROJECT_NUMBER tag can be used to enter a project or revision number. 
-# This could be handy for archiving the generated documentation or 
-# if some version control system is used.
-
 PROJECT_NUMBER         = 2.0.0
-
-# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) 
-# base path where the generated documentation will be put. 
-# If a relative path is entered, it will be relative to the location 
-# where doxygen was started. If left blank the current directory will be used.
-
 OUTPUT_DIRECTORY       = build
-
-# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 
-# 4096 sub-directories (in 2 levels) under the output directory of each output 
-# format and will distribute the generated files over these directories. 
-# Enabling this option can be useful when feeding doxygen a huge amount of 
-# source files, where putting all generated files in the same directory would 
-# otherwise cause performance problems for the file system.
-
-CREATE_SUBDIRS         = NO
-
-# The OUTPUT_LANGUAGE tag is used to specify the language in which all 
-# documentation generated by doxygen is written. Doxygen will use this 
-# information to generate all constant output in the proper language. 
-# The default language is English, other supported languages are: 
-# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, 
-# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, 
-# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English 
-# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, 
-# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak, 
-# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
-
-OUTPUT_LANGUAGE        = English
-
-# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will 
-# include brief member descriptions after the members that are listed in 
-# the file and class documentation (similar to JavaDoc). 
-# Set to NO to disable this.
-
-BRIEF_MEMBER_DESC      = YES
-
-# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend 
-# the brief description of a member or function before the detailed description. 
-# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the 
-# brief descriptions will be completely suppressed.
-
-REPEAT_BRIEF           = YES
-
-# This tag implements a quasi-intelligent brief description abbreviator 
-# that is used to form the text in various listings. Each string 
-# in this list, if found as the leading text of the brief description, will be 
-# stripped from the text and the result after processing the whole list, is 
-# used as the annotated text. Otherwise, the brief description is used as-is. 
-# If left blank, the following values are used ("$name" is automatically 
-# replaced with the name of the entity): "The $name class" "The $name widget" 
-# "The $name file" "is" "provides" "specifies" "contains" 
-# "represents" "a" "an" "the"
-
-ABBREVIATE_BRIEF       = "The $name class" \
-                         "The $name widget" \
-                         "The $name file" \
-                         is \
-                         provides \
-                         specifies \
-                         contains \
-                         represents \
-                         a \
-                         an \
-                         the
-
-# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then 
-# Doxygen will generate a detailed section even if there is only a brief 
-# description.
-
-ALWAYS_DETAILED_SEC    = NO
-
-# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all 
-# inherited members of a class in the documentation of that class as if those 
-# members were ordinary class members. Constructors, destructors and assignment 
-# operators of the base classes will not be shown.
-
-INLINE_INHERITED_MEMB  = NO
-
-# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full 
-# path before files name in the file list and in the header files. If set 
-# to NO the shortest path that makes the file name unique will be used.
-
-FULL_PATH_NAMES        = YES
-
-# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag 
-# can be used to strip a user-defined part of the path. Stripping is 
-# only done if one of the specified strings matches the left-hand part of 
-# the path. The tag can be used to show relative paths in the file list. 
-# If left blank the directory from which doxygen is run is used as the 
-# path to strip.
-
 STRIP_FROM_PATH        = ../../numpy/core
-
-# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of 
-# the path mentioned in the documentation of a class, which tells 
-# the reader which header file to include in order to use a class. 
-# If left blank only the name of the header file containing the class 
-# definition is used. Otherwise one should specify the include paths that 
-# are normally passed to the compiler using the -I flag.
-
-STRIP_FROM_INC_PATH    = 
-
-# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter 
-# (but less readable) file names. This can be useful is your file systems 
-# doesn't support long names like on DOS, Mac, or CD-ROM.
-
-SHORT_NAMES            = NO
-
-# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen 
-# will interpret the first line (until the first dot) of a JavaDoc-style 
-# comment as the brief description. If set to NO, the JavaDoc 
-# comments will behave just like regular Qt-style comments 
-# (thus requiring an explicit @brief command for a brief description.)
-
-JAVADOC_AUTOBRIEF      = NO
-
-# If the QT_AUTOBRIEF tag is set to YES then Doxygen will 
-# interpret the first line (until the first dot) of a Qt-style 
-# comment as the brief description. If set to NO, the comments 
-# will behave just like regular Qt-style comments (thus requiring 
-# an explicit \brief command for a brief description.)
-
-QT_AUTOBRIEF           = NO
-
-# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen 
-# treat a multi-line C++ special comment block (i.e. a block of //! or /// 
-# comments) as a brief description. This used to be the default behaviour. 
-# The new default is to treat a multi-line C++ comment block as a detailed 
-# description. Set this tag to YES if you prefer the old behaviour instead.
-
-MULTILINE_CPP_IS_BRIEF = NO
-
-# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented 
-# member inherits the documentation from any documented member that it 
-# re-implements.
-
 INHERIT_DOCS           = YES
-
-# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce 
-# a new page for each member. If set to NO, the documentation of a member will 
-# be part of the file/class/namespace that contains it.
-
-SEPARATE_MEMBER_PAGES  = NO
-
-# The TAB_SIZE tag can be used to set the number of spaces in a tab. 
-# Doxygen uses this value to replace tabs by spaces in code fragments.
-
 TAB_SIZE               = 8
-
-# This tag can be used to specify a number of aliases that acts 
-# as commands in the documentation. An alias has the form "name=value". 
-# For example adding "sideeffect=\par Side Effects:\n" will allow you to 
-# put the command \sideeffect (or @sideeffect) in the documentation, which 
-# will result in a user-defined paragraph with heading "Side Effects:". 
-# You can put \n's in the value part of an alias to insert newlines.
-
-ALIASES                = 
-
-# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C 
-# sources only. Doxygen will then generate output that is more tailored for C. 
-# For instance, some of the names that are used will be different. The list 
-# of all members will be omitted, etc.
-
 OPTIMIZE_OUTPUT_FOR_C  = YES
-
-# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java 
-# sources only. Doxygen will then generate output that is more tailored for 
-# Java. For instance, namespaces will be presented as packages, qualified 
-# scopes will look different, etc.
-
-OPTIMIZE_OUTPUT_JAVA   = NO
-
-# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran 
-# sources only. Doxygen will then generate output that is more tailored for 
-# Fortran.
-
-OPTIMIZE_FOR_FORTRAN   = NO
-
-# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL 
-# sources. Doxygen will then generate output that is tailored for 
-# VHDL.
-
-OPTIMIZE_OUTPUT_VHDL   = NO
-
-# Doxygen selects the parser to use depending on the extension of the files it parses. 
-# With this tag you can assign which parser to use for a given extension. 
-# Doxygen has a built-in mapping, but you can override or extend it using this tag. 
-# The format is ext=language, where ext is a file extension, and language is one of 
-# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP, 
-# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat 
-# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran), 
-# use: inc=Fortran f=C. Note that for custom extensions you also need to set
-# FILE_PATTERNS otherwise the files are not read by doxygen.
-
-EXTENSION_MAPPING      = 
-
-# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want 
-# to include (a tag file for) the STL sources as input, then you should 
-# set this tag to YES in order to let doxygen match functions declarations and 
-# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. 
-# func(std::string) {}). This also make the inheritance and collaboration 
-# diagrams that involve STL classes more complete and accurate.
-
-BUILTIN_STL_SUPPORT    = NO
-
-# If you use Microsoft's C++/CLI language, you should set this option to YES to 
-# enable parsing support.
-
-CPP_CLI_SUPPORT        = NO
-
-# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. 
-# Doxygen will parse them like normal C++ but will assume all classes use public 
-# instead of private inheritance when no explicit protection keyword is present.
-
-SIP_SUPPORT            = NO
-
-# For Microsoft's IDL there are propget and propput attributes to indicate getter 
-# and setter methods for a property. Setting this option to YES (the default) 
-# will make doxygen to replace the get and set methods by a property in the 
-# documentation. This will only work if the methods are indeed getting or 
-# setting a simple type. If this is not the case, or you want to show the 
-# methods anyway, you should set this option to NO.
-
-IDL_PROPERTY_SUPPORT   = YES
-
-# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC 
-# tag is set to YES, then doxygen will reuse the documentation of the first 
-# member in the group (if any) for the other members of the group. By default 
-# all members of a group must be documented explicitly.
-
-DISTRIBUTE_GROUP_DOC   = NO
-
-# Set the SUBGROUPING tag to YES (the default) to allow class member groups of 
-# the same type (for instance a group of public functions) to be put as a 
-# subgroup of that type (e.g. under the Public Functions section). Set it to 
-# NO to prevent subgrouping. Alternatively, this can be done per class using 
-# the \nosubgrouping command.
-
-SUBGROUPING            = YES
-
-# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum 
-# is documented as struct, union, or enum with the name of the typedef. So 
-# typedef struct TypeS {} TypeT, will appear in the documentation as a struct 
-# with name TypeT. When disabled the typedef will appear as a member of a file, 
-# namespace, or class. And the struct will be named TypeS. This can typically 
-# be useful for C code in case the coding convention dictates that all compound 
-# types are typedef'ed and only the typedef is referenced, never the tag name.
-
-TYPEDEF_HIDES_STRUCT   = NO
-
-# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to 
-# determine which symbols to keep in memory and which to flush to disk. 
-# When the cache is full, less often used symbols will be written to disk. 
-# For small to medium size projects (<1000 input files) the default value is 
-# probably good enough. For larger projects a too small cache size can cause 
-# doxygen to be busy swapping symbols to and from disk most of the time 
-# causing a significant performance penalty. 
-# If the system has enough physical memory increasing the cache will improve the 
-# performance by keeping more symbols in memory. Note that the value works on 
-# a logarithmic scale so increasing the size by one will roughly double the 
-# memory usage. The cache size is given by this formula: 
-# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, 
-# corresponding to a cache size of 2^16 = 65536 symbols
-
-SYMBOL_CACHE_SIZE      = 0
-
-#---------------------------------------------------------------------------
-# Build related configuration options
-#---------------------------------------------------------------------------
-
-# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in 
-# documentation are documented, even if no documentation was available. 
-# Private class members and static file members will be hidden unless 
-# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
-
 EXTRACT_ALL            = YES
-
-# If the EXTRACT_PRIVATE tag is set to YES all private members of a class 
-# will be included in the documentation.
-
 EXTRACT_PRIVATE        = YES
-
-# If the EXTRACT_STATIC tag is set to YES all static members of a file 
-# will be included in the documentation.
-
 EXTRACT_STATIC         = YES
-
-# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) 
-# defined locally in source files will be included in the documentation. 
-# If set to NO only classes defined in header files are included.
-
-EXTRACT_LOCAL_CLASSES  = YES
-
-# This flag is only useful for Objective-C code. When set to YES local 
-# methods, which are defined in the implementation section but not in 
-# the interface are included in the documentation. 
-# If set to NO (the default) only methods in the interface are included.
-
-EXTRACT_LOCAL_METHODS  = NO
-
-# If this flag is set to YES, the members of anonymous namespaces will be 
-# extracted and appear in the documentation as a namespace called 
-# 'anonymous_namespace{file}', where file will be replaced with the base 
-# name of the file that contains the anonymous namespace. By default 
-# anonymous namespace are hidden.
-
-EXTRACT_ANON_NSPACES   = NO
-
-# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all 
-# undocumented members of documented classes, files or namespaces. 
-# If set to NO (the default) these members will be included in the 
-# various overviews, but no documentation section is generated. 
-# This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_MEMBERS     = NO
-
-# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all 
-# undocumented classes that are normally visible in the class hierarchy. 
-# If set to NO (the default) these classes will be included in the various 
-# overviews. This option has no effect if EXTRACT_ALL is enabled.
-
-HIDE_UNDOC_CLASSES     = NO
-
-# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all 
-# friend (class|struct|union) declarations. 
-# If set to NO (the default) these declarations will be included in the 
-# documentation.
-
-HIDE_FRIEND_COMPOUNDS  = NO
-
-# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any 
-# documentation blocks found inside the body of a function. 
-# If set to NO (the default) these blocks will be appended to the 
-# function's detailed documentation block.
-
-HIDE_IN_BODY_DOCS      = NO
-
-# The INTERNAL_DOCS tag determines if documentation 
-# that is typed after a \internal command is included. If the tag is set 
-# to NO (the default) then the documentation will be excluded. 
-# Set it to YES to include the internal documentation.
-
-INTERNAL_DOCS          = NO
-
-# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate 
-# file names in lower-case letters. If set to YES upper-case letters are also 
-# allowed. This is useful if you have classes or files whose names only differ 
-# in case and if your file system supports case sensitive file names. Windows 
-# and Mac users are advised to set this option to NO.
-
 CASE_SENSE_NAMES       = NO
-
-# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen 
-# will show members with their full class and namespace scopes in the 
-# documentation. If set to YES the scope will be hidden.
-
-HIDE_SCOPE_NAMES       = NO
-
-# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen 
-# will put a list of the files that are included by a file in the documentation 
-# of that file.
-
-SHOW_INCLUDE_FILES     = YES
-
-# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen 
-# will list include files with double quotes in the documentation 
-# rather than with sharp brackets.
-
-FORCE_LOCAL_INCLUDES   = NO
-
-# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] 
-# is inserted in the documentation for inline members.
-
-INLINE_INFO            = YES
-
-# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen 
-# will sort the (detailed) documentation of file and class members 
-# alphabetically by member name. If set to NO the members will appear in 
-# declaration order.
-
-SORT_MEMBER_DOCS       = YES
-
-# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the 
-# brief documentation of file, namespace and class members alphabetically 
-# by member name. If set to NO (the default) the members will appear in 
-# declaration order.
-
-SORT_BRIEF_DOCS        = NO
-
-# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen
-# will sort the (brief and detailed) documentation of class members so that
-# constructors and destructors are listed first. If set to NO (the default)
-# the constructors will appear in the respective orders defined by
-# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS.
-# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO
-# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
-
-SORT_MEMBERS_CTORS_1ST = NO
-
-# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the 
-# hierarchy of group names into alphabetical order. If set to NO (the default) 
-# the group names will appear in their defined order.
-
-SORT_GROUP_NAMES       = NO
-
-# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be 
-# sorted by fully-qualified names, including namespaces. If set to 
-# NO (the default), the class list will be sorted only by class name, 
-# not including the namespace part. 
-# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. 
-# Note: This option applies only to the class list, not to the 
-# alphabetical list.
-
-SORT_BY_SCOPE_NAME     = NO
-
-# The GENERATE_TODOLIST tag can be used to enable (YES) or 
-# disable (NO) the todo list. This list is created by putting \todo 
-# commands in the documentation.
-
-GENERATE_TODOLIST      = YES
-
-# The GENERATE_TESTLIST tag can be used to enable (YES) or 
-# disable (NO) the test list. This list is created by putting \test 
-# commands in the documentation.
-
-GENERATE_TESTLIST      = YES
-
-# The GENERATE_BUGLIST tag can be used to enable (YES) or 
-# disable (NO) the bug list. This list is created by putting \bug 
-# commands in the documentation.
-
-GENERATE_BUGLIST       = YES
-
-# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or 
-# disable (NO) the deprecated list. This list is created by putting 
-# \deprecated commands in the documentation.
-
-GENERATE_DEPRECATEDLIST= YES
-
-# The ENABLED_SECTIONS tag can be used to enable conditional 
-# documentation sections, marked by \if sectionname ... \endif.
-
-ENABLED_SECTIONS       = 
-
-# The MAX_INITIALIZER_LINES tag determines the maximum number of lines 
-# the initial value of a variable or define consists of for it to appear in 
-# the documentation. If the initializer consists of more lines than specified 
-# here it will be hidden. Use a value of 0 to hide initializers completely. 
-# The appearance of the initializer of individual variables and defines in the 
-# documentation can be controlled using \showinitializer or \hideinitializer 
-# command in the documentation regardless of this setting.
-
-MAX_INITIALIZER_LINES  = 30
-
-# Set the SHOW_USED_FILES tag to NO to disable the list of files generated 
-# at the bottom of the documentation of classes and structs. If set to YES the 
-# list will mention the files that were used to generate the documentation.
-
-SHOW_USED_FILES        = YES
-
-# If the sources in your project are distributed over multiple directories 
-# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy 
-# in the documentation. The default is NO.
-
-SHOW_DIRECTORIES       = NO
-
-# Set the SHOW_FILES tag to NO to disable the generation of the Files page. 
-# This will remove the Files entry from the Quick Index and from the 
-# Folder Tree View (if specified). The default is YES.
-
-SHOW_FILES             = YES
-
-# Set the SHOW_NAMESPACES tag to NO to disable the generation of the 
-# Namespaces page.  This will remove the Namespaces entry from the Quick Index 
-# and from the Folder Tree View (if specified). The default is YES.
-
-SHOW_NAMESPACES        = YES
-
-# The FILE_VERSION_FILTER tag can be used to specify a program or script that 
-# doxygen should invoke to get the current version for each file (typically from 
-# the version control system). Doxygen will invoke the program by executing (via 
-# popen()) the command <command> <input-file>, where <command> is the value of 
-# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file 
-# provided by doxygen. Whatever the program writes to standard output 
-# is used as the file version. See the manual for examples.
-
-FILE_VERSION_FILTER    = 
-
-# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by 
-# doxygen. The layout file controls the global structure of the generated output files 
-# in an output format independent way. The create the layout file that represents 
-# doxygen's defaults, run doxygen with the -l option. You can optionally specify a 
-# file name after the option, if omitted DoxygenLayout.xml will be used as the name 
-# of the layout file.
-
-LAYOUT_FILE            = 
-
-#---------------------------------------------------------------------------
-# configuration options related to warning and progress messages
-#---------------------------------------------------------------------------
-
-# The QUIET tag can be used to turn on/off the messages that are generated 
-# by doxygen. Possible values are YES and NO. If left blank NO is used.
-
-QUIET                  = NO
-
-# The WARNINGS tag can be used to turn on/off the warning messages that are 
-# generated by doxygen. Possible values are YES and NO. If left blank 
-# NO is used.
-
-WARNINGS               = YES
-
-# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings 
-# for undocumented members. If EXTRACT_ALL is set to YES then this flag will 
-# automatically be disabled.
-
-WARN_IF_UNDOCUMENTED   = YES
-
-# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for 
-# potential errors in the documentation, such as not documenting some 
-# parameters in a documented function, or documenting parameters that 
-# don't exist or using markup commands wrongly.
-
-WARN_IF_DOC_ERROR      = YES
-
-# This WARN_NO_PARAMDOC option can be abled to get warnings for 
-# functions that are documented, but have no documentation for their parameters 
-# or return value. If set to NO (the default) doxygen will only warn about 
-# wrong or incomplete parameter documentation, but not about the absence of 
-# documentation.
-
-WARN_NO_PARAMDOC       = NO
-
-# The WARN_FORMAT tag determines the format of the warning messages that 
-# doxygen can produce. The string should contain the $file, $line, and $text 
-# tags, which will be replaced by the file and line number from which the 
-# warning originated and the warning text. Optionally the format may contain 
-# $version, which will be replaced by the version of the file (if it could 
-# be obtained via FILE_VERSION_FILTER)
-
-WARN_FORMAT            = "$file:$line: $text"
-
-# The WARN_LOGFILE tag can be used to specify a file to which warning 
-# and error messages should be written. If left blank the output is written 
-# to stderr.
-
-WARN_LOGFILE           = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the input files
-#---------------------------------------------------------------------------
-
-# The INPUT tag can be used to specify the files and/or directories that contain 
-# documented source files. You may enter file names like "myfile.cpp" or 
-# directories like "/usr/src/myproject". Separate the files or directories 
-# with spaces.
-
 INPUT                  = ../../numpy/core/src \
                          ../../numpy/core/include
-
-# This tag can be used to specify the character encoding of the source files 
-# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is 
-# also the default input encoding. Doxygen uses libiconv (or the iconv built 
-# into libc) for the transcoding. See https://www.gnu.org/software/libiconv for
-# the list of possible encodings.
-
-INPUT_ENCODING         = UTF-8
-
-# If the value of the INPUT tag contains directories, you can use the 
-# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank the following patterns are tested: 
-# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx 
-# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
-
 FILE_PATTERNS          = *.h *.c *.src
-
-# The RECURSIVE tag can be used to turn specify whether or not subdirectories 
-# should be searched for input files as well. Possible values are YES and NO. 
-# If left blank NO is used.
-
 RECURSIVE              = YES
-
-# The EXCLUDE tag can be used to specify files and/or directories that should 
-# excluded from the INPUT source files. This way you can easily exclude a 
-# subdirectory from a directory tree whose root is specified with the INPUT tag.
-
-EXCLUDE                = 
-
-# The EXCLUDE_SYMLINKS tag can be used select whether or not files or 
-# directories that are symbolic links (a Unix filesystem feature) are excluded 
-# from the input.
-
-EXCLUDE_SYMLINKS       = NO
-
-# If the value of the INPUT tag contains directories, you can use the 
-# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude 
-# certain files from those directories. Note that the wildcards are matched 
-# against the file with absolute path, so to exclude all test directories 
-# for example use the pattern */test/*
-
-EXCLUDE_PATTERNS       = 
-
-# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names 
-# (namespaces, classes, functions, etc.) that should be excluded from the 
-# output. The symbol name can be a fully qualified name, a word, or if the 
-# wildcard * is used, a substring. Examples: ANamespace, AClass, 
-# AClass::ANamespace, ANamespace::*Test
-
-EXCLUDE_SYMBOLS        = 
-
-# The EXAMPLE_PATH tag can be used to specify one or more files or 
-# directories that contain example code fragments that are included (see 
-# the \include command).
-
-EXAMPLE_PATH           = 
-
-# If the value of the EXAMPLE_PATH tag contains directories, you can use the 
-# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp 
-# and *.h) to filter out the source-files in the directories. If left 
-# blank all files are included.
-
-EXAMPLE_PATTERNS       = *
-
-# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be 
-# searched for input files to be used with the \include or \dontinclude 
-# commands irrespective of the value of the RECURSIVE tag. 
-# Possible values are YES and NO. If left blank NO is used.
-
-EXAMPLE_RECURSIVE      = NO
-
-# The IMAGE_PATH tag can be used to specify one or more files or 
-# directories that contain image that are included in the documentation (see 
-# the \image command).
-
-IMAGE_PATH             = 
-
-# The INPUT_FILTER tag can be used to specify a program that doxygen should 
-# invoke to filter for each input file. Doxygen will invoke the filter program 
-# by executing (via popen()) the command <filter> <input-file>, where <filter> 
-# is the value of the INPUT_FILTER tag, and <input-file> is the name of an 
-# input file. Doxygen will then use the output that the filter program writes 
-# to standard output.  If FILTER_PATTERNS is specified, this tag will be 
-# ignored.
-
 INPUT_FILTER           = ./numpyfilter.py
-
-# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern 
-# basis.  Doxygen will compare the file name with each pattern and apply the 
-# filter if there is a match.  The filters are a list of the form: 
-# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further 
-# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER 
-# is applied to all files.
-
-FILTER_PATTERNS        = 
-
-# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using 
-# INPUT_FILTER) will be used to filter the input files when producing source 
-# files to browse (i.e. when SOURCE_BROWSER is set to YES).
-
-FILTER_SOURCE_FILES    = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to source browsing
-#---------------------------------------------------------------------------
-
-# If the SOURCE_BROWSER tag is set to YES then a list of source files will 
-# be generated. Documented entities will be cross-referenced with these sources. 
-# Note: To get rid of all source code in the generated output, make sure also 
-# VERBATIM_HEADERS is set to NO.
-
-SOURCE_BROWSER         = NO
-
-# Setting the INLINE_SOURCES tag to YES will include the body 
-# of functions and classes directly in the documentation.
-
-INLINE_SOURCES         = NO
-
-# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct 
-# doxygen to hide any special comment blocks from generated source code 
-# fragments. Normal C and C++ comments will always remain visible.
-
-STRIP_CODE_COMMENTS    = YES
-
-# If the REFERENCED_BY_RELATION tag is set to YES 
-# then for each documented function all documented 
-# functions referencing it will be listed.
-
 REFERENCED_BY_RELATION = YES
-
-# If the REFERENCES_RELATION tag is set to YES 
-# then for each documented function all documented entities 
-# called/used by that function will be listed.
-
 REFERENCES_RELATION    = YES
-
-# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) 
-# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from 
-# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will 
-# link to the source code.  Otherwise they will link to the documentation.
-
-REFERENCES_LINK_SOURCE = YES
-
-# If the USE_HTAGS tag is set to YES then the references to source code 
-# will point to the HTML generated by the htags(1) tool instead of doxygen 
-# built-in source browser. The htags tool is part of GNU's global source 
-# tagging system (see https://www.gnu.org/software/global/global.html). You
-# will need version 4.8.6 or higher.
-
-USE_HTAGS              = NO
-
-# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen 
-# will generate a verbatim copy of the header file for each class for 
-# which an include is specified. Set to NO to disable this.
-
-VERBATIM_HEADERS       = YES
-
-#---------------------------------------------------------------------------
-# configuration options related to the alphabetical class index
-#---------------------------------------------------------------------------
-
-# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index 
-# of all compounds will be generated. Enable this if the project 
-# contains a lot of classes, structs, unions or interfaces.
-
 ALPHABETICAL_INDEX     = NO
-
-# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then 
-# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns 
-# in which this list will be split (can be a number in the range [1..20])
-
-COLS_IN_ALPHA_INDEX    = 5
-
-# In case all classes in a project start with a common prefix, all 
-# classes will be put under the same header in the alphabetical index. 
-# The IGNORE_PREFIX tag can be used to specify one or more prefixes that 
-# should be ignored while generating the index headers.
-
-IGNORE_PREFIX          = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the HTML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_HTML tag is set to YES (the default) Doxygen will 
-# generate HTML output.
-
 GENERATE_HTML          = YES
-
-# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `html' will be used as the default path.
-
-HTML_OUTPUT            = html
-
-# The HTML_FILE_EXTENSION tag can be used to specify the file extension for 
-# each generated HTML page (for example: .htm,.php,.asp). If it is left blank 
-# doxygen will generate files with .html extension.
-
-HTML_FILE_EXTENSION    = .html
-
-# The HTML_HEADER tag can be used to specify a personal HTML header for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard header.
-
-HTML_HEADER            = 
-
-# The HTML_FOOTER tag can be used to specify a personal HTML footer for 
-# each generated HTML page. If it is left blank doxygen will generate a 
-# standard footer.
-
-HTML_FOOTER            = 
-
-# The HTML_STYLESHEET tag can be used to specify a user-defined cascading 
-# style sheet that is used by each HTML page. It can be used to 
-# fine-tune the look of the HTML output. If the tag is left blank doxygen 
-# will generate a default style sheet. Note that doxygen will try to copy 
-# the style sheet file to the HTML output directory, so don't put your own 
-# stylesheet in the HTML output directory as well, or it will be erased!
-
-HTML_STYLESHEET        = 
-
-# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML 
-# page will contain the date and time when the page was generated. Setting 
-# this to NO can help when comparing the output of multiple runs.
-
 HTML_TIMESTAMP         = YES
-
-# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes, 
-# files or namespaces will be aligned in HTML using tables. If set to 
-# NO a bullet list will be used.
-
-HTML_ALIGN_MEMBERS     = YES
-
-# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML 
-# documentation will contain sections that can be hidden and shown after the 
-# page has loaded. For this to work a browser that supports 
-# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox 
-# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
-
-HTML_DYNAMIC_SECTIONS  = NO
-
-# If the GENERATE_DOCSET tag is set to YES, additional index files 
-# will be generated that can be used as input for Apple's Xcode 3 
-# integrated development environment, introduced with OSX 10.5 (Leopard). 
-# To create a documentation set, doxygen will generate a Makefile in the 
-# HTML output directory. Running make will produce the docset in that 
-# directory and running "make install" will install the docset in 
-# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find 
-# it at startup. 
-# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html (dead link)
-# for more information.
-
-GENERATE_DOCSET        = NO
-
-# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the 
-# feed. A documentation feed provides an umbrella under which multiple 
-# documentation sets from a single provider (such as a company or product suite) 
-# can be grouped.
-
-DOCSET_FEEDNAME        = "Doxygen generated docs"
-
-# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that 
-# should uniquely identify the documentation set bundle. This should be a 
-# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen 
-# will append .docset to the name.
-
-DOCSET_BUNDLE_ID       = org.doxygen.Project
-
-# If the GENERATE_HTMLHELP tag is set to YES, additional index files 
-# will be generated that can be used as input for tools like the 
-# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) 
-# of the generated HTML documentation.
-
-GENERATE_HTMLHELP      = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can 
-# be used to specify the file name of the resulting .chm file. You 
-# can add a path in front of the file if the result should not be 
-# written to the html output directory.
-
-CHM_FILE               = 
-
-# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can 
-# be used to specify the location (absolute path including file name) of 
-# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run 
-# the HTML help compiler on the generated index.hhp.
-
-HHC_LOCATION           = 
-
-# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag 
-# controls if a separate .chi index file is generated (YES) or that 
-# it should be included in the master .chm file (NO).
-
-GENERATE_CHI           = NO
-
-# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING 
-# is used to encode HtmlHelp index (hhk), content (hhc) and project file 
-# content.
-
-CHM_INDEX_ENCODING     = 
-
-# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag 
-# controls whether a binary table of contents is generated (YES) or a 
-# normal table of contents (NO) in the .chm file.
-
-BINARY_TOC             = NO
-
-# The TOC_EXPAND flag can be set to YES to add extra items for group members 
-# to the contents of the HTML help documentation and to the tree view.
-
-TOC_EXPAND             = NO
-
-# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER 
-# are set, an additional index file will be generated that can be used as input for 
-# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated 
-# HTML documentation.
-
-GENERATE_QHP           = NO
-
-# If the QHG_LOCATION tag is specified, the QCH_FILE tag can 
-# be used to specify the file name of the resulting .qch file. 
-# The path specified is relative to the HTML output folder.
-
-QCH_FILE               = 
-
-# The QHP_NAMESPACE tag specifies the namespace to use when generating 
-# Qt Help Project output. For more information please see 
-# https://doc.qt.io/qt-5/qthelpproject.html#namespace
-
-QHP_NAMESPACE          = org.doxygen.Project
-
-# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating 
-# Qt Help Project output. For more information please see 
-# https://doc.qt.io/qt-5/qthelpproject.html#virtual-folders
-
-QHP_VIRTUAL_FOLDER     = doc
-
-# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add. 
-# For more information please see 
-# https://doc.qt.io/qt-5/qthelpproject.html#custom-filters
-
-QHP_CUST_FILTER_NAME   = 
-
-# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see 
-# <a href="https://doc.qt.io/qt-5/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
-
-QHP_CUST_FILTER_ATTRS  = 
-
-# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's 
-# filter section matches. 
-# <a href="https://doc.qt.io/qt-5/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
-
-QHP_SECT_FILTER_ATTRS  = 
-
-# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can 
-# be used to specify the location of Qt's qhelpgenerator. 
-# If non-empty doxygen will try to run qhelpgenerator on the generated 
-# .qhp file.
-
-QHG_LOCATION           = 
-
-# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files  
-# will be generated, which together with the HTML files, form an Eclipse help  
-# plugin. To install this plugin and make it available under the help contents 
-# menu in Eclipse, the contents of the directory containing the HTML and XML 
-# files needs to be copied into the plugins directory of eclipse. The name of 
-# the directory within the plugins directory should be the same as 
-# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before
-# the help appears.
-
-GENERATE_ECLIPSEHELP   = NO
-
-# A unique identifier for the eclipse help plugin. When installing the plugin 
-# the directory name containing the HTML and XML files should also have 
-# this name.
-
-ECLIPSE_DOC_ID         = org.doxygen.Project
-
-# The DISABLE_INDEX tag can be used to turn on/off the condensed index at 
-# top of each HTML page. The value NO (the default) enables the index and 
-# the value YES disables it.
-
-DISABLE_INDEX          = NO
-
-# This tag can be used to set the number of enum values (range [1..20]) 
-# that doxygen will group on one line in the generated HTML documentation.
-
-ENUM_VALUES_PER_LINE   = 4
-
-# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index 
-# structure should be generated to display hierarchical information. 
-# If the tag value is set to YES, a side panel will be generated 
-# containing a tree-like index structure (just like the one that 
-# is generated for HTML Help). For this to work a browser that supports 
-# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). 
-# Windows users are probably better off using the HTML help feature.
-
 GENERATE_TREEVIEW      = YES
-
-# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories, 
-# and Class Hierarchy pages using a tree view instead of an ordered list.
-
-USE_INLINE_TREES       = NO
-
-# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be 
-# used to set the initial width (in pixels) of the frame in which the tree 
-# is shown.
-
-TREEVIEW_WIDTH         = 250
-
-# Use this tag to change the font size of Latex formulas included 
-# as images in the HTML documentation. The default is 10. Note that 
-# when you change the font size after a successful doxygen run you need 
-# to manually remove any form_*.png images from the HTML output directory 
-# to force them to be regenerated.
-
-FORMULA_FONTSIZE       = 10
-
-# When the SEARCHENGINE tag is enabled doxygen will generate a search box
-# for the HTML output. The underlying search engine uses javascript 
-# and DHTML and should work on any modern browser. Note that when using
-# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets
-# (GENERATE_DOCSET) there is already a search function so this one should 
-# typically be disabled. For large projects the javascript based search engine 
-# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
-
 SEARCHENGINE           = NO
-
-# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a PHP enabled web server instead of at the web client
-# using Javascript. Doxygen will generate the search PHP script and index 
-# file to put on the web server. The advantage of the server
-# based approach is that it scales better to large projects and allows
-# full text search. The disadvances is that it is more difficult to setup 
-# and does not have live searching capabilities.
-
-SERVER_BASED_SEARCH    = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the LaTeX output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will 
-# generate Latex output.
-
 GENERATE_LATEX         = NO
-
-# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `latex' will be used as the default path.
-
-LATEX_OUTPUT           = latex
-
-# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be 
-# invoked. If left blank `latex' will be used as the default command name. 
-# Note that when enabling USE_PDFLATEX this option is only used for 
-# generating bitmaps for formulas in the HTML output, but not in the 
-# Makefile that is written to the output directory.
-
-LATEX_CMD_NAME         = latex
-
-# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to 
-# generate index for LaTeX. If left blank `makeindex' will be used as the 
-# default command name.
-
-MAKEINDEX_CMD_NAME     = makeindex
-
-# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact 
-# LaTeX documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_LATEX          = NO
-
-# The PAPER_TYPE tag can be used to set the paper type that is used 
-# by the printer. Possible values are: a4, a4wide, letter, legal and 
-# executive. If left blank a4wide will be used.
-
 PAPER_TYPE             = a4wide
-
-# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX 
-# packages that should be included in the LaTeX output.
-
-EXTRA_PACKAGES         = 
-
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for 
-# the generated latex document. The header should contain everything until 
-# the first chapter. If it is left blank doxygen will generate a 
-# standard header. Notice: only use this tag if you know what you are doing!
-
-LATEX_HEADER           = 
-
-# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated 
-# is prepared for conversion to pdf (using ps2pdf). The pdf file will 
-# contain links (just like the HTML output) instead of page references 
-# This makes the output suitable for online browsing using a pdf viewer.
-
-PDF_HYPERLINKS         = YES
-
-# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of 
-# plain latex in the generated Makefile. Set this option to YES to get a 
-# higher quality PDF documentation.
-
-USE_PDFLATEX           = YES
-
-# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode. 
-# command to the generated LaTeX files. This will instruct LaTeX to keep 
-# running if errors occur, instead of asking the user for help. 
-# This option is also used when generating formulas in HTML.
-
-LATEX_BATCHMODE        = NO
-
-# If LATEX_HIDE_INDICES is set to YES then doxygen will not 
-# include the index chapters (such as File Index, Compound Index, etc.) 
-# in the output.
-
-LATEX_HIDE_INDICES     = NO
-
-# If LATEX_SOURCE_CODE is set to YES then doxygen will include
-# source code with syntax highlighting in the LaTeX output.
-# Note that which sources are shown also depends on other settings
-# such as SOURCE_BROWSER.
-
-LATEX_SOURCE_CODE      = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the RTF output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output 
-# The RTF output is optimized for Word 97 and may not look very pretty with 
-# other RTF readers or editors.
-
-GENERATE_RTF           = NO
-
-# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `rtf' will be used as the default path.
-
-RTF_OUTPUT             = rtf
-
-# If the COMPACT_RTF tag is set to YES Doxygen generates more compact 
-# RTF documents. This may be useful for small projects and may help to 
-# save some trees in general.
-
-COMPACT_RTF            = NO
-
-# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated 
-# will contain hyperlink fields. The RTF file will 
-# contain links (just like the HTML output) instead of page references. 
-# This makes the output suitable for online browsing using WORD or other 
-# programs which support those fields. 
-# Note: wordpad (write) and others do not support links.
-
-RTF_HYPERLINKS         = NO
-
-# Load stylesheet definitions from file. Syntax is similar to doxygen's 
-# config file, i.e. a series of assignments. You only have to provide 
-# replacements, missing definitions are set to their default value.
-
-RTF_STYLESHEET_FILE    = 
-
-# Set optional variables used in the generation of an rtf document. 
-# Syntax is similar to doxygen's config file.
-
-RTF_EXTENSIONS_FILE    = 
-
-#---------------------------------------------------------------------------
-# configuration options related to the man page output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_MAN tag is set to YES (the default) Doxygen will 
-# generate man pages
-
-GENERATE_MAN           = NO
-
-# The MAN_OUTPUT tag is used to specify where the man pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `man' will be used as the default path.
-
-MAN_OUTPUT             = man
-
-# The MAN_EXTENSION tag determines the extension that is added to 
-# the generated man pages (default is the subroutine's section .3)
-
-MAN_EXTENSION          = .3
-
-# If the MAN_LINKS tag is set to YES and Doxygen generates man output, 
-# then it will generate one additional man file for each entity 
-# documented in the real man page(s). These additional files 
-# only source the real man page, but without them the man command 
-# would be unable to find the correct page. The default is NO.
-
-MAN_LINKS              = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the XML output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_XML tag is set to YES Doxygen will 
-# generate an XML file that captures the structure of 
-# the code including all documentation.
-
 GENERATE_XML           = NO
-
-# The XML_OUTPUT tag is used to specify where the XML pages will be put. 
-# If a relative path is entered the value of OUTPUT_DIRECTORY will be 
-# put in front of it. If left blank `xml' will be used as the default path.
-
-XML_OUTPUT             = xml
-
-# The XML_SCHEMA tag can be used to specify an XML schema, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_SCHEMA             = 
-
-# The XML_DTD tag can be used to specify an XML DTD, 
-# which can be used by a validating XML parser to check the 
-# syntax of the XML files.
-
-XML_DTD                = 
-
-# If the XML_PROGRAMLISTING tag is set to YES Doxygen will 
-# dump the program listings (including syntax highlighting 
-# and cross-referencing information) to the XML output. Note that 
-# enabling this will significantly increase the size of the XML output.
-
-XML_PROGRAMLISTING     = YES
-
-#---------------------------------------------------------------------------
-# configuration options for the AutoGen Definitions output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will 
-# generate an AutoGen Definitions (see autogen.sf.net) file 
-# that captures the structure of the code including all 
-# documentation. Note that this feature is still experimental 
-# and incomplete at the moment.
-
-GENERATE_AUTOGEN_DEF   = NO
-
-#---------------------------------------------------------------------------
-# configuration options related to the Perl module output
-#---------------------------------------------------------------------------
-
-# If the GENERATE_PERLMOD tag is set to YES Doxygen will 
-# generate a Perl module file that captures the structure of 
-# the code including all documentation. Note that this 
-# feature is still experimental and incomplete at the 
-# moment.
-
-GENERATE_PERLMOD       = NO
-
-# If the PERLMOD_LATEX tag is set to YES Doxygen will generate 
-# the necessary Makefile rules, Perl scripts and LaTeX code to be able 
-# to generate PDF and DVI output from the Perl module output.
-
-PERLMOD_LATEX          = NO
-
-# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be 
-# nicely formatted so it can be parsed by a human reader.  This is useful 
-# if you want to understand what is going on.  On the other hand, if this 
-# tag is set to NO the size of the Perl module output will be much smaller 
-# and Perl will parse it just the same.
-
-PERLMOD_PRETTY         = YES
-
-# The names of the make variables in the generated doxyrules.make file 
-# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. 
-# This is useful so different doxyrules.make files included by the same 
-# Makefile don't overwrite each other's variables.
-
-PERLMOD_MAKEVAR_PREFIX = 
-
-#---------------------------------------------------------------------------
-# Configuration options related to the preprocessor
-#---------------------------------------------------------------------------
-
-# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will 
-# evaluate all C-preprocessor directives found in the sources and include 
-# files.
-
-ENABLE_PREPROCESSING   = YES
-
-# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro 
-# names in the source code. If set to NO (the default) only conditional 
-# compilation will be performed. Macro expansion can be done in a controlled 
-# way by setting EXPAND_ONLY_PREDEF to YES.
-
-MACRO_EXPANSION        = NO
-
-# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES 
-# then the macro expansion is limited to the macros specified with the 
-# PREDEFINED and EXPAND_AS_DEFINED tags.
-
-EXPAND_ONLY_PREDEF     = NO
-
-# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files 
-# in the INCLUDE_PATH (see below) will be search if a #include is found.
-
-SEARCH_INCLUDES        = YES
-
-# The INCLUDE_PATH tag can be used to specify one or more directories that 
-# contain include files that are not input files but should be processed by 
-# the preprocessor.
-
-INCLUDE_PATH           = 
-
-# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard 
-# patterns (like *.h and *.hpp) to filter out the header-files in the 
-# directories. If left blank, the patterns specified with FILE_PATTERNS will 
-# be used.
-
-INCLUDE_FILE_PATTERNS  = 
-
-# The PREDEFINED tag can be used to specify one or more macro names that 
-# are defined before the preprocessor is started (similar to the -D option of 
-# gcc). The argument of the tag is a list of macros of the form: name 
-# or name=definition (no spaces). If the definition and the = are 
-# omitted =1 is assumed. To prevent a macro definition from being 
-# undefined via #undef or recursively expanded use the := operator 
-# instead of the = operator.
-
-PREDEFINED             = 
-
-# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then 
-# this tag can be used to specify a list of macro names that should be expanded. 
-# The macro definition that is found in the sources will be used. 
-# Use the PREDEFINED tag if you want to use a different macro definition.
-
-EXPAND_AS_DEFINED      = 
-
-# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then 
-# doxygen's preprocessor will remove all function-like macros that are alone 
-# on a line, have an all uppercase name, and do not end with a semicolon. Such 
-# function macros are typically used for boiler-plate code, and will confuse 
-# the parser if not removed.
-
-SKIP_FUNCTION_MACROS   = YES
-
-#---------------------------------------------------------------------------
-# Configuration::additions related to external references
-#---------------------------------------------------------------------------
-
-# The TAGFILES option can be used to specify one or more tagfiles. 
-# Optionally an initial location of the external documentation 
-# can be added for each tagfile. The format of a tag file without 
-# this location is as follows: 
-#   TAGFILES = file1 file2 ... 
-# Adding location for the tag files is done as follows: 
-#   TAGFILES = file1=loc1 "file2 = loc2" ... 
-# where "loc1" and "loc2" can be relative or absolute paths or 
-# URLs. If a location is present for each tag, the installdox tool 
-# does not have to be run to correct the links. 
-# Note that each tag file must have a unique name 
-# (where the name does NOT include the path) 
-# If a tag file is not located in the directory in which doxygen 
-# is run, you must also specify the path to the tagfile here.
-
-TAGFILES               = 
-
-# When a file name is specified after GENERATE_TAGFILE, doxygen will create 
-# a tag file that is based on the input files it reads.
-
-GENERATE_TAGFILE       = 
-
-# If the ALLEXTERNALS tag is set to YES all external classes will be listed 
-# in the class index. If set to NO only the inherited external classes 
-# will be listed.
-
-ALLEXTERNALS           = NO
-
-# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed 
-# in the modules index. If set to NO, only the current project's groups will 
-# be listed.
-
-EXTERNAL_GROUPS        = YES
-
-# The PERL_PATH should be the absolute path and name of the perl script 
-# interpreter (i.e. the result of `which perl').
-
-PERL_PATH              = /usr/bin/perl
-
-#---------------------------------------------------------------------------
-# Configuration options related to the dot tool
-#---------------------------------------------------------------------------
-
-# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will 
-# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base 
-# or super classes. Setting the tag to NO turns the diagrams off. Note that 
-# this option is superseded by the HAVE_DOT option below. This is only a 
-# fallback. It is recommended to install and use dot, since it yields more 
-# powerful graphs.
-
-CLASS_DIAGRAMS         = YES
-
-# You can define message sequence charts within doxygen comments using the \msc 
-# command. Doxygen will then run the mscgen tool (see 
-# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the 
-# documentation. The MSCGEN_PATH tag allows you to specify the directory where 
-# the mscgen tool resides. If left empty the tool is assumed to be found in the 
-# default search path.
-
-MSCGEN_PATH            = 
-
-# If set to YES, the inheritance and collaboration graphs will hide 
-# inheritance and usage relations if the target is undocumented 
-# or is not a class.
-
-HIDE_UNDOC_RELATIONS   = YES
-
-# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is 
-# available from the path. This tool is part of Graphviz, a graph visualization 
-# toolkit from AT&T and Lucent Bell Labs. The other options in this section 
-# have no effect if this option is set to NO (the default)
-
 HAVE_DOT               = NO
-
-# By default doxygen will write a font called FreeSans.ttf to the output 
-# directory and reference it in all dot files that doxygen generates. This 
-# font does not include all possible unicode characters however, so when you need 
-# these (or just want a differently looking font) you can specify the font name 
-# using DOT_FONTNAME. You need need to make sure dot is able to find the font, 
-# which can be done by putting it in a standard location or by setting the 
-# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory 
-# containing the font.
-
-DOT_FONTNAME           = FreeSans
-
-# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs. 
-# The default size is 10pt.
-
-DOT_FONTSIZE           = 10
-
-# By default doxygen will tell dot to use the output directory to look for the 
-# FreeSans.ttf font (which doxygen will put there itself). If you specify a 
-# different font using DOT_FONTNAME you can set the path where dot 
-# can find it using this tag.
-
-DOT_FONTPATH           = 
-
-# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect inheritance relations. Setting this tag to YES will force the 
-# the CLASS_DIAGRAMS tag to NO.
-
-CLASS_GRAPH            = YES
-
-# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for each documented class showing the direct and 
-# indirect implementation dependencies (inheritance, containment, and 
-# class references variables) of the class with other documented classes.
-
-COLLABORATION_GRAPH    = YES
-
-# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen 
-# will generate a graph for groups, showing the direct groups dependencies
-
-GROUP_GRAPHS           = YES
-
-# If the UML_LOOK tag is set to YES doxygen will generate inheritance and 
-# collaboration diagrams in a style similar to the OMG's Unified Modeling 
-# Language.
-
-UML_LOOK               = NO
-
-# If set to YES, the inheritance and collaboration graphs will show the 
-# relations between templates and their instances.
-
-TEMPLATE_RELATIONS     = NO
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT 
-# tags are set to YES then doxygen will generate a graph for each documented 
-# file showing the direct and indirect include dependencies of the file with 
-# other documented files.
-
-INCLUDE_GRAPH          = YES
-
-# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and 
-# HAVE_DOT tags are set to YES then doxygen will generate a graph for each 
-# documented header file showing the documented files that directly or 
-# indirectly include this file.
-
-INCLUDED_BY_GRAPH      = YES
-
-# If the CALL_GRAPH and HAVE_DOT options are set to YES then 
-# doxygen will generate a call dependency graph for every global function 
-# or class method. Note that enabling this option will significantly increase 
-# the time of a run. So in most cases it will be better to enable call graphs 
-# for selected functions only using the \callgraph command.
-
-CALL_GRAPH             = NO
-
-# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then 
-# doxygen will generate a caller dependency graph for every global function 
-# or class method. Note that enabling this option will significantly increase 
-# the time of a run. So in most cases it will be better to enable caller 
-# graphs for selected functions only using the \callergraph command.
-
-CALLER_GRAPH           = NO
-
-# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen 
-# will graphical hierarchy of all classes instead of a textual one.
-
-GRAPHICAL_HIERARCHY    = YES
-
-# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES 
-# then doxygen will show the dependencies a directory has on other directories 
-# in a graphical way. The dependency relations are determined by the #include 
-# relations between the files in the directories.
-
-DIRECTORY_GRAPH        = YES
-
-# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images 
-# generated by dot. Possible values are png, jpg, or gif 
-# If left blank png will be used.
-
-DOT_IMAGE_FORMAT       = png
-
-# The tag DOT_PATH can be used to specify the path where the dot tool can be 
-# found. If left blank, it is assumed the dot tool can be found in the path.
-
-DOT_PATH               = 
-
-# The DOTFILE_DIRS tag can be used to specify one or more directories that 
-# contain dot files that are included in the documentation (see the 
-# \dotfile command).
-
-DOTFILE_DIRS           = 
-
-# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of 
-# nodes that will be shown in the graph. If the number of nodes in a graph 
-# becomes larger than this value, doxygen will truncate the graph, which is 
-# visualized by representing a node as a red box. Note that doxygen if the 
-# number of direct children of the root node in a graph is already larger than 
-# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note 
-# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
-
-DOT_GRAPH_MAX_NODES    = 50
-
-# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the 
-# graphs generated by dot. A depth value of 3 means that only nodes reachable 
-# from the root by following a path via at most 3 edges will be shown. Nodes 
-# that lay further from the root node will be omitted. Note that setting this 
-# option to 1 or 2 may greatly reduce the computation time needed for large 
-# code bases. Also note that the size of a graph can be further restricted by 
-# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
-
-MAX_DOT_GRAPH_DEPTH    = 0
-
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent 
-# background. This is disabled by default, because dot on Windows does not 
-# seem to support this out of the box. Warning: Depending on the platform used, 
-# enabling this option may lead to badly anti-aliased labels on the edges of 
-# a graph (i.e. they become hard to read).
-
-DOT_TRANSPARENT        = NO
-
-# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output 
-# files in one run (i.e. multiple -o and -T options on the command line). This 
-# makes dot run faster, but since only newer versions of dot (>1.8.10) 
-# support this, this feature is disabled by default.
-
-DOT_MULTI_TARGETS      = NO
-
-# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will 
-# generate a legend page explaining the meaning of the various boxes and 
-# arrows in the dot generated graphs.
-
-GENERATE_LEGEND        = YES
-
-# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will 
-# remove the intermediate dot files that are used to generate 
-# the various graphs.
-
-DOT_CLEANUP            = YES
index bc6225ec8ce5e6096bbb69cf50333af7057bf653..8b9deada8ad95689e0569e9c7cbcbc42d8b95319 100644 (file)
@@ -3,5 +3,8 @@ all: build
 build:
        doxygen
 
-.PHONY: all build
+clean:
+       rm -rf build
+
+.PHONY: all build clean
 
index 0ec50697e119c052727fad8cb9e517fa710d2e79..d3cfe18f0cb0ae723d74eb5f2bb7e657637dfd68 100755 (executable)
@@ -1,41 +1,37 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
-numpyfilter.py INPUTFILE
+numpyfilter.py [-h] inputfile
 
 Interpret C comments as ReStructuredText, and replace them by the HTML output.
 Also, add Doxygen /** and /**< syntax automatically where appropriate.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import re
 import os
 import textwrap
-import optparse
 
-from numpy.core.numeric import pickle
+from numpy.compat import pickle
 
 CACHE_FILE = 'build/rst-cache.pck'
 
 def main():
-    p = optparse.OptionParser(usage=__doc__.strip())
-    options, args = p.parse_args()
+    import argparse
 
-    if len(args) != 1:
-        p.error("no input file given")
+    parser = argparse.ArgumentParser(usage=__doc__.strip())
+    parser.add_argument('input_file', help='input file')
+    args = parser.parse_args()
 
     comment_re = re.compile(r'(\n.*?)/\*(.*?)\*/', re.S)
 
     cache = load_cache()
 
-    f = open(args[0], 'r')
     try:
-        text = f.read()
-        text = comment_re.sub(lambda m: process_match(m, cache), text)
-        sys.stdout.write(text)
+        with open(args.input_file, 'r') as f:
+            text = f.read()
+            text = comment_re.sub(lambda m: process_match(m, cache), text)
+            sys.stdout.write(text)
     finally:
-        f.close()
         save_cache(cache)
 
 def filter_comment(text):
@@ -69,23 +65,18 @@ def process_match(m, cache=None):
 
 def load_cache():
     if os.path.exists(CACHE_FILE):
-        f = open(CACHE_FILE, 'rb')
-        try:
-            cache = pickle.load(f)
-        except Exception:
-            cache = {}
-        finally:
-            f.close()
+        with open(CACHE_FILE, 'rb') as f:
+            try:
+                cache = pickle.load(f)
+            except Exception:
+                cache = {}
     else:
         cache = {}
     return cache
 
 def save_cache(cache):
-    f = open(CACHE_FILE + '.new', 'wb')
-    try:
+    with open(CACHE_FILE + '.new', 'wb') as f:
         pickle.dump(cache, f)
-    finally:
-        f.close()
     os.rename(CACHE_FILE + '.new', CACHE_FILE)
 
 def render_html(text):
@@ -108,6 +99,6 @@ def render_html(text):
                                   _disable_config=1,
                                   )
     )
-    return parts['html_body'].encode('utf-8')
+    return parts['html_body']
 
 if __name__ == "__main__": main()
index 75d9964e3e7f8996d13f2fc7d4fe2ab0c2c6d13c..2e91f510f529d57beaa183ae95cf47161ba968ab 100644 (file)
@@ -225,7 +225,7 @@ A total of 418 pull requests were merged for this release.
 * `#7240 <https://github.com/numpy/numpy/pull/7240>`__: Change 'pubic' to 'public'.
 * `#7241 <https://github.com/numpy/numpy/pull/7241>`__: MAINT: update doc/sphinxext to numpydoc 0.6.0, and fix up some...
 * `#7243 <https://github.com/numpy/numpy/pull/7243>`__: ENH: Adding support to the range keyword for estimation of the...
-* `#7246 <https://github.com/numpy/numpy/pull/7246>`__: DOC: metion writeable keyword in as_strided in release notes
+* `#7246 <https://github.com/numpy/numpy/pull/7246>`__: DOC: mention writeable keyword in as_strided in release notes
 * `#7247 <https://github.com/numpy/numpy/pull/7247>`__: TST: Fail quickly on AppVeyor for superseded PR builds
 * `#7248 <https://github.com/numpy/numpy/pull/7248>`__: DOC: remove link to documentation wiki editor from HOWTO_DOCUMENT.
 * `#7250 <https://github.com/numpy/numpy/pull/7250>`__: DOC,REL: Update 1.11.0 notes.
@@ -333,7 +333,7 @@ A total of 418 pull requests were merged for this release.
 * `#7534 <https://github.com/numpy/numpy/pull/7534>`__: MAINT: Update setup.py to reflect supported python versions.
 * `#7536 <https://github.com/numpy/numpy/pull/7536>`__: MAINT: Always use PyCapsule instead of PyCObject in mtrand.pyx
 * `#7539 <https://github.com/numpy/numpy/pull/7539>`__: MAINT: Cleanup of random stuff
-* `#7549 <https://github.com/numpy/numpy/pull/7549>`__: BUG: allow graceful recovery for no Liux compiler
+* `#7549 <https://github.com/numpy/numpy/pull/7549>`__: BUG: allow graceful recovery for no Linux compiler
 * `#7562 <https://github.com/numpy/numpy/pull/7562>`__: BUG: Fix test_from_object_array_unicode (test_defchararray.TestBasic)…
 * `#7565 <https://github.com/numpy/numpy/pull/7565>`__: BUG: Fix test_ctypeslib and test_indexing for debug interpreter
 * `#7566 <https://github.com/numpy/numpy/pull/7566>`__: MAINT: use manylinux1 wheel for cython
@@ -459,7 +459,7 @@ A total of 418 pull requests were merged for this release.
 * `#8016 <https://github.com/numpy/numpy/pull/8016>`__: BUG: Fix numpy.ma.median.
 * `#8018 <https://github.com/numpy/numpy/pull/8018>`__: BUG: Fixes return for np.ma.count if keepdims is True and axis...
 * `#8021 <https://github.com/numpy/numpy/pull/8021>`__: DOC: change all non-code instances of Numpy to NumPy
-* `#8027 <https://github.com/numpy/numpy/pull/8027>`__: ENH: Add platform indepedent lib dir to PYTHONPATH
+* `#8027 <https://github.com/numpy/numpy/pull/8027>`__: ENH: Add platform independent lib dir to PYTHONPATH
 * `#8028 <https://github.com/numpy/numpy/pull/8028>`__: DOC: Update 1.11.2 release notes.
 * `#8030 <https://github.com/numpy/numpy/pull/8030>`__: BUG: fix np.ma.median with only one non-masked value and an axis...
 * `#8038 <https://github.com/numpy/numpy/pull/8038>`__: MAINT: Update error message in rollaxis.
index 4e3d3680b454f41d7d933cd6891174f2cd4a3c19..dd5544ac9fecf47831ea6216604730f53f3c31c2 100644 (file)
@@ -316,7 +316,7 @@ A total of 438 pull requests were merged for this release.
 * `#10618 <https://github.com/numpy/numpy/pull/10618>`__: MAINT: Stop using non-tuple indices internally
 * `#10619 <https://github.com/numpy/numpy/pull/10619>`__: BUG: np.ma.flatnotmasked_contiguous behaves differently on mask=nomask...
 * `#10621 <https://github.com/numpy/numpy/pull/10621>`__: BUG: deallocate recursive closure in arrayprint.py
-* `#10623 <https://github.com/numpy/numpy/pull/10623>`__: BUG: Correctly identify comma seperated dtype strings
+* `#10623 <https://github.com/numpy/numpy/pull/10623>`__: BUG: Correctly identify comma separated dtype strings
 * `#10625 <https://github.com/numpy/numpy/pull/10625>`__: BUG: Improve the accuracy of the FFT implementation
 * `#10635 <https://github.com/numpy/numpy/pull/10635>`__: ENH: Implement initial kwarg for ufunc.add.reduce
 * `#10641 <https://github.com/numpy/numpy/pull/10641>`__: MAINT: Post 1.14.1 release updates for master branch
@@ -343,7 +343,7 @@ A total of 438 pull requests were merged for this release.
 * `#10699 <https://github.com/numpy/numpy/pull/10699>`__: DOC: Grammar of np.gradient docstring
 * `#10702 <https://github.com/numpy/numpy/pull/10702>`__: TST, DOC: Upload devdocs and neps after circleci build
 * `#10703 <https://github.com/numpy/numpy/pull/10703>`__: MAINT: NEP process updates
-* `#10708 <https://github.com/numpy/numpy/pull/10708>`__: BUG: fix problem with modifing pyf lines containing ';' in f2py
+* `#10708 <https://github.com/numpy/numpy/pull/10708>`__: BUG: fix problem with modifying pyf lines containing ';' in f2py
 * `#10710 <https://github.com/numpy/numpy/pull/10710>`__: BUG: fix error message in numpy.select
 * `#10711 <https://github.com/numpy/numpy/pull/10711>`__: MAINT: Hard tab and whitespace cleanup.
 * `#10715 <https://github.com/numpy/numpy/pull/10715>`__: MAINT: Fixed C++ guard in f2py test.
index 19374058d1670d31234af9eec8bad58e0b675c97..c609d214c5efb254d087a9e8e45e2704e5ba2479 100644 (file)
@@ -37,14 +37,14 @@ A total of 23 pull requests were merged for this release.
 * `#13933 <https://github.com/numpy/numpy/pull/13933>`__: MAINT/BUG/DOC: Fix errors in _add_newdocs
 * `#13984 <https://github.com/numpy/numpy/pull/13984>`__: BUG: fix byte order reversal for datetime64[ns]
 * `#13994 <https://github.com/numpy/numpy/pull/13994>`__: MAINT,BUG: Use nbytes to also catch empty descr during allocation
-* `#14042 <https://github.com/numpy/numpy/pull/14042>`__: BUG: np.array cleared errors occured in PyMemoryView_FromObject
+* `#14042 <https://github.com/numpy/numpy/pull/14042>`__: BUG: np.array cleared errors occurred in PyMemoryView_FromObject
 * `#14043 <https://github.com/numpy/numpy/pull/14043>`__: BUG: Fixes for Undefined Behavior Sanitizer (UBSan) errors.
 * `#14044 <https://github.com/numpy/numpy/pull/14044>`__: BUG: ensure that casting to/from structured is properly checked.
 * `#14045 <https://github.com/numpy/numpy/pull/14045>`__: MAINT: fix histogram*d dispatchers
 * `#14046 <https://github.com/numpy/numpy/pull/14046>`__: BUG: further fixup to histogram2d dispatcher.
 * `#14052 <https://github.com/numpy/numpy/pull/14052>`__: BUG: Replace contextlib.suppress for Python 2.7
 * `#14056 <https://github.com/numpy/numpy/pull/14056>`__: BUG: fix compilation of 3rd party modules with Py_LIMITED_API...
-* `#14057 <https://github.com/numpy/numpy/pull/14057>`__: BUG: Fix memory leak in dtype from dict contructor
+* `#14057 <https://github.com/numpy/numpy/pull/14057>`__: BUG: Fix memory leak in dtype from dict constructor
 * `#14058 <https://github.com/numpy/numpy/pull/14058>`__: DOC: Document array_function at a higher level.
 * `#14084 <https://github.com/numpy/numpy/pull/14084>`__: BUG, DOC: add new recfunctions to `__all__`
 * `#14162 <https://github.com/numpy/numpy/pull/14162>`__: BUG: Remove stray print that causes a SystemError on python 3.7
index debfb6f5be985617fe4405d58e25e69d31ebe225..4177c848fd7e91af0ad47ba1694263e6a560704f 100644 (file)
@@ -276,7 +276,7 @@ A total of 531 pull requests were merged for this release.
 * `#12696 <https://github.com/numpy/numpy/pull/12696>`__: BUG: Fix leak of void scalar buffer info
 * `#12698 <https://github.com/numpy/numpy/pull/12698>`__: DOC: improve comments in copycast_isaligned
 * `#12700 <https://github.com/numpy/numpy/pull/12700>`__: ENH: chain additional exception on ufunc method lookup error
-* `#12702 <https://github.com/numpy/numpy/pull/12702>`__: TST: Check FFT results for C/Fortran ordered and non contigous...
+* `#12702 <https://github.com/numpy/numpy/pull/12702>`__: TST: Check FFT results for C/Fortran ordered and non contiguous...
 * `#12704 <https://github.com/numpy/numpy/pull/12704>`__: TST: pin Azure brew version for stability
 * `#12709 <https://github.com/numpy/numpy/pull/12709>`__: TST: add ppc64le to Travis CI matrix
 * `#12713 <https://github.com/numpy/numpy/pull/12713>`__: BUG: loosen kwargs requirements in ediff1d
@@ -536,7 +536,7 @@ A total of 531 pull requests were merged for this release.
 * `#13503 <https://github.com/numpy/numpy/pull/13503>`__: ENH: Support object arrays in matmul
 * `#13504 <https://github.com/numpy/numpy/pull/13504>`__: DOC: Update links in PULL_REQUEST_TEMPLATE.md
 * `#13506 <https://github.com/numpy/numpy/pull/13506>`__: ENH: Add sparse option to np.core.numeric.indices
-* `#13507 <https://github.com/numpy/numpy/pull/13507>`__: BUG: np.array cleared errors occured in PyMemoryView_FromObject
+* `#13507 <https://github.com/numpy/numpy/pull/13507>`__: BUG: np.array cleared errors occurred in PyMemoryView_FromObject
 * `#13508 <https://github.com/numpy/numpy/pull/13508>`__: BUG: Removes ValueError for empty kwargs in arraymultiter_new
 * `#13518 <https://github.com/numpy/numpy/pull/13518>`__: MAINT: implement assert_array_compare without converting array...
 * `#13520 <https://github.com/numpy/numpy/pull/13520>`__: BUG: exp, log AVX loops do not use steps
@@ -643,7 +643,7 @@ A total of 531 pull requests were merged for this release.
 * `#13815 <https://github.com/numpy/numpy/pull/13815>`__: MAINT: Correct intrinsic use on Windows
 * `#13818 <https://github.com/numpy/numpy/pull/13818>`__: TST: Add tests for ComplexWarning in astype
 * `#13819 <https://github.com/numpy/numpy/pull/13819>`__: DOC: Fix documented default value of ``__array_priority__`` for...
-* `#13820 <https://github.com/numpy/numpy/pull/13820>`__: MAINT, DOC: Fix misspelled words in documetation.
+* `#13820 <https://github.com/numpy/numpy/pull/13820>`__: MAINT, DOC: Fix misspelled words in documentation.
 * `#13821 <https://github.com/numpy/numpy/pull/13821>`__: MAINT: core: Fix a compiler warning.
 * `#13830 <https://github.com/numpy/numpy/pull/13830>`__: MAINT: Update tox for supported Python versions
 * `#13832 <https://github.com/numpy/numpy/pull/13832>`__: MAINT: remove pcg32 BitGenerator
@@ -656,7 +656,7 @@ A total of 531 pull requests were merged for this release.
 * `#13849 <https://github.com/numpy/numpy/pull/13849>`__: DOC: np.random documentation cleanup and expansion.
 * `#13850 <https://github.com/numpy/numpy/pull/13850>`__: DOC: Update performance numbers
 * `#13851 <https://github.com/numpy/numpy/pull/13851>`__: MAINT: Update shippable.yml to remove Python 2 dependency
-* `#13855 <https://github.com/numpy/numpy/pull/13855>`__: BUG: Fix memory leak in dtype from dict contructor
+* `#13855 <https://github.com/numpy/numpy/pull/13855>`__: BUG: Fix memory leak in dtype from dict constructor
 * `#13856 <https://github.com/numpy/numpy/pull/13856>`__: MAINT: move location of bitgen.h
 * `#13858 <https://github.com/numpy/numpy/pull/13858>`__: BUG: do not force emulation of 128-bit arithmetic.
 * `#13859 <https://github.com/numpy/numpy/pull/13859>`__: DOC: Update performance numbers for PCG64
diff --git a/doc/changelog/1.18.5-changelog.rst b/doc/changelog/1.18.5-changelog.rst
deleted file mode 100644 (file)
index f0bc51e..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-
-Contributors
-============
-
-A total of 3 people contributed to this release.  People with a "+" by their
-names contributed a patch for the first time.
-
-* Charles Harris
-* Matti Picus
-* Siyuan +
-
-Pull requests merged
-====================
-
-A total of 2 pull requests were merged for this release.
-
-* `#16439 <https://github.com/numpy/numpy/pull/16439>`__: ENH: enable pickle protocol 5 support for python3.5
-* `#16441 <https://github.com/numpy/numpy/pull/16441>`__: BUG: relpath fails for different drives on windows
diff --git a/doc/changelog/1.19.0-changelog.rst b/doc/changelog/1.19.0-changelog.rst
new file mode 100644 (file)
index 0000000..bd74383
--- /dev/null
@@ -0,0 +1,592 @@
+
+Contributors
+============
+
+A total of 126 people contributed to this release.  People with a "+" by their
+names contributed a patch for the first time.
+
+* Alex Henrie
+* Alexandre de Siqueira +
+* Andras Deak
+* Andrea Sangalli +
+* Andreas Klöckner +
+* Andrei Shirobokov +
+* Anirudh Subramanian +
+* Anne Bonner
+* Anton Ritter-Gogerly +
+* Benjamin Trendelkamp-Schroer +
+* Bharat Raghunathan
+* Brandt Bucher +
+* Brian Wignall
+* Bui Duc Minh +
+* Changqing Li +
+* Charles Harris
+* Chris Barker
+* Chris Holland +
+* Christian Kastner +
+* Chunlin +
+* Chunlin Fang +
+* Damien Caliste +
+* Dan Allan
+* Daniel Hrisca
+* Daniel Povey +
+* Dustan Levenstein +
+* Emmanuelle Gouillart +
+* Eric Larson
+* Eric M. Bray
+* Eric Mariasis +
+* Eric Wieser
+* Erik Welch +
+* Fabio Zeiser +
+* Gabriel Gerlero +
+* Ganesh Kathiresan +
+* Gengxin Xie +
+* Guilherme Leobas
+* Guillaume Peillex +
+* Hameer Abbasi
+* Hao Jin +
+* Harshal Prakash Patankar +
+* Heshy Roskes +
+* Himanshu Garg +
+* Huon Wilson +
+* John Han +
+* John Kirkham
+* Jon Dufresne
+* Jon Morris +
+* Josh Wilson
+* Justus Magin
+* Kai Striega
+* Kerem Hallaç +
+* Kevin Sheppard
+* Kirill Zinovjev +
+* Marcin Podhajski +
+* Mark Harfouche
+* Marten van Kerkwijk
+* Martin Michlmayr +
+* Masashi Kishimoto +
+* Mathieu Lamarre
+* Matt Hancock +
+* MatteoRaso +
+* Matthew Harrigan
+* Matthias Bussonnier
+* Matti Picus
+* Max Balandat +
+* Maximilian Konrad +
+* Maxwell Aladago
+* Maxwell Bileschi +
+* Melissa Weber Mendonça +
+* Michael Felt
+* Michael Hirsch +
+* Mike Taves
+* Nico Schlömer
+* Pan Jan +
+* Paul Rougieux +
+* Pauli Virtanen
+* Peter Andreas Entschev
+* Petre-Flaviu Gostin +
+* Pierre de Buyl
+* Piotr GaiÅ„ski +
+* Przemyslaw Bartosik +
+* Raghuveer Devulapalli
+* Rakesh Vasudevan +
+* Ralf Gommers
+* RenaRuirui +
+* Robert Kern
+* Roman Yurchak
+* Ross Barnowski +
+* Ryan +
+* Ryan Soklaski
+* Sanjeev Kumar +
+* SanthoshBala18 +
+* Sayed Adel +
+* Sebastian Berg
+* Seth Troisi
+* Sha Liu +
+* Siba Smarak Panigrahi +
+* Simon Gasse +
+* Stephan Hoyer
+* Steve Dower +
+* Thomas A Caswell
+* Till Hoffmann +
+* Tim Hoffmann
+* Tina Oberoi +
+* Tirth Patel
+* Tyler Reddy
+* Warren Weckesser
+* Wojciech Rzadkowski +
+* Xavier Thomas +
+* Yilin LI +
+* Zac Hatfield-Dodds +
+* Zé Vinícius +
+* @Adam +
+* @Anthony +
+* @Jim +
+* @bartosz-grabowski +
+* @dojafrat +
+* @gamboon +
+* @jfbu +
+* @keremh +
+* @mayeut +
+* @ndunnewind +
+* @nglinh +
+* @shreepads +
+* @sslivkoff +
+
+
+Pull requests merged
+====================
+
+A total of 452 pull requests were merged for this release.
+
+* `#8255 <https://github.com/numpy/numpy/pull/8255>`__: ENH: add identity kwarg to frompyfunc
+* `#12646 <https://github.com/numpy/numpy/pull/12646>`__: TST: check exception details in refguide_check.py
+* `#13421 <https://github.com/numpy/numpy/pull/13421>`__: ENH: improve runtime detection of CPU features
+* `#14326 <https://github.com/numpy/numpy/pull/14326>`__: TST: Add assert_array_equal test for big integer arrays.
+* `#14376 <https://github.com/numpy/numpy/pull/14376>`__: MAINT: Remove unnecessary 'from __future__ import ...' statements
+* `#14530 <https://github.com/numpy/numpy/pull/14530>`__: MAINT: Fix typos and copy edit NEP-0030.
+* `#14546 <https://github.com/numpy/numpy/pull/14546>`__: DOC: NumPy for absolute beginners tutorial
+* `#14715 <https://github.com/numpy/numpy/pull/14715>`__: NEP: Proposal for array creation dispatching with `__array_function__`
+* `#14867 <https://github.com/numpy/numpy/pull/14867>`__: ENH: Use AVX-512F for np.maximum and np.minimum
+* `#14924 <https://github.com/numpy/numpy/pull/14924>`__: BUG: Fix numpy.random.dirichlet returns NaN for small 'alpha'...
+* `#14933 <https://github.com/numpy/numpy/pull/14933>`__: API: Use `ResultType` in `PyArray_ConvertToCommonType`
+* `#14942 <https://github.com/numpy/numpy/pull/14942>`__: MAINT,API: ignore and NULL fasttake/fastputmask ArrFuncs slots
+* `#14981 <https://github.com/numpy/numpy/pull/14981>`__: BUG: Make ``ediff1d`` kwarg casting consistent
+* `#14988 <https://github.com/numpy/numpy/pull/14988>`__: DOC: linalg: Include information about scipy.linalg.
+* `#14995 <https://github.com/numpy/numpy/pull/14995>`__: BUG: Use ``__array__`` during dimension discovery
+* `#15011 <https://github.com/numpy/numpy/pull/15011>`__: MAINT: cleanup compat.py3k.py
+* `#15022 <https://github.com/numpy/numpy/pull/15022>`__: ENH: f2py: improve error messages
+* `#15028 <https://github.com/numpy/numpy/pull/15028>`__: [DOC] LaTeX: fix preamble (closes #15026)
+* `#15035 <https://github.com/numpy/numpy/pull/15035>`__: BUG: add endfunction, endsubroutine to valid fortran end words
+* `#15040 <https://github.com/numpy/numpy/pull/15040>`__: TST: Add test for object method (and general unary) loops
+* `#15042 <https://github.com/numpy/numpy/pull/15042>`__: REL: Update master after 1.18.x branch.
+* `#15043 <https://github.com/numpy/numpy/pull/15043>`__: DOC: Update HOWTO_RELEASE.rst.txt
+* `#15046 <https://github.com/numpy/numpy/pull/15046>`__: API, DOC: change names to multivariate_hypergeometric, improve...
+* `#15050 <https://github.com/numpy/numpy/pull/15050>`__: DOC: Fix statement about norms
+* `#15052 <https://github.com/numpy/numpy/pull/15052>`__: MAINT: follow-up cleanup for blas64 PR
+* `#15054 <https://github.com/numpy/numpy/pull/15054>`__: DOC: add docstrings to refguide-check
+* `#15066 <https://github.com/numpy/numpy/pull/15066>`__: Revert "DEP: issue deprecation warning when creating ragged array...
+* `#15069 <https://github.com/numpy/numpy/pull/15069>`__: ENH: add support for ILP64 OpenBLAS (without symbol suffix)
+* `#15070 <https://github.com/numpy/numpy/pull/15070>`__: DOC: correct version for NaT sort
+* `#15072 <https://github.com/numpy/numpy/pull/15072>`__: TST: Check requires_memory immediately before the test
+* `#15073 <https://github.com/numpy/numpy/pull/15073>`__: MAINT: core: Fix a very long line in the ufunc docstrings.
+* `#15076 <https://github.com/numpy/numpy/pull/15076>`__: BUG: test, fix flexible dtype conversion on class with __array__
+* `#15082 <https://github.com/numpy/numpy/pull/15082>`__: TST: add value to pytest.ini for pytest6 compatibility
+* `#15085 <https://github.com/numpy/numpy/pull/15085>`__: MAINT: Ragged cleanup
+* `#15097 <https://github.com/numpy/numpy/pull/15097>`__: DOC: bring the out parameter docstring into line with ufuncs
+* `#15106 <https://github.com/numpy/numpy/pull/15106>`__: ENH: f2py: add --f2cmap option for specifying the name of .f2py_f2cmap
+* `#15107 <https://github.com/numpy/numpy/pull/15107>`__: TST: add BLAS ILP64 run in Travis & Azure
+* `#15110 <https://github.com/numpy/numpy/pull/15110>`__: MAINT: Fix expm1 instability for small complex numbers.
+* `#15115 <https://github.com/numpy/numpy/pull/15115>`__: MAINT: random: Remove a few unused imports from test files.
+* `#15116 <https://github.com/numpy/numpy/pull/15116>`__: MAINT: Bump pytest from 5.3.1 to 5.3.2
+* `#15118 <https://github.com/numpy/numpy/pull/15118>`__: API: remove undocumented use of __array__(dtype, context)
+* `#15120 <https://github.com/numpy/numpy/pull/15120>`__: MAINT,CI: fix signed-unsigned comparison warning
+* `#15124 <https://github.com/numpy/numpy/pull/15124>`__: DOC: Update documentation of np.clip
+* `#15125 <https://github.com/numpy/numpy/pull/15125>`__: DOC: Remove reference to basic RNG
+* `#15126 <https://github.com/numpy/numpy/pull/15126>`__: MAINT: Fix randint 0d limits and other 0d cleanups
+* `#15129 <https://github.com/numpy/numpy/pull/15129>`__: DOC: Fix typos, via a Levenshtein-style corrector
+* `#15133 <https://github.com/numpy/numpy/pull/15133>`__: MAINT: CI: Clean up .travis.yml
+* `#15136 <https://github.com/numpy/numpy/pull/15136>`__: DOC: Correct choice signature
+* `#15138 <https://github.com/numpy/numpy/pull/15138>`__: DOC: Correct documentation in choice
+* `#15143 <https://github.com/numpy/numpy/pull/15143>`__: TST: shippable build efficiency
+* `#15144 <https://github.com/numpy/numpy/pull/15144>`__: BUG: ensure reduction output matches input along non-reduction...
+* `#15149 <https://github.com/numpy/numpy/pull/15149>`__: REL: Update master after NumPy 1.18.0 release.
+* `#15150 <https://github.com/numpy/numpy/pull/15150>`__: MAINT: Update pavement.py for towncrier.
+* `#15153 <https://github.com/numpy/numpy/pull/15153>`__: DOC: update cholesky docstring regarding input checking
+* `#15154 <https://github.com/numpy/numpy/pull/15154>`__: DOC: update documentation on how to build NumPy
+* `#15156 <https://github.com/numpy/numpy/pull/15156>`__: DOC: add moved modules to 1.18 release note
+* `#15160 <https://github.com/numpy/numpy/pull/15160>`__: MAINT: Update required cython version to 0.29.14.
+* `#15164 <https://github.com/numpy/numpy/pull/15164>`__: BUG: searchsorted: passing the keys as a keyword argument
+* `#15170 <https://github.com/numpy/numpy/pull/15170>`__: BUG: use tmp dir and check version for cython test
+* `#15178 <https://github.com/numpy/numpy/pull/15178>`__: TST: improve assert message of assert_array_max_ulp
+* `#15187 <https://github.com/numpy/numpy/pull/15187>`__: MAINT: unskip test on win32
+* `#15189 <https://github.com/numpy/numpy/pull/15189>`__: ENH: Add property-based tests using Hypothesis
+* `#15194 <https://github.com/numpy/numpy/pull/15194>`__: BUG: test, fix for c++ compilation
+* `#15196 <https://github.com/numpy/numpy/pull/15196>`__: DOC: Adding instructions for building documentation to developer...
+* `#15197 <https://github.com/numpy/numpy/pull/15197>`__: DOC: NEP 37: A dispatch protocol for NumPy-like modules
+* `#15203 <https://github.com/numpy/numpy/pull/15203>`__: MAINT: Do not use private Python function in testing
+* `#15205 <https://github.com/numpy/numpy/pull/15205>`__: DOC: Improvements to Quickstart Tutorial.
+* `#15211 <https://github.com/numpy/numpy/pull/15211>`__: BUG: distutils: fix msvc+gfortran openblas handling corner case
+* `#15212 <https://github.com/numpy/numpy/pull/15212>`__: BUG: lib: Fix handling of integer arrays by gradient.
+* `#15215 <https://github.com/numpy/numpy/pull/15215>`__: MAINT: lib: A little bit of clean up for the new year.
+* `#15216 <https://github.com/numpy/numpy/pull/15216>`__: REL: Update master after NumPy 1.16.6 and 1.17.5 releases.
+* `#15217 <https://github.com/numpy/numpy/pull/15217>`__: DEP: records: Deprecate treating shape=0 as shape=None
+* `#15218 <https://github.com/numpy/numpy/pull/15218>`__: ENH: build fallback lapack_lite with 64-bit integers on 64-bit...
+* `#15224 <https://github.com/numpy/numpy/pull/15224>`__: MAINT: linalg: use symbol suffix in fallback lapack_lite
+* `#15227 <https://github.com/numpy/numpy/pull/15227>`__: DOC: typo in release.rst
+* `#15228 <https://github.com/numpy/numpy/pull/15228>`__: NEP: universal SIMD NEP 38
+* `#15229 <https://github.com/numpy/numpy/pull/15229>`__: MAINT: Remove unused int_asbuffer
+* `#15232 <https://github.com/numpy/numpy/pull/15232>`__: MAINT: Cleaning up PY_MAJOR_VERSION/PY_VERSION_HEX
+* `#15233 <https://github.com/numpy/numpy/pull/15233>`__: MAINT: Clean up more PY_VERSION_HEX
+* `#15236 <https://github.com/numpy/numpy/pull/15236>`__: MAINT: Remove implicit inheritance from object class
+* `#15238 <https://github.com/numpy/numpy/pull/15238>`__: MAINT: only add --std=c99 where needed
+* `#15239 <https://github.com/numpy/numpy/pull/15239>`__: MAINT: Remove Python2 newbuffer getbuffer
+* `#15240 <https://github.com/numpy/numpy/pull/15240>`__: MAINT: Py3K array_as_buffer and gentype_as_buffer
+* `#15241 <https://github.com/numpy/numpy/pull/15241>`__: MAINT: Remove references to non-existent sys.exc_clear()
+* `#15242 <https://github.com/numpy/numpy/pull/15242>`__: DOC: Update HOWTO_RELEASE.rst
+* `#15248 <https://github.com/numpy/numpy/pull/15248>`__: MAINT: cleanup use of sys.exc_info
+* `#15249 <https://github.com/numpy/numpy/pull/15249>`__: MAINT: Eliminate some calls to `eval`
+* `#15251 <https://github.com/numpy/numpy/pull/15251>`__: MAINT: Improve const-correctness of shapes and strides
+* `#15253 <https://github.com/numpy/numpy/pull/15253>`__: DOC: clarify the effect of None parameters passed to ndarray.view
+* `#15254 <https://github.com/numpy/numpy/pull/15254>`__: MAINT: Improve const-correctness of string arguments
+* `#15255 <https://github.com/numpy/numpy/pull/15255>`__: MAINT: Delete numpy.distutils.compat
+* `#15256 <https://github.com/numpy/numpy/pull/15256>`__: MAINT: Implement keyword-only arguments as syntax
+* `#15260 <https://github.com/numpy/numpy/pull/15260>`__: MAINT: Remove FIXME comments introduced in the previous commit
+* `#15261 <https://github.com/numpy/numpy/pull/15261>`__: MAINT: Work with unicode strings in `dtype('i8,i8')`
+* `#15262 <https://github.com/numpy/numpy/pull/15262>`__: BUG: Use PyDict_GetItemWithError() instead of PyDict_GetItem()
+* `#15263 <https://github.com/numpy/numpy/pull/15263>`__: MAINT: Remove python2 array_{get,set}slice
+* `#15264 <https://github.com/numpy/numpy/pull/15264>`__: DOC: Add some missing functions in the list of available ufuncs.
+* `#15265 <https://github.com/numpy/numpy/pull/15265>`__: MAINT: Tidy PyArray_DescrConverter
+* `#15266 <https://github.com/numpy/numpy/pull/15266>`__: MAINT: remove duplicated if statements between DescrConverters
+* `#15267 <https://github.com/numpy/numpy/pull/15267>`__: BUG: Fix PyArray_DescrAlignConverter2 on tuples
+* `#15268 <https://github.com/numpy/numpy/pull/15268>`__: MAINT: Remove Python2 ndarray.__unicode__
+* `#15272 <https://github.com/numpy/numpy/pull/15272>`__: MAINT: Remove Python 2 divide
+* `#15273 <https://github.com/numpy/numpy/pull/15273>`__: MAINT: minor formatting fixups for NEP-37
+* `#15274 <https://github.com/numpy/numpy/pull/15274>`__: MAINT: Post NumPy 1.18.1 update.
+* `#15275 <https://github.com/numpy/numpy/pull/15275>`__: MAINT: travis-ci: Update CI scripts.
+* `#15278 <https://github.com/numpy/numpy/pull/15278>`__: BENCH: Add benchmark for small array coercions
+* `#15279 <https://github.com/numpy/numpy/pull/15279>`__: BUILD: use standard build of OpenBLAS for aarch64, ppc64le, s390x
+* `#15280 <https://github.com/numpy/numpy/pull/15280>`__: BENCH: Add basic benchmarks for take and putmask
+* `#15281 <https://github.com/numpy/numpy/pull/15281>`__: MAINT: Cleanup most PY3K #ifdef guards
+* `#15282 <https://github.com/numpy/numpy/pull/15282>`__: DOC: BLD: add empty release notes for 1.19.0 to fix doc build...
+* `#15284 <https://github.com/numpy/numpy/pull/15284>`__: MAINT: Use a simpler return convention for internal functions
+* `#15285 <https://github.com/numpy/numpy/pull/15285>`__: MAINT: Simplify np.int_ inheritance
+* `#15286 <https://github.com/numpy/numpy/pull/15286>`__: DOC" Update np.full docstring.
+* `#15287 <https://github.com/numpy/numpy/pull/15287>`__: MAINT: Express PyArray_DescrAlignConverter in terms of _convert_from_any
+* `#15288 <https://github.com/numpy/numpy/pull/15288>`__: MAINT: Push down declarations in _convert_from_*
+* `#15289 <https://github.com/numpy/numpy/pull/15289>`__: MAINT: C code simplifications
+* `#15291 <https://github.com/numpy/numpy/pull/15291>`__: BUG: Add missing error handling to _convert_from_list
+* `#15295 <https://github.com/numpy/numpy/pull/15295>`__: DOC: Added tutorial about linear algebra on multidimensional...
+* `#15300 <https://github.com/numpy/numpy/pull/15300>`__: MAINT: Refactor dtype conversion functions to be more similar
+* `#15303 <https://github.com/numpy/numpy/pull/15303>`__: DOC: Updating f2py docs to python 3 and fixing some typos
+* `#15304 <https://github.com/numpy/numpy/pull/15304>`__: MAINT: Remove NPY_PY3K constant
+* `#15305 <https://github.com/numpy/numpy/pull/15305>`__: MAINT: Remove sys.version checks in tests
+* `#15307 <https://github.com/numpy/numpy/pull/15307>`__: MAINT: cleanup sys.version dependant code
+* `#15310 <https://github.com/numpy/numpy/pull/15310>`__: MAINT: Ensure `_convert_from_*` functions set errors
+* `#15312 <https://github.com/numpy/numpy/pull/15312>`__: MAINT: Avoid escaping unicode in error messages
+* `#15315 <https://github.com/numpy/numpy/pull/15315>`__: MAINT: Change file extension of ma README to rst.
+* `#15319 <https://github.com/numpy/numpy/pull/15319>`__: BUG: fix NameError in clip nan propagation tests
+* `#15323 <https://github.com/numpy/numpy/pull/15323>`__: NEP: document reimplementation of NEP 34
+* `#15324 <https://github.com/numpy/numpy/pull/15324>`__: MAINT: fix typos
+* `#15328 <https://github.com/numpy/numpy/pull/15328>`__: TST: move pypy CI to ubuntu 18.04
+* `#15329 <https://github.com/numpy/numpy/pull/15329>`__: TST: move _no_tracing to testing._private, remove testing.support
+* `#15333 <https://github.com/numpy/numpy/pull/15333>`__: BUG: Add some missing C error handling
+* `#15335 <https://github.com/numpy/numpy/pull/15335>`__: MAINT: Remove sys.version checks
+* `#15336 <https://github.com/numpy/numpy/pull/15336>`__: DEP: Deprecate `->f->fastclip` at registration time
+* `#15338 <https://github.com/numpy/numpy/pull/15338>`__: DOC: document site.cfg.example
+* `#15350 <https://github.com/numpy/numpy/pull/15350>`__: MAINT: Fix mistype in histogramdd docstring
+* `#15351 <https://github.com/numpy/numpy/pull/15351>`__: DOC, BLD: reword release note, upgrade sphinx version
+* `#15353 <https://github.com/numpy/numpy/pull/15353>`__: MAINT: Remove unnecessary calls to PyArray_DATA from binomial...
+* `#15354 <https://github.com/numpy/numpy/pull/15354>`__: MAINT: Bump pytest from 5.3.2 to 5.3.3
+* `#15358 <https://github.com/numpy/numpy/pull/15358>`__: MAINT: Remove six
+* `#15361 <https://github.com/numpy/numpy/pull/15361>`__: MAINT: Revise imports from collections.abc module
+* `#15362 <https://github.com/numpy/numpy/pull/15362>`__: MAINT: remove internal functions required to handle Python2/3...
+* `#15364 <https://github.com/numpy/numpy/pull/15364>`__: MAINT: Remove other uses of six module
+* `#15366 <https://github.com/numpy/numpy/pull/15366>`__: MAINT: resolve pyflake F403 'from module import *' used
+* `#15368 <https://github.com/numpy/numpy/pull/15368>`__: MAINT: Update tox for supported Python versions
+* `#15369 <https://github.com/numpy/numpy/pull/15369>`__: MAINT: simd: Avoid signed comparison warning
+* `#15370 <https://github.com/numpy/numpy/pull/15370>`__: DOC: Updating Chararry Buffer datatypes #15360
+* `#15374 <https://github.com/numpy/numpy/pull/15374>`__: TST: Simplify unicode test
+* `#15375 <https://github.com/numpy/numpy/pull/15375>`__: MAINT: Use `with open` when possible
+* `#15377 <https://github.com/numpy/numpy/pull/15377>`__: MAINT: Cleanup python2 references
+* `#15379 <https://github.com/numpy/numpy/pull/15379>`__: MAINT: Python2 Cleanups
+* `#15381 <https://github.com/numpy/numpy/pull/15381>`__: DEP: add PendingDeprecation to matlib.py funky namespace
+* `#15385 <https://github.com/numpy/numpy/pull/15385>`__: BUG, MAINT: Stop using the error-prone deprecated Py_UNICODE...
+* `#15386 <https://github.com/numpy/numpy/pull/15386>`__: MAINT: clean up some macros in scalarapi.c
+* `#15393 <https://github.com/numpy/numpy/pull/15393>`__: MAINT/BUG: Fixups to scalar base classes
+* `#15397 <https://github.com/numpy/numpy/pull/15397>`__: BUG: np.load does not handle empty array with an empty descr
+* `#15398 <https://github.com/numpy/numpy/pull/15398>`__: MAINT: Revise imports from urllib modules
+* `#15399 <https://github.com/numpy/numpy/pull/15399>`__: MAINT: Remove Python3 DeprecationWarning from pytest.ini
+* `#15400 <https://github.com/numpy/numpy/pull/15400>`__: MAINT: cleanup _pytesttester.py
+* `#15401 <https://github.com/numpy/numpy/pull/15401>`__: BUG: Flags should not contain spaces
+* `#15403 <https://github.com/numpy/numpy/pull/15403>`__: MAINT: Clean up, mostly unused imports.
+* `#15405 <https://github.com/numpy/numpy/pull/15405>`__: BUG/TEST: core: Fix an undefined name in a test.
+* `#15407 <https://github.com/numpy/numpy/pull/15407>`__: MAINT: Replace basestring with str.
+* `#15408 <https://github.com/numpy/numpy/pull/15408>`__: ENH: Use AVX-512F for complex number arithmetic, absolute, square...
+* `#15414 <https://github.com/numpy/numpy/pull/15414>`__: MAINT: Remove Python2 workarounds
+* `#15417 <https://github.com/numpy/numpy/pull/15417>`__: MAINT: Cleanup references to python2
+* `#15418 <https://github.com/numpy/numpy/pull/15418>`__: MAINT, DOC: Remove use of old Python __builtin__, now known as...
+* `#15421 <https://github.com/numpy/numpy/pull/15421>`__: ENH: Make use of ExitStack in npyio.py
+* `#15422 <https://github.com/numpy/numpy/pull/15422>`__: MAINT: Inline gentype_getreadbuf
+* `#15423 <https://github.com/numpy/numpy/pull/15423>`__: MAINT: Use f-strings for clarity.
+* `#15427 <https://github.com/numpy/numpy/pull/15427>`__: DEP: Schedule unused C-API functions for removal/disabling
+* `#15428 <https://github.com/numpy/numpy/pull/15428>`__: DOC: Improve ndarray.ctypes example
+* `#15429 <https://github.com/numpy/numpy/pull/15429>`__: DOC: distutils: Add a docstring to show_config().
+* `#15430 <https://github.com/numpy/numpy/pull/15430>`__: MAINT: Use contextmanager in _run_doctests
+* `#15434 <https://github.com/numpy/numpy/pull/15434>`__: MAINT: Updated polynomial to use fstrings
+* `#15435 <https://github.com/numpy/numpy/pull/15435>`__: DOC: Fix Incorrect document in Beginner Docs
+* `#15436 <https://github.com/numpy/numpy/pull/15436>`__: MAINT: Update core.py with fstrings (issue #15420)
+* `#15439 <https://github.com/numpy/numpy/pull/15439>`__: DOC: fix docstrings so `python tools/refguide-check --rst <file>...
+* `#15441 <https://github.com/numpy/numpy/pull/15441>`__: MAINT: Tidy macros in scalar_new
+* `#15444 <https://github.com/numpy/numpy/pull/15444>`__: MAINT: use 'yield from <expr>' for simple cases
+* `#15445 <https://github.com/numpy/numpy/pull/15445>`__: MAINT: Bump pytest from 5.3.3 to 5.3.4
+* `#15446 <https://github.com/numpy/numpy/pull/15446>`__: BUG: Reject nonsense arguments to scalar constructors
+* `#15449 <https://github.com/numpy/numpy/pull/15449>`__: DOC: Update refguide_check note on how to skip code
+* `#15451 <https://github.com/numpy/numpy/pull/15451>`__: MAINT: Simplify `np.object_.__new__`
+* `#15452 <https://github.com/numpy/numpy/pull/15452>`__: STY,MAINT: avoid 'multiple imports on one line'
+* `#15464 <https://github.com/numpy/numpy/pull/15464>`__: MAINT: Cleanup duplicate line in refguide_check
+* `#15465 <https://github.com/numpy/numpy/pull/15465>`__: MAINT: cleanup unused imports; avoid redefinition of imports
+* `#15468 <https://github.com/numpy/numpy/pull/15468>`__: BUG: Fix for SVD not always sorted with hermitian=True
+* `#15469 <https://github.com/numpy/numpy/pull/15469>`__: MAINT: Simplify scalar __new__ some more
+* `#15474 <https://github.com/numpy/numpy/pull/15474>`__: MAINT: Eliminate messy _WORK macro
+* `#15476 <https://github.com/numpy/numpy/pull/15476>`__: update result of rng.random(3) to current rng output
+* `#15480 <https://github.com/numpy/numpy/pull/15480>`__: DOC: Correct get_state doc
+* `#15482 <https://github.com/numpy/numpy/pull/15482>`__: MAINT: Use `.identifier = val` to fill type structs
+* `#15483 <https://github.com/numpy/numpy/pull/15483>`__: [DOC] Mention behaviour of np.squeeze with one element
+* `#15484 <https://github.com/numpy/numpy/pull/15484>`__: ENH: fixing generic error messages to be more specific in multiarray/descriptor.c
+* `#15487 <https://github.com/numpy/numpy/pull/15487>`__: BUG: Fixing result of np quantile edge case
+* `#15491 <https://github.com/numpy/numpy/pull/15491>`__: TST: mark the top 3 slowest tests to save ~10 seconds
+* `#15493 <https://github.com/numpy/numpy/pull/15493>`__: MAINT: Bump pytest from 5.3.4 to 5.3.5
+* `#15500 <https://github.com/numpy/numpy/pull/15500>`__: MAINT: Use True/False instead of 1/0 in np.dtype.__reduce__
+* `#15503 <https://github.com/numpy/numpy/pull/15503>`__: MAINT: Do not allow `copyswap` and friends to fail silently
+* `#15504 <https://github.com/numpy/numpy/pull/15504>`__: DOC: Remove duplicated code in true_divide docstring
+* `#15505 <https://github.com/numpy/numpy/pull/15505>`__: NEP 40: Informational NEP about current DTypes
+* `#15510 <https://github.com/numpy/numpy/pull/15510>`__: DOC: Update unique docstring example
+* `#15511 <https://github.com/numpy/numpy/pull/15511>`__: MAINT: Large overhead in some random functions
+* `#15516 <https://github.com/numpy/numpy/pull/15516>`__: TST: Fix missing output in refguide-check
+* `#15521 <https://github.com/numpy/numpy/pull/15521>`__: MAINT: Simplify arraydescr_richcompare
+* `#15522 <https://github.com/numpy/numpy/pull/15522>`__: MAINT: Fix internal misuses of `NPY_TITLE_KEY`
+* `#15524 <https://github.com/numpy/numpy/pull/15524>`__: DOC: Update instructions for building/archiving docs.
+* `#15526 <https://github.com/numpy/numpy/pull/15526>`__: BUG: Fix inline assembly that detects cpu features on x86(32bit)
+* `#15532 <https://github.com/numpy/numpy/pull/15532>`__: update doctests, small bugs and changes of repr
+* `#15534 <https://github.com/numpy/numpy/pull/15534>`__: DEP: Do not allow "abstract" dtype conversion/creation
+* `#15536 <https://github.com/numpy/numpy/pull/15536>`__: DOC: Minor copyediting on NEP 37.
+* `#15538 <https://github.com/numpy/numpy/pull/15538>`__: MAINT: Extract repeated code to a helper function
+* `#15543 <https://github.com/numpy/numpy/pull/15543>`__: NEP: edit and move NEP 38 to accepted status
+* `#15547 <https://github.com/numpy/numpy/pull/15547>`__: MAINT: Refresh Doxyfile and modernize numpyfilter.py
+* `#15549 <https://github.com/numpy/numpy/pull/15549>`__: TST: Accuracy test float32 sin/cos/exp/log for AVX platforms
+* `#15550 <https://github.com/numpy/numpy/pull/15550>`__: DOC: Improve the `numpy.linalg.eig` docstring.
+* `#15554 <https://github.com/numpy/numpy/pull/15554>`__: NEP 44 - Restructuring the NumPy Documentation
+* `#15556 <https://github.com/numpy/numpy/pull/15556>`__: TST: (Travis CI) Use full python3-dbg path for virtual env creation
+* `#15560 <https://github.com/numpy/numpy/pull/15560>`__: BUG, DOC: restore missing import
+* `#15566 <https://github.com/numpy/numpy/pull/15566>`__: DOC: Removing bad practices from quick start + some PEP8
+* `#15574 <https://github.com/numpy/numpy/pull/15574>`__: TST: Do not create symbolic link named gfortran.
+* `#15575 <https://github.com/numpy/numpy/pull/15575>`__: DOC: Document caveat in random.uniform
+* `#15579 <https://github.com/numpy/numpy/pull/15579>`__: DOC: numpy.clip is equivalent to minimum(..., maximum(...))
+* `#15582 <https://github.com/numpy/numpy/pull/15582>`__: MAINT: Bump cython from 0.29.14 to 0.29.15
+* `#15583 <https://github.com/numpy/numpy/pull/15583>`__: MAINT: Bump hypothesis from 5.3.0 to 5.5.4
+* `#15585 <https://github.com/numpy/numpy/pull/15585>`__: BLD: manylinux2010 docker reports machine=i686
+* `#15598 <https://github.com/numpy/numpy/pull/15598>`__: BUG: Ignore differences in NAN for computing ULP differences
+* `#15600 <https://github.com/numpy/numpy/pull/15600>`__: TST: use manylinux2010 docker instead of ubuntu
+* `#15610 <https://github.com/numpy/numpy/pull/15610>`__: TST: mask DeprecationWarning in xfailed test
+* `#15612 <https://github.com/numpy/numpy/pull/15612>`__: BUG: Fix bug in AVX-512F np.maximum and np.minimum
+* `#15615 <https://github.com/numpy/numpy/pull/15615>`__: BUG: Remove check requiring natural alignment of float/double...
+* `#15616 <https://github.com/numpy/numpy/pull/15616>`__: DOC: Add missing imports, definitions and dummy file
+* `#15619 <https://github.com/numpy/numpy/pull/15619>`__: DOC: Fix documentation for apply_along_axis
+* `#15624 <https://github.com/numpy/numpy/pull/15624>`__: DOC: fix printing, np., deprecation for refguide
+* `#15631 <https://github.com/numpy/numpy/pull/15631>`__: MAINT: Pull identical line out of conditional.
+* `#15633 <https://github.com/numpy/numpy/pull/15633>`__: DOC: remove broken link in f2py tutorial
+* `#15639 <https://github.com/numpy/numpy/pull/15639>`__: BLD: update openblas download to new location, use manylinux2010-base
+* `#15648 <https://github.com/numpy/numpy/pull/15648>`__: MAINT: AVX512 implementation with intrinsic for float64 input...
+* `#15653 <https://github.com/numpy/numpy/pull/15653>`__: BLD: update OpenBLAS to pre-0.3.9 version
+* `#15662 <https://github.com/numpy/numpy/pull/15662>`__: DOC: Refactor `np.polynomial` docs using `automodule`
+* `#15665 <https://github.com/numpy/numpy/pull/15665>`__: BUG: fix doctest exception messages
+* `#15672 <https://github.com/numpy/numpy/pull/15672>`__: MAINT: Added comment pointing FIXME to relevant PR.
+* `#15673 <https://github.com/numpy/numpy/pull/15673>`__: DOC: Make extension module wording more clear
+* `#15678 <https://github.com/numpy/numpy/pull/15678>`__: DOC: Improve np.finfo docs
+* `#15680 <https://github.com/numpy/numpy/pull/15680>`__: DOC: Improve Benchmark README with environment setup and more...
+* `#15682 <https://github.com/numpy/numpy/pull/15682>`__: MAINT: Bump hypothesis from 5.5.4 to 5.6.0
+* `#15683 <https://github.com/numpy/numpy/pull/15683>`__: NEP: move NEP 44 to accepted status
+* `#15694 <https://github.com/numpy/numpy/pull/15694>`__: DOC: Fix indexing docs to pass refguide
+* `#15695 <https://github.com/numpy/numpy/pull/15695>`__: MAINT: Test during import to detect bugs with Accelerate(MacOS)...
+* `#15696 <https://github.com/numpy/numpy/pull/15696>`__: MAINT: Add a fast path to var for complex input
+* `#15701 <https://github.com/numpy/numpy/pull/15701>`__: MAINT: Convert shebang from python to python3 (#15687)
+* `#15702 <https://github.com/numpy/numpy/pull/15702>`__: MAINT: replace optparse with argparse for 'doc' and 'tools' scripts
+* `#15703 <https://github.com/numpy/numpy/pull/15703>`__: DOC: Fix quickstart doc to pass refguide
+* `#15706 <https://github.com/numpy/numpy/pull/15706>`__: MAINT: Fixing typos in f2py comments and code.
+* `#15710 <https://github.com/numpy/numpy/pull/15710>`__: DOC: fix SVD tutorial to pass refguide
+* `#15714 <https://github.com/numpy/numpy/pull/15714>`__: MAINT: use list-based APIs to call subprocesses
+* `#15715 <https://github.com/numpy/numpy/pull/15715>`__: ENH: update numpy.linalg.multi_dot to accept an `out` argument
+* `#15716 <https://github.com/numpy/numpy/pull/15716>`__: TST: always use 'python -mpip' not 'pip'
+* `#15717 <https://github.com/numpy/numpy/pull/15717>`__: DOC: update datetime reference to pass refguide
+* `#15718 <https://github.com/numpy/numpy/pull/15718>`__: DOC: Fix coremath.rst to fix refguide_check
+* `#15720 <https://github.com/numpy/numpy/pull/15720>`__: DOC: fix remaining doc files for refguide_check
+* `#15723 <https://github.com/numpy/numpy/pull/15723>`__: BUG: fix logic error when nm fails on 32-bit
+* `#15724 <https://github.com/numpy/numpy/pull/15724>`__: TST: Remove nose from the test_requirements.txt file.
+* `#15733 <https://github.com/numpy/numpy/pull/15733>`__: DOC: Allow NEPs to link to python, numpy, scipy, and matplotlib...
+* `#15736 <https://github.com/numpy/numpy/pull/15736>`__: BUG: Guarantee array is in valid state after memory error occurs...
+* `#15738 <https://github.com/numpy/numpy/pull/15738>`__: MAINT: Remove non-native byte order from _var check.
+* `#15740 <https://github.com/numpy/numpy/pull/15740>`__: MAINT: Add better error handling in linalg.norm for vectors and...
+* `#15745 <https://github.com/numpy/numpy/pull/15745>`__: MAINT: doc: Remove doc/summarize.py
+* `#15747 <https://github.com/numpy/numpy/pull/15747>`__: BUG: lib: Handle axes with length 0 in np.unique.
+* `#15749 <https://github.com/numpy/numpy/pull/15749>`__: DOC: document inconsistency between the shape of data and mask...
+* `#15750 <https://github.com/numpy/numpy/pull/15750>`__: BUG, TST: fix f2py for PyPy, skip one test for PyPy
+* `#15752 <https://github.com/numpy/numpy/pull/15752>`__: MAINT: Fix swig tests issue #15743
+* `#15757 <https://github.com/numpy/numpy/pull/15757>`__: MAINT: CI: Add an explicit 'pr' section to azure-pipelines.yml
+* `#15762 <https://github.com/numpy/numpy/pull/15762>`__: MAINT: Bump pytest from 5.3.5 to 5.4.1
+* `#15766 <https://github.com/numpy/numpy/pull/15766>`__: BUG,MAINT: Remove incorrect special case in string to number...
+* `#15768 <https://github.com/numpy/numpy/pull/15768>`__: REL: Update master after 1.18.2 release.
+* `#15769 <https://github.com/numpy/numpy/pull/15769>`__: ENH: Allow toggling madvise hugepage and fix default
+* `#15771 <https://github.com/numpy/numpy/pull/15771>`__: DOC: Fix runtests example in developer docs
+* `#15773 <https://github.com/numpy/numpy/pull/15773>`__: DEP: Make issubdtype consistent for types and dtypes
+* `#15774 <https://github.com/numpy/numpy/pull/15774>`__: MAINT: remove useless `global` statements
+* `#15778 <https://github.com/numpy/numpy/pull/15778>`__: BLD: Add requirements.txt file for building docs
+* `#15781 <https://github.com/numpy/numpy/pull/15781>`__: BUG: don't add 'public' or 'private' if the other one exists
+* `#15784 <https://github.com/numpy/numpy/pull/15784>`__: ENH: Use TypeError in `np.array` for python consistency
+* `#15794 <https://github.com/numpy/numpy/pull/15794>`__: BUG: Add basic __format__ for masked element to fix incorrect...
+* `#15797 <https://github.com/numpy/numpy/pull/15797>`__: TST: Add unit test for out=None of np.einsum
+* `#15799 <https://github.com/numpy/numpy/pull/15799>`__: MAINT: Cleanups to np.insert and np.delete
+* `#15800 <https://github.com/numpy/numpy/pull/15800>`__: BUG: Add error-checking versions of strided casts.
+* `#15802 <https://github.com/numpy/numpy/pull/15802>`__: DEP: Make `np.insert` and `np.delete` on 0d arrays with an axis...
+* `#15803 <https://github.com/numpy/numpy/pull/15803>`__: DOC: correct possible list lengths for `extobj` in ufunc calls
+* `#15804 <https://github.com/numpy/numpy/pull/15804>`__: DEP: Make np.delete on out-of-bounds indices an error
+* `#15805 <https://github.com/numpy/numpy/pull/15805>`__: DEP: Forbid passing non-integral index arrays to `insert` and...
+* `#15806 <https://github.com/numpy/numpy/pull/15806>`__: TST: Parametrize sort test
+* `#15809 <https://github.com/numpy/numpy/pull/15809>`__: TST: switch PyPy job with CPython
+* `#15812 <https://github.com/numpy/numpy/pull/15812>`__: TST: Remove code that is not supposed to warn out of warning...
+* `#15815 <https://github.com/numpy/numpy/pull/15815>`__: DEP: Do not cast boolean indices to integers in np.delete
+* `#15816 <https://github.com/numpy/numpy/pull/15816>`__: MAINT: simplify code that assumes str/unicode and int/long are...
+* `#15830 <https://github.com/numpy/numpy/pull/15830>`__: MAINT: pathlib and hashlib are in stdlib in Python 3.5+
+* `#15832 <https://github.com/numpy/numpy/pull/15832>`__: ENH: improved error message `IndexError: too many indices for...
+* `#15836 <https://github.com/numpy/numpy/pull/15836>`__: BUG: Fix IndexError for illegal axis in np.mean
+* `#15839 <https://github.com/numpy/numpy/pull/15839>`__: DOC: Minor fix to _hist_bin_fd documentation
+* `#15840 <https://github.com/numpy/numpy/pull/15840>`__: BUG,DEP: Make `scalar.__round__()` behave like pythons round
+* `#15843 <https://github.com/numpy/numpy/pull/15843>`__: DOC: First steps towards docs restructuring (NEP 44)
+* `#15848 <https://github.com/numpy/numpy/pull/15848>`__: DOC, TST: enable refguide_check in circleci
+* `#15850 <https://github.com/numpy/numpy/pull/15850>`__: DOC: fix typo in C-API reference
+* `#15854 <https://github.com/numpy/numpy/pull/15854>`__: DOC: Fix docstring for _hist_bin_auto.
+* `#15866 <https://github.com/numpy/numpy/pull/15866>`__: MAINT: Bump cython from 0.29.15 to 0.29.16
+* `#15867 <https://github.com/numpy/numpy/pull/15867>`__: DEP: Deprecate ndarray.tostring()
+* `#15868 <https://github.com/numpy/numpy/pull/15868>`__: TST: use draft OpenBLAS build
+* `#15872 <https://github.com/numpy/numpy/pull/15872>`__: BUG: Fix eigh and cholesky methods of numpy.random.multivariate_normal
+* `#15876 <https://github.com/numpy/numpy/pull/15876>`__: BUG: Check that `pvals` is 1D in `_generator.multinomial`.
+* `#15877 <https://github.com/numpy/numpy/pull/15877>`__: DOC: Add missing signature from nditer docstring
+* `#15881 <https://github.com/numpy/numpy/pull/15881>`__: BUG: Fix empty_like to respect shape=()
+* `#15882 <https://github.com/numpy/numpy/pull/15882>`__: BUG: Do not ignore empty tuple of strides in ndarray.__new__
+* `#15883 <https://github.com/numpy/numpy/pull/15883>`__: MAINT: Remove duplicated code in iotools.py
+* `#15884 <https://github.com/numpy/numpy/pull/15884>`__: BUG: Setting a 0d array's strides to themselves should be legal
+* `#15885 <https://github.com/numpy/numpy/pull/15885>`__: BUG: Respect itershape=() in nditer
+* `#15887 <https://github.com/numpy/numpy/pull/15887>`__: MAINT: Clean-up 'next = __next__' used for Python 2 compatibility
+* `#15893 <https://github.com/numpy/numpy/pull/15893>`__: TST: Run test_large_zip in a child process
+* `#15894 <https://github.com/numpy/numpy/pull/15894>`__: DOC: Add missing doc of numpy.ma.apply_over_axes in API list.
+* `#15899 <https://github.com/numpy/numpy/pull/15899>`__: DOC: Improve record module documentation
+* `#15901 <https://github.com/numpy/numpy/pull/15901>`__: DOC: Fixed order of items and link to mailing list in dev docs...
+* `#15903 <https://github.com/numpy/numpy/pull/15903>`__: BLD: report clang version on macOS
+* `#15904 <https://github.com/numpy/numpy/pull/15904>`__: MAINT: records: Remove private `format_parser._descr` attribute
+* `#15914 <https://github.com/numpy/numpy/pull/15914>`__: BUG: random: Disallow p=0 in negative_binomial
+* `#15921 <https://github.com/numpy/numpy/pull/15921>`__: ENH: Use sysconfig instead of probing Makefile
+* `#15928 <https://github.com/numpy/numpy/pull/15928>`__: DOC: Update np.copy docstring to include ragged case
+* `#15931 <https://github.com/numpy/numpy/pull/15931>`__: DOC: Correct private function name to PyArray_AdaptFlexibleDType
+* `#15936 <https://github.com/numpy/numpy/pull/15936>`__: MAINT: Fix capitalization in error message in `mtrand.pyx`
+* `#15939 <https://github.com/numpy/numpy/pull/15939>`__: DOC: Update np.rollaxis docstring
+* `#15949 <https://github.com/numpy/numpy/pull/15949>`__: BUG: fix AttributeError on accessing object in nested MaskedArray.
+* `#15951 <https://github.com/numpy/numpy/pull/15951>`__: BUG: Alpha parameter must be 1D in `generator.dirichlet`
+* `#15953 <https://github.com/numpy/numpy/pull/15953>`__: NEP: minor maintenance, update filename and fix a cross-reference
+* `#15964 <https://github.com/numpy/numpy/pull/15964>`__: MAINT: Bump hypothesis from 5.8.0 to 5.8.3
+* `#15967 <https://github.com/numpy/numpy/pull/15967>`__: TST: Add slow_pypy support
+* `#15968 <https://github.com/numpy/numpy/pull/15968>`__: DOC: Added note to angle function docstring about angle(0) being...
+* `#15982 <https://github.com/numpy/numpy/pull/15982>`__: MAINT/BUG: Cleanup and minor fixes to conform_reduce_result
+* `#15985 <https://github.com/numpy/numpy/pull/15985>`__: BUG: Avoid duplication in stack trace of `linspace(a, b, num=1.5)`
+* `#15988 <https://github.com/numpy/numpy/pull/15988>`__: BUG: Fix inf and NaN-warnings in half float `nextafter`
+* `#15989 <https://github.com/numpy/numpy/pull/15989>`__: MAINT: Remove 0d check for PyArray_ISONESEGMENT
+* `#15990 <https://github.com/numpy/numpy/pull/15990>`__: DEV: Pass additional runtests.py args to ASV
+* `#15993 <https://github.com/numpy/numpy/pull/15993>`__: DOC: Fix method documentation of function sort in MaskedArray
+* `#16000 <https://github.com/numpy/numpy/pull/16000>`__: NEP: Improve Value Based Casting paragraph in NEP 40
+* `#16001 <https://github.com/numpy/numpy/pull/16001>`__: DOC: add note on flatten ordering in matlab page
+* `#16007 <https://github.com/numpy/numpy/pull/16007>`__: TST: Add tests for the conversion utilities
+* `#16008 <https://github.com/numpy/numpy/pull/16008>`__: BUG: Unify handling of string enum converters
+* `#16009 <https://github.com/numpy/numpy/pull/16009>`__: MAINT: Replace npyiter_order_converter with PyArray_OrderConverter
+* `#16010 <https://github.com/numpy/numpy/pull/16010>`__: BUG: Fix lexsort axis check
+* `#16011 <https://github.com/numpy/numpy/pull/16011>`__: DOC: Clarify single-segment arrays in np reference
+* `#16014 <https://github.com/numpy/numpy/pull/16014>`__: DOC: Change import error "howto" to link to new troubleshooting...
+* `#16015 <https://github.com/numpy/numpy/pull/16015>`__: DOC: update first section of NEP 37 (``__array_function__`` downsides)
+* `#16021 <https://github.com/numpy/numpy/pull/16021>`__: REL: Update master after 1.18.3 release.
+* `#16024 <https://github.com/numpy/numpy/pull/16024>`__: MAINT: Bump hypothesis from 5.8.3 to 5.10.1
+* `#16025 <https://github.com/numpy/numpy/pull/16025>`__: DOC: initialise random number generator before first use in quickstart
+* `#16032 <https://github.com/numpy/numpy/pull/16032>`__: ENH: Fix exception causes in build_clib.py
+* `#16038 <https://github.com/numpy/numpy/pull/16038>`__: MAINT,TST: Move _repr_latex tests to test_printing.
+* `#16041 <https://github.com/numpy/numpy/pull/16041>`__: BUG: missing 'f' prefix for fstring
+* `#16042 <https://github.com/numpy/numpy/pull/16042>`__: ENH: Fix exception causes in build_ext.py
+* `#16053 <https://github.com/numpy/numpy/pull/16053>`__: DOC: Small typo fixes to NEP 40.
+* `#16054 <https://github.com/numpy/numpy/pull/16054>`__: DOC, BLD: update release howto and walkthrough for ananconda.org...
+* `#16061 <https://github.com/numpy/numpy/pull/16061>`__: ENH: Chained exceptions in linalg.py and polyutils.py
+* `#16064 <https://github.com/numpy/numpy/pull/16064>`__: MAINT: Chain exceptions in several places.
+* `#16067 <https://github.com/numpy/numpy/pull/16067>`__: MAINT: Chain exceptions in memmap.py and core.py
+* `#16068 <https://github.com/numpy/numpy/pull/16068>`__: BUG: Fix string to bool cast regression
+* `#16069 <https://github.com/numpy/numpy/pull/16069>`__: DOC: Added page describing how to contribute to the docs team
+* `#16075 <https://github.com/numpy/numpy/pull/16075>`__: DOC: add a note on sampling 2-D arrays to random.choice docstring
+* `#16076 <https://github.com/numpy/numpy/pull/16076>`__: BUG: random: Generator.integers(2**32) always returned 0.
+* `#16077 <https://github.com/numpy/numpy/pull/16077>`__: BLD: fix path to libgfortran on macOS
+* `#16078 <https://github.com/numpy/numpy/pull/16078>`__: DOC: Add axis to random module "new or different" docs
+* `#16079 <https://github.com/numpy/numpy/pull/16079>`__: DOC,BLD: Limit timeit iterations in random docs.
+* `#16081 <https://github.com/numpy/numpy/pull/16081>`__: DOC: add note on type casting to numpy.left_shift().
+* `#16083 <https://github.com/numpy/numpy/pull/16083>`__: DOC: improve development debugging doc
+* `#16084 <https://github.com/numpy/numpy/pull/16084>`__: DOC: tweak neps/scope.rst
+* `#16085 <https://github.com/numpy/numpy/pull/16085>`__: MAINT: Bump cython from 0.29.16 to 0.29.17
+* `#16086 <https://github.com/numpy/numpy/pull/16086>`__: MAINT: Bump hypothesis from 5.10.1 to 5.10.4
+* `#16094 <https://github.com/numpy/numpy/pull/16094>`__: TST: use latest released PyPy instead of nightly builds
+* `#16097 <https://github.com/numpy/numpy/pull/16097>`__: MAINT, DOC: Improve grammar on a comment in the quickstart
+* `#16100 <https://github.com/numpy/numpy/pull/16100>`__: NEP 41: Accept NEP 41 and add DType<->scalar duplication paragraph
+* `#16101 <https://github.com/numpy/numpy/pull/16101>`__: BLD: put openblas library in local directory on windows
+* `#16113 <https://github.com/numpy/numpy/pull/16113>`__: MAINT: Fix random.PCG64 signature
+* `#16119 <https://github.com/numpy/numpy/pull/16119>`__: DOC: Move misplaced news fragment for gh-13421
+* `#16122 <https://github.com/numpy/numpy/pull/16122>`__: DOC: Fix links for NEP 40 in NEP 41
+* `#16125 <https://github.com/numpy/numpy/pull/16125>`__: BUG: lib: Fix a problem with vectorize with default parameters.
+* `#16129 <https://github.com/numpy/numpy/pull/16129>`__: ENH: Better error message when ``bins`` has float value in ``histogramdd``.
+* `#16133 <https://github.com/numpy/numpy/pull/16133>`__: MAINT: Unify casting error creation (outside the iterator)
+* `#16141 <https://github.com/numpy/numpy/pull/16141>`__: BENCH: Default to building HEAD instead of master
+* `#16144 <https://github.com/numpy/numpy/pull/16144>`__: REL: Update master after NumPy 1.18.4 release
+* `#16145 <https://github.com/numpy/numpy/pull/16145>`__: DOC: Add VSCode help link to importerror troubleshooting
+* `#16147 <https://github.com/numpy/numpy/pull/16147>`__: CI: pin 32-bit manylinux2010 image tag
+* `#16151 <https://github.com/numpy/numpy/pull/16151>`__: MAINT: Bump pytz from 2019.3 to 2020.1
+* `#16153 <https://github.com/numpy/numpy/pull/16153>`__: BUG: Correct loop order in MT19937 jump
+* `#16155 <https://github.com/numpy/numpy/pull/16155>`__: CI: unpin 32-bit manylinux2010 image tag
+* `#16162 <https://github.com/numpy/numpy/pull/16162>`__: BUG: add missing numpy/__init__.pxd to the wheel
+* `#16168 <https://github.com/numpy/numpy/pull/16168>`__: BUG:Umath remove unnecessary include of simd.inc in fast_loop_macro.h
+* `#16169 <https://github.com/numpy/numpy/pull/16169>`__: DOC,BLD: Add :doc: to whitelisted roles in refguide_check.
+* `#16170 <https://github.com/numpy/numpy/pull/16170>`__: ENH: resync numpy/__init__.pxd with upstream
+* `#16171 <https://github.com/numpy/numpy/pull/16171>`__: ENH: allow choosing which manylinux artifact to download
+* `#16173 <https://github.com/numpy/numpy/pull/16173>`__: MAINT: Mark tests as a subpackage rather than data.
+* `#16182 <https://github.com/numpy/numpy/pull/16182>`__: Update Docs : point users of np.outer to np.multiply.outer
+* `#16183 <https://github.com/numpy/numpy/pull/16183>`__: DOC: Fix link to numpy docs in README.
+* `#16185 <https://github.com/numpy/numpy/pull/16185>`__: ENH: Allow pickle with protocol 5 when higher is requested
+* `#16188 <https://github.com/numpy/numpy/pull/16188>`__: MAINT: cleanups to _iotools.StringConverter
+* `#16197 <https://github.com/numpy/numpy/pull/16197>`__: DOC: Unify cross-references between array joining methods
+* `#16199 <https://github.com/numpy/numpy/pull/16199>`__: DOC: Improve docstring of ``numpy.core.records``
+* `#16201 <https://github.com/numpy/numpy/pull/16201>`__: DOC: update Code of Conduct committee
+* `#16203 <https://github.com/numpy/numpy/pull/16203>`__: MAINT: Bump hypothesis from 5.10.4 to 5.12.0
+* `#16204 <https://github.com/numpy/numpy/pull/16204>`__: MAINT: Bump pytest from 5.4.1 to 5.4.2
+* `#16210 <https://github.com/numpy/numpy/pull/16210>`__: DOC: warn about runtime of shares_memory
+* `#16213 <https://github.com/numpy/numpy/pull/16213>`__: ENH: backport scipy changes to openblas download script
+* `#16214 <https://github.com/numpy/numpy/pull/16214>`__: BUG: skip complex256 arcsinh precision test on glibc2.17
+* `#16215 <https://github.com/numpy/numpy/pull/16215>`__: MAINT: Chain exceptions and use NameError in np.bmat
+* `#16216 <https://github.com/numpy/numpy/pull/16216>`__: DOC,BLD: pin sphinx to <3.0 in doc_requirements.txt
+* `#16223 <https://github.com/numpy/numpy/pull/16223>`__: BUG: fix signature of PyArray_SearchSorted in __init__.pxd
+* `#16224 <https://github.com/numpy/numpy/pull/16224>`__: ENH: add manylinux1 openblas hashes
+* `#16226 <https://github.com/numpy/numpy/pull/16226>`__: DOC: Fix Generator.choice docstring
+* `#16227 <https://github.com/numpy/numpy/pull/16227>`__: DOC: Add PyDev instructions to troubleshooting doc
+* `#16228 <https://github.com/numpy/numpy/pull/16228>`__: DOC: Add Clang and MSVC to supported compilers list
+* `#16240 <https://github.com/numpy/numpy/pull/16240>`__: DOC: Warn about behavior of ptp with signed integers.
+* `#16258 <https://github.com/numpy/numpy/pull/16258>`__: DOC: Update the f2py section of the "Using Python as Glue" page.
+* `#16263 <https://github.com/numpy/numpy/pull/16263>`__: BUG: Add missing decref in fromarray error path
+* `#16265 <https://github.com/numpy/numpy/pull/16265>`__: ENH: Add tool for downloading release wheels from Anaconda.
+* `#16269 <https://github.com/numpy/numpy/pull/16269>`__: DOC: Fix typos and cosmetic issues
+* `#16280 <https://github.com/numpy/numpy/pull/16280>`__: REL: Prepare for the 1.19.0 release
+* `#16293 <https://github.com/numpy/numpy/pull/16293>`__: BUG: Fix tools/download-wheels.py.
+* `#16301 <https://github.com/numpy/numpy/pull/16301>`__: BUG: Require Python >= 3.6 in setup.py
+* `#16312 <https://github.com/numpy/numpy/pull/16312>`__: BUG: relpath fails for different drives on windows
+* `#16314 <https://github.com/numpy/numpy/pull/16314>`__: DOC: Fix documentation rendering,
+* `#16341 <https://github.com/numpy/numpy/pull/16341>`__: BUG: Don't segfault on bad __len__ when assigning. (gh-16327)
+* `#16342 <https://github.com/numpy/numpy/pull/16342>`__: MAINT: Stop Using PyEval_Call* and simplify some uses
+* `#16343 <https://github.com/numpy/numpy/pull/16343>`__: BLD: Avoid "visibility attribute not supported" warning.
+* `#16344 <https://github.com/numpy/numpy/pull/16344>`__: BUG: Allow attaching documentation twice in add_docstring
+* `#16355 <https://github.com/numpy/numpy/pull/16355>`__: MAINT: Remove f-strings in setup.py. (gh-16346)
+* `#16356 <https://github.com/numpy/numpy/pull/16356>`__: BUG: Indentation for docstrings
+* `#16358 <https://github.com/numpy/numpy/pull/16358>`__: BUG: Fix dtype leak in `PyArray_FromAny` error path
+* `#16383 <https://github.com/numpy/numpy/pull/16383>`__: ENH: Optimize Cpu feature detect in X86, fix for GCC on macOS...
+* `#16398 <https://github.com/numpy/numpy/pull/16398>`__: MAINT: core: Use a raw string for the fromstring docstring.
+* `#16399 <https://github.com/numpy/numpy/pull/16399>`__: MAINT: Make ctypes optional on Windows
+* `#16400 <https://github.com/numpy/numpy/pull/16400>`__: BUG: Fix small leaks in error path and ``empty_like`` with shape
+* `#16402 <https://github.com/numpy/numpy/pull/16402>`__: TST, MAINT: Fix detecting and testing armhf features
+* `#16412 <https://github.com/numpy/numpy/pull/16412>`__: DOC,BLD: Update sphinx conf to use xelatex.
+* `#16413 <https://github.com/numpy/numpy/pull/16413>`__: DOC,BLD: Update make dist html target.
+* `#16414 <https://github.com/numpy/numpy/pull/16414>`__: MAINT, DOC: add index for user docs.
+* `#16437 <https://github.com/numpy/numpy/pull/16437>`__: MAINT: support python 3.10
+* `#16456 <https://github.com/numpy/numpy/pull/16456>`__: DOC: Fix troubleshooting code snippet when env vars are empty
+* `#16457 <https://github.com/numpy/numpy/pull/16457>`__: REL: Prepare for the NumPy 1.19.0rc2 release.
+* `#16526 <https://github.com/numpy/numpy/pull/16526>`__: MAINT:ARMHF Fix detecting feature groups NEON_HALF and NEON_VFPV4
+* `#16527 <https://github.com/numpy/numpy/pull/16527>`__: BUG:random: Error when ``size`` is smaller than broadcast input...
+* `#16528 <https://github.com/numpy/numpy/pull/16528>`__: BUG: fix GCC 10 major version comparison
+* `#16563 <https://github.com/numpy/numpy/pull/16563>`__: BUG: Ensure SeedSequence 0-padding does not collide with spawn...
+* `#16586 <https://github.com/numpy/numpy/pull/16586>`__: BUG: fix sin/cos bug when input is strided array
+* `#16602 <https://github.com/numpy/numpy/pull/16602>`__: MAINT: Move and improve ``test_ignore_nan_ulperror``.
+* `#16645 <https://github.com/numpy/numpy/pull/16645>`__: REL: Update 1.19.0-changelog.rst for 1.19.0 release.
index 8a5f9948f3cb4ce709804d571ed698b484f212d8..5e3d79807d8c15c441094a6e2ef4298432235028 100644 (file)
@@ -8,8 +8,6 @@ extend over multiple lines, the closing three quotation marks must be on
 a line by itself, preferably preceded by a blank line.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import os # standard library imports first
 
 # Do NOT import using *, e.g. from numpy import *
index 3c023ae9bc9b8e77a5d02f1222f1369f532866cc..4bbe4b42aaa3afa3dbf4404dbbd0711798ffd40c 100644 (file)
@@ -2,20 +2,23 @@
 #
 
 # You can set these variables from the command line.
-SPHINXOPTS    = -W
-SPHINXBUILD   = sphinx-build
+SPHINXOPTS    ?=
+SPHINXBUILD   ?= LANG=C sphinx-build
+
+# Internal variables
 SPHINXPROJ    = NumPyEnhancementProposals
 SOURCEDIR     = .
 BUILDDIR      = _build
+ALLSPHINXOPTS = -WT --keep-going -n -d $(SPHINXOPTS)
 
 # Put it first so that "make" without argument is like "make help".
 help:
-       @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+       @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(ALLSPHINXOPTS) $(O)
 
 .PHONY: help Makefile index
 
 index:
-       python tools/build_index.py
+       python3 tools/build_index.py
 
 # Catch-all target: route all unknown targets to Sphinx using the new
 # "make mode" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).
diff --git a/doc/neps/_static/nep-0040_dtype-hierarchy.png b/doc/neps/_static/nep-0040_dtype-hierarchy.png
new file mode 100644 (file)
index 0000000..6c45758
Binary files /dev/null and b/doc/neps/_static/nep-0040_dtype-hierarchy.png differ
diff --git a/doc/neps/_static/nep-0041-mindmap.svg b/doc/neps/_static/nep-0041-mindmap.svg
new file mode 100644 (file)
index 0000000..2b396f3
--- /dev/null
@@ -0,0 +1,3640 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/"
+   xmlns:cc="http://creativecommons.org/ns#"
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+   xmlns:svg="http://www.w3.org/2000/svg"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:xlink="http://www.w3.org/1999/xlink"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   width="1299pt"
+   height="720pt"
+   viewBox="0 0 1299 720"
+   version="1.1"
+   id="svg1387"
+   sodipodi:docname="mindmap.svg"
+   inkscape:version="0.92.4 (5da689c313, 2019-01-14)">
+  <metadata
+     id="metadata1391">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <sodipodi:namedview
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="3440"
+     inkscape:window-height="1376"
+     id="namedview1389"
+     showgrid="false"
+     inkscape:zoom="0.8221709"
+     inkscape:cx="902.39885"
+     inkscape:cy="314.46198"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     inkscape:current-layer="surface913125" />
+  <defs
+     id="defs352">
+    <g
+       id="g350">
+      <symbol
+         overflow="visible"
+         id="glyph0-0">
+        <path
+           style="stroke:none;"
+           d="M 0.953125 2.8125 L 0.953125 -10.125 L 8.0625 -10.125 L 8.0625 2.8125 Z M 1.765625 2 L 7.25 2 L 7.25 -9.296875 L 1.765625 -9.296875 Z M 1.765625 2 "
+           id="path2" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-1">
+        <path
+           style="stroke:none;"
+           d="M 2.890625 -8.84375 L 2.890625 -1.15625 L 4.640625 -1.15625 C 6.109375 -1.15625 7.1875 -1.460938 7.875 -2.078125 C 8.5625 -2.703125 8.90625 -3.679688 8.90625 -5.015625 C 8.90625 -6.335938 8.5625 -7.304688 7.875 -7.921875 C 7.1875 -8.535156 6.109375 -8.84375 4.640625 -8.84375 Z M 1.4375 -10 L 4.40625 -10 C 6.476562 -10 8 -9.59375 8.96875 -8.78125 C 9.945312 -7.976562 10.4375 -6.722656 10.4375 -5.015625 C 10.4375 -3.296875 9.945312 -2.03125 8.96875 -1.21875 C 8 -0.40625 6.476562 0 4.40625 0 L 1.4375 0 Z M 1.4375 -10 "
+           id="path5" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-2">
+        <path
+           style="stroke:none;"
+           d="M -0.046875 -10 L 9 -10 L 9 -8.8125 L 5.203125 -8.8125 L 5.203125 0 L 3.75 0 L 3.75 -8.8125 L -0.046875 -8.8125 Z M -0.046875 -10 "
+           id="path8" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-3">
+        <path
+           style="stroke:none;"
+           d="M 4.71875 0.703125 C 4.34375 1.660156 3.976562 2.28125 3.625 2.5625 C 3.28125 2.851562 2.8125 3 2.21875 3 L 1.15625 3 L 1.15625 1.921875 L 1.9375 1.921875 C 2.300781 1.921875 2.582031 1.832031 2.78125 1.65625 C 2.976562 1.488281 3.203125 1.085938 3.453125 0.453125 L 3.6875 -0.140625 L 0.4375 -8 L 1.828125 -8 L 4.34375 -1.75 L 6.84375 -8 L 8.25 -8 Z M 4.71875 0.703125 "
+           id="path11" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-4">
+        <path
+           style="stroke:none;"
+           d="M 2.65625 -1.375 L 2.65625 3 L 1.328125 3 L 1.328125 -8 L 2.65625 -8 L 2.65625 -6.8125 C 2.9375 -7.21875 3.285156 -7.515625 3.703125 -7.703125 C 4.128906 -7.898438 4.632812 -8 5.21875 -8 C 6.195312 -8 6.988281 -7.628906 7.59375 -6.890625 C 8.207031 -6.160156 8.515625 -5.195312 8.515625 -4 C 8.515625 -2.800781 8.207031 -1.832031 7.59375 -1.09375 C 6.988281 -0.363281 6.195312 0 5.21875 0 C 4.632812 0 4.128906 -0.109375 3.703125 -0.328125 C 3.285156 -0.554688 2.9375 -0.90625 2.65625 -1.375 Z M 7.140625 -4.09375 C 7.140625 -5.03125 6.941406 -5.765625 6.546875 -6.296875 C 6.148438 -6.835938 5.601562 -7.109375 4.90625 -7.109375 C 4.207031 -7.109375 3.65625 -6.835938 3.25 -6.296875 C 2.851562 -5.765625 2.65625 -5.03125 2.65625 -4.09375 C 2.65625 -3.15625 2.851562 -2.414062 3.25 -1.875 C 3.65625 -1.34375 4.207031 -1.078125 4.90625 -1.078125 C 5.601562 -1.078125 6.148438 -1.34375 6.546875 -1.875 C 6.941406 -2.414062 7.140625 -3.15625 7.140625 -4.09375 Z M 7.140625 -4.09375 "
+           id="path14" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-5">
+        <path
+           style="stroke:none;"
+           d="M 8.25 -4.5625 L 8.25 -4 L 2.1875 -4 C 2.238281 -3.050781 2.507812 -2.328125 3 -1.828125 C 3.488281 -1.335938 4.171875 -1.09375 5.046875 -1.09375 C 5.554688 -1.09375 6.046875 -1.15625 6.515625 -1.28125 C 6.992188 -1.414062 7.46875 -1.613281 7.9375 -1.875 L 7.9375 -0.609375 C 7.46875 -0.421875 6.984375 -0.269531 6.484375 -0.15625 C 5.984375 -0.0507812 5.476562 0 4.96875 0 C 3.6875 0 2.671875 -0.351562 1.921875 -1.0625 C 1.179688 -1.769531 0.8125 -2.726562 0.8125 -3.9375 C 0.8125 -5.1875 1.164062 -6.175781 1.875 -6.90625 C 2.582031 -7.632812 3.539062 -8 4.75 -8 C 5.820312 -8 6.671875 -7.691406 7.296875 -7.078125 C 7.929688 -6.460938 8.25 -5.625 8.25 -4.5625 Z M 6.921875 -5 C 6.910156 -5.582031 6.707031 -6.046875 6.3125 -6.390625 C 5.925781 -6.734375 5.40625 -6.90625 4.75 -6.90625 C 4.019531 -6.90625 3.429688 -6.738281 2.984375 -6.40625 C 2.546875 -6.082031 2.296875 -5.613281 2.234375 -5 Z M 6.921875 -5 "
+           id="path17" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-6">
+        <path
+           style="stroke:none;"
+           d=""
+           id="path20" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-7">
+        <path
+           style="stroke:none;"
+           d="M 1.4375 -10 L 2.890625 -10 L 2.890625 -6 L 8.140625 -6 L 8.140625 -10 L 9.59375 -10 L 9.59375 0 L 8.140625 0 L 8.140625 -4.8125 L 2.890625 -4.8125 L 2.890625 0 L 1.4375 0 Z M 1.4375 -10 "
+           id="path23" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-8">
+        <path
+           style="stroke:none;"
+           d="M 1.375 -8 L 2.703125 -8 L 2.703125 0 L 1.375 0 Z M 1.375 -11 L 2.703125 -11 L 2.703125 -9.375 L 1.375 -9.375 Z M 1.375 -11 "
+           id="path26" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-9">
+        <path
+           style="stroke:none;"
+           d="M 6.03125 -6.796875 C 5.882812 -6.878906 5.722656 -6.941406 5.546875 -6.984375 C 5.367188 -7.023438 5.175781 -7.046875 4.96875 -7.046875 C 4.226562 -7.046875 3.65625 -6.800781 3.25 -6.3125 C 2.851562 -5.832031 2.65625 -5.132812 2.65625 -4.21875 L 2.65625 0 L 1.328125 0 L 1.328125 -8 L 2.65625 -8 L 2.65625 -6.78125 C 2.9375 -7.195312 3.296875 -7.503906 3.734375 -7.703125 C 4.179688 -7.898438 4.722656 -8 5.359375 -8 C 5.453125 -8 5.550781 -8.003906 5.65625 -8.015625 C 5.769531 -8.035156 5.894531 -8.066406 6.03125 -8.109375 Z M 6.03125 -6.796875 "
+           id="path29" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-10">
+        <path
+           style="stroke:none;"
+           d="M 5.03125 -3.90625 C 3.96875 -3.90625 3.226562 -3.785156 2.8125 -3.546875 C 2.40625 -3.316406 2.203125 -2.921875 2.203125 -2.359375 C 2.203125 -1.898438 2.351562 -1.535156 2.65625 -1.265625 C 2.96875 -1.003906 3.390625 -0.875 3.921875 -0.875 C 4.648438 -0.875 5.234375 -1.125 5.671875 -1.625 C 6.117188 -2.132812 6.34375 -2.800781 6.34375 -3.625 L 6.34375 -3.90625 Z M 7.65625 -4.453125 L 7.65625 0 L 6.34375 0 L 6.34375 -1.1875 C 6.039062 -0.78125 5.664062 -0.476562 5.21875 -0.28125 C 4.769531 -0.09375 4.21875 0 3.5625 0 C 2.738281 0 2.082031 -0.210938 1.59375 -0.640625 C 1.113281 -1.066406 0.875 -1.640625 0.875 -2.359375 C 0.875 -3.203125 1.175781 -3.835938 1.78125 -4.265625 C 2.382812 -4.691406 3.285156 -4.90625 4.484375 -4.90625 L 6.34375 -4.90625 L 6.34375 -5.03125 C 6.34375 -5.625 6.140625 -6.082031 5.734375 -6.40625 C 5.335938 -6.738281 4.78125 -6.90625 4.0625 -6.90625 C 3.601562 -6.90625 3.15625 -6.851562 2.71875 -6.75 C 2.289062 -6.644531 1.875 -6.484375 1.46875 -6.265625 L 1.46875 -7.453125 C 1.945312 -7.628906 2.410156 -7.765625 2.859375 -7.859375 C 3.316406 -7.953125 3.765625 -8 4.203125 -8 C 5.359375 -8 6.222656 -7.703125 6.796875 -7.109375 C 7.367188 -6.523438 7.65625 -5.640625 7.65625 -4.453125 Z M 7.65625 -4.453125 "
+           id="path32" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-11">
+        <path
+           style="stroke:none;"
+           d="M 7.15625 -7.515625 L 7.15625 -6.328125 C 6.78125 -6.515625 6.40625 -6.65625 6.03125 -6.75 C 5.65625 -6.851562 5.28125 -6.90625 4.90625 -6.90625 C 4.050781 -6.90625 3.382812 -6.648438 2.90625 -6.140625 C 2.4375 -5.628906 2.203125 -4.914062 2.203125 -4 C 2.203125 -3.082031 2.4375 -2.367188 2.90625 -1.859375 C 3.382812 -1.347656 4.050781 -1.09375 4.90625 -1.09375 C 5.28125 -1.09375 5.65625 -1.140625 6.03125 -1.234375 C 6.40625 -1.328125 6.78125 -1.472656 7.15625 -1.671875 L 7.15625 -0.5 C 6.789062 -0.332031 6.410156 -0.207031 6.015625 -0.125 C 5.617188 -0.0390625 5.195312 0 4.75 0 C 3.539062 0 2.582031 -0.359375 1.875 -1.078125 C 1.164062 -1.796875 0.8125 -2.769531 0.8125 -4 C 0.8125 -5.238281 1.171875 -6.210938 1.890625 -6.921875 C 2.609375 -7.640625 3.59375 -8 4.84375 -8 C 5.25 -8 5.644531 -7.957031 6.03125 -7.875 C 6.414062 -7.789062 6.789062 -7.671875 7.15625 -7.515625 Z M 7.15625 -7.515625 "
+           id="path35" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-12">
+        <path
+           style="stroke:none;"
+           d="M 8.046875 -4.71875 L 8.046875 0 L 6.734375 0 L 6.734375 -4.671875 C 6.734375 -5.410156 6.582031 -5.960938 6.28125 -6.328125 C 5.988281 -6.691406 5.546875 -6.875 4.953125 -6.875 C 4.242188 -6.875 3.679688 -6.65625 3.265625 -6.21875 C 2.859375 -5.78125 2.65625 -5.179688 2.65625 -4.421875 L 2.65625 0 L 1.328125 0 L 1.328125 -11 L 2.65625 -11 L 2.65625 -6.59375 C 2.96875 -7.0625 3.335938 -7.410156 3.765625 -7.640625 C 4.191406 -7.878906 4.6875 -8 5.25 -8 C 6.175781 -8 6.875 -7.71875 7.34375 -7.15625 C 7.8125 -6.601562 8.046875 -5.789062 8.046875 -4.71875 Z M 8.046875 -4.71875 "
+           id="path38" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-13">
+        <path
+           style="stroke:none;"
+           d="M 4.546875 -11 C 3.910156 -9.945312 3.4375 -8.90625 3.125 -7.875 C 2.8125 -6.84375 2.65625 -5.800781 2.65625 -4.75 C 2.65625 -3.695312 2.8125 -2.648438 3.125 -1.609375 C 3.4375 -0.578125 3.910156 0.457031 4.546875 1.5 L 3.40625 1.5 C 2.6875 0.4375 2.148438 -0.613281 1.796875 -1.65625 C 1.441406 -2.695312 1.265625 -3.726562 1.265625 -4.75 C 1.265625 -5.757812 1.441406 -6.78125 1.796875 -7.8125 C 2.148438 -8.851562 2.6875 -9.914062 3.40625 -11 Z M 4.546875 -11 "
+           id="path41" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-14">
+        <path
+           style="stroke:none;"
+           d="M 7.140625 -4 C 7.140625 -4.90625 6.941406 -5.617188 6.546875 -6.140625 C 6.148438 -6.660156 5.601562 -6.921875 4.90625 -6.921875 C 4.207031 -6.921875 3.65625 -6.660156 3.25 -6.140625 C 2.851562 -5.617188 2.65625 -4.90625 2.65625 -4 C 2.65625 -3.09375 2.851562 -2.378906 3.25 -1.859375 C 3.65625 -1.335938 4.207031 -1.078125 4.90625 -1.078125 C 5.601562 -1.078125 6.148438 -1.335938 6.546875 -1.859375 C 6.941406 -2.378906 7.140625 -3.09375 7.140625 -4 Z M 2.65625 -6.625 C 2.9375 -7.09375 3.285156 -7.4375 3.703125 -7.65625 C 4.128906 -7.882812 4.632812 -8 5.21875 -8 C 6.195312 -8 6.988281 -7.628906 7.59375 -6.890625 C 8.207031 -6.160156 8.515625 -5.195312 8.515625 -4 C 8.515625 -2.800781 8.207031 -1.832031 7.59375 -1.09375 C 6.988281 -0.363281 6.195312 0 5.21875 0 C 4.632812 0 4.128906 -0.109375 3.703125 -0.328125 C 3.285156 -0.554688 2.9375 -0.90625 2.65625 -1.375 L 2.65625 0 L 1.328125 0 L 1.328125 -11 L 2.65625 -11 Z M 2.65625 -6.625 "
+           id="path44" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-15">
+        <path
+           style="stroke:none;"
+           d="M 6.5 -7.578125 L 6.5 -6.390625 C 6.125 -6.566406 5.734375 -6.695312 5.328125 -6.78125 C 4.929688 -6.875 4.519531 -6.921875 4.09375 -6.921875 C 3.4375 -6.921875 2.941406 -6.828125 2.609375 -6.640625 C 2.285156 -6.453125 2.125 -6.164062 2.125 -5.78125 C 2.125 -5.5 2.238281 -5.273438 2.46875 -5.109375 C 2.707031 -4.941406 3.179688 -4.78125 3.890625 -4.625 L 4.34375 -4.53125 C 5.28125 -4.34375 5.941406 -4.078125 6.328125 -3.734375 C 6.722656 -3.390625 6.921875 -2.910156 6.921875 -2.296875 C 6.921875 -1.585938 6.625 -1.023438 6.03125 -0.609375 C 5.445312 -0.203125 4.640625 0 3.609375 0 C 3.179688 0 2.734375 -0.0390625 2.265625 -0.125 C 1.796875 -0.207031 1.304688 -0.328125 0.796875 -0.484375 L 0.796875 -1.796875 C 1.285156 -1.554688 1.765625 -1.375 2.234375 -1.25 C 2.703125 -1.132812 3.171875 -1.078125 3.640625 -1.078125 C 4.265625 -1.078125 4.742188 -1.175781 5.078125 -1.375 C 5.410156 -1.582031 5.578125 -1.867188 5.578125 -2.234375 C 5.578125 -2.566406 5.453125 -2.820312 5.203125 -3 C 4.960938 -3.1875 4.4375 -3.359375 3.625 -3.515625 L 3.171875 -3.625 C 2.347656 -3.789062 1.753906 -4.039062 1.390625 -4.375 C 1.035156 -4.71875 0.859375 -5.179688 0.859375 -5.765625 C 0.859375 -6.472656 1.125 -7.019531 1.65625 -7.40625 C 2.1875 -7.800781 2.945312 -8 3.9375 -8 C 4.414062 -8 4.867188 -7.960938 5.296875 -7.890625 C 5.734375 -7.828125 6.132812 -7.722656 6.5 -7.578125 Z M 6.5 -7.578125 "
+           id="path47" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-16">
+        <path
+           style="stroke:none;"
+           d="M 2.6875 -10 L 2.6875 -8 L 5.40625 -8 L 5.40625 -7 L 2.6875 -7 L 2.6875 -2.625 C 2.6875 -1.96875 2.773438 -1.546875 2.953125 -1.359375 C 3.128906 -1.171875 3.492188 -1.078125 4.046875 -1.078125 L 5.40625 -1.078125 L 5.40625 0 L 4.046875 0 C 3.023438 0 2.320312 -0.1875 1.9375 -0.5625 C 1.550781 -0.945312 1.359375 -1.644531 1.359375 -2.65625 L 1.359375 -7 L 0.390625 -7 L 0.390625 -8 L 1.359375 -8 L 1.359375 -10 Z M 2.6875 -10 "
+           id="path50" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-17">
+        <path
+           style="stroke:none;"
+           d="M 1.171875 -11 L 2.328125 -11 C 3.035156 -9.914062 3.566406 -8.851562 3.921875 -7.8125 C 4.285156 -6.78125 4.46875 -5.757812 4.46875 -4.75 C 4.46875 -3.726562 4.285156 -2.695312 3.921875 -1.65625 C 3.566406 -0.613281 3.035156 0.4375 2.328125 1.5 L 1.171875 1.5 C 1.804688 0.457031 2.28125 -0.578125 2.59375 -1.609375 C 2.90625 -2.648438 3.0625 -3.695312 3.0625 -4.75 C 3.0625 -5.800781 2.90625 -6.84375 2.59375 -7.875 C 2.28125 -8.90625 1.804688 -9.945312 1.171875 -11 Z M 1.171875 -11 "
+           id="path53" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-18">
+        <path
+           style="stroke:none;"
+           d="M 7.859375 -9.46875 L 7.859375 -8.171875 C 7.304688 -8.398438 6.785156 -8.570312 6.296875 -8.6875 C 5.804688 -8.800781 5.335938 -8.859375 4.890625 -8.859375 C 4.097656 -8.859375 3.488281 -8.722656 3.0625 -8.453125 C 2.632812 -8.179688 2.421875 -7.789062 2.421875 -7.28125 C 2.421875 -6.863281 2.5625 -6.546875 2.84375 -6.328125 C 3.132812 -6.109375 3.675781 -5.9375 4.46875 -5.8125 L 5.34375 -5.640625 C 6.414062 -5.460938 7.207031 -5.140625 7.71875 -4.671875 C 8.238281 -4.210938 8.5 -3.597656 8.5 -2.828125 C 8.5 -1.898438 8.148438 -1.195312 7.453125 -0.71875 C 6.753906 -0.238281 5.738281 0 4.40625 0 C 3.894531 0 3.351562 -0.0507812 2.78125 -0.15625 C 2.207031 -0.269531 1.617188 -0.4375 1.015625 -0.65625 L 1.015625 -2.015625 C 1.597656 -1.722656 2.171875 -1.503906 2.734375 -1.359375 C 3.296875 -1.210938 3.851562 -1.140625 4.40625 -1.140625 C 5.226562 -1.140625 5.863281 -1.285156 6.3125 -1.578125 C 6.757812 -1.867188 6.984375 -2.28125 6.984375 -2.8125 C 6.984375 -3.28125 6.820312 -3.648438 6.5 -3.921875 C 6.175781 -4.191406 5.648438 -4.390625 4.921875 -4.515625 L 4.03125 -4.671875 C 2.957031 -4.859375 2.175781 -5.15625 1.6875 -5.5625 C 1.207031 -5.976562 0.96875 -6.550781 0.96875 -7.28125 C 0.96875 -8.125 1.300781 -8.785156 1.96875 -9.265625 C 2.632812 -9.753906 3.550781 -10 4.71875 -10 C 5.21875 -10 5.726562 -9.953125 6.25 -9.859375 C 6.769531 -9.773438 7.304688 -9.644531 7.859375 -9.46875 Z M 7.859375 -9.46875 "
+           id="path56" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-19">
+        <path
+           style="stroke:none;"
+           d="M 4.484375 -6.90625 C 3.785156 -6.90625 3.226562 -6.644531 2.8125 -6.125 C 2.40625 -5.601562 2.203125 -4.894531 2.203125 -4 C 2.203125 -3.101562 2.40625 -2.394531 2.8125 -1.875 C 3.21875 -1.351562 3.773438 -1.09375 4.484375 -1.09375 C 5.191406 -1.09375 5.75 -1.351562 6.15625 -1.875 C 6.570312 -2.394531 6.78125 -3.101562 6.78125 -4 C 6.78125 -4.894531 6.570312 -5.601562 6.15625 -6.125 C 5.75 -6.644531 5.191406 -6.90625 4.484375 -6.90625 Z M 4.484375 -8 C 5.640625 -8 6.539062 -7.644531 7.1875 -6.9375 C 7.84375 -6.226562 8.171875 -5.25 8.171875 -4 C 8.171875 -2.757812 7.84375 -1.78125 7.1875 -1.0625 C 6.539062 -0.351562 5.640625 0 4.484375 0 C 3.335938 0 2.4375 -0.351562 1.78125 -1.0625 C 1.132812 -1.78125 0.8125 -2.757812 0.8125 -4 C 0.8125 -5.25 1.132812 -6.226562 1.78125 -6.9375 C 2.4375 -7.644531 3.335938 -8 4.484375 -8 Z M 4.484375 -8 "
+           id="path59" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-20">
+        <path
+           style="stroke:none;"
+           d="M 8.046875 -4.71875 L 8.046875 0 L 6.734375 0 L 6.734375 -4.796875 C 6.734375 -5.554688 6.582031 -6.125 6.28125 -6.5 C 5.988281 -6.875 5.546875 -7.0625 4.953125 -7.0625 C 4.242188 -7.0625 3.679688 -6.835938 3.265625 -6.390625 C 2.859375 -5.941406 2.65625 -5.328125 2.65625 -4.546875 L 2.65625 0 L 1.328125 0 L 1.328125 -8 L 2.65625 -8 L 2.65625 -6.765625 C 2.96875 -7.171875 3.335938 -7.476562 3.765625 -7.6875 C 4.191406 -7.894531 4.6875 -8 5.25 -8 C 6.175781 -8 6.875 -7.71875 7.34375 -7.15625 C 7.8125 -6.601562 8.046875 -5.789062 8.046875 -4.71875 Z M 8.046875 -4.71875 "
+           id="path62" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-21">
+        <path
+           style="stroke:none;"
+           d="M 6.65625 -4 C 6.65625 -4.925781 6.457031 -5.644531 6.0625 -6.15625 C 5.675781 -6.664062 5.125 -6.921875 4.40625 -6.921875 C 3.707031 -6.921875 3.160156 -6.664062 2.765625 -6.15625 C 2.367188 -5.644531 2.171875 -4.925781 2.171875 -4 C 2.171875 -3.070312 2.367188 -2.351562 2.765625 -1.84375 C 3.160156 -1.332031 3.707031 -1.078125 4.40625 -1.078125 C 5.125 -1.078125 5.675781 -1.332031 6.0625 -1.84375 C 6.457031 -2.351562 6.65625 -3.070312 6.65625 -4 Z M 7.984375 -1.015625 C 7.984375 0.335938 7.675781 1.34375 7.0625 2 C 6.457031 2.664062 5.53125 3 4.28125 3 C 3.820312 3 3.382812 2.960938 2.96875 2.890625 C 2.5625 2.828125 2.164062 2.726562 1.78125 2.59375 L 1.78125 1.328125 C 2.164062 1.546875 2.546875 1.703125 2.921875 1.796875 C 3.296875 1.890625 3.679688 1.9375 4.078125 1.9375 C 4.941406 1.9375 5.585938 1.710938 6.015625 1.265625 C 6.441406 0.828125 6.65625 0.160156 6.65625 -0.734375 L 6.65625 -1.375 C 6.382812 -0.914062 6.035156 -0.570312 5.609375 -0.34375 C 5.191406 -0.113281 4.6875 0 4.09375 0 C 3.101562 0 2.304688 -0.363281 1.703125 -1.09375 C 1.109375 -1.820312 0.8125 -2.789062 0.8125 -4 C 0.8125 -5.207031 1.109375 -6.175781 1.703125 -6.90625 C 2.304688 -7.632812 3.101562 -8 4.09375 -8 C 4.6875 -8 5.191406 -7.882812 5.609375 -7.65625 C 6.035156 -7.425781 6.382812 -7.082031 6.65625 -6.625 L 6.65625 -8 L 7.984375 -8 Z M 7.984375 -1.015625 "
+           id="path65" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-22">
+        <path
+           style="stroke:none;"
+           d="M 5.4375 -11 L 5.4375 -9.9375 L 4.1875 -9.9375 C 3.707031 -9.9375 3.375 -9.84375 3.1875 -9.65625 C 3.007812 -9.476562 2.921875 -9.148438 2.921875 -8.671875 L 2.921875 -8 L 5.09375 -8 L 5.09375 -7 L 2.921875 -7 L 2.921875 0 L 1.59375 0 L 1.59375 -7 L 0.34375 -7 L 0.34375 -8 L 1.59375 -8 L 1.59375 -8.546875 C 1.59375 -9.398438 1.800781 -10.019531 2.21875 -10.40625 C 2.632812 -10.800781 3.296875 -11 4.203125 -11 Z M 5.4375 -11 "
+           id="path68" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-23">
+        <path
+           style="stroke:none;"
+           d="M 7.625 -6.3125 C 7.957031 -6.882812 8.351562 -7.304688 8.8125 -7.578125 C 9.269531 -7.859375 9.8125 -8 10.4375 -8 C 11.269531 -8 11.910156 -7.710938 12.359375 -7.140625 C 12.816406 -6.578125 13.046875 -5.769531 13.046875 -4.71875 L 13.046875 0 L 11.71875 0 L 11.71875 -4.671875 C 11.71875 -5.421875 11.582031 -5.972656 11.3125 -6.328125 C 11.039062 -6.691406 10.625 -6.875 10.0625 -6.875 C 9.382812 -6.875 8.847656 -6.65625 8.453125 -6.21875 C 8.054688 -5.78125 7.859375 -5.179688 7.859375 -4.421875 L 7.859375 0 L 6.53125 0 L 6.53125 -4.671875 C 6.53125 -5.421875 6.390625 -5.972656 6.109375 -6.328125 C 5.835938 -6.691406 5.421875 -6.875 4.859375 -6.875 C 4.179688 -6.875 3.644531 -6.648438 3.25 -6.203125 C 2.851562 -5.765625 2.65625 -5.171875 2.65625 -4.421875 L 2.65625 0 L 1.328125 0 L 1.328125 -8 L 2.65625 -8 L 2.65625 -6.59375 C 2.957031 -7.070312 3.316406 -7.425781 3.734375 -7.65625 C 4.160156 -7.882812 4.660156 -8 5.234375 -8 C 5.816406 -8 6.3125 -7.851562 6.71875 -7.5625 C 7.132812 -7.28125 7.4375 -6.863281 7.625 -6.3125 Z M 7.625 -6.3125 "
+           id="path71" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-24">
+        <path
+           style="stroke:none;"
+           d="M 7.484375 2 L 7.484375 3 L -0.140625 3 L -0.140625 2 Z M 7.484375 2 "
+           id="path74" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-25">
+        <path
+           style="stroke:none;"
+           d="M 6.65625 -6.625 L 6.65625 -11 L 7.984375 -11 L 7.984375 0 L 6.65625 0 L 6.65625 -1.171875 C 6.382812 -0.773438 6.035156 -0.476562 5.609375 -0.28125 C 5.191406 -0.09375 4.6875 0 4.09375 0 C 3.125 0 2.332031 -0.363281 1.71875 -1.09375 C 1.113281 -1.832031 0.8125 -2.800781 0.8125 -4 C 0.8125 -5.195312 1.113281 -6.160156 1.71875 -6.890625 C 2.332031 -7.628906 3.125 -8 4.09375 -8 C 4.6875 -8 5.191406 -7.882812 5.609375 -7.65625 C 6.035156 -7.4375 6.382812 -7.09375 6.65625 -6.625 Z M 2.171875 -3.890625 C 2.171875 -2.953125 2.367188 -2.210938 2.765625 -1.671875 C 3.160156 -1.140625 3.707031 -0.875 4.40625 -0.875 C 5.101562 -0.875 5.648438 -1.140625 6.046875 -1.671875 C 6.453125 -2.210938 6.65625 -2.953125 6.65625 -3.890625 C 6.65625 -4.835938 6.453125 -5.578125 6.046875 -6.109375 C 5.648438 -6.648438 5.101562 -6.921875 4.40625 -6.921875 C 3.707031 -6.921875 3.160156 -6.648438 2.765625 -6.109375 C 2.367188 -5.578125 2.171875 -4.835938 2.171875 -3.890625 Z M 2.171875 -3.890625 "
+           id="path77" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-26">
+        <path
+           style="stroke:none;"
+           d="M 1.375 -11 L 2.703125 -11 L 2.703125 0 L 1.375 0 Z M 1.375 -11 "
+           id="path80" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-27">
+        <path
+           style="stroke:none;"
+           d="M 1.71875 -1.421875 L 3.234375 -1.421875 L 3.234375 -0.21875 L 2.0625 2 L 1.125 2 L 1.71875 -0.21875 Z M 1.71875 -1.421875 "
+           id="path83" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-28">
+        <path
+           style="stroke:none;"
+           d="M 1.5625 -1.765625 L 3.078125 -1.765625 L 3.078125 0 L 1.5625 0 Z M 1.5625 -1.765625 "
+           id="path86" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-29">
+        <path
+           style="stroke:none;"
+           d="M 1.25 -3.28125 L 1.25 -8 L 2.5625 -8 L 2.5625 -3.1875 C 2.5625 -2.425781 2.707031 -1.851562 3 -1.46875 C 3.300781 -1.09375 3.75 -0.90625 4.34375 -0.90625 C 5.050781 -0.90625 5.609375 -1.128906 6.015625 -1.578125 C 6.429688 -2.035156 6.640625 -2.65625 6.640625 -3.4375 L 6.640625 -8 L 7.96875 -8 L 7.96875 0 L 6.640625 0 L 6.640625 -1.203125 C 6.328125 -0.796875 5.957031 -0.492188 5.53125 -0.296875 C 5.113281 -0.0976562 4.625 0 4.0625 0 C 3.132812 0 2.429688 -0.273438 1.953125 -0.828125 C 1.484375 -1.390625 1.25 -2.207031 1.25 -3.28125 Z M 4.5625 -8 Z M 4.5625 -8 "
+           id="path89" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-30">
+        <path
+           style="stroke:none;"
+           d="M 1.4375 -10 L 3.59375 -10 L 6.328125 -3.1875 L 9.0625 -10 L 11.21875 -10 L 11.21875 0 L 9.8125 0 L 9.8125 -8.78125 L 7.0625 -1.921875 L 5.609375 -1.921875 L 2.84375 -8.78125 L 2.84375 0 L 1.4375 0 Z M 1.4375 -10 "
+           id="path92" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-31">
+        <path
+           style="stroke:none;"
+           d="M 1.4375 -10 L 2.890625 -10 L 2.890625 -1.1875 L 8.09375 -1.1875 L 8.09375 0 L 1.4375 0 Z M 1.4375 -10 "
+           id="path95" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-32">
+        <path
+           style="stroke:none;"
+           d="M 7.859375 -8 L 7.859375 0 L 6.546875 0 L 6.546875 -7 L 2.921875 -7 L 2.921875 0 L 1.59375 0 L 1.59375 -7 L 0.34375 -7 L 0.34375 -8 L 1.59375 -8 L 1.59375 -8.546875 C 1.59375 -9.378906 1.800781 -9.992188 2.21875 -10.390625 C 2.632812 -10.796875 3.269531 -11 4.125 -11 L 5.4375 -11 L 5.4375 -9.9375 L 4.1875 -9.9375 C 3.707031 -9.9375 3.375 -9.84375 3.1875 -9.65625 C 3.007812 -9.476562 2.921875 -9.148438 2.921875 -8.671875 L 2.921875 -8 Z M 6.546875 -11 L 7.859375 -11 L 7.859375 -9.375 L 6.546875 -9.375 Z M 6.546875 -11 "
+           id="path98" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-33">
+        <path
+           style="stroke:none;"
+           d="M 1.71875 -1.765625 L 3.234375 -1.765625 L 3.234375 0 L 1.71875 0 Z M 1.71875 -7 L 3.234375 -7 L 3.234375 -5.21875 L 1.71875 -5.21875 Z M 1.71875 -7 "
+           id="path101" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-34">
+        <path
+           style="stroke:none;"
+           d="M 1.4375 -10 L 2.890625 -10 L 2.890625 0 L 1.4375 0 Z M 1.4375 -10 "
+           id="path104" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-35">
+        <path
+           style="stroke:none;"
+           d="M 9.453125 -9.015625 L 9.453125 -7.65625 C 8.960938 -8.050781 8.441406 -8.347656 7.890625 -8.546875 C 7.335938 -8.742188 6.75 -8.84375 6.125 -8.84375 C 4.90625 -8.84375 3.96875 -8.515625 3.3125 -7.859375 C 2.664062 -7.203125 2.34375 -6.25 2.34375 -5 C 2.34375 -3.757812 2.664062 -2.804688 3.3125 -2.140625 C 3.96875 -1.484375 4.90625 -1.15625 6.125 -1.15625 C 6.75 -1.15625 7.335938 -1.253906 7.890625 -1.453125 C 8.441406 -1.648438 8.960938 -1.945312 9.453125 -2.34375 L 9.453125 -1 C 8.941406 -0.664062 8.398438 -0.414062 7.828125 -0.25 C 7.265625 -0.0820312 6.671875 0 6.046875 0 C 4.429688 0 3.15625 -0.441406 2.21875 -1.328125 C 1.289062 -2.222656 0.828125 -3.445312 0.828125 -5 C 0.828125 -6.550781 1.289062 -7.769531 2.21875 -8.65625 C 3.15625 -9.550781 4.429688 -10 6.046875 -10 C 6.679688 -10 7.28125 -9.914062 7.84375 -9.75 C 8.414062 -9.59375 8.953125 -9.347656 9.453125 -9.015625 Z M 9.453125 -9.015625 "
+           id="path107" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-36">
+        <path
+           style="stroke:none;"
+           d="M 2.890625 -8.84375 L 2.890625 -4.984375 L 4.703125 -4.984375 C 5.378906 -4.984375 5.898438 -5.148438 6.265625 -5.484375 C 6.628906 -5.816406 6.8125 -6.296875 6.8125 -6.921875 C 6.8125 -7.535156 6.628906 -8.007812 6.265625 -8.34375 C 5.898438 -8.675781 5.378906 -8.84375 4.703125 -8.84375 Z M 1.4375 -10 L 4.703125 -10 C 5.898438 -10 6.804688 -9.738281 7.421875 -9.21875 C 8.035156 -8.695312 8.34375 -7.925781 8.34375 -6.90625 C 8.34375 -5.894531 8.035156 -5.128906 7.421875 -4.609375 C 6.804688 -4.085938 5.898438 -3.828125 4.703125 -3.828125 L 2.890625 -3.828125 L 2.890625 0 L 1.4375 0 Z M 1.4375 -10 "
+           id="path110" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-37">
+        <path
+           style="stroke:none;"
+           d="M 0.4375 -8 L 1.828125 -8 L 4.34375 -1.28125 L 6.84375 -8 L 8.25 -8 L 5.234375 0 L 3.453125 0 Z M 0.4375 -8 "
+           id="path113" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-38">
+        <path
+           style="stroke:none;"
+           d="M 0.609375 -8 L 1.9375 -8 L 3.578125 -1.75 L 5.21875 -8 L 6.78125 -8 L 8.421875 -1.75 L 10.0625 -8 L 11.390625 -8 L 9.28125 0 L 7.734375 0 L 6 -6.5625 L 4.265625 0 L 2.71875 0 Z M 0.609375 -8 "
+           id="path116" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-39">
+        <path
+           style="stroke:none;"
+           d="M 1.265625 -11 L 4.296875 -11 L 4.296875 -10.015625 L 2.578125 -10.015625 L 2.578125 1.015625 L 4.296875 1.015625 L 4.296875 1.984375 L 1.265625 1.984375 Z M 1.265625 -11 "
+           id="path119" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph0-40">
+        <path
+           style="stroke:none;"
+           d="M 4.46875 -11 L 4.46875 1.984375 L 1.421875 1.984375 L 1.421875 1.015625 L 3.140625 1.015625 L 3.140625 -10.015625 L 1.421875 -10.015625 L 1.421875 -11 Z M 4.46875 -11 "
+           id="path122" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph1-0">
+        <path
+           style="stroke:none;"
+           d="M 1.078125 4.25 L 1.078125 -16.953125 L 13.078125 -16.953125 L 13.078125 4.25 Z M 2.421875 2.90625 L 11.734375 2.90625 L 11.734375 -15.609375 L 2.421875 -15.609375 Z M 2.421875 2.90625 "
+           id="path125" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph1-1">
+        <path
+           style="stroke:none;"
+           d="M 2.5625 -3.09375 L 5.046875 -3.09375 L 5.046875 0 L 2.5625 0 Z M 2.5625 -3.09375 "
+           id="path128" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-0">
+        <path
+           style="stroke:none;"
+           d="M 1.421875 4.53125 L 1.421875 -18.953125 L 14.921875 -18.953125 L 14.921875 4.53125 Z M 2.921875 3.046875 L 13.421875 3.046875 L 13.421875 -17.453125 L 2.921875 -17.453125 Z M 2.921875 3.046875 "
+           id="path131" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-1">
+        <path
+           style="stroke:none;"
+           d="M 5.25 -17.828125 L 5.25 -2.171875 L 8.421875 -2.171875 C 11.109375 -2.171875 13.070312 -2.796875 14.3125 -4.046875 C 15.5625 -5.304688 16.1875 -7.296875 16.1875 -10.015625 C 16.1875 -12.710938 15.5625 -14.6875 14.3125 -15.9375 C 13.070312 -17.195312 11.109375 -17.828125 8.421875 -17.828125 Z M 2.625 -20 L 8.015625 -20 C 11.785156 -20 14.550781 -19.191406 16.3125 -17.578125 C 18.082031 -15.960938 18.96875 -13.441406 18.96875 -10.015625 C 18.96875 -6.566406 18.082031 -4.035156 16.3125 -2.421875 C 14.539062 -0.804688 11.773438 0 8.015625 0 L 2.625 0 Z M 2.625 -20 "
+           id="path134" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-2">
+        <path
+           style="stroke:none;"
+           d="M -0.078125 -20 L 16.375 -20 L 16.375 -17.765625 L 9.46875 -17.765625 L 9.46875 0 L 6.828125 0 L 6.828125 -17.765625 L -0.078125 -17.765625 Z M -0.078125 -20 "
+           id="path137" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-3">
+        <path
+           style="stroke:none;"
+           d="M 8.578125 1.625 C 7.898438 3.425781 7.238281 4.601562 6.59375 5.15625 C 5.957031 5.71875 5.101562 6 4.03125 6 L 2.109375 6 L 2.109375 3.984375 L 3.515625 3.984375 C 4.171875 3.984375 4.679688 3.816406 5.046875 3.484375 C 5.410156 3.148438 5.816406 2.378906 6.265625 1.171875 L 6.6875 0.03125 L 0.796875 -15 L 3.328125 -15 L 7.890625 -3.046875 L 12.453125 -15 L 14.984375 -15 Z M 8.578125 1.625 "
+           id="path140" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-4">
+        <path
+           style="stroke:none;"
+           d="M 4.828125 -2.5625 L 4.828125 6 L 2.421875 6 L 2.421875 -15 L 4.828125 -15 L 4.828125 -12.4375 C 5.335938 -13.300781 5.972656 -13.941406 6.734375 -14.359375 C 7.503906 -14.785156 8.425781 -15 9.5 -15 C 11.269531 -15 12.707031 -14.3125 13.8125 -12.9375 C 14.914062 -11.5625 15.46875 -9.75 15.46875 -7.5 C 15.46875 -5.25 14.914062 -3.4375 13.8125 -2.0625 C 12.707031 -0.6875 11.269531 0 9.5 0 C 8.425781 0 7.503906 -0.207031 6.734375 -0.625 C 5.972656 -1.050781 5.335938 -1.695312 4.828125 -2.5625 Z M 12.984375 -7.5 C 12.984375 -9.207031 12.617188 -10.546875 11.890625 -11.515625 C 11.171875 -12.492188 10.175781 -12.984375 8.90625 -12.984375 C 7.632812 -12.984375 6.632812 -12.492188 5.90625 -11.515625 C 5.1875 -10.546875 4.828125 -9.207031 4.828125 -7.5 C 4.828125 -5.789062 5.1875 -4.445312 5.90625 -3.46875 C 6.632812 -2.5 7.632812 -2.015625 8.90625 -2.015625 C 10.175781 -2.015625 11.171875 -2.5 11.890625 -3.46875 C 12.617188 -4.445312 12.984375 -5.789062 12.984375 -7.5 Z M 12.984375 -7.5 "
+           id="path143" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-5">
+        <path
+           style="stroke:none;"
+           d="M 14.984375 -8.25 L 14.984375 -7.125 L 3.96875 -7.125 C 4.070312 -5.46875 4.566406 -4.203125 5.453125 -3.328125 C 6.347656 -2.460938 7.59375 -2.03125 9.1875 -2.03125 C 10.101562 -2.03125 10.992188 -2.144531 11.859375 -2.375 C 12.722656 -2.601562 13.582031 -2.941406 14.4375 -3.390625 L 14.4375 -1.125 C 13.570312 -0.757812 12.6875 -0.476562 11.78125 -0.28125 C 10.882812 -0.09375 9.96875 0 9.03125 0 C 6.707031 0 4.863281 -0.660156 3.5 -1.984375 C 2.144531 -3.316406 1.46875 -5.113281 1.46875 -7.375 C 1.46875 -9.71875 2.113281 -11.570312 3.40625 -12.9375 C 4.695312 -14.3125 6.4375 -15 8.625 -15 C 10.582031 -15 12.128906 -14.390625 13.265625 -13.171875 C 14.410156 -11.960938 14.984375 -10.320312 14.984375 -8.25 Z M 12.59375 -9 C 12.570312 -10.207031 12.203125 -11.164062 11.484375 -11.875 C 10.773438 -12.59375 9.828125 -12.953125 8.640625 -12.953125 C 7.304688 -12.953125 6.238281 -12.609375 5.4375 -11.921875 C 4.632812 -11.234375 4.171875 -10.257812 4.046875 -9 Z M 12.59375 -9 "
+           id="path146" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-6">
+        <path
+           style="stroke:none;"
+           d=""
+           id="path149" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-7">
+        <path
+           style="stroke:none;"
+           d="M 17.171875 -18.140625 L 17.171875 -15.390625 C 16.285156 -16.210938 15.34375 -16.820312 14.34375 -17.21875 C 13.34375 -17.625 12.273438 -17.828125 11.140625 -17.828125 C 8.921875 -17.828125 7.21875 -17.15625 6.03125 -15.8125 C 4.851562 -14.46875 4.265625 -12.53125 4.265625 -10 C 4.265625 -7.46875 4.851562 -5.53125 6.03125 -4.1875 C 7.21875 -2.84375 8.921875 -2.171875 11.140625 -2.171875 C 12.273438 -2.171875 13.34375 -2.367188 14.34375 -2.765625 C 15.34375 -3.171875 16.285156 -3.785156 17.171875 -4.609375 L 17.171875 -1.890625 C 16.253906 -1.253906 15.28125 -0.78125 14.25 -0.46875 C 13.21875 -0.15625 12.128906 0 10.984375 0 C 8.046875 0 5.726562 -0.890625 4.03125 -2.671875 C 2.34375 -4.460938 1.5 -6.90625 1.5 -10 C 1.5 -13.09375 2.34375 -15.53125 4.03125 -17.3125 C 5.726562 -19.101562 8.046875 -20 10.984375 -20 C 12.148438 -20 13.25 -19.84375 14.28125 -19.53125 C 15.3125 -19.226562 16.273438 -18.765625 17.171875 -18.140625 Z M 17.171875 -18.140625 "
+           id="path152" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-8">
+        <path
+           style="stroke:none;"
+           d="M 2.515625 -20 L 4.90625 -20 L 4.90625 0 L 2.515625 0 Z M 2.515625 -20 "
+           id="path155" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-9">
+        <path
+           style="stroke:none;"
+           d="M 9.140625 -8 C 7.203125 -8 5.859375 -7.765625 5.109375 -7.296875 C 4.367188 -6.835938 4 -6.046875 4 -4.921875 C 4 -4.023438 4.273438 -3.316406 4.828125 -2.796875 C 5.390625 -2.273438 6.15625 -2.015625 7.125 -2.015625 C 8.445312 -2.015625 9.507812 -2.503906 10.3125 -3.484375 C 11.125 -4.472656 11.53125 -5.789062 11.53125 -7.4375 L 11.53125 -8 Z M 13.921875 -8.359375 L 13.921875 0 L 11.53125 0 L 11.53125 -2.625 C 10.976562 -1.726562 10.289062 -1.066406 9.46875 -0.640625 C 8.65625 -0.210938 7.660156 0 6.484375 0 C 4.992188 0 3.804688 -0.425781 2.921875 -1.28125 C 2.046875 -2.144531 1.609375 -3.304688 1.609375 -4.765625 C 1.609375 -6.460938 2.15625 -7.738281 3.25 -8.59375 C 4.34375 -9.457031 5.984375 -9.890625 8.171875 -9.890625 L 11.53125 -9.890625 L 11.53125 -10.078125 C 11.53125 -10.992188 11.164062 -11.703125 10.4375 -12.203125 C 9.707031 -12.703125 8.691406 -12.953125 7.390625 -12.953125 C 6.554688 -12.953125 5.742188 -12.867188 4.953125 -12.703125 C 4.160156 -12.546875 3.398438 -12.300781 2.671875 -11.96875 L 2.671875 -13.96875 C 3.546875 -14.300781 4.394531 -14.554688 5.21875 -14.734375 C 6.039062 -14.910156 6.84375 -15 7.625 -15 C 9.738281 -15 11.316406 -14.445312 12.359375 -13.34375 C 13.398438 -12.25 13.921875 -10.585938 13.921875 -8.359375 Z M 13.921875 -8.359375 "
+           id="path158" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-10">
+        <path
+           style="stroke:none;"
+           d="M 11.8125 -14.21875 L 11.8125 -11.96875 C 11.132812 -12.3125 10.429688 -12.566406 9.703125 -12.734375 C 8.972656 -12.898438 8.21875 -12.984375 7.4375 -12.984375 C 6.25 -12.984375 5.359375 -12.804688 4.765625 -12.453125 C 4.171875 -12.097656 3.875 -11.566406 3.875 -10.859375 C 3.875 -10.304688 4.082031 -9.875 4.5 -9.5625 C 4.925781 -9.257812 5.785156 -8.96875 7.078125 -8.6875 L 7.890625 -8.515625 C 9.585938 -8.148438 10.796875 -7.644531 11.515625 -7 C 12.234375 -6.351562 12.59375 -5.453125 12.59375 -4.296875 C 12.59375 -2.972656 12.054688 -1.925781 10.984375 -1.15625 C 9.910156 -0.382812 8.4375 0 6.5625 0 C 5.78125 0 4.96875 -0.078125 4.125 -0.234375 C 3.28125 -0.390625 2.390625 -0.617188 1.453125 -0.921875 L 1.453125 -3.359375 C 2.335938 -2.910156 3.207031 -2.570312 4.0625 -2.34375 C 4.925781 -2.125 5.773438 -2.015625 6.609375 -2.015625 C 7.742188 -2.015625 8.613281 -2.203125 9.21875 -2.578125 C 9.820312 -2.953125 10.125 -3.484375 10.125 -4.171875 C 10.125 -4.804688 9.90625 -5.289062 9.46875 -5.625 C 9.03125 -5.96875 8.070312 -6.296875 6.59375 -6.609375 L 5.75 -6.796875 C 4.269531 -7.097656 3.195312 -7.566406 2.53125 -8.203125 C 1.875 -8.835938 1.546875 -9.707031 1.546875 -10.8125 C 1.546875 -12.144531 2.03125 -13.175781 3 -13.90625 C 3.976562 -14.632812 5.363281 -15 7.15625 -15 C 8.039062 -15 8.875 -14.929688 9.65625 -14.796875 C 10.4375 -14.671875 11.15625 -14.476562 11.8125 -14.21875 Z M 11.8125 -14.21875 "
+           id="path161" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-11">
+        <path
+           style="stroke:none;"
+           d="M 2.3125 -20 L 4.96875 -20 L 4.96875 -8.0625 C 4.96875 -5.96875 5.34375 -4.457031 6.09375 -3.53125 C 6.851562 -2.601562 8.078125 -2.140625 9.765625 -2.140625 C 11.453125 -2.140625 12.671875 -2.601562 13.421875 -3.53125 C 14.179688 -4.457031 14.5625 -5.96875 14.5625 -8.0625 L 14.5625 -20 L 17.203125 -20 L 17.203125 -7.75 C 17.203125 -5.1875 16.570312 -3.253906 15.3125 -1.953125 C 14.0625 -0.648438 12.210938 0 9.765625 0 C 7.304688 0 5.445312 -0.648438 4.1875 -1.953125 C 2.9375 -3.253906 2.3125 -5.1875 2.3125 -7.75 Z M 2.3125 -20 "
+           id="path164" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-12">
+        <path
+           style="stroke:none;"
+           d="M 2.625 -20 L 13.796875 -20 L 13.796875 -17.765625 L 5.25 -17.765625 L 5.25 -11.21875 L 12.953125 -11.21875 L 12.953125 -9 L 5.25 -9 L 5.25 0 L 2.625 0 Z M 2.625 -20 "
+           id="path167" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-13">
+        <path
+           style="stroke:none;"
+           d="M 2.265625 -6.15625 L 2.265625 -15 L 4.65625 -15 L 4.65625 -6.25 C 4.65625 -4.863281 4.925781 -3.820312 5.46875 -3.125 C 6.007812 -2.4375 6.816406 -2.09375 7.890625 -2.09375 C 9.179688 -2.09375 10.203125 -2.503906 10.953125 -3.328125 C 11.703125 -4.160156 12.078125 -5.289062 12.078125 -6.71875 L 12.078125 -15 L 14.484375 -15 L 14.484375 0 L 12.078125 0 L 12.078125 -2.625 C 11.503906 -1.738281 10.832031 -1.078125 10.0625 -0.640625 C 9.289062 -0.210938 8.398438 0 7.390625 0 C 5.710938 0 4.4375 -0.519531 3.5625 -1.5625 C 2.695312 -2.613281 2.265625 -4.144531 2.265625 -6.15625 Z M 8.296875 -15 Z M 8.296875 -15 "
+           id="path170" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-14">
+        <path
+           style="stroke:none;"
+           d="M 14.640625 -8.84375 L 14.640625 0 L 12.234375 0 L 12.234375 -8.765625 C 12.234375 -10.148438 11.960938 -11.1875 11.421875 -11.875 C 10.890625 -12.5625 10.085938 -12.90625 9.015625 -12.90625 C 7.722656 -12.90625 6.703125 -12.488281 5.953125 -11.65625 C 5.203125 -10.832031 4.828125 -9.707031 4.828125 -8.28125 L 4.828125 0 L 2.421875 0 L 2.421875 -15 L 4.828125 -15 L 4.828125 -12.375 C 5.398438 -13.25 6.070312 -13.90625 6.84375 -14.34375 C 7.625 -14.78125 8.523438 -15 9.546875 -15 C 11.222656 -15 12.488281 -14.476562 13.34375 -13.4375 C 14.207031 -12.394531 14.640625 -10.863281 14.640625 -8.84375 Z M 14.640625 -8.84375 "
+           id="path173" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-15">
+        <path
+           style="stroke:none;"
+           d="M 13.015625 -14.078125 L 13.015625 -11.859375 C 12.335938 -12.222656 11.65625 -12.492188 10.96875 -12.671875 C 10.289062 -12.859375 9.601562 -12.953125 8.90625 -12.953125 C 7.351562 -12.953125 6.144531 -12.472656 5.28125 -11.515625 C 4.425781 -10.554688 4 -9.21875 4 -7.5 C 4 -5.769531 4.425781 -4.425781 5.28125 -3.46875 C 6.144531 -2.507812 7.351562 -2.03125 8.90625 -2.03125 C 9.601562 -2.03125 10.289062 -2.117188 10.96875 -2.296875 C 11.65625 -2.484375 12.335938 -2.757812 13.015625 -3.125 L 13.015625 -0.9375 C 12.335938 -0.625 11.640625 -0.390625 10.921875 -0.234375 C 10.210938 -0.078125 9.453125 0 8.640625 0 C 6.453125 0 4.707031 -0.675781 3.40625 -2.03125 C 2.113281 -3.382812 1.46875 -5.207031 1.46875 -7.5 C 1.46875 -9.820312 2.117188 -11.648438 3.421875 -12.984375 C 4.734375 -14.328125 6.523438 -15 8.796875 -15 C 9.535156 -15 10.253906 -14.921875 10.953125 -14.765625 C 11.660156 -14.617188 12.347656 -14.390625 13.015625 -14.078125 Z M 13.015625 -14.078125 "
+           id="path176" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-16">
+        <path
+           style="stroke:none;"
+           d="M 2.515625 -15 L 4.90625 -15 L 4.90625 0 L 2.515625 0 Z M 2.515625 -20 L 4.90625 -20 L 4.90625 -16.953125 L 2.515625 -16.953125 Z M 2.515625 -20 "
+           id="path179" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-17">
+        <path
+           style="stroke:none;"
+           d="M 4.890625 -19 L 4.890625 -15 L 9.8125 -15 L 9.8125 -13.140625 L 4.890625 -13.140625 L 4.890625 -4.921875 C 4.890625 -3.679688 5.050781 -2.882812 5.375 -2.53125 C 5.695312 -2.1875 6.359375 -2.015625 7.359375 -2.015625 L 9.8125 -2.015625 L 9.8125 0 L 7.359375 0 C 5.503906 0 4.222656 -0.351562 3.515625 -1.0625 C 2.816406 -1.78125 2.46875 -3.082031 2.46875 -4.96875 L 2.46875 -13.140625 L 0.71875 -13.140625 L 0.71875 -15 L 2.46875 -15 L 2.46875 -19 Z M 4.890625 -19 "
+           id="path182" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-18">
+        <path
+           style="stroke:none;"
+           d="M 14.640625 -8.84375 L 14.640625 0 L 12.234375 0 L 12.234375 -8.765625 C 12.234375 -10.148438 11.960938 -11.1875 11.421875 -11.875 C 10.890625 -12.5625 10.085938 -12.90625 9.015625 -12.90625 C 7.722656 -12.90625 6.703125 -12.488281 5.953125 -11.65625 C 5.203125 -10.832031 4.828125 -9.707031 4.828125 -8.28125 L 4.828125 0 L 2.421875 0 L 2.421875 -20 L 4.828125 -20 L 4.828125 -12.375 C 5.398438 -13.25 6.070312 -13.90625 6.84375 -14.34375 C 7.625 -14.78125 8.523438 -15 9.546875 -15 C 11.222656 -15 12.488281 -14.476562 13.34375 -13.4375 C 14.207031 -12.394531 14.640625 -10.863281 14.640625 -8.84375 Z M 14.640625 -8.84375 "
+           id="path185" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph2-19">
+        <path
+           style="stroke:none;"
+           d="M 12.109375 -7.5 C 12.109375 -9.238281 11.75 -10.585938 11.03125 -11.546875 C 10.320312 -12.503906 9.316406 -12.984375 8.015625 -12.984375 C 6.734375 -12.984375 5.734375 -12.503906 5.015625 -11.546875 C 4.304688 -10.585938 3.953125 -9.238281 3.953125 -7.5 C 3.953125 -5.757812 4.304688 -4.410156 5.015625 -3.453125 C 5.734375 -2.492188 6.734375 -2.015625 8.015625 -2.015625 C 9.316406 -2.015625 10.320312 -2.492188 11.03125 -3.453125 C 11.75 -4.410156 12.109375 -5.757812 12.109375 -7.5 Z M 14.515625 -1.671875 C 14.515625 0.910156 13.960938 2.832031 12.859375 4.09375 C 11.753906 5.363281 10.0625 6 7.78125 6 C 6.945312 6 6.15625 5.929688 5.40625 5.796875 C 4.65625 5.671875 3.929688 5.476562 3.234375 5.21875 L 3.234375 2.75 C 3.929688 3.175781 4.625 3.488281 5.3125 3.6875 C 6 3.894531 6.695312 4 7.40625 4 C 8.976562 4 10.15625 3.554688 10.9375 2.671875 C 11.71875 1.796875 12.109375 0.46875 12.109375 -1.3125 L 12.109375 -2.578125 C 11.617188 -1.710938 10.984375 -1.066406 10.203125 -0.640625 C 9.429688 -0.210938 8.507812 0 7.4375 0 C 5.644531 0 4.203125 -0.679688 3.109375 -2.046875 C 2.015625 -3.421875 1.46875 -5.238281 1.46875 -7.5 C 1.46875 -9.757812 2.015625 -11.570312 3.109375 -12.9375 C 4.203125 -14.3125 5.644531 -15 7.4375 -15 C 8.507812 -15 9.429688 -14.785156 10.203125 -14.359375 C 10.984375 -13.929688 11.617188 -13.285156 12.109375 -12.421875 L 12.109375 -15 L 14.515625 -15 Z M 14.515625 -1.671875 "
+           id="path188" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-0">
+        <path
+           style="stroke:none;"
+           d="M 1.25 -10.6875 L 7.0625 -10.6875 L 7.0625 0 L 1.25 0 Z M 2 -0.75 L 6.3125 -0.75 L 6.3125 -9.953125 L 2 -9.953125 Z M 2 -0.75 "
+           id="path191" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-1">
+        <path
+           style="stroke:none;"
+           d="M 7.90625 -10 L 7.90625 -3.609375 C 7.90625 -2.441406 7.601562 -1.546875 7 -0.921875 C 6.40625 -0.304688 5.523438 0 4.359375 0 C 2.046875 0 0.890625 -1.210938 0.890625 -3.640625 L 0.890625 -10 L 2.234375 -10 L 2.234375 -3.765625 C 2.234375 -2.023438 2.960938 -1.15625 4.421875 -1.15625 C 5.835938 -1.15625 6.554688 -2.023438 6.578125 -3.765625 L 6.578125 -10 Z M 7.90625 -10 "
+           id="path194" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-2">
+        <path
+           style="stroke:none;"
+           d="M 3.078125 0 L 1.75 0 L 1.75 -10 L 7.765625 -10 L 7.765625 -8.828125 L 3.078125 -8.828125 L 3.078125 -5.984375 L 7.5 -5.984375 L 7.5 -4.828125 L 3.078125 -4.828125 Z M 3.078125 0 "
+           id="path197" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-3">
+        <path
+           style="stroke:none;"
+           d="M 6.609375 0 L 6.40625 -1.1875 L 6.34375 -1.1875 C 5.84375 -0.394531 5.046875 0 3.953125 0 C 2.078125 0 1.140625 -0.953125 1.140625 -2.859375 L 1.140625 -8 L 2.453125 -8 L 2.453125 -2.9375 C 2.453125 -1.695312 3.015625 -1.078125 4.140625 -1.078125 C 4.910156 -1.078125 5.472656 -1.296875 5.828125 -1.734375 C 6.179688 -2.179688 6.359375 -2.910156 6.359375 -3.921875 L 6.359375 -8 L 7.65625 -8 L 7.65625 0 Z M 6.609375 0 "
+           id="path200" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-4">
+        <path
+           style="stroke:none;"
+           d="M 6.359375 0 L 6.359375 -5.171875 C 6.359375 -6.429688 5.789062 -7.0625 4.65625 -7.0625 C 3.1875 -7.0625 2.453125 -6.09375 2.453125 -4.15625 L 2.453125 0 L 1.140625 0 L 1.140625 -8 L 2.203125 -8 L 2.390625 -6.9375 L 2.46875 -6.9375 C 2.957031 -7.644531 3.757812 -8 4.875 -8 C 6.726562 -8 7.65625 -7.039062 7.65625 -5.125 L 7.65625 0 Z M 6.359375 0 "
+           id="path203" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-5">
+        <path
+           style="stroke:none;"
+           d="M 7.59375 -7.578125 L 7.15625 -6.453125 C 6.4375 -6.710938 5.796875 -6.84375 5.234375 -6.84375 C 3.460938 -6.84375 2.578125 -5.882812 2.578125 -3.96875 C 2.578125 -2.082031 3.441406 -1.140625 5.171875 -1.140625 C 5.921875 -1.140625 6.6875 -1.285156 7.46875 -1.578125 L 7.46875 -0.4375 C 6.820312 -0.144531 6.035156 0 5.109375 0 C 3.878906 0 2.925781 -0.335938 2.25 -1.015625 C 1.570312 -1.703125 1.234375 -2.679688 1.234375 -3.953125 C 1.234375 -5.265625 1.578125 -6.265625 2.265625 -6.953125 C 2.960938 -7.648438 3.9375 -8 5.1875 -8 C 6.039062 -8 6.84375 -7.859375 7.59375 -7.578125 Z M 7.59375 -7.578125 "
+           id="path206" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-6">
+        <path
+           style="stroke:none;"
+           d="M 7.171875 0 L 1.609375 0 L 1.609375 -0.953125 L 3.71875 -0.953125 L 3.71875 -9.046875 L 1.609375 -9.046875 L 1.609375 -10 L 7.171875 -10 L 7.171875 -9.046875 L 5.0625 -9.046875 L 5.0625 -0.953125 L 7.171875 -0.953125 Z M 7.171875 0 "
+           id="path209" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-7">
+        <path
+           style="stroke:none;"
+           d="M 7 0 L 7 -5.171875 C 7 -5.878906 6.9375 -6.367188 6.8125 -6.640625 C 6.6875 -6.921875 6.472656 -7.0625 6.171875 -7.0625 C 5.753906 -7.0625 5.453125 -6.859375 5.265625 -6.453125 C 5.078125 -6.054688 4.984375 -5.378906 4.984375 -4.421875 L 4.984375 0 L 3.828125 0 L 3.828125 -5.171875 C 3.828125 -6.429688 3.53125 -7.0625 2.9375 -7.0625 C 2.53125 -7.0625 2.238281 -6.867188 2.0625 -6.484375 C 1.894531 -6.097656 1.8125 -5.320312 1.8125 -4.15625 L 1.8125 0 L 0.65625 0 L 0.65625 -8 L 1.5625 -8 L 1.765625 -6.9375 L 1.828125 -6.9375 C 2.148438 -7.644531 2.632812 -8 3.28125 -8 C 4.050781 -8 4.554688 -7.613281 4.796875 -6.84375 L 4.84375 -6.84375 C 5.207031 -7.613281 5.726562 -8 6.40625 -8 C 7.019531 -8 7.460938 -7.773438 7.734375 -7.328125 C 8.015625 -6.890625 8.15625 -6.15625 8.15625 -5.125 L 8.15625 0 Z M 7 0 "
+           id="path212" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-8">
+        <path
+           style="stroke:none;"
+           d="M 2.4375 -1.140625 L 2.34375 -1.140625 C 2.40625 -0.441406 2.4375 0 2.4375 0.1875 L 2.4375 4 L 1.125 4 L 1.125 -8 L 2.1875 -8 L 2.375 -6.9375 L 2.4375 -6.9375 C 2.957031 -7.644531 3.726562 -8 4.75 -8 C 5.707031 -8 6.457031 -7.644531 7 -6.9375 C 7.550781 -6.238281 7.828125 -5.257812 7.828125 -4 C 7.828125 -2.75 7.550781 -1.769531 7 -1.0625 C 6.445312 -0.351562 5.695312 0 4.75 0 C 3.757812 0 2.988281 -0.378906 2.4375 -1.140625 Z M 2.4375 -4.390625 L 2.4375 -4.09375 C 2.4375 -3 2.601562 -2.222656 2.9375 -1.765625 C 3.269531 -1.304688 3.796875 -1.078125 4.515625 -1.078125 C 5.816406 -1.078125 6.46875 -2.085938 6.46875 -4.109375 C 6.46875 -6.078125 5.8125 -7.0625 4.5 -7.0625 C 3.78125 -7.0625 3.257812 -6.851562 2.9375 -6.4375 C 2.625 -6.019531 2.457031 -5.335938 2.4375 -4.390625 Z M 2.4375 -4.390625 "
+           id="path215" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-9">
+        <path
+           style="stroke:none;"
+           d="M 3.8125 -9.984375 L 1.890625 -10.140625 L 1.890625 -11 L 5.125 -11 L 5.125 -0.953125 L 7.640625 -0.953125 L 7.640625 0 L 1.34375 0 L 1.34375 -0.953125 L 3.8125 -0.953125 Z M 3.8125 -9.984375 "
+           id="path218" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-10">
+        <path
+           style="stroke:none;"
+           d="M 6.734375 3.125 L 2.953125 3.125 L 2.953125 -10 L 6.734375 -10 L 6.734375 -8.9375 L 4.25 -8.9375 L 4.25 2.0625 L 6.734375 2.0625 Z M 6.734375 3.125 "
+           id="path221" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-11">
+        <path
+           style="stroke:none;"
+           d="M 0.96875 0 L 0.96875 -10 L 3.421875 -10 C 4.929688 -10 6.109375 -9.566406 6.953125 -8.703125 C 7.796875 -7.835938 8.21875 -6.632812 8.21875 -5.09375 C 8.21875 -3.445312 7.78125 -2.1875 6.90625 -1.3125 C 6.03125 -0.4375 4.769531 0 3.125 0 Z M 2.3125 -8.859375 L 2.3125 -1.140625 L 3 -1.140625 C 5.539062 -1.140625 6.8125 -2.441406 6.8125 -5.046875 C 6.8125 -7.585938 5.632812 -8.859375 3.28125 -8.859375 Z M 2.3125 -8.859375 "
+           id="path224" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-12">
+        <path
+           style="stroke:none;"
+           d="M 5.0625 0 L 3.71875 0 L 3.71875 -8.828125 L 0.734375 -8.828125 L 0.734375 -10 L 8.046875 -10 L 8.046875 -8.828125 L 5.0625 -8.828125 Z M 5.0625 0 "
+           id="path227" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-13">
+        <path
+           style="stroke:none;"
+           d="M 0.59375 -8 L 1.9375 -8 L 3.8125 -3.046875 C 4.207031 -2.003906 4.421875 -1.269531 4.453125 -0.84375 L 4.484375 -0.84375 C 4.597656 -1.414062 4.816406 -2.15625 5.140625 -3.0625 L 6.84375 -8 L 8.203125 -8 L 4.796875 1.359375 C 4.472656 2.234375 4.097656 2.890625 3.671875 3.328125 C 3.253906 3.773438 2.671875 4 1.921875 4 C 1.503906 4 1.101562 3.957031 0.71875 3.875 L 0.71875 2.828125 C 1.007812 2.890625 1.332031 2.921875 1.6875 2.921875 C 2.144531 2.921875 2.5 2.816406 2.75 2.609375 C 3.007812 2.410156 3.242188 2.054688 3.453125 1.546875 L 3.859375 0.40625 Z M 0.59375 -8 "
+           id="path230" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-14">
+        <path
+           style="stroke:none;"
+           d="M 7.859375 -3.875 L 2.3125 -3.875 C 2.34375 -2.050781 3.160156 -1.140625 4.765625 -1.140625 C 5.703125 -1.140625 6.585938 -1.320312 7.421875 -1.6875 L 7.421875 -0.53125 C 6.628906 -0.175781 5.757812 0 4.8125 0 C 3.644531 0 2.707031 -0.347656 2 -1.046875 C 1.300781 -1.753906 0.953125 -2.722656 0.953125 -3.953125 C 0.953125 -5.179688 1.273438 -6.160156 1.921875 -6.890625 C 2.566406 -7.628906 3.429688 -8 4.515625 -8 C 5.535156 -8 6.347656 -7.691406 6.953125 -7.078125 C 7.554688 -6.472656 7.859375 -5.664062 7.859375 -4.65625 Z M 2.328125 -4.9375 L 6.4375 -4.9375 C 6.4375 -6.25 5.785156 -6.90625 4.484375 -6.90625 C 3.171875 -6.90625 2.453125 -6.25 2.328125 -4.9375 Z M 2.328125 -4.9375 "
+           id="path233" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-15">
+        <path
+           style="stroke:none;"
+           d="M 5.515625 -1.9375 L 5.625 -1.765625 C 5.351562 -0.691406 4.890625 0.5625 4.234375 2 L 3.15625 2 C 3.519531 0.457031 3.785156 -0.851562 3.953125 -1.9375 Z M 5.515625 -1.9375 "
+           id="path236" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-16">
+        <path
+           style="stroke:none;"
+           d="M 4.40625 -2.375 C 5.125 -2.375 5.484375 -1.976562 5.484375 -1.1875 C 5.484375 -0.394531 5.125 0 4.40625 0 C 3.675781 0 3.3125 -0.394531 3.3125 -1.1875 C 3.3125 -1.976562 3.675781 -2.375 4.40625 -2.375 Z M 4.40625 -2.375 "
+           id="path239" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-17">
+        <path
+           style="stroke:none;"
+           d="M 2.078125 2.0625 L 4.546875 2.0625 L 4.546875 -8.9375 L 2.078125 -8.9375 L 2.078125 -10 L 5.859375 -10 L 5.859375 3.125 L 2.078125 3.125 Z M 2.078125 2.0625 "
+           id="path242" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-18">
+        <path
+           style="stroke:none;"
+           d="M 7.1875 0 L 6.15625 -2.8125 L 2.640625 -2.8125 L 1.59375 0 L 0.234375 0 L 3.703125 -10 L 5.09375 -10 L 8.5625 0 Z M 5.78125 -4 L 4.828125 -7 C 4.640625 -7.582031 4.492188 -8.113281 4.390625 -8.59375 C 4.285156 -8.125 4.175781 -7.691406 4.0625 -7.296875 L 3.015625 -4 Z M 5.78125 -4 "
+           id="path245" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-19">
+        <path
+           style="stroke:none;"
+           d="M 6.421875 -1.046875 L 6.375 -1.046875 C 5.832031 -0.347656 5.0625 0 4.0625 0 C 3.101562 0 2.347656 -0.347656 1.796875 -1.046875 C 1.253906 -1.753906 0.984375 -2.734375 0.984375 -3.984375 C 0.984375 -5.242188 1.253906 -6.226562 1.796875 -6.9375 C 2.347656 -7.644531 3.101562 -8 4.0625 -8 C 5.039062 -8 5.8125 -7.613281 6.375 -6.84375 L 6.453125 -6.84375 C 6.398438 -7.4375 6.375 -7.816406 6.375 -7.984375 L 6.375 -11 L 7.671875 -11 L 7.671875 0 L 6.625 0 Z M 6.375 -3.703125 L 6.375 -3.984375 C 6.375 -5.035156 6.207031 -5.785156 5.875 -6.234375 C 5.539062 -6.679688 5.007812 -6.90625 4.28125 -6.90625 C 2.976562 -6.90625 2.328125 -5.925781 2.328125 -3.96875 C 2.328125 -2.039062 2.984375 -1.078125 4.296875 -1.078125 C 5.023438 -1.078125 5.546875 -1.28125 5.859375 -1.6875 C 6.179688 -2.101562 6.351562 -2.773438 6.375 -3.703125 Z M 6.375 -3.703125 "
+           id="path248" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-20">
+        <path
+           style="stroke:none;"
+           d="M 5.328125 -11 C 5.835938 -11 6.09375 -10.726562 6.09375 -10.1875 C 6.09375 -9.632812 5.835938 -9.359375 5.328125 -9.359375 C 4.816406 -9.359375 4.5625 -9.632812 4.5625 -10.1875 C 4.5625 -10.726562 4.816406 -11 5.328125 -11 Z M 0.96875 3.75 L 0.96875 2.625 C 1.601562 2.820312 2.289062 2.921875 3.03125 2.921875 C 3.59375 2.921875 4.03125 2.773438 4.34375 2.484375 C 4.65625 2.191406 4.8125 1.789062 4.8125 1.28125 L 4.8125 -7.046875 L 1.8125 -7.046875 L 1.8125 -8 L 6.125 -8 L 6.125 1.171875 C 6.125 2.078125 5.851562 2.773438 5.3125 3.265625 C 4.769531 3.753906 4.003906 4 3.015625 4 C 2.234375 4 1.550781 3.914062 0.96875 3.75 Z M 0.96875 3.75 "
+           id="path251" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-21">
+        <path
+           style="stroke:none;"
+           d="M 1.453125 -0.484375 L 1.453125 -1.65625 C 2.378906 -1.257812 3.265625 -1.0625 4.109375 -1.0625 C 5.421875 -1.0625 6.078125 -1.441406 6.078125 -2.203125 C 6.078125 -2.460938 5.957031 -2.691406 5.71875 -2.890625 C 5.488281 -3.085938 4.953125 -3.335938 4.109375 -3.640625 C 2.992188 -4.046875 2.289062 -4.414062 2 -4.75 C 1.707031 -5.09375 1.5625 -5.492188 1.5625 -5.953125 C 1.5625 -6.585938 1.828125 -7.085938 2.359375 -7.453125 C 2.898438 -7.816406 3.640625 -8 4.578125 -8 C 5.523438 -8 6.40625 -7.820312 7.21875 -7.46875 L 6.796875 -6.40625 C 5.921875 -6.738281 5.15625 -6.90625 4.5 -6.90625 C 3.375 -6.90625 2.8125 -6.597656 2.8125 -5.984375 C 2.8125 -5.703125 2.929688 -5.472656 3.171875 -5.296875 C 3.410156 -5.117188 3.96875 -4.882812 4.84375 -4.59375 C 5.851562 -4.226562 6.519531 -3.867188 6.84375 -3.515625 C 7.175781 -3.171875 7.34375 -2.75 7.34375 -2.25 C 7.34375 -1.539062 7.0625 -0.988281 6.5 -0.59375 C 5.945312 -0.195312 5.160156 0 4.140625 0 C 2.953125 0 2.054688 -0.160156 1.453125 -0.484375 Z M 1.453125 -0.484375 "
+           id="path254" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-22">
+        <path
+           style="stroke:none;"
+           d="M 7.3125 -1.21875 L 7.3125 -0.234375 C 6.6875 -0.078125 6.082031 0 5.5 0 C 3.769531 0 2.90625 -0.816406 2.90625 -2.453125 L 2.90625 -7.03125 L 1 -7.03125 L 1 -7.703125 L 2.90625 -8.03125 L 3.453125 -10 L 4.21875 -10 L 4.21875 -8 L 7.34375 -8 L 7.34375 -7.03125 L 4.21875 -7.03125 L 4.21875 -2.453125 C 4.21875 -1.523438 4.675781 -1.0625 5.59375 -1.0625 C 6.03125 -1.0625 6.601562 -1.113281 7.3125 -1.21875 Z M 7.3125 -1.21875 "
+           id="path257" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-23">
+        <path
+           style="stroke:none;"
+           d=""
+           id="path260" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-24">
+        <path
+           style="stroke:none;"
+           d="M 6.40625 0 L 6.140625 -1.234375 L 6.09375 -1.234375 C 5.71875 -0.765625 5.335938 -0.441406 4.953125 -0.265625 C 4.566406 -0.0859375 4.066406 0 3.453125 0 C 2.679688 0 2.070312 -0.210938 1.625 -0.640625 C 1.1875 -1.078125 0.96875 -1.675781 0.96875 -2.4375 C 0.96875 -4.09375 2.1875 -4.921875 4.625 -4.921875 L 6.078125 -4.921875 L 6.078125 -5.375 C 6.078125 -6.394531 5.492188 -6.90625 4.328125 -6.90625 C 3.628906 -6.90625 2.847656 -6.734375 1.984375 -6.390625 L 1.53125 -7.296875 C 2.46875 -7.765625 3.378906 -8 4.265625 -8 C 5.347656 -8 6.128906 -7.789062 6.609375 -7.375 C 7.097656 -6.957031 7.34375 -6.289062 7.34375 -5.375 L 7.34375 0 Z M 6.0625 -4.078125 L 4.90625 -4.078125 C 3.96875 -4.078125 3.300781 -3.9375 2.90625 -3.65625 C 2.519531 -3.382812 2.328125 -2.972656 2.328125 -2.421875 C 2.328125 -1.503906 2.800781 -1.046875 3.75 -1.046875 C 4.457031 -1.046875 5.019531 -1.242188 5.4375 -1.640625 C 5.851562 -2.046875 6.0625 -2.613281 6.0625 -3.34375 Z M 6.0625 -4.078125 "
+           id="path263" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-25">
+        <path
+           style="stroke:none;"
+           d="M 7.59375 -7.703125 L 7.234375 -6.640625 C 6.648438 -6.859375 6.113281 -6.96875 5.625 -6.96875 C 4.851562 -6.96875 4.253906 -6.738281 3.828125 -6.28125 C 3.398438 -5.832031 3.1875 -5.179688 3.1875 -4.328125 L 3.1875 0 L 1.890625 0 L 1.890625 -8 L 2.953125 -8 L 3.109375 -6.5625 L 3.171875 -6.5625 C 3.535156 -7.082031 3.921875 -7.453125 4.328125 -7.671875 C 4.742188 -7.890625 5.257812 -8 5.875 -8 C 6.4375 -8 7.007812 -7.898438 7.59375 -7.703125 Z M 7.59375 -7.703125 "
+           id="path266" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-26">
+        <path
+           style="stroke:none;"
+           d="M 4.53125 -11 C 5.039062 -11 5.296875 -10.726562 5.296875 -10.1875 C 5.296875 -9.914062 5.21875 -9.707031 5.0625 -9.5625 C 4.914062 -9.425781 4.738281 -9.359375 4.53125 -9.359375 C 4.019531 -9.359375 3.765625 -9.632812 3.765625 -10.1875 C 3.765625 -10.726562 4.019531 -11 4.53125 -11 Z M 3.875 -6.953125 L 1.953125 -7.109375 L 1.953125 -8 L 5.171875 -8 L 5.171875 -0.953125 L 7.703125 -0.953125 L 7.703125 0 L 1.40625 0 L 1.40625 -0.953125 L 3.875 -0.953125 Z M 3.875 -6.953125 "
+           id="path269" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-27">
+        <path
+           style="stroke:none;"
+           d="M 5.296875 -10 L 6.671875 -10 C 4.523438 -8.175781 3.453125 -6.003906 3.453125 -3.484375 C 3.453125 -0.960938 4.519531 1.195312 6.65625 3 L 5.296875 3 C 3.171875 1.289062 2.109375 -0.863281 2.109375 -3.46875 C 2.109375 -6.0625 3.171875 -8.238281 5.296875 -10 Z M 5.296875 -10 "
+           id="path272" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-28">
+        <path
+           style="stroke:none;"
+           d="M 8.0625 -8 L 8.0625 -7.046875 L 6.65625 -6.8125 C 6.96875 -6.332031 7.125 -5.738281 7.125 -5.03125 C 7.125 -4.125 6.867188 -3.398438 6.359375 -2.859375 C 5.859375 -2.328125 5.148438 -2.0625 4.234375 -2.0625 C 3.972656 -2.0625 3.769531 -2.078125 3.625 -2.109375 C 3.144531 -1.929688 2.90625 -1.738281 2.90625 -1.53125 C 2.90625 -1.289062 3.289062 -1.171875 4.0625 -1.171875 L 5.40625 -1.171875 C 6.226562 -1.171875 6.859375 -0.972656 7.296875 -0.578125 C 7.742188 -0.191406 7.96875 0.367188 7.96875 1.109375 C 7.96875 3.035156 6.617188 4 3.921875 4 C 2.878906 4 2.085938 3.789062 1.546875 3.375 C 1.003906 2.957031 0.734375 2.375 0.734375 1.625 C 0.734375 0.519531 1.304688 -0.175781 2.453125 -0.46875 C 1.992188 -0.632812 1.765625 -0.910156 1.765625 -1.296875 C 1.765625 -1.691406 2.082031 -2.035156 2.71875 -2.328125 C 2.289062 -2.535156 1.953125 -2.867188 1.703125 -3.328125 C 1.460938 -3.796875 1.34375 -4.304688 1.34375 -4.859375 C 1.34375 -5.859375 1.597656 -6.628906 2.109375 -7.171875 C 2.617188 -7.722656 3.34375 -8 4.28125 -8 C 4.695312 -8 5.054688 -8 5.359375 -8 Z M 4.25 -2.9375 C 5.320312 -2.9375 5.859375 -3.609375 5.859375 -4.953125 C 5.859375 -6.359375 5.316406 -7.0625 4.234375 -7.0625 C 3.160156 -7.0625 2.625 -6.351562 2.625 -4.9375 C 2.625 -3.601562 3.164062 -2.9375 4.25 -2.9375 Z M 4.953125 0 L 3.609375 0 C 2.515625 0 1.96875 0.53125 1.96875 1.59375 C 1.96875 2.539062 2.613281 3.015625 3.90625 3.015625 C 5.789062 3.015625 6.734375 2.410156 6.734375 1.203125 C 6.734375 0.734375 6.613281 0.414062 6.375 0.25 C 6.132812 0.0820312 5.660156 0 4.953125 0 Z M 4.953125 0 "
+           id="path275" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-29">
+        <path
+           style="stroke:none;"
+           d="M 6.359375 0 L 6.359375 -5.0625 C 6.359375 -6.289062 5.789062 -6.90625 4.65625 -6.90625 C 3.1875 -6.90625 2.453125 -5.957031 2.453125 -4.0625 L 2.453125 0 L 1.140625 0 L 1.140625 -11 L 2.453125 -11 L 2.453125 -7.78125 L 2.390625 -6.78125 L 2.46875 -6.78125 C 2.957031 -7.59375 3.757812 -8 4.875 -8 C 6.726562 -8 7.65625 -7.039062 7.65625 -5.125 L 7.65625 0 Z M 6.359375 0 "
+           id="path278" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph3-30">
+        <path
+           style="stroke:none;"
+           d="M 3.5 3 L 2.140625 3 C 4.273438 1.195312 5.34375 -0.960938 5.34375 -3.484375 C 5.34375 -6.003906 4.269531 -8.175781 2.125 -10 L 3.5 -10 C 5.625 -8.25 6.6875 -6.070312 6.6875 -3.46875 C 6.6875 -0.851562 5.625 1.300781 3.5 3 Z M 3.5 3 "
+           id="path281" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-0">
+        <path
+           style="stroke:none;"
+           d="M 0.875 2.140625 L 0.875 -9.609375 L 7.734375 -9.609375 L 7.734375 2.140625 Z M 1.625 1.390625 L 7 1.390625 L 7 -8.875 L 1.625 -8.875 Z M 1.625 1.390625 "
+           id="path284" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-1">
+        <path
+           style="stroke:none;"
+           d="M 5.484375 -6.796875 C 5.347656 -6.878906 5.195312 -6.941406 5.03125 -6.984375 C 4.875 -7.023438 4.703125 -7.046875 4.515625 -7.046875 C 3.835938 -7.046875 3.316406 -6.800781 2.953125 -6.3125 C 2.597656 -5.832031 2.421875 -5.132812 2.421875 -4.21875 L 2.421875 0 L 1.203125 0 L 1.203125 -8 L 2.421875 -8 L 2.421875 -6.78125 C 2.671875 -7.195312 2.992188 -7.503906 3.390625 -7.703125 C 3.796875 -7.898438 4.289062 -8 4.875 -8 C 4.945312 -8 5.035156 -8.007812 5.140625 -8.03125 C 5.242188 -8.050781 5.351562 -8.078125 5.46875 -8.109375 Z M 5.484375 -6.796875 "
+           id="path287" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-2">
+        <path
+           style="stroke:none;"
+           d="M 7.484375 -4.5625 L 7.484375 -4 L 1.984375 -4 C 2.035156 -3.050781 2.28125 -2.328125 2.71875 -1.828125 C 3.164062 -1.335938 3.789062 -1.09375 4.59375 -1.09375 C 5.050781 -1.09375 5.492188 -1.15625 5.921875 -1.28125 C 6.359375 -1.414062 6.785156 -1.613281 7.203125 -1.875 L 7.203125 -0.609375 C 6.773438 -0.421875 6.335938 -0.269531 5.890625 -0.15625 C 5.441406 -0.0507812 4.984375 0 4.515625 0 C 3.347656 0 2.425781 -0.351562 1.75 -1.0625 C 1.070312 -1.769531 0.734375 -2.726562 0.734375 -3.9375 C 0.734375 -5.1875 1.054688 -6.175781 1.703125 -6.90625 C 2.347656 -7.632812 3.21875 -8 4.3125 -8 C 5.289062 -8 6.0625 -7.691406 6.625 -7.078125 C 7.195312 -6.460938 7.484375 -5.625 7.484375 -4.5625 Z M 6.296875 -5 C 6.285156 -5.582031 6.097656 -6.046875 5.734375 -6.390625 C 5.378906 -6.734375 4.910156 -6.90625 4.328125 -6.90625 C 3.648438 -6.90625 3.109375 -6.738281 2.703125 -6.40625 C 2.304688 -6.070312 2.082031 -5.601562 2.03125 -5 Z M 6.296875 -5 "
+           id="path290" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-3">
+        <path
+           style="stroke:none;"
+           d="M 1.96875 -4 C 1.96875 -3.09375 2.148438 -2.378906 2.515625 -1.859375 C 2.878906 -1.335938 3.378906 -1.078125 4.015625 -1.078125 C 4.640625 -1.078125 5.132812 -1.335938 5.5 -1.859375 C 5.863281 -2.378906 6.046875 -3.09375 6.046875 -4 C 6.046875 -4.90625 5.863281 -5.617188 5.5 -6.140625 C 5.132812 -6.660156 4.640625 -6.921875 4.015625 -6.921875 C 3.378906 -6.921875 2.878906 -6.660156 2.515625 -6.140625 C 2.148438 -5.617188 1.96875 -4.90625 1.96875 -4 Z M 6.046875 -1.375 C 5.796875 -0.90625 5.476562 -0.554688 5.09375 -0.328125 C 4.707031 -0.109375 4.25 0 3.71875 0 C 2.832031 0 2.113281 -0.363281 1.5625 -1.09375 C 1.007812 -1.832031 0.734375 -2.800781 0.734375 -4 C 0.734375 -5.195312 1.007812 -6.160156 1.5625 -6.890625 C 2.113281 -7.628906 2.832031 -8 3.71875 -8 C 4.25 -8 4.707031 -7.882812 5.09375 -7.65625 C 5.476562 -7.425781 5.796875 -7.082031 6.046875 -6.625 L 6.046875 -8 L 7.25 -8 L 7.25 3 L 6.046875 3 Z M 6.046875 -1.375 "
+           id="path293" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-4">
+        <path
+           style="stroke:none;"
+           d="M 1.125 -3.28125 L 1.125 -8 L 2.328125 -8 L 2.328125 -3.1875 C 2.328125 -2.425781 2.460938 -1.851562 2.734375 -1.46875 C 3.003906 -1.09375 3.40625 -0.90625 3.9375 -0.90625 C 4.582031 -0.90625 5.09375 -1.128906 5.46875 -1.578125 C 5.851562 -2.035156 6.046875 -2.65625 6.046875 -3.4375 L 6.046875 -8 L 7.234375 -8 L 7.234375 0 L 6.046875 0 L 6.046875 -1.203125 C 5.753906 -0.796875 5.414062 -0.492188 5.03125 -0.296875 C 4.644531 -0.0976562 4.195312 0 3.6875 0 C 2.851562 0 2.21875 -0.273438 1.78125 -0.828125 C 1.34375 -1.390625 1.125 -2.207031 1.125 -3.28125 Z M 4.140625 -8 Z M 4.140625 -8 "
+           id="path296" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-5">
+        <path
+           style="stroke:none;"
+           d="M 1.25 -8 L 2.453125 -8 L 2.453125 0 L 1.25 0 Z M 1.25 -11 L 2.453125 -11 L 2.453125 -9.375 L 1.25 -9.375 Z M 1.25 -11 "
+           id="path299" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-6">
+        <path
+           style="stroke:none;"
+           d="M 5.90625 -7.578125 L 5.90625 -6.390625 C 5.5625 -6.566406 5.207031 -6.695312 4.84375 -6.78125 C 4.476562 -6.875 4.101562 -6.921875 3.71875 -6.921875 C 3.125 -6.921875 2.675781 -6.828125 2.375 -6.640625 C 2.082031 -6.453125 1.9375 -6.164062 1.9375 -5.78125 C 1.9375 -5.5 2.039062 -5.273438 2.25 -5.109375 C 2.46875 -4.941406 2.894531 -4.78125 3.53125 -4.625 L 3.9375 -4.53125 C 4.789062 -4.34375 5.394531 -4.078125 5.75 -3.734375 C 6.113281 -3.390625 6.296875 -2.910156 6.296875 -2.296875 C 6.296875 -1.585938 6.023438 -1.023438 5.484375 -0.609375 C 4.953125 -0.203125 4.21875 0 3.28125 0 C 2.882812 0 2.472656 -0.0390625 2.046875 -0.125 C 1.628906 -0.207031 1.1875 -0.328125 0.71875 -0.484375 L 0.71875 -1.796875 C 1.164062 -1.554688 1.601562 -1.375 2.03125 -1.25 C 2.457031 -1.132812 2.882812 -1.078125 3.3125 -1.078125 C 3.875 -1.078125 4.304688 -1.175781 4.609375 -1.375 C 4.910156 -1.570312 5.0625 -1.859375 5.0625 -2.234375 C 5.0625 -2.566406 4.953125 -2.820312 4.734375 -3 C 4.515625 -3.1875 4.035156 -3.359375 3.296875 -3.515625 L 2.875 -3.625 C 2.132812 -3.789062 1.597656 -4.039062 1.265625 -4.375 C 0.941406 -4.707031 0.78125 -5.164062 0.78125 -5.75 C 0.78125 -6.46875 1.019531 -7.019531 1.5 -7.40625 C 1.988281 -7.800781 2.679688 -8 3.578125 -8 C 4.015625 -8 4.425781 -7.960938 4.8125 -7.890625 C 5.207031 -7.816406 5.570312 -7.710938 5.90625 -7.578125 Z M 5.90625 -7.578125 "
+           id="path302" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-7">
+        <path
+           style="stroke:none;"
+           d="M 7.125 -9.46875 L 7.125 -8.171875 C 6.632812 -8.398438 6.164062 -8.570312 5.71875 -8.6875 C 5.28125 -8.800781 4.851562 -8.859375 4.4375 -8.859375 C 3.71875 -8.859375 3.164062 -8.722656 2.78125 -8.453125 C 2.394531 -8.179688 2.203125 -7.789062 2.203125 -7.28125 C 2.203125 -6.863281 2.328125 -6.546875 2.578125 -6.328125 C 2.835938 -6.109375 3.328125 -5.9375 4.046875 -5.8125 L 4.84375 -5.640625 C 5.820312 -5.460938 6.546875 -5.140625 7.015625 -4.671875 C 7.484375 -4.210938 7.71875 -3.597656 7.71875 -2.828125 C 7.71875 -1.898438 7.398438 -1.195312 6.765625 -0.71875 C 6.140625 -0.238281 5.21875 0 4 0 C 3.539062 0 3.050781 -0.0507812 2.53125 -0.15625 C 2.007812 -0.269531 1.472656 -0.4375 0.921875 -0.65625 L 0.921875 -2.015625 C 1.453125 -1.722656 1.972656 -1.503906 2.484375 -1.359375 C 2.992188 -1.210938 3.5 -1.140625 4 -1.140625 C 4.75 -1.140625 5.328125 -1.285156 5.734375 -1.578125 C 6.140625 -1.867188 6.34375 -2.28125 6.34375 -2.8125 C 6.34375 -3.28125 6.195312 -3.648438 5.90625 -3.921875 C 5.613281 -4.191406 5.132812 -4.390625 4.46875 -4.515625 L 3.65625 -4.671875 C 2.675781 -4.859375 1.96875 -5.15625 1.53125 -5.5625 C 1.09375 -5.976562 0.875 -6.550781 0.875 -7.28125 C 0.875 -8.113281 1.175781 -8.773438 1.78125 -9.265625 C 2.382812 -9.753906 3.21875 -10 4.28125 -10 C 4.738281 -10 5.203125 -9.953125 5.671875 -9.859375 C 6.148438 -9.773438 6.632812 -9.644531 7.125 -9.46875 Z M 7.125 -9.46875 "
+           id="path305" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-8">
+        <path
+           style="stroke:none;"
+           d="M 7.3125 -4.71875 L 7.3125 0 L 6.125 0 L 6.125 -4.671875 C 6.125 -5.410156 5.988281 -5.960938 5.71875 -6.328125 C 5.445312 -6.691406 5.039062 -6.875 4.5 -6.875 C 3.851562 -6.875 3.34375 -6.65625 2.96875 -6.21875 C 2.601562 -5.78125 2.421875 -5.175781 2.421875 -4.40625 L 2.421875 0 L 1.203125 0 L 1.203125 -11 L 2.421875 -11 L 2.421875 -6.59375 C 2.703125 -7.0625 3.035156 -7.410156 3.421875 -7.640625 C 3.816406 -7.878906 4.265625 -8 4.765625 -8 C 5.609375 -8 6.242188 -7.71875 6.671875 -7.15625 C 7.097656 -6.601562 7.3125 -5.789062 7.3125 -4.71875 Z M 7.3125 -4.71875 "
+           id="path308" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-9">
+        <path
+           style="stroke:none;"
+           d="M 4.5625 -4 C 3.601562 -4 2.9375 -3.878906 2.5625 -3.640625 C 2.1875 -3.398438 2 -2.984375 2 -2.390625 C 2 -1.921875 2.140625 -1.550781 2.421875 -1.28125 C 2.703125 -1.007812 3.082031 -0.875 3.5625 -0.875 C 4.226562 -0.875 4.757812 -1.128906 5.15625 -1.640625 C 5.5625 -2.160156 5.765625 -2.851562 5.765625 -3.71875 L 5.765625 -4 Z M 6.953125 -4.453125 L 6.953125 0 L 5.765625 0 L 5.765625 -1.203125 C 5.484375 -0.785156 5.140625 -0.476562 4.734375 -0.28125 C 4.328125 -0.09375 3.828125 0 3.234375 0 C 2.492188 0 1.898438 -0.21875 1.453125 -0.65625 C 1.015625 -1.09375 0.796875 -1.675781 0.796875 -2.40625 C 0.796875 -3.269531 1.070312 -3.914062 1.625 -4.34375 C 2.175781 -4.78125 2.992188 -5 4.078125 -5 L 5.765625 -5 L 5.765625 -5.125 C 5.765625 -5.6875 5.582031 -6.125 5.21875 -6.4375 C 4.851562 -6.75 4.34375 -6.90625 3.6875 -6.90625 C 3.269531 -6.90625 2.863281 -6.851562 2.46875 -6.75 C 2.070312 -6.644531 1.691406 -6.488281 1.328125 -6.28125 L 1.328125 -7.453125 C 1.765625 -7.628906 2.191406 -7.765625 2.609375 -7.859375 C 3.023438 -7.953125 3.425781 -8 3.8125 -8 C 4.863281 -8 5.648438 -7.703125 6.171875 -7.109375 C 6.691406 -6.523438 6.953125 -5.640625 6.953125 -4.453125 Z M 6.953125 -4.453125 "
+           id="path311" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-10">
+        <path
+           style="stroke:none;"
+           d=""
+           id="path314" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-11">
+        <path
+           style="stroke:none;"
+           d="M 4.5625 -9.15625 L 2.765625 -3.984375 L 6.34375 -3.984375 Z M 3.8125 -10 L 5.296875 -10 L 9 0 L 7.640625 0 L 6.75 -2.828125 L 2.375 -2.828125 L 1.484375 0 L 0.109375 0 Z M 3.8125 -10 "
+           id="path317" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-12">
+        <path
+           style="stroke:none;"
+           d="M 2.625 -8.84375 L 2.625 -4.984375 L 4.28125 -4.984375 C 4.882812 -4.984375 5.351562 -5.148438 5.6875 -5.484375 C 6.03125 -5.816406 6.203125 -6.296875 6.203125 -6.921875 C 6.203125 -7.535156 6.03125 -8.007812 5.6875 -8.34375 C 5.351562 -8.675781 4.882812 -8.84375 4.28125 -8.84375 Z M 1.3125 -10 L 4.28125 -10 C 5.363281 -10 6.179688 -9.738281 6.734375 -9.21875 C 7.296875 -8.695312 7.578125 -7.925781 7.578125 -6.90625 C 7.578125 -5.894531 7.296875 -5.128906 6.734375 -4.609375 C 6.179688 -4.085938 5.363281 -3.828125 4.28125 -3.828125 L 2.625 -3.828125 L 2.625 0 L 1.3125 0 Z M 1.3125 -10 "
+           id="path320" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-13">
+        <path
+           style="stroke:none;"
+           d="M 1.3125 -10 L 2.625 -10 L 2.625 0 L 1.3125 0 Z M 1.3125 -10 "
+           id="path323" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-14">
+        <path
+           style="stroke:none;"
+           d="M 3.390625 -10 L 4.484375 -10 L 1.109375 1.5 L 0 1.5 Z M 3.390625 -10 "
+           id="path326" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-15">
+        <path
+           style="stroke:none;"
+           d="M 6.9375 -6.3125 C 7.226562 -6.882812 7.582031 -7.304688 8 -7.578125 C 8.414062 -7.859375 8.90625 -8 9.46875 -8 C 10.226562 -8 10.8125 -7.710938 11.21875 -7.140625 C 11.632812 -6.566406 11.84375 -5.757812 11.84375 -4.71875 L 11.84375 0 L 10.640625 0 L 10.640625 -4.671875 C 10.640625 -5.421875 10.515625 -5.972656 10.265625 -6.328125 C 10.023438 -6.691406 9.648438 -6.875 9.140625 -6.875 C 8.523438 -6.875 8.035156 -6.65625 7.671875 -6.21875 C 7.304688 -5.78125 7.125 -5.175781 7.125 -4.40625 L 7.125 0 L 5.921875 0 L 5.921875 -4.671875 C 5.921875 -5.421875 5.796875 -5.972656 5.546875 -6.328125 C 5.304688 -6.691406 4.925781 -6.875 4.40625 -6.875 C 3.800781 -6.875 3.316406 -6.648438 2.953125 -6.203125 C 2.597656 -5.765625 2.421875 -5.164062 2.421875 -4.40625 L 2.421875 0 L 1.203125 0 L 1.203125 -8 L 2.421875 -8 L 2.421875 -6.59375 C 2.691406 -7.070312 3.015625 -7.425781 3.390625 -7.65625 C 3.773438 -7.882812 4.226562 -8 4.75 -8 C 5.28125 -8 5.734375 -7.851562 6.109375 -7.5625 C 6.484375 -7.269531 6.757812 -6.851562 6.9375 -6.3125 Z M 6.9375 -6.3125 "
+           id="path329" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-16">
+        <path
+           style="stroke:none;"
+           d="M 2.4375 -10 L 2.4375 -8 L 4.90625 -8 L 4.90625 -7 L 2.4375 -7 L 2.4375 -2.625 C 2.4375 -1.96875 2.515625 -1.546875 2.671875 -1.359375 C 2.835938 -1.171875 3.171875 -1.078125 3.671875 -1.078125 L 4.90625 -1.078125 L 4.90625 0 L 3.671875 0 C 2.753906 0 2.117188 -0.1875 1.765625 -0.5625 C 1.410156 -0.945312 1.234375 -1.644531 1.234375 -2.65625 L 1.234375 -7 L 0.359375 -7 L 0.359375 -8 L 1.234375 -8 L 1.234375 -10 Z M 2.4375 -10 "
+           id="path332" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-17">
+        <path
+           style="stroke:none;"
+           d="M 4.078125 -6.90625 C 3.441406 -6.90625 2.9375 -6.644531 2.5625 -6.125 C 2.1875 -5.601562 2 -4.894531 2 -4 C 2 -3.101562 2.179688 -2.394531 2.546875 -1.875 C 2.921875 -1.351562 3.429688 -1.09375 4.078125 -1.09375 C 4.710938 -1.09375 5.21875 -1.351562 5.59375 -1.875 C 5.96875 -2.394531 6.15625 -3.101562 6.15625 -4 C 6.15625 -4.894531 5.96875 -5.601562 5.59375 -6.125 C 5.21875 -6.644531 4.710938 -6.90625 4.078125 -6.90625 Z M 4.078125 -8 C 5.117188 -8 5.9375 -7.644531 6.53125 -6.9375 C 7.125 -6.226562 7.421875 -5.25 7.421875 -4 C 7.421875 -2.757812 7.125 -1.78125 6.53125 -1.0625 C 5.9375 -0.351562 5.117188 0 4.078125 0 C 3.035156 0 2.21875 -0.351562 1.625 -1.0625 C 1.03125 -1.78125 0.734375 -2.757812 0.734375 -4 C 0.734375 -5.25 1.03125 -6.226562 1.625 -6.9375 C 2.21875 -7.644531 3.035156 -8 4.078125 -8 Z M 4.078125 -8 "
+           id="path335" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-18">
+        <path
+           style="stroke:none;"
+           d="M 6.046875 -6.625 L 6.046875 -11 L 7.25 -11 L 7.25 0 L 6.046875 0 L 6.046875 -1.171875 C 5.796875 -0.773438 5.476562 -0.476562 5.09375 -0.28125 C 4.707031 -0.09375 4.25 0 3.71875 0 C 2.832031 0 2.113281 -0.363281 1.5625 -1.09375 C 1.007812 -1.832031 0.734375 -2.800781 0.734375 -4 C 0.734375 -5.195312 1.007812 -6.160156 1.5625 -6.890625 C 2.113281 -7.628906 2.832031 -8 3.71875 -8 C 4.25 -8 4.707031 -7.882812 5.09375 -7.65625 C 5.476562 -7.425781 5.796875 -7.082031 6.046875 -6.625 Z M 1.96875 -3.890625 C 1.96875 -2.953125 2.148438 -2.210938 2.515625 -1.671875 C 2.878906 -1.140625 3.378906 -0.875 4.015625 -0.875 C 4.640625 -0.875 5.132812 -1.140625 5.5 -1.671875 C 5.863281 -2.210938 6.046875 -2.953125 6.046875 -3.890625 C 6.046875 -4.835938 5.863281 -5.578125 5.5 -6.109375 C 5.132812 -6.648438 4.640625 -6.921875 4.015625 -6.921875 C 3.378906 -6.921875 2.878906 -6.648438 2.515625 -6.109375 C 2.148438 -5.578125 1.96875 -4.835938 1.96875 -3.890625 Z M 1.96875 -3.890625 "
+           id="path338" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-19">
+        <path
+           style="stroke:none;"
+           d="M 0.390625 -8 L 1.671875 -8 L 3.9375 -1.28125 L 6.21875 -8 L 7.484375 -8 L 4.75 0 L 3.125 0 Z M 0.390625 -8 "
+           id="path341" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-20">
+        <path
+           style="stroke:none;"
+           d="M 2.625 -4.84375 L 2.625 -1.15625 L 4.734375 -1.15625 C 5.441406 -1.15625 5.960938 -1.304688 6.296875 -1.609375 C 6.640625 -1.910156 6.8125 -2.375 6.8125 -3 C 6.8125 -3.632812 6.640625 -4.097656 6.296875 -4.390625 C 5.960938 -4.691406 5.441406 -4.84375 4.734375 -4.84375 Z M 2.625 -8.84375 L 2.625 -5.96875 L 4.5625 -5.96875 C 5.207031 -5.96875 5.6875 -6.085938 6 -6.328125 C 6.3125 -6.566406 6.46875 -6.925781 6.46875 -7.40625 C 6.46875 -7.882812 6.3125 -8.242188 6 -8.484375 C 5.6875 -8.722656 5.207031 -8.84375 4.5625 -8.84375 Z M 1.3125 -10 L 4.671875 -10 C 5.671875 -10 6.441406 -9.785156 6.984375 -9.359375 C 7.523438 -8.941406 7.796875 -8.34375 7.796875 -7.5625 C 7.796875 -6.96875 7.65625 -6.492188 7.375 -6.140625 C 7.101562 -5.785156 6.695312 -5.5625 6.15625 -5.46875 C 6.800781 -5.320312 7.300781 -5.019531 7.65625 -4.5625 C 8.019531 -4.101562 8.203125 -3.523438 8.203125 -2.828125 C 8.203125 -1.929688 7.90625 -1.234375 7.3125 -0.734375 C 6.726562 -0.242188 5.890625 0 4.796875 0 L 1.3125 0 Z M 1.3125 -10 "
+           id="path344" />
+      </symbol>
+      <symbol
+         overflow="visible"
+         id="glyph4-21">
+        <path
+           style="stroke:none;"
+           d="M 4.28125 0.703125 C 3.945312 1.660156 3.617188 2.28125 3.296875 2.5625 C 2.972656 2.851562 2.546875 3 2.015625 3 L 1.046875 3 L 1.046875 1.921875 L 1.75 1.921875 C 2.082031 1.921875 2.335938 1.832031 2.515625 1.65625 C 2.703125 1.488281 2.90625 1.085938 3.125 0.453125 L 3.34375 -0.140625 L 0.390625 -8 L 1.671875 -8 L 3.9375 -1.75 L 6.21875 -8 L 7.484375 -8 Z M 4.28125 0.703125 "
+           id="path347" />
+      </symbol>
+    </g>
+  </defs>
+  <g
+     id="surface913125">
+    <rect
+       style="opacity:0.275;fill:#008080;fill-opacity:1;stroke:none;stroke-width:1.03388488;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+       id="rect2198"
+       width="576.52246"
+       height="351.20435"
+       x="5.4733415"
+       y="362.4101"
+       rx="8.0613747"
+       ry="7.3037553" />
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(77.647059%,14.901961%,18.039216%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 334.433406 906.716003 C 437.433406 906.716003 437.433406 724.216003 540.433406 724.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path354" />
+    <path
+       style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(77.647059%,14.901961%,18.039216%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 545.433406 700.216003 L 678.433406 700.216003 C 678.433406 700.216003 688.433406 724.216003 678.433406 748.216003 L 545.433406 748.216003 C 545.433406 748.216003 535.433406 724.216003 545.433406 700.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path356" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g390">
+      <use
+         xlink:href="#glyph0-1"
+         x="318"
+         y="325.839844"
+         id="use358" />
+      <use
+         xlink:href="#glyph0-2"
+         x="329"
+         y="325.839844"
+         id="use360" />
+      <use
+         xlink:href="#glyph0-3"
+         x="336"
+         y="325.839844"
+         id="use362" />
+      <use
+         xlink:href="#glyph0-4"
+         x="345"
+         y="325.839844"
+         id="use364" />
+      <use
+         xlink:href="#glyph0-5"
+         x="354"
+         y="325.839844"
+         id="use366" />
+      <use
+         xlink:href="#glyph0-6"
+         x="363"
+         y="325.839844"
+         id="use368" />
+      <use
+         xlink:href="#glyph0-7"
+         x="368"
+         y="325.839844"
+         id="use370" />
+      <use
+         xlink:href="#glyph0-8"
+         x="379"
+         y="325.839844"
+         id="use372" />
+      <use
+         xlink:href="#glyph0-5"
+         x="383"
+         y="325.839844"
+         id="use374" />
+      <use
+         xlink:href="#glyph0-9"
+         x="392"
+         y="325.839844"
+         id="use376" />
+      <use
+         xlink:href="#glyph0-10"
+         x="398"
+         y="325.839844"
+         id="use378" />
+      <use
+         xlink:href="#glyph0-9"
+         x="407"
+         y="325.839844"
+         id="use380" />
+      <use
+         xlink:href="#glyph0-11"
+         x="413"
+         y="325.839844"
+         id="use382" />
+      <use
+         xlink:href="#glyph0-12"
+         x="421"
+         y="325.839844"
+         id="use384" />
+      <use
+         xlink:href="#glyph0-3"
+         x="430"
+         y="325.839844"
+         id="use386" />
+      <use
+         xlink:href="#glyph0-6"
+         x="439"
+         y="325.839844"
+         id="use388" />
+    </g>
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g426">
+      <use
+         xlink:href="#glyph0-13"
+         x="318"
+         y="343.839844"
+         id="use392" />
+      <use
+         xlink:href="#glyph0-10"
+         x="324"
+         y="343.839844"
+         id="use394" />
+      <use
+         xlink:href="#glyph0-14"
+         x="333"
+         y="343.839844"
+         id="use396" />
+      <use
+         xlink:href="#glyph0-15"
+         x="342"
+         y="343.839844"
+         id="use398" />
+      <use
+         xlink:href="#glyph0-16"
+         x="350"
+         y="343.839844"
+         id="use400" />
+      <use
+         xlink:href="#glyph0-9"
+         x="356"
+         y="343.839844"
+         id="use402" />
+      <use
+         xlink:href="#glyph0-10"
+         x="362"
+         y="343.839844"
+         id="use404" />
+      <use
+         xlink:href="#glyph0-11"
+         x="371"
+         y="343.839844"
+         id="use406" />
+      <use
+         xlink:href="#glyph0-16"
+         x="379"
+         y="343.839844"
+         id="use408" />
+      <use
+         xlink:href="#glyph0-6"
+         x="385"
+         y="343.839844"
+         id="use410" />
+      <use
+         xlink:href="#glyph0-1"
+         x="390"
+         y="343.839844"
+         id="use412" />
+      <use
+         xlink:href="#glyph0-2"
+         x="401"
+         y="343.839844"
+         id="use414" />
+      <use
+         xlink:href="#glyph0-3"
+         x="408"
+         y="343.839844"
+         id="use416" />
+      <use
+         xlink:href="#glyph0-4"
+         x="417"
+         y="343.839844"
+         id="use418" />
+      <use
+         xlink:href="#glyph0-5"
+         x="426"
+         y="343.839844"
+         id="use420" />
+      <use
+         xlink:href="#glyph0-15"
+         x="435"
+         y="343.839844"
+         id="use422" />
+      <use
+         xlink:href="#glyph0-17"
+         x="443"
+         y="343.839844"
+         id="use424" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47.843137%,21.176471%,69.411765%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 334.433406 906.716003 C 437.433406 906.716003 437.433406 783.216003 540.433406 783.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path428" />
+    <path
+       style="fill-rule:nonzero;fill:none;fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47%, 21%, 69%);stroke-opacity:1;stroke-miterlimit:10"
+       d="M 540.433406 768.216003 L 741.433406 768.216003 L 741.433406 798.216003 L 540.433406 798.216003 Z M 540.433406 768.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path430" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g482">
+      <use
+         xlink:href="#glyph0-18"
+         x="318"
+         y="393.839844"
+         id="use432" />
+      <use
+         xlink:href="#glyph0-16"
+         x="327"
+         y="393.839844"
+         id="use434" />
+      <use
+         xlink:href="#glyph0-19"
+         x="333"
+         y="393.839844"
+         id="use436" />
+      <use
+         xlink:href="#glyph0-9"
+         x="342"
+         y="393.839844"
+         id="use438" />
+      <use
+         xlink:href="#glyph0-5"
+         x="348"
+         y="393.839844"
+         id="use440" />
+      <use
+         xlink:href="#glyph0-15"
+         x="357"
+         y="393.839844"
+         id="use442" />
+      <use
+         xlink:href="#glyph0-6"
+         x="365"
+         y="393.839844"
+         id="use444" />
+      <use
+         xlink:href="#glyph0-11"
+         x="370"
+         y="393.839844"
+         id="use446" />
+      <use
+         xlink:href="#glyph0-10"
+         x="378"
+         y="393.839844"
+         id="use448" />
+      <use
+         xlink:href="#glyph0-15"
+         x="387"
+         y="393.839844"
+         id="use450" />
+      <use
+         xlink:href="#glyph0-16"
+         x="395"
+         y="393.839844"
+         id="use452" />
+      <use
+         xlink:href="#glyph0-8"
+         x="401"
+         y="393.839844"
+         id="use454" />
+      <use
+         xlink:href="#glyph0-20"
+         x="405"
+         y="393.839844"
+         id="use456" />
+      <use
+         xlink:href="#glyph0-21"
+         x="414"
+         y="393.839844"
+         id="use458" />
+      <use
+         xlink:href="#glyph0-8"
+         x="423"
+         y="393.839844"
+         id="use460" />
+      <use
+         xlink:href="#glyph0-20"
+         x="427"
+         y="393.839844"
+         id="use462" />
+      <use
+         xlink:href="#glyph0-22"
+         x="436"
+         y="393.839844"
+         id="use464" />
+      <use
+         xlink:href="#glyph0-19"
+         x="441"
+         y="393.839844"
+         id="use466" />
+      <use
+         xlink:href="#glyph0-9"
+         x="450"
+         y="393.839844"
+         id="use468" />
+      <use
+         xlink:href="#glyph0-23"
+         x="456"
+         y="393.839844"
+         id="use470" />
+      <use
+         xlink:href="#glyph0-10"
+         x="470"
+         y="393.839844"
+         id="use472" />
+      <use
+         xlink:href="#glyph0-16"
+         x="479"
+         y="393.839844"
+         id="use474" />
+      <use
+         xlink:href="#glyph0-8"
+         x="485"
+         y="393.839844"
+         id="use476" />
+      <use
+         xlink:href="#glyph0-19"
+         x="489"
+         y="393.839844"
+         id="use478" />
+      <use
+         xlink:href="#glyph0-20"
+         x="498"
+         y="393.839844"
+         id="use480" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47.843137%,21.176471%,69.411765%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 334.433406 906.716003 C 437.433406 906.716003 437.433406 906.716003 540.433406 906.716003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path484" />
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47.843137%,21.176471%,69.411765%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 746.433406 906.716003 C 806.433406 906.716003 806.433406 842.216003 866.433406 842.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path486" />
+    <path
+       style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47.843137%,21.176471%,69.411765%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 866.433406 818.216003 L 1107.433406 818.216003 L 1107.433406 866.216003 L 866.433406 866.216003 Z M 866.433406 818.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path488" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g546">
+      <use
+         xlink:href="#glyph0-24"
+         x="644"
+         y="443.839844"
+         id="use490" />
+      <use
+         xlink:href="#glyph0-24"
+         x="651"
+         y="443.839844"
+         id="use492" />
+      <use
+         xlink:href="#glyph0-11"
+         x="658"
+         y="443.839844"
+         id="use494" />
+      <use
+         xlink:href="#glyph0-19"
+         x="666"
+         y="443.839844"
+         id="use496" />
+      <use
+         xlink:href="#glyph0-23"
+         x="675"
+         y="443.839844"
+         id="use498" />
+      <use
+         xlink:href="#glyph0-23"
+         x="689"
+         y="443.839844"
+         id="use500" />
+      <use
+         xlink:href="#glyph0-19"
+         x="703"
+         y="443.839844"
+         id="use502" />
+      <use
+         xlink:href="#glyph0-20"
+         x="712"
+         y="443.839844"
+         id="use504" />
+      <use
+         xlink:href="#glyph0-24"
+         x="721"
+         y="443.839844"
+         id="use506" />
+      <use
+         xlink:href="#glyph0-25"
+         x="728"
+         y="443.839844"
+         id="use508" />
+      <use
+         xlink:href="#glyph0-16"
+         x="737"
+         y="443.839844"
+         id="use510" />
+      <use
+         xlink:href="#glyph0-3"
+         x="743"
+         y="443.839844"
+         id="use512" />
+      <use
+         xlink:href="#glyph0-4"
+         x="752"
+         y="443.839844"
+         id="use514" />
+      <use
+         xlink:href="#glyph0-5"
+         x="761"
+         y="443.839844"
+         id="use516" />
+      <use
+         xlink:href="#glyph0-24"
+         x="770"
+         y="443.839844"
+         id="use518" />
+      <use
+         xlink:href="#glyph0-24"
+         x="777"
+         y="443.839844"
+         id="use520" />
+      <use
+         xlink:href="#glyph0-13"
+         x="784"
+         y="443.839844"
+         id="use522" />
+      <use
+         xlink:href="#glyph0-11"
+         x="790"
+         y="443.839844"
+         id="use524" />
+      <use
+         xlink:href="#glyph0-26"
+         x="798"
+         y="443.839844"
+         id="use526" />
+      <use
+         xlink:href="#glyph0-15"
+         x="802"
+         y="443.839844"
+         id="use528" />
+      <use
+         xlink:href="#glyph0-27"
+         x="810"
+         y="443.839844"
+         id="use530" />
+      <use
+         xlink:href="#glyph0-6"
+         x="815"
+         y="443.839844"
+         id="use532" />
+      <use
+         xlink:href="#glyph0-19"
+         x="820"
+         y="443.839844"
+         id="use534" />
+      <use
+         xlink:href="#glyph0-16"
+         x="829"
+         y="443.839844"
+         id="use536" />
+      <use
+         xlink:href="#glyph0-12"
+         x="835"
+         y="443.839844"
+         id="use538" />
+      <use
+         xlink:href="#glyph0-5"
+         x="844"
+         y="443.839844"
+         id="use540" />
+      <use
+         xlink:href="#glyph0-9"
+         x="853"
+         y="443.839844"
+         id="use542" />
+      <use
+         xlink:href="#glyph0-17"
+         x="859"
+         y="443.839844"
+         id="use544" />
+    </g>
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g606">
+      <use
+         xlink:href="#glyph0-13"
+         x="644"
+         y="461.839844"
+         id="use548" />
+      <use
+         xlink:href="#glyph0-5"
+         x="650"
+         y="461.839844"
+         id="use550" />
+      <use
+         xlink:href="#glyph0-28"
+         x="659"
+         y="461.839844"
+         id="use552" />
+      <use
+         xlink:href="#glyph0-21"
+         x="664"
+         y="461.839844"
+         id="use554" />
+      <use
+         xlink:href="#glyph0-28"
+         x="673"
+         y="461.839844"
+         id="use556" />
+      <use
+         xlink:href="#glyph0-6"
+         x="678"
+         y="461.839844"
+         id="use558" />
+      <use
+         xlink:href="#glyph0-29"
+         x="683"
+         y="461.839844"
+         id="use560" />
+      <use
+         xlink:href="#glyph0-15"
+         x="692"
+         y="461.839844"
+         id="use562" />
+      <use
+         xlink:href="#glyph0-5"
+         x="700"
+         y="461.839844"
+         id="use564" />
+      <use
+         xlink:href="#glyph0-25"
+         x="709"
+         y="461.839844"
+         id="use566" />
+      <use
+         xlink:href="#glyph0-6"
+         x="718"
+         y="461.839844"
+         id="use568" />
+      <use
+         xlink:href="#glyph0-8"
+         x="723"
+         y="461.839844"
+         id="use570" />
+      <use
+         xlink:href="#glyph0-20"
+         x="727"
+         y="461.839844"
+         id="use572" />
+      <use
+         xlink:href="#glyph0-6"
+         x="736"
+         y="461.839844"
+         id="use574" />
+      <use
+         xlink:href="#glyph0-20"
+         x="741"
+         y="461.839844"
+         id="use576" />
+      <use
+         xlink:href="#glyph0-4"
+         x="750"
+         y="461.839844"
+         id="use578" />
+      <use
+         xlink:href="#glyph0-28"
+         x="759"
+         y="461.839844"
+         id="use580" />
+      <use
+         xlink:href="#glyph0-11"
+         x="764"
+         y="461.839844"
+         id="use582" />
+      <use
+         xlink:href="#glyph0-19"
+         x="772"
+         y="461.839844"
+         id="use584" />
+      <use
+         xlink:href="#glyph0-23"
+         x="781"
+         y="461.839844"
+         id="use586" />
+      <use
+         xlink:href="#glyph0-23"
+         x="795"
+         y="461.839844"
+         id="use588" />
+      <use
+         xlink:href="#glyph0-19"
+         x="809"
+         y="461.839844"
+         id="use590" />
+      <use
+         xlink:href="#glyph0-20"
+         x="818"
+         y="461.839844"
+         id="use592" />
+      <use
+         xlink:href="#glyph0-24"
+         x="827"
+         y="461.839844"
+         id="use594" />
+      <use
+         xlink:href="#glyph0-16"
+         x="834"
+         y="461.839844"
+         id="use596" />
+      <use
+         xlink:href="#glyph0-3"
+         x="840"
+         y="461.839844"
+         id="use598" />
+      <use
+         xlink:href="#glyph0-4"
+         x="849"
+         y="461.839844"
+         id="use600" />
+      <use
+         xlink:href="#glyph0-5"
+         x="858"
+         y="461.839844"
+         id="use602" />
+      <use
+         xlink:href="#glyph0-17"
+         x="867"
+         y="461.839844"
+         id="use604" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47.843137%,21.176471%,69.411765%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 746.433406 906.716003 C 806.433406 906.716003 806.433406 910.216003 866.433406 910.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path608" />
+    <path
+       style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47.843137%,21.176471%,69.411765%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 866.433406 886.216003 L 1015.433406 886.216003 L 1015.433406 934.216003 L 866.433406 934.216003 Z M 866.433406 886.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path610" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g650">
+      <use
+         xlink:href="#glyph0-30"
+         x="644"
+         y="511.839844"
+         id="use612" />
+      <use
+         xlink:href="#glyph0-5"
+         x="657"
+         y="511.839844"
+         id="use614" />
+      <use
+         xlink:href="#glyph0-16"
+         x="666"
+         y="511.839844"
+         id="use616" />
+      <use
+         xlink:href="#glyph0-12"
+         x="672"
+         y="511.839844"
+         id="use618" />
+      <use
+         xlink:href="#glyph0-19"
+         x="681"
+         y="511.839844"
+         id="use620" />
+      <use
+         xlink:href="#glyph0-25"
+         x="690"
+         y="511.839844"
+         id="use622" />
+      <use
+         xlink:href="#glyph0-15"
+         x="699"
+         y="511.839844"
+         id="use624" />
+      <use
+         xlink:href="#glyph0-6"
+         x="707"
+         y="511.839844"
+         id="use626" />
+      <use
+         xlink:href="#glyph0-22"
+         x="712"
+         y="511.839844"
+         id="use628" />
+      <use
+         xlink:href="#glyph0-19"
+         x="717"
+         y="511.839844"
+         id="use630" />
+      <use
+         xlink:href="#glyph0-9"
+         x="726"
+         y="511.839844"
+         id="use632" />
+      <use
+         xlink:href="#glyph0-6"
+         x="732"
+         y="511.839844"
+         id="use634" />
+      <use
+         xlink:href="#glyph0-29"
+         x="737"
+         y="511.839844"
+         id="use636" />
+      <use
+         xlink:href="#glyph0-15"
+         x="746"
+         y="511.839844"
+         id="use638" />
+      <use
+         xlink:href="#glyph0-5"
+         x="754"
+         y="511.839844"
+         id="use640" />
+      <use
+         xlink:href="#glyph0-6"
+         x="763"
+         y="511.839844"
+         id="use642" />
+      <use
+         xlink:href="#glyph0-8"
+         x="768"
+         y="511.839844"
+         id="use644" />
+      <use
+         xlink:href="#glyph0-20"
+         x="772"
+         y="511.839844"
+         id="use646" />
+      <use
+         xlink:href="#glyph0-6"
+         x="781"
+         y="511.839844"
+         id="use648" />
+    </g>
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g678">
+      <use
+         xlink:href="#glyph0-20"
+         x="644"
+         y="529.839844"
+         id="use652" />
+      <use
+         xlink:href="#glyph0-4"
+         x="653"
+         y="529.839844"
+         id="use654" />
+      <use
+         xlink:href="#glyph0-28"
+         x="662"
+         y="529.839844"
+         id="use656" />
+      <use
+         xlink:href="#glyph0-10"
+         x="667"
+         y="529.839844"
+         id="use658" />
+      <use
+         xlink:href="#glyph0-9"
+         x="676"
+         y="529.839844"
+         id="use660" />
+      <use
+         xlink:href="#glyph0-9"
+         x="682"
+         y="529.839844"
+         id="use662" />
+      <use
+         xlink:href="#glyph0-10"
+         x="688"
+         y="529.839844"
+         id="use664" />
+      <use
+         xlink:href="#glyph0-3"
+         x="697"
+         y="529.839844"
+         id="use666" />
+      <use
+         xlink:href="#glyph0-13"
+         x="706"
+         y="529.839844"
+         id="use668" />
+      <use
+         xlink:href="#glyph0-28"
+         x="712"
+         y="529.839844"
+         id="use670" />
+      <use
+         xlink:href="#glyph0-28"
+         x="717"
+         y="529.839844"
+         id="use672" />
+      <use
+         xlink:href="#glyph0-28"
+         x="722"
+         y="529.839844"
+         id="use674" />
+      <use
+         xlink:href="#glyph0-17"
+         x="727"
+         y="529.839844"
+         id="use676" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47.843137%,21.176471%,69.411765%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 746.433406 906.716003 C 806.433406 906.716003 806.433406 974.716003 866.433406 974.716003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path680" />
+    <path
+       style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47.843137%,21.176471%,69.411765%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 866.433406 954.216003 L 902.433406 954.216003 L 902.433406 995.216003 L 866.433406 995.216003 Z M 866.433406 954.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path682" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g690">
+      <use
+         xlink:href="#glyph1-1"
+         x="644"
+         y="588.839844"
+         id="use684" />
+      <use
+         xlink:href="#glyph1-1"
+         x="652"
+         y="588.839844"
+         id="use686" />
+      <use
+         xlink:href="#glyph1-1"
+         x="660"
+         y="588.839844"
+         id="use688" />
+    </g>
+    <path
+       style="fill-rule:nonzero;fill:none;fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47%, 21%, 69%);stroke-opacity:1;stroke-miterlimit:10"
+       d="M 545.433406 891.716003 L 741.433406 891.716003 C 741.433406 891.716003 751.433406 906.716003 741.433406 921.716003 L 545.433406 921.716003 C 545.433406 921.716003 535.433406 906.716003 545.433406 891.716003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path692" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g742">
+      <use
+         xlink:href="#glyph0-31"
+         x="318"
+         y="517.339844"
+         id="use694" />
+      <use
+         xlink:href="#glyph0-19"
+         x="326"
+         y="517.339844"
+         id="use696" />
+      <use
+         xlink:href="#glyph0-21"
+         x="335"
+         y="517.339844"
+         id="use698" />
+      <use
+         xlink:href="#glyph0-8"
+         x="344"
+         y="517.339844"
+         id="use700" />
+      <use
+         xlink:href="#glyph0-11"
+         x="348"
+         y="517.339844"
+         id="use702" />
+      <use
+         xlink:href="#glyph0-6"
+         x="356"
+         y="517.339844"
+         id="use704" />
+      <use
+         xlink:href="#glyph0-25"
+         x="361"
+         y="517.339844"
+         id="use706" />
+      <use
+         xlink:href="#glyph0-5"
+         x="370"
+         y="517.339844"
+         id="use708" />
+      <use
+         xlink:href="#glyph0-32"
+         x="379"
+         y="517.339844"
+         id="use710" />
+      <use
+         xlink:href="#glyph0-20"
+         x="388"
+         y="517.339844"
+         id="use712" />
+      <use
+         xlink:href="#glyph0-5"
+         x="397"
+         y="517.339844"
+         id="use714" />
+      <use
+         xlink:href="#glyph0-25"
+         x="406"
+         y="517.339844"
+         id="use716" />
+      <use
+         xlink:href="#glyph0-6"
+         x="415"
+         y="517.339844"
+         id="use718" />
+      <use
+         xlink:href="#glyph0-14"
+         x="420"
+         y="517.339844"
+         id="use720" />
+      <use
+         xlink:href="#glyph0-3"
+         x="429"
+         y="517.339844"
+         id="use722" />
+      <use
+         xlink:href="#glyph0-6"
+         x="438"
+         y="517.339844"
+         id="use724" />
+      <use
+         xlink:href="#glyph0-23"
+         x="443"
+         y="517.339844"
+         id="use726" />
+      <use
+         xlink:href="#glyph0-5"
+         x="457"
+         y="517.339844"
+         id="use728" />
+      <use
+         xlink:href="#glyph0-16"
+         x="466"
+         y="517.339844"
+         id="use730" />
+      <use
+         xlink:href="#glyph0-12"
+         x="472"
+         y="517.339844"
+         id="use732" />
+      <use
+         xlink:href="#glyph0-19"
+         x="481"
+         y="517.339844"
+         id="use734" />
+      <use
+         xlink:href="#glyph0-25"
+         x="490"
+         y="517.339844"
+         id="use736" />
+      <use
+         xlink:href="#glyph0-15"
+         x="499"
+         y="517.339844"
+         id="use738" />
+      <use
+         xlink:href="#glyph0-33"
+         x="507"
+         y="517.339844"
+         id="use740" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47.843137%,21.176471%,69.411765%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 334.433406 906.716003 C 437.433406 906.716003 437.433406 1030.216003 540.433406 1030.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path744" />
+    <path
+       style="fill-rule:nonzero;fill:none;fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(47%, 21%, 69%);stroke-opacity:1;stroke-miterlimit:10"
+       d="M 545.433406 1015.216003 L 693.433406 1015.216003 C 693.433406 1015.216003 703.433406 1030.216003 693.433406 1045.216003 L 545.433406 1045.216003 C 545.433406 1045.216003 535.433406 1030.216003 545.433406 1015.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path746" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g786">
+      <use
+         xlink:href="#glyph0-34"
+         x="318"
+         y="640.839844"
+         id="use748" />
+      <use
+         xlink:href="#glyph0-20"
+         x="322"
+         y="640.839844"
+         id="use750" />
+      <use
+         xlink:href="#glyph0-15"
+         x="331"
+         y="640.839844"
+         id="use752" />
+      <use
+         xlink:href="#glyph0-16"
+         x="339"
+         y="640.839844"
+         id="use754" />
+      <use
+         xlink:href="#glyph0-10"
+         x="345"
+         y="640.839844"
+         id="use756" />
+      <use
+         xlink:href="#glyph0-20"
+         x="354"
+         y="640.839844"
+         id="use758" />
+      <use
+         xlink:href="#glyph0-11"
+         x="363"
+         y="640.839844"
+         id="use760" />
+      <use
+         xlink:href="#glyph0-5"
+         x="371"
+         y="640.839844"
+         id="use762" />
+      <use
+         xlink:href="#glyph0-15"
+         x="380"
+         y="640.839844"
+         id="use764" />
+      <use
+         xlink:href="#glyph0-6"
+         x="388"
+         y="640.839844"
+         id="use766" />
+      <use
+         xlink:href="#glyph0-10"
+         x="393"
+         y="640.839844"
+         id="use768" />
+      <use
+         xlink:href="#glyph0-9"
+         x="402"
+         y="640.839844"
+         id="use770" />
+      <use
+         xlink:href="#glyph0-5"
+         x="408"
+         y="640.839844"
+         id="use772" />
+      <use
+         xlink:href="#glyph0-6"
+         x="417"
+         y="640.839844"
+         id="use774" />
+      <use
+         xlink:href="#glyph0-25"
+         x="422"
+         y="640.839844"
+         id="use776" />
+      <use
+         xlink:href="#glyph0-16"
+         x="431"
+         y="640.839844"
+         id="use778" />
+      <use
+         xlink:href="#glyph0-3"
+         x="437"
+         y="640.839844"
+         id="use780" />
+      <use
+         xlink:href="#glyph0-4"
+         x="446"
+         y="640.839844"
+         id="use782" />
+      <use
+         xlink:href="#glyph0-5"
+         x="455"
+         y="640.839844"
+         id="use784" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(20%,20%,20%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 334.433406 906.716003 C 437.433406 906.716003 437.433406 1080.216003 540.433406 1080.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path788" />
+    <path
+       style="stroke:none;fill-rule:nonzero;fill:none;fill-opacity:1"
+       d="M 312 670.839844 L 491 670.839844 L 491 700.839844 L 312 700.839844 Z M 312 670.839844 "
+       id="path790" />
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(20%,20%,20%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 550.433406 1065.216003 L 540.433406 1065.216003 L 540.433406 1095.216003 L 550.433406 1095.216003 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path792" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g836">
+      <use
+         xlink:href="#glyph0-35"
+         x="318"
+         y="690.839844"
+         id="use794" />
+      <use
+         xlink:href="#glyph0-29"
+         x="328"
+         y="690.839844"
+         id="use796" />
+      <use
+         xlink:href="#glyph0-9"
+         x="337"
+         y="690.839844"
+         id="use798" />
+      <use
+         xlink:href="#glyph0-9"
+         x="343"
+         y="690.839844"
+         id="use800" />
+      <use
+         xlink:href="#glyph0-5"
+         x="349"
+         y="690.839844"
+         id="use802" />
+      <use
+         xlink:href="#glyph0-20"
+         x="358"
+         y="690.839844"
+         id="use804" />
+      <use
+         xlink:href="#glyph0-16"
+         x="367"
+         y="690.839844"
+         id="use806" />
+      <use
+         xlink:href="#glyph0-26"
+         x="373"
+         y="690.839844"
+         id="use808" />
+      <use
+         xlink:href="#glyph0-3"
+         x="377"
+         y="690.839844"
+         id="use810" />
+      <use
+         xlink:href="#glyph0-6"
+         x="386"
+         y="690.839844"
+         id="use812" />
+      <use
+         xlink:href="#glyph0-16"
+         x="391"
+         y="690.839844"
+         id="use814" />
+      <use
+         xlink:href="#glyph0-3"
+         x="397"
+         y="690.839844"
+         id="use816" />
+      <use
+         xlink:href="#glyph0-4"
+         x="406"
+         y="690.839844"
+         id="use818" />
+      <use
+         xlink:href="#glyph0-5"
+         x="415"
+         y="690.839844"
+         id="use820" />
+      <use
+         xlink:href="#glyph0-6"
+         x="424"
+         y="690.839844"
+         id="use822" />
+      <use
+         xlink:href="#glyph0-20"
+         x="429"
+         y="690.839844"
+         id="use824" />
+      <use
+         xlink:href="#glyph0-29"
+         x="438"
+         y="690.839844"
+         id="use826" />
+      <use
+         xlink:href="#glyph0-23"
+         x="447"
+         y="690.839844"
+         id="use828" />
+      <use
+         xlink:href="#glyph0-14"
+         x="461"
+         y="690.839844"
+         id="use830" />
+      <use
+         xlink:href="#glyph0-5"
+         x="470"
+         y="690.839844"
+         id="use832" />
+      <use
+         xlink:href="#glyph0-9"
+         x="479"
+         y="690.839844"
+         id="use834" />
+    </g>
+    <path
+       style="stroke:none;fill-rule:nonzero;fill:#6a3eaa;fill-opacity:1;opacity:1"
+       d="M 20 490.339844 L 192 490.339844 L 192 534.339844 L 20 534.339844 Z M 20 490.339844 "
+       id="path838" />
+    <g
+       style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none"
+       id="g862">
+      <use
+         xlink:href="#glyph2-1"
+         x="26"
+         y="521.339844"
+         id="use840"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-2"
+         x="47"
+         y="521.339844"
+         id="use842"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-3"
+         x="59"
+         y="521.339844"
+         id="use844"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-4"
+         x="75"
+         y="521.339844"
+         id="use846"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-5"
+         x="92"
+         y="521.339844"
+         id="use848"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-6"
+         x="108"
+         y="521.339844"
+         id="use850"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-7"
+         x="116"
+         y="521.339844"
+         id="use852"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-8"
+         x="135"
+         y="521.339844"
+         id="use854"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-9"
+         x="142"
+         y="521.339844"
+         id="use856"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-10"
+         x="158"
+         y="521.339844"
+         id="use858"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+      <use
+         xlink:href="#glyph2-10"
+         x="172"
+         y="521.339844"
+         id="use860"
+         style="fill:#000000;fill-opacity:1;stroke:none;stroke-opacity:1;stroke-width:13.82475;stroke-miterlimit:4;stroke-dasharray:none" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(97.647059%,76.862745%,25.098039%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 389.839656 436.376159 C 477.589656 436.376159 477.589656 431.876159 565.339656 431.876159 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path864" />
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(97.647059%,76.862745%,25.098039%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 726.339656 431.876159 L 846.339656 431.876159 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path866" />
+    <path
+       style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(97.647059%,76.862745%,25.098039%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 851.339656 416.876159 L 1087.339656 416.876159 C 1087.339656 416.876159 1097.339656 431.876159 1087.339656 446.876159 L 851.339656 446.876159 C 851.339656 446.876159 841.339656 431.876159 851.339656 416.876159 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path868" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g922">
+      <use
+         xlink:href="#glyph3-1"
+         x="623.90625"
+         y="42.5"
+         id="use870" />
+      <use
+         xlink:href="#glyph3-2"
+         x="632.90625"
+         y="42.5"
+         id="use872" />
+      <use
+         xlink:href="#glyph3-3"
+         x="641.90625"
+         y="42.5"
+         id="use874" />
+      <use
+         xlink:href="#glyph3-4"
+         x="650.90625"
+         y="42.5"
+         id="use876" />
+      <use
+         xlink:href="#glyph3-5"
+         x="659.90625"
+         y="42.5"
+         id="use878" />
+      <use
+         xlink:href="#glyph3-6"
+         x="668.90625"
+         y="42.5"
+         id="use880" />
+      <use
+         xlink:href="#glyph3-7"
+         x="677.90625"
+         y="42.5"
+         id="use882" />
+      <use
+         xlink:href="#glyph3-8"
+         x="686.90625"
+         y="42.5"
+         id="use884" />
+      <use
+         xlink:href="#glyph3-9"
+         x="695.90625"
+         y="42.5"
+         id="use886" />
+      <use
+         xlink:href="#glyph3-10"
+         x="704.90625"
+         y="42.5"
+         id="use888" />
+      <use
+         xlink:href="#glyph3-11"
+         x="713.90625"
+         y="42.5"
+         id="use890" />
+      <use
+         xlink:href="#glyph3-12"
+         x="722.90625"
+         y="42.5"
+         id="use892" />
+      <use
+         xlink:href="#glyph3-13"
+         x="731.90625"
+         y="42.5"
+         id="use894" />
+      <use
+         xlink:href="#glyph3-8"
+         x="740.90625"
+         y="42.5"
+         id="use896" />
+      <use
+         xlink:href="#glyph3-14"
+         x="749.90625"
+         y="42.5"
+         id="use898" />
+      <use
+         xlink:href="#glyph3-15"
+         x="758.90625"
+         y="42.5"
+         id="use900" />
+      <use
+         xlink:href="#glyph3-11"
+         x="767.90625"
+         y="42.5"
+         id="use902" />
+      <use
+         xlink:href="#glyph3-12"
+         x="776.90625"
+         y="42.5"
+         id="use904" />
+      <use
+         xlink:href="#glyph3-13"
+         x="785.90625"
+         y="42.5"
+         id="use906" />
+      <use
+         xlink:href="#glyph3-8"
+         x="794.90625"
+         y="42.5"
+         id="use908" />
+      <use
+         xlink:href="#glyph3-14"
+         x="803.90625"
+         y="42.5"
+         id="use910" />
+      <use
+         xlink:href="#glyph3-15"
+         x="812.90625"
+         y="42.5"
+         id="use912" />
+      <use
+         xlink:href="#glyph3-16"
+         x="821.90625"
+         y="42.5"
+         id="use914" />
+      <use
+         xlink:href="#glyph3-16"
+         x="830.90625"
+         y="42.5"
+         id="use916" />
+      <use
+         xlink:href="#glyph3-16"
+         x="839.90625"
+         y="42.5"
+         id="use918" />
+      <use
+         xlink:href="#glyph3-17"
+         x="848.90625"
+         y="42.5"
+         id="use920" />
+    </g>
+    <path
+       style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(97.647059%,76.862745%,25.098039%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 570.339656 416.876159 L 721.339656 416.876159 C 721.339656 416.876159 731.339656 431.876159 721.339656 446.876159 L 570.339656 446.876159 C 570.339656 446.876159 560.339656 431.876159 570.339656 416.876159 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path924" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g966">
+      <use
+         xlink:href="#glyph0-30"
+         x="342.90625"
+         y="42.5"
+         id="use926" />
+      <use
+         xlink:href="#glyph0-29"
+         x="355.90625"
+         y="42.5"
+         id="use928" />
+      <use
+         xlink:href="#glyph0-26"
+         x="364.90625"
+         y="42.5"
+         id="use930" />
+      <use
+         xlink:href="#glyph0-16"
+         x="368.90625"
+         y="42.5"
+         id="use932" />
+      <use
+         xlink:href="#glyph0-8"
+         x="374.90625"
+         y="42.5"
+         id="use934" />
+      <use
+         xlink:href="#glyph0-4"
+         x="378.90625"
+         y="42.5"
+         id="use936" />
+      <use
+         xlink:href="#glyph0-26"
+         x="387.90625"
+         y="42.5"
+         id="use938" />
+      <use
+         xlink:href="#glyph0-5"
+         x="391.90625"
+         y="42.5"
+         id="use940" />
+      <use
+         xlink:href="#glyph0-6"
+         x="400.90625"
+         y="42.5"
+         id="use942" />
+      <use
+         xlink:href="#glyph0-1"
+         x="405.90625"
+         y="42.5"
+         id="use944" />
+      <use
+         xlink:href="#glyph0-8"
+         x="416.90625"
+         y="42.5"
+         id="use946" />
+      <use
+         xlink:href="#glyph0-15"
+         x="420.90625"
+         y="42.5"
+         id="use948" />
+      <use
+         xlink:href="#glyph0-4"
+         x="428.90625"
+         y="42.5"
+         id="use950" />
+      <use
+         xlink:href="#glyph0-10"
+         x="437.90625"
+         y="42.5"
+         id="use952" />
+      <use
+         xlink:href="#glyph0-16"
+         x="446.90625"
+         y="42.5"
+         id="use954" />
+      <use
+         xlink:href="#glyph0-11"
+         x="452.90625"
+         y="42.5"
+         id="use956" />
+      <use
+         xlink:href="#glyph0-12"
+         x="460.90625"
+         y="42.5"
+         id="use958" />
+      <use
+         xlink:href="#glyph0-8"
+         x="469.90625"
+         y="42.5"
+         id="use960" />
+      <use
+         xlink:href="#glyph0-20"
+         x="473.90625"
+         y="42.5"
+         id="use962" />
+      <use
+         xlink:href="#glyph0-21"
+         x="482.90625"
+         y="42.5"
+         id="use964" />
+    </g>
+    <path
+       style="stroke:none;fill-rule:nonzero;fill:#f8c23f;fill-opacity:1"
+       d="M 30.90625 20 L 291.90625 20 L 291.90625 64 L 30.90625 64 Z M 30.90625 20 "
+       id="path968" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g1004">
+      <use
+         xlink:href="#glyph2-11"
+         x="36.90625"
+         y="51"
+         id="use970" />
+      <use
+         xlink:href="#glyph2-12"
+         x="56.90625"
+         y="51"
+         id="use972" />
+      <use
+         xlink:href="#glyph2-13"
+         x="70.90625"
+         y="51"
+         id="use974" />
+      <use
+         xlink:href="#glyph2-14"
+         x="87.90625"
+         y="51"
+         id="use976" />
+      <use
+         xlink:href="#glyph2-15"
+         x="104.90625"
+         y="51"
+         id="use978" />
+      <use
+         xlink:href="#glyph2-6"
+         x="119.90625"
+         y="51"
+         id="use980" />
+      <use
+         xlink:href="#glyph2-1"
+         x="127.90625"
+         y="51"
+         id="use982" />
+      <use
+         xlink:href="#glyph2-16"
+         x="148.90625"
+         y="51"
+         id="use984" />
+      <use
+         xlink:href="#glyph2-10"
+         x="155.90625"
+         y="51"
+         id="use986" />
+      <use
+         xlink:href="#glyph2-4"
+         x="169.90625"
+         y="51"
+         id="use988" />
+      <use
+         xlink:href="#glyph2-9"
+         x="186.90625"
+         y="51"
+         id="use990" />
+      <use
+         xlink:href="#glyph2-17"
+         x="202.90625"
+         y="51"
+         id="use992" />
+      <use
+         xlink:href="#glyph2-15"
+         x="212.90625"
+         y="51"
+         id="use994" />
+      <use
+         xlink:href="#glyph2-18"
+         x="227.90625"
+         y="51"
+         id="use996" />
+      <use
+         xlink:href="#glyph2-16"
+         x="244.90625"
+         y="51"
+         id="use998" />
+      <use
+         xlink:href="#glyph2-14"
+         x="251.90625"
+         y="51"
+         id="use1000" />
+      <use
+         xlink:href="#glyph2-19"
+         x="268.90625"
+         y="51"
+         id="use1002" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(40.784314%,71.764706%,13.72549%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 769.534969 625.923034 L 945.534969 621.423034 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1006" />
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(40.784314%,71.764706%,13.72549%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 1150.534969 621.423034 C 1210.534969 621.423034 1210.534969 562.423034 1270.534969 562.423034 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1008" />
+    <path
+       style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(40.784314%,71.764706%,13.72549%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 1270.534969 538.423034 L 1507.534969 538.423034 L 1507.534969 586.423034 L 1270.534969 586.423034 Z M 1270.534969 538.423034 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1010" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g1062">
+      <use
+         xlink:href="#glyph3-18"
+         x="1048.101562"
+         y="164.046875"
+         id="use1012" />
+      <use
+         xlink:href="#glyph3-19"
+         x="1057.101562"
+         y="164.046875"
+         id="use1014" />
+      <use
+         xlink:href="#glyph3-20"
+         x="1066.101562"
+         y="164.046875"
+         id="use1016" />
+      <use
+         xlink:href="#glyph3-3"
+         x="1075.101562"
+         y="164.046875"
+         id="use1018" />
+      <use
+         xlink:href="#glyph3-21"
+         x="1084.101562"
+         y="164.046875"
+         id="use1020" />
+      <use
+         xlink:href="#glyph3-22"
+         x="1093.101562"
+         y="164.046875"
+         id="use1022" />
+      <use
+         xlink:href="#glyph3-21"
+         x="1102.101562"
+         y="164.046875"
+         id="use1024" />
+      <use
+         xlink:href="#glyph3-23"
+         x="1111.101562"
+         y="164.046875"
+         id="use1026" />
+      <use
+         xlink:href="#glyph3-8"
+         x="1120.101562"
+         y="164.046875"
+         id="use1028" />
+      <use
+         xlink:href="#glyph3-24"
+         x="1129.101562"
+         y="164.046875"
+         id="use1030" />
+      <use
+         xlink:href="#glyph3-25"
+         x="1138.101562"
+         y="164.046875"
+         id="use1032" />
+      <use
+         xlink:href="#glyph3-24"
+         x="1147.101562"
+         y="164.046875"
+         id="use1034" />
+      <use
+         xlink:href="#glyph3-7"
+         x="1156.101562"
+         y="164.046875"
+         id="use1036" />
+      <use
+         xlink:href="#glyph3-14"
+         x="1165.101562"
+         y="164.046875"
+         id="use1038" />
+      <use
+         xlink:href="#glyph3-22"
+         x="1174.101562"
+         y="164.046875"
+         id="use1040" />
+      <use
+         xlink:href="#glyph3-25"
+         x="1183.101562"
+         y="164.046875"
+         id="use1042" />
+      <use
+         xlink:href="#glyph3-26"
+         x="1192.101562"
+         y="164.046875"
+         id="use1044" />
+      <use
+         xlink:href="#glyph3-5"
+         x="1201.101562"
+         y="164.046875"
+         id="use1046" />
+      <use
+         xlink:href="#glyph3-23"
+         x="1210.101562"
+         y="164.046875"
+         id="use1048" />
+      <use
+         xlink:href="#glyph3-19"
+         x="1219.101562"
+         y="164.046875"
+         id="use1050" />
+      <use
+         xlink:href="#glyph3-22"
+         x="1228.101562"
+         y="164.046875"
+         id="use1052" />
+      <use
+         xlink:href="#glyph3-13"
+         x="1237.101562"
+         y="164.046875"
+         id="use1054" />
+      <use
+         xlink:href="#glyph3-8"
+         x="1246.101562"
+         y="164.046875"
+         id="use1056" />
+      <use
+         xlink:href="#glyph3-14"
+         x="1255.101562"
+         y="164.046875"
+         id="use1058" />
+      <use
+         xlink:href="#glyph3-21"
+         x="1264.101562"
+         y="164.046875"
+         id="use1060" />
+    </g>
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g1104">
+      <use
+         xlink:href="#glyph3-27"
+         x="1048.101562"
+         y="182.046875"
+         id="use1064" />
+      <use
+         xlink:href="#glyph3-14"
+         x="1057.101562"
+         y="182.046875"
+         id="use1066" />
+      <use
+         xlink:href="#glyph3-16"
+         x="1066.101562"
+         y="182.046875"
+         id="use1068" />
+      <use
+         xlink:href="#glyph3-28"
+         x="1075.101562"
+         y="182.046875"
+         id="use1070" />
+      <use
+         xlink:href="#glyph3-16"
+         x="1084.101562"
+         y="182.046875"
+         id="use1072" />
+      <use
+         xlink:href="#glyph3-23"
+         x="1093.101562"
+         y="182.046875"
+         id="use1074" />
+      <use
+         xlink:href="#glyph3-21"
+         x="1102.101562"
+         y="182.046875"
+         id="use1076" />
+      <use
+         xlink:href="#glyph3-22"
+         x="1111.101562"
+         y="182.046875"
+         id="use1078" />
+      <use
+         xlink:href="#glyph3-25"
+         x="1120.101562"
+         y="182.046875"
+         id="use1080" />
+      <use
+         xlink:href="#glyph3-26"
+         x="1129.101562"
+         y="182.046875"
+         id="use1082" />
+      <use
+         xlink:href="#glyph3-4"
+         x="1138.101562"
+         y="182.046875"
+         id="use1084" />
+      <use
+         xlink:href="#glyph3-28"
+         x="1147.101562"
+         y="182.046875"
+         id="use1086" />
+      <use
+         xlink:href="#glyph3-23"
+         x="1156.101562"
+         y="182.046875"
+         id="use1088" />
+      <use
+         xlink:href="#glyph3-9"
+         x="1165.101562"
+         y="182.046875"
+         id="use1090" />
+      <use
+         xlink:href="#glyph3-14"
+         x="1174.101562"
+         y="182.046875"
+         id="use1092" />
+      <use
+         xlink:href="#glyph3-4"
+         x="1183.101562"
+         y="182.046875"
+         id="use1094" />
+      <use
+         xlink:href="#glyph3-28"
+         x="1192.101562"
+         y="182.046875"
+         id="use1096" />
+      <use
+         xlink:href="#glyph3-22"
+         x="1201.101562"
+         y="182.046875"
+         id="use1098" />
+      <use
+         xlink:href="#glyph3-29"
+         x="1210.101562"
+         y="182.046875"
+         id="use1100" />
+      <use
+         xlink:href="#glyph3-30"
+         x="1219.101562"
+         y="182.046875"
+         id="use1102" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(40.784314%,71.764706%,13.72549%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 1150.534969 621.423034 C 1210.534969 621.423034 1210.534969 630.423034 1270.534969 630.423034 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1106" />
+    <path
+       style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(40.784314%,71.764706%,13.72549%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 1270.534969 606.423034 L 1451.534969 606.423034 L 1451.534969 654.423034 L 1270.534969 654.423034 Z M 1270.534969 606.423034 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1108" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g1158">
+      <use
+         xlink:href="#glyph0-36"
+         x="1048.101562"
+         y="232.046875"
+         id="use1110" />
+      <use
+         xlink:href="#glyph0-9"
+         x="1057.101562"
+         y="232.046875"
+         id="use1112" />
+      <use
+         xlink:href="#glyph0-19"
+         x="1063.101562"
+         y="232.046875"
+         id="use1114" />
+      <use
+         xlink:href="#glyph0-37"
+         x="1072.101562"
+         y="232.046875"
+         id="use1116" />
+      <use
+         xlink:href="#glyph0-8"
+         x="1081.101562"
+         y="232.046875"
+         id="use1118" />
+      <use
+         xlink:href="#glyph0-25"
+         x="1085.101562"
+         y="232.046875"
+         id="use1120" />
+      <use
+         xlink:href="#glyph0-5"
+         x="1094.101562"
+         y="232.046875"
+         id="use1122" />
+      <use
+         xlink:href="#glyph0-15"
+         x="1103.101562"
+         y="232.046875"
+         id="use1124" />
+      <use
+         xlink:href="#glyph0-6"
+         x="1111.101562"
+         y="232.046875"
+         id="use1126" />
+      <use
+         xlink:href="#glyph0-26"
+         x="1116.101562"
+         y="232.046875"
+         id="use1128" />
+      <use
+         xlink:href="#glyph0-19"
+         x="1120.101562"
+         y="232.046875"
+         id="use1130" />
+      <use
+         xlink:href="#glyph0-38"
+         x="1129.101562"
+         y="232.046875"
+         id="use1132" />
+      <use
+         xlink:href="#glyph0-6"
+         x="1141.101562"
+         y="232.046875"
+         id="use1134" />
+      <use
+         xlink:href="#glyph0-26"
+         x="1146.101562"
+         y="232.046875"
+         id="use1136" />
+      <use
+         xlink:href="#glyph0-5"
+         x="1150.101562"
+         y="232.046875"
+         id="use1138" />
+      <use
+         xlink:href="#glyph0-37"
+         x="1159.101562"
+         y="232.046875"
+         id="use1140" />
+      <use
+         xlink:href="#glyph0-5"
+         x="1168.101562"
+         y="232.046875"
+         id="use1142" />
+      <use
+         xlink:href="#glyph0-26"
+         x="1177.101562"
+         y="232.046875"
+         id="use1144" />
+      <use
+         xlink:href="#glyph0-6"
+         x="1181.101562"
+         y="232.046875"
+         id="use1146" />
+      <use
+         xlink:href="#glyph0-11"
+         x="1186.101562"
+         y="232.046875"
+         id="use1148" />
+      <use
+         xlink:href="#glyph0-10"
+         x="1194.101562"
+         y="232.046875"
+         id="use1150" />
+      <use
+         xlink:href="#glyph0-15"
+         x="1203.101562"
+         y="232.046875"
+         id="use1152" />
+      <use
+         xlink:href="#glyph0-16"
+         x="1211.101562"
+         y="232.046875"
+         id="use1154" />
+      <use
+         xlink:href="#glyph0-6"
+         x="1217.101562"
+         y="232.046875"
+         id="use1156" />
+    </g>
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g1176">
+      <use
+         xlink:href="#glyph0-22"
+         x="1048.101562"
+         y="250.046875"
+         id="use1160" />
+      <use
+         xlink:href="#glyph0-29"
+         x="1053.101562"
+         y="250.046875"
+         id="use1162" />
+      <use
+         xlink:href="#glyph0-20"
+         x="1062.101562"
+         y="250.046875"
+         id="use1164" />
+      <use
+         xlink:href="#glyph0-11"
+         x="1071.101562"
+         y="250.046875"
+         id="use1166" />
+      <use
+         xlink:href="#glyph0-16"
+         x="1079.101562"
+         y="250.046875"
+         id="use1168" />
+      <use
+         xlink:href="#glyph0-8"
+         x="1085.101562"
+         y="250.046875"
+         id="use1170" />
+      <use
+         xlink:href="#glyph0-19"
+         x="1089.101562"
+         y="250.046875"
+         id="use1172" />
+      <use
+         xlink:href="#glyph0-20"
+         x="1098.101562"
+         y="250.046875"
+         id="use1174" />
+    </g>
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(40.784314%,71.764706%,13.72549%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 1150.534969 621.423034 C 1210.534969 621.423034 1210.534969 689.423034 1270.534969 689.423034 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1178" />
+    <path
+       style=" stroke:none;fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;"
+       d="M 1042.101562 280.046875 L 1160.101562 280.046875 L 1160.101562 310.046875 L 1042.101562 310.046875 Z M 1042.101562 280.046875 "
+       id="path1180" />
+    <path
+       style="fill:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(40.784314%,71.764706%,13.72549%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 1280.534969 674.423034 L 1270.534969 674.423034 L 1270.534969 704.423034 L 1280.534969 704.423034 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1182" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g1212">
+      <use
+         xlink:href="#glyph0-35"
+         x="1048.101562"
+         y="300.046875"
+         id="use1184" />
+      <use
+         xlink:href="#glyph0-10"
+         x="1058.101562"
+         y="300.046875"
+         id="use1186" />
+      <use
+         xlink:href="#glyph0-15"
+         x="1067.101562"
+         y="300.046875"
+         id="use1188" />
+      <use
+         xlink:href="#glyph0-16"
+         x="1075.101562"
+         y="300.046875"
+         id="use1190" />
+      <use
+         xlink:href="#glyph0-8"
+         x="1081.101562"
+         y="300.046875"
+         id="use1192" />
+      <use
+         xlink:href="#glyph0-20"
+         x="1085.101562"
+         y="300.046875"
+         id="use1194" />
+      <use
+         xlink:href="#glyph0-21"
+         x="1094.101562"
+         y="300.046875"
+         id="use1196" />
+      <use
+         xlink:href="#glyph0-6"
+         x="1103.101562"
+         y="300.046875"
+         id="use1198" />
+      <use
+         xlink:href="#glyph0-15"
+         x="1108.101562"
+         y="300.046875"
+         id="use1200" />
+      <use
+         xlink:href="#glyph0-10"
+         x="1116.101562"
+         y="300.046875"
+         id="use1202" />
+      <use
+         xlink:href="#glyph0-22"
+         x="1125.101562"
+         y="300.046875"
+         id="use1204" />
+      <use
+         xlink:href="#glyph0-5"
+         x="1130.101562"
+         y="300.046875"
+         id="use1206" />
+      <use
+         xlink:href="#glyph0-16"
+         x="1139.101562"
+         y="300.046875"
+         id="use1208" />
+      <use
+         xlink:href="#glyph0-3"
+         x="1145.101562"
+         y="300.046875"
+         id="use1210" />
+    </g>
+    <path
+       style="fill-rule:nonzero;fill:rgb(100%,100%,100%);fill-opacity:1;stroke-width:4;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(40.784314%,71.764706%,13.72549%);stroke-opacity:1;stroke-miterlimit:10;"
+       d="M 950.534969 606.423034 L 1145.534969 606.423034 C 1145.534969 606.423034 1155.534969 621.423034 1145.534969 636.423034 L 950.534969 636.423034 C 950.534969 636.423034 940.534969 621.423034 950.534969 606.423034 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1214" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g1264">
+      <use
+         xlink:href="#glyph0-35"
+         x="723.101562"
+         y="232.046875"
+         id="use1216" />
+      <use
+         xlink:href="#glyph0-10"
+         x="733.101562"
+         y="232.046875"
+         id="use1218" />
+      <use
+         xlink:href="#glyph0-15"
+         x="742.101562"
+         y="232.046875"
+         id="use1220" />
+      <use
+         xlink:href="#glyph0-16"
+         x="750.101562"
+         y="232.046875"
+         id="use1222" />
+      <use
+         xlink:href="#glyph0-8"
+         x="756.101562"
+         y="232.046875"
+         id="use1224" />
+      <use
+         xlink:href="#glyph0-20"
+         x="760.101562"
+         y="232.046875"
+         id="use1226" />
+      <use
+         xlink:href="#glyph0-21"
+         x="769.101562"
+         y="232.046875"
+         id="use1228" />
+      <use
+         xlink:href="#glyph0-34"
+         x="778.101562"
+         y="232.046875"
+         id="use1230" />
+      <use
+         xlink:href="#glyph0-23"
+         x="782.101562"
+         y="232.046875"
+         id="use1232" />
+      <use
+         xlink:href="#glyph0-4"
+         x="796.101562"
+         y="232.046875"
+         id="use1234" />
+      <use
+         xlink:href="#glyph0-26"
+         x="805.101562"
+         y="232.046875"
+         id="use1236" />
+      <use
+         xlink:href="#glyph0-39"
+         x="809.101562"
+         y="232.046875"
+         id="use1238" />
+      <use
+         xlink:href="#glyph0-1"
+         x="815.101562"
+         y="232.046875"
+         id="use1240" />
+      <use
+         xlink:href="#glyph0-2"
+         x="826.101562"
+         y="232.046875"
+         id="use1242" />
+      <use
+         xlink:href="#glyph0-3"
+         x="833.101562"
+         y="232.046875"
+         id="use1244" />
+      <use
+         xlink:href="#glyph0-4"
+         x="842.101562"
+         y="232.046875"
+         id="use1246" />
+      <use
+         xlink:href="#glyph0-5"
+         x="851.101562"
+         y="232.046875"
+         id="use1248" />
+      <use
+         xlink:href="#glyph0-27"
+         x="860.101562"
+         y="232.046875"
+         id="use1250" />
+      <use
+         xlink:href="#glyph0-1"
+         x="865.101562"
+         y="232.046875"
+         id="use1252" />
+      <use
+         xlink:href="#glyph0-2"
+         x="876.101562"
+         y="232.046875"
+         id="use1254" />
+      <use
+         xlink:href="#glyph0-3"
+         x="883.101562"
+         y="232.046875"
+         id="use1256" />
+      <use
+         xlink:href="#glyph0-4"
+         x="892.101562"
+         y="232.046875"
+         id="use1258" />
+      <use
+         xlink:href="#glyph0-5"
+         x="901.101562"
+         y="232.046875"
+         id="use1260" />
+      <use
+         xlink:href="#glyph0-40"
+         x="910.101562"
+         y="232.046875"
+         id="use1262" />
+    </g>
+    <path
+       style="stroke:none;fill-rule:nonzero;fill:#66b521;fill-opacity:1"
+       d="M 485.101562 209.546875 L 597.101562 209.546875 L 597.101562 253.546875 L 485.101562 253.546875 Z M 485.101562 209.546875 "
+       id="path1266" />
+    <g
+       style="fill:rgb(0%,0%,0%);fill-opacity:1;"
+       id="g1282">
+      <use
+         xlink:href="#glyph2-7"
+         x="491.101562"
+         y="240.546875"
+         id="use1268" />
+      <use
+         xlink:href="#glyph2-9"
+         x="510.101562"
+         y="240.546875"
+         id="use1270" />
+      <use
+         xlink:href="#glyph2-10"
+         x="526.101562"
+         y="240.546875"
+         id="use1272" />
+      <use
+         xlink:href="#glyph2-17"
+         x="540.101562"
+         y="240.546875"
+         id="use1274" />
+      <use
+         xlink:href="#glyph2-16"
+         x="550.101562"
+         y="240.546875"
+         id="use1276" />
+      <use
+         xlink:href="#glyph2-14"
+         x="557.101562"
+         y="240.546875"
+         id="use1278" />
+      <use
+         xlink:href="#glyph2-19"
+         x="574.101562"
+         y="240.546875"
+         id="use1280" />
+    </g>
+    <path
+       style="fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(80%,0%,0%);stroke-opacity:1;stroke-dasharray:2,8;stroke-miterlimit:10;"
+       d="M 620.488094 695.216003 C 642.406063 620.102721 651.351375 538.98944 647.331844 451.876159 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1284" />
+    <path
+       style=" stroke:none;fill-rule:nonzero;fill:rgb(80%,0%,0%);fill-opacity:1;"
+       d="M 392.054688 300.839844 L 402.195312 292.707031 L 387.878906 288.527344 Z M 392.054688 300.839844 "
+       id="path1286" />
+    <path
+       style="fill:#cc0000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.12582338"
+       d="m 385.36881,167.34353 h 59.66863 c 3.72929,0 6.75494,3.02565 6.75494,6.75494 v 19.139 c 0,3.73368 -3.02565,6.75494 -6.75494,6.75494 h -59.66863 c -3.72929,0 -6.75494,-3.02126 -6.75494,-6.75494 v -19.139 c 0,-3.72929 3.02565,-6.75494 6.75494,-6.75494 z m 0,0"
+       id="path1288"
+       inkscape:connector-curvature="0" />
+    <g
+       style="fill:#ffffff;fill-opacity:1"
+       id="g1306"
+       transform="matrix(1.1258233,0,0,1.1258233,-52.242237,-23.109714)">
+      <use
+         xlink:href="#glyph4-1"
+         x="388.70312"
+         y="188.16797"
+         id="use1290"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-2"
+         x="393.70312"
+         y="188.16797"
+         id="use1292"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-3"
+         x="401.70312"
+         y="188.16797"
+         id="use1294"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-4"
+         x="409.70312"
+         y="188.16797"
+         id="use1296"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-5"
+         x="417.70312"
+         y="188.16797"
+         id="use1298"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-1"
+         x="421.70312"
+         y="188.16797"
+         id="use1300"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-2"
+         x="426.70312"
+         y="188.16797"
+         id="use1302"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-6"
+         x="434.70312"
+         y="188.16797"
+         id="use1304"
+         width="100%"
+         height="100%" />
+    </g>
+    <path
+       style="fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(46.666667%,46.666667%,46.666667%);stroke-opacity:1;stroke-dasharray:20,8;stroke-miterlimit:10;"
+       d="M 1030.890438 601.423034 C 986.933406 546.33319 965.824031 496.485534 967.566219 451.876159 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1308" />
+    <path
+       style=" stroke:none;fill-rule:nonzero;fill:rgb(46.666667%,46.666667%,46.666667%);fill-opacity:1;"
+       d="M 739.132812 57.5 L 731.265625 67.851562 L 746.167969 68.433594 Z M 739.132812 57.5 "
+       id="path1310" />
+    <path
+       style=" stroke:none;fill-rule:nonzero;fill:rgb(46.666667%,46.666667%,46.666667%);fill-opacity:1;"
+       d="M 802.457031 207.046875 L 801.644531 194.074219 L 789.984375 203.375 Z M 802.457031 207.046875 "
+       id="path1312" />
+    <path
+       style="fill:#757575;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.1717118"
+       d="m 710.88877,101.39438 h 85.53496 c 3.8813,0 7.03027,3.1444 7.03027,7.03027 v 39.8382 c 0,3.8813 -3.14897,7.03027 -7.03027,7.03027 h -85.53496 c -3.8813,0 -7.03027,-3.14897 -7.03027,-7.03027 v -39.8382 c 0,-3.88587 3.14897,-7.03027 7.03027,-7.03027 z m 0,0"
+       id="path1314"
+       inkscape:connector-curvature="0" />
+    <g
+       style="fill:#ffffff;fill-opacity:1"
+       id="g1338"
+       transform="matrix(1.1717118,0,0,1.1717118,-129.41169,-22.03814)">
+      <use
+         xlink:href="#glyph4-7"
+         x="717.15625"
+         y="124.34375"
+         id="use1316"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-8"
+         x="725.15625"
+         y="124.34375"
+         id="use1318"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-9"
+         x="733.15625"
+         y="124.34375"
+         id="use1320"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-1"
+         x="741.15625"
+         y="124.34375"
+         id="use1322"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-2"
+         x="746.15625"
+         y="124.34375"
+         id="use1324"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-6"
+         x="754.15625"
+         y="124.34375"
+         id="use1326"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-10"
+         x="761.15625"
+         y="124.34375"
+         id="use1328"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-11"
+         x="765.15625"
+         y="124.34375"
+         id="use1330"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-12"
+         x="774.15625"
+         y="124.34375"
+         id="use1332"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-13"
+         x="782.15625"
+         y="124.34375"
+         id="use1334"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-14"
+         x="786.15625"
+         y="124.34375"
+         id="use1336"
+         width="100%"
+         height="100%" />
+    </g>
+    <g
+       style="fill:#ffffff;fill-opacity:1"
+       id="g1354"
+       transform="matrix(1.1717118,0,0,1.1717118,-129.41169,-22.03814)">
+      <use
+         xlink:href="#glyph4-15"
+         x="717.15625"
+         y="141.34375"
+         id="use1340"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-2"
+         x="730.15625"
+         y="141.34375"
+         id="use1342"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-16"
+         x="738.15625"
+         y="141.34375"
+         id="use1344"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-8"
+         x="743.15625"
+         y="141.34375"
+         id="use1346"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-17"
+         x="751.15625"
+         y="141.34375"
+         id="use1348"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-18"
+         x="759.15625"
+         y="141.34375"
+         id="use1350"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-6"
+         x="767.15625"
+         y="141.34375"
+         id="use1352"
+         width="100%"
+         height="100%" />
+    </g>
+    <path
+       style="fill:none;stroke-width:2;stroke-linecap:round;stroke-linejoin:miter;stroke:rgb(46.666667%,46.666667%,46.666667%);stroke-opacity:1;stroke-dasharray:2,8;stroke-miterlimit:10;"
+       d="M 1040.890438 641.423034 C 984.038875 728.954284 887.581844 780.516784 751.519344 796.102721 "
+       transform="matrix(1,0,0,1,-228.433406,-394.376159)"
+       id="path1356" />
+    <path
+       style=" stroke:none;fill-rule:nonzero;fill:rgb(46.666667%,46.666667%,46.666667%);fill-opacity:1;"
+       d="M 523.085938 401.726562 L 534.515625 407.921875 L 532.816406 393.105469 Z M 523.085938 401.726562 "
+       id="path1358" />
+    <path
+       style="fill:#757575;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1.16217232"
+       d="m 652.15184,334.51569 h 90.64944 c 3.8497,0 6.97303,3.1188 6.97303,6.97303 v 19.75693 c 0,3.8497 -3.12333,6.97304 -6.97303,6.97304 h -90.64944 c -3.85423,0 -6.97303,-3.12334 -6.97303,-6.97304 v -19.75693 c 0,-3.85423 3.1188,-6.97303 6.97303,-6.97303 z m 0,0"
+       id="path1360"
+       inkscape:connector-curvature="0" />
+    <g
+       style="fill:#ffffff;fill-opacity:1"
+       id="g1384"
+       transform="matrix(1.1621723,0,0,1.1621723,-113.11137,-56.98202)">
+      <use
+         xlink:href="#glyph4-12"
+         x="658.47656"
+         y="355.86719"
+         id="use1362"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-1"
+         x="666.47656"
+         y="355.86719"
+         id="use1364"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-17"
+         x="671.47656"
+         y="355.86719"
+         id="use1366"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-19"
+         x="679.47656"
+         y="355.86719"
+         id="use1368"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-5"
+         x="687.47656"
+         y="355.86719"
+         id="use1370"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-18"
+         x="691.47656"
+         y="355.86719"
+         id="use1372"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-2"
+         x="699.47656"
+         y="355.86719"
+         id="use1374"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-18"
+         x="707.47656"
+         y="355.86719"
+         id="use1376"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-10"
+         x="715.47656"
+         y="355.86719"
+         id="use1378"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-20"
+         x="719.47656"
+         y="355.86719"
+         id="use1380"
+         width="100%"
+         height="100%" />
+      <use
+         xlink:href="#glyph4-21"
+         x="728.47656"
+         y="355.86719"
+         id="use1382"
+         width="100%"
+         height="100%" />
+    </g>
+    <text
+       xml:space="preserve"
+       style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:12.51816273px;line-height:1.25;font-family:flux;-inkscape-font-specification:flux;letter-spacing:0px;word-spacing:0px;fill:#004141;fill-opacity:1;stroke:none;stroke-width:0.9388622"
+       x="9.0130692"
+       y="702.06409"
+       id="text2202"><tspan
+         sodipodi:role="line"
+         id="tspan2200"
+         x="9.0130692"
+         y="702.06409"
+         style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:50.07265091px;line-height:1.25;font-family:serif;-inkscape-font-specification:serif;fill:#004141;fill-opacity:1;stroke-width:0.9388622">Phase I</tspan></text>
+  </g>
+</svg>
index 6eed7d0c96cec3a845d23497a5ef45a9b760e753..6837b12bddc3661d3db877a417478d6e3b0ac89c 100644 (file)
@@ -30,7 +30,10 @@ import os
 # Add any Sphinx extension module names here, as strings. They can be
 # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
 # ones.
-extensions = ['sphinx.ext.imgmath',]
+extensions = [
+    'sphinx.ext.imgmath',
+    'sphinx.ext.intersphinx',
+]
 
 # Add any paths that contain templates here, relative to this directory.
 templates_path = ['../source/_templates/']
@@ -218,3 +221,14 @@ texinfo_documents = [
      author, 'NumPyEnhancementProposals', 'One line description of project.',
      'Miscellaneous'),
 ]
+
+# -----------------------------------------------------------------------------
+# Intersphinx configuration
+# -----------------------------------------------------------------------------
+intersphinx_mapping = {
+    'python': ('https://docs.python.org/dev', None),
+    'numpy': ('https://numpy.org/devdocs', None),
+    'scipy': ('https://docs.scipy.org/doc/scipy/reference', None),
+    'matplotlib': ('https://matplotlib.org', None)
+}
+
index 0a2dbdefbb761964f19fdb85b12cd90a2b559804..56a332626ae52b85d0988867cb37be22675c8a84 100644 (file)
@@ -76,7 +76,7 @@ where ``<n>`` is an appropriately assigned four-digit number (e.g.,
 ``nep-0000.rst``). The draft must use the :doc:`nep-template` file.
 
 Once the PR for the NEP is in place, a post should be made to the
-mailing list containing the sections upto "Backward compatibility",
+mailing list containing the sections up to "Backward compatibility",
 with the purpose of limiting discussion there to usage and impact.
 Discussion on the pull request will have a broader scope, also including
 details of implementation.
index fd7b3e52c44a48dec6bd04ca00d5be87f505c9b7..7a2a272f41d76f50f4c1ac140ab7fe1b038ad0c9 100644 (file)
@@ -1291,7 +1291,7 @@ Construction and Destruction
 
     Returns ``NPY_SUCCEED`` or ``NPY_FAIL``.
 
-``int NpyIter_HasInnerLoop(NpyIter *iter``
+``int NpyIter_HasInnerLoop(NpyIter *iter)``
 
     Returns 1 if the iterator handles the inner loop,
     or 0 if the caller needs to handle it.  This is controlled
index dbcf1b579d6294c66aaa2186917a7b71b282e85d..f7026b4beaaa89ace06060c3bed0c41f7768dacd 100644 (file)
@@ -313,7 +313,7 @@ The following works in the current draft implementation::
 For floating point numbers, Inf and NaN are separate concepts from
 missing values. If a division by zero occurs in an array with default
 missing value support, an unmasked Inf or NaN will be produced. To
-mask those values, a further 'a[np.logical_not(a.isfinite(a)] = np.NA'
+mask those values, a further 'a[np.logical_not(a.isfinite(a))] = np.NA'
 can achieve that. For the bitpattern approach, the parameterized
 dtype('NA[f8,InfNan]') described in a later section can be used to get
 these semantics without the extra manipulation.
@@ -926,7 +926,7 @@ to access the array elements. This python indexing still goes through the
 Python API, so the NA handling and error checking in numpy still can work
 like normal and fail if the inputs have NAs which cannot fit in the output
 array. In this case it fails when trying to convert the NA into an integer
-to set in in the output.
+to set in the output.
 
 The next version of the code introduces more efficient indexing. This
 operates based on Python's buffer protocol. This causes Cython to call
index dab9ab022d2a539566244a990c604ccda36f1191..0d20d680ffbf30cd255665b0a9462a312b8c449a 100644 (file)
@@ -48,7 +48,7 @@ NumPy arrays currently support a flexible range of indexing operations:
 
 For clarity, we will refer to these existing rules as "legacy indexing".
 This is only a high-level summary; for more details, see NumPy's documentation
-and and `Examples` below.
+and `Examples` below.
 
 Outer indexing
 ~~~~~~~~~~~~~~
@@ -108,7 +108,7 @@ array ``arr`` with shape ``(X, Y, Z)``:
 3. ``arr[0, :, [0, 1]]`` has shape ``(2, Y)``, not ``(Y, 2)``!
 
 These first two cases are intuitive and consistent with outer indexing, but
-this last case is quite surprising, even to many higly experienced NumPy users.
+this last case is quite surprising, even to many highly experienced NumPy users.
 
 Mixed cases involving multiple array indices are also surprising, and only
 less problematic because the current behavior is so useless that it is rarely
@@ -240,7 +240,7 @@ be deduced:
 7. To ensure that existing subclasses of `ndarray` that override indexing
    do not inadvertently revert to default behavior for indexing attributes,
    these attribute should have explicit checks that disable them if
-   ``__getitem__`` or ``__setitem__`` has been overriden.
+   ``__getitem__`` or ``__setitem__`` has been overridden.
 
 Unlike plain indexing, the new indexing attributes are explicitly aimed
 at higher dimensional indexing, several additional changes should be implemented:
@@ -319,7 +319,7 @@ of ``__getitem__`` on these attributes should test
 subclass has special handling for indexing and ``NotImplementedError``
 should be raised, requiring that the indexing attributes is also explicitly
 overwritten. Likewise, implementations of ``__setitem__`` should check to see
-if ``__setitem__`` is overriden.
+if ``__setitem__`` is overridden.
 
 A further question is how to facilitate implementing the special attributes.
 Also there is the weird functionality where ``__setitem__`` calls
index 158b08f1f18d2b95651a70227cd0c43e8ae66d0d..92974ad6ea2be8e7c0ba7a2710ec518934660751 100644 (file)
@@ -198,7 +198,7 @@ Policy
    can be made, *provided the benefit is worth the cost* and suitable deprecation
    warnings have been raised first.
 3. Deprecation warnings are in all cases warnings that functionality will be removed.
-   If there is no intent to remove functionlity, then deprecation in documentation
+   If there is no intent to remove functionality, then deprecation in documentation
    only or other types of warnings shall be used.
 4. Deprecations for stylistic reasons (e.g. consistency between functions) are
    strongly discouraged.
index b418ca831b324bf39d264171dc270c3fd3e566e7..68f25ad4d491034c91ff55d87301819d42bd18cb 100644 (file)
@@ -131,7 +131,7 @@ Possible options for static site generators
    Unlike the previous options, Docusaurus doesn't come with themes, and thus we
    would not want to use this for our landing page. This is an excellent docs
    option written in React. Docusaurus natively has support for i18n (via
-   Crowdin_, document versioning, and document search.
+   Crowdin_), document versioning, and document search.
 
 Both Jekyll and Hugo are excellent options that should be supported into the
 future and are good choices for NumPy. Docusaurus has several bonus features
@@ -153,7 +153,7 @@ significant drain on the time of maintainers.
 2. *Github Pages.* Github Pages also has a 100GB bandwidth limit, and is unclear if
    additional bandwidth can be purchased. It is also unclear where sites are deployed,
    and should be assumed sites aren't deployed globally. Github Pages has an easy to
-   use CI & DNS, similar to to Netlify. HTTPS is supported.
+   use CI & DNS, similar to Netlify. HTTPS is supported.
 3. *Cloudflare.* An excellent option, additional CI is likely needed for the same
    ease of deployment.
 
@@ -166,7 +166,7 @@ have a similar deployment to GitHub Pages or Netlify.
 Analytics
 ~~~~~~~~~
 
-It's benefical to maintainers to know how many visitors are coming to
+It's beneficial to maintainers to know how many visitors are coming to
 numpy.org. Google Analytics offers visitor counts and locations. This will
 help to support and deploy more strategically, and help maintainers
 understand where traffic is coming from.
index f98449ed6d3a6ae46e7f3f74950e6ddfff1d9ab9..6b636f9b068103edbb6c67af7f750d8bf648295b 100644 (file)
@@ -24,7 +24,7 @@ Detailed description
 NumPy's API, including array definitions, is implemented and mimicked in
 countless other projects. By definition, many of those arrays are fairly
 similar in how they operate to the NumPy standard. The introduction of
-``__array_function__`` allowed dispathing of functions implemented by several
+``__array_function__`` allowed dispatching of functions implemented by several
 of these projects directly via NumPy's API. This introduces a new requirement,
 returning the NumPy-like array itself, rather than forcing a coercion into a
 pure NumPy array.
@@ -33,30 +33,32 @@ For the purpose above, NEP 22 introduced the concept of duck typing to NumPy
 arrays. The suggested solution described in the NEP allows libraries to avoid
 coercion of a NumPy-like array to a pure NumPy array where necessary, while
 still allowing that NumPy-like array libraries that do not wish to implement
-the protocol to coerce arrays to a pure Numpy array via ``np.asarray``.
+the protocol to coerce arrays to a pure NumPy array via ``np.asarray``.
 
 Usage Guidance
 ~~~~~~~~~~~~~~
 
-Code that uses np.duckarray is meant for supporting other ndarray-like objects
+Code that uses ``np.duckarray`` is meant for supporting other ndarray-like objects
 that "follow the NumPy API". That is an ill-defined concept at the moment --
 every known library implements the NumPy API only partly, and many deviate
 intentionally in at least some minor ways. This cannot be easily remedied, so
-for users of ``__duckarray__`` we recommend the following strategy: check if the
-NumPy functionality used by the code that follows your use of ``__duckarray__``
+for users of ``np.duckarray`` we recommend the following strategy: check if the
+NumPy functionality used by the code that follows your use of ``np.duckarray``
 is present in Dask, CuPy and Sparse. If so, it's reasonable to expect any duck
 array to work here. If not, we suggest you indicate in your docstring what kinds
 of duck arrays are accepted, or what properties they need to have.
 
 To exemplify the usage of duck arrays, suppose one wants to take the ``mean()``
 of an array-like object ``arr``. Using NumPy to achieve that, one could write
-``np.asarray(arr).mean()`` to achieve the intended result. However, libraries
-may expect ``arr`` to be a NumPy-like array, and at the same time, the array may
-or may not be an object compliant to the NumPy API (either in full or partially)
-such as a CuPy, Sparse or a Dask array. In the case where ``arr`` is already an
-object compliant to the NumPy API, we would simply return it (and prevent it
-from being coerced into a pure NumPy array), otherwise, it would then be coerced
-into a NumPy array.
+``np.asarray(arr).mean()`` to achieve the intended result. If ``arr`` is not
+a NumPy array, this would create an actual NumPy array in order to call
+``.mean()``. However, if the array is an object that is compliant with the NumPy
+API (either in full or partially) such as a CuPy, Sparse or a Dask array, then
+that copy would have been unnecessary. On the other hand, if one were to use the new
+``__duckarray__`` protocol: ``np.duckarray(arr).mean()``, and ``arr`` is an object
+compliant with the NumPy API, it would simply be returned rather than coerced
+into a pure NumPy array, avoiding unnecessary copies and potential loss of
+performance.
 
 Implementation
 --------------
@@ -64,9 +66,9 @@ Implementation
 The implementation idea is fairly straightforward, requiring a new function
 ``duckarray`` to be introduced in NumPy, and a new method ``__duckarray__`` in
 NumPy-like array classes. The new ``__duckarray__`` method shall return the
-downstream array-like object itself, such as the ``self`` object. If appropriate,
-an ``__array__`` method may be implemented that returns a NumPy array or possibly
-raise a ``TypeError`` with a helpful message.
+downstream array-like object itself, such as the ``self`` object, while the
+``__array__`` method raises ``TypeError``.  Alternatively, the ``__array__``
+method could create an actual NumPy array and return that.
 
 The new NumPy ``duckarray`` function can be implemented as follows:
 
@@ -91,8 +93,8 @@ a complete implementation would look like the following:
             return self
 
         def __array__(self):
-            return TypeError("NumPyLikeArray can not be converted to a numpy array. "
-                             "You may want to use np.duckarray.")
+            raise TypeError("NumPyLikeArray can not be converted to a NumPy "
+                             "array. You may want to use np.duckarray() instead.")
 
 The implementation above exemplifies the simplest case, but the overall idea
 is that libraries will implement a ``__duckarray__`` method that returns the
@@ -114,7 +116,7 @@ An example of how the ``__duckarray__`` protocol could be used to write a
 seen below. The example here was chosen not only to demonstrate the usage of
 the ``duckarray`` function, but also to demonstrate its dependency on the NumPy
 API, demonstrated by checks on the array's ``shape`` attribute. Note that the
-example is merely a simplified version of NumPy's actually implementation of
+example is merely a simplified version of NumPy's actual implementation of
 ``stack`` working on the first axis, and it is assumed that Dask has implemented
 the ``__duckarray__`` method.
 
diff --git a/doc/neps/nep-0034-infer-dtype-is-object.rst b/doc/neps/nep-0034-infer-dtype-is-object.rst
new file mode 100644 (file)
index 0000000..2e0ae46
--- /dev/null
@@ -0,0 +1,146 @@
+===========================================================
+NEP 34 â€” Disallow inferring ``dtype=object`` from sequences
+===========================================================
+
+:Author: Matti Picus
+:Status: Accepted
+:Type: Standards Track
+:Created: 2019-10-10
+:Resolution: https://mail.python.org/pipermail/numpy-discussion/2019-October/080200.html
+
+Abstract
+--------
+
+When users create arrays with sequences-of-sequences, they sometimes err in
+matching the lengths of the nested sequences_, commonly called "ragged
+arrays".  Here we will refer to them as ragged nested sequences. Creating such
+arrays via ``np.array([<ragged_nested_sequence>])`` with no ``dtype`` keyword
+argument will today default to an ``object``-dtype array. Change the behaviour to
+raise a ``ValueError`` instead.
+
+Motivation and Scope
+--------------------
+
+Users who specify lists-of-lists when creating a `numpy.ndarray` via
+``np.array`` may mistakenly pass in lists of different lengths. Currently we
+accept this input and automatically create an array with ``dtype=object``. This
+can be confusing, since it is rarely what is desired. Changing the automatic
+dtype detection to never return ``object`` for ragged nested sequences (defined as a
+recursive sequence of sequences, where not all the sequences on the same
+level have the same length) will force users who actually wish to create
+``object`` arrays to specify that explicitly. Note that ``lists``, ``tuples``,
+and ``nd.ndarrays`` are all sequences [0]_. See for instance `issue 5303`_.
+
+Usage and Impact
+----------------
+
+After this change, array creation with ragged nested sequences must explicitly
+define a dtype:
+
+    >>> np.array([[1, 2], [1]])
+    ValueError: cannot guess the desired dtype from the input
+
+    >>> np.array([[1, 2], [1]], dtype=object)
+    # succeeds, with no change from current behaviour
+
+The deprecation will affect any call that internally calls ``np.asarray``.  For
+instance, the ``assert_equal`` family of functions calls ``np.asarray``, so
+users will have to change code like::
+
+    np.assert_equal(a, [[1, 2], 3])
+
+to::
+
+    np.assert_equal(a, np.array([[1, 2], 3], dtype=object))
+
+Detailed description
+--------------------
+
+To explicitly set the shape of the object array, since it is sometimes hard to
+determine what shape is desired, one could use:
+
+    >>> arr = np.empty(correct_shape, dtype=object)
+    >>> arr[...] = values
+
+We will also reject mixed sequences of non-sequence and sequence, for instance
+all of these will be rejected:
+
+    >>> arr = np.array([np.arange(10), [10]])
+    >>> arr = np.array([[range(3), range(3), range(3)], [range(3), 0, 0]])
+
+Related Work
+------------
+
+`PR 14341`_ tried to raise an error when ragged nested sequences were specified
+with a numeric dtype ``np.array, [[1], [2, 3]], dtype=int)`` but failed due to
+false-positives, for instance ``np.array([1, np.array([5])], dtype=int)``.
+
+.. _`PR 14341`: https://github.com/numpy/numpy/pull/14341
+
+Implementation
+--------------
+
+The code to be changed is inside ``PyArray_GetArrayParamsFromObject`` and the
+internal ``discover_dimensions`` function. The first implementation in `PR
+14794`_ caused a number of downstream library failures and was reverted before
+the release of 1.18. Subsequently downstream libraries fixed the places they
+were using ragged arrays. The reimplementation became `PR 15119`_ which was
+merged for the 1.19 release.
+
+Backward compatibility
+----------------------
+
+Anyone depending on creating object arrays from ragged nested sequences will
+need to modify their code. There will be a deprecation period during which the
+current behaviour will emit a ``DeprecationWarning``. 
+
+Alternatives
+------------
+
+- We could continue with the current situation.
+
+- It was also suggested to add a kwarg ``depth`` to array creation, or perhaps
+  to add another array creation API function ``ragged_array_object``. The goal
+  was to eliminate the ambiguity in creating an object array from ``array([[1,
+  2], [1]], dtype=object)``: should the returned array have a shape of
+  ``(1,)``, or ``(2,)``? This NEP does not deal with that issue, and only
+  deprecates the use of ``array`` with no ``dtype=object`` for ragged nested
+  sequences. Users of ragged nested sequences may face another deprecation
+  cycle in the future. Rationale: we expect that there are very few users who
+  intend to use ragged arrays like that, this was never intended as a use case
+  of NumPy arrays. Users are likely better off with `another library`_ or just
+  using list of lists.
+
+- It was also suggested to deprecate all automatic creation of ``object``-dtype
+  arrays, which would require adding an explicit ``dtype=object`` for something
+  like ``np.array([Decimal(10), Decimal(10)])``. This too is out of scope for
+  the current NEP. Rationale: it's harder to asses the impact of this larger
+  change, we're not sure how many users this may impact.
+
+Discussion
+----------
+
+Comments to `issue 5303`_ indicate this is unintended behaviour as far back as
+2014. Suggestions to change it have been made in the ensuing years, but none
+have stuck. The WIP implementation in `PR 14794`_ seems to point to the
+viability of this approach.
+
+References and Footnotes
+------------------------
+
+.. _`issue 5303`: https://github.com/numpy/numpy/issues/5303
+.. _sequences: https://docs.python.org/3.7/glossary.html#term-sequence
+.. _`PR 14794`: https://github.com/numpy/numpy/pull/14794
+.. _`PR 15119`: https://github.com/numpy/numpy/pull/15119
+.. _`another library`: https://github.com/scikit-hep/awkward-array
+
+.. [0] ``np.ndarrays`` are not recursed into, rather their shape is used
+   directly. This will not emit warnings::
+
+      ragged = np.array([[1], [1, 2, 3]], dtype=object)
+      np.array([ragged, ragged]) # no dtype needed
+
+Copyright
+---------
+
+This document has been placed in the public domain.
diff --git a/doc/neps/nep-0034.rst b/doc/neps/nep-0034.rst
deleted file mode 100644 (file)
index 4863bad..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-===========================================================
-NEP 34 â€” Disallow inferring ``dtype=object`` from sequences
-===========================================================
-
-:Author: Matti Picus
-:Status: Accepted
-:Type: Standards Track
-:Created: 2019-10-10
-:Resolution: https://mail.python.org/pipermail/numpy-discussion/2019-October/080200.html
-
-Abstract
---------
-
-When users create arrays with sequences-of-sequences, they sometimes err in
-matching the lengths of the nested sequences_, commonly called "ragged
-arrays".  Here we will refer to them as ragged nested sequences. Creating such
-arrays via ``np.array([<ragged_nested_sequence>])`` with no ``dtype`` keyword
-argument will today default to an ``object``-dtype array. Change the behaviour to
-raise a ``ValueError`` instead.
-
-Motivation and Scope
---------------------
-
-Users who specify lists-of-lists when creating a `numpy.ndarray` via
-``np.array`` may mistakenly pass in lists of different lengths. Currently we
-accept this input and automatically create an array with ``dtype=object``. This
-can be confusing, since it is rarely what is desired. Changing the automatic
-dtype detection to never return ``object`` for ragged nested sequences (defined as a
-recursive sequence of sequences, where not all the sequences on the same
-level have the same length) will force users who actually wish to create
-``object`` arrays to specify that explicitly. Note that ``lists``, ``tuples``,
-and ``nd.ndarrays`` are all sequences [0]_. See for instance `issue 5303`_.
-
-Usage and Impact
-----------------
-
-After this change, array creation with ragged nested sequences must explicitly
-define a dtype:
-
-    >>> np.array([[1, 2], [1]])
-    ValueError: cannot guess the desired dtype from the input
-
-    >>> np.array([[1, 2], [1]], dtype=object)
-    # succeeds, with no change from current behaviour
-
-The deprecation will affect any call that internally calls ``np.asarray``.  For
-instance, the ``assert_equal`` family of functions calls ``np.asarray``, so
-users will have to change code like::
-
-    np.assert_equal(a, [[1, 2], 3])
-
-to::
-
-    np.assert_equal(a, np.array([[1, 2], 3], dtype=object))
-
-Detailed description
---------------------
-
-To explicitly set the shape of the object array, since it is sometimes hard to
-determine what shape is desired, one could use:
-
-    >>> arr = np.empty(correct_shape, dtype=object)
-    >>> arr[...] = values
-
-We will also reject mixed sequences of non-sequence and sequence, for instance
-all of these will be rejected:
-
-    >>> arr = np.array([np.arange(10), [10]])
-    >>> arr = np.array([[range(3), range(3), range(3)], [range(3), 0, 0]])
-
-Related Work
-------------
-
-`PR 14341`_ tried to raise an error when ragged nested sequences were specified
-with a numeric dtype ``np.array, [[1], [2, 3]], dtype=int)`` but failed due to
-false-positives, for instance ``np.array([1, np.array([5])], dtype=int)``.
-
-.. _`PR 14341`: https://github.com/numpy/numpy/pull/14341
-
-Implementation
---------------
-
-The code to be changed is inside ``PyArray_GetArrayParamsFromObject`` and the
-internal ``discover_dimentions`` function. See `PR 14794`_.
-
-Backward compatibility
-----------------------
-
-Anyone depending on creating object arrays from ragged nested sequences will
-need to modify their code. There will be a deprecation period during which the
-current behaviour will emit a ``DeprecationWarning``. 
-
-Alternatives
-------------
-
-- We could continue with the current situation.
-
-- It was also suggested to add a kwarg ``depth`` to array creation, or perhaps
-  to add another array creation API function ``ragged_array_object``. The goal
-  was to eliminate the ambiguity in creating an object array from ``array([[1,
-  2], [1]], dtype=object)``: should the returned array have a shape of
-  ``(1,)``, or ``(2,)``? This NEP does not deal with that issue, and only
-  deprecates the use of ``array`` with no ``dtype=object`` for ragged nested
-  sequences. Users of ragged nested sequences may face another deprecation
-  cycle in the future. Rationale: we expect that there are very few users who
-  intend to use ragged arrays like that, this was never intended as a use case
-  of NumPy arrays. Users are likely better off with `another library`_ or just
-  using list of lists.
-
-- It was also suggested to deprecate all automatic creation of ``object``-dtype
-  arrays, which would require adding an explicit ``dtype=object`` for something
-  like ``np.array([Decimal(10), Decimal(10)])``. This too is out of scope for
-  the current NEP. Rationale: it's harder to asses the impact of this larger
-  change, we're not sure how many users this may impact.
-
-Discussion
-----------
-
-Comments to `issue 5303`_ indicate this is unintended behaviour as far back as
-2014. Suggestions to change it have been made in the ensuing years, but none
-have stuck. The WIP implementation in `PR 14794`_ seems to point to the
-viability of this approach.
-
-References and Footnotes
-------------------------
-
-.. _`issue 5303`: https://github.com/numpy/numpy/issues/5303
-.. _sequences: https://docs.python.org/3.7/glossary.html#term-sequence
-.. _`PR 14794`: https://github.com/numpy/numpy/pull/14794
-.. _`another library`: https://github.com/scikit-hep/awkward-array
-
-.. [0] ``np.ndarrays`` are not recursed into, rather their shape is used
-   directly. This will not emit warnings::
-
-      ragged = np.array([[1], [1, 2, 3]], dtype=object)
-      np.array([ragged, ragged]) # no dtype needed
-
-Copyright
----------
-
-This document has been placed in the public domain.
diff --git a/doc/neps/nep-0035-array-creation-dispatch-with-array-function.rst b/doc/neps/nep-0035-array-creation-dispatch-with-array-function.rst
new file mode 100644 (file)
index 0000000..884dbe0
--- /dev/null
@@ -0,0 +1,186 @@
+===========================================================
+NEP 35 â€” Array Creation Dispatching With __array_function__
+===========================================================
+
+:Author: Peter Andreas Entschev <pentschev@nvidia.com>
+:Status: Draft
+:Type: Standards Track
+:Created: 2019-10-15
+:Updated: 2019-10-15
+:Resolution:
+
+Abstract
+--------
+
+We propose the introduction of a new keyword argument ``like=`` to all array
+creation functions to permit dispatching of such functions by the
+``__array_function__`` protocol, addressing one of the protocol shortcomings,
+as described by NEP-18 [1]_.
+
+Detailed description
+--------------------
+
+The introduction of the ``__array_function__`` protocol allowed downstream
+library developers to use NumPy as a dispatching API. However, the protocol
+did not -- and did not intend to -- address the creation of arrays by downstream
+libraries, preventing those libraries from using such important functionality in
+that context.
+
+Other NEPs have been written to address parts of that limitation, such as the
+introduction of the ``__duckarray__`` protocol in NEP-30 [2]_, and the
+introduction of an overriding mechanism called ``uarray`` by NEP-31 [3]_.
+
+The purpose of this NEP is to address that shortcoming in a simple and
+straighforward way: introduce a new ``like=`` keyword argument, similar to how
+the ``empty_like`` family of functions work. When array creation functions
+receive such an argument, they will trigger the ``__array_function__`` protocol,
+and call the downstream library's own array creation function implementation.
+The ``like=`` argument, as its own name suggests, shall be used solely for the
+purpose of identifying where to dispatch.  In contrast to the way
+``__array_function__`` has been used so far (the first argument identifies where
+to dispatch), and to avoid breaking NumPy's API with regards to array creation,
+the new ``like=`` keyword shall be used for the purpose of dispatching.
+
+Usage Guidance
+~~~~~~~~~~~~~~
+
+The new ``like=`` keyword is solely intended to identify the downstream library
+where to dispatch and the object is used only as reference, meaning that no
+modifications, copies or processing will be performed on that object.
+
+We expect that this functionality will be mostly useful to library developers,
+allowing them to create new arrays for internal usage based on arrays passed
+by the user, preventing unnecessary creation of NumPy arrays that will
+ultimately lead to an additional conversion into a downstream array type.
+
+Implementation
+--------------
+
+The implementation requires introducing a new ``like=`` keyword to all existing
+array creation functions of NumPy. As examples of functions that would add this
+new argument (but not limited to) we can cite those taking array-like objects
+such as ``array`` and ``asarray``, functions that create arrays based on
+numerical ranges such as ``range`` and ``linspace``, as well as the ``empty``
+family of functions, even though that may be redundant, since there exists
+already specializations for those with the naming format ``empty_like``. As of
+the writing of this NEP, a complete list of array creation functions can be
+found in [4]_.
+
+This newly proposed keyword shall be removed by the ``__array_function__``
+mechanism from the keyword dictionary before dispatching. The purpose for this
+is twofold:
+
+1. The object will have no use in the downstream library's implementation; and
+2. Simplifies adoption of array creation by those libraries already opting-in
+   to implement the ``__array_function__`` protocol, thus removing the
+   requirement to explicitly opt-in for all array creation functions.
+
+Downstream libraries thus shall _NOT_ include the ``like=`` keyword to their
+array creation APIs, which is a NumPy-exclusive keyword.
+
+Function Dispatching
+~~~~~~~~~~~~~~~~~~~~
+
+There are two different cases to dispatch: Python functions, and C functions.
+To permit ``__array_function__`` dispatching, one possible implementation is to
+decorate Python functions with ``overrides.array_function_dispatch``, but C
+functions have a different requirement, which we shall describe shortly.
+
+The example below shows a suggestion on how the ``asarray`` could be decorated
+with ``overrides.array_function_dispatch``:
+
+.. code:: python
+
+    def _asarray_decorator(a, dtype=None, order=None, like=None):
+        return (like,)
+
+    @set_module('numpy')
+    @array_function_dispatch(_asarray_decorator)
+    def asarray(a, dtype=None, order=None, like=None):
+        return array(a, dtype, copy=False, order=order)
+
+Note in the example above that the implementation remains unchanged, the only
+difference is the decoration, which uses the new ``_asarray_decorator`` function
+to instruct the ``__array_function__`` protocol to dispatch if ``like`` is not
+``None``.
+
+We will now look at a C function example, and since ``asarray`` is anyway a
+specialization of ``array``, we will use the latter as an example now. As
+``array`` is a C function, currently all NumPy does regarding its Python source
+is to import the function and adjust its ``__module__`` to ``numpy``. The
+function will now be decorated with a specialization of
+``overrides.array_function_from_dispatcher``, which shall take care of adjusting
+the module too.
+
+.. code:: python
+
+    array_function_nodocs_from_c_func_and_dispatcher = functools.partial(
+        overrides.array_function_from_dispatcher,
+        module='numpy', docs_from_dispatcher=False, verify=False)
+
+    @array_function_nodocs_from_c_func_and_dispatcher(_multiarray_umath.array)
+    def array(a, dtype=None, copy=True, order='K', subok=False, ndmin=0, like=None):
+        return (like,)
+
+There are two downsides to the implementation above for C functions:
+
+1.  It creates another Python function call; and
+2.  To follow current implementation standards, documentation should be attached
+    directly to the Python source code.
+
+Alternatively for C functions, the implementation of ``like=`` could be moved
+into the C implementation itself. This is not the primary suggestion here due
+to its inherent complexity which would be difficult too long to describe in its
+entirety here, and too tedious for the reader. However, we leave that as an
+option open for discussion.
+
+Usage
+-----
+
+The purpose of this NEP is to keep things simple. Similarly, we can exemplify
+the usage of ``like=`` in a simple way. Imagine you have an array of ones
+created by a downstream library, such as CuPy. What you need now is a new array
+that can be created using the NumPy API, but that will in fact be created by
+the downstream library, a simple way to achieve that is shown below.
+
+.. code:: python
+
+    x = cupy.ones(2)
+    np.array([1, 3, 5], like=x)     # Returns cupy.ndarray
+
+As a second example, we could also create an array of evenly spaced numbers
+using a Dask identity matrix as reference:
+
+.. code:: python
+
+    x = dask.array.eye(3)
+    np.linspace(0, 2, like=x)       # Returns dask.array
+
+
+Compatibility
+-------------
+
+This proposal does not raise any backward compatibility issues within NumPy,
+given that it only introduces a new keyword argument to existing array creation
+functions.
+
+Downstream libraries will benefit from the ``like=`` argument automatically,
+that is, without any explicit changes in their codebase. The only requirement
+is that they already implement the ``__array_function__`` protocol, as
+described by NEP-18 [2]_.
+
+References and Footnotes
+------------------------
+
+.. [1] `NEP-18 - A dispatch mechanism for NumPy's high level array functions <https://numpy.org/neps/nep-0018-array-function-protocol.html>`_.
+
+.. [2] `NEP 30 â€” Duck Typing for NumPy Arrays - Implementation <https://numpy.org/neps/nep-0030-duck-array-protocol.html>`_.
+
+.. [3] `NEP 31 â€” Context-local and global overrides of the NumPy API <https://github.com/numpy/numpy/pull/14389>`_.
+
+.. [4] `Array creation routines <https://docs.scipy.org/doc/numpy-1.17.0/reference/routines.array-creation.html>`_.
+
+Copyright
+---------
+
+This document has been placed in the public domain.
diff --git a/doc/neps/nep-0037-array-module.rst b/doc/neps/nep-0037-array-module.rst
new file mode 100644 (file)
index 0000000..d789ef0
--- /dev/null
@@ -0,0 +1,568 @@
+===================================================
+NEP 37 â€” A dispatch protocol for NumPy-like modules
+===================================================
+
+:Author: Stephan Hoyer <shoyer@google.com>
+:Author: Hameer Abbasi
+:Author: Sebastian Berg
+:Status: Draft
+:Type: Standards Track
+:Created: 2019-12-29
+
+Abstract
+--------
+
+NEP-18's ``__array_function__`` has been a mixed success. Some projects (e.g.,
+dask, CuPy, xarray, sparse, Pint, MXNet) have enthusiastically adopted it.
+Others (e.g., JAX) have been more reluctant. Here we propose a new
+protocol, ``__array_module__``, that we expect could eventually subsume most
+use-cases for ``__array_function__``. The protocol requires explicit adoption
+by both users and library authors, which ensures backwards compatibility, and
+is also significantly simpler than ``__array_function__``, both of which we
+expect will make it easier to adopt.
+
+Why ``__array_function__`` hasn't been enough
+---------------------------------------------
+
+There are two broad ways in which NEP-18 has fallen short of its goals:
+
+1. **Backwards compatibility concerns**. `__array_function__` has significant
+   implications for libraries that use it:
+
+   - `JAX <https://github.com/google/jax/issues/1565>`_ has been reluctant
+     to implement ``__array_function__`` in part because it is concerned about
+     breaking existing code: users expect NumPy functions like
+     ``np.concatenate`` to return NumPy arrays. This is a fundamental
+     limitation of the ``__array_function__`` design, which we chose to allow
+     overriding the existing ``numpy`` namespace.
+     Libraries like Dask and CuPy have looked at and accepted the backwards
+     incompatibility impact of ``__array_function__``; it would still have been
+     better for them if that impact didn't exist.
+
+     Note that projects like `PyTorch
+     <https://github.com/pytorch/pytorch/issues/22402>`_ and `scipy.sparse
+     <https://github.com/scipy/scipy/issues/10362>`_ have also not
+     adopted ``__array_function__`` yet, because they don't have a
+     NumPy-compatible API or semantics. In the case of PyTorch, that is likely
+     to be added in the future. ``scipy.sparse`` is in the same situation as
+     ``numpy.matrix``: its semantics are not compatible with ``numpy.ndarray``
+     and therefore adding ``__array_function__`` (except to return ``NotImplemented``
+     perhaps) is not a healthy idea.
+   - ``__array_function__`` currently requires an "all or nothing" approach to
+     implementing NumPy's API. There is no good pathway for **incremental
+     adoption**, which is particularly problematic for established projects
+     for which adopting ``__array_function__`` would result in breaking
+     changes.
+
+2. **Limitations on what can be overridden.** ``__array_function__`` has some
+   important gaps, most notably array creation and coercion functions:
+
+   - **Array creation** routines (e.g., ``np.arange`` and those in
+     ``np.random``) need some other mechanism for indicating what type of
+     arrays to create. `NEP 35 <https://numpy.org/neps/nep-0035-array-creation-dispatch-with-array-function.html>`_
+     proposed adding optional ``like=`` arguments to functions without
+     existing array arguments. However, we still lack any mechanism to
+     override methods on objects, such as those needed by
+     ``np.random.RandomState``.
+   - **Array conversion** can't reuse the existing coercion functions like
+     ``np.asarray``, because ``np.asarray`` sometimes means "convert to an
+     exact ``np.ndarray``" and other times means "convert to something _like_
+     a NumPy array." This led to the `NEP 30
+     <https://numpy.org/neps/nep-0030-duck-array-protocol.html>`_ proposal for
+     a separate ``np.duckarray`` function, but this still does not resolve how
+     to cast one duck array into a type matching another duck array.
+
+Other maintainability concerns that were raised include:
+
+- It is no longer possible to use **aliases to NumPy functions** within
+  modules that support overrides. For example, both CuPy and JAX set
+  ``result_type = np.result_type`` and now have to wrap use of
+  ``np.result_type`` in their own ``result_type`` function instead.
+- Implementing **fall-back mechanisms** for unimplemented NumPy functions
+  by using NumPy's implementation is hard to get right (but see the
+  `version from dask <https://github.com/dask/dask/pull/5043>`_), because
+  ``__array_function__`` does not present a consistent interface.
+  Converting all arguments of array type requires recursing into generic
+  arguments of the form ``*args, **kwargs``.
+
+``get_array_module`` and the ``__array_module__`` protocol
+----------------------------------------------------------
+
+We propose a new user-facing mechanism for dispatching to a duck-array
+implementation, ``numpy.get_array_module``. ``get_array_module`` performs the
+same type resolution as ``__array_function__`` and returns a module with an API
+promised to match the standard interface of ``numpy`` that can implement
+operations on all provided array types.
+
+The protocol itself is both simpler and more powerful than
+``__array_function__``, because it doesn't need to worry about actually
+implementing functions. We believe it resolves most of the maintainability and
+functionality limitations of ``__array_function__``.
+
+The new protocol is opt-in, explicit and with local control; see
+:ref:`appendix-design-choices` for discussion on the importance of these design
+features.
+
+The array module contract
+=========================
+
+Modules returned by ``get_array_module``/``__array_module__`` should make a
+best effort to implement NumPy's core functionality on new array types(s).
+Unimplemented functionality should simply be omitted (e.g., accessing an
+unimplemented function should raise ``AttributeError``). In the future, we
+anticipate codifying a protocol for requesting restricted subsets of ``numpy``;
+see :ref:`requesting-restricted-subsets` for more details.
+
+How to use ``get_array_module``
+===============================
+
+Code that wants to support generic duck arrays should explicitly call
+``get_array_module`` to determine an appropriate array module from which to
+call functions, rather than using the ``numpy`` namespace directly. For
+example:
+
+.. code:: python
+
+    # calls the appropriate version of np.something for x and y
+    module = np.get_array_module(x, y)
+    module.something(x, y)
+
+Both array creation and array conversion are supported, because dispatching is
+handled by ``get_array_module`` rather than via the types of function
+arguments. For example, to use random number generation functions or methods,
+we can simply pull out the appropriate submodule:
+
+.. code:: python
+
+    def duckarray_add_random(array):
+        module = np.get_array_module(array)
+        noise = module.random.randn(*array.shape)
+        return array + noise
+
+We can also write the duck-array ``stack`` function from `NEP 30
+<https://numpy.org/neps/nep-0030-duck-array-protocol.html>`_, without the need
+for a new ``np.duckarray`` function:
+
+.. code:: python
+
+    def duckarray_stack(arrays):
+        module = np.get_array_module(*arrays)
+        arrays = [module.asarray(arr) for arr in arrays]
+        shapes = {arr.shape for arr in arrays}
+        if len(shapes) != 1:
+            raise ValueError('all input arrays must have the same shape')
+        expanded_arrays = [arr[module.newaxis, ...] for arr in arrays]
+        return module.concatenate(expanded_arrays, axis=0)
+
+By default, ``get_array_module`` will return the ``numpy`` module if no
+arguments are arrays. This fall-back can be explicitly controlled by providing
+the ``module`` keyword-only argument. It is also possible to indicate that an
+exception should be raised instead of returning a default array module by
+setting ``module=None``.
+
+How to implement ``__array_module__``
+=====================================
+
+Libraries implementing a duck array type that want to support
+``get_array_module`` need to implement the corresponding protocol,
+``__array_module__``. This new protocol is based on Python's dispatch protocol
+for arithmetic, and is essentially a simpler version of ``__array_function__``.
+
+Only one argument is passed into ``__array_module__``, a Python collection of
+unique array types passed into ``get_array_module``, i.e., all arguments with
+an ``__array_module__`` attribute.
+
+The special method should either return a namespace with an API matching
+``numpy``, or ``NotImplemented``, indicating that it does not know how to
+handle the operation:
+
+.. code:: python
+
+    class MyArray:
+        def __array_module__(self, types):
+            if not all(issubclass(t, MyArray) for t in types):
+                return NotImplemented
+            return my_array_module
+
+Returning custom objects from ``__array_module__``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+``my_array_module`` will typically, but need not always, be a Python module.
+Returning a custom objects (e.g., with functions implemented via
+``__getattr__``) may be useful for some advanced use cases.
+
+For example, custom objects could allow for partial implementations of duck
+array modules that fall-back to NumPy (although this is not recommended in
+general because such fall-back behavior can be error prone):
+
+.. code:: python
+
+    class MyArray:
+        def __array_module__(self, types):
+            if all(issubclass(t, MyArray) for t in types):
+                return ArrayModule()
+            else:
+                return NotImplemented
+
+    class ArrayModule:
+        def __getattr__(self, name):
+            import base_module
+            return getattr(base_module, name, getattr(numpy, name))
+
+Subclassing from ``numpy.ndarray``
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+All of the same guidance about well-defined type casting hierarchies from
+NEP-18 still applies. ``numpy.ndarray`` itself contains a matching
+implementation of ``__array_module__``,  which is convenient for subclasses:
+
+.. code:: python
+
+    class ndarray:
+        def __array_module__(self, types):
+            if all(issubclass(t, ndarray) for t in types):
+                return numpy
+            else:
+                return NotImplemented
+
+NumPy's internal machinery
+==========================
+
+The type resolution rules of ``get_array_module`` follow the same model as
+Python and NumPy's existing dispatch protocols: subclasses are called before
+super-classes, and otherwise left to right. ``__array_module__`` is guaranteed
+to be called only  a single time on each unique type.
+
+The actual implementation of `get_array_module` will be in C, but should be
+equivalent to this Python code:
+
+.. code:: python
+
+    def get_array_module(*arrays, default=numpy):
+        implementing_arrays, types = _implementing_arrays_and_types(arrays)
+        if not implementing_arrays and default is not None:
+            return default
+        for array in implementing_arrays:
+            module = array.__array_module__(types)
+            if module is not NotImplemented:
+                return module
+        raise TypeError("no common array module found")
+
+    def _implementing_arrays_and_types(relevant_arrays):
+        types = []
+        implementing_arrays = []
+        for array in relevant_arrays:
+            t = type(array)
+            if t not in types and hasattr(t, '__array_module__'):
+                types.append(t)
+                # Subclasses before superclasses, otherwise left to right
+                index = len(implementing_arrays)
+                for i, old_array in enumerate(implementing_arrays):
+                    if issubclass(t, type(old_array)):
+                        index = i
+                        break
+                implementing_arrays.insert(index, array)
+        return implementing_arrays, types
+
+Relationship with ``__array_ufunc__`` and ``__array_function__``
+----------------------------------------------------------------
+
+These older protocols have distinct use-cases and should remain
+===============================================================
+
+``__array_module__`` is intended to resolve limitations of
+``__array_function__``, so it is natural to consider whether it could entirely
+replace ``__array_function__``. This would offer dual benefits: (1) simplifying
+the user-story about how to override NumPy and (2) removing the slowdown
+associated with checking for dispatch when calling every NumPy function.
+
+However, ``__array_module__`` and ``__array_function__`` are pretty different
+from a user perspective: it requires explicit calls to ``get_array_function``,
+rather than simply reusing original ``numpy`` functions. This is probably fine
+for *libraries* that rely on duck-arrays, but may be frustratingly verbose for
+interactive use.
+
+Some of the dispatching use-cases for ``__array_ufunc__`` are also solved by
+``__array_module__``, but not all of them. For example, it is still useful to
+be able to define non-NumPy ufuncs (e.g., from Numba or SciPy) in a generic way
+on non-NumPy arrays (e.g., with dask.array).
+
+Given their existing adoption and distinct use cases, we don't think it makes
+sense to remove or deprecate ``__array_function__`` and ``__array_ufunc__`` at
+this time.
+
+Mixin classes to implement ``__array_function__`` and ``__array_ufunc__``
+=========================================================================
+
+Despite the user-facing differences, ``__array_module__`` and a module
+implementing NumPy's API still contain sufficient functionality needed to
+implement dispatching with the existing duck array protocols.
+
+For example, the following mixin classes would provide sensible defaults for
+these special methods in terms of ``get_array_module`` and
+``__array_module__``:
+
+.. code:: python
+
+    class ArrayUfuncFromModuleMixin:
+
+        def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
+            arrays = inputs + kwargs.get('out', ())
+            try:
+                array_module = np.get_array_module(*arrays)
+            except TypeError:
+                return NotImplemented
+
+            try:
+                # Note this may have false positive matches, if ufunc.__name__
+                # matches the name of a ufunc defined by NumPy. Unfortunately
+                # there is no way to determine in which module a ufunc was
+                # defined.
+                new_ufunc = getattr(array_module, ufunc.__name__)
+            except AttributeError:
+                return NotImplemented
+
+            try:
+                callable = getattr(new_ufunc, method)
+            except AttributeError:
+                return NotImplemented
+
+            return callable(*inputs, **kwargs)
+
+    class ArrayFunctionFromModuleMixin:
+
+        def __array_function__(self, func, types, args, kwargs):
+            array_module = self.__array_module__(types)
+            if array_module is NotImplemented:
+                return NotImplemented
+
+            # Traverse submodules to find the appropriate function
+            modules = func.__module__.split('.')
+            assert modules[0] == 'numpy'
+            for submodule in modules[1:]:
+                module = getattr(module, submodule, None)
+            new_func = getattr(module, func.__name__, None)
+            if new_func is None:
+                return NotImplemented
+
+            return new_func(*args, **kwargs)
+
+To make it easier to write duck arrays, we could also add these mixin classes
+into ``numpy.lib.mixins`` (but the examples above may suffice).
+
+Alternatives considered
+-----------------------
+
+Naming
+======
+
+We like the name ``__array_module__`` because it mirrors the existing
+``__array_function__`` and ``__array_ufunc__`` protocols. Another reasonable
+choice could be ``__array_namespace__``.
+
+It is less clear what the NumPy function that calls this protocol should be
+called (``get_array_module`` in this proposal). Some possible alternatives:
+``array_module``, ``common_array_module``, ``resolve_array_module``,
+``get_namespace``, ``get_numpy``, ``get_numpylike_module``,
+``get_duck_array_module``.
+
+.. _requesting-restricted-subsets:
+
+Requesting restricted subsets of NumPy's API
+============================================
+
+Over time, NumPy has accumulated a very large API surface, with over 600
+attributes in the top level ``numpy`` module alone. It is unlikely that any
+duck array library could or would want to implement all of these functions and
+classes, because the frequently used subset of NumPy is much smaller.
+
+We think it would be useful exercise to define "minimal" subset(s) of NumPy's
+API, omitting rarely used or non-recommended functionality. For example,
+minimal NumPy might include ``stack``, but not the other stacking functions
+``column_stack``, ``dstack``, ``hstack`` and ``vstack``. This could clearly
+indicate to duck array authors and users what functionality is core and what
+functionality they can skip.
+
+Support for requesting a restricted subset of NumPy's API would be a natural
+feature to include in  ``get_array_function`` and ``__array_module__``, e.g.,
+
+.. code:: python
+
+    # array_module is only guaranteed to contain "minimal" NumPy
+    array_module = np.get_array_module(*arrays, request='minimal')
+
+To facilitate testing with NumPy and use with any valid duck array library,
+NumPy itself would return restricted versions of the ``numpy`` module when
+``get_array_module`` is called only on NumPy arrays. Omitted functions would
+simply not exist.
+
+Unfortunately, we have not yet figured out what these restricted subsets should
+be, so it doesn't make sense to do this yet. When/if we do, we could either add
+new keyword arguments to ``get_array_module`` or add new top level functions,
+e.g., ``get_minimal_array_module``. We would also need to add either a new
+protocol patterned off of ``__array_module__`` (e.g.,
+``__array_module_minimal__``), or could add an optional second argument to
+``__array_module__`` (catching errors with ``try``/``except``).
+
+A new namespace for implicit dispatch
+=====================================
+
+Instead of supporting overrides in the main `numpy` namespace with
+``__array_function__``, we could create a new opt-in namespace, e.g.,
+``numpy.api``, with versions of NumPy functions that support dispatching. These
+overrides would need new opt-in protocols, e.g., ``__array_function_api__``
+patterned off of ``__array_function__``.
+
+This would resolve the biggest limitations of ``__array_function__`` by being
+opt-in and would also allow for unambiguously overriding functions like
+``asarray``, because ``np.api.asarray`` would always mean "convert an
+array-like object."  But it wouldn't solve all the dispatching needs met by
+``__array_module__``, and would leave us with supporting a considerably more
+complex protocol both for array users and implementors.
+
+We could potentially implement such a new namespace *via* the
+``__array_module__`` protocol. Certainly some users would find this convenient,
+because it is slightly less boilerplate. But this would leave users with a
+confusing choice: when should they use `get_array_module` vs.
+`np.api.something`. Also, we would have to add and maintain a whole new module,
+which is considerably more expensive than merely adding a function.
+
+Dispatching on both types and arrays instead of only types
+==========================================================
+
+Instead of supporting dispatch only via unique array types, we could also
+support dispatch via array objects, e.g., by passing an ``arrays`` argument as
+part of the ``__array_module__`` protocol. This could potentially be useful for
+dispatch for arrays with metadata, such provided by Dask and Pint, but would
+impose costs in terms of type safety and complexity.
+
+For example, a library that supports arrays on both CPUs and GPUs might decide
+on which device to create a new arrays from functions like ``ones`` based on
+input arguments:
+
+.. code:: python
+
+    class Array:
+        def __array_module__(self, types, arrays):
+            useful_arrays = tuple(a in arrays if isinstance(a, Array))
+            if not useful_arrays:
+                return NotImplemented
+            prefer_gpu = any(a.prefer_gpu for a in useful_arrays)
+            return ArrayModule(prefer_gpu)
+
+    class ArrayModule:
+        def __init__(self, prefer_gpu):
+            self.prefer_gpu = prefer_gpu
+
+        def __getattr__(self, name):
+            import base_module
+            base_func = getattr(base_module, name)
+            return functools.partial(base_func, prefer_gpu=self.prefer_gpu)
+
+This might be useful, but it's not clear if we really need it. Pint seems to
+get along OK without any explicit array creation routines (favoring
+multiplication by units, e.g., ``np.ones(5) * ureg.m``), and for the most part
+Dask is also OK with existing ``__array_function__`` style overrides (e.g.,
+favoring ``np.ones_like`` over ``np.ones``). Choosing whether to place an array
+on the CPU or GPU could be solved by `making array creation lazy
+<https://github.com/google/jax/pull/1668>`_.
+
+.. _appendix-design-choices:
+
+Appendix: design choices for API overrides
+------------------------------------------
+
+There is a large range of possible design choices for overriding NumPy's API.
+Here we discuss three major axes of the design decision that guided our design
+for ``__array_module__``.
+
+Opt-in vs. opt-out for users
+============================
+
+The ``__array_ufunc__`` and ``__array_function__`` protocols provide a
+mechanism for overriding NumPy functions *within NumPy's existing namespace*.
+This means that users need to explicitly opt-out if they do not want any
+overridden behavior, e.g., by casting arrays with ``np.asarray()``.
+
+In theory, this approach lowers the barrier for adopting these protocols in
+user code and libraries, because code that uses the standard NumPy namespace is
+automatically compatible. But in practice, this hasn't worked out. For example,
+most well-maintained libraries that use NumPy follow the best practice of
+casting all inputs with ``np.asarray()``, which they would have to explicitly
+relax to use ``__array_function__``. Our experience has been that making a
+library compatible with a new duck array type typically requires at least a
+small amount of work to accommodate differences in the data model and operations
+that can be implemented efficiently.
+
+These opt-out approaches also considerably complicate backwards compatibility
+for libraries that adopt these protocols, because by opting in as a library
+they also opt-in their users, whether they expect it or not. For winning over
+libraries that have been unable to adopt ``__array_function__``, an opt-in
+approach seems like a must.
+
+Explicit vs. implicit choice of implementation
+==============================================
+
+Both ``__array_ufunc__`` and ``__array_function__`` have implicit control over
+dispatching: the dispatched functions are determined via the appropriate
+protocols in every function call. This generalizes well to handling many
+different types of objects, as evidenced by its use for implementing arithmetic
+operators in Python, but it has an important downside for **readability**:
+it is not longer immediately evident to readers of code what happens when a
+function is called, because the function's implementation could be overridden
+by any of its arguments.
+
+The **speed** implications are:
+
+- When using a *duck-array type*, ``get_array_module`` means type checking only
+  needs to happen once inside each function that supports duck typing, whereas
+  with ``__array_function__`` it happens every time a NumPy function is called.
+  Obvious it's going to depend on the function, but if a typical duck-array
+  supporting function calls into other NumPy functions 3-5 times this is a factor
+  of 3-5x more overhead.
+- When using *NumPy arrays*, ``get_array_module`` is one extra call per
+  function (``__array_function__`` overhead remains the same), which means a
+  small amount of extra overhead.
+
+Explicit and implicit choice of implementations are not mutually exclusive
+options. Indeed, most implementations of NumPy API overrides via
+``__array_function__`` that we are familiar with (namely, Dask, CuPy and
+Sparse, but not Pint) also include an explicit way to use their version of
+NumPy's API by importing a module directly (``dask.array``, ``cupy`` or
+``sparse``, respectively).
+
+Local vs. non-local vs. global control
+======================================
+
+The final design axis is how users control the choice of API:
+
+- **Local control**, as exemplified by multiple dispatch and Python protocols for
+  arithmetic, determines which implementation to use either by checking types
+  or calling methods on the direct arguments of a function.
+- **Non-local control** such as `np.errstate
+  <https://docs.scipy.org/doc/numpy/reference/generated/numpy.errstate.html>`_
+  overrides behavior with global-state via function decorators or
+  context-managers. Control is determined hierarchically, via the inner-most
+  context.
+- **Global control** provides a mechanism for users to set default behavior,
+  either via function calls or configuration files. For example, matplotlib
+  allows setting a global choice of plotting backend.
+
+Local control is generally considered a best practice for API design, because
+control flow is entirely explicit, which makes it the easiest to understand.
+Non-local and global control are occasionally used, but generally either due to
+ignorance or a lack of better alternatives.
+
+In the case of duck typing for NumPy's public API, we think non-local or global
+control would be mistakes, mostly because they **don't compose well**. If one
+library sets/needs one set of overrides and then internally calls a routine
+that expects another set of overrides, the resulting behavior may be very
+surprising. Higher order functions are especially problematic, because the
+context in which functions are evaluated may not be the context in which they
+are defined.
+
+One class of override use cases where we think non-local and global control are
+appropriate is for choosing a backend system that is guaranteed to have an
+entirely consistent interface, such as a faster alternative implementation of
+``numpy.fft`` on NumPy arrays. However, these are out of scope for the current
+proposal, which is focused on duck arrays.
diff --git a/doc/neps/nep-0038-SIMD-optimizations.rst b/doc/neps/nep-0038-SIMD-optimizations.rst
new file mode 100644 (file)
index 0000000..ab16868
--- /dev/null
@@ -0,0 +1,334 @@
+=============================================================
+NEP 38 â€” Using SIMD optimization instructions for performance
+=============================================================
+
+:Author: Sayed Adel, Matti Picus, Ralf Gommers
+:Status: Accepted
+:Type: Standards
+:Created: 2019-11-25
+:Resolution: http://numpy-discussion.10968.n7.nabble.com/NEP-38-Universal-SIMD-intrinsics-td47854.html
+
+
+Abstract
+--------
+
+While compilers are getting better at using hardware-specific routines to
+optimize code, they sometimes do not produce optimal results. Also, we would
+like to be able to copy binary optimized C-extension modules from one machine
+to another with the same base architecture (x86, ARM, or PowerPC) but with
+different capabilities without recompiling.
+
+We have a mechanism in the ufunc machinery to `build alternative loops`_
+indexed by CPU feature name. At import (in ``InitOperators``), the loop
+function that matches the run-time CPU info `is chosen`_ from the candidates.This
+NEP proposes a mechanism to build on that for many more features and
+architectures.  The steps proposed are to:
+
+- Establish a set of well-defined, architecture-agnostic, universal intrisics
+  which capture features available across architectures.
+- Capture these universal intrisics in a set of C macros and use the macros
+  to build code paths for sets of features from the baseline up to the maximum
+  set of features available on that architecture. Offer these as a limited
+  number of compiled alternative code paths.
+- At runtime, discover which CPU features are available, and choose from among
+  the possible code paths accordingly.
+
+
+Motivation and Scope
+--------------------
+
+Traditionally NumPy has depended on compilers to generate optimal code
+specifically for the target architecture.
+However few users today compile NumPy locally for their machines. Most use the
+binary packages which must provide run-time support for the lowest-common
+denominator CPU architecture. Thus NumPy cannot take advantage of 
+more advanced features of their CPU processors, since they may not be available
+on all users' systems.
+
+Traditionally, CPU features have been exposed through `intrinsics`_ which are
+compiler-specific instructions that map directly to assembly instructions.
+Recently there were discussions about the effectiveness of adding more
+intrinsics (e.g., `gh-11113`_ for AVX optimizations for floats).  In the past,
+architecture-specific code was added to NumPy for `fast avx512 routines`_ in
+various ufuncs, using the mechanism described above to choose the best loop
+for the architecture. However the code is not generic and does not generalize
+to other architectures.
+
+Recently, OpenCV moved to using `universal intrinsics`_ in the Hardware
+Abstraction Layer (HAL) which provided a nice abstraction for common shared
+Single Instruction Multiple Data (SIMD) constructs. This NEP proposes a similar
+mechanism for NumPy. There are three stages to using the mechanism:
+
+- Infrastructure is provided in the code for abstract intrinsics. The ufunc
+  machinery will be extended using sets of these abstract intrinsics, so that
+  a single ufunc will be expressed as a set of loops, going from a minimal to
+  a maximal set of possibly availabe intrinsics.
+- At compile time, compiler macros and CPU detection are used to turn the
+  abstract intrinsics into concrete intrinsic calls. Any intrinsics not
+  available on the platform, either because the CPU does not support them
+  (and so cannot be tested) or because the abstract intrinsic does not have a
+  parallel concrete intrinsic on the platform will not error, rather the
+  corresponding loop will not be produced and added to the set of
+  possibilities.
+- At runtime, the CPU detection code will further limit the set of loops
+  available, and the optimal one will be chosen for the ufunc.
+
+The current NEP proposes only to use the runtime feature detection and optimal
+loop selection mechanism for ufuncs. Future NEPS may propose other uses for the
+proposed solution.
+
+The ufunc machinery already has the ability to select an optimal loop for
+specifically available CPU features at runtime, currently used for ``avx2``,
+``fma`` and ``avx512f`` loops (in the generated ``__umath_generated.c`` file);
+universal intrinsics would extend the generated code to include more loop
+variants.
+
+Usage and Impact
+----------------
+
+The end user will be able to get a list of intrinsics available for their
+platform and compiler. Optionally,
+the user may be able to specify which of the loops available at runtime will be
+used, perhaps via an environment variable to enable benchmarking the impact of
+the different loops. There should be no direct impact to naive end users, the
+results of all the loops should be identical to within a small number (1-3?)
+ULPs. On the other hand, users with more powerful machines should notice a
+significant performance boost.
+
+Binary releases - wheels on PyPI and conda packages
+```````````````````````````````````````````````````
+
+The binaries released by this process will be larger since they include all
+possible loops for the architecture. Some packagers may prefer to limit the
+number of loops in order to limit the size of the binaries, we would hope they
+would still support a wide range of families of architectures. Note this
+problem already exists in the Intel MKL offering, where the binary package
+includes an extensive set of alternative shared objects (DLLs) for various CPU
+alternatives.
+
+Source builds
+`````````````
+
+See "Detailed Description" below. A source build where the packager knows
+details of the target machine could theoretically produce a smaller binary by
+choosing to compile only the loops needed by the target via command line
+arguments.
+
+How to run benchmarks to assess performance benefits
+````````````````````````````````````````````````````
+
+Adding more code which use intrinsics will make the code harder to maintain.
+Therefore, such code should only be added if it yields a significant
+performance benefit. Assessing this performance benefit can be nontrivial.
+To aid with this, the implementation for this NEP will add a way to select
+which instruction sets can be used at *runtime* via environment variables.
+(name TBD). This ablility is critical for CI code verification.
+
+
+Diagnostics
+```````````
+
+A new dictionary ``__cpu_features__`` will be available to python. The keys are
+the available features, the value is a boolean whether the feature is available
+or not. Various new private
+C functions will be used internally to query available features. These
+might be exposed via specific c-extension modules for testing.
+
+
+Workflow for adding a new CPU architecture-specific optimization
+````````````````````````````````````````````````````````````````
+
+NumPy will always have a baseline C implementation for any code that may be
+a candidate for SIMD vectorization.  If a contributor wants to add SIMD
+support for some architecture (typically the one of most interest to them),
+this comment is the beginning of a tutorial on how to do so:
+https://github.com/numpy/numpy/pull/13516#issuecomment-558859638
+
+.. _tradeoffs:
+
+As of this moment, NumPy has a number of ``avx512f`` and ``avx2`` and ``fma``
+SIMD loops for many ufuncs. These would likely be the first candidates
+to be ported to universal intrinsics. The expectation is that the new
+implementation may cause a regression in benchmarks, but not increase the
+size of the binary. If the regression is not minimal, we may choose to keep
+the X86-specific code for that platform and use the universal intrisic code
+for other platforms.
+
+Any new PRs to implement ufuncs using intrinsics will be expected to use the
+universal intrinsics. If it can be demonstrated that the use of universal
+intrinsics is too awkward or is not performant enough, platform specific code
+may be accepted as well. In rare cases, a single-platform only PR may be
+accepted, but it would have to be examined within the framework of preferring
+a solution using universal intrinsics.
+
+The subjective criteria for accepting new loops are:
+
+- correctness: the new code must not decrease accuracy by more than 1-3 ULPs
+  even at edge points in the algorithm.
+- code bloat: both source code size and especially binary size of the compiled
+  wheel.
+- maintainability: how readable is the code
+- performance: benchmarks must show a significant performance boost
+
+.. _new-intrinsics:
+
+Adding a new intrinsic
+~~~~~~~~~~~~~~~~~~~~~~
+
+If a contributor wants to use a platform-specific SIMD instruction that is not
+yet supported as a universal intrinsic, then:
+
+1. It should be added as a universal intrinsic for all platforms
+2. If it does not have an equivalent instruction on other platforms (e.g.
+   ``_mm512_mask_i32gather_ps`` in ``AVX512``), then no universal intrinsic
+   should be added and a platform-specific ``ufunc`` or a short helper fuction
+   should be written instead. If such a helper function is used, it must be
+   wrapped with the feature macros, and a reasonable non-intrinsic fallback to
+   be used by default.
+
+We expect (2) to be the exception. The contributor and maintainers should
+consider whether that single-platform intrinsic is worth it compared to using
+the best available universal intrinsic based implementation.
+
+Reuse by other projects
+```````````````````````
+
+It would be nice if the universal intrinsics would be available to other
+libraries like SciPy or Astropy that also build ufuncs, but that is not an
+explicit goal of the first implementation of this NEP.
+
+Backward compatibility
+----------------------
+
+There should be no impact on backwards compatibility.
+
+
+Detailed description
+--------------------
+
+The CPU-specific are mapped to unversal intrinsics which are
+similar for all x86 SIMD variants, ARM SIMD variants etc. For example, the
+NumPy universal intrinsic ``npyv_load_u32`` maps to:
+
+*  ``vld1q_u32`` for ARM based NEON
+* ``_mm256_loadu_si256`` for x86 based AVX2 
+* ``_mm512_loadu_si512`` for x86 based AVX-512
+
+Anyone writing a SIMD loop will use the ``npyv_load_u32`` macro instead of the
+architecture specific intrinsic. The code also supplies guard macros for
+compilation and runtime, so that the proper loops can be chosen.
+
+Two new build options are available to ``runtests.py`` and ``setup.py``:
+``--cpu-baseline`` and ``--cpu-dispatch``.
+The absolute minimum required features to compile are defined by
+``--cpu-baseline``.  For instance, on ``x86_64`` this defaults to ``SSE3``. The
+minimum features will be enabled if the compiler support it. The
+set of additional intrinsics that can be detected and used as sets of
+requirements to dispatch on are set by ``--cpu-dispatch``. For instance, on
+``x86_64`` this defaults to ``[SSSE3, SSE41, POPCNT, SSE42, AVX, F16C, XOP,
+FMA4, FMA3, AVX2, AVX512F, AVX512CD, AVX512_KNL, AVX512_KNM, AVX512_SKX,
+AVX512_CLX, AVX512_CNL, AVX512_ICL]``. These features are all mapped to a
+c-level boolean array ``npy__cpu_have``, and a c-level convenience function
+``npy_cpu_have(int feature_id)`` queries this array, and the results are stored
+in ``__cpu_features__`` at runtime.
+
+When importing the ufuncs, the available compiled loops' required features are
+matched to the ones discovered. The loop with the best match is marked to be
+called by the ufunc.
+
+Related Work
+------------
+
+- `Pixman`_ is the library used by Cairo and X to manipulate pixels. It uses
+  a technique like the one described here to fill a structure with function
+  pointers at runtime. These functions are similar to ufunc loops.
+- `Eigen`_ is a C++ template library for linear algebra: matrices, vectors,
+  numerical solvers, and related algorithms. It is a higher level-abstraction
+  than the intrinsics discussed here.
+- `xsimd`_ is a header-only C++ library for x86 and ARM that implements the
+  mathematical functions used in the algorithms of ``boost.SIMD``.
+- `Simd`_ is a high-level image processing and machine learning library with
+  optimizations for different platforms.
+- OpenCV used to have the one-implementation-per-architecture design, but more
+  recently moved to a design that is quite similar to what is proposed in this
+  NEP. The top-level `dispatch code`_ includes a `generic header`_ that is
+  `specialized at compile time`_ by the CMakefile system.
+- `VOLK`_ is a GPL3 library used by gnuradio and others to abstract SIMD
+  intrinsics. They offer a set of high-level operations which have been
+  optimized for each architecture.
+- The C++ Standards Committee has proposed `class templates`_ for portable
+  SIMD programming via vector types, and `namespaces`_ for the templates.
+
+Implementation
+--------------
+
+Current PRs:
+
+- `gh-13421 improve runtime detection of CPU features <https://github.com/numpy/numpy/pull/13421>`_
+- `gh-13516: enable multi-platform SIMD compiler optimizations <https://github.com/numpy/numpy/pull/13516>`_
+
+The compile-time and runtime code infrastructure are supplied by the first PR.
+The second adds a demonstration of use of the infrastructure for a loop. Once
+the NEP is approved, more work is needed to write loops using the machnisms
+provided by the NEP.
+
+Alternatives
+------------
+
+A proposed alternative in gh-13516_ is to implement loops for each CPU
+architecture separately by hand, without trying to abstract common patterns in
+the SIMD intrinsics (e.g., have `loops.avx512.c.src`, `loops.avx2.c.src`,
+`loops.sse.c.src`, `loops.vsx.c.src`, `loops.neon.c.src`, etc.). This is more
+similar to what PIXMAX does. There's a lot of duplication here though, and the
+manual code duplication requires a champion who will be dedicated to
+implementing and maintaining that platform's loop code.
+
+
+Discussion
+----------
+
+Most of the discussion took place on the PR `gh-15228`_ to accecpt this NEP.
+Discussion on the mailing list mentioned `VOLK`_ which was added to
+the section on related work. The question of maintainability also was raised
+both on the mailing list and in `gh-15228`_ and resolved as follows:
+
+- If contributors want to leverage a specific SIMD instruction, will they be
+  expected to add software implementation of this instruction for all other
+  architectures too? (see the `new-intrinsics`_ part of the workflow).
+- On whom does the burden lie to verify the code and benchmarks for all
+  architectures? What happens if adding a universal ufunc in place of
+  architecture-specific code helps one architecture but harms performance
+  on another? (answered in the tradeoffs_ part of the workflow).
+
+References and Footnotes
+------------------------
+
+.. _`build alternative loops`: https://github.com/numpy/numpy/blob/v1.17.4/numpy/core/code_generators/generate_umath.py#L50
+.. _`is chosen`: https://github.com/numpy/numpy/blob/v1.17.4/numpy/core/code_generators/generate_umath.py#L1038
+.. _`gh-11113`: https://github.com/numpy/numpy/pull/11113
+.. _`gh-15228`: https://github.com/numpy/numpy/pull/15228
+.. _`gh-13516`: https://github.com/numpy/numpy/pull/13516
+.. _`fast avx512 routines`: https://github.com/numpy/numpy/pulls?q=is%3Apr+avx512+is%3Aclosed
+
+.. [1] Each NEP must either be explicitly labeled as placed in the public domain (see
+   this NEP as an example) or licensed under the `Open Publication License`_.
+
+.. _Open Publication License: https://www.opencontent.org/openpub/
+
+.. _`xsimd`: https://xsimd.readthedocs.io/en/latest/
+.. _`Pixman`: https://gitlab.freedesktop.org/pixman
+.. _`VOLK`: https://www.libvolk.org/doxygen/index.html
+.. _`Eigen`: http://eigen.tuxfamily.org/index.php?title=Main_Page
+.. _`Simd`: https://github.com/ermig1979/Simd
+.. _`dispatch code`: https://github.com/opencv/opencv/blob/4.1.2/modules/core/src/arithm.dispatch.cpp
+.. _`generic header`: https://github.com/opencv/opencv/blob/4.1.2/modules/core/src/arithm.simd.hpp
+.. _`specialized at compile time`: https://github.com/opencv/opencv/blob/4.1.2/modules/core/CMakeLists.txt#L3-#L13
+.. _`intrinsics`: https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-intrinsics
+.. _`universal intrinsics`: https://docs.opencv.org/master/df/d91/group__core__hal__intrin.html
+.. _`class templates`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0214r8.pdf
+.. _`namespaces`: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2019/n4808.pdf
+
+Copyright
+---------
+
+This document has been placed in the public domain. [1]_
diff --git a/doc/neps/nep-0040-legacy-datatype-impl.rst b/doc/neps/nep-0040-legacy-datatype-impl.rst
new file mode 100644 (file)
index 0000000..c247e3d
--- /dev/null
@@ -0,0 +1,645 @@
+.. _NEP40:
+
+================================================
+NEP 40 â€” Legacy Datatype Implementation in NumPy
+================================================
+
+:title: Legacy Datatype Implementation in NumPy
+:Author: Sebastian Berg
+:Status: Draft
+:Type: Informational
+:Created: 2019-07-17
+
+
+.. note::
+
+    This NEP is part of a series of NEPs encompassing first information
+    about the previous dtype implementation and issues with it in NEP 40
+    (this document).
+    :ref:`NEP 41 <NEP41>` then provides an overview and generic design choices
+    for the refactor.
+    Further NEPs 42 and 43 go into the technical details of the datatype
+    and universal function related internal and external API changes.
+    In some cases it may be necessary to consult the other NEPs for a full
+    picture of the desired changes and why these changes are necessary.
+
+
+
+Abstract
+--------
+
+As a preparation to further NumPy enhancement proposals 41, 42, and 43. This
+NEP details the current status of NumPy datatypes as of NumPy 1.18.
+It describes some of the technical aspects and concepts that
+motivated the other proposals.
+For more general information most readers should begin by reading :ref:`NEP 41 <NEP41>`
+and use this document only as a reference or for additional details.
+
+
+Detailed Description
+--------------------
+
+This section describes some central concepts and provides a brief overview
+of the current implementation of dtypes as well as a discussion.
+In many cases subsections will be split roughly to first describe the
+current implementation and then follow with an "Issues and Discussion" section.
+
+Parametric Datatypes
+^^^^^^^^^^^^^^^^^^^^
+
+Some datatypes are inherently *parametric*. All ``np.flexible`` scalar
+types are attached to parametric datatypes (string, bytes, and void).
+The class ``np.flexible`` for scalars is a superclass for the data types of
+variable length (string, bytes, and void).
+This distinction is similarly exposed by the C-Macros
+``PyDataType_ISFLEXIBLE`` and ``PyTypeNum_ISFLEXIBLE``.
+This flexibility generalizes to the set of values which can be represented
+inside the array.
+For instance, ``"S8"`` can represent longer strings than ``"S4"``.
+The parametric string datatype thus also limits the values inside the array
+to a subset (or subtype) of all values which can be represented by string
+scalars.
+
+The basic numerical datatypes are not flexible (do not inherit from
+``np.flexible``). ``float64``, ``float32``, etc. do have a byte order, but the described
+values are unaffected by it, and it is always possible to cast them to the
+native, canonical representation without any loss of information.
+
+The concept of flexibility can be generalized to parametric datatypes.
+For example the private ``PyArray_AdaptFlexibleDType`` function also accepts the
+naive datetime dtype as input to find the correct time unit.
+The datetime dtype is thus parametric not in the size of its storage,
+but instead in what the stored value represents.
+Currently ``np.can_cast("datetime64[s]", "datetime64[ms]", casting="safe")``
+returns true, although it is unclear that this is desired or generalizes
+to possible future data types such as physical units.
+
+Thus we have data types (mainly strings) with the properties that:
+
+1. Casting is not always safe (``np.can_cast("S8", "S4")``)
+2. Array coercion should be able to discover the exact dtype, such as for
+   ``np.array(["str1", 12.34], dtype="S")`` where NumPy discovers the
+   resulting dtype as ``"S5"``.
+   (If the dtype argument is ommitted the behaviour is currently ill defined [gh-15327]_.)
+   A form similar to ``dtype="S"`` is ``dtype="datetime64"`` which can
+   discover the unit: ``np.array(["2017-02"], dtype="datetime64")``.
+
+This notion highlights that some datatypes are more complex than the basic
+numerical ones, which is evident in the complicated output type discovery
+of universal functions.
+
+
+Value Based Casting
+^^^^^^^^^^^^^^^^^^^
+
+Casting is typically defined between two types:
+A type is considered to cast safely to a second type when the second type
+can represent all values of the first without loss of information.
+NumPy may inspect the actual value to decide
+whether casting is safe or not.
+
+This is useful for example in expressions such as::
+
+    arr = np.array([1, 2, 3], dtype="int8")
+    result = arr + 5
+    assert result.dtype == np.dtype("int8")
+    # If the value is larger, the result will change however:
+    result = arr + 500
+    assert result.dtype == np.dtype("int16")
+
+In this expression, the python value (which originally has no datatype) is
+represented as an ``int8`` or ``int16`` (the smallest possible data type).
+
+NumPy currently does this even for NumPy scalars and zero-dimensional arrays,
+so that replacing ``5`` with ``np.int64(5)`` or ``np.array(5, dtype="int64")``
+in the above expression will lead to the same results, and thus ignores the
+existing datatype. The same logic also applies to floating-point scalars,
+which are allowed to lose precision.
+The behavior is not used when both inputs are scalars, so that
+``5 + np.int8(5)`` returns the default integer size (32 or 64-bit) and not
+an ``np.int8``.
+
+While the behaviour is defined in terms of casting and exposed by
+``np.result_type`` it is mainly important for universal functions
+(such as ``np.add`` in the above examples).
+Universal functions currently rely on safe casting semantics to decide which
+loop should be used, and thus what the output datatype will be.
+
+
+Issues and Discussion
+"""""""""""""""""""""
+
+There appears to be some agreement that the current method is
+not desirable for values that have a datatype,
+but may be useful for pure python integers or floats as in the first
+example.
+However, any change of the datatype system and universal function dispatching
+must initially fully support the current behavior.
+A main difficulty is that for example the value ``156`` can be represented
+by ``np.uint8`` and ``np.int16``.
+The result depends on the "minimal" representation in the context of the
+conversion (for ufuncs the context may depend on the loop order).
+
+
+The Object Datatype
+^^^^^^^^^^^^^^^^^^^
+
+The object datatype currently serves as a generic fallback for any value
+which is not otherwise representable.
+However, due to not having a well-defined type, it has some issues,
+for example when an array is filled with Python sequences::
+
+    >>> l = [1, [2]]
+    >>> np.array(l, dtype=np.object_)
+    array([1, list([2])], dtype=object)  # a 1d array
+
+    >>> a = np.empty((), dtype=np.object_)
+    >>> a[...] = l
+    ValueError: assignment to 0-d array  # ???
+    >>> a[()] = l
+    >>> a
+    array(list([1, [2]]), dtype=object)
+
+Without a well-defined type, functions such as ``isnan()`` or ``conjugate()``
+do not necessarily work, but can work for a :class:`decimal.Decimal`.
+To improve this situation it seems desirable to make it easy to create
+``object`` dtypes that represent a specific Python datatype and stores its object
+inside the array in the form of pointer to python ``PyObject``.
+Unlike most datatypes, Python objects require garbage collection.
+This means that additional methods to handle references and
+visit all objects must be defined.
+In practice, for most use-cases it is sufficient to limit the creation of such
+datatypes so that all functionality related to Python C-level references is
+private to NumPy.
+
+Creating NumPy datatypes that match builtin Python objects also creates a few problems
+that require more thoughts and discussion.
+These issues do not need to solved right away:
+
+* NumPy currently returns *scalars* even for array input in some cases, in most
+  cases this works seamlessly. However, this is only true because the NumPy
+  scalars behave much like NumPy arrays, a feature that general Python objects
+  do not have.
+* Seamless integration probably requires that ``np.array(scalar)`` finds the
+  correct DType automatically since some operations (such as indexing) return
+  the scalar instead of a 0D array.
+  This is problematic if multiple users independently decide to implement
+  for example a DType for ``decimal.Decimal``.
+
+
+Current ``dtype`` Implementation
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Currently ``np.dtype`` is a Python class with its instances being the
+``np.dtype(">float64")``, etc. instances.
+To set the actual behaviour of these instances, a prototype instance is stored
+globally and looked up based on the ``dtype.typenum``. The singleton is used
+where possible. Where required it is copied and modified, for instance to change
+endianess.
+
+Parametric datatypes (strings, void, datetime, and timedelta) must store
+additional information such as string lengths, fields, or datetime units --
+new instances of these types are created instead of relying on a singleton.
+All current datatypes within NumPy further support setting a metadata field
+during creation which can be set to an arbitrary dictionary value, but seems
+rarely used in practice (one recent and prominent user is h5py).
+
+Many datatype-specific functions are defined within a C structure called
+:c:type:`PyArray_ArrFuncs`, which is part of each ``dtype`` instance and
+has a similarity to Python's ``PyNumberMethods``.
+For user-defined datatypes this structure is exposed to the user, making
+ABI-compatible changes impossible.
+This structure holds important information such as how to copy or cast,
+and provides space for pointers to functions, such as comparing elements,
+converting to bool, or sorting.
+Since some of these functions are vectorized operations, operating on more than
+one element, they fit the model of ufuncs and do not need to be defined on the
+datatype in the future.
+For example the ``np.clip`` function was previously implemented using
+``PyArray_ArrFuncs`` and is now implemented as a ufunc.
+
+Discussion and Issues
+"""""""""""""""""""""
+
+A further issue with the current implementation of the functions on the dtype
+is that, unlike methods,
+they are not passed an instance of the dtype when called.
+Instead, in many cases, the array which is being operated on is passed in
+and typically only used to extract the datatype again.
+A future API should likely stop passing in the full array object.
+Since it will be necessary to fall back to the old definitions for
+backward compatibility, the array object may not be available.
+However, passing a "fake" array in which mainly the datatype is defined
+is probably a sufficient workaround
+(see backward compatibility; alignment information may sometimes also be desired).
+
+Although not extensively used outside of NumPy itself, the currently
+``PyArray_Descr`` is a public structure.
+This is especially also true for the ``PyArray_ArrFuncs`` structure stored in
+the ``f`` field.
+Due to compatibility they may need to remain supported for a very long time,
+with the possibility of replacing them by functions that dispatch to a newer API.
+
+However, in the long run access to these structures will probably have to
+be deprecated.
+
+
+NumPy Scalars and Type Hierarchy
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As a side note to the above datatype implementation: unlike the datatypes,
+the NumPy scalars currently **do** provide a type hierarchy, consisting of abstract
+types such as ``np.inexact`` (see figure below).
+In fact, some control flow within NumPy currently uses
+``issubclass(a.dtype.type, np.inexact)``.
+
+.. figure:: _static/nep-0040_dtype-hierarchy.png
+
+   **Figure:** Hierarchy of NumPy scalar types reproduced from the reference
+   documentation. Some aliases such as ``np.intp`` are excluded. Datetime
+   and timedelta are not shown.
+
+NumPy scalars try to mimic zero-dimensional arrays with a fixed datatype.
+For the numerical (and unicode) datatypes, they are further limited to
+native byte order.
+
+
+Current Implementation of Casting
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+One of the main features which datatypes need to support is casting between one
+another using ``arr.astype(new_dtype, casting="unsafe")``, or during execution
+of ufuncs with different types (such as adding integer and floating point numbers).
+
+Casting tables determine whether it is possible to cast from one specific type to another.
+However, generic casting rules cannot handle the parametric dtypes such as strings.
+The logic for parametric datatypes is defined mainly in ``PyArray_CanCastTo``
+and currently cannot be customized for user defined datatypes.
+
+The actual casting has two distinct parts:
+
+1. ``copyswap``/``copyswapn`` are defined for each dtype and can handle
+   byte-swapping for non-native byte orders as well as unaligned memory.
+2. The generic casting code is provided by C functions which know how to
+   cast aligned and contiguous memory from one dtype to another
+   (both in native byte order).
+   These C-level functions can be registered to cast aligned and contiguous memory
+   from one dtype to another.
+   The function may be provided with both arrays (although the parameter
+   is sometimes ``NULL`` for scalars).
+   NumPy will ensure that these functions receive native byte order input.
+   The current implementation stores the functions either in a C-array
+   on the datatype which is cast, or in a dictionary when casting to a user
+   defined datatype.
+
+Generally NumPy will thus perform casting as chain of the three functions
+``in_copyswapn -> castfunc -> out_copyswapn`` using (small) buffers between
+these steps.
+
+The above multiple functions are wrapped into a single function (with metadata)
+that handles the cast and is used for example during the buffered iteration used
+by ufuncs.
+This is the mechanism that is always used for user defined datatypes.
+For most dtypes defined within NumPy itself, more specialized code is used to
+find a function to do the actual cast
+(defined by the private ``PyArray_GetDTypeTransferFunction``).
+This mechanism replaces most of the above mechanism and provides much faster
+casts for example when the inputs are not contiguous in memory.
+However, it cannot be extended by user defined datatypes.
+
+Related to casting, we currently have a ``PyArray_EquivTypes`` function which
+indicate that a *view* is sufficient (and thus no cast is necessary).
+This function is used multiple places and should probably be part of
+a redesigned casting API.
+
+
+DType handling in Universal functions
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Universal functions are implemented as instances of the ``numpy.UFunc`` class
+with an ordered-list of datatype-specific
+(based on the dtype typecode character, not datatype instances) implementations,
+each with a signature and a function pointer.
+This list of implementations can be seen with ``ufunc.types`` where
+all implementations are listed with their C-style typecode signatures.
+For example::
+
+    >>> np.add.types
+    [...,
+     'll->l',
+     ...,
+     'dd->d',
+     ...]
+
+Each of these signatures is associated with a single inner-loop function defined
+in C, which does the actual calculation, and may be called multiple times.
+
+The main step in finding the correct inner-loop function is to call a
+:c:type:`PyUFunc_TypeResolutionFunc` which retrieves the input dtypes from 
+the provided input arrays
+and will determine the full type signature (including output dtype) to be executed.
+
+By default the ``TypeResolver`` is implemented by searching all of the implementations
+listed in ``ufunc.types`` in order and stopping if all inputs can be safely
+cast to fit the signature.
+This means that if long (``l``) and double (``d``) arrays are added,
+numpy will find that the ``'dd->d'`` definition works
+(long can safely cast to double) and uses that.
+
+In some cases this is not desirable. For example the ``np.isnat`` universal
+function has a ``TypeResolver`` which rejects integer inputs instead of
+allowing them to be cast to float.
+In principle, downstream projects can currently use their own non-default
+``TypeResolver``, since the corresponding C-structure necessary to do this
+is public.
+The only project known to do this is Astropy, which is willing to switch to
+a new API if NumPy were to remove the possibility to replace the TypeResolver.
+
+For user defined datatypes, the dispatching logic is similar,
+although separately implemented and limited (see discussion below).
+
+
+Issues and Discussion
+"""""""""""""""""""""
+
+It is currently only possible for user defined functions to be found/resolved
+if any of the inputs (or the outputs) has the user datatype, since it uses the
+`OO->O` signature.
+For example, given that a ufunc loop to implement ``fraction_divide(int, int)
+-> Fraction`` has been implemented, 
+the call ``fraction_divide(4, 5)`` (with no specific output dtype) will fail
+because the loop that
+includes the user datatype ``Fraction`` (as output) can only be found if any of
+the inputs is already a ``Fraction``.
+``fraction_divide(4, 5, dtype=Fraction)`` can be made to work, but is inconvenient.
+
+Typically, dispatching is done by finding the first loop that matches. A match
+is defined as: all inputs (and possibly outputs) can
+be cast safely to the signature typechars (see also the current implementation
+section).
+However, in some cases safe casting is problematic and thus explicitly not
+allowed.
+For example the ``np.isnat`` function is currently only defined for
+datetime and timedelta,
+even though integers are defined to be safely castable to timedelta.
+If this was not the case, calling
+``np.isnat(np.array("NaT", "timedelta64").astype("int64"))`` would currently
+return true, although the integer input array has no notion of "not a time".
+If a universal function, such as most functions in ``scipy.special``, is only
+defined for ``float32`` and ``float64`` it will currently automatically
+cast a ``float16`` silently to ``float32`` (similarly for any integer input).
+This ensures successful execution, but may lead to a change in the output dtype
+when support for new data types is added to a ufunc.
+When a ``float16`` loop is added, the output datatype will currently change
+from ``float32`` to ``float16`` without a warning.
+
+In general the order in which loops are registered is important.
+However, this is only reliable if all loops are added when the ufunc is first defined.
+Additional loops added when a new user datatypes is imported
+must not be sensitive to the order in which imports occur.
+
+There are two main approaches to better define the type resolution for user
+defined types:
+
+1. Allow for user dtypes to directly influence the loop selection.
+   For example they may provide a function which return/select a loop
+   when there is no exact matching loop available.
+2. Define a total ordering of all implementations/loops, probably based on
+   "safe casting" semantics, or semantics similar to that.
+
+While option 2 may be less complex to reason about it remains to be seen
+whether it is sufficient for all (or most) use cases.
+
+
+Adjustment of Parametric output DTypes in UFuncs
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+A second step necessary for parametric dtypes is currently performed within
+the ``TypeResolver``:
+the datetime and timedelta datatypes have to decide on the correct parameter
+for the operation and output array.
+This step also needs to double check that all casts can be performed safely,
+which by default means that they are "same kind" casts.
+
+Issues and Discussion
+"""""""""""""""""""""
+
+Fixing the correct output dtype is currently part of the type resolution.
+However, it is a distinct step and should probably be handled as such after
+the actual type/loop resolution has occurred.
+
+As such this step may move from the dispatching step (described above) to
+the implementation-specific code described below.
+
+
+DType-specific Implementation of the UFunc
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Once the correct implementation/loop is found, UFuncs currently call
+a single *inner-loop function* which is written in C.
+This may be called multiple times to do the full calculation and it has
+little or no information about the current context. It also has a void
+return value.
+
+Issues and Discussion
+"""""""""""""""""""""
+
+Parametric datatypes may require passing
+additional information to the inner-loop function to decide how to interpret
+the data.
+This is the reason why currently no universal functions for ``string`` dtypes
+exist (although technically possible within NumPy itself).
+Note that it is currently possible to pass in the input array objects
+(which in turn hold the datatypes when no casting is necessary).
+However, the full array information should not be required and currently the
+arrays are passed in before any casting occurs.
+The feature is unused within NumPy and no known user exists.
+
+Another issue is the error reporting from within the inner-loop function.
+There exist currently two ways to do this:
+
+1. by setting a Python exception
+2. using the CPU floating point error flags.
+
+Both of these are checked before returning to the user.
+However, many integer functions currently can set neither of these errors,
+so that checking the floating point error flags is unnecessary overhead.
+On the other hand, there is no way to stop the iteration or pass out error
+information which does not use the floating point flags or requires to hold
+the Python global interpreter lock (GIL).
+
+It seems necessary to provide more control to authors of inner loop functions.
+This means allowing users to pass in and out information from the inner-loop
+function more easily, while *not* providing the input array objects.
+Most likely this will involve:
+
+* Allowing the execution of additional code before the first and after
+  the last inner-loop call.
+* Returning an integer value from the inner-loop to allow stopping the
+  iteration early and possibly propagate error information.
+* Possibly, to allow specialized inner-loop selections. For example currently
+  ``matmul`` and many reductions will execute optimized code for certain inputs.
+  It may make sense to allow selecting such optimized loops beforehand.
+  Allowing this may also help to bring casting (which uses this heavily) and
+  ufunc implementations closer.
+
+The issues surrounding the inner-loop functions have been discussed in some
+detail in the github issue gh-12518_ .
+
+Reductions use an "identity" value.
+This is currently defined once per ufunc, regardless of the ufunc dtype signature.
+For example  ``0`` is used for ``sum``, or ``math.inf`` for ``min``.
+This works well for numerical datatypes, but is not always appropriate for other dtypes.
+In general it should be possible to provide a dtype-specific identity to the
+ufunc reduction.
+
+
+Datatype Discovery during Array Coercion
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+When calling ``np.array(...)`` to coerce a general Python object to a NumPy array,
+all objects need to be inspected to find the correct dtype.
+The input to ``np.array()`` are potentially nested Python sequences which hold
+the final elements as generic Python objects.
+NumPy has to unpack all the nested sequences and then inspect the elements.
+The final datatype is found by iterating over all elements which will end up
+in the array and:
+
+1. discovering the dtype of the single element:
+
+   * from array (or array like) or NumPy scalar using ``element.dtype``
+   * using ``isinstance(..., float)`` for known Python types
+     (note that these rules mean that subclasses are *currently* valid).
+   * special rule for void datatypes to coerce tuples.
+
+2. Promoting the current dtype with the next elements dtype using
+   ``np.promote_types``.
+3. If strings are found, the whole process is restarted (see also [gh-15327]_),
+   in a similar manner as if ``dtype="S"`` was given (see below).
+
+If ``dtype=...`` is given, this dtype is used unmodified, unless
+it is an unspecific *parametric dtype instance* which means "S0", "V0", "U0",
+"datetime64", and "timdelta64".
+These are thus flexible datatypes without length 0 â€“ considered to be unsized â€“
+and datetimes or timedelta without a unit attached ("generic unit").
+
+In future DType class hierarchy, these may be represented by the class rather
+than a special instance, since these special instances should not normally be
+attached to an array.
+
+If such a *parametric dtype instance* is provided for example using ``dtype="S"``
+``PyArray_AdaptFlexibleDType`` is called and effectively inspects all values
+using DType specific logic.
+That is:
+
+* Strings will use ``str(element)`` to find the length of most elements
+* Datetime64 is capable of coercing from strings and guessing the correct unit.
+
+
+Discussion and Issues
+"""""""""""""""""""""
+
+It seems probable that during normal discovery, the ``isinstance`` should rather
+be strict ``type(element) is desired_type`` checks.
+Further, the current ``AdaptFlexibleDType`` logic should be made available to
+user DTypes and not be a secondary step, but instead replace, or be part of,
+the normal discovery.
+
+
+
+Related Issues
+--------------
+
+``np.save`` currently translates all user-defined dtypes to void dtypes.
+This means they cannot be stored using the ``npy`` format.
+This is not an issue for the python pickle protocol, although it may require
+some thought if we wish to ensure that such files can be loaded securely
+without the possibility of executing malicious code
+(i.e. without the ``allow_pickle=True`` keyword argument).
+
+The additional existence of masked arrays and especially masked datatypes
+within Pandas has interesting implications for interoperability.
+Since mask information is often stored separately, its handling requires
+support by the container (array) object.
+NumPy itself does not provide such support, and is not expected to add it
+in the foreseeable future.
+However, if such additions to the datatypes within NumPy would improve
+interoperability they could be considered even if
+they are not used by NumPy itself.
+
+
+Related Work
+------------
+
+* Julia types are an interesting blueprint for a type hierarchy, and define
+  abstract and concrete types [julia-types]_. 
+
+* In Julia promotion can occur based on abstract types. If a promoter is
+  defined, it will cast the inputs and then Julia can then retry to find
+  an implementation with the new values [julia-promotion]_.
+
+* ``xnd-project`` (https://github.com/xnd-project) with ndtypes and gumath
+
+  * The ``xnd-project`` is similar to NumPy and defines data types as well
+    as the possibility to extend them. A major difference is that it does
+    not use promotion/casting within the ufuncs, but instead requires explicit
+    definition of ``int32 + float64 -> float64`` loops.
+
+
+
+Discussion
+----------
+
+There have been many discussions about the current state and what a future
+datatype system may look like.
+The full list of these discussion is long and some are lost to time,
+the following provides a subset for more recent ones:
+
+* Draft NEP by Stephan Hoyer after a developer meeting (was updated on the next developer meeting) https://hackmd.io/6YmDt_PgSVORRNRxHyPaNQ
+
+* List of related documents gathered previously here
+  https://hackmd.io/UVOtgj1wRZSsoNQCjkhq1g (TODO: Reduce to the most important
+  ones):
+
+  * https://github.com/numpy/numpy/pull/12630
+    Matti Picus draft NEP, discusses the technical side of subclassing  more from
+    the side of ``ArrFunctions``
+
+  * https://hackmd.io/ok21UoAQQmOtSVk6keaJhw and https://hackmd.io/s/ryTFaOPHE
+    (2019-04-30) Proposals for subclassing implementation approach.
+  
+  * Discussion about the calling convention of ufuncs and need for more
+    powerful UFuncs: https://github.com/numpy/numpy/issues/12518
+
+  * 2018-11-30 developer meeting notes:
+    https://github.com/BIDS-numpy/docs/blob/master/meetings/2018-11-30-dev-meeting.md
+    and subsequent draft for an NEP: https://hackmd.io/6YmDt_PgSVORRNRxHyPaNQ
+
+    BIDS Meeting on November 30, 2018 and document by Stephan Hoyer about
+    what numpy should provide and thoughts of how to get there. Meeting with
+    Eric Wieser, Matti Picus, Charles Harris, Tyler Reddy, Stéfan van der
+    Walt, and Travis Oliphant.
+
+  * SciPy 2018 brainstorming session with summaries of use cases:
+    https://github.com/numpy/numpy/wiki/Dtype-Brainstorming
+
+    Also lists some requirements and some ideas on implementations
+
+
+
+References
+----------
+
+.. _gh-12518: https://github.com/numpy/numpy/issues/12518
+.. [gh-15327] https://github.com/numpy/numpy/issues/12518
+
+.. [julia-types] https://docs.julialang.org/en/v1/manual/types/index.html#Abstract-Types-1
+
+.. [julia-promotion] https://docs.julialang.org/en/v1/manual/conversion-and-promotion/
+
+
+
+Copyright
+---------
+
+This document has been placed in the public domain.
diff --git a/doc/neps/nep-0041-improved-dtype-support.rst b/doc/neps/nep-0041-improved-dtype-support.rst
new file mode 100644 (file)
index 0000000..56ff5ea
--- /dev/null
@@ -0,0 +1,762 @@
+.. _NEP41:
+
+=================================================
+NEP 41 â€” First step towards a new Datatype System
+=================================================
+
+:title: First step towards a new Datatype System
+:Author: Sebastian Berg
+:Author: Stéfan van der Walt
+:Author: Matti Picus
+:Status: Accepted
+:Type: Standard Track
+:Created: 2020-02-03
+:Resolution: https://mail.python.org/pipermail/numpy-discussion/2020-April/080573.html and https://mail.python.org/pipermail/numpy-discussion/2020-March/080495.html
+
+.. note::
+
+    This NEP is part of a series of NEPs encompassing first information
+    about the previous dtype implementation and issues with it in
+    :ref:`NEP 40 <NEP40>`.
+    NEP 41 (this document) then provides an overview and generic design
+    choices for the refactor.
+    Further NEPs 42 and 43 go into the technical details of the datatype
+    and universal function related internal and external API changes.
+    In some cases it may be necessary to consult the other NEPs for a full
+    picture of the desired changes and why these changes are necessary.
+
+
+Abstract
+--------
+
+:ref:`Datatypes <arrays.dtypes>` in NumPy describe how to interpret each
+element in arrays. NumPy provides ``int``, ``float``, and ``complex`` numerical
+types, as well as string, datetime, and structured datatype capabilities.
+The growing Python community, however, has need for more diverse datatypes.
+Examples are datatypes with unit information attached (such as meters) or
+categorical datatypes (fixed set of possible values).
+However, the current NumPy datatype API is too limited to allow the creation
+of these.
+
+This NEP is the first step to enable such growth; it will lead to
+a simpler development path for new datatypes.
+In the long run the new datatype system will also support the creation
+of datatypes directly from Python rather than C.
+Refactoring the datatype API will improve maintainability and facilitate
+development of both user-defined external datatypes,
+as well as new features for existing datatypes internal to NumPy.
+
+
+Motivation and Scope
+--------------------
+
+.. seealso::
+
+    The user impact section includes examples of what kind of new datatypes
+    will be enabled by the proposed changes in the long run.
+    It may thus help to read these section out of order.
+
+Motivation
+^^^^^^^^^^
+
+One of the main issues with the current API is the definition of typical
+functions such as addition and multiplication for parametric datatypes
+(see also :ref:`NEP 40 <NEP40>`)
+which require additional steps to determine the output type.
+For example when adding two strings of length 4, the result is a string
+of length 8, which is different from the input.
+Similarly, a datatype which embeds a physical unit must calculate the new unit
+information: dividing a distance by a time results in a speed.
+A related difficulty is that the :ref:`current casting rules <ufuncs.casting>`
+-- the conversion between different datatypes --
+cannot describe casting for such parametric datatypes implemented outside of NumPy.
+
+This additional functionality for supporting parametric datatypes introduces
+increased complexity within NumPy itself,
+and furthermore is not available to external user-defined datatypes.
+In general the concerns of different datatypes are not well well-encapsulated.
+This burden is exacerbated by the exposure of internal C structures,
+limiting the addition of new fields
+(for example to support new sorting methods [new_sort]_).
+
+Currently there are many factors which limit the creation of new user-defined
+datatypes:
+
+* Creating casting rules for parametric user-defined dtypes is either impossible
+  or so complex that it has never been attempted.
+* Type promotion, e.g. the operation deciding that adding float and integer
+  values should return a float value, is very valuable for numeric datatypes
+  but is limited in scope for user-defined and especially parametric datatypes.
+* Much of the logic (e.g. promotion) is written in single functions
+  instead of being split as methods on the datatype itself.
+* In the current design datatypes cannot have methods that do not generalize
+  to other datatypes. For example a unit datatype cannot have a ``.to_si()`` method to
+  easily find the datatype which would represent the same values in SI units.
+
+The large need to solve these issues has driven the scientific community
+to create work-arounds in multiple projects implementing physical units as an
+array-like class instead of a datatype, which would generalize better across
+multiple array-likes (Dask, pandas, etc.).
+Already, Pandas has made a push into the same direction with its
+extension arrays [pandas_extension_arrays]_ and undoubtedly
+the community would be best served if such new features could be common
+between NumPy, Pandas, and other projects.
+
+Scope
+^^^^^
+
+The proposed refactoring of the datatype system is a large undertaking and
+thus is proposed to be split into various phases, roughly:
+
+* Phase I: Restructure and extend the datatype infrastructure (This NEP 41)
+* Phase II: Incrementally define or rework API (Detailed largely in NEPs 42/43)
+* Phase III: Growth of NumPy and Scientific Python Ecosystem capabilities.
+
+For a more detailed accounting of the various phases, see
+"Plan to Approach the Full Refactor" in the Implementation section below.
+This NEP proposes to move ahead with the necessary creation of new dtype
+subclasses (Phase I),
+and start working on implementing current functionality.
+Within the context of this NEP all development will be fully private API or
+use preliminary underscored names which must be changed in the future.
+Most of the internal and public API choices are part of a second Phase
+and will be discussed in more detail in the following NEPs 42 and 43.
+The initial implementation of this NEP will have little or no effect on users,
+but provides the necessary ground work for incrementally addressing the
+full rework.
+
+The implementation of this NEP and the following, implied large rework of how
+datatypes are defined in NumPy is expected to create small incompatibilities
+(see backward compatibility section).
+However, a transition requiring large code adaption is not anticipated and not
+within scope.
+
+Specifically, this NEP makes the following design choices which are discussed
+in more details in the detailed description section:
+
+1. Each datatype will be an instance of a subclass of ``np.dtype``, with most of the
+   datatype-specific logic being implemented
+   as special methods on the class. In the C-API, these correspond to specific
+   slots. In short, for ``f = np.dtype("f8")``, ``isinstance(f, np.dtype)`` will remain true,
+   but ``type(f)`` will be a subclass of ``np.dtype`` rather than just ``np.dtype`` itself.
+   The ``PyArray_ArrFuncs`` which are currently stored as a pointer on the instance (as ``PyArray_Descr->f``),
+   should instead be stored on the class as typically done in Python.
+   In the future these may correspond to python side dunder methods.
+   Storage information such as itemsize and byteorder can differ between
+   different dtype instances (e.g. "S3" vs. "S8") and will remain part of the instance.
+   This means that in the long run the current lowlevel access to dtype methods
+   will be removed (see ``PyArray_ArrFuncs`` in
+   :ref:`NEP 40 <NEP40>`).
+
+2. The current NumPy scalars will *not* change, they will not be instances of
+   datatypes. This will also be true for new datatypes, scalars will not be
+   instances of a dtype (although ``isinstance(scalar, dtype)`` may be made
+   to return ``True`` when appropriate).
+
+Detailed technical decisions to follow in NEP 42.
+
+Further, the public API will be designed in a way that is extensible in the future:
+
+3. All new C-API functions provided to the user will hide implementation details
+   as much as possible. The public API should be an identical, but limited,
+   version of the C-API used for the internal NumPy datatypes.
+
+The datatype system may be targeted to work with NumPy arrays,
+for example by providing strided-loops, but should avoid direct
+interactions with the array-object (typically `np.ndarray` instances).
+Instead, the design principle will be that the array-object is a consumer
+of the datatype.
+While only a guiding principle, this may allow splitting the datatype system
+or even the NumPy datatypes into their own project which NumPy depends on.
+
+The changes to the datatype system in Phase II must include a large refactor of the
+UFunc machinery, which will be further defined in NEP 43:
+
+4. To enable all of the desired functionality for new user-defined datatypes,
+   the UFunc machinery will be changed to replace the current dispatching
+   and type resolution system.
+   The old system should be *mostly* supported as a legacy version for some time.
+
+Additionally, as a general design principle, the addition of new user-defined
+datatypes will *not* change the behaviour of programs.
+For example ``common_dtype(a, b)`` must not be ``c`` unless ``a`` or ``b`` know
+that ``c`` exists.
+
+
+User Impact
+-----------
+
+The current ecosystem has very few user-defined datatypes using NumPy, the
+two most prominent being: ``rational`` and ``quaternion``.
+These represent fairly simple datatypes which are not strongly impacted
+by the current limitations.
+However, we have identified a need for datatypes such as:
+
+* bfloat16, used in deep learning
+* categorical types
+* physical units (such as meters)
+* datatypes for tracing/automatic differentiation
+* high, fixed precision math
+* specialized integer types such as int2, int24
+* new, better datetime representations
+* extending e.g. integer dtypes to have a sentinel NA value
+* geometrical objects [pygeos]_
+
+Some of these are partially solved; for example unit capability is provided
+in ``astropy.units``, ``unyt``, or ``pint``, as `numpy.ndarray` subclasses.
+Most of these datatypes, however, simply cannot be reasonably defined
+right now.
+An advantage of having such datatypes in NumPy is that they should integrate
+seamlessly with other array or array-like packages such as Pandas,
+``xarray`` [xarray_dtype_issue]_, or ``Dask``.
+
+The long term user impact of implementing this NEP will be to allow both
+the growth of the whole ecosystem by having such new datatypes, as well as
+consolidating implementation of such datatypes within NumPy to achieve
+better interoperability.
+
+
+Examples
+^^^^^^^^
+
+The following examples represent future user-defined datatypes we wish to enable.
+These datatypes are not part the NEP and choices (e.g. choice of casting rules)
+are possibilities we wish to enable and do not represent recommendations.
+
+Simple Numerical Types
+""""""""""""""""""""""
+
+Mainly used where memory is a consideration, lower-precision numeric types
+such as `bfloat16 <https://en.wikipedia.org/wiki/Bfloat16_floating-point_format>`_
+are common in other computational frameworks.
+For these types the definitions of things such as ``np.common_type`` and
+``np.can_cast`` are some of the most important interfaces. Once they
+support ``np.common_type``, it is (for the most part) possible to find
+the correct ufunc loop to call, since most ufuncs -- such as add -- effectively
+only require ``np.result_type``::
+
+    >>> np.add(arr1, arr2).dtype == np.result_type(arr1, arr2)
+
+and `~numpy.result_type` is largely identical to `~numpy.common_type`.
+
+
+Fixed, high precision math
+""""""""""""""""""""""""""
+
+Allowing arbitrary precision or higher precision math is important in
+simulations. For instance ``mpmath`` defines a precision::
+
+    >>> import mpmath as mp
+    >>> print(mp.dps)  # the current (default) precision
+    15
+
+NumPy should be able to construct a native, memory-efficient array from
+a list of ``mpmath.mpf`` floating point objects::
+
+    >>> arr_15_dps = np.array(mp.arange(3))  # (mp.arange returns a list)
+    >>> print(arr_15_dps)  # Must find the correct precision from the objects:
+    array(['0.0', '1.0', '2.0'], dtype=mpf[dps=15])
+
+We should also be able to specify the desired precision when
+creating the datatype for an array. Here, we use ``np.dtype[mp.mpf]``
+to find the DType class (the notation is not part of this NEP),
+which is then instantiated with the desired parameter.
+This could also be written as ``MpfDType`` class::
+
+    >>> arr_100_dps = np.array([1, 2, 3], dtype=np.dtype[mp.mpf](dps=100))
+    >>> print(arr_15_dps + arr_100_dps)
+    array(['0.0', '2.0', '4.0'], dtype=mpf[dps=100])
+
+The ``mpf`` datatype can decide that the result of the operation should be the
+higher precision one of the two, so uses a precision of 100.
+Furthermore, we should be able to define casting, for example as in::
+
+    >>> np.can_cast(arr_15_dps.dtype, arr_100_dps.dtype, casting="safe")
+    True
+    >>> np.can_cast(arr_100_dps.dtype, arr_15_dps.dtype, casting="safe")
+    False  # loses precision
+    >>> np.can_cast(arr_100_dps.dtype, arr_100_dps.dtype, casting="same_kind")
+    True
+
+Casting from float is a probably always at least a ``same_kind`` cast, but
+in general, it is not safe::
+
+    >>> np.can_cast(np.float64, np.dtype[mp.mpf](dps=4), casting="safe")
+    False
+
+since a float64 has a higer precision than the ``mpf`` datatype with
+``dps=4``.
+
+Alternatively, we can say that::
+
+    >>> np.common_type(np.dtype[mp.mpf](dps=5), np.dtype[mp.mpf](dps=10))
+    np.dtype[mp.mpf](dps=10)
+
+And possibly even::
+
+    >>> np.common_type(np.dtype[mp.mpf](dps=5), np.float64)
+    np.dtype[mp.mpf](dps=16)  # equivalent precision to float64 (I believe)
+
+since ``np.float64`` can be cast to a ``np.dtype[mp.mpf](dps=16)`` safely.
+
+
+Categoricals
+""""""""""""
+
+Categoricals are interesting in that they can have fixed, predefined values,
+or can be dynamic with the ability to modify categories when necessary.
+The fixed categories (defined ahead of time) is the most straight forward
+categorical definition.
+Categoricals are *hard*, since there are many strategies to implement them,
+suggesting NumPy should only provide the scaffolding for user-defined
+categorical types. For instance::
+
+    >>> cat = Categorical(["eggs", "spam", "toast"])
+    >>> breakfast = array(["eggs", "spam", "eggs", "toast"], dtype=cat)
+
+could store the array very efficiently, since it knows that there are only 3
+categories.
+Since a categorical in this sense knows almost nothing about the data stored
+in it, few operations makes, sense, although equality does:
+
+    >>> breakfast2 = array(["eggs", "eggs", "eggs", "eggs"], dtype=cat)
+    >>> breakfast == breakfast2
+    array[True, False, True, False])
+
+The categorical datatype could work like a dictionary: no two
+items names can be equal (checked on dtype creation), so that the equality
+operation above can be performed very efficiently.
+If the values define an order, the category labels (internally integers) could
+be ordered the same way to allow efficient sorting and comparison.
+
+Whether or not casting is defined from one categorical with less to one with
+strictly more values defined, is something that the Categorical datatype would
+need to decide. Both options should be available.
+
+
+Unit on the Datatype
+""""""""""""""""""""
+
+There are different ways to define Units, depending on how the internal
+machinery would be organized, one way is to have a single Unit datatype
+for every existing numerical type.
+This will be written as ``Unit[float64]``, the unit itself is part of the
+DType instance ``Unit[float64]("m")`` is a ``float64`` with meters attached::
+
+    >>> from astropy import units
+    >>> meters = np.array([1, 2, 3], dtype=np.float64) * units.m  # meters
+    >>> print(meters)
+    array([1.0, 2.0, 3.0], dtype=Unit[float64]("m"))
+
+Note that units are a bit tricky. It is debatable, whether::
+
+    >>> np.array([1.0, 2.0, 3.0], dtype=Unit[float64]("m"))
+
+should be valid syntax (coercing the float scalars without a unit to meters).
+Once the array is created, math will work without any issue::
+
+    >>> meters / (2 * unit.seconds)
+    array([0.5, 1.0, 1.5], dtype=Unit[float64]("m/s"))
+
+Casting is not valid from one unit to the other, but can be valid between
+different scales of the same dimensionality (although this may be "unsafe")::
+
+    >>> meters.astype(Unit[float64]("s"))
+    TypeError: Cannot cast meters to seconds.
+    >>> meters.astype(Unit[float64]("km"))
+    >>> # Convert to centimeter-gram-second (cgs) units:
+    >>> meters.astype(meters.dtype.to_cgs())
+
+The above notation is somewhat clumsy. Functions
+could be used instead to convert between units.
+There may be ways to make these more convenient, but those must be left
+for future discussions::
+
+    >>> units.convert(meters, "km")
+    >>> units.to_cgs(meters)
+
+There are some open questions. For example, whether additional methods
+on the array object could exist to simplify some of the notions, and how these
+would percolate from the datatype to the ``ndarray``.
+
+The interaction with other scalars would likely be defined through::
+
+    >>> np.common_type(np.float64, Unit)
+    Unit[np.float64](dimensionless)
+
+Ufunc output datatype determination can be more involved than for simple
+numerical dtypes since there is no "universal" output type::
+
+    >>> np.multiply(meters, seconds).dtype != np.result_type(meters, seconds)
+
+In fact ``np.result_type(meters, seconds)`` must error without context
+of the operation being done.
+This example highlights how the specific ufunc loop
+(loop with known, specific DTypes as inputs), has to be able to make
+certain decisions before the actual calculation can start.
+
+
+
+Implementation
+--------------
+
+Plan to Approach the Full Refactor
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+To address these issues in NumPy and enable new datatypes,
+multiple development stages are required:
+
+* Phase I: Restructure and extend the datatype infrastructure (This NEP)
+
+  * Organize Datatypes like normal Python classes [`PR 15508`]_
+
+* Phase II: Incrementally define or rework API
+
+  * Create a new and easily extensible API for defining new datatypes
+    and related functionality. (NEP 42)
+
+  * Incrementally define all necessary functionality through the new API (NEP 42):
+
+    * Defining operations such as ``np.common_type``.
+    * Allowing to define casting between datatypes.
+    * Add functionality necessary to create a numpy array from Python scalars
+      (i.e. ``np.array(...)``).
+    * â€¦
+
+  * Restructure how universal functions work (NEP 43), in order to:
+
+    * make it possible to allow a `~numpy.ufunc` such as ``np.add`` to be
+      extended by user-defined datatypes such as Units.
+
+    * allow efficient lookup for the correct implementation for user-defined
+      datatypes.
+
+    * enable reuse of existing code. Units should be able to use the
+      normal math loops and add additional logic to determine output type.
+
+* Phase III: Growth of NumPy and Scientific Python Ecosystem capabilities:
+
+  * Cleanup of legacy behaviour where it is considered buggy or undesirable.
+  * Provide a path to define new datatypes from Python.
+  * Assist the community in creating types such as Units or Categoricals
+  * Allow strings to be used in functions such as ``np.equal`` or ``np.add``.
+  * Remove legacy code paths within NumPy to improve long term maintainability
+
+This document serves as a basis for phase I and provides the vision and
+motivation for the full project.
+Phase I does not introduce any new user-facing features,
+but is concerned with the necessary conceptual cleanup of the current datatype system.
+It provides a more "pythonic" datatype Python type object, with a clear class hierarchy.
+
+The second phase is the incremental creation of all APIs necessary to define
+fully featured datatypes and reorganization of the NumPy datatype system.
+This phase will thus be primarily concerned with defining an,
+initially preliminary, stable public API.
+
+Some of the benefits of a large refactor may only become evident after the full
+deprecation of the current legacy implementation (i.e. larger code removals).
+However, these steps are necessary for improvements to many parts of the
+core NumPy API, and are expected to make the implementation generally
+easier to understand.
+
+The following figure illustrates the proposed design at a high level,
+and roughly delineates the components of the overall design.
+Note that this NEP only regards Phase I (shaded area),
+the rest encompasses Phase II and the design choices are up for discussion,
+however, it highlights that the DType datatype class is the central, necessary
+concept:
+
+.. image:: _static/nep-0041-mindmap.svg
+
+
+First steps directly related to this NEP
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The required changes necessary to NumPy are large and touch many areas
+of the code base
+but many of these changes can be addressed incrementally.
+
+To enable an incremental approach we will start by creating a C defined
+``PyArray_DTypeMeta`` class with its instances being the ``DType`` classes,
+subclasses of ``np.dtype``.
+This is necessary to add the ability of storing custom slots on the DType in C.
+This ``DTypeMeta`` will be implemented first to then enable incremental
+restructuring of current code.
+
+The addition of ``DType`` will then enable addressing other changes
+incrementally, some of which may begin before the settling the full internal
+API:
+
+1. New machinery for array coercion, with the goal of enabling user DTypes
+   with appropriate class methods.
+2. The replacement or wrapping of the current casting machinery.
+3. Incremental redefinition of the current ``PyArray_ArrFuncs`` slots into
+   DType method slots.
+
+At this point, no or only very limited new public API will be added and
+the internal API is considered to be in flux.
+Any new public API may be set up give warnings and will have leading underscores
+to indicate that it is not finalized and can be changed without warning.
+
+
+Backward compatibility
+----------------------
+
+While the actual backward compatibility impact of implementing Phase I and II
+are not yet fully clear, we anticipate, and accept the following changes:
+
+* **Python API**:
+
+  * ``type(np.dtype("f8"))`` will be a subclass of ``np.dtype``, while right
+    now ``type(np.dtype("f8")) is np.dtype``.
+    Code should use ``isinstance`` checks, and in very rare cases may have to
+    be adapted to use it.
+
+* **C-API**:
+
+    * In old versions of NumPy ``PyArray_DescrCheck`` is a macro which uses
+      ``type(dtype) is np.dtype``. When compiling against an old NumPy version,
+      the macro may have to be replaced with the corresponding
+      ``PyObject_IsInstance`` call. (If this is a problem, we could backport
+      fixing the macro)
+
+   * The UFunc machinery changes will break *limited* parts of the current
+     implementation. Replacing e.g. the default ``TypeResolver`` is expected
+     to remain supported for a time, although optimized masked inner loop iteration
+     (which is not even used *within* NumPy) will no longer be supported.
+
+   * All functions currently defined on the dtypes, such as
+     ``PyArray_Descr->f->nonzero``, will be defined and accessed differently.
+     This means that in the long run lowlevel access code will
+     have to be changed to use the new API. Such changes are expected to be
+     necessary in very few project.
+
+* **dtype implementors (C-API)**:
+
+  * The array which is currently provided to some functions (such as cast functions),
+    will no longer be provided.
+    For example ``PyArray_Descr->f->nonzero`` or ``PyArray_Descr->f->copyswapn``,
+    may instead receive a dummy array object with only some fields (mainly the
+    dtype), being valid.
+    At least in some code paths, a similar mechanism is already used.
+
+  * The ``scalarkind`` slot and registration of scalar casting will be
+     removed/ignored without replacement.
+     It currently allows partial value-based casting.
+     The ``PyArray_ScalarKind`` function will continue to work for builtin types,
+     but will not be used internally and be deprecated.
+
+   * Currently user dtypes are defined as instances of ``np.dtype``.
+     The creation works by the user providing a prototype instance.
+     NumPy will need to modify at least the type during registration.
+     This has no effect for either ``rational`` or ``quaternion`` and mutation
+     of the structure seems unlikely after registration.
+
+Since there is a fairly large API surface concerning datatypes, further changes
+or the limitation certain function to currently existing datatypes is
+likely to occur.
+For example functions which use the type number as input
+should be replaced with functions taking DType classes instead.
+Although public, large parts of this C-API seem to be used rarely,
+possibly never, by downstream projects.
+
+
+
+Detailed Description
+--------------------
+
+This section details the design decisions covered by this NEP.
+The subsections correspond to the list of design choices presented
+in the Scope section.
+
+Datatypes as Python Classes (1)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The current NumPy datatypes are not full scale python classes.
+They are instead (prototype) instances of a single ``np.dtype`` class.
+Changing this means that any special handling, e.g. for ``datetime``
+can be moved to the Datetime DType class instead, away from monolithic general
+code (e.g. current ``PyArray_AdjustFlexibleDType``).
+
+The main consequence of this change with respect to the API is that
+special methods move from the dtype instances to methods on the new DType class.
+This is the typical design pattern used in Python.
+Organizing these methods and information in a more Pythonic way provides a
+solid foundation for refining and extending the API in the future.
+The current API cannot be extended due to how it is exposed publically.
+This means for example that the methods currently stored in ``PyArray_ArrFuncs``
+on each datatype (see :ref:`NEP 40 <NEP40>`)
+will be defined differently in the future and
+deprecated in the long run.
+
+The most prominent visible side effect of this will be that
+``type(np.dtype(np.float64))`` will not be ``np.dtype`` anymore.
+Instead it will be a subclass of ``np.dtype`` meaning that
+``isinstance(np.dtype(np.float64), np.dtype)`` will remain true.
+This will also add the ability to use ``isinstance(dtype, np.dtype[float64])``
+thus removing the need to use ``dtype.kind``, ``dtype.char``, or ``dtype.type``
+to do this check.
+
+With the design decision of DTypes as full-scale Python classes,
+the question of subclassing arises.
+Inheritance, however, appears problematic and a complexity best avoided
+(at least initially) for container datatypes.
+Further, subclasses may be more interesting for interoperability for
+example with GPU backends (CuPy) storing additional methods related to the
+GPU rather than as a mechanism to define new datatypes.
+A class hierarchy does provides value, and one can be achieved by
+allowing the creation of *abstract* datatypes.
+An example for an abstract datatype would be the datatype equivalent of
+``np.floating``, representing any floating point number.
+These can serve the same purpose as Python's abstract base classes.
+
+This NEP chooses to duplicate the scalar hierarchy fully or in part.
+The main reason is to uncouple the implementation of the DType and scalar.
+To add a DType to NumPy, in theory the scalar will not need to be
+modified or know about NumPy. Also note that the categorical DType as
+currently implemented in pandas does not have a scalar correspondence
+making it less straight forward to rely on scalars to implement behaviour.
+While DType and Scalar describe the same concept/type (e.g. an `int64`),
+it seems practical to split out the information and functionality necessary
+for numpy into the DType class.
+
+
+Scalars should not be instances of the datatypes (2)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+For simple datatypes such as ``float64`` (see also below), it seems
+tempting that the instance of a ``np.dtype("float64")`` can be the scalar.
+This idea may be even more appealing due to the fact that scalars,
+rather than datatypes, currently define a useful type hierarchy.
+
+However, we have specifically decided against this for a number of reasons.
+First, the new datatypes described herein would be instances of DType classes.
+Making these instances themselves classes, while possible, adds additional
+complexity that users need to understand.
+It would also mean that scalars must have storage information (such as byteorder)
+which is generally unnecessary and currently is not used.
+Second, while the simple NumPy scalars such as ``float64`` may be such instances,
+it should be possible to create datatypes for Python objects without enforcing
+NumPy as a dependency.
+However, Python objects that do not depend on NumPy cannot be instances of a NumPy DType.
+Third, there is a mismatch between the methods and attributes which are useful
+for scalars and datatypes. For instance ``to_float()`` makes sense for a scalar
+but not for a datatype and ``newbyteorder`` is not useful on a scalar (or has
+a different meaning).
+
+Overall, it seem rather than reducing the complexity, i.e. by merging
+the two distinct type hierarchies, making scalars instances of DTypes would
+increase the complexity of both the design and implementation.
+
+A possible future path may be to instead simplify the current NumPy scalars to
+be much simpler objects which largely derive their behaviour from the datatypes.
+
+C-API for creating new Datatypes (3)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The current C-API with which users can create new datatypes
+is limited in scope, and requires use of "private" structures. This means
+the API is not extensible: no new members can be added to the structure
+without losing binary compatibility.
+This has already limited the inclusion of new sorting methods into
+NumPy [new_sort]_.
+
+The new version shall thus replace the current ``PyArray_ArrFuncs`` structure used
+to define new datatypes.
+Datatypes that currently exist and are defined using these slots will be
+supported during a deprecation period.
+
+The most likely solution is to hide the implementation from the user and thus make
+it extensible in the future is to model the API after Python's stable
+API [PEP-384]_:
+
+.. code-block:: C
+
+    static struct PyArrayMethodDef slots[] = {
+        {NPY_dt_method, method_implementation},
+        ...,
+        {0, NULL}
+    }
+
+    typedef struct{
+      PyTypeObject *typeobj;  /* type of python scalar */
+      ...;
+      PyType_Slot *slots;
+    } PyArrayDTypeMeta_Spec;
+
+    PyObject* PyArray_InitDTypeMetaFromSpec(
+            PyArray_DTypeMeta *user_dtype, PyArrayDTypeMeta_Spec *dtype_spec);
+
+The C-side slots should be designed to mirror Python side methods
+such as ``dtype.__dtype_method__``, although the exposure to Python is
+a later step in the implementation to reduce the complexity of the initial
+implementation.
+
+
+C-API Changes to the UFunc Machinery (4)
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Proposed changes to the UFunc machinery will be part of NEP 43.
+However, the following changes will be necessary
+(see :ref:`NEP 40 <NEP40>`
+for a detailed description of the current implementation and its issues):
+
+* The current UFunc type resolution must be adapted to allow better control
+  for user-defined dtypes as well as resolve current inconsistencies.
+* The inner-loop used in UFuncs must be expanded to include a return value.
+  Further, error reporting must be improved, and passing in dtype-specific
+  information enabled.
+  This requires the modification of the inner-loop function signature and
+  addition of new hooks called before and after the inner-loop is used.
+
+An important goal for any changes to the universal functions will be to
+allow the reuse of existing loops.
+It should be easy for a new units datatype to fall back to existing math
+functions after handling the unit related computations.
+
+
+Discussion
+----------
+
+See :ref:`NEP 40 <NEP40>`
+for a list of previous meetings and discussions.
+
+Additional discussion around this specific NEP has occured on both
+the mailing list and the pull request:
+
+* `Mailing list discussion <https://mail.python.org/pipermail/numpy-discussion/2020-March/080481.html>`_
+* `NEP 41 pull request <https://github.com/numpy/numpy/pull/15506>`_
+* `Pull request thread on Dtype hierarchy and Scalars <https://github.com/numpy/numpy/pull/15506#discussion_r390016298>`_
+
+
+References
+----------
+
+.. [pandas_extension_arrays] https://pandas.pydata.org/pandas-docs/stable/development/extending.html#extension-types
+
+.. [xarray_dtype_issue] https://github.com/pydata/xarray/issues/1262
+
+.. [pygeos] https://github.com/caspervdw/pygeos
+
+.. [new_sort] https://github.com/numpy/numpy/pull/12945
+
+.. [PEP-384] https://www.python.org/dev/peps/pep-0384/
+
+.. [PR 15508] https://github.com/numpy/numpy/pull/15508
+
+
+Copyright
+---------
+
+This document has been placed in the public domain.
+
+
+Acknowledgments
+---------------
+
+The effort to create new datatypes for NumPy has been discussed for several
+years in many different contexts and settings, making it impossible to list everyone involved.
+We would like to thank especially Stephan Hoyer, Nathaniel Smith, and Eric Wieser
+for repeated in-depth discussion about datatype design.
+We are very grateful for the community input in reviewing and revising this
+NEP and would like to thank especially Ross Barnowski and Ralf Gommers.
diff --git a/doc/neps/nep-0044-restructuring-numpy-docs.rst b/doc/neps/nep-0044-restructuring-numpy-docs.rst
new file mode 100644 (file)
index 0000000..87da4ed
--- /dev/null
@@ -0,0 +1,243 @@
+===================================================
+NEP 44 â€” Restructuring the NumPy Documentation
+===================================================
+
+:Author: Ralf Gommers
+:Author: Melissa Mendonça
+:Author: Mars Lee
+:Status: Accepted
+:Type: Process
+:Created: 2020-02-11
+:Resolution: https://mail.python.org/pipermail/numpy-discussion/2020-March/080467.html
+
+Abstract
+========
+
+This document proposes a restructuring of the NumPy Documentation, both in form
+and content, with the goal of making it more organized and discoverable for
+beginners and experienced users.
+
+Motivation and Scope
+====================
+
+See `here <https://numpy.org/devdocs/>`_ for the front page of the latest docs.
+The organization is quite confusing and illogical (e.g. user and developer docs
+are mixed). We propose the following:
+
+- Reorganizing the docs into the four categories mentioned in [1]_, namely *Tutorials*, *How Tos*, *Reference Guide* and *Explanations* (more about this below).
+- Creating dedicated sections for Tutorials and How-Tos, including orientation
+  on how to create new content;
+- Adding an Explanations section for key concepts and techniques that require
+  deeper descriptions, some of which will be rearranged from the Reference Guide.
+
+Usage and Impact
+================
+
+The documentation is a fundamental part of any software project, especially
+open source projects. In the case of NumPy, many beginners might feel demotivated
+by the current structure of the documentation, since it is difficult to discover
+what to learn (unless the user has a clear view of what to look for in the
+Reference docs, which is not always the case).
+
+Looking at the results of a "NumPy Tutorial" search on any search engine also
+gives an idea of the demand for this kind of content. Having official high-level
+documentation written using up-to-date content and techniques will certainly
+mean more users (and developers/contributors) are involved in the NumPy
+community.
+
+Backward compatibility
+======================
+
+The restructuring will effectively demand a complete rewrite of links and some
+of the current content. Input from the community will be useful for identifying
+key links and pages that should not be broken.
+
+Detailed description
+====================
+
+As discussed in the article [1]_, there are four categories of doc content:
+
+- Tutorials
+- How-to guides
+- Explanations
+- Reference guide
+
+We propose to use those categories as the ones we use (for writing and
+reviewing) whenever we add a new documentation section.
+
+The reasoning for this is that it is clearer both for
+developers/documentation writers and to users where each piece of
+information should go, and the scope and tone of each document. For
+example, if explanations are mixed with basic tutorials, beginners
+might be overwhelmed and alienated. On the other hand, if the reference
+guide contains basic how-tos, it might be difficult for experienced
+users to find the information they need, quickly.
+
+Currently, there are many blogs and tutorials on the internet about NumPy or
+using NumPy. One of the issues with this is that if users search for this
+information they may end up in an outdated (unofficial) tutorial before
+they find the current official documentation. This can be especially
+confusing, especially for beginners. Having a better infrastructure for the
+documentation also aims to solve this problem by giving users high-level,
+up-to-date official documentation that can be easily updated.
+
+Status and ideas of each type of doc content
+--------------------------------------------
+
+**Reference guide**
+
+NumPy has a quite complete reference guide. All functions are documented, most
+have examples, and most are cross-linked well with *See Also* sections. Further
+improving the reference guide is incremental work that can be done (and is being
+done) by many people. There are, however, many explanations in the reference
+guide. These can be moved to a more dedicated Explanations section on the docs.
+
+**How-to guides**
+
+NumPy does not have many how-to's. The subclassing and array ducktyping section
+may be an example of a how-to. Others that could be added are:
+
+- Parallelization (controlling BLAS multithreading with ``threadpoolctl``, using
+  multiprocessing, random number generation, etc.)
+- Storing and loading data (``.npy``/``.npz`` format, text formats, Zarr, HDF5,
+  Bloscpack, etc.)
+- Performance (memory layout, profiling, use with Numba, Cython, or Pythran)
+- Writing generic code that works with NumPy, Dask, CuPy, pydata/sparse, etc.
+
+**Explanations**
+
+There is a reasonable amount of content on fundamental NumPy concepts such as
+indexing, vectorization, broadcasting, (g)ufuncs, and dtypes. This could be
+organized better and clarified to ensure it's really about explaining the concepts
+and not mixed with tutorial or how-to like content.
+
+There are few explanations about anything other than those fundamental NumPy
+concepts. 
+
+Some examples of concepts that could be expanded:
+
+- Copies vs. Views;
+- BLAS and other linear algebra libraries; 
+- Fancy indexing.
+
+In addition, there are many explanations in the Reference Guide, which should be
+moved to this new dedicated Explanations section.
+
+**Tutorials**
+
+There's a lot of scope for writing better tutorials. We have a new *NumPy for
+absolute beginners tutorial* [3]_ (GSoD project of Anne Bonner). In addition we
+need a number of tutorials addressing different levels of experience with Python
+and NumPy. This could be done using engaging data sets, ideas or stories. For
+example, curve fitting with polynomials and functions in ``numpy.linalg`` could
+be done with the Keeling curve (decades worth of CO2 concentration in air
+measurements) rather than with synthetic random data.
+
+Ideas for tutorials (these capture the types of things that make sense, they're
+not necessarily the exact topics we propose to implement):
+
+- Conway's game of life with only NumPy (note: already in `Nicolas Rougier's book
+  <https://www.labri.fr/perso/nrougier/from-python-to-numpy/#the-game-of-life>`_)
+- Using masked arrays to deal with missing data in time series measurements
+- Using Fourier transforms to analyze the Keeling curve data, and extrapolate it.
+- Geospatial data (e.g. lat/lon/time to create maps for every year via a stacked
+  array, like `gridMet data <http://www.climatologylab.org/gridmet.html>`_)
+- Using text data and dtypes (e.g. use speeches from different people, shape
+  ``(n_speech, n_sentences, n_words)``)
+
+The *Preparing to Teach* document [2]_ from the Software Carpentry Instructor
+Training materials is a nice summary of how to write effective lesson plans (and
+tutorials would be very similar). In addition to adding new tutorials, we also
+propose a *How to write a tutorial* document, which would help users contribute
+new high-quality content to the documentation.
+
+Data sets
+---------
+
+Using interesting data in the NumPy docs requires giving all users access to
+that data, either inside NumPy or in a separate package. The former is not the
+best idea, since it's hard to do without increasing the size of NumPy
+significantly. Even for SciPy there has so far been no consensus on this (see
+`scipy PR 8707 <https://github.com/scipy/scipy/pull/8707>`_ on adding a new
+``scipy.datasets`` subpackage).
+
+So we'll aim for a new (pure Python) package, named ``numpy-datasets`` or
+``scipy-datasets`` or something similar. That package can take some lessons from
+how, e.g., scikit-learn ships data sets. Small data sets can be included in the
+repo, large data sets can be accessed via a downloader class or function.
+
+Related Work
+============
+
+Some examples of documentation organization in other projects:
+
+- `Documentation for Jupyter <https://jupyter.org/documentation>`_
+- `Documentation for Python <https://docs.python.org/3/>`_
+- `Documentation for TensorFlow <https://www.tensorflow.org/learn>`_
+
+These projects make the intended audience for each part of the documentation
+more explicit, as well as previewing some of the content in each section. 
+
+Implementation
+==============
+
+Currently, the `documentation for NumPy <https://numpy.org/devdocs/>`_ can be
+confusing, especially for beginners. Our proposal is to reorganize the docs in
+the following structure:
+
+- For users:
+    - Absolute Beginners Tutorial
+    - main Tutorials section
+    - How Tos for common tasks with NumPy
+    - Reference Guide (API Reference)
+    - Explanations
+    - F2Py Guide
+    - Glossary
+- For developers/contributors:
+    - Contributor's Guide
+    - Under-the-hood docs
+    - Building and extending the documentation
+    - Benchmarking 
+    - NumPy Enhancement Proposals
+- Meta information
+    - Reporting bugs
+    - Release Notes
+    - About NumPy
+    - License
+
+Ideas for follow-up
+-------------------
+
+Besides rewriting the current documentation to some extent, it would be ideal
+to have a technical infrastructure that would allow more contributions from the
+community. For example, if Jupyter Notebooks could be submitted as-is as
+tutorials or How-Tos, this might create more contributors and broaden the NumPy
+community.
+
+Similarly, if people could download some of the documentation in Notebook
+format, this would certainly mean people would use less outdated material for
+learning NumPy.
+
+It would also be interesting if the new structure for the documentation makes
+translations easier.
+      
+Discussion
+==========
+
+Discussion around this NEP can be found on the NumPy mailing list:
+
+- https://mail.python.org/pipermail/numpy-discussion/2020-February/080419.html
+
+References and Footnotes
+========================
+
+.. [1] `What nobody tells you about documentation <https://www.divio.com/blog/documentation/>`_
+
+.. [2] `Preparing to Teach <https://carpentries.github.io/instructor-training/15-lesson-study/index.html>`_ (from the `Software Carpentry <https://software-carpentry.org/>`_ Instructor Training materials)
+
+.. [3] `NumPy for absolute beginners Tutorial <https://numpy.org/devdocs/user/absolute_beginners.html>`_ by Anne Bonner
+
+Copyright
+=========
+
+This document has been placed in the public domain.
index a675b8c966ef478a15ca0997bf2f124b2cf5584e..93887c4b12ff395e9df43c68355caeb615c0d2fb 100644 (file)
@@ -14,7 +14,8 @@ Here, we describe aspects of N-d array computation that are within scope for Num
 
   - NumPy is a *de facto* standard for array APIs in Python
   - Indexing and fast iteration over elements (ufunc)
-  - Interoperability protocols with other data container implementations (like `__array_ufunc__`).
+  - Interoperability protocols with other data container implementations (like
+    :ref:`__array_ufunc__ and __array_function__ <basics.dispatch>`.
 
 - **Python API and a C API** to the ndarray's methods and attributes.
 
@@ -35,7 +36,8 @@ Here, we describe aspects of N-d array computation that are within scope for Num
 
 - NumPy provides some **infrastructure for other packages in the scientific Python ecosystem**:
 
-  - numpy.distutils (build support for C++, Fortran, BLAS/LAPACK, and other relevant libraries for scientific computing
+  - numpy.distutils (build support for C++, Fortran, BLAS/LAPACK, and other
+    relevant libraries for scientific computing)
   - f2py (generating bindings for Fortran code)
   - testing utilities
 
index d9c4f690ba21450038063238d6df0f4aabc69bb4..7d159fdb3cc98674389d8c08f34b4a38e61456f7 100644 (file)
@@ -4,7 +4,6 @@ metadata is passed to Jinja for filling out `index.rst.tmpl`.
 """
 
 import os
-import sys
 import jinja2
 import glob
 import re
@@ -35,15 +34,23 @@ def nep_metadata():
             tags = [match.groups() for match in tags if match is not None]
             tags = {tag[0]: tag[1] for tag in tags}
 
-            # We could do a clever regexp, but for now just assume the title is
-            # the second line of the document
-            tags['Title'] = lines[1].strip()
+            # The title should be the first line after a line containing only
+            # * or = signs.
+            for i, line in enumerate(lines[:-1]):
+                chars = set(line.rstrip())
+                if len(chars) == 1 and ("=" in chars or "*" in chars):
+                    break
+            else:
+                raise RuntimeError("Unable to find NEP title.")
+
+            tags['Title'] = lines[i+1].strip()
             tags['Filename'] = source
 
         if not tags['Title'].startswith(f'NEP {nr} â€” '):
             raise RuntimeError(
                 f'Title for NEP {nr} does not start with "NEP {nr} â€” " '
-                '(note that â€” here is a special, enlongated dash)')
+                '(note that â€” here is a special, enlongated dash). Got: '
+                f'    {tags["Title"]!r}')
 
         if tags['Status'] in ('Accepted', 'Rejected', 'Withdrawn'):
             if not 'Resolution' in tags:
index 2e50c115edbe8ef4051d1501d5d1ccb94b9c804b..3e066d22eb9eb084ad67bbc27df78fa42a2ddcdd 100755 (executable)
@@ -1,42 +1,28 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
-%prog MODE FILES...
-
 Post-processes HTML and Latex files output by Sphinx.
-MODE is either 'html' or 'tex'.
-
 """
-from __future__ import division, absolute_import, print_function
-
-import re
-import optparse
 import io
 
 def main():
-    p = optparse.OptionParser(__doc__)
-    options, args = p.parse_args()
-
-    if len(args) < 1:
-        p.error('no mode given')
+    import argparse
 
-    mode = args.pop(0)
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument('mode', help='file mode', choices=('html', 'tex'))
+    parser.add_argument('file', nargs='+', help='input file(s)')
+    args = parser.parse_args()
 
-    if mode not in ('html', 'tex'):
-        p.error('unknown mode %s' % mode)
+    mode = args.mode
 
-    for fn in args:
-        f = io.open(fn, 'r', encoding="utf-8")
-        try:
+    for fn in args.file:
+        with io.open(fn, 'r', encoding="utf-8") as f:
             if mode == 'html':
                 lines = process_html(fn, f.readlines())
             elif mode == 'tex':
                 lines = process_tex(f.readlines())
-        finally:
-            f.close()
 
-        f = io.open(fn, 'w', encoding="utf-8")
-        f.write("".join(lines))
-        f.close()
+        with io.open(fn, 'w', encoding="utf-8") as f:
+            f.write("".join(lines))
 
 def process_html(fn, lines):
     return lines
index 9c8a3b5fca7e5551d0b4f17b9810866b34e307af..997b4850ea5812a8d79a1edc762dd140fedd7a12 100644 (file)
@@ -17,6 +17,7 @@
 {% if definitions[category]['showcontent'] %}
 {% for text, values in sections[section][category].items() %}
 {{ text }}
+
 {{ get_indent(text) }}({{values|join(', ') }})
 
 {% endfor %}
index 294d392334b5fb0840626970f65495a1f5df63b7..d77c5a85e326341f2d761e566e198b664ab27ad8 100644 (file)
@@ -1,35 +1,43 @@
 {% extends "defindex.html" %}
 {% block tables %}
-  <p><strong>Parts of the documentation:</strong></p>
-  <table class="contentstable" align="center"><tr>
+<p><strong>For users:</strong></p>
+<table class="contentstable" align="center"><tr>
     <td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("user/index") }}">NumPy User Guide</a><br/>
-         <span class="linkdescr">start here</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("reference/index") }}">NumPy Reference</a><br/>
-         <span class="linkdescr">reference documentation</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("benchmarking") }}">Benchmarking</a><br/>
-         <span class="linkdescr">benchmarking NumPy</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("user/setting-up") }}">Setting Up</a><br/>
+       <span class="linkdescr">Learn about what NumPy is and how to install it</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("user/quickstart") }}">Quickstart Tutorial</a><br/>
+       <span class="linkdescr">Aimed at domain experts or people migrating to NumPy</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("user/absolute_beginners") }}">Absolute Beginners Tutorial</a><br/>
+       <span class="linkdescr">Start here for an overview of NumPy features and syntax</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("user/tutorials_index") }}">Tutorials</a><br/>
+       <span class="linkdescr">Learn about concepts and submodules</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("user/howtos_index") }}">How Tos</a><br/>
+       <span class="linkdescr">How to do common tasks with NumPy</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("reference/index") }}">NumPy API Reference</a><br/>
+        <span class="linkdescr">Automatically generated reference documentation</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("user/explanations_index") }}">Explanations</a><br/>
+       <span class="linkdescr">In depth explanation of concepts, best practices and techniques</span></p>
       <p class="biglink"><a class="biglink" href="{{ pathto("f2py/index") }}">F2Py Guide</a><br/>
-         <span class="linkdescr">f2py documentation</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("dev/index") }}">NumPy Developer Guide</a><br/>
-         <span class="linkdescr">contributing to NumPy</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("docs/index") }}">Building and Extending the Documentation</a><br/>
-         <span class="linkdescr">about this documentation</span></p>
-    </td></tr>
-  </table>
+        <span class="linkdescr">Documentation for the f2py module (Fortran extensions for Python)</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("glossary") }}">Glossary</a><br/>
+        <span class="linkdescr">List of the most important terms</span></p>
+  </td></tr>
+</table>
 
-  <p><strong>Indices and tables:</strong></p>
-  <table class="contentstable" align="center"><tr>
+<p><strong>For developers/contributors:</strong></p>
+<table class="contentstable" align="center"><tr>
     <td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("genindex") }}">General Index</a><br/>
-         <span class="linkdescr">all functions, classes, terms</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("glossary") }}">Glossary</a><br/>
-         <span class="linkdescr">the most important terms explained</span></p>
-    </td><td width="50%">
-      <p class="biglink"><a class="biglink" href="{{ pathto("search") }}">Search page</a><br/>
-         <span class="linkdescr">search this documentation</span></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("contents") }}">Complete Table of Contents</a><br/>
-         <span class="linkdescr">lists all sections and subsections</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("dev/index") }}">NumPy Contributor Guide</a><br/>
+        <span class="linkdescr">Contributing to NumPy</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("dev/underthehood") }}">Under-the-hood docs</a><br/>
+       <span class="linkdescr">Specialized, in-depth documentation</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("docs/index") }}">Building and Extending the Documentation</a><br/>
+        <span class="linkdescr">How to contribute to this documentation (user and API)</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("docs/howto_document") }}">The numpydoc docstring guide</a><br/>
+       <span class="linkdescr">How to write docstrings in the numpydoc format</span></p>
+      <p class="biglink"><a class="biglink" href="{{ pathto("benchmarking") }}">Benchmarking</a><br/>
+        <span class="linkdescr">benchmarking NumPy</span></p>
+      <p class="biglink"><a class="biglink" href="https://www.numpy.org/neps/index.html">NumPy Enhancement Proposals</a><br/>
     </td></tr>
   </table>
 
   <table class="contentstable" align="center"><tr>
     <td width="50%">
       <p class="biglink"><a class="biglink" href="{{ pathto("bugs") }}">Reporting bugs</a></p>
-      <p class="biglink"><a class="biglink" href="{{ pathto("about") }}">About NumPy</a></p>
-      <p class="biglink"><a class="biglink" href="https://www.numpy.org/neps/index.html">
-         NumPy Enhancement Proposals</a><br/>
-    </td><td width="50%">
       <p class="biglink"><a class="biglink" href="{{ pathto("release") }}">Release Notes</a></p>
+    </td><td width="50%">
+      <p class="biglink"><a class="biglink" href="{{ pathto("about") }}">About NumPy</a></p>
       <p class="biglink"><a class="biglink" href="{{ pathto("license") }}">License of NumPy</a></p>
     </td></tr>
   </table>
@@ -56,7 +62,7 @@
   </p>
   <p>
     The preferred way to update the documentation is by submitting a pull
-    request on Github (see the <a href="{{ pathto("docs/index") }}">Documentation Index</a>.
+    request on Github (see the <a href="{{ pathto("docs/index") }}">Documentation Index</a>).
     Please help us to further improve the NumPy documentation!
   </p>
 {% endblock %}
index 83cecc917ea8e896e7e43105a4530333609d943c..d6a0f8bf32f8b570a84eb91180b2f6a2d952cf6f 100644 (file)
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
-from __future__ import division, absolute_import, print_function
-
-import sys, os, re
+import os
+import re
+import sys
 
 # Minimum version, enforced by sphinx
 needs_sphinx = '2.2.0'
@@ -42,7 +42,7 @@ master_doc = 'contents'
 
 # General substitutions.
 project = 'NumPy'
-copyright = '2008-2019, The SciPy community'
+copyright = '2008-2020, The SciPy community'
 
 # The default replacements for |version| and |release|, also used in various
 # other places throughout the built documents.
@@ -155,6 +155,9 @@ plot_html_show_source_link = False
 # The font size ('10pt', '11pt' or '12pt').
 #latex_font_size = '10pt'
 
+# XeLaTeX for better support of unicode characters
+latex_engine = 'xelatex'
+
 # Grouping the document tree into LaTeX files. List of tuples
 # (source start file, target name, title, author, document class [howto/manual]).
 _stdauthor = 'Written by the NumPy community'
@@ -178,15 +181,29 @@ latex_elements = {
 }
 
 # Additional stuff for the LaTeX preamble.
-latex_preamble = r'''
-\usepackage{amsmath}
-\DeclareUnicodeCharacter{00A0}{\nobreakspace}
-
+latex_elements['preamble'] = r'''
 % In the parameters section, place a newline after the Parameters
 % header
+\usepackage{xcolor}
 \usepackage{expdlist}
 \let\latexdescription=\description
 \def\description{\latexdescription{}{} \breaklabel}
+% but expdlist old LaTeX package requires fixes:
+% 1) remove extra space
+\usepackage{etoolbox}
+\makeatletter
+\patchcmd\@item{{\@breaklabel} }{{\@breaklabel}}{}{}
+\makeatother
+% 2) fix bug in expdlist's way of breaking the line after long item label
+\makeatletter
+\def\breaklabel{%
+    \def\@breaklabel{%
+        \leavevmode\par
+        % now a hack because Sphinx inserts \leavevmode after term node
+        \def\leavevmode{\def\leavevmode{\unhbox\voidb@x}}%
+    }%
+}
+\makeatother
 
 % Make Examples/etc section headers smaller and more compact
 \makeatletter
@@ -225,7 +242,9 @@ texinfo_documents = [
 intersphinx_mapping = {
     'python': ('https://docs.python.org/dev', None),
     'scipy': ('https://docs.scipy.org/doc/scipy/reference', None),
-    'matplotlib': ('https://matplotlib.org', None)
+    'matplotlib': ('https://matplotlib.org', None),
+    'imageio': ('https://imageio.readthedocs.io/en/stable', None),
+    'skimage': ('https://scikit-image.org/docs/stable', None)
 }
 
 
@@ -243,7 +262,6 @@ numpydoc_use_plots = True
 # Autosummary
 # -----------------------------------------------------------------------------
 
-import glob
 autosummary_generate = True
 
 # -----------------------------------------------------------------------------
@@ -367,7 +385,6 @@ def linkcode_resolve(domain, info):
            numpy.__version__, fn, linespec)
 
 from pygments.lexers import CLexer
-from pygments import token
 import copy
 
 class NumPyLexer(CLexer):
index 019dcc71d093038b2a3b0bc6a1dd2ff5bed59f23..baea7784c9c73c20c20dc76e9310ee4033fcf997 100644 (file)
@@ -1,16 +1,27 @@
-#####################
-NumPy manual contents
-#####################
+.. _numpy_docs_mainpage:
+
+###################
+NumPy Documentation
+###################
 
 .. toctree::
 
-   user/index
+   user/setting-up
+   user/quickstart
+   user/absolute_beginners
+   user/tutorials_index
+   user/howtos_index
    reference/index
+   user/explanations_index
    f2py/index
+   glossary
    dev/index
+   dev/underthehood
    docs/index
+   docs/howto_document
+   benchmarking
+   bugs
    release
    about
-   bugs
    license
-   glossary
+
index aca39d8a792f598b9b4269bc6e5de823f0628678..f2f0a536dc566982b36718bc19d113d1be7d0fb6 100644 (file)
@@ -113,8 +113,8 @@ You can report issues to the NumPy Code of Conduct committee, at
 numpy-conduct@googlegroups.com. Currently, the committee consists of:
 
 - Stefan van der Walt
-- Nathaniel J. Smith
-- Ralf Gommers
+- Melissa Weber Mendonça
+- Anirudh Subramanian
 
 If your report involves any members of the committee, or if they feel they have
 a conflict of interest in handling it, then they will recuse themselves from
index c20b6fe407323ed7ca6255f49b000af142d84d5c..ff78cecc53156c05e18a7a59ea821e50aefcb322 100644 (file)
@@ -44,7 +44,7 @@ arguments may be forwarded to the target embedded by ``runtests.py`` by passing
 the extra arguments after a bare ``--``. For example, to run a test method with
 the ``--pdb`` flag forwarded to the target, run the following::
 
-    $ python runtests.py -t numpy/tests/test_scripts.py:test_f2py -- --pdb
+    $ python runtests.py -t numpy/tests/test_scripts.py::test_f2py -- --pdb
 
 When using pytest as a target (the default), you can
 `match test names using python operators`_ by passing the ``-k`` argument to pytest::
@@ -211,10 +211,20 @@ Debugging
 ---------
 
 Another frequently asked question is "How do I debug C code inside NumPy?".
-The easiest way to do this is to first write a Python script that invokes the C
-code whose execution you want to debug. For instance ``mytest.py``::
+First, ensure that you have gdb installed on your system with the Python
+extensions (often the default on Linux). You can see which version of
+Python is running inside gdb to verify your setup::
 
-    from numpy import linspace
+    (gdb) python
+    >import sys
+    >print(sys.version_info)
+    >end
+    sys.version_info(major=3, minor=7, micro=0, releaselevel='final', serial=0)
+
+Next you need to write a Python script that invokes the C code whose execution
+you want to debug. For instance ``mytest.py``::
+
+    import numpy as np
     x = np.arange(5)
     np.empty_like(x)
 
@@ -228,10 +238,14 @@ And then in the debugger::
     (gdb) run
 
 The execution will now stop at the corresponding C function and you can step
-through it as usual.  With the Python extensions for gdb installed (often the
-default on Linux), a number of useful Python-specific commands are available.
+through it as usual. A number of useful Python-specific commands are available.
 For example to see where in the Python code you are, use ``py-list``.  For more
-details, see `DebuggingWithGdb`_.
+details, see `DebuggingWithGdb`_. Here are some commonly used commands:
+
+   - ``list``: List specified function or line.
+   - ``next``: Step program, proceeding through subroutine calls.
+   - ``step``: Continue program being debugged, after signal or breakpoint.
+   - ``print``: Print value of expression EXP.
 
 Instead of plain ``gdb`` you can of course use your favourite
 alternative debugger; run it on the python binary with arguments
index 900431374454358cf26b80fd3f71ae4d4635ac8b..2ad764a78707ed3aea69fd507a1ed57861bf6641 100644 (file)
@@ -26,7 +26,7 @@ In short:
    - *Contributors*: push your feature branch to your own Github repo, and
      :ref:`create a pull request <asking-for-merging>`.
 
-   - *Core developers* If you want to push changes without
+   - *Core developers*: If you want to push changes without
      further review, see the notes :ref:`below <pushing-to-main>`.
 
 This way of working helps to keep work well organized and the history
@@ -303,7 +303,7 @@ Suppose that the commit history looks like this::
     2dec1ac Fix a few bugs + disable
     13d7934 First implementation
     6ad92e5 * masked is now an instance of a new object, MaskedConstant
-    29001ed Add pre-nep for a copule of structured_array_extensions.
+    29001ed Add pre-nep for a couple of structured_array_extensions.
     ...
 
 and ``6ad92e5`` is the last commit in the ``master`` branch. Suppose we
index 54e52363c00d696082a2e75cea944614a11fbf05..d8719700f2da99e0a7639e16bc9f98bfb31eb5aa 100644 (file)
@@ -301,7 +301,7 @@ its interactions with NumFOCUS.
    or technical direction of the Project.
 -  This Subcommittee will have 5 members, 4 of whom will be current
    Council Members and 1 of whom will be external to the Steering
-   Council. No more than 2 Subcommitee Members can report to one person
+   Council. No more than 2 Subcommittee Members can report to one person
    through employment or contracting work (including the reportee, i.e.
    the reportee + 1 is the max). This avoids effective majorities
    resting on one person.
index 10af7f2212d524c63e6b12041f8a417a576911f4..db2704d0930795672a3917ad861fd041acad6773 100644 (file)
@@ -56,7 +56,7 @@ NumFOCUS Subcommittee
 Institutional Partners
 ----------------------
 
-* UC Berkeley (Stefan van der Walt, Matti Picus, Tyler Reddy, Sebastian Berg)
+* UC Berkeley (Stefan van der Walt, Sebastian Berg, Warren Weckesser, Ross Barnowski)
 
-* Quansight (Ralf Gommers, Hameer Abbasi)
+* Quansight (Ralf Gommers, Hameer Abbasi, Melissa Weber Mendonça, Mars Lee, Matti Picus)
 
diff --git a/doc/source/dev/howto-docs.rst b/doc/source/dev/howto-docs.rst
new file mode 100644 (file)
index 0000000..0e2e03e
--- /dev/null
@@ -0,0 +1,149 @@
+.. _howto-docs:
+
+############################################
+How to contribute to the NumPy documentation
+############################################
+
+The *Documentation* for a software project is the set of reference,
+instructional, educational, informative material generated by the project
+developers and contributors, as well as discussions, presentations, videos and
+other user-generated content. It may include learning-oriented content (such as
+tutorials and how-tos), use-cases or in-depth explanations and reference for
+developers.
+
+If you're reading this page, you probably want to help. This guide is meant to
+help you decide which kind of content you'll write, as well as give you some
+tips and instructions for submitting it to the official NumPy documentation
+(that is, the documentation that ships with NumPy and lives on the
+:ref:`official project pages <numpy_docs_mainpage>`). Keep in mind that if you
+don't want to do this, writing a tutorial on your own blog, creating a YouTube
+video or answering questions on social media or Stack Overflow are also great
+contributions!
+
+NumPy has a Documentation Team. We have open meetings on Zoom every three weeks
+and invite everyone to join. Don't hesitate to reach out if you have questions
+or just need someone to guide you through your first steps - we're always happy
+to help. Meetings are usually announced on the `numpy-discussion mailing list
+<https://mail.python.org/mailman/listinfo/numpy-discussion>`__. Meeting minutes
+are taken `on hackmd.io <https://hackmd.io/oB_boakvRqKR-_2jRV-Qjg>`__ and stored
+in the `NumPy Archive repository <https://github.com/numpy/archive>`__.
+
+You can find larger planned and in-progress documentation improvement ideas `at
+our GitHub project <https://github.com/orgs/numpy/projects/2>`__.
+
+Current vision for the documentation: NEP 44
+--------------------------------------------
+
+Recently, the NumPy community approved a *NumPy Enhancement Proposal (NEP)*
+about documentation, `NEP 44 - Restructuring the NumPy Documentation
+<https://www.numpy.org/neps/nep-0044-restructuring-numpy-docs>`__.
+
+**Where is the documentation?**
+
+The main page for the :ref:`NumPy Documentation <numpy_docs_mainpage>` lists
+several categories. The documents mentioned there live in different places.
+
+- **Tutorials, How-Tos, Explanations:** These documents are stored in the NumPy
+  source code tree, which means that in order to add them to the official
+  documentation, you have to download the NumPy source code,
+  :ref:`build it <howto-build-docs>` and submit your changes via a
+  :ref:`GitHub pull request <devindex>`.
+
+- **API Reference:** These are mainly the result of rendering the NumPy code
+  `docstrings <https://www.python.org/dev/peps/pep-0257/>`__ into formatted
+  documents. They are automatically generated when the NumPy documentation is
+  :ref:`built from source<howto-build-docs>`.
+
+**Datasets**
+
+If you are writing a tutorial or how-to, we encourage you to use real images and
+data (provided they are appropriately licensed and available). This makes the
+material more engaging for readers, and choosing the right data can add
+pedagogical value to your content.
+
+*Note: currently we cannot easily use data in other packages (except, e.g., from
+SciPy or Matplotlib). We plan to create a dedicated datasets package, but that's
+not ready yet - please discuss with us if you have data sources in mind.*
+
+Creating new content
+--------------------
+
+The documentation is written in restructuredText, which is the format required
+by Sphinx, the tool most Python projects use to automatically build and link the
+documentation within the project. You can read the
+`Quick reStructuredText Guide
+<https://docutils.sourceforge.io/docs/user/rst/quickref.html>`__ or the
+`reStructuredText Primer
+<http://www.sphinx-doc.org/en/stable/usage/restructuredtext/basics.html>`__ for
+more information.
+
+If you have already decided which type of document you want to write, you can
+check out the following specific guides:
+
+- Guide to writing Tutorials (TODO)
+- :ref:`Guide to writing reference (API) documentation: the numpydoc docstring
+  guide <howto-document>`
+
+Major additions to the documentation (e.g. new tutorials) should be proposed to
+the `mailing list
+<https://mail.python.org/mailman/listinfo/numpy-discussion>`__.
+  
+Other ways to contribute
+------------------------
+
+Correcting technical inaccuracies in the documentation are high priority. For
+example, if a docstring is missing a parameter or the description of a
+fuction/parameter/method etc. is incorrect. Other "structural" defects like
+broken links are also high priority.
+
+Proposals for changes that improve the clarity of the documentation are welcome.
+However, "clarity" is a bit subjective, so such proposals are best made by
+raising issues that describe what could be improved in the current
+documentation. Proposals that include specific suggestions for the improvement
+are encouraged as the proposed changes helps frame the discussion.
+
+Based on the above characterization, "high-priority" changes (i.e. fixing
+technical inaccuracies, broken links, etc.) can be proposed via pull requests
+directly as they are straightforward to review. Other changes should be raised
+as issues first so that the discussion can happen before you make major
+modifications, which in principle saves you from wasting your time on
+undesired changes.
+
+If you see a good tutorial, how-to or explanation that is not included in the
+official documentation, you can suggest it to be added by `opening an issue on
+GitHub <https://github.com/numpy/numpy/issues>`__. Similarly, opening issues to
+suggest a tutorial, how-to or explanation that you can't find anywhere is a
+great way to help the documentation team direct efforts towards what users are
+looking for. `See this issue <https://github.com/numpy/numpy/issues/15760>`__
+for an example of how to do this.
+
+Finally, if you detect a typo or an error in the documentation, or would like to
+suggest a different approach, you can also open an issue or submit a pull
+request with your suggestion. Keep in mind that changes fixing
+grammatical/spelling errors are welcome but not necessarily the highest
+priority. "Grammatical correctness" often gets confused with "style" which can
+result in unfruitful discussions that don't necessarily improve anything.
+Changes that modify wording or rearrange phrasing without changing the technical
+content are discouraged. If you think that a different wording improves clarity,
+you should open an issue as noted above, but again, changes along these lines
+very often tend to be highly subjective and not necessarily do much to improve
+the quality of the documentation.
+
+**Final tips**
+
+- Don't worry if English is not your first language. Do your best - we'll revise
+  your content and make sure we fix any issues with the code or text.
+- If you are unsure whether your tutorial is useful to the community, consider
+  submitting an issue on GitHub suggesting it, or asking on the mailing
+  list or Stack Overflow.
+- If you are unfamiliar with git/GitHub or the process of submitting a pull
+  request (PR), check our :ref:`Contributor Guide <devindex>`.
+
+**Other interesting material**
+
+- `writethedocs.org <https://www.writethedocs.org/>`__ has a lot of interesting
+  resources for technical writing.
+- Google offers two free `Technical Writing Courses
+  <https://developers.google.com/tech-writing>`__
+- `Software Carpentry <https://software-carpentry.org/software>`__ has a lot of
+  nice recommendations for creating educational material.
index 306c150697fd817fa3dd017c5a0cb866557000ab..5270bfb775f038ecb9efdd60ebc83980534752af 100644 (file)
@@ -1,3 +1,5 @@
+.. _devindex:
+
 #####################
 Contributing to NumPy
 #####################
@@ -10,24 +12,23 @@ we list them in alphabetical order):
 - Community coordination
 - DevOps
 - Developing educational content & narrative documentation
-- Writing technical documentation
 - Fundraising
-- Project management
 - Marketing
+- Project management
 - Translating content
 - Website design and development
+- Writing technical documentation
 
 The rest of this document discusses working on the NumPy code base and documentation.
 We're in the process of updating our descriptions of other activities and roles.
 If you are interested in these other activities, please contact us!
 You can do this via
-the `numpy-discussion mailing list <https://scipy.org/scipylib/mailing-lists.html>`__,
-or on GitHub (open an issue or comment on a relevant issue). These are our preferred
-communication channels (open source is open by nature!), however if you prefer
-to discuss in private first, please reach out to our community coordinators
-at `numpy-team@googlegroups.com` or `numpy-team.slack.com` (send an email to
-`numpy-team@googlegroups.com` for an invite the first time).
-
+the `numpy-discussion mailing list <https://mail.python.org/mailman/listinfo/numpy-discussion>`__,
+or on `GitHub <https://github.com/numpy/numpy>`__ (open an issue or comment on a
+relevant issue). These are our preferred communication channels (open source is open
+by nature!), however if you prefer to discuss in private first, please reach out to
+our community coordinators at `numpy-team@googlegroups.com` or `numpy-team.slack.com`
+(send an email to `numpy-team@googlegroups.com` for an invite the first time).
 
 Development process - summary
 =============================
@@ -85,7 +86,7 @@ Here's the short summary, complete TOC links are below:
 
    * Enter your GitHub username and password (repeat contributors or advanced
      users can remove this step by connecting to GitHub with
-     :ref:`SSH<set-up-and-configure-a-github-account>` .
+     :ref:`SSH<set-up-and-configure-a-github-account>`).
 
    * Go to GitHub. The new branch will show up with a green Pull Request
      button. Make sure the title and message are clear, concise, and self-
@@ -198,6 +199,13 @@ Pull requests (PRs) that modify code should either have new tests, or modify exi
 tests to fail before the PR and pass afterwards. You should :ref:`run the tests
 <development-environment>` before pushing a PR.
 
+Running NumPy's test suite locally requires some additional packages, such as
+``pytest`` and ``hypothesis``. The additional testing dependencies are listed
+in ``test_requirements.txt`` in the top-level directory, and can conveniently
+be installed with::
+
+    pip install -r test_requirements.txt
+
 Tests for a module should ideally cover all code in that module,
 i.e., statement coverage should be at 100%.
 
@@ -231,6 +239,27 @@ Requirements
 `Sphinx <http://www.sphinx-doc.org/en/stable/>`__ is needed to build
 the documentation. Matplotlib, SciPy, and IPython are also required.
 
+These additional dependencies for building the documentation are listed in
+``doc_requirements.txt`` and can be conveniently installed with::
+
+    pip install -r doc_requirements.txt
+
+The numpy documentation also depends on the
+`numpydoc <https://numpydoc.readthedocs.io/en/latest/>`__ sphinx extension
+as well as an external sphinx theme.
+These extensions are included as git submodules and must be initialized
+before building the docs.
+From the ``doc/`` directory:
+
+.. code:: sh
+
+    git submodule update --init
+
+The documentation includes mathematical formulae with LaTeX formatting.
+A working LaTeX document production system 
+(e.g. `texlive <https://www.tug.org/texlive/>`__) is required for the
+proper rendering of the LaTeX math in the documentation.
+
 Fixing Warnings
 ~~~~~~~~~~~~~~~
 
@@ -257,6 +286,7 @@ The rest of the story
    style_guide
    releasing
    governance/index
+   howto-docs
 
 NumPy-specific workflow is in :ref:`numpy-development-workflow
 <development-workflow>`.
diff --git a/doc/source/dev/underthehood.rst b/doc/source/dev/underthehood.rst
new file mode 100644 (file)
index 0000000..4dae486
--- /dev/null
@@ -0,0 +1,7 @@
+.. _underthehood:
+
+===========================================
+Under-the-hood Documentation for developers
+===========================================
+
+To be completed.
index 6deacda5cc93026e9b177c5590c033a72448d11b..29912a5af8f1b2d7a2d6d00a62c3f90e3447a2fb 100644 (file)
@@ -5,12 +5,12 @@ Building the NumPy API and reference docs
 =========================================
 
 We currently use Sphinx_ for generating the API and reference
-documentation for NumPy.  You will need Sphinx 1.8.3 <= 1.8.5.
+documentation for NumPy.  You will need Sphinx >= 2.2.0.
 
 If you only want to get the documentation, note that pre-built
 versions can be found at
 
-    https://docs.scipy.org/
+    https://numpy.org/doc/
 
 in several different formats.
 
@@ -23,23 +23,30 @@ Instructions
 If you obtained NumPy via git, get also the git submodules that contain
 additional parts required for building the documentation::
 
-    git submodule init
-    git submodule update
+    git submodule update --init
 
 In addition, building the documentation requires the Sphinx extension
 `plot_directive`, which is shipped with Matplotlib_. This Sphinx extension can
-be installed by installing Matplotlib. You will also need python3.6.
+be installed by installing Matplotlib. You will also need Python>=3.6.
 
 Since large parts of the main documentation are obtained from numpy via
 ``import numpy`` and examining the docstrings, you will need to first build
 NumPy, and install it so that the correct version is imported.
 
+After NumPy is installed, install SciPy since some of the plots in the random
+module require `scipy.special` to display properly.
+
 Note that you can eg. install NumPy to a temporary location and set
 the PYTHONPATH environment variable appropriately.
+Alternatively, if using Python virtual environments (via e.g. ``conda``,
+``virtualenv`` or the ``venv`` module), installing numpy into a
+new virtual environment is recommended.
+All of the necessary dependencies for building the NumPy docs can be installed
+with::
 
-After NumPy is installed, install SciPy since some of the plots in the random
-module require `scipy.special` to display properly. Now you are ready to
-generate the docs, so write::
+    pip install -r doc_requirements.txt
+
+Now you are ready to generate the docs, so write::
 
     make html
 
@@ -57,7 +64,9 @@ To build the PDF documentation, do instead::
    make latex
    make -C build/latex all-pdf
 
-You will need to have Latex installed for this.
+You will need to have Latex installed for this, inclusive of support for
+Greek letters.  For example, on Ubuntu xenial ``texlive-lang-greek`` and
+``cm-super`` are needed.  Also ``latexmk`` is needed on non-Windows systems.
 
 Instead of the above, you can also do::
 
@@ -67,9 +76,9 @@ which will rebuild NumPy, install it to a temporary location, and
 build the documentation in all formats. This will most likely again
 only work on Unix platforms.
 
-The documentation for NumPy distributed at https://docs.scipy.org in html and
-pdf format is also built with ``make dist``.  See `HOWTO RELEASE`_ for details on
-how to update https://docs.scipy.org.
+The documentation for NumPy distributed at https://numpy.org/doc in html and
+pdf format is also built with ``make dist``.  See `HOWTO RELEASE`_ for details
+on how to update https://numpy.org/doc.
 
 .. _Matplotlib: https://matplotlib.org/
 .. _HOWTO RELEASE: https://github.com/numpy/numpy/blob/master/doc/HOWTO_RELEASE.rst.txt
index 375922033d58dcf6b23963531fd567aad0e68862..1b4625dde9fcd925c65bd0b3b6f3d214fa393fa5 100644 (file)
@@ -25,7 +25,7 @@ In Python:
 Modifying the dictionary of a F2PY generated module
 ===================================================
 
-The following example illustrates how to add user-defined
+The following example illustrates how to add user-defined
 variables to a F2PY generated extension module. Given the following
 signature file
 
index fc91959b738de440475c73b82c76174749f48e6c..754d9cb8b5a255705299cbc2d57bb5dfd90e802c 100644 (file)
@@ -1,27 +1,29 @@
->>> import allocarr 
->>> print allocarr.mod.__doc__
+>>> import allocarr
+>>> print(allocarr.mod.__doc__)
 b - 'f'-array(-1,-1), not allocated
 foo - Function signature:
   foo()
 
 >>> allocarr.mod.foo()  
  b is not allocated
->>> allocarr.mod.b = [[1,2,3],[4,5,6]]         # allocate/initialize b
+>>> allocarr.mod.b = [[1, 2, 3], [4, 5, 6]]             # allocate/initialize b
 >>> allocarr.mod.foo()
  b=[
    1.000000       2.000000       3.000000    
    4.000000       5.000000       6.000000    
  ]
->>> allocarr.mod.b                             # b is Fortran-contiguous
+>>> allocarr.mod.b                                      # b is Fortran-contiguous
 array([[ 1.,  2.,  3.],
-       [ 4.,  5.,  6.]],'f')
->>> allocarr.mod.b = [[1,2,3],[4,5,6],[7,8,9]] # reallocate/initialize b
+       [ 4.,  5.,  6.]], dtype=float32)
+>>> allocarr.mod.b.flags.f_contiguous
+True
+>>> allocarr.mod.b = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]  # reallocate/initialize b
 >>> allocarr.mod.foo()
  b=[
    1.000000       2.000000       3.000000    
    4.000000       5.000000       6.000000    
    7.000000       8.000000       9.000000    
  ]
->>> allocarr.mod.b = None                      # deallocate array
+>>> allocarr.mod.b = None                               # deallocate array
 >>> allocarr.mod.foo()
  b is not allocated
index 069530d032eef6a18169bcf3f25e2498e5237f1d..714c03651f84a8fe0a6220bfa583be6305ef261d 100644 (file)
@@ -1,65 +1,87 @@
 >>> import arr
->>> from numpy import array
->>> print arr.foo.__doc__
-foo - Function signature:
-  a = foo(a,[overwrite_a])
-Required arguments:
-  a : input rank-2 array('d') with bounds (n,m)
-Optional arguments:
-  overwrite_a := 0 input int
-Return objects:
-  a : rank-2 array('d') with bounds (n,m)
+>>> from numpy import asfortranarray
+>>> print(arr.foo.__doc__)
+a = foo(a,[overwrite_a])
 
->>> a=arr.foo([[1,2,3],
-...            [4,5,6]])
-copied an array using PyArray_CopyFromObject: size=6, elsize=8
->>> print a
+Wrapper for ``foo``.
+
+Parameters
+----------
+a : input rank-2 array('d') with bounds (n,m)
+
+Other Parameters
+----------------
+overwrite_a : input int, optional
+    Default: 0
+
+Returns
+-------
+a : rank-2 array('d') with bounds (n,m)
+
+>>> a = arr.foo([[1, 2, 3],
+...              [4, 5, 6]])
+created an array from object
+>>> print(a)
 [[ 1.  3.  4.]
  [ 3.  5.  6.]]
->>> a.iscontiguous(), arr.has_column_major_storage(a)
-(0, 1)
->>> b=arr.foo(a)              # even if a is proper-contiguous
-...                           # and has proper type, a copy is made
-...                           # forced by intent(copy) attribute
-...                           # to preserve its original contents
-... 
-copied an array using copy_ND_array: size=6, elsize=8
->>> print a
+>>> a.flags.c_contiguous
+False
+>>> a.flags.f_contiguous
+True
+# even if a is proper-contiguous and has proper type,
+# a copy is made forced by intent(copy) attribute
+# to preserve its original contents
+>>> b = arr.foo(a)
+copied an array: size=6, elsize=8
+>>> print(a)
 [[ 1.  3.  4.]
  [ 3.  5.  6.]]
->>> print b
+>>> print(b)
 [[ 1.  4.  5.]
  [ 2.  5.  6.]]
->>> b=arr.foo(a,overwrite_a=1) # a is passed directly to Fortran
-...                            # routine and its contents is discarded
+>>> b = arr.foo(a, overwrite_a = 1) # a is passed directly to Fortran
+...                                 # routine and its contents is discarded
 ... 
->>> print a
+>>> print(a)
 [[ 1.  4.  5.]
  [ 2.  5.  6.]]
->>> print b
+>>> print(b)
 [[ 1.  4.  5.]
  [ 2.  5.  6.]]
->>> a is b                       # a and b are actually the same objects
-1
->>> print arr.foo([1,2,3])       # different rank arrays are allowed
-copied an array using PyArray_CopyFromObject: size=3, elsize=8
+>>> a is b                          # a and b are actually the same objects
+True
+>>> print(arr.foo([1, 2, 3]))       # different rank arrays are allowed
+created an array from object
 [ 1.  1.  2.]
->>> print arr.foo([[[1],[2],[3]]])
-copied an array using PyArray_CopyFromObject: size=3, elsize=8
-[ [[ 1.]
-  [ 3.]
-  [ 4.]]]
+>>> print(arr.foo([[[1], [2], [3]]]))
+created an array from object
+[[[ 1.]
+  [ 1.]
+  [ 2.]]]
 >>>
 >>> # Creating arrays with column major data storage order:
-...
->>> s = arr.as_column_major_storage(array([[1,2,3],[4,5,6]]))
-copied an array using copy_ND_array: size=6, elsize=4
->>> arr.has_column_major_storage(s)
-1
->>> print s
+ ...
+>>> s = asfortranarray([[1, 2, 3], [4, 5, 6]])
+>>> s.flags.f_contiguous
+True
+>>> print(s)
 [[1 2 3]
  [4 5 6]]
->>> s2 = arr.as_column_major_storage(s)
+>>> print(arr.foo(s))
+>>> s2 = asfortranarray(s)
 >>> s2 is s    # an array with column major storage order 
                # is returned immediately
-1
+True
+>>> # Note that arr.foo returns a column major data storage order array:
+ ...
+>>> s3 = ascontiguousarray(s)
+>>> s3.flags.f_contiguous
+False
+>>> s3.flags.c_contiguous
+True
+>>> s3 = arr.foo(s3)
+copied an array: size=6, elsize=8
+>>> s3.flags.f_contiguous
+True
+>>> s3.flags.c_contiguous
+False
index 1cda1c8ddd3d4fd31f581420426feb4bb1ee3ee4..4ff570d28ff5ad9129cef49ce783753808c3b752 100644 (file)
@@ -7,7 +7,7 @@ cf2py y = func(y)
 c
 cf2py intent(in,out,copy) x
       integer n,i
-      real*8 x(n)
+      real*8 x(n), func
       do i=1,n
          x(i) = func(x(i))
       end do
index 2fe64f522463af4e9bd135ee60984a9f1b4c7a35..c4c38070099ccc8555a118fad0c5b753dd0cc88d 100644 (file)
@@ -3,4 +3,4 @@
 array([  0.,   1.,   4.,   9.,  16.])
 >>> import math
 >>> foo.calculate(range(5), math.exp)
-array([  1.        ,   2.71828175,   7.38905621,  20.08553696,  54.59814835])
+array([  1.        ,   2.71828183,   7.3890561,  20.08553692,  54.59815003])
index 6e9bfb920cdfb3b3b9d03969ee9ce01db6c26e58..d5cfc757411d19186218f71e05f43465609d70e8 100644 (file)
@@ -2,7 +2,7 @@ C FILE: CALLBACK.F
       SUBROUTINE FOO(FUN,R)
       EXTERNAL FUN
       INTEGER I
-      REAL*8 R
+      REAL*8 R, FUN
 Cf2py intent(out) r
       R = 0D0
       DO I=-5,5
index cd2f26084990429806ffb74e181d3aa062ceb83b..460c9ce28873eed488b67161cd046a83bbb5ee3f 100644 (file)
@@ -1,14 +1,26 @@
 >>> import callback
->>> print callback.foo.__doc__
-foo - Function signature:
-  r = foo(fun,[fun_extra_args])
-Required arguments:
-  fun : call-back function
-Optional arguments:
-  fun_extra_args := () input tuple
-Return objects:
-  r : float
-Call-back functions:
+>>> print(callback.foo.__doc__)
+r = foo(fun,[fun_extra_args])
+
+Wrapper for ``foo``.
+
+Parameters
+----------
+fun : call-back function
+
+Other Parameters
+----------------
+fun_extra_args : input tuple, optional
+    Default: ()
+
+Returns
+-------
+r : float
+
+Notes
+-----
+Call-back functions::
+
   def fun(i): return r
   Required arguments:
     i : input int
@@ -17,7 +29,7 @@ Call-back functions:
 
 >>> def f(i): return i*i
 ... 
->>> print callback.foo(f)     
+>>> print(callback.foo(f))
 110.0
->>> print callback.foo(lambda i:1)
+>>> print(callback.foo(lambda i:1))
 11.0
index 846fdaa07621a63fa5df4293763307f219b0bf00..0a38bec27b8a10ee6a51da70a1f47b9d50502ded 100644 (file)
@@ -1,5 +1,5 @@
 >>> import common
->>> print common.data.__doc__
+>>> print(common.data.__doc__)
 i - 'i'-scalar
 x - 'i'-array(4)
 a - 'f'-array(2,3)
@@ -8,20 +8,23 @@ a - 'f'-array(2,3)
 >>> common.data.x[1] = 2 
 >>> common.data.a = [[1,2,3],[4,5,6]]
 >>> common.foo()
- I= 5
- X=[ 0 2 0 0]
+>>> common.foo()
+ I=           5
+ X=[           0           2           0           0 ]
  A=[
- [  1.,  2.,  3.]
- [  4.,  5.,  6.]
+ [   1.00000000     ,   2.00000000     ,   3.00000000     ]
+ [   4.00000000     ,   5.00000000     ,   6.00000000     ]
  ]
 >>> common.data.a[1] = 45
 >>> common.foo()
- I= 5
- X=[ 0 2 0 0]
+ I=           5
+ X=[           0           2           0           0 ]
  A=[
- [  1.,  2.,  3.]
- [  45.,  45.,  45.]
+ [   1.00000000     ,   2.00000000     ,   3.00000000     ]
+ [   45.0000000     ,   45.0000000     ,   45.0000000     ]
  ]
 >>> common.data.a                 # a is Fortran-contiguous
 array([[  1.,   2.,   3.],
-       [ 45.,  45.,  45.]],'f')
+       [ 45.,  45.,  45.]], dtype=float32)
+>>> common.data.a.flags.f_contiguous
+True
\ No newline at end of file
index c22935ea0f7dd59a343e9c1ea75aabe651030242..5b97ab7cfff28939729489841fa31b193ecb5467 100644 (file)
@@ -1,10 +1,10 @@
 >>> import pfromf
 >>> pfromf.f2()
 Traceback (most recent call last):
-  File "<stdin>", line 1, in ?
+  File "<stdin>", line 1, in <module>
 pfromf.error: Callback fpy not defined (as an argument or module pfromf attribute).
 
->>> def f(): print "python f"
+>>> def f(): print("python f")
 ... 
 >>> pfromf.fpy = f
 >>> pfromf.f2()
diff --git a/doc/source/f2py/f2py.getting-started.rst b/doc/source/f2py/f2py.getting-started.rst
new file mode 100644 (file)
index 0000000..27ddbb0
--- /dev/null
@@ -0,0 +1,272 @@
+======================================
+ Three ways to wrap - getting started
+======================================
+
+Wrapping Fortran or C functions to Python using F2PY consists of the
+following steps:
+
+* Creating the so-called signature file that contains descriptions of
+  wrappers to Fortran or C functions, also called as signatures of the
+  functions. In the case of Fortran routines, F2PY can create initial
+  signature file by scanning Fortran source codes and
+  catching all relevant information needed to create wrapper
+  functions.
+
+* Optionally, F2PY created signature files can be edited to optimize
+  wrappers functions, make them "smarter" and more "Pythonic".
+
+* F2PY reads a signature file and writes a Python C/API module containing
+  Fortran/C/Python bindings.
+
+* F2PY compiles all sources and builds an extension module containing
+  the wrappers. In building extension modules, F2PY uses
+  ``numpy_distutils`` that supports a number of Fortran 77/90/95
+  compilers, including Gnu, Intel,
+  Sun Fortre, SGI MIPSpro, Absoft, NAG, Compaq etc. compilers.
+
+Depending on a particular situation, these steps can be carried out
+either by just in one command or step-by-step, some steps can be
+omitted or combined with others.
+
+Below I'll describe three typical approaches of using F2PY.
+The following example Fortran 77 code will be used for
+illustration, save it as fib1.f:
+
+.. include:: fib1.f
+   :literal:
+
+
+The quick way
+==============
+
+The quickest way to wrap the Fortran subroutine ``FIB`` to Python is
+to run
+
+::
+
+  python -m numpy.f2py -c fib1.f -m fib1
+
+This command builds (see ``-c`` flag, execute ``python -m numpy.f2py`` without
+arguments to see the explanation of command line options) an extension
+module ``fib1.so`` (see ``-m`` flag) to the current directory. Now, in
+Python the Fortran subroutine ``FIB`` is accessible via ``fib1.fib``::
+
+  >>> import numpy
+  >>> import fib1
+  >>> print(fib1.fib.__doc__)
+  fib(a,[n])
+
+  Wrapper for ``fib``.
+
+  Parameters
+  ----------
+  a : input rank-1 array('d') with bounds (n)
+
+  Other Parameters
+  ----------------
+  n : input int, optional
+      Default: len(a)
+
+  >>> a = numpy.zeros(8, 'd')
+  >>> fib1.fib(a)
+  >>> print(a)
+  [  0.   1.   1.   2.   3.   5.   8.  13.]
+
+.. note::
+
+  * Note that F2PY found that the second argument ``n`` is the
+    dimension of the first array argument ``a``. Since by default all
+    arguments are input-only arguments, F2PY concludes that ``n`` can
+    be optional with the default value ``len(a)``.
+
+  * One can use different values for optional ``n``::
+
+      >>> a1 = numpy.zeros(8, 'd')
+      >>> fib1.fib(a1, 6)
+      >>> print(a1)
+      [ 0.  1.  1.  2.  3.  5.  0.  0.]
+
+    but an exception is raised when it is incompatible with the input
+    array ``a``::
+
+      >>> fib1.fib(a, 10)
+      Traceback (most recent call last):
+        File "<stdin>", line 1, in <module>
+      fib.error: (len(a)>=n) failed for 1st keyword n: fib:n=10
+      >>>
+
+    F2PY implements basic compatibility checks between related
+    arguments in order to avoid any unexpected crashes.
+
+  * When a NumPy array, that is Fortran contiguous and has a dtype
+    corresponding to presumed Fortran type, is used as an input array
+    argument, then its C pointer is directly passed to Fortran.
+
+    Otherwise F2PY makes a contiguous copy (with a proper dtype) of
+    the input array and passes C pointer of the copy to Fortran
+    subroutine. As a result, any possible changes to the (copy of)
+    input array have no effect to the original argument, as
+    demonstrated below::
+
+      >>> a = numpy.ones(8, 'i')
+      >>> fib1.fib(a)
+      >>> print(a)
+      [1 1 1 1 1 1 1 1]
+
+    Clearly, this is not an expected behaviour. The fact that the
+    above example worked with ``dtype=float`` is considered
+    accidental.
+
+    F2PY provides ``intent(inplace)`` attribute that would modify
+    the attributes of an input array so that any changes made by
+    Fortran routine will be effective also in input argument. For example,
+    if one specifies ``intent(inplace) a`` (see below, how), then
+    the example above would read::
+
+      >>> a = numpy.ones(8, 'i')
+      >>> fib1.fib(a)
+      >>> print(a)
+      [  0.   1.   1.   2.   3.   5.   8.  13.]
+
+    However, the recommended way to get changes made by Fortran
+    subroutine back to Python is to use ``intent(out)`` attribute. It
+    is more efficient and a cleaner solution.
+
+  * The usage of ``fib1.fib`` in Python is very similar to using
+    ``FIB`` in Fortran. However, using *in situ* output arguments in
+    Python indicates a poor style as there is no safety mechanism
+    in Python with respect to wrong argument types. When using Fortran
+    or C, compilers naturally discover any type mismatches during
+    compile time but in Python the types must be checked in
+    runtime. So, using *in situ* output arguments in Python may cause
+    difficult to find bugs, not to mention that the codes will be less
+    readable when all required type checks are implemented.
+
+  Though the demonstrated way of wrapping Fortran routines to Python
+  is very straightforward, it has several drawbacks (see the comments
+  above).  These drawbacks are due to the fact that there is no way
+  that F2PY can determine what is the actual intention of one or the
+  other argument, is it input or output argument, or both, or
+  something else. So, F2PY conservatively assumes that all arguments
+  are input arguments by default.
+
+  However, there are ways (see below) how to "teach" F2PY about the
+  true intentions (among other things) of function arguments; and then
+  F2PY is able to generate more Pythonic (more explicit, easier to
+  use, and less error prone) wrappers to Fortran functions.
+
+The smart way
+==============
+
+Let's apply the steps of wrapping Fortran functions to Python one by
+one.
+
+* First, we create a signature file from ``fib1.f`` by running
+
+  ::
+
+    python -m numpy.f2py fib1.f -m fib2 -h fib1.pyf
+
+  The signature file is saved to ``fib1.pyf`` (see ``-h`` flag) and
+  its contents is shown below.
+
+  .. include:: fib1.pyf
+     :literal:
+
+* Next, we'll teach F2PY that the argument ``n`` is an input argument
+  (use ``intent(in)`` attribute) and that the result, i.e. the
+  contents of ``a`` after calling Fortran function ``FIB``, should be
+  returned to Python (use ``intent(out)`` attribute). In addition, an
+  array ``a`` should be created dynamically using the size given by
+  the input argument ``n`` (use ``depend(n)`` attribute to indicate
+  dependence relation).
+
+  The content of a modified version of ``fib1.pyf`` (saved as
+  ``fib2.pyf``) is as follows:
+
+  .. include:: fib2.pyf
+     :literal:
+
+* And finally, we build the extension module by running
+
+  ::
+
+    python -m numpy.f2py -c fib2.pyf fib1.f
+
+In Python::
+
+  >>> import fib2
+  >>> print(fib2.fib.__doc__)
+  a = fib(n)
+
+  Wrapper for ``fib``.
+
+  Parameters
+  ----------
+  n : input int
+
+  Returns
+  -------
+  a : rank-1 array('d') with bounds (n)
+
+  >>> print(fib2.fib(8))
+  [  0.   1.   1.   2.   3.   5.   8.  13.]
+
+.. note::
+
+  * Clearly, the signature of ``fib2.fib`` now corresponds to the
+    intention of Fortran subroutine ``FIB`` more closely: given the
+    number ``n``, ``fib2.fib`` returns the first ``n`` Fibonacci numbers
+    as a NumPy array. Also, the new Python signature ``fib2.fib``
+    rules out any surprises that we experienced with ``fib1.fib``.
+
+  * Note that by default using single ``intent(out)`` also implies
+    ``intent(hide)``. Arguments that have the ``intent(hide)`` attribute
+    specified will not be listed in the argument list of a wrapper
+    function.
+
+The quick and smart way
+========================
+
+The "smart way" of wrapping Fortran functions, as explained above, is
+suitable for wrapping (e.g. third party) Fortran codes for which
+modifications to their source codes are not desirable nor even
+possible.
+
+However, if editing Fortran codes is acceptable, then the generation
+of an intermediate signature file can be skipped in most
+cases. Namely, F2PY specific attributes can be inserted directly to
+Fortran source codes using the so-called F2PY directive. A F2PY
+directive defines special comment lines (starting with ``Cf2py``, for
+example) which are ignored by Fortran compilers but F2PY interprets
+them as normal lines.
+
+Here is shown a modified version of the previous Fortran code, save it
+as ``fib3.f``:
+
+.. include:: fib3.f
+   :literal:
+
+Building the extension module can be now carried out in one command::
+
+  python -m numpy.f2py -c -m fib3 fib3.f
+
+Notice that the resulting wrapper to ``FIB`` is as "smart" as in
+previous case::
+
+  >>> import fib3
+  >>> print(fib3.fib.__doc__)
+  a = fib(n)
+
+  Wrapper for ``fib``.
+
+  Parameters
+  ----------
+  n : input int
+
+  Returns
+  -------
+  a : rank-1 array('d') with bounds (n)
+
+  >>> print(fib3.fib(8))
+  [  0.   1.   1.   2.   3.   5.   8.  13.]
index 01f9febaf403a95750a3bc321fe9ed83684f9ea8..e39cc128d5bcf4804bd1608e39929690d1df9375 100644 (file)
@@ -1,13 +1,13 @@
 >>> import ftype
->>> print ftype.__doc__
-This module 'ftype' is auto-generated with f2py (version:2.28.198-1366).
+>>> print(ftype.__doc__)
+This module 'ftype' is auto-generated with f2py (version:2).
 Functions:
   foo(n=13)
 COMMON blocks:
   /data/ a,x(3)
 .
->>> type(ftype.foo),type(ftype.data)
-(<type 'fortran'>, <type 'fortran'>)
+>>> type(ftype.foo), type(ftype.data)
+(<class 'fortran'>, <class 'fortran'>)
 >>> ftype.foo()
  IN FOO: N= 13 A=  0. X=[  0.  0.  0.]
 >>> ftype.data.a = 3
@@ -18,4 +18,4 @@ COMMON blocks:
 >>> ftype.foo(24)
  IN FOO: N= 24 A=  3. X=[  1.  45.  3.]
 >>> ftype.data.x
-array([  1.,  45.,   3.],'f')
+array([  1.,  45.,   3.], dtype=float32)
diff --git a/doc/source/f2py/getting-started.rst b/doc/source/f2py/getting-started.rst
deleted file mode 100644 (file)
index 3d8ea24..0000000
+++ /dev/null
@@ -1,261 +0,0 @@
-======================================
- Three ways to wrap - getting started
-======================================
-
-Wrapping Fortran or C functions to Python using F2PY consists of the
-following steps:
-
-* Creating the so-called signature file that contains descriptions of
-  wrappers to Fortran or C functions, also called as signatures of the
-  functions. In the case of Fortran routines, F2PY can create initial
-  signature file by scanning Fortran source codes and
-  catching all relevant information needed to create wrapper
-  functions.
-
-* Optionally, F2PY created signature files can be edited to optimize
-  wrappers functions, make them "smarter" and more "Pythonic".
-
-* F2PY reads a signature file and writes a Python C/API module containing
-  Fortran/C/Python bindings.
-
-* F2PY compiles all sources and builds an extension module containing
-  the wrappers. In building extension modules, F2PY uses
-  ``numpy_distutils`` that supports a number of Fortran 77/90/95
-  compilers, including Gnu, Intel,
-  Sun Fortre, SGI MIPSpro, Absoft, NAG, Compaq etc. compilers.
-
-Depending on a particular situation, these steps can be carried out
-either by just in one command or step-by-step, some steps can be
-omitted or combined with others.
-
-Below I'll describe three typical approaches of using F2PY.
-The following `example Fortran 77 code`__ will be used for
-illustration:
-
-.. include:: fib1.f
-   :literal:
-
-__ fib1.f
-
-The quick way
-==============
-
-The quickest way to wrap the Fortran subroutine ``FIB`` to Python is
-to run
-
-::
-
-  python -m numpy.f2py -c fib1.f -m fib1
-
-This command builds (see ``-c`` flag, execute ``python -m numpy.f2py`` without
-arguments to see the explanation of command line options) an extension
-module ``fib1.so`` (see ``-m`` flag) to the current directory. Now, in
-Python the Fortran subroutine ``FIB`` is accessible via ``fib1.fib``::
-
-  >>> import numpy
-  >>> import fib1
-  >>> print fib1.fib.__doc__
-  fib - Function signature:
-    fib(a,[n])
-  Required arguments:
-    a : input rank-1 array('d') with bounds (n)
-  Optional arguments:
-    n := len(a) input int
-
-  >>> a = numpy.zeros(8,'d')
-  >>> fib1.fib(a)
-  >>> print a
-  [  0.   1.   1.   2.   3.   5.   8.  13.]
-
-.. note::
-
-  * Note that F2PY found that the second argument ``n`` is the
-    dimension of the first array argument ``a``. Since by default all
-    arguments are input-only arguments, F2PY concludes that ``n`` can
-    be optional with the default value ``len(a)``.
-
-  * One can use different values for optional ``n``::
-
-      >>> a1 = numpy.zeros(8,'d')
-      >>> fib1.fib(a1,6)
-      >>> print a1
-      [ 0.  1.  1.  2.  3.  5.  0.  0.]
-
-    but an exception is raised when it is incompatible with the input
-    array ``a``::
-
-      >>> fib1.fib(a,10)
-      fib:n=10
-      Traceback (most recent call last):
-        File "<stdin>", line 1, in ?
-      fib.error: (len(a)>=n) failed for 1st keyword n
-      >>>
-
-    This demonstrates one of the useful features in F2PY, that it,
-    F2PY implements basic compatibility checks between related
-    arguments in order to avoid any unexpected crashes.
-
-  * When a NumPy array, that is Fortran contiguous and has a dtype
-    corresponding to presumed Fortran type, is used as an input array
-    argument, then its C pointer is directly passed to Fortran.
-
-    Otherwise F2PY makes a contiguous copy (with a proper dtype) of
-    the input array and passes C pointer of the copy to Fortran
-    subroutine. As a result, any possible changes to the (copy of)
-    input array have no effect to the original argument, as
-    demonstrated below::
-
-      >>> a = numpy.ones(8,'i')
-      >>> fib1.fib(a)
-      >>> print a
-      [1 1 1 1 1 1 1 1]
-
-    Clearly, this is not an expected behaviour. The fact that the
-    above example worked with ``dtype=float`` is considered
-    accidental.
-
-    F2PY provides ``intent(inplace)`` attribute that would modify
-    the attributes of an input array so that any changes made by
-    Fortran routine will be effective also in input argument. For example,
-    if one specifies ``intent(inplace) a`` (see below, how), then
-    the example above would read:
-
-      >>> a = numpy.ones(8,'i')
-      >>> fib1.fib(a)
-      >>> print a
-      [  0.   1.   1.   2.   3.   5.   8.  13.]
-
-    However, the recommended way to get changes made by Fortran
-    subroutine back to python is to use ``intent(out)`` attribute. It
-    is more efficient and a cleaner solution.
-
-  * The usage of ``fib1.fib`` in Python is very similar to using
-    ``FIB`` in Fortran. However, using *in situ* output arguments in
-    Python indicates a poor style as there is no safety mechanism
-    in Python with respect to wrong argument types. When using Fortran
-    or C, compilers naturally discover any type mismatches during
-    compile time but in Python the types must be checked in
-    runtime. So, using *in situ* output arguments in Python may cause
-    difficult to find bugs, not to mention that the codes will be less
-    readable when all required type checks are implemented.
-
-  Though the demonstrated way of wrapping Fortran routines to Python
-  is very straightforward, it has several drawbacks (see the comments
-  above).  These drawbacks are due to the fact that there is no way
-  that F2PY can determine what is the actual intention of one or the
-  other argument, is it input or output argument, or both, or
-  something else. So, F2PY conservatively assumes that all arguments
-  are input arguments by default.
-
-  However, there are ways (see below) how to "teach" F2PY about the
-  true intentions (among other things) of function arguments; and then
-  F2PY is able to generate more Pythonic (more explicit, easier to
-  use, and less error prone) wrappers to Fortran functions.
-
-The smart way
-==============
-
-Let's apply the steps of wrapping Fortran functions to Python one by
-one.
-
-* First, we create a signature file from ``fib1.f`` by running
-
-  ::
-
-    python -m numpy.f2py fib1.f -m fib2 -h fib1.pyf
-
-  The signature file is saved to ``fib1.pyf`` (see ``-h`` flag) and
-  its contents is shown below.
-
-  .. include:: fib1.pyf
-     :literal:
-
-* Next, we'll teach F2PY that the argument ``n`` is an input argument
-  (use ``intent(in)`` attribute) and that the result, i.e. the
-  contents of ``a`` after calling Fortran function ``FIB``, should be
-  returned to Python (use ``intent(out)`` attribute). In addition, an
-  array ``a`` should be created dynamically using the size given by
-  the input argument ``n`` (use ``depend(n)`` attribute to indicate
-  dependence relation).
-
-  The content of a modified version of ``fib1.pyf`` (saved as
-  ``fib2.pyf``) is as follows:
-
-  .. include:: fib2.pyf
-     :literal:
-
-* And finally, we build the extension module by running
-
-  ::
-
-    python -m numpy.f2py -c fib2.pyf fib1.f
-
-In Python::
-
-  >>> import fib2
-  >>> print fib2.fib.__doc__
-  fib - Function signature:
-    a = fib(n)
-  Required arguments:
-    n : input int
-  Return objects:
-    a : rank-1 array('d') with bounds (n)
-
-  >>> print fib2.fib(8)
-  [  0.   1.   1.   2.   3.   5.   8.  13.]
-
-.. note::
-
-  * Clearly, the signature of ``fib2.fib`` now corresponds to the
-    intention of Fortran subroutine ``FIB`` more closely: given the
-    number ``n``, ``fib2.fib`` returns the first ``n`` Fibonacci numbers
-    as a NumPy array. Also, the new Python signature ``fib2.fib``
-    rules out any surprises that we experienced with ``fib1.fib``.
-
-  * Note that by default using single ``intent(out)`` also implies
-    ``intent(hide)``. Argument that has ``intent(hide)`` attribute
-    specified, will not be listed in the argument list of a wrapper
-    function.
-
-The quick and smart way
-========================
-
-The "smart way" of wrapping Fortran functions, as explained above, is
-suitable for wrapping (e.g. third party) Fortran codes for which
-modifications to their source codes are not desirable nor even
-possible.
-
-However, if editing Fortran codes is acceptable, then the generation
-of an intermediate signature file can be skipped in most
-cases. Namely, F2PY specific attributes can be inserted directly to
-Fortran source codes using the so-called F2PY directive. A F2PY
-directive defines special comment lines (starting with ``Cf2py``, for
-example) which are ignored by Fortran compilers but F2PY interprets
-them as normal lines.
-
-Here is shown a `modified version of the example Fortran code`__, saved
-as ``fib3.f``:
-
-.. include:: fib3.f
-   :literal:
-
-__ fib3.f
-
-Building the extension module can be now carried out in one command::
-
-  python -m numpy.f2py -c -m fib3 fib3.f
-
-Notice that the resulting wrapper to ``FIB`` is as "smart" as in
-previous case::
-
-  >>> import fib3
-  >>> print fib3.fib.__doc__
-  fib - Function signature:
-    a = fib(n)
-  Required arguments:
-    n : input int
-  Return objects:
-    a : rank-1 array('d') with bounds (n)
-
-  >>> print fib3.fib(8)
-  [  0.   1.   1.   2.   3.   5.   8.  13.]
index d6773a76f77e5925a9211bf201c7fd521e24dc1d..4921396512cc68dddd664732f89102a7f980fb5c 100644 (file)
@@ -19,7 +19,7 @@ from Python.
 .. toctree::
    :maxdepth: 2
 
-   getting-started
+   f2py.getting-started
    signature-file
    python-usage
    usage
index 1ec212f8bd22cbccee2af73ff5ff28d340046c7c..e3c7580416f25dc4699424a890395dbb7b8d7282 100644 (file)
@@ -1,12 +1,11 @@
 >>> import moddata
->>> print moddata.mod.__doc__
+>>> print(moddata.mod.__doc__)
 i - 'i'-scalar
 x - 'i'-array(4)
 a - 'f'-array(2,3)
 foo - Function signature:
   foo()
 
-
 >>> moddata.mod.i = 5  
 >>> moddata.mod.x[:2] = [1,2]
 >>> moddata.mod.a = [[1,2,3],[4,5,6]]
@@ -20,4 +19,6 @@ foo - Function signature:
  Setting a(1,2)=a(1,2)+3
 >>> moddata.mod.a               # a is Fortran-contiguous
 array([[ 1.,  5.,  3.],
-       [ 4.,  5.,  6.]],'f')
+       [ 4.,  5.,  6.]], dtype=float32)
+>>> moddata.mod.a.flags.f_contiguous
+True
index 60167d01a1dc68808c50d3280b41d65429022af3..a7f2b3d860df9749ec9b45010ead9dbbed327880 100644 (file)
@@ -8,7 +8,7 @@ type objects.  Routine wrappers are callable ``fortran`` type objects
 while wrappers to Fortran data have attributes referring to data
 objects.
 
-All ``fortran`` type object have attribute ``_cpointer`` that contains
+All ``fortran`` type objects have attribute ``_cpointer`` that contains
 CObject referring to the C pointer of the corresponding Fortran/C
 function or variable in C level. Such CObjects can be used as a
 callback argument of F2PY generated functions to bypass Python C/API
@@ -34,7 +34,7 @@ Scalar arguments
 =================
 
 In general, a scalar argument of a F2PY generated wrapper function can
-be ordinary Python scalar (integer, float, complex number) as well as
+be an ordinary Python scalar (integer, float, complex number) as well as
 an arbitrary sequence object (list, tuple, array, string) of
 scalars. In the latter case, the first element of the sequence object
 is passed to Fortran routine as a scalar argument.
@@ -45,7 +45,7 @@ float), F2PY does not raise any exception. In complex to real
 type-casting only the real part of a complex number is used.
 
 ``intent(inout)`` scalar arguments are assumed to be array objects in
-order to *in situ* changes to be effective. It is recommended to use
+order to have *in situ* changes be effective. It is recommended to use
 arrays with proper type but also other types work.
 
 Consider the following Fortran 77 code:
@@ -75,8 +75,7 @@ expected, the string is truncated. If the length is smaller that
 expected, additional memory is allocated and filled with ``\0``.
 
 Because Python strings are immutable, an ``intent(inout)`` argument
-expects an array version of a string in order to *in situ* changes to
-be effective.
+expects an array version of a string in order to have *in situ* changes be effective.
 
 Consider the following Fortran 77 code:
 
@@ -99,7 +98,7 @@ arbitrary sequences that can be transformed to NumPy array objects.
 An exception is ``intent(inout)`` array arguments that always must be
 proper-contiguous and have proper type, otherwise an exception is
 raised. Another exception is ``intent(inplace)`` array arguments that
-attributes will be changed in-situ if the argument has different type
+attributes will be changed *in situ* if the argument has different type
 than expected (see ``intent(inplace)`` attribute for more
 information).
 
@@ -129,11 +128,9 @@ and C-contiguous if the order is as follows::
 
   A[0,0] A[0,1] A[1,0] A[1,1]
 
-To test whether an array is C-contiguous, use ``.iscontiguous()``
-method of NumPy arrays.  To test for Fortran contiguity, all
-F2PY generated extension modules provide a function
-``has_column_major_storage(<array>)``. This function is equivalent to
-``<array>.flags.f_contiguous`` but more efficient.
+To test whether an array is C-contiguous, use the ``.flags.c_contiguous``
+attribute of NumPy arrays.  To test for Fortran contiguity, use the
+``.flags.f_contiguous`` attribute.
 
 Usually there is no need to worry about how the arrays are stored in
 memory and whether the wrapped functions, being either Fortran or C
@@ -146,11 +143,9 @@ the physical memory in your computer, then a care must be taken to use
 always proper-contiguous and proper type arguments.
 
 To transform input arrays to column major storage order before passing
-them to Fortran routines, use a function
-``as_column_major_storage(<array>)`` that is provided by all F2PY
-generated extension modules.
+them to Fortran routines, use the function ``numpy.asfortranarray(<array>)``.
 
-Consider Fortran 77 code:
+Consider the following Fortran 77 code:
 
   .. include:: array.f
      :literal:
index 8aff097c2f1e2a57fc2b2d246cf5f10a9b77ae98..3bb45ed686eb2fba5a281f214522c65f28ea312d 100644 (file)
@@ -1,21 +1,24 @@
 >>> import scalar
->>> print scalar.foo.__doc__
-foo - Function signature:
-  foo(a,b)
-Required arguments:
-  a : input float
-  b : in/output rank-0 array(float,'d')
+>>> print(scalar.foo.__doc__)
+foo(a,b)
+
+Wrapper for ``foo``.
+
+Parameters
+----------
+a : input float
+b : in/output rank-0 array(float,'d')
  
->>> scalar.foo(2,3)   
+>>> scalar.foo(2, 3)   
      A=  2. B=  3.
  INCREMENT A AND B
  NEW A=  3. B=  4.
 >>> import numpy
->>> a=numpy.array(2)   # these are integer rank-0 arrays
->>> b=numpy.array(3)
->>> scalar.foo(a,b)
+>>> a = numpy.array(2)   # these are integer rank-0 arrays
+>>> b = numpy.array(3)
+>>> scalar.foo(a, b)
      A=  2. B=  3.
  INCREMENT A AND B
  NEW A=  3. B=  4.
->>> print a,b            # note that only b is changed in situ
+>>> print(a, b)          # note that only b is changed in situ
 2 4
index 54af7729988ee039d09687f26c3c21322a8e41b5..479acc004d601212a92b5f84eab2dad89b9e682e 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy.distutils.core import Extension
 
 ext1 = Extension(name = 'scalar',
index 8e5a9710cbe4abe1940cc90c5bdfd6b8f86704a8..3a163ee23d87632a73e80bab9f1d18c25fe4d4cb 100644 (file)
@@ -14,7 +14,7 @@ Signature files may contain arbitrary Fortran code (so that Fortran
 codes can be considered as signature files). F2PY silently ignores
 Fortran constructs that are irrelevant for creating the interface.
 However, this includes also syntax errors. So, be careful not making
-ones;-).
+ones ;-).
 
 In general, the contents of signature files is case-sensitive.  When
 scanning Fortran codes and writing a signature file, F2PY lowers all
index 7f99d13f9a6231a988cf46112638d141b6248912..bd5832d88072d46ac9e78df7b81c24770755bdb5 100644 (file)
@@ -1,5 +1,5 @@
 >>> import spam
 >>> status = spam.system('whoami')
 pearu
->> status = spam.system('blah')
+>>> status = spam.system('blah')
 sh: line 1: blah: command not found
\ No newline at end of file
index cbae6b784987b68ac95737d927faa6a58acb892e..e8f7854d93413629bcb3f5481891cd89ff063951 100644 (file)
@@ -1,19 +1,22 @@
 >>> import mystring
->>> print mystring.foo.__doc__
-foo - Function signature:
-  foo(a,b,c,d)
-Required arguments:
-  a : input string(len=5)
-  b : in/output rank-0 array(string(len=5),'c')
-  c : input string(len=-1)
-  d : in/output rank-0 array(string(len=-1),'c')
+>>> print(mystring.foo.__doc__)
+foo(a,b,c,d)
 
->>> import numpy
->>> a=numpy.array('123')
->>> b=numpy.array('123')
->>> c=numpy.array('123')
->>> d=numpy.array('123')
->>> mystring.foo(a,b,c,d)
+Wrapper for ``foo``.
+
+Parameters
+----------
+a : input string(len=5)
+b : in/output rank-0 array(string(len=5),'c')
+c : input string(len=-1)
+d : in/output rank-0 array(string(len=-1),'c')
+
+>>> from numpy import array
+>>> a = array(b'123\0\0')
+>>> b = array(b'123\0\0')
+>>> c = array(b'123')
+>>> d = array(b'123')
+>>> mystring.foo(a, b, c, d)
  A=123
  B=123
  C=123
@@ -23,5 +26,5 @@ Required arguments:
  B=B23
  C=C23
  D=D23
->>> a.tostring(),b.tostring(),c.tostring(),d.tostring()
-('123', 'B23', '123', 'D23')
+>>> a[()], b[()], c[()], d[()]
+(b'123', b'B23', b'123', b'D2')
index 5043ec43095889bbf2583ddd5131c497be1004fe..6c3b4b6efb1e6fdb68b00ec3240f6859c824d5b8 100644 (file)
@@ -6,11 +6,9 @@ F2PY can be used either as a command line tool ``f2py`` or as a Python
 module ``numpy.f2py``. While we try to install the command line tool as part
 of the numpy setup, some platforms like Windows make it difficult to
 reliably put the executable on the ``PATH``. We will refer to ``f2py``
-in this document but you may have to run it as a module
+in this document but you may have to run it as a module::
 
-```
-python -m numpy.f2py
-```
+   python -m numpy.f2py
 
 If you run ``f2py`` with no arguments, and the line ``numpy Version`` at the
 end matches the NumPy version printed from ``python -m numpy.f2py``, then you
@@ -50,9 +48,9 @@ distinguished by the usage of ``-c`` and ``-h`` switches:
 
    ::
 
-     f2py <options> <fortran files>          \
-       [[ only: <fortran functions>  : ]     \
-        [ skip: <fortran functions>  : ]]... \
+     f2py -m <modulename> <options> <fortran files>   \
+       [[ only: <fortran functions>  : ]              \
+        [ skip: <fortran functions>  : ]]...          \
        [<fortran files> ...]
 
    The constructed extension module is saved as
@@ -79,11 +77,9 @@ distinguished by the usage of ``-c`` and ``-h`` switches:
      functions. This feature enables using arbitrary C functions
      (defined in ``<includefile>``) in F2PY generated wrappers.
 
-     This option is deprecated. Use ``usercode`` statement to specify
-     C code snippets directly in signature files
+     .. note:: This option is deprecated. Use ``usercode`` statement to specify C code snippets directly in signature files.
 
    ``--[no-]wrap-functions``
-
      Create Fortran subroutine wrappers to Fortran functions.
      ``--wrap-functions`` is default because it ensures maximum
      portability and compiler independence.
@@ -161,12 +157,29 @@ distinguished by the usage of ``-c`` and ``-h`` switches:
      for ``-l``.
  
    ``link-<resource>``
      Link extension module with <resource> as defined by
      ``numpy_distutils/system_info.py``. E.g. to link with optimized
      LAPACK libraries (vecLib on MacOSX, ATLAS elsewhere), use
      ``--link-lapack_opt``. See also ``--help-link`` switch.
+
+   .. note:: The ``f2py -c`` option must be applied either to an existing ``.pyf`` file (plus the source/object/library files) or one must specify the ``-m <modulename>`` option (plus the sources/object/library files). Use one of the following options:
+
+      ::
+
+         f2py -c -m fib1 fib1.f
+
+      or
+
+      ::
+
+         f2py -m fib1 fib1.f -h fib1.pyf
+         f2py -c fib1.pyf fib1.f
+
+      For more information, see `Building C and C++ Extensions`__ Python documentation for details.
+
+      __ https://docs.python.org/3/extending/building.html
+
+
    When building an extension module, a combination of the following
    macros may be required for non-gcc Fortran compilers::
  
index 9dcbb6267ddfb77bc1799a63d0954bdfe8f08432..6b6f366dfcd91bdba7e0a2eb26b48f84522b82e1 100644 (file)
@@ -6,6 +6,10 @@ Standard array subclasses
 
 .. currentmodule:: numpy
 
+.. for doctests
+   >>> import numpy as np
+   >>> np.random.seed(1)
+
 .. note::
 
     Subclassing a ``numpy.ndarray`` is possible but if your goal is to create
@@ -404,23 +408,25 @@ alias for "matrix "in NumPy.
 
 Example 1: Matrix creation from a string
 
->>> a=mat('1 2 3; 4 5 3')
->>> print (a*a.T).I
-[[ 0.2924 -0.1345]
- [-0.1345  0.0819]]
+>>> a = np.mat('1 2 3; 4 5 3')
+>>> print((a*a.T).I)
+    [[ 0.29239766 -0.13450292]
+     [-0.13450292  0.08187135]]
+
 
 Example 2: Matrix creation from nested sequence
 
->>> mat([[1,5,10],[1.0,3,4j]])
+>>> np.mat([[1,5,10],[1.0,3,4j]])
 matrix([[  1.+0.j,   5.+0.j,  10.+0.j],
         [  1.+0.j,   3.+0.j,   0.+4.j]])
 
 Example 3: Matrix creation from an array
 
->>> mat(random.rand(3,3)).T
-matrix([[ 0.7699,  0.7922,  0.3294],
-        [ 0.2792,  0.0101,  0.9219],
-        [ 0.3398,  0.7571,  0.8197]])
+>>> np.mat(np.random.rand(3,3)).T
+matrix([[4.17022005e-01, 3.02332573e-01, 1.86260211e-01],
+        [7.20324493e-01, 1.46755891e-01, 3.45560727e-01],
+        [1.14374817e-04, 9.23385948e-02, 3.96767474e-01]])
+
 
 Memory-mapped file arrays
 =========================
@@ -451,15 +457,15 @@ array actually get written to disk.
 
 Example:
 
->>> a = memmap('newfile.dat', dtype=float, mode='w+', shape=1000)
+>>> a = np.memmap('newfile.dat', dtype=float, mode='w+', shape=1000)
 >>> a[10] = 10.0
 >>> a[30] = 30.0
 >>> del a
->>> b = fromfile('newfile.dat', dtype=float)
->>> print b[10], b[30]
+>>> b = np.fromfile('newfile.dat', dtype=float)
+>>> print(b[10], b[30])
 10.0 30.0
->>> a = memmap('newfile.dat', dtype=float)
->>> print a[10], a[30]
+>>> a = np.memmap('newfile.dat', dtype=float)
+>>> print(a[10], a[30])
 10.0 30.0
 
 
@@ -590,9 +596,9 @@ This default iterator selects a sub-array of dimension :math:`N-1`
 from the array. This can be a useful construct for defining recursive
 algorithms. To loop over the entire array requires :math:`N` for-loops.
 
->>> a = arange(24).reshape(3,2,4)+10
+>>> a = np.arange(24).reshape(3,2,4)+10
 >>> for val in a:
-...     print 'item:', val
+...     print('item:', val)
 item: [[10 11 12 13]
  [14 15 16 17]]
 item: [[18 19 20 21]
@@ -614,7 +620,7 @@ an iterator that will cycle over the entire array in C-style
 contiguous order.
 
 >>> for i, val in enumerate(a.flat):
-...     if i%5 == 0: print i, val
+...     if i%5 == 0: print(i, val)
 0 10
 5 15
 10 20
@@ -636,8 +642,8 @@ N-dimensional enumeration
 Sometimes it may be useful to get the N-dimensional index while
 iterating. The ndenumerate iterator can achieve this.
 
->>> for i, val in ndenumerate(a):
-...     if sum(i)%5 == 0: print i, val
+>>> for i, val in np.ndenumerate(a):
+...     if sum(i)%5 == 0: print(i, val)
 (0, 0, 0) 10
 (1, 1, 3) 25
 (2, 0, 3) 29
@@ -658,8 +664,8 @@ objects as inputs and returns an iterator that returns tuples
 providing each of the input sequence elements in the broadcasted
 result.
 
->>> for val in broadcast([[1,0],[2,3]],[0,1]):
-...     print val
+>>> for val in np.broadcast([[1,0],[2,3]],[0,1]):
+...     print(val)
 (1, 0)
 (0, 1)
 (2, 0)
index 9c45e04c77ecf43199acccc0cea5fd46f4021dd0..9ce77424a4f8c721d5baefa0b923633dec5e4276 100644 (file)
@@ -54,7 +54,7 @@ letters, for a "Not A Time" value.
 
     NAT (not a time):
 
-    >>> numpy.datetime64('nat')
+    >>> np.datetime64('nat')
     numpy.datetime64('NaT')
 
 When creating an array of datetimes from a string, it is still possible
@@ -67,7 +67,8 @@ datetime type with generic units.
     array(['2007-07-13', '2006-01-13', '2010-08-13'], dtype='datetime64[D]')
 
     >>> np.array(['2001-01-01T12:00', '2002-02-03T13:56:03.172'], dtype='datetime64')
-    array(['2001-01-01T12:00:00.000-0600', '2002-02-03T13:56:03.172-0600'], dtype='datetime64[ms]')
+    array(['2001-01-01T12:00:00.000', '2002-02-03T13:56:03.172'],
+          dtype='datetime64[ms]')
 
 
 The datetime type works with many common NumPy functions, for
@@ -85,7 +86,7 @@ example :func:`arange` can be used to generate ranges of dates.
            '2005-02-17', '2005-02-18', '2005-02-19', '2005-02-20',
            '2005-02-21', '2005-02-22', '2005-02-23', '2005-02-24',
            '2005-02-25', '2005-02-26', '2005-02-27', '2005-02-28'],
-           dtype='datetime64[D]')
+          dtype='datetime64[D]')
 
 The datetime object represents a single moment in time. If two
 datetimes have different units, they may still be representing
@@ -98,9 +99,17 @@ because the moment of time is still being represented exactly.
     >>> np.datetime64('2005') == np.datetime64('2005-01-01')
     True
 
-    >>> np.datetime64('2010-03-14T15Z') == np.datetime64('2010-03-14T15:00:00.00Z')
+    >>> np.datetime64('2010-03-14T15') == np.datetime64('2010-03-14T15:00:00.00')
     True
 
+.. deprecated:: 1.11.0
+
+  NumPy does not store timezone information. For backwards compatibility, datetime64
+  still parses timezone offsets, which it handles by converting to
+  UTC. This behaviour is deprecated and will raise an error in the
+  future.
+
+
 Datetime and Timedelta Arithmetic
 =================================
 
@@ -114,13 +123,13 @@ data type also accepts the string "NAT" in place of the number for a "Not A Time
 
 .. admonition:: Example
 
-    >>> numpy.timedelta64(1, 'D')
+    >>> np.timedelta64(1, 'D')
     numpy.timedelta64(1,'D')
 
-    >>> numpy.timedelta64(4, 'h')
+    >>> np.timedelta64(4, 'h')
     numpy.timedelta64(4,'h')
 
-    >>> numpy.timedelta64('nAt')
+    >>> np.timedelta64('nAt')
     numpy.timedelta64('NaT')
 
 Datetimes and Timedeltas work together to provide ways for
@@ -135,7 +144,7 @@ simple datetime calculations.
     numpy.datetime64('2009-01-21')
 
     >>> np.datetime64('2011-06-15T00:00') + np.timedelta64(12, 'h')
-    numpy.datetime64('2011-06-15T12:00-0500')
+    numpy.datetime64('2011-06-15T12:00')
 
     >>> np.timedelta64(1,'W') / np.timedelta64(1,'D')
     7.0
@@ -143,10 +152,10 @@ simple datetime calculations.
     >>> np.timedelta64(1,'W') % np.timedelta64(10,'D')
     numpy.timedelta64(7,'D')
 
-    >>> numpy.datetime64('nat') - numpy.datetime64('2009-01-01')
+    >>> np.datetime64('nat') - np.datetime64('2009-01-01')
     numpy.timedelta64('NaT','D')
 
-    >>> numpy.datetime64('2009-01-01') + numpy.timedelta64('nat')
+    >>> np.datetime64('2009-01-01') + np.timedelta64('nat')
     numpy.datetime64('NaT')
 
 There are two Timedelta units ('Y', years and 'M', months) which are treated
@@ -275,16 +284,16 @@ is necessary to get a desired answer.
     The first business day on or after a date:
 
     >>> np.busday_offset('2011-03-20', 0, roll='forward')
-    numpy.datetime64('2011-03-21','D')
+    numpy.datetime64('2011-03-21')
     >>> np.busday_offset('2011-03-22', 0, roll='forward')
-    numpy.datetime64('2011-03-22','D')
+    numpy.datetime64('2011-03-22')
 
     The first business day strictly after a date:
 
     >>> np.busday_offset('2011-03-20', 1, roll='backward')
-    numpy.datetime64('2011-03-21','D')
+    numpy.datetime64('2011-03-21')
     >>> np.busday_offset('2011-03-22', 1, roll='backward')
-    numpy.datetime64('2011-03-23','D')
+    numpy.datetime64('2011-03-23')
 
 The function is also useful for computing some kinds of days
 like holidays. In Canada and the U.S., Mother's day is on
@@ -294,7 +303,7 @@ weekmask.
 .. admonition:: Example
 
     >>> np.busday_offset('2012-05', 1, roll='forward', weekmask='Sun')
-    numpy.datetime64('2012-05-13','D')
+    numpy.datetime64('2012-05-13')
 
 When performance is important for manipulating many business dates
 with one particular choice of weekmask and holidays, there is
@@ -315,7 +324,7 @@ To test a datetime64 value to see if it is a valid day, use :func:`is_busday`.
     True
     >>> a = np.arange(np.datetime64('2011-07-11'), np.datetime64('2011-07-18'))
     >>> np.is_busday(a)
-    array([ True,  True,  True,  True,  True, False, False], dtype='bool')
+    array([ True,  True,  True,  True,  True, False, False])
 
 np.busday_count():
 ``````````````````
@@ -359,38 +368,3 @@ Some examples::
     weekmask = "Mon Tue Wed Thu Fri"
     # any amount of whitespace is allowed; abbreviations are case-sensitive.
     weekmask = "MonTue Wed  Thu\tFri"
-
-Changes with NumPy 1.11
-=======================
-
-In prior versions of NumPy, the datetime64 type always stored
-times in UTC. By default, creating a datetime64 object from a string or
-printing it would convert from or to local time::
-
-    # old behavior
-    >>> np.datetime64('2000-01-01T00:00:00')
-    numpy.datetime64('2000-01-01T00:00:00-0800')  # note the timezone offset -08:00
-
-A consensus of datetime64 users agreed that this behavior is undesirable
-and at odds with how datetime64 is usually used (e.g., by pandas_). For
-most use cases, a timezone naive datetime type is preferred, similar to the
-``datetime.datetime`` type in the Python standard library. Accordingly,
-datetime64 no longer assumes that input is in local time, nor does it print
-local times::
-
-    >>> np.datetime64('2000-01-01T00:00:00')
-    numpy.datetime64('2000-01-01T00:00:00')
-
-For backwards compatibility, datetime64 still parses timezone offsets, which
-it handles by converting to UTC. However, the resulting datetime is timezone
-naive::
-
-    >>> np.datetime64('2000-01-01T00:00:00-08')
-    DeprecationWarning: parsing timezone aware datetimes is deprecated; this will raise an error in the future
-    numpy.datetime64('2000-01-01T08:00:00')
-
-As a corollary to this change, we no longer prohibit casting between datetimes
-with date units and datetimes with timeunits. With timezone naive datetimes,
-the rule for casting from dates to times is no longer ambiguous.
-
-.. _pandas: http://pandas.pydata.org
index 231707b118bf26b55aee209499489630bd64a149..f8d40b13c5ad35ba4b7450b46165189fbee97fe8 100644 (file)
@@ -87,22 +87,22 @@ Sub-arrays always have a C-contiguous memory layout.
 
    >>> dt = np.dtype([('name', np.unicode_, 16), ('grades', np.float64, (2,))])
    >>> dt['name']
-   dtype('|U16')
+   dtype('<U16')
    >>> dt['grades']
-   dtype(('float64',(2,)))
+   dtype(('<f8', (2,)))
 
    Items of an array of this data type are wrapped in an :ref:`array
    scalar <arrays.scalars>` type that also has two fields:
 
    >>> x = np.array([('Sarah', (8.0, 7.0)), ('John', (6.0, 7.0))], dtype=dt)
    >>> x[1]
-   ('John', [6.0, 7.0])
+   ('John', [6., 7.])
    >>> x[1]['grades']
-   array([ 6.,  7.])
+   array([6.,  7.])
    >>> type(x[1])
-   <type 'numpy.void'>
+   <class 'numpy.void'>
    >>> type(x[1]['grades'])
-   <type 'numpy.ndarray'>
+   <class 'numpy.ndarray'>
 
 .. _arrays.dtypes.constructing:
 
@@ -156,6 +156,14 @@ Array-scalar types
 
 Generic types
 
+    .. deprecated NumPy 1.19::
+
+        The use of generic types is deprecated. This is because it can be
+        unexpected in a context such as ``arr.astype(dtype=np.floating)``.
+        ``arr.astype(dtype=np.floating)`` which casts an array of ``float32``
+        to an array of ``float64``, even though ``float32`` is a subdtype of
+        ``np.floating``.
+
     The generic hierarchical type objects convert to corresponding
     type objects according to the associations:
 
@@ -179,8 +187,7 @@ Built-in Python types
     :class:`float`    :class:`float\_`
     :class:`complex`  :class:`cfloat`
     :class:`bytes`    :class:`bytes\_`
-    :class:`str`      :class:`bytes\_` (Python2) or :class:`unicode\_` (Python3)
-    :class:`unicode`  :class:`unicode\_`
+    :class:`str`      :class:`str\_`
     :class:`buffer`   :class:`void`
     (all others)      :class:`object_`
     ================  ===============
@@ -196,6 +203,11 @@ Built-in Python types
        >>> dt = np.dtype(int)     # Python-compatible integer
        >>> dt = np.dtype(object)  # Python object
 
+    .. note::
+
+        All other types map to ``object_`` for convenience. Code should expect
+        that such types may map to a specific (new) dtype in future the future.
+
 Types with ``.dtype``
 
     Any type object with a ``dtype`` attribute: The attribute will be
@@ -304,7 +316,7 @@ Type strings
    .. admonition:: Example
 
       >>> dt = np.dtype('uint32')   # 32-bit unsigned integer
-      >>> dt = np.dtype('Float64')  # 64-bit floating-point number
+      >>> dt = np.dtype('float64')  # 64-bit floating-point number
 
 .. index::
    triple: dtype; construction; from tuple
@@ -328,13 +340,14 @@ Type strings
     The first argument is any object that can be converted into a
     fixed-size data-type object. The second argument is the desired
     shape of this type. If the shape parameter is 1, then the
-    data-type object is equivalent to fixed dtype. If *shape* is a
-    tuple, then the new dtype defines a sub-array of the given shape.
+    data-type object used to be equivalent to fixed dtype. This behaviour is
+    deprecated since NumPy 1.17 and will raise an error in the future.
+    If *shape* is a tuple, then the new dtype defines a sub-array of the given
+    shape.
 
     .. admonition:: Example
 
        >>> dt = np.dtype((np.int32, (2,2)))          # 2 x 2 integer sub-array
-       >>> dt = np.dtype(('U10', 1))                 # 10-character string
        >>> dt = np.dtype(('i4, (2,3)f8, f4', (2,3))) # 2 x 3 structured sub-array
 
 .. index::
@@ -411,7 +424,7 @@ Type strings
        an 8-bit unsigned integer:
 
        >>> dt = np.dtype({'names': ['r','g','b','a'],
-       ...                'formats': [uint8, uint8, uint8, uint8]})
+       ...                'formats': [np.uint8, np.uint8, np.uint8, np.uint8]})
 
        Data type with fields ``r`` and ``b`` (with the given titles),
        both being 8-bit unsigned integers, the first at byte position
@@ -441,8 +454,8 @@ Type strings
        byte position 0), ``col2`` (32-bit float at byte position 10),
        and ``col3`` (integers at byte position 14):
 
-       >>> dt = np.dtype({'col1': ('U10', 0), 'col2': (float32, 10),
-           'col3': (int, 14)})
+       >>> dt = np.dtype({'col1': ('U10', 0), 'col2': (np.float32, 10),
+       ...                'col3': (int, 14)})
 
 ``(base_dtype, new_dtype)``
 
@@ -464,7 +477,7 @@ Type strings
        32-bit integer, whose first two bytes are interpreted as an integer
        via field ``real``, and the following two bytes via field ``imag``.
 
-       >>> dt = np.dtype((np.int32,{'real':(np.int16, 0),'imag':(np.int16, 2)})
+       >>> dt = np.dtype((np.int32,{'real':(np.int16, 0),'imag':(np.int16, 2)}))
 
        32-bit integer, which is interpreted as consisting of a sub-array
        of shape ``(4,)`` containing 8-bit integers:
index 8ec8d8330beaec92df550777fe4e1f472bba5bf1..56b99f272c1020424e029abf06cd3c7291b586af 100644 (file)
@@ -1,3 +1,6 @@
+.. for doctests
+   >>> import numpy as np
+
 .. _arrays.indexing:
 
 Indexing
@@ -114,7 +117,7 @@ concepts to remember include:
       array([5, 6, 7, 8, 9])
 
 - If the number of objects in the selection tuple is less than
-  *N* , then ``:`` is assumed for any subsequent dimensions.
+  *N*, then ``:`` is assumed for any subsequent dimensions.
 
   .. admonition:: Example
 
@@ -265,10 +268,10 @@ understood with an example.
     one needs to select all elements *explicitly*. Using the method explained
     previously one could write:
 
-    >>> x = array([[ 0,  1,  2],
-    ...            [ 3,  4,  5],
-    ...            [ 6,  7,  8],
-    ...            [ 9, 10, 11]])
+    >>> x = np.array([[ 0,  1,  2],
+    ...               [ 3,  4,  5],
+    ...               [ 6,  7,  8],
+    ...               [ 9, 10, 11]])
     >>> rows = np.array([[0, 0],
     ...                  [3, 3]], dtype=np.intp)
     >>> columns = np.array([[0, 2],
@@ -392,7 +395,7 @@ smaller than *x* it is identical to filling it with :const:`False`.
 
     >>> x = np.array([[1., 2.], [np.nan, 3.], [np.nan, np.nan]])
     >>> x[~np.isnan(x)]
-    array([ 1.,  2.,  3.])
+    array([1., 2., 3.])
 
     Or wish to add a constant to all negative elements:
 
@@ -422,18 +425,6 @@ with.
     array([[0, 1],
            [1, 1]])
 
-    But if ``rowsum`` would have two dimensions as well:
-
-    >>> rowsum = x.sum(-1, keepdims=True)
-    >>> rowsum.shape
-    (3, 1)
-    >>> x[rowsum <= 2, :]    # fails
-    IndexError: too many indices
-    >>> x[rowsum <= 2]
-    array([0, 1])
-
-    The last one giving only the first elements because of the extra dimension.
-    Compare ``rowsum.nonzero()`` to understand this example.
 
 Combining multiple Boolean indexing arrays or a Boolean with an integer
 indexing array can best be understood with the
@@ -447,10 +438,10 @@ also supports boolean arrays and will work without any surprises.
     advanced integer index. Using the :func:`ix_` function this can be done
     with:
 
-    >>> x = array([[ 0,  1,  2],
-    ...            [ 3,  4,  5],
-    ...            [ 6,  7,  8],
-    ...            [ 9, 10, 11]])
+    >>> x = np.array([[ 0,  1,  2],
+    ...               [ 3,  4,  5],
+    ...               [ 6,  7,  8],
+    ...               [ 9, 10, 11]])
     >>> rows = (x.sum(-1) % 2) == 0
     >>> rows
     array([False,  True, False,  True])
index 831d211bc5169bfa3a7fe3ca52b8e72ef142ea8e..689240c7d6c5d6d3a365675a9cc5a1ea754878e4 100644 (file)
@@ -37,7 +37,7 @@ objects implementing the :class:`buffer` or :ref:`array
 
    >>> x = np.array([[1, 2, 3], [4, 5, 6]], np.int32)
    >>> type(x)
-   <type 'numpy.ndarray'>
+   <class 'numpy.ndarray'>
    >>> x.shape
    (2, 3)
    >>> x.dtype
@@ -47,6 +47,7 @@ objects implementing the :class:`buffer` or :ref:`array
 
    >>> # The element of x in the *second* row, *third* column, namely, 6.
    >>> x[1, 2]
+   6
 
    For example :ref:`slicing <arrays.indexing>` can produce views of
    the array:
@@ -132,6 +133,11 @@ Both the C and Fortran orders are :term:`contiguous`, *i.e.,*
 single-segment, memory layouts, in which every part of the
 memory block can be accessed by some combination of the indices.
 
+.. note::
+
+    `Contiguous arrays` and `single-segment arrays` are synonymous
+    and are used interchangeably throughout the documentation.
+
 While a C-style and Fortran-style contiguous array, which has the corresponding
 flags set, can be addressed with the above strides, the actual strides may be
 different. This can happen in two cases:
@@ -157,10 +163,12 @@ base offset itself is a multiple of `self.itemsize`. Understanding
 
 .. note::
 
-    Points (1) and (2) are not yet applied by default. Beginning with
-    NumPy 1.8.0, they are applied consistently only if the environment
-    variable ``NPY_RELAXED_STRIDES_CHECKING=1`` was defined when NumPy
-    was built. Eventually this will become the default.
+    Points (1) and (2) can currently be disabled by the compile time
+    environmental variable ``NPY_RELAXED_STRIDES_CHECKING=0``,
+    which was the default before NumPy 1.10.
+    No users should have to do this. ``NPY_RELAXED_STRIDES_DEBUG=1``
+    can be used to help find errors when incorrectly relying on the strides
+    in C-extension code (see below warning).
 
     You can check whether this option was enabled when your NumPy was
     built by looking at the value of ``np.ones((10,1),
@@ -371,6 +379,7 @@ Many of these methods take an argument named *axis*. In such cases,
    A 3-dimensional array of size 3 x 3 x 3, summed over each of its
    three axes
 
+   >>> x = np.arange(27).reshape((3,3,3))
    >>> x
    array([[[ 0,  1,  2],
            [ 3,  4,  5],
@@ -512,10 +521,6 @@ Arithmetic:
    - Any third argument to :func:`pow()` is silently ignored,
      as the underlying :func:`ufunc <power>` takes only two arguments.
 
-   - The three division operators are all defined; :obj:`div` is active
-     by default, :obj:`truediv` is active when
-     :obj:`__future__` division is in effect.
-
    - Because :class:`ndarray` is a built-in type (written in C), the
      ``__r{op}__`` special methods are not directly defined.
 
diff --git a/doc/source/reference/arrays.nditer.cython.rst b/doc/source/reference/arrays.nditer.cython.rst
new file mode 100644 (file)
index 0000000..2cc7763
--- /dev/null
@@ -0,0 +1,147 @@
+Putting the Inner Loop in Cython
+================================
+
+Those who want really good performance out of their low level operations
+should strongly consider directly using the iteration API provided
+in C, but for those who are not comfortable with C or C++, Cython
+is a good middle ground with reasonable performance tradeoffs. For
+the :class:`nditer` object, this means letting the iterator take care
+of broadcasting, dtype conversion, and buffering, while giving the inner
+loop to Cython.
+
+For our example, we'll create a sum of squares function. To start,
+let's implement this function in straightforward Python. We want to
+support an 'axis' parameter similar to the numpy :func:`sum` function,
+so we will need to construct a list for the `op_axes` parameter.
+Here's how this looks.
+
+.. admonition:: Example
+
+    >>> def axis_to_axeslist(axis, ndim):
+    ...     if axis is None:
+    ...         return [-1] * ndim
+    ...     else:
+    ...         if type(axis) is not tuple:
+    ...             axis = (axis,)
+    ...         axeslist = [1] * ndim
+    ...         for i in axis:
+    ...             axeslist[i] = -1
+    ...         ax = 0
+    ...         for i in range(ndim):
+    ...             if axeslist[i] != -1:
+    ...                 axeslist[i] = ax
+    ...                 ax += 1
+    ...         return axeslist
+    ...
+    >>> def sum_squares_py(arr, axis=None, out=None):
+    ...     axeslist = axis_to_axeslist(axis, arr.ndim)
+    ...     it = np.nditer([arr, out], flags=['reduce_ok',
+    ...                                       'buffered', 'delay_bufalloc'],
+    ...                 op_flags=[['readonly'], ['readwrite', 'allocate']],
+    ...                 op_axes=[None, axeslist],
+    ...                 op_dtypes=['float64', 'float64'])
+    ...     with it:
+    ...         it.operands[1][...] = 0
+    ...         it.reset()
+    ...         for x, y in it:
+    ...             y[...] += x*x
+    ...         return it.operands[1]
+    ...
+    >>> a = np.arange(6).reshape(2,3)
+    >>> sum_squares_py(a)
+    array(55.0)
+    >>> sum_squares_py(a, axis=-1)
+    array([  5.,  50.])
+
+To Cython-ize this function, we replace the inner loop (y[...] += x*x) with
+Cython code that's specialized for the float64 dtype. With the
+'external_loop' flag enabled, the arrays provided to the inner loop will
+always be one-dimensional, so very little checking needs to be done.
+
+Here's the listing of sum_squares.pyx::
+
+    import numpy as np
+    cimport numpy as np
+    cimport cython
+
+    def axis_to_axeslist(axis, ndim):
+        if axis is None:
+            return [-1] * ndim
+        else:
+            if type(axis) is not tuple:
+                axis = (axis,)
+            axeslist = [1] * ndim
+            for i in axis:
+                axeslist[i] = -1
+            ax = 0
+            for i in range(ndim):
+                if axeslist[i] != -1:
+                    axeslist[i] = ax
+                    ax += 1
+            return axeslist
+
+    @cython.boundscheck(False)
+    def sum_squares_cy(arr, axis=None, out=None):
+        cdef np.ndarray[double] x
+        cdef np.ndarray[double] y
+        cdef int size
+        cdef double value
+
+        axeslist = axis_to_axeslist(axis, arr.ndim)
+        it = np.nditer([arr, out], flags=['reduce_ok', 'external_loop',
+                                          'buffered', 'delay_bufalloc'],
+                    op_flags=[['readonly'], ['readwrite', 'allocate']],
+                    op_axes=[None, axeslist],
+                    op_dtypes=['float64', 'float64'])
+        with it:
+            it.operands[1][...] = 0
+            it.reset()
+            for xarr, yarr in it:
+                x = xarr
+                y = yarr
+                size = x.shape[0]
+                for i in range(size):
+                   value = x[i]
+                   y[i] = y[i] + value * value
+            return it.operands[1]
+
+On this machine, building the .pyx file into a module looked like the
+following, but you may have to find some Cython tutorials to tell you
+the specifics for your system configuration.::
+
+    $ cython sum_squares.pyx
+    $ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -I/usr/include/python2.7 -fno-strict-aliasing -o sum_squares.so sum_squares.c
+
+Running this from the Python interpreter produces the same answers
+as our native Python/NumPy code did.
+
+.. admonition:: Example
+
+    >>> from sum_squares import sum_squares_cy
+    >>> a = np.arange(6).reshape(2,3)
+    >>> sum_squares_cy(a)
+    array(55.0)
+    >>> sum_squares_cy(a, axis=-1)
+    array([  5.,  50.])
+
+Doing a little timing in IPython shows that the reduced overhead and
+memory allocation of the Cython inner loop is providing a very nice
+speedup over both the straightforward Python code and an expression
+using NumPy's built-in sum function.::
+
+    >>> a = np.random.rand(1000,1000)
+
+    >>> timeit sum_squares_py(a, axis=-1)
+    10 loops, best of 3: 37.1 ms per loop
+
+    >>> timeit np.sum(a*a, axis=-1)
+    10 loops, best of 3: 20.9 ms per loop
+
+    >>> timeit sum_squares_cy(a, axis=-1)
+    100 loops, best of 3: 11.8 ms per loop
+
+    >>> np.all(sum_squares_cy(a, axis=-1) == np.sum(a*a, axis=-1))
+    True
+
+    >>> np.all(sum_squares_py(a, axis=-1) == np.sum(a*a, axis=-1))
+    True
index 7dab09a71329c958f9e07479f28cc5450078c9d3..2db12a40852fab44617095fb227c4923a6272a7b 100644 (file)
@@ -1,5 +1,9 @@
 .. currentmodule:: numpy
 
+.. for doctests
+   The last section on Cython is 'included' at the end of this file. The tests
+   for that section are disabled.
+
 .. _arrays.nditer:
 
 *********************
@@ -218,21 +222,21 @@ produce identical results to the ones in the previous section.
     >>> it = np.nditer(a, flags=['f_index'])
     >>> while not it.finished:
     ...     print("%d <%d>" % (it[0], it.index), end=' ')
-    ...     it.iternext()
+    ...     is_not_finished = it.iternext()
     ...
     0 <0> 1 <2> 2 <4> 3 <1> 4 <3> 5 <5>
 
     >>> it = np.nditer(a, flags=['multi_index'])
     >>> while not it.finished:
     ...     print("%d <%s>" % (it[0], it.multi_index), end=' ')
-    ...     it.iternext()
+    ...     is_not_finished = it.iternext()
     ...
     0 <(0, 0)> 1 <(0, 1)> 2 <(0, 2)> 3 <(1, 0)> 4 <(1, 1)> 5 <(1, 2)>
 
     >>> with np.nditer(a, flags=['multi_index'], op_flags=['writeonly']) as it:
     ...     while not it.finished:
     ...         it[0] = it.multi_index[1] - it.multi_index[0]
-    ...         it.iternext()
+    ...         is_not_finished = it.iternext()
     ...
     >>> a
     array([[ 0,  1,  2],
@@ -316,12 +320,13 @@ specified as an iterator flag.
     ...                 op_dtypes=['complex128']):
     ...     print(np.sqrt(x), end=' ')
     ...
-    1.73205080757j 1.41421356237j 1j 0j (1+0j) (1.41421356237+0j)
+    1.7320508075688772j 1.4142135623730951j 1j 0j (1+0j) (1.4142135623730951+0j)
 
     >>> for x in np.nditer(a, flags=['buffered'], op_dtypes=['complex128']):
     ...     print(np.sqrt(x), end=' ')
     ...
-    1.73205080757j 1.41421356237j 1j 0j (1+0j) (1.41421356237+0j)
+    1.7320508075688772j 1.4142135623730951j 1j 0j (1+0j) (1.4142135623730951+0j)
+
 
 The iterator uses NumPy's casting rules to determine whether a specific
 conversion is permitted. By default, it enforces 'safe' casting. This means,
@@ -405,8 +410,8 @@ which includes the input shapes to help diagnose the problem.
     ...     print("%d:%d" % (x,y), end=' ')
     ...
     Traceback (most recent call last):
-      File "<stdin>", line 1, in <module>
-    ValueError: operands could not be broadcast together with shapes (2) (2,3)
+    ...
+    ValueError: operands could not be broadcast together with shapes (2,) (2,3)
 
 Iterator-Allocated Output Arrays
 --------------------------------
@@ -482,9 +487,9 @@ reasons.
 
     >>> square(np.arange(6).reshape(2,3), out=b)
     Traceback (most recent call last):
-      File "<stdin>", line 1, in <module>
-      File "<stdin>", line 4, in square
-    ValueError: non-broadcastable output operand with shape (3) doesn't match the broadcast shape (2,3)
+      ...
+    ValueError: non-broadcastable output operand with shape (3,) doesn't
+    match the broadcast shape (2,3)
 
 Outer Product Iteration
 -----------------------
@@ -550,7 +555,7 @@ For a simple example, consider taking the sum of all elements in an array.
 
     >>> a = np.arange(24).reshape(2,3,4)
     >>> b = np.array(0)
-    >>> with np.nditer([a, b], flags=['reduce_ok', 'external_loop'],
+    >>> with np.nditer([a, b], flags=['reduce_ok'],
     ...                     op_flags=[['readonly'], ['readwrite']]) as it:
     ...     for x,y in it:
     ...         y[...] += x
@@ -568,7 +573,7 @@ sums along the last axis of `a`.
 .. admonition:: Example
 
     >>> a = np.arange(24).reshape(2,3,4)
-    >>> it = np.nditer([a, None], flags=['reduce_ok', 'external_loop'],
+    >>> it = np.nditer([a, None], flags=['reduce_ok'],
     ...             op_flags=[['readonly'], ['readwrite', 'allocate']],
     ...             op_axes=[None, [0,1,-1]])
     >>> with it:
@@ -602,7 +607,7 @@ buffering.
 .. admonition:: Example
 
     >>> a = np.arange(24).reshape(2,3,4)
-    >>> it = np.nditer([a, None], flags=['reduce_ok', 'external_loop',
+    >>> it = np.nditer([a, None], flags=['reduce_ok',
     ...                                  'buffered', 'delay_bufalloc'],
     ...             op_flags=[['readonly'], ['readwrite', 'allocate']],
     ...             op_axes=[None, [0,1,-1]])
@@ -617,150 +622,8 @@ buffering.
     array([[ 6, 22, 38],
            [54, 70, 86]])
 
-Putting the Inner Loop in Cython
-================================
-
-Those who want really good performance out of their low level operations
-should strongly consider directly using the iteration API provided
-in C, but for those who are not comfortable with C or C++, Cython
-is a good middle ground with reasonable performance tradeoffs. For
-the :class:`nditer` object, this means letting the iterator take care
-of broadcasting, dtype conversion, and buffering, while giving the inner
-loop to Cython.
-
-For our example, we'll create a sum of squares function. To start,
-let's implement this function in straightforward Python. We want to
-support an 'axis' parameter similar to the numpy :func:`sum` function,
-so we will need to construct a list for the `op_axes` parameter.
-Here's how this looks.
-
-.. admonition:: Example
-
-    >>> def axis_to_axeslist(axis, ndim):
-    ...     if axis is None:
-    ...         return [-1] * ndim
-    ...     else:
-    ...         if type(axis) is not tuple:
-    ...             axis = (axis,)
-    ...         axeslist = [1] * ndim
-    ...         for i in axis:
-    ...             axeslist[i] = -1
-    ...         ax = 0
-    ...         for i in range(ndim):
-    ...             if axeslist[i] != -1:
-    ...                 axeslist[i] = ax
-    ...                 ax += 1
-    ...         return axeslist
-    ...
-    >>> def sum_squares_py(arr, axis=None, out=None):
-    ...     axeslist = axis_to_axeslist(axis, arr.ndim)
-    ...     it = np.nditer([arr, out], flags=['reduce_ok', 'external_loop',
-    ...                                       'buffered', 'delay_bufalloc'],
-    ...                 op_flags=[['readonly'], ['readwrite', 'allocate']],
-    ...                 op_axes=[None, axeslist],
-    ...                 op_dtypes=['float64', 'float64'])
-    ...     with it:
-    ...         it.operands[1][...] = 0
-    ...         it.reset()
-    ...         for x, y in it:
-    ...             y[...] += x*x
-    ...         return it.operands[1]
-    ...
-    >>> a = np.arange(6).reshape(2,3)
-    >>> sum_squares_py(a)
-    array(55.0)
-    >>> sum_squares_py(a, axis=-1)
-    array([  5.,  50.])
-
-To Cython-ize this function, we replace the inner loop (y[...] += x*x) with
-Cython code that's specialized for the float64 dtype. With the
-'external_loop' flag enabled, the arrays provided to the inner loop will
-always be one-dimensional, so very little checking needs to be done.
-
-Here's the listing of sum_squares.pyx::
-
-    import numpy as np
-    cimport numpy as np
-    cimport cython
-
-    def axis_to_axeslist(axis, ndim):
-        if axis is None:
-            return [-1] * ndim
-        else:
-            if type(axis) is not tuple:
-                axis = (axis,)
-            axeslist = [1] * ndim
-            for i in axis:
-                axeslist[i] = -1
-            ax = 0
-            for i in range(ndim):
-                if axeslist[i] != -1:
-                    axeslist[i] = ax
-                    ax += 1
-            return axeslist
-
-    @cython.boundscheck(False)
-    def sum_squares_cy(arr, axis=None, out=None):
-        cdef np.ndarray[double] x
-        cdef np.ndarray[double] y
-        cdef int size
-        cdef double value
-
-        axeslist = axis_to_axeslist(axis, arr.ndim)
-        it = np.nditer([arr, out], flags=['reduce_ok', 'external_loop',
-                                          'buffered', 'delay_bufalloc'],
-                    op_flags=[['readonly'], ['readwrite', 'allocate']],
-                    op_axes=[None, axeslist],
-                    op_dtypes=['float64', 'float64'])
-        with it:
-            it.operands[1][...] = 0
-            it.reset()
-            for xarr, yarr in it:
-                x = xarr
-                y = yarr
-                size = x.shape[0]
-                for i in range(size):
-                   value = x[i]
-                   y[i] = y[i] + value * value
-            return it.operands[1]
-
-On this machine, building the .pyx file into a module looked like the
-following, but you may have to find some Cython tutorials to tell you
-the specifics for your system configuration.::
-
-    $ cython sum_squares.pyx
-    $ gcc -shared -pthread -fPIC -fwrapv -O2 -Wall -I/usr/include/python2.7 -fno-strict-aliasing -o sum_squares.so sum_squares.c
-
-Running this from the Python interpreter produces the same answers
-as our native Python/NumPy code did.
-
-.. admonition:: Example
-
-    >>> from sum_squares import sum_squares_cy
-    >>> a = np.arange(6).reshape(2,3)
-    >>> sum_squares_cy(a)
-    array(55.0)
-    >>> sum_squares_cy(a, axis=-1)
-    array([  5.,  50.])
-
-Doing a little timing in IPython shows that the reduced overhead and
-memory allocation of the Cython inner loop is providing a very nice
-speedup over both the straightforward Python code and an expression
-using NumPy's built-in sum function.::
-
-    >>> a = np.random.rand(1000,1000)
-
-    >>> timeit sum_squares_py(a, axis=-1)
-    10 loops, best of 3: 37.1 ms per loop
-
-    >>> timeit np.sum(a*a, axis=-1)
-    10 loops, best of 3: 20.9 ms per loop
-
-    >>> timeit sum_squares_cy(a, axis=-1)
-    100 loops, best of 3: 11.8 ms per loop
-
-    >>> np.all(sum_squares_cy(a, axis=-1) == np.sum(a*a, axis=-1))
-    True
+.. for doctests
+   Include Cython section separately. Those tests are skipped entirely via an
+   entry in RST_SKIPLIST
 
-    >>> np.all(sum_squares_py(a, axis=-1) == np.sum(a*a, axis=-1))
-    True
+.. include:: arrays.nditer.cython.rst
index 0530a5747a9be55dc80eace0fbfb51fe71c440d8..56fc59da39d2151d5e48cff1537e63a99bf135c2 100644 (file)
@@ -426,10 +426,8 @@ From other objects
     may be 0. Also, if *op* is not already an array (or does not
     expose the array interface), then a new array will be created (and
     filled from *op* using the sequence protocol). The new array will
-    have :c:data:`NPY_ARRAY_DEFAULT` as its flags member. The *context* argument
-    is passed to the :obj:`~numpy.class.__array__` method of *op* and is only used if
-    the array is constructed that way. Almost always this
-    parameter is ``NULL``.
+    have :c:data:`NPY_ARRAY_DEFAULT` as its flags member. The *context*
+    argument is unused.
 
     .. c:var:: NPY_ARRAY_C_CONTIGUOUS
 
@@ -552,71 +550,16 @@ From other objects
         PyArray_Descr** out_dtype, int* out_ndim, npy_intp* out_dims, \
         PyArrayObject** out_arr, PyObject* context)
 
-    .. versionadded:: 1.6
+    .. deprecated:: NumPy 1.19
 
-    Retrieves the array parameters for viewing/converting an arbitrary
-    PyObject* to a NumPy array. This allows the "innate type and shape"
-    of Python list-of-lists to be discovered without
-    actually converting to an array. PyArray_FromAny calls this function
-    to analyze its input.
-
-    In some cases, such as structured arrays and the :obj:`~numpy.class.__array__` interface,
-    a data type needs to be used to make sense of the object.  When
-    this is needed, provide a Descr for 'requested_dtype', otherwise
-    provide NULL. This reference is not stolen. Also, if the requested
-    dtype doesn't modify the interpretation of the input, out_dtype will
-    still get the "innate" dtype of the object, not the dtype passed
-    in 'requested_dtype'.
-
-    If writing to the value in 'op' is desired, set the boolean
-    'writeable' to 1.  This raises an error when 'op' is a scalar, list
-    of lists, or other non-writeable 'op'. This differs from passing
-    :c:data:`NPY_ARRAY_WRITEABLE` to PyArray_FromAny, where the writeable array may
-    be a copy of the input.
-
-    When success (0 return value) is returned, either out_arr
-    is filled with a non-NULL PyArrayObject and
-    the rest of the parameters are untouched, or out_arr is
-    filled with NULL, and the rest of the parameters are filled.
-
-    Typical usage:
+        Unless NumPy is made aware of an issue with this, this function
+        is scheduled for rapid removal without replacement.
 
-    .. code-block:: c
+    .. versionchanged:: NumPy 1.19
 
-        PyArrayObject *arr = NULL;
-        PyArray_Descr *dtype = NULL;
-        int ndim = 0;
-        npy_intp dims[NPY_MAXDIMS];
+        `context` is never used. Its use results in an error.
 
-        if (PyArray_GetArrayParamsFromObject(op, NULL, 1, &dtype,
-                                            &ndim, &dims, &arr, NULL) < 0) {
-            return NULL;
-        }
-        if (arr == NULL) {
-            /*
-            ... validate/change dtype, validate flags, ndim, etc ...
-             Could make custom strides here too */
-            arr = PyArray_NewFromDescr(&PyArray_Type, dtype, ndim,
-                                        dims, NULL,
-                                        fortran ? NPY_ARRAY_F_CONTIGUOUS : 0,
-                                        NULL);
-            if (arr == NULL) {
-                return NULL;
-            }
-            if (PyArray_CopyObject(arr, op) < 0) {
-                Py_DECREF(arr);
-                return NULL;
-            }
-        }
-        else {
-            /*
-            ... in this case the other parameters weren't filled, just
-                validate and possibly copy arr itself ...
-            */
-        }
-        /*
-        ... use arr ...
-        */
+    .. versionadded:: 1.6
 
 .. c:function:: PyObject* PyArray_CheckFromAny( \
         PyObject* op, PyArray_Descr* dtype, int min_depth, int max_depth, \
@@ -677,10 +620,8 @@ From other objects
         PyObject* op, PyArray_Descr* dtype, PyObject* context)
 
     Return an ndarray object from a Python object that exposes the
-    :obj:`~numpy.class.__array__` method. The :obj:`~numpy.class.__array__` method can take 0, 1, or 2
-    arguments ([dtype, context]) where *context* is used to pass
-    information about where the :obj:`~numpy.class.__array__` method is being called
-    from (currently only used in ufuncs).
+    :obj:`~numpy.class.__array__` method. The :obj:`~numpy.class.__array__`
+    method can take 0, or 1 argument ``([dtype])``. ``context`` is unused.
 
 .. c:function:: PyObject* PyArray_ContiguousFromAny( \
         PyObject* op, int typenum, int min_depth, int max_depth)
@@ -859,15 +800,16 @@ General check of Python Type
     conversion occurs. Otherwise, out will contain a borrowed
     reference to :c:data:`Py_NotImplemented` and no error condition is set.
 
-.. c:function:: PyArray_HasArrayInterfaceType(op, type, context, out)
+.. c:function:: PyArray_HasArrayInterfaceType(op, dtype, context, out)
 
     If ``op`` implements any part of the array interface, then ``out``
     will contain a new reference to the newly created ndarray using
     the interface or ``out`` will contain ``NULL`` if an error during
     conversion occurs. Otherwise, out will contain a borrowed
     reference to Py_NotImplemented and no error condition is set.
-    This version allows setting of the type and context in the part of
-    the array interface that looks for the :obj:`~numpy.class.__array__` attribute.
+    This version allows setting of the dtype in the part of the array interface
+    that looks for the :obj:`~numpy.class.__array__` attribute. `context` is
+    unused.
 
 .. c:function:: PyArray_IsZeroDim(op)
 
@@ -892,7 +834,7 @@ General check of Python Type
 .. c:function:: PyArray_IsPythonScalar(op)
 
     Evaluates true if *op* is a builtin Python scalar object (int,
-    float, complex, str, unicode, long, bool).
+    float, complex, bytes, str, long, bool).
 
 .. c:function:: PyArray_IsAnyScalar(op)
 
@@ -1223,7 +1165,7 @@ Converting data types
 
 .. c:function:: int PyArray_ObjectType(PyObject* op, int mintype)
 
-    This function is superceded by :c:func:`PyArray_MinScalarType` and/or
+    This function is superseded by :c:func:`PyArray_MinScalarType` and/or
     :c:func:`PyArray_ResultType`.
 
     This function is useful for determining a common type that two or
@@ -1237,7 +1179,7 @@ Converting data types
 .. c:function:: void PyArray_ArrayType( \
         PyObject* op, PyArray_Descr* mintype, PyArray_Descr* outtype)
 
-    This function is superceded by :c:func:`PyArray_ResultType`.
+    This function is superseded by :c:func:`PyArray_ResultType`.
 
     This function works similarly to :c:func:`PyArray_ObjectType` (...)
     except it handles flexible arrays. The *mintype* argument can have
@@ -1248,21 +1190,25 @@ Converting data types
 .. c:function:: PyArrayObject** PyArray_ConvertToCommonType( \
         PyObject* op, int* n)
 
-    The functionality this provides is largely superceded by iterator
+    The functionality this provides is largely superseded by iterator
     :c:type:`NpyIter` introduced in 1.6, with flag
     :c:data:`NPY_ITER_COMMON_DTYPE` or with the same dtype parameter for
     all operands.
 
     Convert a sequence of Python objects contained in *op* to an array
     of ndarrays each having the same data type. The type is selected
-    based on the typenumber (larger type number is chosen over a
-    smaller one) ignoring objects that are only scalars. The length of
-    the sequence is returned in *n*, and an *n* -length array of
-    :c:type:`PyArrayObject` pointers is the return value (or ``NULL`` if an
-    error occurs). The returned array must be freed by the caller of
-    this routine (using :c:func:`PyDataMem_FREE` ) and all the array objects
-    in it ``DECREF`` 'd or a memory-leak will occur. The example
-    template-code below shows a typically usage:
+    in the same way as `PyArray_ResultType`. The length of the sequence is
+    returned in *n*, and an *n* -length array of :c:type:`PyArrayObject`
+    pointers is the return value (or ``NULL`` if an error occurs).
+    The returned array must be freed by the caller of this routine
+    (using :c:func:`PyDataMem_FREE` ) and all the array objects in it
+    ``DECREF`` 'd or a memory-leak will occur. The example template-code
+    below shows a typically usage:
+
+    .. versionchanged:: 1.18.0
+       A mix of scalars and zero-dimensional arrays now produces a type
+       capable of holding the scalar value.
+       Previously priority was given to the dtype of the arrays.
 
     .. code-block:: c
 
@@ -1435,7 +1381,7 @@ An ndarray can have a data segment that is not a simple contiguous
 chunk of well-behaved memory you can manipulate. It may not be aligned
 with word boundaries (very important on some platforms). It might have
 its data in a different byte-order than the machine recognizes. It
-might not be writeable. It might be in Fortan-contiguous order. The
+might not be writeable. It might be in Fortran-contiguous order. The
 array flags are used to indicate what can be said about data
 associated with an array.
 
@@ -1940,7 +1886,7 @@ Item selection and manipulation
 
     Equivalent to :meth:`ndarray.sort<numpy.ndarray.sort>` (*self*, *axis*, *kind*).
     Return an array with the items of *self* sorted along *axis*. The array
-    is sorted using the algorithm denoted by *kind* , which is an integer/enum pointing
+    is sorted using the algorithm denoted by *kind*, which is an integer/enum pointing
     to the type of sorting algorithms used.
 
 .. c:function:: PyObject* PyArray_ArgSort(PyArrayObject* self, int axis)
@@ -2484,7 +2430,7 @@ an element copier function as a primitive.::
 Array Iterators
 ---------------
 
-As of NumPy 1.6.0, these array iterators are superceded by
+As of NumPy 1.6.0, these array iterators are superseded by
 the new array iterator, :c:type:`NpyIter`.
 
 An array iterator is a simple way to access the elements of an
@@ -2510,7 +2456,7 @@ this useful approach to looping over an array.
     stride and that axis will be used.
 
 .. c:function:: PyObject *PyArray_BroadcastToShape( \
-        PyObject* arr, npy_intp *dimensions, int nd)
+        PyObject* arr, npy_intp const *dimensions, int nd)
 
     Return an array iterator that is broadcast to iterate as an array
     of the shape provided by *dimensions* and *nd*.
@@ -3080,7 +3026,7 @@ Other conversions
 
     .. code-block:: c
 
-        #define error_converting(x) (((x) == -1) && PyErr_Occurred()
+        #define error_converting(x) (((x) == -1) && PyErr_Occurred())
 
 .. c:function:: npy_intp PyArray_PyIntAsIntp(PyObject* op)
 
index 7e00322f96a857e6896cf0b99799b8762f67b5a5..0c46475cfccd34583fd791339b8f0dd5153b4512 100644 (file)
@@ -193,7 +193,7 @@ Those can be useful for precise floating point comparison.
 .. c:function:: int npy_get_floatstatus_barrier(char*)
 
     Get floating point status. A pointer to a local variable is passed in to
-    prevent aggressive compiler optimizations from reodering this function call
+    prevent aggressive compiler optimizations from reordering this function call
     relative to the code setting the status, which could lead to incorrect
     results.
 
@@ -219,7 +219,7 @@ Those can be useful for precise floating point comparison.
 .. c:function:: int npy_clear_floatstatus_barrier(char*)
 
     Clears the floating point status. A pointer to a local variable is passed in to
-    prevent aggressive compiler optimizations from reodering this function call.
+    prevent aggressive compiler optimizations from reordering this function call.
     Returns the previous status mask.
 
     .. versionadded:: 1.15.0
@@ -249,9 +249,14 @@ Linking against the core math library in an extension
 To use the core math library in your own extension, you need to add the npymath
 compile and link options to your extension in your setup.py:
 
+        .. hidden in a comment so as to be included in refguide but not rendered documentation
+                >>> import numpy.distutils.misc_util
+                >>> config = np.distutils.misc_util.Configuration(None, '', '.')
+                >>> with open('foo.c', 'w') as f: pass
+
         >>> from numpy.distutils.misc_util import get_info
         >>> info = get_info('npymath')
-        >>> config.add_extension('foo', sources=['foo.c'], extra_info=info)
+        >>> _ = config.add_extension('foo', sources=['foo.c'], extra_info=info)
 
 In other words, the usage of info is exactly the same as when using blas_info
 and co.
index 56fe8e473f914e97294b23a21c42adb927a17b84..bb1ed154e9b0867689f2802763ba516d7f47db01 100644 (file)
@@ -21,7 +21,7 @@ experience at first. Be assured that the task becomes easier with
 practice, and you may be surprised at how simple the C-code can be to
 understand. Even if you don't think you can write C-code from scratch,
 it is much easier to understand and modify already-written source code
-then create it *de novo*.
+than create it *de novo*.
 
 Python extensions are especially straightforward to understand because
 they all have a very similar structure. Admittedly, NumPy is not a
index 336dff211576b5f64f77e0de0b842670361eb388..60d8e420b81b7ba7c66712e9235be8ed36c37878 100644 (file)
@@ -452,9 +452,9 @@ PyArrayDescr_Type and PyArray_Descr
            PyArray_ScalarKindFunc *scalarkind;
            int **cancastscalarkindto;
            int *cancastto;
-           PyArray_FastClipFunc *fastclip;
-           PyArray_FastPutmaskFunc *fastputmask;
-           PyArray_FastTakeFunc *fasttake;
+           PyArray_FastClipFunc *fastclip;  /* deprecated */
+           PyArray_FastPutmaskFunc *fastputmask;  /* deprecated */
+           PyArray_FastTakeFunc *fasttake;  /* deprecated */
            PyArray_ArgFunc *argmin;
        } PyArray_ArrFuncs;
 
@@ -641,6 +641,16 @@ PyArrayDescr_Type and PyArray_Descr
     .. c:member:: void fastclip( \
             void *in, npy_intp n_in, void *min, void *max, void *out)
 
+        .. deprecated:: 1.17
+            The use of this function will give a deprecation warning when
+            ``np.clip``. Instead of this function, the datatype must
+            instead use ``PyUFunc_RegisterLoopForDescr`` to attach a custom
+            loop to ``np.core.umath.clip``, ``np.minimum``, and ``np.maximum``.
+
+        .. deprecated:: 1.19
+            Setting this function is deprecated and should always be ``NULL``,
+            if set, it will be ignored.
+
         A function that reads ``n_in`` items from ``in``, and writes to
         ``out`` the read value if it is within the limits pointed to by
         ``min`` and ``max``, or the corresponding limit if outside. The
@@ -650,6 +660,10 @@ PyArrayDescr_Type and PyArray_Descr
     .. c:member:: void fastputmask( \
             void *in, void *mask, npy_intp n_in, void *values, npy_intp nv)
 
+        .. deprecated:: 1.19
+            Setting this function is deprecated and should always be ``NULL``,
+            if set, it will be ignored.
+
         A function that takes a pointer ``in`` to an array of ``n_in``
         items, a pointer ``mask`` to an array of ``n_in`` boolean
         values, and a pointer ``vals`` to an array of ``nv`` items.
@@ -662,6 +676,10 @@ PyArrayDescr_Type and PyArray_Descr
             npy_intp n_outer, npy_intp m_middle, npy_intp nelem, \
             NPY_CLIPMODE clipmode)
 
+        .. deprecated:: 1.19
+            Setting this function is deprecated and should always be ``NULL``,
+            if set, it will be ignored.
+
         A function that takes a pointer ``src`` to a C contiguous,
         behaved segment, interpreted as a 3-dimensional array of shape
         ``(n_outer, nindarray, nelem)``, a pointer ``indarray`` to a
index c9cc60141bfcc999599f102e3bc433599a2c3002..16ddde58c8ace5696358714fa29cf36e7d5cffee 100644 (file)
@@ -77,7 +77,7 @@ Functions
         signature:
 
         .. c:function:: void loopfunc(
-                char** args, npy_intp* dimensions, npy_intp* steps, void* data)
+                char** args, npy_intp const *dimensions, npy_intp const *steps, void* data)
 
             *args*
 
@@ -108,8 +108,10 @@ Functions
             .. code-block:: c
 
                 static void
-                double_add(char **args, npy_intp *dimensions, npy_intp *steps,
-                   void *extra)
+                double_add(char **args,
+                           npy_intp const *dimensions,
+                           npy_intp const *steps,
+                           void *extra)
                 {
                     npy_intp i;
                     npy_intp is1 = steps[0], is2 = steps[1];
@@ -253,15 +255,16 @@ Functions
 .. c:function:: int PyUFunc_GenericFunction( \
         PyUFuncObject* self, PyObject* args, PyObject* kwds, PyArrayObject** mps)
 
-    A generic ufunc call. The ufunc is passed in as *self*, the arguments
-    to the ufunc as *args* and *kwds*. The *mps* argument is an array of
-    :c:type:`PyArrayObject` pointers whose values are discarded and which
-    receive the converted input arguments as well as the ufunc outputs
-    when success is returned. The user is responsible for managing this
-    array and receives a new reference for each array in *mps*. The total
-    number of arrays in *mps* is given by *self* ->nin + *self* ->nout.
+    .. deprecated:: NumPy 1.19
 
-    Returns 0 on success, -1 on error.
+        Unless NumPy is made aware of an issue with this, this function
+        is scheduled for rapid removal without replacement.
+
+    Instead of this function ``PyObject_Call(ufunc, args, kwds)`` should be
+    used. The above function differs from this because it ignores support
+    for non-array, or array subclasses as inputs.
+    To ensure identical behaviour, it may be necessary to convert all inputs
+    using ``PyArray_FromAny(obj, NULL, 0, 0, NPY_ARRAY_ENSUREARRAY, NULL)``.
 
 .. c:function:: int PyUFunc_checkfperr(int errmask, PyObject* errobj)
 
@@ -311,37 +314,37 @@ functions stored in the functions member of the PyUFuncObject
 structure.
 
 .. c:function:: void PyUFunc_f_f_As_d_d( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_d_d( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_f_f( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_g_g( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_F_F_As_D_D( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_F_F( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_D_D( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_G_G( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_e_e( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_e_e_As_f_f( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_e_e_As_d_d( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
     Type specific, core 1-d functions for ufuncs where each
     calculation is obtained by calling a function taking one input
@@ -357,37 +360,37 @@ structure.
     C-function that takes double and returns double.
 
 .. c:function:: void PyUFunc_ff_f_As_dd_d( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_ff_f( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_dd_d( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_gg_g( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_FF_F_As_DD_D( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_DD_D( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_FF_F( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_GG_G( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_ee_e( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_ee_e_As_ff_f( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_ee_e_As_dd_d( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
     Type specific, core 1-d functions for ufuncs where each
     calculation is obtained by calling a function taking two input
@@ -400,10 +403,10 @@ structure.
     to use the underlying function that takes a different data type.
 
 .. c:function:: void PyUFunc_O_O( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
 .. c:function:: void PyUFunc_OO_O( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
     One-input, one-output, and two-input, one-output core 1-d functions
     for the :c:data:`NPY_OBJECT` data type. These functions handle reference
@@ -413,7 +416,7 @@ structure.
     PyObject *)`` for :c:func:`PyUFunc_OO_O`.
 
 .. c:function:: void PyUFunc_O_O_method( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
     This general purpose 1-d core function assumes that *func* is a string
     representing a method of the input object. For each
@@ -421,7 +424,7 @@ structure.
     and its *func* method is called returning the result to the output array.
 
 .. c:function:: void PyUFunc_OO_O_method( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
     This general purpose 1-d core function assumes that *func* is a
     string representing a method of the input object that takes one
@@ -431,7 +434,7 @@ structure.
     of *args*.
 
 .. c:function:: void PyUFunc_On_Om( \
-        char** args, npy_intp* dimensions, npy_intp* steps, void* func)
+        char** args, npy_intp const *dimensions, npy_intp const *steps, void* func)
 
     This is the 1-d core function used by the dynamic ufuncs created
     by umath.frompyfunc(function, nin, nout). In this case *func* is a
index a22db3e8e3a3d041aa467268226424bd6c46d14f..6057c7ed0b8b10d210639a446c3e3734c4eaf1d3 100644 (file)
@@ -15,6 +15,11 @@ keyword arguments to pass to the setup function (by passing the
 dictionary obtained from the todict() method of the class). More
 information is available in the :ref:`distutils-user-guide`.
 
+The choice and location of linked libraries such as BLAS and LAPACK as well as
+include paths and other such build options can be specified in a ``site.cfg``
+file located in the NumPy root repository or a ``.numpy-site.cfg`` file in your
+home directory. See the ``site.cfg.example`` example file included in the NumPy
+repository or sdist for documentation.
 
 .. index::
    single: distutils
@@ -112,6 +117,11 @@ install the C library, you just use the method `add_installed_library` instead o
 `add_library`, which takes the same arguments except for an additional
 ``install_dir`` argument::
 
+  .. hidden in a comment so as to be included in refguide but not rendered documentation
+    >>> import numpy.distutils.misc_util
+    >>> config = np.distutils.misc_util.Configuration(None, '', '.')
+    >>> with open('foo.c', 'w') as f: pass
+
   >>> config.add_installed_library('foo', sources=['foo.c'], install_dir='lib')
 
 npy-pkg-config files
@@ -175,8 +185,8 @@ Reusing a C library from another package
 Info are easily retrieved from the `get_info` function in
 `numpy.distutils.misc_util`::
 
-  >>> info = get_info('npymath')
-  >>> config.add_extension('foo', sources=['foo.c'], extra_info=**info)
+  >>> info = np.distutils.misc_util.get_info('npymath')
+  >>> config.add_extension('foo', sources=['foo.c'], extra_info=info)
 
 An additional list of paths to look for .ini files can be given to `get_info`.
 
diff --git a/doc/source/reference/global_state.rst b/doc/source/reference/global_state.rst
new file mode 100644 (file)
index 0000000..2a16339
--- /dev/null
@@ -0,0 +1,85 @@
+.. _global_state:
+
+************
+Global State
+************
+
+NumPy has a few import-time, compile-time, or runtime options
+which change the global behaviour.
+Most of these are related to performance or for debugging
+purposes and will not be interesting to the vast majority
+of users.
+
+
+Performance-Related Options
+===========================
+
+Number of Threads used for Linear Algebra
+-----------------------------------------
+
+NumPy itself is normally intentionally limited to a single thread
+during function calls, however it does support multiple Python
+threads running at the same time.
+Note that for performant linear algebra NumPy uses a BLAS backend
+such as OpenBLAS or MKL, which may use multiple threads that may
+be controlled by environment variables such as ``OMP_NUM_THREADS``
+depending on what is used.
+One way to control the number of threads is the package
+`threadpoolctl <https://pypi.org/project/threadpoolctl/>`_
+
+
+Madvise Hugepage on Linux
+-------------------------
+
+When working with very large arrays on modern Linux kernels,
+you can experience a significant speedup when
+`transparent hugepage <https://www.kernel.org/doc/html/latest/admin-guide/mm/transhuge.html>`_
+is used.
+The current system policy for transparent hugepages can be seen by::
+
+    cat /sys/kernel/mm/transparent_hugepage/enabled
+
+When set to ``madvise`` NumPy will typically use hugepages for a performance
+boost. This behaviour can be modified by setting the environment variable::
+
+    NUMPY_MADVISE_HUGEPAGE=0
+
+or setting it to ``1`` to always enable it. When not set, the default
+is to use madvise on Kernels 4.6 and newer. These kernels presumably
+experience a large speedup with hugepage support.
+This flag is checked at import time.
+
+
+Interoperability-Related Options
+================================
+
+The array function protocol which allows array-like objects to
+hook into the NumPy API is currently enabled by default.
+This option exists since NumPy 1.16 and is enabled by default since
+NumPy 1.17. It can be disabled using::
+
+    NUMPY_EXPERIMENTAL_ARRAY_FUNCTION=0
+
+See also :py:meth:`numpy.class.__array_function__` for more information.
+This flag is checked at import time.
+
+
+Debugging-Related Options
+=========================
+
+Relaxed Strides Checking
+------------------------
+
+The *compile-time* environment variables::
+
+    NPY_RELAXED_STRIDES_DEBUG=0
+    NPY_RELAXED_STRIDES_CHECKING=1
+
+control how NumPy reports contiguity for arrays.
+The default that it is enabled and the debug mode is disabled.
+This setting should always be enabled. Setting the
+debug option can be interesting for testing code written
+in C which iterates through arrays that may or may not be
+contiguous in memory.
+Most users will have no reason to change these, for details
+please see the `memory layout <memory-layout>`_ documentation.
index 6742d605ac292b394926be9264d14470c633707d..2e1dcafa2a5e512222d08700b1283c87ce3b540b 100644 (file)
@@ -12,7 +12,7 @@ NumPy Reference
 
 This reference manual details functions, modules, and objects
 included in NumPy, describing what they are and what they do.
-For learning how to use NumPy, see also :ref:`user`.
+For learning how to use NumPy, see the :ref:`complete documentation <numpy_docs_mainpage>`.
 
 
 .. toctree::
@@ -22,6 +22,7 @@ For learning how to use NumPy, see also :ref:`user`.
    constants
    ufuncs
    routines
+   global_state
    distutils
    distutils_guide
    c-api/index
index 03d081bf99e7d5d90e67fd4458e849880437b920..aacfabcd3f4020bf6cf7a6ec2f89b3c5f178bd04 100644 (file)
@@ -1,3 +1,5 @@
+.. _numpy-internals:
+
 ***************
 NumPy internals
 ***************
index 5bbdd02995d8a04058488e509050bc7e55ec5f96..5c1bdda239c6d87e5c45a2b34dfacf13f3b75d69 100644 (file)
@@ -1,5 +1,8 @@
 .. currentmodule:: numpy.ma
 
+.. for doctests
+   >>> import numpy as np
+   >>> from numpy import ma
 
 .. _numpy.ma.constants:
 
@@ -21,16 +24,16 @@ defines several constants.
       True
       >>> x[-1] = ma.masked
       >>> x
-      masked_array(data = [1 -- --],
-                   mask = [False  True  True],
-             fill_value = 999999)
+      masked_array(data=[1, --, --],
+                   mask=[False,  True,  True],
+             fill_value=999999)
 
 
 .. data:: nomask
 
    Value indicating that a masked array has no invalid entry.
    :attr:`nomask` is used internally to speed up computations when the mask
-   is not needed.
+   is not needed. It is represented internally as ``np.False_``.
 
 
 .. data:: masked_print_options
@@ -122,7 +125,6 @@ Conversion
 
    MaskedArray.__float__
    MaskedArray.__int__
-   MaskedArray.__long__
 
    MaskedArray.view
    MaskedArray.astype
index 4adb90c06297b2ee7d5ca152518caa39204c14db..2c506e94343ff2cc153d44e7ec147e605e970cdc 100644 (file)
@@ -41,15 +41,24 @@ wrap around, providing array alignment information -- still apply.
     :language: cython
     :end-before: example 2
 
-The BitGenerator can also be directly accessed using the members of the basic
-RNG structure.
+The BitGenerator can also be directly accessed using the members of the ``bitgen_t``
+struct.
 
 .. literalinclude:: ../../../../numpy/random/_examples/cython/extending_distributions.pyx
     :language: cython
     :start-after: example 2
+    :end-before: example 3
 
-See :ref:`extending_cython_example` for a complete working example including a
-minimal setup and cython files.
+Cython can be used to directly access the functions in
+``numpy/random/c_distributions.pxd``. This requires linking with the
+``npyrandom`` library located in ``numpy/random/lib``.
+
+.. literalinclude:: ../../../../numpy/random/_examples/cython/extending_distributions.pyx
+    :language: cython
+    :start-after: example 3
+
+See :ref:`extending_cython_example` for the complete listings of these examples
+and a minimal ``setup.py`` to build the c-extension modules.
 
 CFFI
 ====
@@ -70,9 +79,9 @@ directly from the ``_generator`` shared object, using the `BitGenerator.cffi` in
     :start-after: dlopen
 
 
-New Basic RNGs
-==============
-`~Generator` can be used with other user-provided BitGenerators. The simplest
+New Bit Generators
+==================
+`~Generator` can be used with user-provided `~BitGenerator`\ s. The simplest
 way to write a new BitGenerator is to examine the pyx file of one of the
 existing BitGenerators. The key structure that must be provided is the
 ``capsule`` which contains a ``PyCapsule`` to a struct pointer of type
index bda9c4d96112ccd4b9f0fea5cc37ab6131c7eb8b..d559f2327f978f39317a68a7aef5975ae74a11c1 100644 (file)
@@ -168,6 +168,9 @@ What's New or Different
   Python's `random.random`.
 * All BitGenerators in numpy use `SeedSequence` to convert seeds into
   initialized states.
+* The addition of an ``axis`` keyword argument to methods such as 
+  `Generator.choice`, `Generator.permutation`,  and `Generator.shuffle` 
+  improves support for sampling from and shuffling multi-dimensional arrays.
 
 See :ref:`new-or-different` for a complete list of improvements and
 differences from the traditional ``Randomstate``.
index 922d76a9ae8a89be75f43edb6db13fd42b8434d7..91b91dac89d90e8468197da0de91f919b60c3b55 100644 (file)
@@ -125,7 +125,7 @@ Distributions
 Functions in `numpy.random`
 ===========================
 Many of the RandomState methods above are exported as functions in
-`numpy.random` This usage is discouraged, as it is implemented via a gloabl
+`numpy.random` This usage is discouraged, as it is implemented via a global
 `RandomState` instance which is not advised on two counts:
 
 - It uses global state, which means results will change as the code changes
index a0a31d0eac37f444b0084d9431a58bdf74a55d86..4b221d9aa6c17e2c84db183584dee9141b82d726 100644 (file)
@@ -11,32 +11,28 @@ these requirements.
 
 This example makes use of Python 3 :mod:`concurrent.futures` to fill an array
 using multiple threads.  Threads are long-lived so that repeated calls do not
-require any additional overheads from thread creation. The underlying
-BitGenerator is `PCG64` which is fast, has a long period and supports
-using `PCG64.jumped` to return a new generator while advancing the
-state. The random numbers generated are reproducible in the sense that the same
-seed will produce the same outputs.
+require any additional overheads from thread creation.
+
+The random numbers generated are reproducible in the sense that the same
+seed will produce the same outputs, given that the number of threads does not
+change.
 
 .. code-block:: ipython
 
-    from numpy.random import Generator, PCG64
+    from numpy.random import default_rng, SeedSequence
     import multiprocessing
     import concurrent.futures
     import numpy as np
 
-    class MultithreadedRNG(object):
+    class MultithreadedRNG:
         def __init__(self, n, seed=None, threads=None):
-            rg = PCG64(seed)
             if threads is None:
                 threads = multiprocessing.cpu_count()
             self.threads = threads
 
-            self._random_generators = [rg]
-            last_rg = rg
-            for _ in range(0, threads-1):
-                new_rg = last_rg.jumped()
-                self._random_generators.append(new_rg)
-                last_rg = new_rg
+            seq = SeedSequence(seed)
+            self._random_generators = [default_rng(s)
+                                       for s in seq.spawn(threads)]
 
             self.n = n
             self.executor = concurrent.futures.ThreadPoolExecutor(threads)
@@ -61,19 +57,20 @@ seed will produce the same outputs.
             self.executor.shutdown(False)
 
 
+
 The multithreaded random number generator can be used to fill an array.
 The ``values`` attributes shows the zero-value before the fill and the
 random value after.
 
 .. code-block:: ipython
 
-    In [2]: mrng = MultithreadedRNG(10000000, seed=0)
-    ...: print(mrng.values[-1])
-    0.0
+    In [2]: mrng = MultithreadedRNG(10000000, seed=12345)
+       ...: print(mrng.values[-1])
+    Out[2]: 0.0
 
     In [3]: mrng.fill()
-        ...: print(mrng.values[-1])
-    3.296046120254392
+       ...: print(mrng.values[-1])
+    Out[3]: 2.4545724517479104
 
 The time required to produce using multiple threads can be compared to
 the time required to generate using a single thread.
@@ -81,28 +78,38 @@ the time required to generate using a single thread.
 .. code-block:: ipython
 
     In [4]: print(mrng.threads)
-        ...: %timeit mrng.fill()
+       ...: %timeit mrng.fill()
 
-    4
-    32.8 ms Â± 2.71 ms per loop (mean Â± std. dev. of 7 runs, 10 loops each)
+    Out[4]: 4
+       ...: 32.8 ms Â± 2.71 ms per loop (mean Â± std. dev. of 7 runs, 10 loops each)
 
 The single threaded call directly uses the BitGenerator.
 
 .. code-block:: ipython
 
     In [5]: values = np.empty(10000000)
-        ...: rg = Generator(PCG64())
-        ...: %timeit rg.standard_normal(out=values)
+       ...: rg = default_rng()
+       ...: %timeit rg.standard_normal(out=values)
 
-    99.6 ms Â± 222 Âµs per loop (mean Â± std. dev. of 7 runs, 10 loops each)
+    Out[5]: 99.6 ms Â± 222 Âµs per loop (mean Â± std. dev. of 7 runs, 10 loops each)
 
-The gains are substantial and the scaling is reasonable even for large that
-are only moderately large.  The gains are even larger when compared to a call
+The gains are substantial and the scaling is reasonable even for arrays that
+are only moderately large. The gains are even larger when compared to a call
 that does not use an existing array due to array creation overhead.
 
 .. code-block:: ipython
 
-    In [6]: rg = Generator(PCG64())
-        ...: %timeit rg.standard_normal(10000000)
+    In [6]: rg = default_rng()
+       ...: %timeit rg.standard_normal(10000000)
+
+    Out[6]: 125 ms Â± 309 Âµs per loop (mean Â± std. dev. of 7 runs, 10 loops each)
+
+Note that if `threads` is not set by the user, it will be determined by
+`multiprocessing.cpu_count()`.
+
+.. code-block:: ipython
 
-    125 ms Â± 309 Âµs per loop (mean Â± std. dev. of 7 runs, 10 loops each)
+    In [7]: # simulate the behavior for `threads=None`, if the machine had only one thread
+       ...: mrng = MultithreadedRNG(10000000, seed=12345, threads=1)
+       ...: print(mrng.values[-1])
+    Out[7]: 1.1800150052158556
index b3bddb44378befe4d9dfdcc63e63863f5ac5064e..03e7775a0d56fd4fb8fe8c5b5f53d4e0d48c03a6 100644 (file)
@@ -52,36 +52,37 @@ And in more detail:
   methods which are 2-10 times faster than NumPy's default implementation in
   `~.Generator.standard_normal`, `~.Generator.standard_exponential` or
   `~.Generator.standard_gamma`.
-* `~.Generator.integers` is now the canonical way to generate integer
-  random numbers from a discrete uniform distribution. The ``rand`` and
-  ``randn`` methods are only available through the legacy `~.RandomState`.
-  This replaces both ``randint`` and the deprecated ``random_integers``.
-* The Box-Muller method used to produce NumPy's normals is no longer available.
-* All bit generators can produce doubles, uint64s and
-  uint32s via CTypes (`~PCG64.ctypes`) and CFFI (`~PCG64.cffi`).
-  This allows these bit generators to be used in numba.
-* The bit generators can be used in downstream projects via
-  Cython.
-
+   
 
 .. ipython:: python
 
   from  numpy.random import Generator, PCG64
   import numpy.random
   rg = Generator(PCG64())
-  %timeit rg.standard_normal(100000)
-  %timeit numpy.random.standard_normal(100000)
+  %timeit -n 1 rg.standard_normal(100000)
+  %timeit -n 1 numpy.random.standard_normal(100000)
 
 .. ipython:: python
 
-  %timeit rg.standard_exponential(100000)
-  %timeit numpy.random.standard_exponential(100000)
+  %timeit -n 1 rg.standard_exponential(100000)
+  %timeit -n 1 numpy.random.standard_exponential(100000)
 
 .. ipython:: python
 
-  %timeit rg.standard_gamma(3.0, 100000)
-  %timeit numpy.random.standard_gamma(3.0, 100000)
+  %timeit -n 1 rg.standard_gamma(3.0, 100000)
+  %timeit -n 1 numpy.random.standard_gamma(3.0, 100000)
+
 
+* `~.Generator.integers` is now the canonical way to generate integer
+  random numbers from a discrete uniform distribution. The ``rand`` and
+  ``randn`` methods are only available through the legacy `~.RandomState`.
+  This replaces both ``randint`` and the deprecated ``random_integers``.
+* The Box-Muller method used to produce NumPy's normals is no longer available.
+* All bit generators can produce doubles, uint64s and
+  uint32s via CTypes (`~PCG64.ctypes`) and CFFI (`~PCG64.cffi`).
+  This allows these bit generators to be used in numba.
+* The bit generators can be used in downstream projects via
+  Cython.
 * Optional ``dtype`` argument that accepts ``np.float32`` or ``np.float64``
   to produce either single or double prevision uniform random variables for
   select distributions
@@ -114,3 +115,15 @@ And in more detail:
   rg.random(out=existing[:2])
   print(existing)
 
+* Optional ``axis`` argument for methods like `~.Generator.choice`,
+  `~.Generator.permutation` and `~.Generator.shuffle` that controls which
+  axis an operation is performed over for multi-dimensional arrays.
+
+.. ipython:: python
+
+  rg = Generator(PCG64(123456789))
+  a = np.arange(12).reshape((3, 4))
+  a
+  rg.choice(a, axis=1, size=5)
+  rg.shuffle(a, axis=1)        # Shuffle in-place
+  a
index d70dd064a70b3e7e8af4c80d69ab2045b62ae351..74dad4cc37d3cb7bb8c6e9e53e29c78a41029de5 100644 (file)
@@ -81,7 +81,7 @@ performance was computed using a geometric mean.
 
 .. note::
 
-   All timings were taken using Linux on a i5-3570 processor.
+   All timings were taken using Linux on an i5-3570 processor.
 
 Performance on different Operating Systems
 ******************************************
@@ -150,4 +150,4 @@ Exponentials                100     33.7      26.3    109.8
 
    Linux timings used Ubuntu 18.04 and GCC 7.4.  Windows timings were made on
    Windows 10 using Microsoft C/C++ Optimizing Compiler Version 19 (Visual
-   Studio 2015). All timings were produced on a i5-3570 processor.
+   Studio 2015). All timings were produced on an i5-3570 processor.
index bf43232efa23d9a413ec7b21eba24867feaade49..8d13a1800abf3acedff0bfc770367f5ebe6da7cb 100644 (file)
@@ -69,11 +69,11 @@ Joining arrays
 
    concatenate
    stack
-   column_stack
-   dstack
-   hstack
-   vstack
    block
+   vstack
+   hstack
+   dstack
+   column_stack
 
 Splitting arrays
 ================
index 8bb29b7934ae8220dae5e445428586d3d8e32225..cf66eab497a714a7e0c3a0225aff6803c6b8f70d 100644 (file)
@@ -1,3 +1,5 @@
+.. _routines.io:
+
 Input and output
 ****************
 
index d42e77ad8e2da72b1a75d413a66e9bce22372215..86e168b262a2083f27d9e92fd5c9ae93b051c089 100644 (file)
@@ -18,6 +18,18 @@ or specify the processor architecture.
 .. _OpenBLAS: https://www.openblas.net/
 .. _threadpoolctl: https://github.com/joblib/threadpoolctl
 
+The SciPy library also contains a `~scipy.linalg` submodule, and there is
+overlap in the functionality provided by the SciPy and NumPy submodules.  SciPy
+contains functions not found in `numpy.linalg`, such as functions related to
+LU decomposition and the Schur decomposition, multiple ways of calculating the
+pseudoinverse, and matrix transcendentals such as the matrix logarithm.  Some
+functions that exist in both have augmented functionality in `scipy.linalg`.
+For example, `scipy.linalg.eig` can take a second matrix argument for solving
+generalized eigenvalue problems.  Some functions in NumPy, however, have more
+flexible broadcasting options.  For example, `numpy.linalg.solve` can handle
+"stacked" arrays, while `scipy.linalg.solve` accepts only a single square
+array as its first argument.
+
 .. currentmodule:: numpy
 
 Matrix and vector products
index 5b2098c7a3579de7f377bd6d09e882cd3305b19e..97859ac67a24096c8b58195aeeb16cda64ce50dd 100644 (file)
@@ -145,13 +145,13 @@ Joining arrays
 .. autosummary::
    :toctree: generated/
 
+   ma.concatenate
    ma.stack
+   ma.vstack
+   ma.hstack
+   ma.dstack
    ma.column_stack
-   ma.concatenate
    ma.append
-   ma.dstack
-   ma.hstack
-   ma.vstack
 
 
 _____
@@ -396,6 +396,7 @@ Miscellanea
    ma.allequal
    ma.allclose
    ma.apply_along_axis
+   ma.apply_over_axes
    ma.arange
    ma.choose
    ma.ediff1d
index 28c9a1ad1ade4bcfb8785f105484ccb111a2b6f4..def5b3e3c9f5fc4a854b96285d783829ac9fab0f 100644 (file)
@@ -44,6 +44,7 @@ Utility
    :toctree: generated/
 
    get_include
+   show_config
    deprecate
    deprecate_with_doc
 
index 60c816f03d1da9f87f95e1de1deca32eb0fd9525..087b7beb9f06be8e6336042c01770b74ccbc94e4 100644 (file)
@@ -1,92 +1,6 @@
-Chebyshev Module (:mod:`numpy.polynomial.chebyshev`)
-====================================================
-
 .. versionadded:: 1.4.0
 
-.. currentmodule:: numpy.polynomial.chebyshev
-
-This module provides a number of objects (mostly functions) useful for
-dealing with Chebyshev series, including a `Chebyshev` class that
-encapsulates the usual arithmetic operations.  (General information
-on how this module represents and works with such polynomials is in the
-docstring for its "parent" sub-package, `numpy.polynomial`).
-
-Chebyshev Class
----------------
-
-.. autosummary::
-   :toctree: generated/
-
-   Chebyshev
-
-Basics
-------
-
-.. autosummary::
-   :toctree: generated/
-
-   chebval
-   chebval2d
-   chebval3d
-   chebgrid2d
-   chebgrid3d
-   chebroots
-   chebfromroots
-
-Fitting
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   chebfit
-   chebvander
-   chebvander2d
-   chebvander3d
-
-Calculus
---------
-
-.. autosummary::
-   :toctree: generated/
-
-   chebder
-   chebint
-
-Algebra
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   chebadd
-   chebsub
-   chebmul
-   chebmulx
-   chebdiv
-   chebpow
-
-Quadrature
-----------
-
-.. autosummary::
-   :toctree: generated/
-
-   chebgauss
-   chebweight
-
-Miscellaneous
--------------
-
-.. autosummary::
-   :toctree: generated/
-
-   chebcompanion
-   chebdomain
-   chebzero
-   chebone
-   chebx
-   chebtrim
-   chebline
-   cheb2poly
-   poly2cheb
+.. automodule:: numpy.polynomial.chebyshev
+   :no-members:
+   :no-inherited-members:
+   :no-special-members:
index da0394305a39d11230db93037b831648e618bb81..71e6358666795a244cd571760af132b58a9b6401 100644 (file)
@@ -52,7 +52,7 @@ the conventional Polynomial class because of its familiarity::
    >>> from numpy.polynomial import Polynomial as P
    >>> p = P([1,2,3])
    >>> p
-   Polynomial([ 1.,  2.,  3.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([1., 2., 3.], domain=[-1,  1], window=[-1,  1])
 
 Note that there are three parts to the long version of the printout. The
 first is the coefficients, the second is the domain, and the third is the
@@ -68,8 +68,8 @@ window::
 Printing a polynomial yields a shorter form without the domain
 and window::
 
-   >>> print p
-   poly([ 1.  2.  3.])
+   >>> print(p)
+   poly([1. 2. 3.])
 
 We will deal with the domain and window when we get to fitting, for the moment
 we ignore them and run through the basic algebraic and arithmetic operations.
@@ -77,19 +77,19 @@ we ignore them and run through the basic algebraic and arithmetic operations.
 Addition and Subtraction::
 
    >>> p + p
-   Polynomial([ 2.,  4.,  6.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([2., 4., 6.], domain=[-1.,  1.], window=[-1.,  1.])
    >>> p - p
-   Polynomial([ 0.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([0.], domain=[-1.,  1.], window=[-1.,  1.])
 
 Multiplication::
 
    >>> p * p
-   Polynomial([  1.,   4.,  10.,  12.,   9.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([ 1.,   4.,  10.,  12.,   9.], domain=[-1.,  1.], window=[-1.,  1.])
 
 Powers::
 
    >>> p**2
-   Polynomial([  1.,   4.,  10.,  12.,   9.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([ 1.,   4., 10., 12.,  9.], domain=[-1.,  1.], window=[-1.,  1.])
 
 Division:
 
@@ -100,20 +100,20 @@ versions the '/' will only work for division by scalars. At some point it
 will be deprecated::
 
    >>> p // P([-1, 1])
-   Polynomial([ 5.,  3.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([5.,  3.], domain=[-1.,  1.], window=[-1.,  1.])
 
 Remainder::
 
    >>> p % P([-1, 1])
-   Polynomial([ 6.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([6.], domain=[-1.,  1.], window=[-1.,  1.])
 
 Divmod::
 
    >>> quo, rem = divmod(p, P([-1, 1]))
    >>> quo
-   Polynomial([ 5.,  3.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([5.,  3.], domain=[-1.,  1.], window=[-1.,  1.])
    >>> rem
-   Polynomial([ 6.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([6.], domain=[-1.,  1.], window=[-1.,  1.])
 
 Evaluation::
 
@@ -134,7 +134,7 @@ the polynomials are regarded as functions this is composition of
 functions::
 
    >>> p(p)
-   Polynomial([  6.,  16.,  36.,  36.,  27.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([ 6., 16., 36., 36., 27.], domain=[-1.,  1.], window=[-1.,  1.])
 
 Roots::
 
@@ -148,11 +148,11 @@ tuples, lists, arrays, and scalars are automatically cast in the arithmetic
 operations::
 
    >>> p + [1, 2, 3]
-   Polynomial([ 2.,  4.,  6.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([2., 4., 6.], domain=[-1.,  1.], window=[-1.,  1.])
    >>> [1, 2, 3] * p
-   Polynomial([  1.,   4.,  10.,  12.,   9.], domain=[-1,  1], window=[-1,  1])
+   Polynomial([ 1.,  4., 10., 12.,  9.], domain=[-1.,  1.], window=[-1.,  1.])
    >>> p / 2
-   Polynomial([ 0.5,  1. ,  1.5], domain=[-1,  1], window=[-1,  1])
+   Polynomial([0.5, 1. , 1.5], domain=[-1.,  1.], window=[-1.,  1.])
 
 Polynomials that differ in domain, window, or class can't be mixed in
 arithmetic::
@@ -180,7 +180,7 @@ conversion of Polynomial classes among themselves is done for type, domain,
 and window casting::
 
     >>> p(T([0, 1]))
-    Chebyshev([ 2.5,  2. ,  1.5], domain=[-1,  1], window=[-1,  1])
+    Chebyshev([2.5, 2. , 1.5], domain=[-1.,  1.], window=[-1.,  1.])
 
 Which gives the polynomial `p` in Chebyshev form. This works because
 :math:`T_1(x) = x` and substituting :math:`x` for :math:`x` doesn't change
@@ -200,18 +200,18 @@ Polynomial instances can be integrated and differentiated.::
     >>> from numpy.polynomial import Polynomial as P
     >>> p = P([2, 6])
     >>> p.integ()
-    Polynomial([ 0.,  2.,  3.], domain=[-1,  1], window=[-1,  1])
+    Polynomial([0., 2., 3.], domain=[-1.,  1.], window=[-1.,  1.])
     >>> p.integ(2)
-    Polynomial([ 0.,  0.,  1.,  1.], domain=[-1,  1], window=[-1,  1])
+    Polynomial([0., 0., 1., 1.], domain=[-1.,  1.], window=[-1.,  1.])
 
 The first example integrates `p` once, the second example integrates it
 twice. By default, the lower bound of the integration and the integration
 constant are 0, but both can be specified.::
 
     >>> p.integ(lbnd=-1)
-    Polynomial([-1.,  2.,  3.], domain=[-1,  1], window=[-1,  1])
+    Polynomial([-1.,  2.,  3.], domain=[-1.,  1.], window=[-1.,  1.])
     >>> p.integ(lbnd=-1, k=1)
-    Polynomial([ 0.,  2.,  3.], domain=[-1,  1], window=[-1,  1])
+    Polynomial([0., 2., 3.], domain=[-1.,  1.], window=[-1.,  1.])
 
 In the first case the lower bound of the integration is set to -1 and the
 integration constant is 0. In the second the constant of integration is set
@@ -220,9 +220,9 @@ number of times the polynomial is differentiated::
 
     >>> p = P([1, 2, 3])
     >>> p.deriv(1)
-    Polynomial([ 2.,  6.], domain=[-1,  1], window=[-1,  1])
+    Polynomial([2., 6.], domain=[-1.,  1.], window=[-1.,  1.])
     >>> p.deriv(2)
-    Polynomial([ 6.], domain=[-1,  1], window=[-1,  1])
+    Polynomial([6.], domain=[-1.,  1.], window=[-1.,  1.])
 
 
 Other Polynomial Constructors
@@ -238,25 +238,25 @@ are demonstrated below::
     >>> from numpy.polynomial import Chebyshev as T
     >>> p = P.fromroots([1, 2, 3])
     >>> p
-    Polynomial([ -6.,  11.,  -6.,   1.], domain=[-1,  1], window=[-1,  1])
+    Polynomial([-6., 11., -6.,  1.], domain=[-1.,  1.], window=[-1.,  1.])
     >>> p.convert(kind=T)
-    Chebyshev([ -9.  ,  11.75,  -3.  ,   0.25], domain=[-1,  1], window=[-1,  1])
+    Chebyshev([-9.  , 11.75, -3.  ,  0.25], domain=[-1.,  1.], window=[-1.,  1.])
 
 The convert method can also convert domain and window::
 
     >>> p.convert(kind=T, domain=[0, 1])
-    Chebyshev([-2.4375 ,  2.96875, -0.5625 ,  0.03125], [ 0.,  1.], [-1.,  1.])
+    Chebyshev([-2.4375 ,  2.96875, -0.5625 ,  0.03125], domain=[0.,  1.], window=[-1.,  1.])
     >>> p.convert(kind=P, domain=[0, 1])
-    Polynomial([-1.875,  2.875, -1.125,  0.125], [ 0.,  1.], [-1.,  1.])
+    Polynomial([-1.875,  2.875, -1.125,  0.125], domain=[0.,  1.], window=[-1.,  1.])
 
 In numpy versions >= 1.7.0 the `basis` and `cast` class methods are also
 available. The cast method works like the convert method while the basis
 method returns the basis polynomial of given degree::
 
     >>> P.basis(3)
-    Polynomial([ 0.,  0.,  0.,  1.], domain=[-1,  1], window=[-1,  1])
+    Polynomial([0., 0., 0., 1.], domain=[-1.,  1.], window=[-1.,  1.])
     >>> T.cast(p)
-    Chebyshev([ -9.  ,  11.75,  -3.  ,   0.25], domain=[-1,  1], window=[-1,  1])
+    Chebyshev([-9.  , 11.75, -3. ,  0.25], domain=[-1.,  1.], window=[-1.,  1.])
 
 Conversions between types can be useful, but it is *not* recommended
 for routine use. The loss of numerical precision in passing from a
index 8ee72e97c3f6cfa37f154fe6d11c78a6c2fb4c1f..c881d9aaf1eaa39932536e64475cbb63788d62d0 100644 (file)
@@ -1,92 +1,6 @@
-Hermite Module, "Physicists'" (:mod:`numpy.polynomial.hermite`)
-===============================================================
-
 .. versionadded:: 1.6.0
 
-.. currentmodule:: numpy.polynomial.hermite
-
-This module provides a number of objects (mostly functions) useful for
-dealing with Hermite series, including a `Hermite` class that
-encapsulates the usual arithmetic operations.  (General information
-on how this module represents and works with such polynomials is in the
-docstring for its "parent" sub-package, `numpy.polynomial`).
-
-Hermite Class
--------------
-
-.. autosummary::
-   :toctree: generated/
-
-   Hermite
-
-Basics
-------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermval
-   hermval2d
-   hermval3d
-   hermgrid2d
-   hermgrid3d
-   hermroots
-   hermfromroots
-
-Fitting
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermfit
-   hermvander
-   hermvander2d
-   hermvander3d
-
-Calculus
---------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermder
-   hermint
-
-Algebra
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermadd
-   hermsub
-   hermmul
-   hermmulx
-   hermdiv
-   hermpow
-
-Quadrature
-----------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermgauss
-   hermweight
-
-Miscellaneous
--------------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermcompanion
-   hermdomain
-   hermzero
-   hermone
-   hermx
-   hermtrim
-   hermline
-   herm2poly
-   poly2herm
+.. automodule:: numpy.polynomial.hermite
+   :no-members:
+   :no-inherited-members:
+   :no-special-members:
index 33a15bb444518d908e989bae704a0c7c2b6f0209..bfcb900c8782fa2659bf1ef0b31457a6eb12d67f 100644 (file)
@@ -1,92 +1,6 @@
-HermiteE Module, "Probabilists'" (:mod:`numpy.polynomial.hermite_e`)
-====================================================================
-
 .. versionadded:: 1.6.0
 
-.. currentmodule:: numpy.polynomial.hermite_e
-
-This module provides a number of objects (mostly functions) useful for
-dealing with HermiteE series, including a `HermiteE` class that
-encapsulates the usual arithmetic operations.  (General information
-on how this module represents and works with such polynomials is in the
-docstring for its "parent" sub-package, `numpy.polynomial`).
-
-HermiteE Class
---------------
-
-.. autosummary::
-   :toctree: generated/
-
-   HermiteE
-
-Basics
-------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermeval
-   hermeval2d
-   hermeval3d
-   hermegrid2d
-   hermegrid3d
-   hermeroots
-   hermefromroots
-
-Fitting
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermefit
-   hermevander
-   hermevander2d
-   hermevander3d
-
-Calculus
---------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermeder
-   hermeint
-
-Algebra
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermeadd
-   hermesub
-   hermemul
-   hermemulx
-   hermediv
-   hermepow
-
-Quadrature
-----------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermegauss
-   hermeweight
-
-Miscellaneous
--------------
-
-.. autosummary::
-   :toctree: generated/
-
-   hermecompanion
-   hermedomain
-   hermezero
-   hermeone
-   hermex
-   hermetrim
-   hermeline
-   herme2poly
-   poly2herme
+.. automodule:: numpy.polynomial.hermite_e
+   :no-members:
+   :no-inherited-members:
+   :no-special-members:
index 45e288cb9c93517ae79b41cb60a41dbcd62bcf3b..68c44630077c21aa5de1440c64b35e52ca500937 100644 (file)
@@ -1,92 +1,6 @@
-Laguerre Module (:mod:`numpy.polynomial.laguerre`)
-==================================================
-
 .. versionadded:: 1.6.0
 
-.. currentmodule:: numpy.polynomial.laguerre
-
-This module provides a number of objects (mostly functions) useful for
-dealing with Laguerre series, including a `Laguerre` class that
-encapsulates the usual arithmetic operations.  (General information
-on how this module represents and works with such polynomials is in the
-docstring for its "parent" sub-package, `numpy.polynomial`).
-
-Laguerre Class
---------------
-
-.. autosummary::
-   :toctree: generated/
-
-   Laguerre
-
-Basics
-------
-
-.. autosummary::
-   :toctree: generated/
-
-   lagval
-   lagval2d
-   lagval3d
-   laggrid2d
-   laggrid3d
-   lagroots
-   lagfromroots
-
-Fitting
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   lagfit
-   lagvander
-   lagvander2d
-   lagvander3d
-
-Calculus
---------
-
-.. autosummary::
-   :toctree: generated/
-
-   lagder
-   lagint
-
-Algebra
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   lagadd
-   lagsub
-   lagmul
-   lagmulx
-   lagdiv
-   lagpow
-
-Quadrature
-----------
-
-.. autosummary::
-   :toctree: generated/
-
-   laggauss
-   lagweight
-
-Miscellaneous
--------------
-
-.. autosummary::
-   :toctree: generated/
-
-   lagcompanion
-   lagdomain
-   lagzero
-   lagone
-   lagx
-   lagtrim
-   lagline
-   lag2poly
-   poly2lag
+.. automodule:: numpy.polynomial.laguerre
+   :no-members:
+   :no-inherited-members:
+   :no-special-members:
index fe6edc216f84340f3acd50408792f2afa03d532a..e10065b4d5fef06d8fca1d173e7f607a1ba2be13 100644 (file)
@@ -1,92 +1,6 @@
-Legendre Module (:mod:`numpy.polynomial.legendre`)
-==================================================
-
 .. versionadded:: 1.6.0
 
-.. currentmodule:: numpy.polynomial.legendre
-
-This module provides a number of objects (mostly functions) useful for
-dealing with Legendre series, including a `Legendre` class that
-encapsulates the usual arithmetic operations.  (General information
-on how this module represents and works with such polynomials is in the
-docstring for its "parent" sub-package, `numpy.polynomial`).
-
-Legendre Class
---------------
-
-.. autosummary::
-   :toctree: generated/
-
-   Legendre
-
-Basics
-------
-
-.. autosummary::
-   :toctree: generated/
-
-   legval
-   legval2d
-   legval3d
-   leggrid2d
-   leggrid3d
-   legroots
-   legfromroots
-
-Fitting
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   legfit
-   legvander
-   legvander2d
-   legvander3d
-
-Calculus
---------
-
-.. autosummary::
-   :toctree: generated/
-
-   legder
-   legint
-
-Algebra
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   legadd
-   legsub
-   legmul
-   legmulx
-   legdiv
-   legpow
-
-Quadrature
-----------
-
-.. autosummary::
-   :toctree: generated/
-
-   leggauss
-   legweight
-
-Miscellaneous
--------------
-
-.. autosummary::
-   :toctree: generated/
-
-   legcompanion
-   legdomain
-   legzero
-   legone
-   legx
-   legtrim
-   legline
-   leg2poly
-   poly2leg
+.. automodule:: numpy.polynomial.legendre
+   :no-members:
+   :no-inherited-members:
+   :no-special-members:
index 7e40d9f00ef2f88987347dc744847ce735c16340..ca1217f80050824e9064152f44d57879355d580c 100644 (file)
@@ -1,20 +1,6 @@
-.. module:: numpy.polynomial
+:orphan:
 
-Polynomial Package
-==================
-
-.. versionadded:: 1.4.0
-
-.. currentmodule:: numpy.polynomial
-
-.. toctree::
-   :maxdepth: 2
-
-   routines.polynomials.classes
-   routines.polynomials.polynomial
-   routines.polynomials.chebyshev
-   routines.polynomials.legendre
-   routines.polynomials.laguerre
-   routines.polynomials.hermite
-   routines.polynomials.hermite_e
-   routines.polynomials.polyutils
+.. automodule:: numpy.polynomial
+   :no-members:
+   :no-inherited-members:
+   :no-special-members:
index 365c8da987e9556b347481653d4b4d67fb201e2b..71000a60db2c59cf9169a992b26a2da2b483bd7f 100644 (file)
@@ -1,84 +1,6 @@
-.. module:: numpy.polynomial.polynomial
-
-Polynomial Module (:mod:`numpy.polynomial.polynomial`)
-======================================================
-
 .. versionadded:: 1.4.0
 
-.. currentmodule:: numpy.polynomial.polynomial
-
-This module provides a number of objects (mostly functions) useful for
-dealing with Polynomial series, including a `Polynomial` class that
-encapsulates the usual arithmetic operations.  (General information
-on how this module represents and works with such polynomials is in the
-docstring for its "parent" sub-package, `numpy.polynomial`).
-
-Polynomial Class
-----------------
-
-.. autosummary::
-   :toctree: generated/
-
-   Polynomial
-
-Basics
-------
-
-.. autosummary::
-   :toctree: generated/
-
-   polyval
-   polyval2d
-   polyval3d
-   polygrid2d
-   polygrid3d
-   polyroots
-   polyfromroots
-   polyvalfromroots
-
-Fitting
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   polyfit
-   polyvander
-   polyvander2d
-   polyvander3d
-
-Calculus
---------
-
-.. autosummary::
-   :toctree: generated/
-
-   polyder
-   polyint
-
-Algebra
--------
-
-.. autosummary::
-   :toctree: generated/
-
-   polyadd
-   polysub
-   polymul
-   polymulx
-   polydiv
-   polypow
-
-Miscellaneous
--------------
-
-.. autosummary::
-   :toctree: generated/
-
-   polycompanion
-   polydomain
-   polyzero
-   polyone
-   polyx
-   polytrim
-   polyline
+.. automodule:: numpy.polynomial.polynomial
+   :no-members:
+   :no-inherited-members:
+   :no-special-members:
index e85d0549b0aef44dcc123dafe21db3329d90ea76..e74c5a683b5786eff5eafae510d545aa2ce9b2f0 100644 (file)
@@ -1,15 +1,17 @@
+.. _routines.polynomial:
+
 Polynomials
 ***********
 
 Polynomials in NumPy can be *created*, *manipulated*, and even *fitted* using
-the :doc:`routines.polynomials.classes`
+the :doc:`convenience classes <routines.polynomials.classes>`
 of the `numpy.polynomial` package, introduced in NumPy 1.4.
 
 Prior to NumPy 1.4, `numpy.poly1d` was the class of choice and it is still
 available in order to maintain backward compatibility.
 However, the newer Polynomial package is more complete than `numpy.poly1d`
 and its convenience classes are better behaved in the numpy environment.
-Therefore Polynomial is recommended for new coding.
+Therefore :mod:`numpy.polynomial` is recommended for new coding.
 
 Transition notice
 -----------------
@@ -22,9 +24,17 @@ degree i.
 
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
+
+   routines.polynomials.classes
+   routines.polynomials.polynomial
+   routines.polynomials.chebyshev
+   routines.polynomials.hermite
+   routines.polynomials.hermite_e
+   routines.polynomials.laguerre
+   routines.polynomials.legendre
+   routines.polynomials.polyutils
 
-   routines.polynomials.package
 
 .. toctree::
    :maxdepth: 2
index 361cf11b9c842b952e68cc16ee51388143493679..6d58d1a6da5a1325fb558ac35a8a81b3dc29329a 100644 (file)
@@ -380,7 +380,7 @@ advanced usage and will not typically be used.
     result as a dimension with size one, so that the result will broadcast
     correctly against the inputs. This option can only be used for generalized
     ufuncs that operate on inputs that all have the same number of core
-    dimensions and with outputs that have no core dimensions , i.e., with
+    dimensions and with outputs that have no core dimensions, i.e., with
     signatures like ``(i),(i)->()`` or ``(m,m)->()``. If used, the location of
     the dimensions in the output can be controlled with ``axes`` and ``axis``.
 
@@ -441,13 +441,13 @@ advanced usage and will not typically be used.
 
 *extobj*
 
-    a list of length 1, 2, or 3 specifying the ufunc buffer-size, the
-    error mode integer, and the error call-back function. Normally, these
+    a list of length 3 specifying the ufunc buffer-size, the error
+    mode integer, and the error call-back function. Normally, these
     values are looked up in a thread-specific dictionary. Passing them
     here circumvents that look up and uses the low-level specification
-    provided for the error mode. This may be useful, for example, as an
-    optimization for calculations requiring many ufunc calls on small arrays
-    in a loop.
+    provided for the error mode. This may be useful, for example, as
+    an optimization for calculations requiring many ufunc calls on
+    small arrays in a loop.
 
 
 
@@ -569,6 +569,7 @@ Math operations
     add
     subtract
     multiply
+    matmul
     divide
     logaddexp
     logaddexp2
@@ -577,6 +578,7 @@ Math operations
     negative
     positive
     power
+    float_power
     remainder
     mod
     fmod
@@ -635,6 +637,8 @@ The ratio of degrees to radians is :math:`180^{\circ}/\pi.`
     arcsinh
     arccosh
     arctanh
+    degrees
+    radians
     deg2rad
     rad2deg
 
index 72cfc20e045f2824adf5cd9f132c21354e44f82b..1e56978286e13a368fa37ff08fa8c25732eb0a0f 100644 (file)
@@ -5,7 +5,7 @@ Release Notes
 .. toctree::
     :maxdepth: 3
 
-    1.18.5 <release/1.18.5-notes>
+    1.19.0 <release/1.19.0-notes>
     1.18.4 <release/1.18.4-notes>
     1.18.3 <release/1.18.3-notes>
     1.18.2 <release/1.18.2-notes>
index 5d8c932fe36dafbe8989852ec3e9d00a14adf3cb..9da9a99d7585a5d37466f3b766a9d2d8f334bf29 100644 (file)
@@ -243,7 +243,7 @@ It is similar to Matlab's square bracket notation for creating block matrices.
 
 ``isin`` function, improving on ``in1d``
 ----------------------------------------
-The new function ``isin`` tests whether each element of an N-dimensonal
+The new function ``isin`` tests whether each element of an N-dimensional
 array is present anywhere within a second array. It is an enhancement
 of ``in1d`` that preserves the shape of the first array.
 
index 462631de6afeec2c8417d2668e0cc7fc64697661..8ee876fd3184014c19ab177757ce98f923c1a73d 100644 (file)
@@ -43,7 +43,7 @@ New functions
   floating-point scalars unambiguously with control of rounding and padding.
 
 * ``PyArray_ResolveWritebackIfCopy`` and ``PyArray_SetWritebackIfCopyBase``,
-  new C-API functions useful in achieving PyPy compatibity.
+  new C-API functions useful in achieving PyPy compatibility.
 
 
 Deprecations
index 5b6eb585ba5471b934ad29107f181001689dfa78..5bf576fd04f1c0f6f051282f7c3f068056cbaaf7 100644 (file)
@@ -51,14 +51,14 @@ A total of 23 pull requests were merged for this release.
 * `#13933 <https://github.com/numpy/numpy/pull/13933>`__: MAINT/BUG/DOC: Fix errors in _add_newdocs
 * `#13984 <https://github.com/numpy/numpy/pull/13984>`__: BUG: fix byte order reversal for datetime64[ns]
 * `#13994 <https://github.com/numpy/numpy/pull/13994>`__: MAINT,BUG: Use nbytes to also catch empty descr during allocation
-* `#14042 <https://github.com/numpy/numpy/pull/14042>`__: BUG: np.array cleared errors occured in PyMemoryView_FromObject
+* `#14042 <https://github.com/numpy/numpy/pull/14042>`__: BUG: np.array cleared errors occurred in PyMemoryView_FromObject
 * `#14043 <https://github.com/numpy/numpy/pull/14043>`__: BUG: Fixes for Undefined Behavior Sanitizer (UBSan) errors.
 * `#14044 <https://github.com/numpy/numpy/pull/14044>`__: BUG: ensure that casting to/from structured is properly checked.
 * `#14045 <https://github.com/numpy/numpy/pull/14045>`__: MAINT: fix histogram*d dispatchers
 * `#14046 <https://github.com/numpy/numpy/pull/14046>`__: BUG: further fixup to histogram2d dispatcher.
 * `#14052 <https://github.com/numpy/numpy/pull/14052>`__: BUG: Replace contextlib.suppress for Python 2.7
 * `#14056 <https://github.com/numpy/numpy/pull/14056>`__: BUG: fix compilation of 3rd party modules with Py_LIMITED_API...
-* `#14057 <https://github.com/numpy/numpy/pull/14057>`__: BUG: Fix memory leak in dtype from dict contructor
+* `#14057 <https://github.com/numpy/numpy/pull/14057>`__: BUG: Fix memory leak in dtype from dict constructor
 * `#14058 <https://github.com/numpy/numpy/pull/14058>`__: DOC: Document array_function at a higher level.
 * `#14084 <https://github.com/numpy/numpy/pull/14084>`__: BUG, DOC: add new recfunctions to `__all__`
 * `#14162 <https://github.com/numpy/numpy/pull/14162>`__: BUG: Remove stray print that causes a SystemError on python 3.7
index a0e7379824c1b5c74d57d612921b3d1162820b69..a93eb21863e5e769fcd7a8c21d8c1990069e4dc4 100644 (file)
@@ -297,7 +297,7 @@ mergesort. Due to the need to maintain backward compatibility, the sorting
 ``kind`` options ``"stable"`` and ``"mergesort"`` have been made aliases of
 each other with the actual sort implementation depending on the array type.
 Radix sort is used for small integer types of 16 bits or less and timsort for
-the remaining types.  Timsort features improved performace on data containing
+the remaining types.  Timsort features improved performance on data containing
 already or nearly sorted data and performs like mergesort on random data and
 requires :math:`O(n/2)` working space.  Details of the timsort algorithm can be
 found at `CPython listsort.txt
index 24aa94445ec335fb89aeece42cba5f6507550438..15e0ad77f5d153408fcb97e39fd7911830efe4d4 100644 (file)
@@ -1,8 +1,8 @@
 .. currentmodule:: numpy
 
-================================
-NumPy NumPy 1.18.0 Release Notes
-================================
+==========================
+NumPy 1.18.0 Release Notes
+==========================
 
 In addition to the usual bug fixes, this NumPy release cleans up and documents
 the new random C-API, expires a large number of old deprecations, and improves
@@ -195,7 +195,7 @@ adjustment to user- facing code. Specifically, code that either disallowed the
 calls to ``numpy.isinf`` or ``numpy.isnan`` or checked that they raised an
 exception will require adaptation, and code that mistakenly called
 ``numpy.fmax`` and ``numpy.fmin`` instead of ``numpy.maximum`` or
-``numpy.minimum`` respectively will requre adjustment. This also affects
+``numpy.minimum`` respectively will require adjustment. This also affects
 ``numpy.nanmax`` and ``numpy.nanmin``.
 (`gh-14841 <https://github.com/numpy/numpy/pull/14841>`__)
 
index fdb42dde02b8294816d1414029cbca91cd0fde56..25ef1d127c68d6f86b00b38a42b36514da7f80a2 100644 (file)
@@ -4,15 +4,15 @@
 NumPy 1.18.4 Release Notes
 ==========================
 
-This is that last planned release in the 1.18.x series. It reverts the
+This is the last planned release in the 1.18.x series. It reverts the
 ``bool("0")`` behavior introduced in 1.18.3 and fixes a bug in
-``Generator.integers``. There is also improved help in the error message
-emitted when numpy import fails due to a link to a new troubleshooting section
-in the documentation that is now included.
+``Generator.integers``. There is also a link to a new troubleshooting section
+in the documentation included in the error message emitted when numpy import
+fails.
 
 The Python versions supported in this release are 3.5-3.8. Downstream
-developers should use Cython >= 0.29.15 for Python 3.8 support and OpenBLAS >=
-3.7 to avoid errors on the Skylake architecture.
+developers should use Cython >= 0.29.15 for Python 3.8 support and
+OpenBLAS >= 3.7 to avoid errors on the Skylake architecture.
 
 Contributors
 ============
diff --git a/doc/source/release/1.18.5-notes.rst b/doc/source/release/1.18.5-notes.rst
deleted file mode 100644 (file)
index e704c00..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-.. currentmodule:: numpy
-
-==========================
-NumPy 1.18.5 Release Notes
-==========================
-
-This is a short release to allow pickle ``protocol=5`` to be used in
-Python3.5. It is motivated by the recent backport of pickle5 to Python3.5.
-
-The Python versions supported in this release are 3.5-3.8. Downstream
-developers should use Cython >= 0.29.15 for Python 3.8 support and
-OpenBLAS >= 3.7 to avoid errors on the Skylake architecture.
-
-Contributors
-============
-
-A total of 3 people contributed to this release.  People with a "+" by their
-names contributed a patch for the first time.
-
-* Charles Harris
-* Matti Picus
-* Siyuan Zhuang +
-
-Pull requests merged
-====================
-
-A total of 2 pull requests were merged for this release.
-
-* `#16439 <https://github.com/numpy/numpy/pull/16439>`__: ENH: enable pickle protocol 5 support for python3.5
-* `#16441 <https://github.com/numpy/numpy/pull/16441>`__: BUG: relpath fails for different drives on windows
-
diff --git a/doc/source/release/1.19.0-notes.rst b/doc/source/release/1.19.0-notes.rst
new file mode 100644 (file)
index 0000000..8f5c2c0
--- /dev/null
@@ -0,0 +1,477 @@
+.. currentmodule:: numpy
+
+==========================
+NumPy 1.19.0 Release Notes
+==========================
+This NumPy release is marked by the removal of much technical debt: support for
+Python 2 has been removed, many deprecations have been expired, and
+documentation has been improved. The polishing of the random module continues
+apace with bug fixes and better usability from Cython.
+
+The Python versions supported for this release are 3.6-3.8. Downstream
+developers should use Cython >= 0.29.16 for Python 3.8 support and
+OpenBLAS >= 3.7 to avoid problems on the Skylake architecture.
+
+
+Highlights
+==========
+
+* Code compatibility with Python versions < 3.6 (including Python 2) was
+  dropped from both the python and C code. The shims in ``numpy.compat`` will
+  remain to support third-party packages, but they may be deprecated in a
+  future release. Note that 1.19.x will *not* compile with earlier versions of
+  Python due to the use of f-strings.
+
+  (`gh-15233 <https://github.com/numpy/numpy/pull/15233>`__)
+
+
+Expired deprecations
+====================
+
+``numpy.insert`` and ``numpy.delete`` can no longer be passed an axis on 0d arrays
+----------------------------------------------------------------------------------
+This concludes a deprecation from 1.9, where when an ``axis`` argument was
+passed to a call to ``~numpy.insert`` and ``~numpy.delete`` on a 0d array, the
+``axis`` and ``obj`` argument and indices would be completely ignored.
+In these cases, ``insert(arr, "nonsense", 42, axis=0)`` would actually overwrite the
+entire array, while ``delete(arr, "nonsense", axis=0)`` would be ``arr.copy()``
+
+Now passing ``axis`` on a 0d array raises ``~numpy.AxisError``.
+
+(`gh-15802 <https://github.com/numpy/numpy/pull/15802>`__)
+
+``numpy.delete`` no longer ignores out-of-bounds indices
+--------------------------------------------------------
+This concludes deprecations from 1.8 and 1.9, where ``np.delete`` would ignore
+both negative and out-of-bounds items in a sequence of indices. This was at
+odds with its behavior when passed a single index.
+
+Now out-of-bounds items throw ``IndexError``, and negative items index from the
+end.
+
+(`gh-15804 <https://github.com/numpy/numpy/pull/15804>`__)
+
+``numpy.insert`` and ``numpy.delete`` no longer accept non-integral indices
+---------------------------------------------------------------------------
+This concludes a deprecation from 1.9, where sequences of non-integers indices
+were allowed and cast to integers. Now passing sequences of non-integral
+indices raises ``IndexError``, just like it does when passing a single
+non-integral scalar.
+
+(`gh-15805 <https://github.com/numpy/numpy/pull/15805>`__)
+
+``numpy.delete`` no longer casts boolean indices to integers
+------------------------------------------------------------
+This concludes a deprecation from 1.8, where ``np.delete`` would cast boolean
+arrays and scalars passed as an index argument into integer indices. The
+behavior now is to treat boolean arrays as a mask, and to raise an error
+on boolean scalars.
+
+(`gh-15815 <https://github.com/numpy/numpy/pull/15815>`__)
+
+
+Compatibility notes
+===================
+
+Changed random variate stream from ``numpy.random.Generator.dirichlet``
+-----------------------------------------------------------------------
+A bug in the generation of random variates for the Dirichlet distribution
+with small 'alpha' values was fixed by using a different algorithm when
+``max(alpha) < 0.1``.  Because of the change, the stream of variates
+generated by ``dirichlet`` in this case will be different from previous
+releases.
+
+(`gh-14924 <https://github.com/numpy/numpy/pull/14924>`__)
+
+Scalar promotion in ``PyArray_ConvertToCommonType``
+---------------------------------------------------
+The promotion of mixed scalars and arrays in ``PyArray_ConvertToCommonType``
+has been changed to adhere to those used by ``np.result_type``.
+This means that input such as ``(1000, np.array([1], dtype=np.uint8)))``
+will now return ``uint16`` dtypes. In most cases the behaviour is unchanged.
+Note that the use of this C-API function is generally discouraged.
+This also fixes ``np.choose`` to behave the same way as the rest of NumPy
+in this respect.
+
+(`gh-14933 <https://github.com/numpy/numpy/pull/14933>`__)
+
+Fasttake and fastputmask slots are deprecated and NULL'ed
+---------------------------------------------------------
+The fasttake and fastputmask slots are now never used and
+must always be set to NULL. This will result in no change in behaviour.
+However, if a user dtype should set one of these a DeprecationWarning
+will be given.
+
+(`gh-14942 <https://github.com/numpy/numpy/pull/14942>`__)
+
+``np.ediff1d`` casting behaviour with ``to_end`` and ``to_begin``
+-----------------------------------------------------------------
+``np.ediff1d`` now uses the ``"same_kind"`` casting rule for
+its additional ``to_end`` and ``to_begin`` arguments. This
+ensures type safety except when the input array has a smaller
+integer type than ``to_begin`` or ``to_end``.
+In rare cases, the behaviour will be more strict than it was
+previously in 1.16 and 1.17. This is necessary to solve issues
+with floating point NaN.
+
+(`gh-14981 <https://github.com/numpy/numpy/pull/14981>`__)
+
+Converting of empty array-like objects to NumPy arrays
+------------------------------------------------------
+Objects with ``len(obj) == 0`` which implement an "array-like" interface,
+meaning an object implementing ``obj.__array__()``,
+``obj.__array_interface__``, ``obj.__array_struct__``, or the python
+buffer interface and which are also sequences (i.e. Pandas objects)
+will now always retain there shape correctly when converted to an array.
+If such an object has a shape of ``(0, 1)`` previously, it could
+be converted into an array of shape ``(0,)`` (losing all dimensions
+after the first 0).
+
+(`gh-14995 <https://github.com/numpy/numpy/pull/14995>`__)
+
+Removed ``multiarray.int_asbuffer``
+-----------------------------------
+As part of the continued removal of Python 2 compatibility,
+``multiarray.int_asbuffer`` was removed. On Python 3, it threw a
+``NotImplementedError`` and was unused internally. It is expected that there
+are no downstream use cases for this method with Python 3.
+
+(`gh-15229 <https://github.com/numpy/numpy/pull/15229>`__)
+
+``numpy.distutils.compat`` has been removed
+-------------------------------------------
+This module contained only the function ``get_exception()``, which was used as::
+
+    try:
+        ...
+    except Exception:
+        e = get_exception()
+
+Its purpose was to handle the change in syntax introduced in Python 2.6, from
+``except Exception, e:`` to ``except Exception as e:``, meaning it was only
+necessary for codebases supporting Python 2.5 and older.
+
+(`gh-15255 <https://github.com/numpy/numpy/pull/15255>`__)
+
+``issubdtype`` no longer interprets ``float`` as ``np.floating``
+----------------------------------------------------------------
+``numpy.issubdtype`` had a FutureWarning since NumPy 1.14 which
+has expired now. This means that certain input where the second
+argument was neither a datatype nor a NumPy scalar type
+(such as a string or a python type like ``int`` or ``float``)
+will now be consistent with passing in ``np.dtype(arg2).type``.
+This makes the result consistent with expectations and leads to
+a false result in some cases which previously returned true.
+
+(`gh-15773 <https://github.com/numpy/numpy/pull/15773>`__)
+
+Change output of ``round`` on scalars to be consistent with Python
+------------------------------------------------------------------
+
+Output of the ``__round__`` dunder method and consequently the Python
+built-in ``round`` has been changed to be a Python ``int`` to be consistent
+with calling it on Python ``float`` objects when called with no arguments.
+Previously, it would return a scalar of the ``np.dtype`` that was passed in.
+
+(`gh-15840 <https://github.com/numpy/numpy/pull/15840>`__)
+
+The ``numpy.ndarray`` constructor no longer interprets ``strides=()`` as ``strides=None``
+-----------------------------------------------------------------------------------------
+The former has changed to have the expected meaning of setting
+``numpy.ndarray.strides`` to ``()``, while the latter continues to result in
+strides being chosen automatically.
+
+(`gh-15882 <https://github.com/numpy/numpy/pull/15882>`__)
+
+C-Level string to datetime casts changed
+----------------------------------------
+The C-level casts from strings were simplified. This changed
+also fixes string to datetime and timedelta casts to behave
+correctly (i.e. like Python casts using ``string_arr.astype("M8")``
+while previously the cast would behave like
+``string_arr.astype(np.int_).astype("M8")``.
+This only affects code using low-level C-API to do manual casts
+(not full array casts) of single scalar values or using e.g.
+``PyArray_GetCastFunc``, and should thus not affect the vast majority
+of users.
+
+(`gh-16068 <https://github.com/numpy/numpy/pull/16068>`__)
+
+``SeedSequence`` with small seeds no longer conflicts with spawning
+-------------------------------------------------------------------
+Small seeds (less than ``2**96``) were previously implicitly 0-padded out to
+128 bits, the size of the internal entropy pool. When spawned, the spawn key
+was concatenated before the 0-padding. Since the first spawn key is ``(0,)``,
+small seeds before the spawn created the same states as the first spawned
+``SeedSequence``.  Now, the seed is explicitly 0-padded out to the internal
+pool size before concatenating the spawn key. Spawned ``SeedSequences`` will
+produce different results than in the previous release. Unspawned
+``SeedSequences`` will still produce the same results.
+
+(`gh-16551 <https://github.com/numpy/numpy/pull/16551>`__)
+
+
+Deprecations
+============
+
+Deprecate automatic ``dtype=object`` for ragged input
+-----------------------------------------------------
+Calling ``np.array([[1, [1, 2, 3]])`` will issue a ``DeprecationWarning`` as
+per `NEP 34`_. Users should explicitly use ``dtype=object`` to avoid the
+warning.
+
+.. _`NEP 34`: https://numpy.org/neps/nep-0034.html
+
+(`gh-15119 <https://github.com/numpy/numpy/pull/15119>`__)
+
+Passing ``shape=0`` to factory functions in ``numpy.rec`` is deprecated
+-----------------------------------------------------------------------
+``0`` is treated as a special case and is aliased to ``None`` in the functions:
+
+* ``numpy.core.records.fromarrays``
+* ``numpy.core.records.fromrecords``
+* ``numpy.core.records.fromstring``
+* ``numpy.core.records.fromfile``
+
+In future, ``0`` will not be special cased, and will be treated as an array
+length like any other integer.
+
+(`gh-15217 <https://github.com/numpy/numpy/pull/15217>`__)
+
+Deprecation of probably unused C-API functions
+----------------------------------------------
+The following C-API functions are probably unused and have been
+deprecated:
+
+* ``PyArray_GetArrayParamsFromObject``
+* ``PyUFunc_GenericFunction``
+* ``PyUFunc_SetUsesArraysAsData``
+
+In most cases ``PyArray_GetArrayParamsFromObject`` should be replaced
+by converting to an array, while ``PyUFunc_GenericFunction`` can be
+replaced with ``PyObject_Call`` (see documentation for details).
+
+(`gh-15427 <https://github.com/numpy/numpy/pull/15427>`__)
+
+Converting certain types to dtypes is Deprecated
+------------------------------------------------
+The super classes of scalar types, such as ``np.integer``, ``np.generic``,
+or ``np.inexact`` will now give a deprecation warning when converted
+to a dtype (or used in a dtype keyword argument).
+The reason for this is that ``np.integer`` is converted to ``np.int_``,
+while it would be expected to represent *any* integer (e.g. also
+``int8``, ``int16``, etc.
+For example, ``dtype=np.floating`` is currently identical to
+``dtype=np.float64``, even though also ``np.float32`` is a subclass of
+``np.floating``.
+
+(`gh-15534 <https://github.com/numpy/numpy/pull/15534>`__)
+
+Deprecation of ``round`` for ``np.complexfloating`` scalars
+-----------------------------------------------------------
+Output of the ``__round__`` dunder method and consequently the Python built-in
+``round`` has been deprecated on complex scalars. This does not affect
+``np.round``.
+
+(`gh-15840 <https://github.com/numpy/numpy/pull/15840>`__)
+
+``numpy.ndarray.tostring()`` is deprecated in favor of ``tobytes()``
+--------------------------------------------------------------------
+``~numpy.ndarray.tobytes`` has existed since the 1.9 release, but until this
+release ``~numpy.ndarray.tostring`` emitted no warning. The change to emit a
+warning brings NumPy in line with the builtin ``array.array`` methods of the
+same name.
+
+(`gh-15867 <https://github.com/numpy/numpy/pull/15867>`__)
+
+
+C API changes
+=============
+
+Better support for ``const`` dimensions in API functions
+--------------------------------------------------------
+The following functions now accept a constant array of ``npy_intp``:
+
+* ``PyArray_BroadcastToShape``
+* ``PyArray_IntTupleFromIntp``
+* ``PyArray_OverflowMultiplyList``
+
+Previously the caller would have to cast away the const-ness to call these
+functions.
+
+(`gh-15251 <https://github.com/numpy/numpy/pull/15251>`__)
+
+Const qualify UFunc inner loops
+-------------------------------
+``UFuncGenericFunction`` now expects pointers to const ``dimension`` and
+``strides`` as arguments. This means inner loops may no longer modify
+either ``dimension`` or ``strides``. This change leads to an
+``incompatible-pointer-types`` warning forcing users to either ignore
+the compiler warnings or to const qualify their own loop signatures.
+
+(`gh-15355 <https://github.com/numpy/numpy/pull/15355>`__)
+
+
+New Features
+============
+
+``numpy.frompyfunc`` now accepts an identity argument
+-----------------------------------------------------
+This allows the :attr:``numpy.ufunc.identity`` attribute to be set on the
+resulting ufunc, meaning it can be used for empty and multi-dimensional
+calls to :meth:``numpy.ufunc.reduce``.
+
+(`gh-8255 <https://github.com/numpy/numpy/pull/8255>`__)
+
+``np.str_`` scalars now support the buffer protocol
+---------------------------------------------------
+``np.str_`` arrays are always stored as UCS4, so the corresponding scalars
+now expose this through the buffer interface, meaning
+``memoryview(np.str_('test'))`` now works.
+
+(`gh-15385 <https://github.com/numpy/numpy/pull/15385>`__)
+
+``subok`` option for ``numpy.copy``
+-----------------------------------
+A new kwarg, ``subok``, was added to ``numpy.copy`` to allow users to toggle
+the behavior of ``numpy.copy`` with respect to array subclasses. The default
+value is ``False`` which is consistent with the behavior of ``numpy.copy`` for
+previous numpy versions. To create a copy that preserves an array subclass with
+``numpy.copy``, call ``np.copy(arr, subok=True)``. This addition better
+documents that the default behavior of ``numpy.copy`` differs from the
+``numpy.ndarray.copy`` method which respects array subclasses by default.
+
+(`gh-15685 <https://github.com/numpy/numpy/pull/15685>`__)
+
+``numpy.linalg.multi_dot`` now accepts an ``out`` argument
+----------------------------------------------------------
+
+``out`` can be used to avoid creating unnecessary copies of the final product
+computed by ``numpy.linalg.multidot``.
+
+(`gh-15715 <https://github.com/numpy/numpy/pull/15715>`__)
+
+``keepdims`` parameter for ``numpy.count_nonzero``
+--------------------------------------------------
+The parameter ``keepdims`` was added to ``numpy.count_nonzero``. The
+parameter has the same meaning as it does in reduction functions such
+as ``numpy.sum`` or ``numpy.mean``.
+
+(`gh-15870 <https://github.com/numpy/numpy/pull/15870>`__)
+
+``equal_nan`` parameter for ``numpy.array_equal``
+-------------------------------------------------
+The keyword argument ``equal_nan`` was added to ``numpy.array_equal``.
+``equal_nan`` is a boolean value that toggles whether or not ``nan`` values are
+considered equal in comparison (default is ``False``). This matches API used in
+related functions such as ``numpy.isclose`` and ``numpy.allclose``.
+
+(`gh-16128 <https://github.com/numpy/numpy/pull/16128>`__)
+
+
+Improvements
+============
+
+Improve detection of CPU features
+=================================
+Replace ``npy_cpu_supports`` which was a gcc specific mechanism to test support
+of AVX with more general functions ``npy_cpu_init`` and ``npy_cpu_have``, and
+expose the results via a ``NPY_CPU_HAVE`` c-macro as well as a python-level
+``__cpu_features__`` dictionary.
+
+(`gh-13421 <https://github.com/numpy/numpy/pull/13421>`__)
+
+Use 64-bit integer size on 64-bit platforms in fallback lapack_lite
+-------------------------------------------------------------------
+Use 64-bit integer size on 64-bit platforms in the fallback LAPACK library,
+which is used when the system has no LAPACK installed, allowing it to deal with
+linear algebra for large arrays.
+
+(`gh-15218 <https://github.com/numpy/numpy/pull/15218>`__)
+
+Use AVX512 intrinsic to implement ``np.exp`` when input is ``np.float64``
+-------------------------------------------------------------------------
+Use AVX512 intrinsic to implement ``np.exp`` when input is ``np.float64``,
+which can improve the performance of ``np.exp`` with ``np.float64`` input 5-7x
+faster than before. The ``_multiarray_umath.so`` module has grown about 63 KB
+on linux64.
+
+(`gh-15648 <https://github.com/numpy/numpy/pull/15648>`__)
+
+Ability to disable madvise hugepages
+------------------------------------
+On Linux NumPy has previously added support for madavise hugepages which can
+improve performance for very large arrays.  Unfortunately, on older Kernel
+versions this led to peformance regressions, thus by default the support has
+been disabled on kernels before version 4.6. To override the default, you can
+use the environment variable::
+
+    NUMPY_MADVISE_HUGEPAGE=0
+
+or set it to 1 to force enabling support. Note that this only makes
+a difference if the operating system is set up to use madvise
+transparent hugepage.
+
+(`gh-15769 <https://github.com/numpy/numpy/pull/15769>`__)
+
+``numpy.einsum`` accepts NumPy ``int64`` type in subscript list
+---------------------------------------------------------------
+There is no longer a type error thrown when ``numpy.einsum`` is passed
+a NumPy ``int64`` array as its subscript list.
+
+(`gh-16080 <https://github.com/numpy/numpy/pull/16080>`__)
+
+``np.logaddexp2.identity`` changed to ``-inf``
+----------------------------------------------
+The ufunc ``~numpy.logaddexp2`` now has an identity of ``-inf``, allowing it to
+be called on empty sequences.  This matches the identity of ``~numpy.logaddexp``.
+
+(`gh-16102 <https://github.com/numpy/numpy/pull/16102>`__)
+
+
+Changes
+=======
+
+Remove handling of extra argument to ``__array__``
+--------------------------------------------------
+A code path and test have been in the code since NumPy 0.4 for a two-argument
+variant of ``__array__(dtype=None, context=None)``. It was activated when
+calling ``ufunc(op)`` or ``ufunc.reduce(op)`` if ``op.__array__`` existed.
+However that variant is not documented, and it is not clear what the intention
+was for its use. It has been removed.
+
+(`gh-15118 <https://github.com/numpy/numpy/pull/15118>`__)
+
+``numpy.random._bit_generator`` moved to ``numpy.random.bit_generator``
+-----------------------------------------------------------------------
+In order to expose ``numpy.random.BitGenerator`` and
+``numpy.random.SeedSequence`` to Cython, the ``_bitgenerator`` module is now
+public as ``numpy.random.bit_generator``
+
+Cython access to the random distributions is provided via a ``pxd`` file
+------------------------------------------------------------------------
+``c_distributions.pxd`` provides access to the c functions behind many of the
+random distributions from Cython, making it convenient to use and extend them.
+
+(`gh-15463 <https://github.com/numpy/numpy/pull/15463>`__)
+
+Fixed ``eigh`` and ``cholesky`` methods in ``numpy.random.multivariate_normal``
+-------------------------------------------------------------------------------
+Previously, when passing ``method='eigh'`` or ``method='cholesky'``,
+``numpy.random.multivariate_normal`` produced samples from the wrong
+distribution. This is now fixed.
+
+(`gh-15872 <https://github.com/numpy/numpy/pull/15872>`__)
+
+Fixed the jumping implementation in ``MT19937.jumped``
+------------------------------------------------------
+This fix changes the stream produced from jumped MT19937 generators. It does
+not affect the stream produced using ``RandomState`` or ``MT19937`` that
+are directly seeded.
+
+The translation of the jumping code for the MT19937 contained a reversed loop
+ordering. ``MT19937.jumped`` matches the Makoto Matsumoto's original
+implementation of the Horner and Sliding Window jump methods.
+
+(`gh-16153 <https://github.com/numpy/numpy/pull/16153>`__)
+
diff --git a/doc/source/user/absolute_beginners.rst b/doc/source/user/absolute_beginners.rst
new file mode 100644 (file)
index 0000000..ad2cd2d
--- /dev/null
@@ -0,0 +1,1692 @@
+
+****************************************
+NumPy: the absolute basics for beginners
+****************************************
+
+.. currentmodule:: numpy
+
+Welcome to the absolute beginner's guide to NumPy! If you have comments or
+suggestions, please don’t hesitate to reach out!
+
+
+Welcome to NumPy!
+-----------------
+
+NumPy (**Numerical Python**) is an open source Python library that's used in
+almost every field of science and engineering. It's the universal standard for
+working with numerical data in Python, and it's at the core of the scientific
+Python and PyData ecosystems. NumPy users include everyone from beginning coders
+to experienced researchers doing state-of-the-art scientific and industrial
+research and development. The NumPy API is used extensively in Pandas, SciPy,
+Matplotlib, scikit-learn, scikit-image and most other data science and
+scientific Python packages.
+
+The NumPy library contains multidimensional array and matrix data structures
+(you'll find more information about this in later sections). It provides
+**ndarray**, a homogeneous n-dimensional array object, with methods to
+efficiently operate on it. NumPy can be used to perform a wide variety of
+mathematical operations on arrays.  It adds powerful data structures to Python
+that guarantee efficient calculations with arrays and matrices and it supplies
+an enormous library of high-level mathematical functions that operate on these
+arrays and matrices.
+
+Learn more about :ref:`NumPy here <whatisnumpy>`!
+
+Installing NumPy
+----------------
+
+To install NumPy, we strongly recommend using a scientific Python distribution.
+If you're looking for the full instructions for installing NumPy on your
+operating system, you can `find all of the details here
+<https://www.scipy.org/install.html>`_.
+
+
+
+If you already have Python, you can install NumPy with::
+
+  conda install numpy
+
+or ::
+
+  pip install numpy
+
+If you don't have Python yet, you might want to consider using `Anaconda
+<https://www.anaconda.com/>`_. It's the easiest way to get started. The good
+thing about getting this distribution is the fact that you don’t need to worry
+too much about separately installing NumPy or any of the major packages that
+you’ll be using for your data analyses, like pandas, Scikit-Learn, etc.
+
+You can find all of the installation details in the
+`Installation <https://www.scipy.org/install.html>`_ section
+at `SciPy <https://www.scipy.org>`_.
+
+How to import NumPy
+-------------------
+
+Any time you want to use a package or library in your code, you first need to
+make it accessible.
+
+In order to start using NumPy and all of the functions available in NumPy,
+you'll need to import it. This can be easily done with this import statement::
+
+  import numpy as np
+
+(We shorten ``numpy`` to ``np`` in order to save time and also to keep code
+standardized so that anyone working with your code can easily understand and
+run it.)
+
+Reading the example code
+------------------------
+
+If you aren't already comfortable with reading tutorials that contain a lot of code,
+you might not know how to interpret a code block that looks
+like this::
+
+  >>> a = np.arange(6)
+  >>> a2 = a[np.newaxis, :]
+  >>> a2.shape
+  (1, 6)
+
+If you aren't familiar with this style, it's very easy to understand.
+If you see ``>>>``, you're looking at **input**, or the code that
+you would enter. Everything that doesn't have ``>>>`` in front of it
+is **output**, or the results of running your code. This is the style
+you see when you run ``python`` on the command line, but if you're using IPython, you might see a different style.
+
+
+What’s the difference between a Python list and a NumPy array?
+--------------------------------------------------------------
+
+NumPy gives you an enormous range of fast and efficient ways of creating arrays
+and manipulating numerical data inside them. While a Python list can contain
+different data types within a single list, all of the elements in a NumPy array
+should be homogenous. The mathematical operations that are meant to be performed
+on arrays would be extremely inefficient if the arrays weren't homogenous.
+
+**Why use NumPy?**
+
+NumPy arrays are faster and more compact than Python lists. An array consumes
+less memory and is convenient to use. NumPy uses much less memory to store data
+and it provides a mechanism of specifying the data types. This allows the code
+to be optimized even further.
+
+What is an array?
+-----------------
+
+An array is a central data structure of the NumPy library. An array is a grid of
+values and it contains information about the raw data, how to locate an element,
+and how to interpret an element. It has a grid of elements that can be indexed
+in :ref:`various ways <quickstart.indexing-slicing-and-iterating>`.
+The elements are all of the same type, referred to as the array ``dtype``.
+
+An array can be indexed by a tuple of nonnegative integers, by booleans, by
+another array, or by integers. The ``rank`` of the array is the number of
+dimensions. The ``shape`` of the array is a tuple of integers giving the size of
+the array along each dimension.
+
+One way we can initialize NumPy arrays is from Python lists, using nested lists
+for two- or higher-dimensional data.
+
+For example::
+
+  >>> a = np.array([1, 2, 3, 4, 5, 6])
+
+or::
+
+  >>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
+
+We can access the elements in the array using square brackets. When you're
+accessing elements, remember that indexing in NumPy starts at 0. That means that
+if you want to access the first element in your array, you'll be accessing
+element "0".
+
+::
+
+  >>> print(a[0])
+  [1 2 3 4]
+
+
+More information about arrays
+-----------------------------
+
+*This section covers* ``1D array``, ``2D array``, ``ndarray``, ``vector``, ``matrix``
+
+------
+
+You might occasionally hear an array referred to as a "ndarray," which is
+shorthand for "N-dimensional array." An N-dimensional array is simply an array
+with any number of dimensions. You might also hear **1-D**, or one-dimensional
+array, **2-D**, or two-dimensional array, and so on. The NumPy ``ndarray`` class
+is used to represent both matrices and vectors. A **vector** is an array with a
+single dimension (there's no difference
+between row and column vectors), while a **matrix** refers to an
+array with two dimensions. For **3-D** or higher dimensional arrays, the term
+**tensor** is also commonly used.
+
+**What are the attributes of an array?**
+
+An array is usually a fixed-size container of items of the same type and size.
+The number of dimensions and items in an array is defined by its shape. The
+shape of an array is a tuple of non-negative integers that specify the sizes of
+each dimension.
+
+In NumPy, dimensions are called **axes**. This means that if you have a 2D array
+that looks like this::
+
+  [[0., 0., 0.],
+   [1., 1., 1.]]
+
+Your array has 2 axes. The first axis has a length of 2 and the second axis has
+a length of 3.
+
+Just like in other Python container objects, the contents of an array can be
+accessed and modified by indexing or slicing the array. Unlike the typical container
+objects, different arrays can share the same data, so changes made on one array might
+be visible in another.
+
+Array **attributes** reflect information intrinsic to the array itself. If you
+need to get, or even set, properties of an array without creating a new array,
+you can often access an array through its attributes.
+
+:ref:`Read more about array attributes here <arrays.ndarray>` and learn about
+:ref:`array objects here <arrays>`.
+
+
+How to create a basic array
+---------------------------
+
+
+*This section covers* ``np.array()``, ``np.zeros()``, ``np.ones()``,
+``np.empty()``, ``np.arange()``, ``np.linspace()``, ``dtype``
+
+-----
+
+To create a NumPy array, you can use the function ``np.array()``.
+
+All you need to do to create a simple array is pass a list to it. If you choose
+to, you can also specify the type of data in your list.
+:ref:`You can find more information about data types here <arrays.dtypes>`. ::
+
+    >>> import numpy as np
+    >>> a = np.array([1, 2, 3])
+
+You can visualize your array this way:
+
+.. image:: images/np_array.png
+
+*Be aware that these visualizations are meant to simplify ideas and give you a basic understanding of NumPy concepts and mechanics. Arrays and array operations are much more complicated than are captured here!*
+
+Besides creating an array from a sequence of elements, you can easily create an
+array filled with ``0``'s::
+
+  >>> np.zeros(2)
+  array([0., 0.])
+
+Or an array filled with ``1``'s::
+
+  >>> np.ones(2)
+  array([1., 1.])
+
+Or even an empty array! The function ``empty`` creates an array whose initial
+content is random and depends on the state of the memory. The reason to use
+``empty`` over ``zeros`` (or something similar) is speed - just make sure to
+fill every element afterwards! ::
+
+  >>> # Create an empty array with 2 elements
+  >>> np.empty(2)
+  array([ 3.14, 42.  ])  # may vary
+
+You can create an array with a range of elements::
+
+  >>> np.arange(4)
+  array([0, 1, 2, 3])
+
+And even an array that contains a range of evenly spaced intervals. To do this,
+you will specify the **first number**, **last number**, and the **step size**. ::
+
+  >>> np.arange(2, 9, 2)
+  array([2, 4, 6, 8])
+
+You can also use ``np.linspace()`` to create an array with values that are
+spaced linearly in a specified interval::
+
+  >>> np.linspace(0, 10, num=5)
+  array([ 0. ,  2.5,  5. ,  7.5, 10. ])
+
+**Specifying your data type**
+
+While the default data type is floating point (``np.float64``), you can explicitly
+specify which data type you want using the ``dtype`` keyword. ::
+
+  >>> x = np.ones(2, dtype=np.int64)
+  >>> x
+  array([1, 1])
+
+:ref:`Learn more about creating arrays here <quickstart.array-creation>`
+
+Adding, removing, and sorting elements
+--------------------------------------
+
+*This section covers* ``np.sort()``, ``np.concatenate()``
+
+-----
+
+Sorting an element is simple with ``np.sort()``. You can specify the axis, kind,
+and order when you call the function.
+
+If you start with this array::
+
+  >>> arr = np.array([2, 1, 5, 3, 7, 4, 6, 8])
+
+You can quickly sort the numbers in ascending order with::
+
+  >>> np.sort(arr)
+  array([1, 2, 3, 4, 5, 6, 7, 8])
+
+In addition to sort, which returns a sorted copy of an array, you can use:
+
+- `argsort`, which is an indirect sort along a specified axis,
+- `lexsort`, which is an indirect stable sort on multiple keys,
+- `searchsorted`, which will find elements in a sorted array, and
+- `partition`, which is a partial sort.
+
+To read more about sorting an array, see: `sort`.
+
+If you start with these arrays::
+
+  >>> a = np.array([1, 2, 3, 4])
+  >>> b = np.array([5, 6, 7, 8])
+
+You can concatenate them with ``np.concatenate()``. ::
+
+  >>> np.concatenate((a, b))
+  array([1, 2, 3, 4, 5, 6, 7, 8])
+
+Or, if you start with these arrays::
+
+  >>> x = np.array([[1, 2], [3, 4]])
+  >>> y = np.array([[5, 6]])
+
+You can concatenate them with::
+
+  >>> np.concatenate((x, y), axis=0)
+  array([[1, 2],
+         [3, 4],
+         [5, 6]])
+
+In order to remove elements from an array, it's simple to use indexing to select
+the elements that you want to keep.
+
+To read more about concatenate, see: `concatenate`.
+
+
+How do you know the shape and size of an array?
+-----------------------------------------------
+
+*This section covers* ``ndarray.ndim``, ``ndarray.size``, ``ndarray.shape``
+
+-----
+
+``ndarray.ndim`` will tell you the number of axes, or dimensions, of the array.
+
+``ndarray.size`` will tell you the total number of elements of the array. This
+is the *product* of the elements of the array's shape.
+
+``ndarray.shape`` will display a tuple of integers that indicate the number of
+elements stored along each dimension of the array. If, for example, you have a
+2-D array with 2 rows and 3 columns, the shape of your array is ``(2, 3)``.
+
+For example, if you create this array::
+
+  >>> array_example = np.array([[[0, 1, 2, 3],
+  ...                            [4, 5, 6, 7]],
+  ...
+  ...                           [[0, 1, 2, 3],
+  ...                            [4, 5, 6, 7]],
+  ...
+  ...                           [[0 ,1 ,2, 3],
+  ...                            [4, 5, 6, 7]]])
+
+To find the number of dimensions of the array, run::
+
+  >>> array_example.ndim
+  3
+
+To find the total number of elements in the array, run::
+
+  >>> array_example.size
+  24
+
+And to find the shape of your array, run::
+
+  >>> array_example.shape
+  (3, 2, 4)
+
+
+Can you reshape an array?
+-------------------------
+
+*This section covers* ``arr.reshape()``
+
+-----
+
+**Yes!**
+
+Using ``arr.reshape()`` will give a new shape to an array without changing the
+data. Just remember that when you use the reshape method, the array you want to
+produce needs to have the same number of elements as the original array. If you
+start with an array with 12 elements, you'll need to make sure that your new
+array also has a total of 12 elements.
+
+If you start with this array::
+
+  >>> a = np.arange(6)
+  >>> print(a)
+  [0 1 2 3 4 5]
+
+You can use ``reshape()`` to reshape your array. For example, you can reshape
+this array to an array with three rows and two columns::
+
+  >>> b = a.reshape(3, 2)
+  >>> print(b)
+  [[0 1]
+   [2 3]
+   [4 5]]
+
+With ``np.reshape``, you can specify a few optional parameters::
+
+  >>> numpy.reshape(a, newshape=(1, 6), order='C')
+  array([[0, 1, 2, 3, 4, 5]])
+
+``a`` is the array to be reshaped.
+
+``newshape`` is the new shape you want. You can specify an integer or a tuple of
+integers. If you specify an integer, the result will be an array of that length.
+The shape should be compatible with the original shape.
+
+``order:`` ``C`` means to read/write the elements using C-like index order,
+``F`` means to read/write the elements using Fortran-like index order, ``A``
+means to read/write the elements in Fortran-like index order if a is Fortran
+contiguous in memory, C-like order otherwise. (This is an optional parameter and
+doesn't need to be specified.)
+
+If you want to learn more about C and Fortran order, you can
+:ref:`read more about the internal organization of NumPy arrays here <numpy-internals>`.
+Essentially, C and Fortran orders have to do with how indices correspond
+to the order the array is stored in memory. In Fortran, when moving through
+the elements of a two-dimensional array as it is stored in memory, the **first**
+index is the most rapidly varying index. As the first index moves to the next
+row as it changes, the matrix is stored one column at a time.
+This is why Fortran is thought of as a **Column-major language**.
+In C on the other hand, the **last** index changes
+the most rapidly. The matrix is stored by rows, making it a **Row-major
+language**. What you do for C or Fortran depends on whether it's more important
+to preserve the indexing convention or not reorder the data.
+
+:ref:`Learn more about shape manipulation here <quickstart.shape-manipulation>`.
+
+
+How to convert a 1D array into a 2D array (how to add a new axis to an array)
+-----------------------------------------------------------------------------
+
+*This section covers* ``np.newaxis``, ``np.expand_dims``
+
+-----
+
+You can use ``np.newaxis`` and ``np.expand_dims`` to increase the dimensions of
+your existing array.
+
+Using ``np.newaxis`` will increase the dimensions of your array by one dimension
+when used once. This means that a **1D** array will become a **2D** array, a
+**2D** array will become a **3D** array, and so on.
+
+For example, if you start with this array::
+
+  >>> a = np.array([1, 2, 3, 4, 5, 6])
+  >>> a.shape
+  (6,)
+
+You can use ``np.newaxis`` to add a new axis::
+
+  >>> a2 = a[np.newaxis, :]
+  >>> a2.shape
+  (1, 6)
+
+You can explicitly convert a 1D array with either a row vector or a column
+vector using ``np.newaxis``. For example, you can convert a 1D array to a row
+vector by inserting an axis along the first dimension::
+
+  >>> row_vector = a[np.newaxis, :]
+  >>> row_vector.shape
+  (1, 6)
+
+Or, for a column vector, you can insert an axis along the second dimension::
+
+  >>> col_vector = a[:, np.newaxis]
+  >>> col_vector.shape
+  (6, 1)
+
+You can also expand an array by inserting a new axis at a specified position
+with ``np.expand_dims``.
+
+For example, if you start with this array::
+
+  >>> a = np.array([1, 2, 3, 4, 5, 6])
+  >>> a.shape
+  (6,)
+
+You can use ``np.expand_dims`` to add an axis at index position 1 with::
+
+  >>> b = np.expand_dims(a, axis=1)
+  >>> b.shape
+  (6, 1)
+
+You can add an axis at index position 0 with::
+
+  >>> c = np.expand_dims(a, axis=0)
+  >>> c.shape
+  (1, 6)
+
+Find more information about :ref:`newaxis here <arrays.indexing>` and
+``expand_dims`` at `expand_dims`.
+
+
+Indexing and slicing
+--------------------
+
+You can index and slice NumPy arrays in the same ways you can slice Python
+lists. ::
+
+  >>> data = np.array([1, 2, 3])
+
+  >>> data[1]
+  2
+  >>> data[0:2]
+  array([1, 2])
+  >>> data[1:]
+  array([2, 3])
+  >>> data[-2:]
+  array([2, 3])
+
+You can visualize it this way:
+
+.. image:: images/np_indexing.png
+
+
+You may want to take a section of your array or specific array elements to use
+in further analysis or additional operations. To do that, you'll need to subset,
+slice, and/or index your arrays.
+
+If you want to select values from your array that fulfill certain conditions,
+it's straightforward with NumPy.
+
+For example, if you start with this array::
+
+  >>> a = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
+
+You can easily print all of the values in the array that are less than 5. ::
+
+  >>> print(a[a < 5])
+  [1 2 3 4]
+
+You can also select, for example, numbers that are equal to or greater than 5,
+and use that condition to index an array. ::
+
+  >>> five_up = (a >= 5)
+  >>> print(a[five_up])
+  [ 5  6  7  8  9 10 11 12]
+
+You can select elements that are divisible by 2::
+
+  >>> divisible_by_2 = a[a%2==0]
+  >>> print(divisible_by_2)
+  [ 2  4  6  8 10 12]
+
+Or you can select elements that satisfy two conditions using the ``&`` and ``|``
+operators::
+
+  >>> c = a[(a > 2) & (a < 11)]
+  >>> print(c)
+  [ 3  4  5  6  7  8  9 10]
+
+You can also make use of the logical operators **&** and **|** in order to
+return boolean values that specify whether or not the values in an array fulfill
+a certain condition. This can be useful with arrays that contain names or other
+categorical values. ::
+
+  >>> five_up = (a > 5) | (a == 5)
+  >>> print(five_up)
+  [[False False False False]
+   [ True  True  True  True]
+   [ True  True  True True]]
+
+You can also use ``np.nonzero()`` to select elements or indices from an array.
+
+Starting with this array::
+
+  >>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
+
+You can use ``np.nonzero()`` to print the indices of elements that are, for
+example, less than 5::
+
+  >>> b = np.nonzero(a < 5)
+  >>> print(b)
+  (array([0, 0, 0, 0]), array([0, 1, 2, 3]))
+
+In this example, a tuple of arrays was returned: one for each dimension. The
+first array represents the row indices where these values are found, and the
+second array represents the column indices where the values are found.
+
+If you want to generate a list of coordinates where the elements exist, you can
+zip the arrays, iterate over the list of coordinates, and print them. For
+example::
+
+  >>> list_of_coordinates= list(zip(b[0], b[1]))
+
+  >>> for coord in list_of_coordinates:
+  ...     print(coord)
+  (0, 0)
+  (0, 1)
+  (0, 2)
+  (0, 3)
+
+You can also use ``np.nonzero()`` to print the elements in an array that are less
+than 5 with::
+
+  >>> print(a[b])
+  [1 2 3 4]
+
+If the element you're looking for doesn't exist in the array, then the returned
+array of indices will be empty. For example::
+
+  >>> not_there = np.nonzero(a == 42)
+  >>> print(not_there)
+  (array([], dtype=int64), array([], dtype=int64))
+
+Learn more about :ref:`indexing and slicing here <quickstart.indexing-slicing-and-iterating>`
+and :ref:`here <basics.indexing>`.
+
+Read more about using the nonzero function at: `nonzero`.
+
+
+How to create an array from existing data
+-----------------------------------------
+
+*This section covers* ``slicing and indexing``, ``np.vstack()``, ``np.hstack()``,
+``np.hsplit()``, ``.view()``, ``copy()``
+
+-----
+
+You can easily use create a new array from a section of an existing array.
+
+Let's say you have this array:
+
+::
+
+  >>> a = np.array([1,  2,  3,  4,  5,  6,  7,  8,  9, 10])
+
+You can create a new array from a section of your array any time by specifying
+where you want to slice your array. ::
+
+  >>> arr1 = a[3:8]
+  >>> arr1
+  array([4, 5, 6, 7, 8])
+
+Here, you grabbed a section of your array from index position 3 through index
+position 8.
+
+You can also stack two existing arrays, both vertically and horizontally. Let's
+say you have two arrays, ``a1`` and ``a2``::
+
+  >>> a1 = np.array([[1, 1],
+  ...                [2, 2]])
+
+  >>> a2 = np.array([[3, 3],
+  ...                [4, 4]])
+
+You can stack them vertically with ``vstack``::
+
+  >>> np.vstack((a1, a2))
+  array([[1, 1],
+         [2, 2],
+         [3, 3],
+         [4, 4]])
+
+Or stack them horizontally with ``hstack``::
+
+  >>> np.hstack((a1, a2))
+  array([[1, 1, 3, 3],
+         [2, 2, 4, 4]])
+
+You can split an array into several smaller arrays using ``hsplit``. You can
+specify either the number of equally shaped arrays to return or the columns
+*after* which the division should occur.
+
+Let's say you have this array::
+
+  >>> x = np.arange(1, 25).reshape(2, 12)
+  >>> x
+  array([[ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12],
+         [13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]])
+
+If you wanted to split this array into three equally shaped arrays, you would
+run::
+
+  >>> np.hsplit(x, 3)
+  [array([[1,  2,  3,  4],
+          [13, 14, 15, 16]]), array([[ 5,  6,  7,  8],
+          [17, 18, 19, 20]]), array([[ 9, 10, 11, 12],
+          [21, 22, 23, 24]])]
+
+If you wanted to split your array after the third and fourth column, you'd run::
+
+  >>> np.hsplit(x, (3, 4))
+  [array([[1, 2, 3],
+          [13, 14, 15]]), array([[ 4],
+          [16]]), array([[ 5, 6, 7, 8, 9, 10, 11, 12],
+          [17, 18, 19, 20, 21, 22, 23, 24]])]
+
+:ref:`Learn more about stacking and splitting arrays here <quickstart.stacking-arrays>`.
+
+You can use the ``view`` method to create a new array object that looks at the
+same data as the original array (a *shallow copy*).
+
+Views are an important NumPy concept! NumPy functions, as well as operations
+like indexing and slicing, will return views whenever possible. This saves
+memory and is faster (no copy of the data has to be made). However it's
+important to be aware of this - modifying data in a view also modifies the
+original array!
+
+Let's say you create this array::
+
+  >>> a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
+
+Now we create an array ``b1`` by slicing ``a`` and modify the first element of
+``b1``. This will modify the corresponding element in ``a`` as well! ::
+
+  >>> b1 = a[0, :]
+  >>> b1
+  array([1, 2, 3, 4])
+  >>> b1[0] = 99
+  >>> b1
+  array([99,  2,  3,  4])
+  >>> a
+  array([[99,  2,  3,  4],
+         [ 5,  6,  7,  8],
+         [ 9, 10, 11, 12]])
+
+Using the ``copy`` method will make a complete copy of the array and its data (a
+*deep copy*). To use this on your array, you could run::
+
+  >>> b2 = a.copy()
+
+:ref:`Learn more about copies and views here <quickstart.copies-and-views>`.
+
+
+Basic array operations
+----------------------
+
+*This section covers addition, subtraction, multiplication, division, and more*
+
+-----
+
+Once you've created your arrays, you can start to work with them.  Let's say,
+for example, that you've created two arrays, one called "data" and one called
+"ones"
+
+.. image:: images/np_array_dataones.png
+
+You can add the arrays together with the plus sign.
+
+::
+
+  >>> data = np.array([1, 2])
+  >>> ones = np.ones(2, dtype=int)
+  >>> data + ones
+  array([2, 3])
+
+.. image:: images/np_data_plus_ones.png
+
+You can, of course, do more than just addition!
+
+::
+
+  >>> data - ones
+  array([0, 1])
+  >>> data * data
+  array([1, 4])
+  >>> data / data
+  array([1., 1.])
+
+.. image:: images/np_sub_mult_divide.png
+
+Basic operations are simple with NumPy. If you want to find the sum of the
+elements in an array, you'd use ``sum()``. This works for 1D arrays, 2D arrays,
+and arrays in higher dimensions. ::
+
+  >>> a = np.array([1, 2, 3, 4])
+
+  >>> a.sum()
+  10
+
+To add the rows or the columns in a 2D array, you would specify the axis.
+
+If you start with this array::
+
+  >>> b = np.array([[1, 1], [2, 2]])
+
+You can sum the rows with::
+
+  >>> b.sum(axis=0)
+  array([3, 3])
+
+You can sum the columns with::
+
+  >>> b.sum(axis=1)
+  array([2, 4])
+
+:ref:`Learn more about basic operations here <quickstart.basic-operations>`.
+
+
+Broadcasting
+------------
+
+There are times when you might want to carry out an operation between an array
+and a single number (also called *an operation between a vector and a scalar*)
+or between arrays of two different sizes. For example, your array (we'll call it
+"data") might contain information about distance in miles but you want to
+convert the information to kilometers. You can perform this operation with::
+
+  >>> data = np.array([1.0, 2.0])
+  >>> data * 1.6
+  array([1.6, 3.2])
+
+.. image:: images/np_multiply_broadcasting.png
+
+NumPy understands that the multiplication should happen with each cell. That
+concept is called **broadcasting**. Broadcasting is a mechanism that allows
+NumPy to perform operations on arrays of different shapes. The dimensions of
+your array must be compatible, for example, when the dimensions of both arrays
+are equal or when one of them is 1. If the dimensions are not compatible, you
+will get a ``ValueError``.
+
+:ref:`Learn more about broadcasting here <basics.broadcasting>`.
+
+
+More useful array operations
+----------------------------
+
+*This section covers maximum, minimum, sum, mean, product, standard deviation, and more*
+
+-----
+
+NumPy also performs aggregation functions. In addition to ``min``, ``max``, and
+``sum``, you can easily run ``mean`` to get the average, ``prod`` to get the
+result of multiplying the elements together, ``std`` to get the standard
+deviation, and more. ::
+
+  >>> data.max()
+  2.0
+  >>> data.min()
+  1.0
+  >>> data.sum()
+  3.0
+
+.. image:: images/np_aggregation.png
+
+Let's start with this array, called "a" ::
+
+  >>> a = np.array([[0.45053314, 0.17296777, 0.34376245, 0.5510652],
+  ...               [0.54627315, 0.05093587, 0.40067661, 0.55645993],
+  ...               [0.12697628, 0.82485143, 0.26590556, 0.56917101]])
+
+It's very common to want to aggregate along a row or column. By default, every
+NumPy aggregation function will return the aggregate of the entire array. To
+find the sum or the minimum of the elements in your array, run::
+
+  >>> a.sum()
+  4.8595784
+
+Or::
+
+  >>> a.min()
+  0.05093587
+
+You can specify on which axis you want the aggregation function to be computed.
+For example, you can find the minimum value within each column by specifying
+``axis=0``. ::
+
+  >>> a.min(axis=0)
+  array([0.12697628, 0.05093587, 0.26590556, 0.5510652 ])
+
+The four values listed above correspond to the number of columns in your array.
+With a four-column array, you will get four values as your result.
+
+Read more about :ref:`array methods here <array.ndarray.methods>`.
+
+
+Creating matrices
+-----------------
+
+You can pass Python lists of lists to create a 2-D array (or "matrix") to
+represent them in NumPy. ::
+
+  >>> data = np.array([[1, 2], [3, 4]])
+  >>> data
+  array([[1, 2],
+         [3, 4]])
+
+.. image:: images/np_create_matrix.png
+
+Indexing and slicing operations are useful when you're manipulating matrices::
+
+  >>> data[0, 1]
+  2
+  >>> data[1:3]
+  array([[3, 4]])
+  >>> data[0:2, 0]
+  array([1, 3])
+
+.. image:: images/np_matrix_indexing.png
+
+You can aggregate matrices the same way you aggregated vectors::
+
+  >>> data.max()
+  4
+  >>> data.min()
+  1
+  >>> data.sum()
+  10
+
+.. image:: images/np_matrix_aggregation.png
+
+You can aggregate all the values in a matrix and you can aggregate them across
+columns or rows using the ``axis`` parameter::
+
+  >>> data.max(axis=0)
+  array([3, 4])
+  >>> data.max(axis=1)
+  array([2, 4])
+
+.. image:: images/np_matrix_aggregation_row.png
+
+Once you've created your matrices, you can add and multiply them using
+arithmetic operators if you have two matrices that are the same size. ::
+
+  >>> data = np.array([[1, 2], [3, 4]])
+  >>> ones = np.array([[1, 1], [1, 1]])
+  >>> data + ones
+  array([[2, 3],
+         [4, 5]])
+
+.. image:: images/np_matrix_arithmetic.png
+
+You can do these arithmetic operations on matrices of different sizes, but only
+if one matrix has only one column or one row. In this case, NumPy will use its
+broadcast rules for the operation. ::
+
+  >>> data = np.array([[1, 2], [3, 4], [5, 6]])
+  >>> ones_row = np.array([[1, 1]])
+  >>> data + ones_row
+  array([[2, 3],
+         [4, 5],
+         [6, 7]])
+
+.. image:: images/np_matrix_broadcasting.png
+
+Be aware that when NumPy prints N-dimensional arrays, the last axis is looped
+over the fastest while the first axis is the slowest. For instance::
+
+  >>> np.ones((4, 3, 2))
+  array([[[1., 1.],
+          [1., 1.],
+          [1., 1.]],
+  <BLANKLINE>
+         [[1., 1.],
+          [1., 1.],
+          [1., 1.]],
+  <BLANKLINE>
+         [[1., 1.],
+          [1., 1.],
+          [1., 1.]],
+  <BLANKLINE>
+         [[1., 1.],
+          [1., 1.],
+          [1., 1.]]])
+
+There are often instances where we want NumPy to initialize the values of an
+array. NumPy offers functions like ``ones()`` and ``zeros()``, and the
+``random.Generator`` class for random number generation for that.
+All you need to do is pass in the number of elements you want it to generate::
+
+  >>> np.ones(3)
+  array([1., 1., 1.])
+  >>> np.zeros(3)
+  array([0., 0., 0.])
+  # the simplest way to generate random numbers
+  >>> rng = np.random.default_rng(0)
+  >>> rng.random(3)
+  array([0.63696169, 0.26978671, 0.04097352])
+
+.. image:: images/np_ones_zeros_random.png
+
+You can also use ``ones()``, ``zeros()``, and ``random()`` to create
+a 2D array if you give them a tuple describing the dimensions of the matrix::
+
+  >>> np.ones((3, 2))
+  array([[1., 1.],
+         [1., 1.],
+         [1., 1.]])
+  >>> np.zeros((3, 2))
+  array([[0., 0.],
+         [0., 0.],
+         [0., 0.]])
+  >>> rng.random((3, 2))
+  array([[0.01652764, 0.81327024],
+         [0.91275558, 0.60663578],
+         [0.72949656, 0.54362499]])  # may vary
+
+.. image:: images/np_ones_zeros_matrix.png
+
+Read more about creating arrays, filled with ``0``'s, ``1``'s, other values or
+uninitialized, at :ref:`array creation routines <routines.array-creation>`.
+
+
+Generating random numbers
+-------------------------
+
+The use of random number generation is an important part of the configuration
+and evaluation of many numerical and machine learning algorithms. Whether you
+need to randomly initialize weights in an artificial neural network, split data
+into random sets, or randomly shuffle your dataset, being able to generate
+random numbers (actually, repeatable pseudo-random numbers) is essential.
+
+With ``Generator.integers``, you can generate random integers from low (remember
+that this is inclusive with NumPy) to high (exclusive). You can set
+``endpoint=True`` to make the high number inclusive.
+
+You can generate a 2 x 4 array of random integers between 0 and 4 with::
+
+  >>> rng.integers(5, size=(2, 4))
+  array([[2, 1, 1, 0],
+         [0, 0, 0, 4]])  # may vary
+
+:ref:`Read more about random number generation here <numpyrandom>`.
+
+
+How to get unique items and counts
+----------------------------------
+
+*This section covers* ``np.unique()``
+
+-----
+
+You can find the unique elements in an array easily with ``np.unique``.
+
+For example, if you start with this array::
+
+  >>> a = np.array([11, 11, 12, 13, 14, 15, 16, 17, 12, 13, 11, 14, 18, 19, 20])
+
+you can use ``np.unique`` to print the unique values in your array::
+
+  >>> unique_values = np.unique(a)
+  >>> print(unique_values)
+  [11 12 13 14 15 16 17 18 19 20]
+
+To get the indices of unique values in a NumPy array (an array of first index
+positions of unique values in the array), just pass the ``return_index``
+argument in ``np.unique()`` as well as your array. ::
+
+  >>> unique_values, indices_list = np.unique(a, return_index=True)
+  >>> print(indices_list)
+  [ 0  2  3  4  5  6  7 12 13 14]
+
+You can pass the ``return_counts`` argument in ``np.unique()`` along with your
+array to get the frequency count of unique values in a NumPy array. ::
+
+  >>> unique_values, occurrence_count = np.unique(a, return_counts=True)
+  >>> print(occurrence_count)
+  [3 2 2 2 1 1 1 1 1 1]
+
+This also works with 2D arrays!
+If you start with this array::
+
+  >>> a_2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12], [1, 2, 3, 4]])
+
+You can find unique values with::
+
+  >>> unique_values = np.unique(a_2d)
+  >>> print(unique_values)
+  [ 1  2  3  4  5  6  7  8  9 10 11 12]
+
+If the axis argument isn't passed, your 2D array will be flattened.
+
+If you want to get the unique rows or columns, make sure to pass the ``axis``
+argument. To find the unique rows, specify ``axis=0`` and for columns, specify
+``axis=1``. ::
+
+  >>> unique_rows = np.unique(a_2d, axis=0)
+  >>> print(unique_rows)
+  [[ 1  2  3  4]
+   [ 5  6  7  8]
+   [ 9 10 11 12]]
+
+To get the unique rows, index position, and occurrence count, you can use::
+
+  >>> unique_rows, indices, occurrence_count = np.unique(
+  ...      a_2d, axis=0, return_counts=True, return_index=True)
+  >>> print(unique_rows)
+  [[ 1  2  3  4]
+   [ 5  6  7  8]
+   [ 9 10 11 12]]
+  >>> print(indices)
+  [0 1 2]
+  >>> print(occurrence_count)
+  [2 1 1]
+
+To learn more about finding the unique elements in an array, see `unique`.
+
+
+Transposing and reshaping a matrix
+----------------------------------
+
+*This section covers* ``arr.reshape()``, ``arr.transpose()``, ``arr.T()``
+
+-----
+
+It's common to need to transpose your matrices. NumPy arrays have the property
+``T`` that allows you to transpose a matrix.
+
+.. image:: images/np_transposing_reshaping.png
+
+You may also need to switch the dimensions of a matrix. This can happen when,
+for example, you have a model that expects a certain input shape that is
+different from your dataset. This is where the ``reshape`` method can be useful.
+You simply need to pass in the new dimensions that you want for the matrix. ::
+
+  >>> data.reshape(2, 3)
+  array([[1, 2, 3],
+         [4, 5, 6]])
+  >>> data.reshape(3, 2)
+  array([[1, 2],
+         [3, 4],
+         [5, 6]])
+
+.. image:: images/np_reshape.png
+
+You can also use ``.transpose`` to reverse or change the axes of an array
+according to the values you specify.
+
+If you start with this array::
+
+  >>> arr = np.arange(6).reshape((2, 3))
+  >>> arr
+  array([[0, 1, 2],
+         [3, 4, 5]])
+
+You can transpose your array with ``arr.transpose()``. ::
+
+  >>> arr.transpose()
+  array([[0, 3],
+         [1, 4],
+         [2, 5]])
+
+To learn more about transposing and reshaping arrays, see `transpose` and
+`reshape`.
+
+
+How to reverse an array
+-----------------------
+
+*This section covers* ``np.flip``
+
+-----
+
+NumPy's ``np.flip()`` function allows you to flip, or reverse, the contents of
+an array along an axis. When using ``np.flip``, specify the array you would like
+to reverse and the axis. If you don't specify the axis, NumPy will reverse the
+contents along all of the axes of your input array.
+
+**Reversing a 1D array**
+
+If you begin with a 1D array like this one::
+
+  >>> arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
+
+You can reverse it with::
+
+  >>> reversed_arr = np.flip(arr)
+
+If you want to print your reversed array, you can run::
+
+  >>> print('Reversed Array: ', reversed_arr)
+  Reversed Array:  [8 7 6 5 4 3 2 1]
+
+**Reversing a 2D array**
+
+A 2D array works much the same way.
+
+If you start with this array::
+
+  >>> arr_2d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
+
+You can reverse the content in all of the rows and all of the columns with::
+
+  >>> reversed_arr = np.flip(arr_2d)
+  >>> print(reversed_arr)
+  [[12 11 10  9]
+   [ 8  7  6  5]
+   [ 4  3  2  1]]
+
+You can easily reverse only the *rows* with::
+
+  >>> reversed_arr_rows = np.flip(arr_2d, axis=0)
+  >>> print(reversed_arr_rows)
+  [[ 9 10 11 12]
+   [ 5  6  7  8]
+   [ 1  2  3  4]]
+
+Or reverse only the *columns* with::
+
+  >>> reversed_arr_columns = np.flip(arr_2d, axis=1)
+  >>> print(reversed_arr_columns)
+  [[ 4  3  2  1]
+   [ 8  7  6  5]
+   [12 11 10  9]]
+
+You can also reverse the contents of only one column or row. For example, you
+can reverse the contents of the row at index position 1 (the second row)::
+
+  >>> arr_2d[1] = np.flip(arr_2d[1])
+  >>> print(arr_2d)
+  [[ 1  2  3  4]
+   [ 8  7  6  5]
+   [ 9 10 11 12]]
+
+You can also reverse the column at index position 1 (the second column)::
+
+  >>> arr_2d[:,1] = np.flip(arr_2d[:,1])
+  >>> print(arr_2d)
+  [[ 1 10  3  4]
+   [ 8  7  6  5]
+   [ 9  2 11 12]]
+
+Read more about reversing arrays at `flip`.
+
+
+Reshaping and flattening multidimensional arrays
+------------------------------------------------
+
+*This section covers* ``.flatten()``, ``ravel()``
+
+-----
+
+There are two popular ways to flatten an array: ``.flatten()`` and ``.ravel()``.
+The primary difference between the two is that the new array created using
+``ravel()`` is actually a reference to the parent array (i.e., a "view"). This
+means that any changes to the new array will affect the parent array as well.
+Since ``ravel`` does not create a copy, it's memory efficient.
+
+If you start with this array::
+
+  >>> x = np.array([[1 , 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
+
+You can use ``flatten`` to flatten your array into a 1D array. ::
+
+  >>> x.flatten()
+  array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])
+
+When you use ``flatten``, changes to your new array won't change the parent
+array.
+
+For example::
+
+  >>> a1 = x.flatten()
+  >>> a1[0] = 99
+  >>> print(x)  # Original array
+  [[ 1  2  3  4]
+   [ 5  6  7  8]
+   [ 9 10 11 12]]
+  >>> print(a1)  # New array
+  [99  2  3  4  5  6  7  8  9 10 11 12]
+
+But when you use ``ravel``, the changes you make to the new array will affect
+the parent array.
+
+For example::
+
+  >>> a2 = x.ravel()
+  >>> a2[0] = 98
+  >>> print(x)  # Original array
+  [[98  2  3  4]
+   [ 5  6  7  8]
+   [ 9 10 11 12]]
+  >>> print(a2)  # New array
+  [98  2  3  4  5  6  7  8  9 10 11 12]
+
+Read more about ``flatten`` at `ndarray.flatten` and ``ravel`` at `ravel`.
+
+
+How to access the docstring for more information
+------------------------------------------------
+
+*This section covers* ``help()``, ``?``, ``??``
+
+-----
+
+When it comes to the data science ecosystem, Python and NumPy are built with the
+user in mind. One of the best examples of this is the built-in access to
+documentation. Every object contains the reference to a string, which is known
+as the **docstring**. In most cases, this docstring contains a quick and concise
+summary of the object and how to use it. Python has a built-in ``help()``
+function that can help you access this information. This means that nearly any
+time you need more information, you can use ``help()`` to quickly find the
+information that you need.
+
+For example::
+
+  >>> help(max)
+  Help on built-in function max in module builtins:
+  <BLANKLINE>
+  max(...)
+      max(iterable, *[, default=obj, key=func]) -> value
+      max(arg1, arg2, *args, *[, key=func]) -> value
+  <BLANKLINE>
+      With a single iterable argument, return its biggest item. The
+      default keyword-only argument specifies an object to return if
+      the provided iterable is empty.
+      With two or more arguments, return the largest argument.
+  <BLANKLINE>
+
+
+Because access to additional information is so useful, IPython uses the ``?``
+character as a shorthand for accessing this documentation along with other
+relevant information. IPython is a command shell for interactive computing in
+multiple languages.
+`You can find more information about IPython here <https://ipython.org/>`_.
+
+For example:
+
+.. code-block:: ipython
+
+  In [0]: max?
+  max(iterable, *[, default=obj, key=func]) -> value
+  max(arg1, arg2, *args, *[, key=func]) -> value
+
+  With a single iterable argument, return its biggest item. The
+  default keyword-only argument specifies an object to return if
+  the provided iterable is empty.
+  With two or more arguments, return the largest argument.
+  Type:      builtin_function_or_method
+
+You can even use this notation for object methods and objects themselves.
+
+Let's say you create this array::
+
+  >>> a = np.array([1, 2, 3, 4, 5, 6])
+
+Then you can obtain a lot of useful information (first details about ``a`` itself,
+followed by the docstring of ``ndarray`` of which ``a`` is an instance):
+
+.. code-block:: ipython
+
+  In [1]: a?
+  Type:            ndarray
+  String form:     [1 2 3 4 5 6]
+  Length:          6
+  File:            ~/anaconda3/lib/python3.7/site-packages/numpy/__init__.py
+  Docstring:       <no docstring>
+  Class docstring:
+  ndarray(shape, dtype=float, buffer=None, offset=0,
+          strides=None, order=None)
+
+  An array object represents a multidimensional, homogeneous array
+  of fixed-size items.  An associated data-type object describes the
+  format of each element in the array (its byte-order, how many bytes it
+  occupies in memory, whether it is an integer, a floating point number,
+  or something else, etc.)
+
+  Arrays should be constructed using `array`, `zeros` or `empty` (refer
+  to the See Also section below).  The parameters given here refer to
+  a low-level method (`ndarray(...)`) for instantiating an array.
+
+  For more information, refer to the `numpy` module and examine the
+  methods and attributes of an array.
+
+  Parameters
+  ----------
+  (for the __new__ method; see Notes below)
+
+  shape : tuple of ints
+          Shape of created array.
+  ...
+
+This also works for functions and other objects that **you** create. Just
+remember to include a docstring with your function using a string literal
+(``""" """`` or ``''' '''`` around your documentation).
+
+For example, if you create this function::
+
+  >>> def double(a):
+  ...   '''Return a * 2'''
+  ...   return a * 2
+
+You can obtain information about the function:
+
+.. code-block:: ipython
+
+  In [2]: double?
+  Signature: double(a)
+  Docstring: Return a * 2
+  File:      ~/Desktop/<ipython-input-23-b5adf20be596>
+  Type:      function
+
+You can reach another level of information by reading the source code of the
+object you're interested in. Using a double question mark (``??``) allows you to
+access the source code.
+
+For example:
+
+.. code-block:: ipython
+
+  In [3]: double??
+  Signature: double(a)
+  Source:
+  def double(a):
+      '''Return a * 2'''
+      return a * 2
+  File:      ~/Desktop/<ipython-input-23-b5adf20be596>
+  Type:      function
+
+If the object in question is compiled in a language other than Python, using
+``??`` will return the same information as ``?``. You'll find this with a lot of
+built-in objects and types, for example:
+
+.. code-block:: ipython
+
+  In [4]: len?
+  Signature: len(obj, /)
+  Docstring: Return the number of items in a container.
+  Type:      builtin_function_or_method
+
+and :
+
+.. code-block:: ipython
+
+  In [5]: len??
+  Signature: len(obj, /)
+  Docstring: Return the number of items in a container.
+  Type:      builtin_function_or_method
+
+have the same output because they were compiled in a programming language other
+than Python.
+
+
+Working with mathematical formulas
+----------------------------------
+
+The ease of implementing mathematical formulas that work on arrays is one of
+the things that make NumPy so widely used in the scientific Python community.
+
+For example, this is the mean square error formula (a central formula used in
+supervised machine learning models that deal with regression):
+
+.. image:: images/np_MSE_formula.png
+
+Implementing this formula is simple and straightforward in NumPy:
+
+.. image:: images/np_MSE_implementation.png
+
+What makes this work so well is that ``predictions`` and ``labels`` can contain
+one or a thousand values. They only need to be the same size.
+
+You can visualize it this way:
+
+.. image:: images/np_mse_viz1.png
+
+In this example, both the predictions and labels vectors contain three values,
+meaning ``n`` has a value of three. After we carry out subtractions the values
+in the vector are squared. Then NumPy sums the values, and your result is the
+error value for that prediction and a score for the quality of the model.
+
+.. image:: images/np_mse_viz2.png
+
+.. image:: images/np_MSE_explanation2.png
+
+
+How to save and load NumPy objects
+----------------------------------
+
+*This section covers* ``np.save``, ``np.savez``, ``np.savetxt``,
+``np.load``, ``np.loadtxt``
+
+-----
+
+You will, at some point, want to save your arrays to disk and load them back
+without having to re-run the code. Fortunately, there are several ways to save
+and load objects with NumPy. The ndarray objects can be saved to and loaded from
+the disk files with ``loadtxt`` and ``savetxt`` functions that handle normal
+text files, ``load`` and ``save`` functions that handle NumPy binary files with
+a **.npy** file extension, and a ``savez`` function that handles NumPy files
+with a **.npz** file extension.
+
+The **.npy** and **.npz** files store data, shape, dtype, and other information
+required to reconstruct the ndarray in a way that allows the array to be
+correctly retrieved, even when the file is on another machine with different
+architecture.
+
+If you want to store a single ndarray object, store it as a .npy file using
+``np.save``. If you want to store more than one ndarray object in a single file,
+save it as a .npz file using ``np.savez``. You can also save several arrays
+into a single file in compressed npz format with `savez_compressed`.
+
+It's easy to save and load and array with ``np.save()``. Just make sure to
+specify the array you want to save and a file name. For example, if you create
+this array::
+
+  >>> a = np.array([1, 2, 3, 4, 5, 6])
+
+You can save it as "filename.npy" with::
+
+  >>> np.save('filename', a)
+
+You can use ``np.load()`` to reconstruct your array. ::
+
+  >>> b = np.load('filename.npy')
+
+If you want to check your array, you can run:::
+
+  >>> print(b)
+  [1 2 3 4 5 6]
+
+You can save a NumPy array as a plain text file like a **.csv** or **.txt** file
+with ``np.savetxt``.
+
+For example, if you create this array::
+
+  >>> csv_arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])
+
+You can easily save it as a .csv file with the name "new_file.csv" like this::
+
+  >>> np.savetxt('new_file.csv', csv_arr)
+
+You can quickly and easily load your saved text file using ``loadtxt()``::
+
+  >>> np.loadtxt('new_file.csv')
+  array([1., 2., 3., 4., 5., 6., 7., 8.])
+
+The ``savetxt()`` and ``loadtxt()`` functions accept additional optional
+parameters such as header, footer, and delimiter. While text files can be easier
+for sharing, .npy and .npz files are smaller and faster to read. If you need more
+sophisticated handling of your text file (for example, if you need to work with
+lines that contain missing values), you will want to use the `genfromtxt`
+function.
+
+With `savetxt`, you can specify headers, footers, comments, and more.
+
+Learn more about :ref:`input and output routines here <routines.io>`.
+
+
+Importing and exporting a CSV
+-----------------------------
+
+.. save a csv
+   
+   >>> with open('music.csv', 'w') as fid:
+   ...     n = fid.write('Artist,Genre,Listeners,Plays\n')
+   ...     n = fid.write('Billie Holiday,Jazz,1300000,27000000\n')
+   ...     n = fid.write('Jimmie Hendrix,Rock,2700000,70000000\n')
+   ...     n = fid.write('Miles Davis,Jazz,1500000,48000000\n')
+   ...     n = fid.write('SIA,Pop,2000000,74000000\n')
+   
+
+
+It's simple to read in a CSV that contains existing information. The best and
+easiest way to do this is to use
+`Pandas <https://pandas.pydata.org/getpandas.html>`_. ::
+
+  >>> import pandas as pd
+
+  >>> # If all of your columns are the same type:
+  >>> x = pd.read_csv('music.csv', header=0).values
+  >>> print(x)
+  [['Billie Holiday' 'Jazz' 1300000 27000000]
+   ['Jimmie Hendrix' 'Rock' 2700000 70000000]
+   ['Miles Davis' 'Jazz' 1500000 48000000]
+   ['SIA' 'Pop' 2000000 74000000]]
+
+  >>> # You can also simply select the columns you need:
+  >>> x = pd.read_csv('music.csv', usecols=['Artist', 'Plays']).values
+  >>> print(x)
+  [['Billie Holiday' 27000000]
+   ['Jimmie Hendrix' 70000000]
+   ['Miles Davis' 48000000]
+   ['SIA' 74000000]]
+
+.. image:: images/np_pandas.png
+
+It's simple to use Pandas in order to export your array as well. If you are new
+to NumPy, you may want to  create a Pandas dataframe from the values in your
+array and then write the data frame to a CSV file with Pandas.
+
+If you created this array "a" ::
+
+  >>> a = np.array([[-2.58289208,  0.43014843, -1.24082018, 1.59572603],
+  ...               [ 0.99027828, 1.17150989,  0.94125714, -0.14692469],
+  ...               [ 0.76989341,  0.81299683, -0.95068423, 0.11769564],
+  ...               [ 0.20484034,  0.34784527,  1.96979195, 0.51992837]])
+
+.. for doctests
+   The continuous integration truncates dataframe display without this setting.
+   >>> pd.set_option('max_columns', 10)
+
+You could create a Pandas dataframe ::
+
+  >>> df = pd.DataFrame(a)
+  >>> print(df)
+            0         1         2         3
+  0 -2.582892  0.430148 -1.240820  1.595726
+  1  0.990278  1.171510  0.941257 -0.146925
+  2  0.769893  0.812997 -0.950684  0.117696
+  3  0.204840  0.347845  1.969792  0.519928
+
+You can easily save your dataframe with::
+
+  >>> df.to_csv('pd.csv')
+
+And read your CSV with::
+
+  >>> data = pd.read_csv('pd.csv')
+
+.. image:: images/np_readcsv.png
+
+You can also save your array with the NumPy ``savetxt`` method. ::
+
+  >>> np.savetxt('np.csv', a, fmt='%.2f', delimiter=',', header='1,  2,  3,  4')
+
+If you're using the command line, you can read your saved CSV any time with a
+command such as::
+
+  $ cat np.csv
+  #  1,  2,  3,  4
+  -2.58,0.43,-1.24,1.60
+  0.99,1.17,0.94,-0.15
+  0.77,0.81,-0.95,0.12
+  0.20,0.35,1.97,0.52
+
+Or you can open the file any time with a text editor!
+
+If you're interested in learning more about Pandas, take a look at the
+`official Pandas documentation <https://pandas.pydata.org/index.html>`_.
+Learn how to install Pandas with the
+`official Pandas installation information <https://pandas.pydata.org/pandas-docs/stable/install.html>`_.
+
+
+Plotting arrays with Matplotlib
+-------------------------------
+
+If you need to generate a plot for your values, it's very simple with
+`Matplotlib <https://matplotlib.org/>`_.
+
+For example, you may have an array like this one::
+
+  >>> a = np.array([2, 1, 5, 7, 4, 6, 8, 14, 10, 9, 18, 20, 22])
+
+If you already have Matplotlib installed, you can import it with::
+
+  >>> import matplotlib.pyplot as plt
+
+  # If you're using Jupyter Notebook, you may also want to run the following
+  # line of code to display your code in the notebook:
+
+  %matplotlib inline
+
+All you need to do to plot your values is run::
+
+  >>> plt.plot(a)
+
+  # If you are running from a command line, you may need to do this:
+  # >>> plt.show()
+
+.. plot:: user/plots/matplotlib1.py
+   :align: center
+   :include-source: 0
+
+For example, you can plot a 1D array like this::
+
+  >>> x = np.linspace(0, 5, 20)
+  >>> y = np.linspace(0, 10, 20)
+  >>> plt.plot(x, y, 'purple') # line
+  >>> plt.plot(x, y, 'o')      # dots
+
+.. plot:: user/plots/matplotlib2.py
+   :align: center
+   :include-source: 0
+
+With Matplotlib, you have access to an enormous number of visualization options. ::
+
+  >>> from mpl_toolkits.mplot3d import Axes3D
+  >>> fig = plt.figure()
+  >>> ax = Axes3D(fig)
+  >>> X = np.arange(-5, 5, 0.15)
+  >>> Y = np.arange(-5, 5, 0.15)
+  >>> X, Y = np.meshgrid(X, Y)
+  >>> R = np.sqrt(X**2 + Y**2)
+  >>> Z = np.sin(R)
+
+  >>> ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='viridis')
+
+.. plot:: user/plots/matplotlib3.py
+   :align: center
+   :include-source: 0
+
+
+To read more about Matplotlib and what it can do, take a look at
+`the official documentation <https://matplotlib.org/>`_.
+For directions regarding installing Matplotlib, see the official
+`installation section <https://matplotlib.org/users/installing.html>`_.
+
+
+-------------------------------------------------------
+
+*Image credits: Jay Alammar http://jalammar.github.io/*
index 4e9016ee0fdada81fa916e42bb153849ab6e1ae3..00bf17a4142bc5b86be673f80acc4a9cb37826ef 100644 (file)
@@ -1,3 +1,5 @@
+.. _basics.broadcasting:
+
 ************
 Broadcasting
 ************
index e70391ed0fe9f82d2a5b6d8cf642d28e7bd9bc53..546fd7dafa430c3ab37ed83e2ee87478ff8cb858 100644 (file)
@@ -11,7 +11,7 @@ Prerequisites
 
 Building NumPy requires the following software installed:
 
-1) Python 3.5.x or newer
+1) Python 3.6.x or newer
 
    Please note that the Python development headers also need to be installed,
    e.g., on Debian/Ubuntu one needs to install both `python3` and
@@ -23,11 +23,11 @@ Building NumPy requires the following software installed:
    Various NumPy modules use FORTRAN 77 libraries, so you'll also need a
    FORTRAN 77 compiler installed.
 
-   Note that NumPy is developed mainly using GNU compilers. Compilers from
-   other vendors such as Intel, Absoft, Sun, NAG, Compaq, Vast, Portland,
-   Lahey, HP, IBM, Microsoft are only supported in the form of community
-   feedback, and may not work out of the box. GCC 4.x (and later) compilers
-   are recommended.
+   Note that NumPy is developed mainly using GNU compilers and tested on
+   MSVC and Clang compilers. Compilers from other vendors such as Intel,
+   Absoft, Sun, NAG, Compaq, Vast, Portland, Lahey, HP, IBM are only supported
+   in the form of community feedback, and may not work out of the box.
+   GCC 4.x (and later) compilers are recommended.
 
 3) Linear Algebra libraries
 
@@ -35,6 +35,12 @@ Building NumPy requires the following software installed:
    installed. However, if these are available, NumPy's setup script can detect
    them and use them for building. A number of different LAPACK library setups
    can be used, including optimized LAPACK libraries such as OpenBLAS or MKL.
+   The choice and location of these libraries as well as include paths and
+   other such build options can be specified in a ``site.cfg`` file located in
+   the NumPy root repository or a ``.numpy-site.cfg`` file in your home
+   directory. See the ``site.cfg.example`` example file included in the NumPy
+   repository or sdist for documentation, and below for specifying search
+   priority from environmental variables.
 
 4) Cython
 
@@ -105,7 +111,8 @@ Accelerated BLAS/LAPACK libraries
 ---------------------------------
 
 NumPy searches for optimized linear algebra libraries such as BLAS and LAPACK.
-There are specific orders for searching these libraries, as described below.
+There are specific orders for searching these libraries, as described below and
+in the ``site.cfg.example`` file.
 
 BLAS
 ~~~~
index 62e8139fe74246296d4703116744635dc0c13ae8..9e9cd30679a08723b89f5213bbdeff59bb57b046 100644 (file)
@@ -110,7 +110,7 @@ to a small(er) fraction of the total time. Even if the interior of the
 loop is performed without a function call it can be advantageous to
 perform the inner loop over the dimension with the highest number of
 elements to take advantage of speed enhancements available on micro-
-processors that use pipelining to enhance fundmental operations.
+processors that use pipelining to enhance fundamental operations.
 
 The :c:func:`PyArray_IterAllButAxis` ( ``array``, ``&dim`` ) constructs an
 iterator object that is modified so that it will not iterate over the
index 00ef8ab7428f1cd33f37031d48ef9a6361796d5f..d7524209202a87b60d215c4877951b3ef739a368 100644 (file)
@@ -38,14 +38,14 @@ basic steps for doing this in Python are well-documented and you can
 find more information in the documentation for Python itself available
 online at `www.python.org <https://www.python.org>`_ .
 
-In addition to the Python C-API, there is a full and rich C-API for
-NumPy allowing sophisticated manipulations on a C-level. However, for
-most applications, only a few API calls will typically be used. If all
-you need to do is extract a pointer to memory along with some shape
-information to pass to another calculation routine, then you will use
-very different calls, then if you are trying to create a new array-
-like type or add a new data type for ndarrays. This chapter documents
-the API calls and macros that are most commonly used.
+In addition to the Python C-API, there is a full and rich C-API for NumPy
+allowing sophisticated manipulations on a C-level. However, for most
+applications, only a few API calls will typically be used. For example, if you
+need to just extract a pointer to memory along with some shape information to
+pass to another calculation routine, then you will use very different calls
+than if you are trying to create a new array-like type or add a new data type
+for ndarrays. This chapter documents the API calls and macros that are most
+commonly used.
 
 
 Required subroutine
@@ -163,7 +163,7 @@ ignored. The *args* argument contains all of the arguments passed in
 to the function as a tuple. You can do anything you want at this
 point, but usually the easiest way to manage the input arguments is to
 call :c:func:`PyArg_ParseTuple` (args, format_string,
-addresses_to_C_variables...) or :c:func:`PyArg_UnpackTuple` (tuple, "name" ,
+addresses_to_C_variables...) or :c:func:`PyArg_UnpackTuple` (tuple, "name",
 min, max, ...). A good description of how to use the first function is
 contained in the Python C-API reference manual under section 5.5
 (Parsing arguments and building values). You should pay particular
index 7b9b096afce8a689188eaf0fc1f8b970fc487ac5..9fe5f8f6e3529ea257b493dec057004ac76eb21b 100644 (file)
@@ -170,7 +170,7 @@ add (zadd, cadd, dadd, sadd). The docstring of each method contains
 information about how the module method may be called::
 
     >>> import add
-    >>> print add.zadd.__doc__
+    >>> print(add.zadd.__doc__)
     zadd - Function signature:
       zadd(a,b,c,n)
     Required arguments:
@@ -241,14 +241,14 @@ that it won't try to create the variable n until the variable a is
 created).
 
 After modifying ``add.pyf``, the new python module file can be generated
-by compiling both ``add.f95`` and ``add.pyf``::
+by compiling both ``add.f`` and ``add.pyf``::
 
-    f2py -c add.pyf add.f95 
+    f2py -c add.pyf add.f
 
 The new interface has docstring::
 
     >>> import add
-    >>> print add.zadd.__doc__
+    >>> print(add.zadd.__doc__)
     zadd - Function signature:
       c = zadd(a,b)
     Required arguments:
@@ -671,7 +671,7 @@ simply have a shared library available to you). Items to remember are:
 - A shared library must be compiled in a special way ( *e.g.* using
   the ``-shared`` flag with gcc).
 
-- On some platforms (*e.g.* Windows) , a shared library requires a
+- On some platforms (*e.g.* Windows), a shared library requires a
   .def file that specifies the functions to be exported. For example a
   mylib.def file might contain::
 
@@ -802,7 +802,7 @@ Calling the function
 
 The function is accessed as an attribute of or an item from the loaded
 shared-library. Thus, if ``./mylib.so`` has a function named
-``cool_function1`` , I could access this function either as:
+``cool_function1``, I could access this function either as:
 
 .. code-block:: python
 
index 96a73f9a60db602367c2ce2de59bd9acb75e6ba7..8ff45a934daa51830298a5762d5d5e631059cf10 100644 (file)
@@ -137,7 +137,6 @@ the module.
 
 
         /* This initiates the module using the above definitions. */
-        #if PY_VERSION_HEX >= 0x03000000
         static struct PyModuleDef moduledef = {
             PyModuleDef_HEAD_INIT,
             "spam",
@@ -159,17 +158,6 @@ the module.
             }
             return m;
         }
-        #else
-        PyMODINIT_FUNC initspam(void)
-        {
-            PyObject *m;
-
-            m = Py_InitModule("spam", SpamMethods);
-            if (m == NULL) {
-                return;
-            }
-        }
-        #endif
 
 To use the setup.py file, place setup.py and spammodule.c in the same
 folder. Then python setup.py build will build the module to import,
@@ -322,7 +310,6 @@ the primary thing that must be changed to create your own ufunc.
 
         static void *data[1] = {NULL};
 
-        #if PY_VERSION_HEX >= 0x03000000
         static struct PyModuleDef moduledef = {
             PyModuleDef_HEAD_INIT,
             "npufunc",
@@ -357,30 +344,6 @@ the primary thing that must be changed to create your own ufunc.
 
             return m;
         }
-        #else
-        PyMODINIT_FUNC initnpufunc(void)
-        {
-            PyObject *m, *logit, *d;
-
-
-            m = Py_InitModule("npufunc", LogitMethods);
-            if (m == NULL) {
-                return;
-            }
-
-            import_array();
-            import_umath();
-
-            logit = PyUFunc_FromFuncAndData(funcs, data, types, 1, 1, 1,
-                                            PyUFunc_None, "logit",
-                                            "logit_docstring", 0);
-
-            d = PyModule_GetDict(m);
-
-            PyDict_SetItemString(d, "logit", logit);
-            Py_DECREF(logit);
-        }
-        #endif
 
 This is a setup.py file for the above code. As before, the module
 can be build via calling python setup.py build at the command prompt,
@@ -601,7 +564,6 @@ the primary thing that must be changed to create your own ufunc.
                         NPY_LONGDOUBLE, NPY_LONGDOUBLE};
         static void *data[4] = {NULL, NULL, NULL, NULL};
 
-        #if PY_VERSION_HEX >= 0x03000000
         static struct PyModuleDef moduledef = {
             PyModuleDef_HEAD_INIT,
             "npufunc",
@@ -636,30 +598,6 @@ the primary thing that must be changed to create your own ufunc.
 
             return m;
         }
-        #else
-        PyMODINIT_FUNC initnpufunc(void)
-        {
-            PyObject *m, *logit, *d;
-
-
-            m = Py_InitModule("npufunc", LogitMethods);
-            if (m == NULL) {
-                return;
-            }
-
-            import_array();
-            import_umath();
-
-            logit = PyUFunc_FromFuncAndData(funcs, data, types, 4, 1, 1,
-                                            PyUFunc_None, "logit",
-                                            "logit_docstring", 0);
-
-            d = PyModule_GetDict(m);
-
-            PyDict_SetItemString(d, "logit", logit);
-            Py_DECREF(logit);
-        }
-        #endif
 
 This is a setup.py file for the above code. As before, the module
 can be build via calling python setup.py build at the command prompt,
@@ -824,7 +762,6 @@ as well as all other properties of a ufunc.
 
         static void *data[1] = {NULL};
 
-        #if PY_VERSION_HEX >= 0x03000000
         static struct PyModuleDef moduledef = {
             PyModuleDef_HEAD_INIT,
             "npufunc",
@@ -859,30 +796,6 @@ as well as all other properties of a ufunc.
 
             return m;
         }
-        #else
-        PyMODINIT_FUNC initnpufunc(void)
-        {
-            PyObject *m, *logit, *d;
-
-
-            m = Py_InitModule("npufunc", LogitMethods);
-            if (m == NULL) {
-                return;
-            }
-
-            import_array();
-            import_umath();
-
-            logit = PyUFunc_FromFuncAndData(funcs, data, types, 1, 2, 2,
-                                            PyUFunc_None, "logit",
-                                            "logit_docstring", 0);
-
-            d = PyModule_GetDict(m);
-
-            PyDict_SetItemString(d, "logit", logit);
-            Py_DECREF(logit);
-        }
-        #endif
 
 
 .. _`sec:NumPy-struct-dtype`:
@@ -976,7 +889,6 @@ The C file is given below.
 
         static void *data[1] = {NULL};
 
-        #if defined(NPY_PY3K)
         static struct PyModuleDef moduledef = {
             PyModuleDef_HEAD_INIT,
             "struct_ufunc_test",
@@ -988,31 +900,18 @@ The C file is given below.
             NULL,
             NULL
         };
-        #endif
 
-        #if defined(NPY_PY3K)
         PyMODINIT_FUNC PyInit_struct_ufunc_test(void)
-        #else
-        PyMODINIT_FUNC initstruct_ufunc_test(void)
-        #endif
         {
             PyObject *m, *add_triplet, *d;
             PyObject *dtype_dict;
             PyArray_Descr *dtype;
             PyArray_Descr *dtypes[3];
 
-        #if defined(NPY_PY3K)
             m = PyModule_Create(&moduledef);
-        #else
-            m = Py_InitModule("struct_ufunc_test", StructUfuncTestMethods);
-        #endif
 
             if (m == NULL) {
-        #if defined(NPY_PY3K)
                 return NULL;
-        #else
-                return;
-        #endif
             }
 
             import_array();
@@ -1043,9 +942,7 @@ The C file is given below.
 
             PyDict_SetItemString(d, "add_triplet", add_triplet);
             Py_DECREF(add_triplet);
-        #if defined(NPY_PY3K)
             return m;
-        #endif
         }
 
 .. index::
diff --git a/doc/source/user/explanations_index.rst b/doc/source/user/explanations_index.rst
new file mode 100644 (file)
index 0000000..f515e36
--- /dev/null
@@ -0,0 +1,14 @@
+.. _explanations:
+
+################
+Explanations
+################
+
+These documents are intended to explain in detail the concepts and techniques
+used in NumPy. For the reference documentation of the functions and classes
+contained in the package, see the :ref:`API reference <reference>`.
+
+.. toctree::
+   :maxdepth: 1
+
+   basics.broadcasting
diff --git a/doc/source/user/howtos_index.rst b/doc/source/user/howtos_index.rst
new file mode 100644 (file)
index 0000000..c052286
--- /dev/null
@@ -0,0 +1,14 @@
+.. _howtos:
+
+################
+NumPy How Tos
+################
+
+These documents are intended as recipes to common tasks using NumPy. For
+detailed reference documentation of the functions and classes contained in
+the package, see the :ref:`API reference <reference>`.
+
+.. toctree::
+   :maxdepth: 1
+
+   ionumpy
diff --git a/doc/source/user/images/np_MSE_explanation.png b/doc/source/user/images/np_MSE_explanation.png
new file mode 100644 (file)
index 0000000..6e20116
Binary files /dev/null and b/doc/source/user/images/np_MSE_explanation.png differ
diff --git a/doc/source/user/images/np_MSE_explanation2.png b/doc/source/user/images/np_MSE_explanation2.png
new file mode 100644 (file)
index 0000000..578e502
Binary files /dev/null and b/doc/source/user/images/np_MSE_explanation2.png differ
diff --git a/doc/source/user/images/np_MSE_formula.png b/doc/source/user/images/np_MSE_formula.png
new file mode 100644 (file)
index 0000000..7e69829
Binary files /dev/null and b/doc/source/user/images/np_MSE_formula.png differ
diff --git a/doc/source/user/images/np_MSE_implementation.png b/doc/source/user/images/np_MSE_implementation.png
new file mode 100644 (file)
index 0000000..004e82a
Binary files /dev/null and b/doc/source/user/images/np_MSE_implementation.png differ
diff --git a/doc/source/user/images/np_aggregation.png b/doc/source/user/images/np_aggregation.png
new file mode 100644 (file)
index 0000000..4356193
Binary files /dev/null and b/doc/source/user/images/np_aggregation.png differ
diff --git a/doc/source/user/images/np_array.png b/doc/source/user/images/np_array.png
new file mode 100644 (file)
index 0000000..24ba412
Binary files /dev/null and b/doc/source/user/images/np_array.png differ
diff --git a/doc/source/user/images/np_array_data_ones.png b/doc/source/user/images/np_array_data_ones.png
new file mode 100644 (file)
index 0000000..9b49b6e
Binary files /dev/null and b/doc/source/user/images/np_array_data_ones.png differ
diff --git a/doc/source/user/images/np_array_dataones.png b/doc/source/user/images/np_array_dataones.png
new file mode 100644 (file)
index 0000000..d9b1323
Binary files /dev/null and b/doc/source/user/images/np_array_dataones.png differ
diff --git a/doc/source/user/images/np_create_array.png b/doc/source/user/images/np_create_array.png
new file mode 100644 (file)
index 0000000..878bad9
Binary files /dev/null and b/doc/source/user/images/np_create_array.png differ
diff --git a/doc/source/user/images/np_create_matrix.png b/doc/source/user/images/np_create_matrix.png
new file mode 100644 (file)
index 0000000..cd685c4
Binary files /dev/null and b/doc/source/user/images/np_create_matrix.png differ
diff --git a/doc/source/user/images/np_data_plus_ones.png b/doc/source/user/images/np_data_plus_ones.png
new file mode 100644 (file)
index 0000000..b80c264
Binary files /dev/null and b/doc/source/user/images/np_data_plus_ones.png differ
diff --git a/doc/source/user/images/np_indexing.png b/doc/source/user/images/np_indexing.png
new file mode 100644 (file)
index 0000000..4303ec3
Binary files /dev/null and b/doc/source/user/images/np_indexing.png differ
diff --git a/doc/source/user/images/np_matrix_aggregation.png b/doc/source/user/images/np_matrix_aggregation.png
new file mode 100644 (file)
index 0000000..9c2fc51
Binary files /dev/null and b/doc/source/user/images/np_matrix_aggregation.png differ
diff --git a/doc/source/user/images/np_matrix_aggregation_row.png b/doc/source/user/images/np_matrix_aggregation_row.png
new file mode 100644 (file)
index 0000000..d474c27
Binary files /dev/null and b/doc/source/user/images/np_matrix_aggregation_row.png differ
diff --git a/doc/source/user/images/np_matrix_arithmetic.png b/doc/source/user/images/np_matrix_arithmetic.png
new file mode 100644 (file)
index 0000000..7947025
Binary files /dev/null and b/doc/source/user/images/np_matrix_arithmetic.png differ
diff --git a/doc/source/user/images/np_matrix_broadcasting.png b/doc/source/user/images/np_matrix_broadcasting.png
new file mode 100644 (file)
index 0000000..e8102a7
Binary files /dev/null and b/doc/source/user/images/np_matrix_broadcasting.png differ
diff --git a/doc/source/user/images/np_matrix_indexing.png b/doc/source/user/images/np_matrix_indexing.png
new file mode 100644 (file)
index 0000000..97f90f1
Binary files /dev/null and b/doc/source/user/images/np_matrix_indexing.png differ
diff --git a/doc/source/user/images/np_mse_viz1.png b/doc/source/user/images/np_mse_viz1.png
new file mode 100644 (file)
index 0000000..987a48c
Binary files /dev/null and b/doc/source/user/images/np_mse_viz1.png differ
diff --git a/doc/source/user/images/np_mse_viz2.png b/doc/source/user/images/np_mse_viz2.png
new file mode 100644 (file)
index 0000000..5594b03
Binary files /dev/null and b/doc/source/user/images/np_mse_viz2.png differ
diff --git a/doc/source/user/images/np_multiply_broadcasting.png b/doc/source/user/images/np_multiply_broadcasting.png
new file mode 100644 (file)
index 0000000..02337d9
Binary files /dev/null and b/doc/source/user/images/np_multiply_broadcasting.png differ
diff --git a/doc/source/user/images/np_ones_zeros_matrix.png b/doc/source/user/images/np_ones_zeros_matrix.png
new file mode 100644 (file)
index 0000000..9cb5464
Binary files /dev/null and b/doc/source/user/images/np_ones_zeros_matrix.png differ
diff --git a/doc/source/user/images/np_ones_zeros_random.png b/doc/source/user/images/np_ones_zeros_random.png
new file mode 100644 (file)
index 0000000..1773071
Binary files /dev/null and b/doc/source/user/images/np_ones_zeros_random.png differ
diff --git a/doc/source/user/images/np_pandas.png b/doc/source/user/images/np_pandas.png
new file mode 100644 (file)
index 0000000..cc0cd06
Binary files /dev/null and b/doc/source/user/images/np_pandas.png differ
diff --git a/doc/source/user/images/np_readcsv.png b/doc/source/user/images/np_readcsv.png
new file mode 100644 (file)
index 0000000..9d2b9e0
Binary files /dev/null and b/doc/source/user/images/np_readcsv.png differ
diff --git a/doc/source/user/images/np_reshape.png b/doc/source/user/images/np_reshape.png
new file mode 100644 (file)
index 0000000..7ebb8d6
Binary files /dev/null and b/doc/source/user/images/np_reshape.png differ
diff --git a/doc/source/user/images/np_sub_mult_divide.png b/doc/source/user/images/np_sub_mult_divide.png
new file mode 100644 (file)
index 0000000..a5df2a6
Binary files /dev/null and b/doc/source/user/images/np_sub_mult_divide.png differ
diff --git a/doc/source/user/images/np_transposing_reshaping.png b/doc/source/user/images/np_transposing_reshaping.png
new file mode 100644 (file)
index 0000000..5399043
Binary files /dev/null and b/doc/source/user/images/np_transposing_reshaping.png differ
index a45fec9ecb6ddb0f25b83cc8f03d43979668020e..4e6a29d9f8634a0ad38a119ef1fba9a28d0e0459 100644 (file)
@@ -1,3 +1,5 @@
+:orphan:
+
 .. _user:
 
 ################
@@ -14,8 +16,11 @@ classes contained in the package, see the :ref:`reference`.
 
    setting-up
    quickstart
+   absolute_beginners
    basics
    misc
    numpy-for-matlab-users
    building
    c-info
+   tutorials_index
+   howtos_index
diff --git a/doc/source/user/ionumpy.rst b/doc/source/user/ionumpy.rst
new file mode 100644 (file)
index 0000000..a317203
--- /dev/null
@@ -0,0 +1,20 @@
+================================================
+How to read and write data using NumPy
+================================================
+
+.. currentmodule:: numpy
+
+.. testsetup::
+
+   import numpy as np
+   np.random.seed(1)
+
+**Objectives**
+
+- Writing NumPy arrays to files
+- Reading NumPy arrays from files
+- Dealing with encoding and dtype issues
+
+**Content**
+
+To be completed.
index e53d1ca45558de8bf14b320241d2024962f96902..602192ecd1e1a898cef95f047fc7dc2fb23140ba 100644 (file)
@@ -394,7 +394,8 @@ Linear Algebra Equivalents
 
    * - ``y=x(:)``
      - ``y = x.flatten()``
-     - turn array into vector (note that this forces a copy)
+     - turn array into vector (note that this forces a copy). To obtain the
+       same data ordering as in Matlab, use ``x.flatten('F')``.
 
    * - ``1:10``
      - ``arange(1.,11.)`` or ``r_[1.:11.]`` or  ``r_[1:10:10j]``
diff --git a/doc/source/user/plot_approx.py b/doc/source/user/plot_approx.py
new file mode 100644 (file)
index 0000000..a2d6981
--- /dev/null
@@ -0,0 +1,19 @@
+from scipy import misc
+import matplotlib.pyplot as plt
+import numpy as np
+from numpy import linalg
+
+img = misc.face()
+img_array = img / 255
+img_gray = img_array @ [0.2126, 0.7152, 0.0722]
+
+U, s, Vt = linalg.svd(img_gray)
+
+Sigma = np.zeros((768, 1024))
+for i in range(768):
+    Sigma[i, i] = s[i]
+
+k = 10
+
+approx = U @ Sigma[:, :k] @ Vt[:k, :]
+plt.imshow(approx, cmap="gray")
diff --git a/doc/source/user/plot_face.py b/doc/source/user/plot_face.py
new file mode 100644 (file)
index 0000000..c0891e7
--- /dev/null
@@ -0,0 +1,5 @@
+from scipy import misc
+import matplotlib.pyplot as plt
+
+img = misc.face()
+plt.imshow(img)
diff --git a/doc/source/user/plot_final.py b/doc/source/user/plot_final.py
new file mode 100644 (file)
index 0000000..10cb097
--- /dev/null
@@ -0,0 +1,19 @@
+from scipy import misc
+import matplotlib.pyplot as plt
+import numpy as np
+from numpy import linalg
+
+img = misc.face()
+img_array = img / 255
+img_array_transposed = np.transpose(img_array, (2, 0, 1))
+
+U, s, Vt = linalg.svd(img_array_transposed)
+
+Sigma = np.zeros((3, 768, 1024))
+for j in range(3):
+    np.fill_diagonal(Sigma[j, :, :], s[j, :])
+
+k = 10
+
+approx_img = U @ Sigma[..., :k] @ Vt[..., :k, :]
+plt.imshow(np.transpose(approx_img, (1, 2, 0)))
diff --git a/doc/source/user/plot_gray.py b/doc/source/user/plot_gray.py
new file mode 100644 (file)
index 0000000..6cb46bb
--- /dev/null
@@ -0,0 +1,8 @@
+from scipy import misc
+import matplotlib.pyplot as plt
+import numpy as np
+
+img = misc.face()
+img_array = img / 255
+img_gray = img_array @ [0.2126, 0.7152, 0.0722]
+plt.imshow(img_gray, cmap="gray")
diff --git a/doc/source/user/plot_gray_svd.py b/doc/source/user/plot_gray_svd.py
new file mode 100644 (file)
index 0000000..9543993
--- /dev/null
@@ -0,0 +1,16 @@
+from scipy import misc
+import matplotlib.pyplot as plt
+import numpy as np
+from numpy import linalg
+
+img = misc.face()
+img_array = img / 255
+img_gray = img_array @ [0.2126, 0.7152, 0.0722]
+
+U, s, Vt = linalg.svd(img_gray)
+
+Sigma = np.zeros((768, 1024))
+for i in range(768):
+    Sigma[i, i] = s[i]
+
+plt.plot(s)
diff --git a/doc/source/user/plot_reconstructed.py b/doc/source/user/plot_reconstructed.py
new file mode 100644 (file)
index 0000000..37cf3c6
--- /dev/null
@@ -0,0 +1,17 @@
+from scipy import misc
+import matplotlib.pyplot as plt
+import numpy as np
+from numpy import linalg
+
+img = misc.face()
+img_array = img / 255
+img_array_transposed = np.transpose(img_array, (2, 0, 1))
+
+U, s, Vt = linalg.svd(img_array_transposed)
+
+Sigma = np.zeros((3, 768, 1024))
+for j in range(3):
+    np.fill_diagonal(Sigma[j, :, :], s[j, :])
+
+reconstructed = U @ Sigma @ Vt
+plt.imshow(np.transpose(reconstructed, (1, 2, 0)))
diff --git a/doc/source/user/plots/matplotlib1.py b/doc/source/user/plots/matplotlib1.py
new file mode 100644 (file)
index 0000000..2cbf87f
--- /dev/null
@@ -0,0 +1,7 @@
+import matplotlib.pyplot as plt
+import numpy as np
+
+a = np.array([2, 1, 5, 7, 4, 6, 8, 14, 10, 9, 18, 20, 22])
+
+plt.plot(a) 
+plt.show()
\ No newline at end of file
diff --git a/doc/source/user/plots/matplotlib2.py b/doc/source/user/plots/matplotlib2.py
new file mode 100644 (file)
index 0000000..e15986c
--- /dev/null
@@ -0,0 +1,8 @@
+import matplotlib.pyplot as plt
+import numpy as np
+
+x = np.linspace(0, 5, 20)
+y = np.linspace(0, 10, 20)
+plt.plot(x, y, 'purple') # line
+plt.plot(x, y, 'o')      # dots
+plt.show()
\ No newline at end of file
diff --git a/doc/source/user/plots/matplotlib3.py b/doc/source/user/plots/matplotlib3.py
new file mode 100644 (file)
index 0000000..20a8c07
--- /dev/null
@@ -0,0 +1,15 @@
+import numpy as np
+import matplotlib.pyplot as plt
+from mpl_toolkits.mplot3d import Axes3D
+
+fig = plt.figure()
+ax = Axes3D(fig)
+X = np.arange(-5, 5, 0.15)
+Y = np.arange(-5, 5, 0.15)
+X, Y = np.meshgrid(X, Y)
+R = np.sqrt(X**2 + Y**2)
+Z = np.sin(R)
+
+ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='viridis')
+
+plt.show()
\ No newline at end of file
index 6211d0c69b80983c2327469ad7835ebb80b43845..29a4d80cae646235d78dae5c1189d2826ac8a9c0 100644 (file)
@@ -6,8 +6,8 @@ Quickstart tutorial
 
 .. testsetup::
 
-   import numpy as np
-   np.random.seed(1)
+   >>> import numpy as np
+   >>> import sys
 
 Prerequisites
 =============
@@ -20,6 +20,27 @@ If you wish to work the examples in this tutorial, you must also have
 some software installed on your computer. Please see
 https://scipy.org/install.html for instructions.
 
+**Learner profile**
+
+This tutorial is intended as a quick overview of 
+algebra and arrays in NumPy and want to understand how n-dimensional
+(:math:`n>=2`) arrays are represented and can be manipulated. In particular, if
+you don't know how to apply common functions to n-dimensional arrays (without
+using for-loops), or if you want to understand axis and shape properties for
+n-dimensional arrays, this tutorial might be of help.
+
+**Learning Objectives**
+
+After this tutorial, you should be able to:
+
+- Understand the difference between one-, two- and n-dimensional arrays in
+  NumPy;
+- Understand how to apply some linear algebra operations to n-dimensional
+  arrays without using for-loops;
+- Understand axis and shape properties for n-dimensional arrays.
+
+.. _quickstart.the-basics:
+
 The Basics
 ==========
 
@@ -88,13 +109,14 @@ An example
     >>> a.size
     15
     >>> type(a)
-    <type 'numpy.ndarray'>
+    <class 'numpy.ndarray'>
     >>> b = np.array([6, 7, 8])
     >>> b
     array([6, 7, 8])
     >>> type(b)
-    <type 'numpy.ndarray'>
+    <class 'numpy.ndarray'>
 
+.. _quickstart.array-creation:
 
 Array Creation
 --------------
@@ -117,13 +139,15 @@ from the type of the elements in the sequences.
     >>> b.dtype
     dtype('float64')
 
-A frequent error consists in calling ``array`` with multiple numeric
-arguments, rather than providing a single list of numbers as an
-argument.
+A frequent error consists in calling ``array`` with multiple arguments,
+rather than providing a single sequence as an argument.
 
 ::
 
     >>> a = np.array(1,2,3,4)    # WRONG
+    Traceback (most recent call last):
+      ...
+    TypeError: array() takes from 1 to 2 positional arguments but 4 were given
     >>> a = np.array([1,2,3,4])  # RIGHT
 
 ``array`` transforms sequences of sequences into two-dimensional arrays,
@@ -134,8 +158,8 @@ so on.
 
     >>> b = np.array([(1.5,2,3), (4,5,6)])
     >>> b
-    array([[ 1.5,  2. ,  3. ],
-           [ 4. ,  5. ,  6. ]])
+    array([[1.5, 2. , 3. ],
+           [4. , 5. , 6. ]])
 
 The type of the array can also be explicitly specified at creation time:
 
@@ -143,8 +167,8 @@ The type of the array can also be explicitly specified at creation time:
 
     >>> c = np.array( [ [1,2], [3,4] ], dtype=complex )
     >>> c
-    array([[ 1.+0.j,  2.+0.j],
-           [ 3.+0.j,  4.+0.j]])
+    array([[1.+0.j, 2.+0.j],
+           [3.+0.j, 4.+0.j]])
 
 Often, the elements of an array are originally unknown, but its size is
 known. Hence, NumPy offers several functions to create
@@ -159,30 +183,32 @@ state of the memory. By default, the dtype of the created array is
 
 ::
 
-    >>> np.zeros( (3,4) )
-    array([[ 0.,  0.,  0.,  0.],
-           [ 0.,  0.,  0.,  0.],
-           [ 0.,  0.,  0.,  0.]])
+    >>> np.zeros((3, 4))
+    array([[0., 0., 0., 0.],
+           [0., 0., 0., 0.],
+           [0., 0., 0., 0.]])
     >>> np.ones( (2,3,4), dtype=np.int16 )                # dtype can also be specified
-    array([[[ 1, 1, 1, 1],
-            [ 1, 1, 1, 1],
-            [ 1, 1, 1, 1]],
-           [[ 1, 1, 1, 1],
-            [ 1, 1, 1, 1],
-            [ 1, 1, 1, 1]]], dtype=int16)
-    >>> np.empty( (2,3) )                                 # uninitialized, output may vary
-    array([[  3.73603959e-262,   6.02658058e-154,   6.55490914e-260],
+    array([[[1, 1, 1, 1],
+            [1, 1, 1, 1],
+            [1, 1, 1, 1]],
+    <BLANKLINE>
+           [[1, 1, 1, 1],
+            [1, 1, 1, 1],
+            [1, 1, 1, 1]]], dtype=int16)
+    >>> np.empty( (2,3) )                                 # uninitialized
+    array([[  3.73603959e-262,   6.02658058e-154,   6.55490914e-260],  # may vary
            [  5.30498948e-313,   3.14673309e-307,   1.00000000e+000]])
 
-To create sequences of numbers, NumPy provides a function analogous to
-``range`` that returns arrays instead of lists.
+To create sequences of numbers, NumPy provides the ``arange`` function
+which is analogous to the Python built-in ``range``, but returns an
+array.
 
 ::
 
     >>> np.arange( 10, 30, 5 )
     array([10, 15, 20, 25])
     >>> np.arange( 0, 2, 0.3 )                 # it accepts float arguments
-    array([ 0. ,  0.3,  0.6,  0.9,  1.2,  1.5,  1.8])
+    array([0. , 0.3, 0.6, 0.9, 1.2, 1.5, 1.8])
 
 When ``arange`` is used with floating point arguments, it is generally
 not possible to predict the number of elements obtained, due to the
@@ -192,7 +218,7 @@ of elements that we want, instead of the step::
 
     >>> from numpy import pi
     >>> np.linspace( 0, 2, 9 )                 # 9 numbers from 0 to 2
-    array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ,  1.25,  1.5 ,  1.75,  2.  ])
+    array([0.  , 0.25, 0.5 , 0.75, 1.  , 1.25, 1.5 , 1.75, 2.  ])
     >>> x = np.linspace( 0, 2*pi, 100 )        # useful to evaluate function at lots of points
     >>> f = np.sin(x)
 
@@ -206,8 +232,8 @@ of elements that we want, instead of the step::
     `empty_like`,
     `arange`,
     `linspace`,
-    `numpy.random.RandomState.rand`,
-    `numpy.random.RandomState.randn`,
+    `numpy.random.Generator.rand`,
+    `numpy.random.Generator.randn`,
     `fromfunction`,
     `fromfile`
 
@@ -243,6 +269,7 @@ matrices and tridimensionals as lists of matrices.
     [[[ 0  1  2  3]
       [ 4  5  6  7]
       [ 8  9 10 11]]
+    <BLANKLINE>
      [[12 13 14 15]
       [16 17 18 19]
       [20 21 22 23]]]
@@ -254,16 +281,16 @@ If an array is too large to be printed, NumPy automatically skips the
 central part of the array and only prints the corners::
 
     >>> print(np.arange(10000))
-    [   0    1    2 ..., 9997 9998 9999]
+    [   0    1    2 ... 9997 9998 9999]
     >>>
     >>> print(np.arange(10000).reshape(100,100))
-    [[   0    1    2 ...,   97   98   99]
-     [ 100  101  102 ...,  197  198  199]
-     [ 200  201  202 ...,  297  298  299]
-     ...,
-     [9700 9701 9702 ..., 9797 9798 9799]
-     [9800 9801 9802 ..., 9897 9898 9899]
-     [9900 9901 9902 ..., 9997 9998 9999]]
+    [[   0    1    2 ...   97   98   99]
+     [ 100  101  102 ...  197  198  199]
+     [ 200  201  202 ...  297  298  299]
+     ...
+     [9700 9701 9702 ... 9797 9798 9799]
+     [9800 9801 9802 ... 9897 9898 9899]
+     [9900 9901 9902 ... 9997 9998 9999]]
 
 To disable this behaviour and force NumPy to print the entire array, you
 can change the printing options using ``set_printoptions``.
@@ -273,6 +300,8 @@ can change the printing options using ``set_printoptions``.
     >>> np.set_printoptions(threshold=sys.maxsize)       # sys module should be imported
 
 
+.. _quickstart.basic-operations:
+
 Basic Operations
 ----------------
 
@@ -293,16 +322,16 @@ created and filled with the result.
     >>> 10*np.sin(a)
     array([ 9.12945251, -9.88031624,  7.4511316 , -2.62374854])
     >>> a<35
-    array([ True, True, False, False])
+    array([ True,  True, False, False])
 
 Unlike in many matrix languages, the product operator ``*`` operates
 elementwise in NumPy arrays. The matrix product can be performed using
 the ``@`` operator (in python >=3.5) or the ``dot`` function or method::
 
     >>> A = np.array( [[1,1],
-    ...             [0,1]] )
+    ...                [0,1]] )
     >>> B = np.array( [[2,0],
-    ...             [3,4]] )
+    ...                [3,4]] )
     >>> A * B                       # elementwise product
     array([[2, 0],
            [0, 4]])
@@ -318,20 +347,21 @@ existing array rather than create a new one.
 
 ::
 
+    >>> rg = np.random.default_rng(1)     # create instance of default random number generator
     >>> a = np.ones((2,3), dtype=int)
-    >>> b = np.random.random((2,3))
+    >>> b = rg.random((2,3))
     >>> a *= 3
     >>> a
     array([[3, 3, 3],
            [3, 3, 3]])
     >>> b += a
     >>> b
-    array([[ 3.417022  ,  3.72032449,  3.00011437],
-           [ 3.30233257,  3.14675589,  3.09233859]])
-    >>> a += b                  # b is not automatically converted to integer type
+    array([[3.51182162, 3.9504637 , 3.14415961],
+           [3.94864945, 3.31183145, 3.42332645]])
+    >>> a += b                            # b is not automatically converted to integer type
     Traceback (most recent call last):
-      ...
-    TypeError: Cannot cast ufunc add output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
+        ...
+    numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'
 
 When operating with arrays of different types, the type of the resulting
 array corresponds to the more general or precise one (a behavior known
@@ -345,7 +375,7 @@ as upcasting).
     'float64'
     >>> c = a+b
     >>> c
-    array([ 1.        ,  2.57079633,  4.14159265])
+    array([1.        , 2.57079633, 4.14159265])
     >>> c.dtype.name
     'float64'
     >>> d = np.exp(c*1j)
@@ -360,16 +390,16 @@ the array, are implemented as methods of the ``ndarray`` class.
 
 ::
 
-    >>> a = np.random.random((2,3))
+    >>> a = rg.random((2,3))
     >>> a
-    array([[ 0.18626021,  0.34556073,  0.39676747],
-           [ 0.53881673,  0.41919451,  0.6852195 ]])
+    array([[0.82770259, 0.40919914, 0.54959369],
+           [0.02755911, 0.75351311, 0.53814331]])
     >>> a.sum()
-    2.5718191614547998
+    3.1057109529998157
     >>> a.min()
-    0.1862602113776709
+    0.027559113243068367
     >>> a.max()
-    0.6852195003967595
+    0.8277025938204418
 
 By default, these operations apply to the array as though it were a list
 of numbers, regardless of its shape. However, by specifying the ``axis``
@@ -408,12 +438,12 @@ operate elementwise on an array, producing an array as output.
     >>> B
     array([0, 1, 2])
     >>> np.exp(B)
-    array([ 1.        ,  2.71828183,  7.3890561 ])
+    array([1.        , 2.71828183, 7.3890561 ])
     >>> np.sqrt(B)
-    array([ 0.        ,  1.        ,  1.41421356])
+    array([0.        , 1.        , 1.41421356])
     >>> C = np.array([2., -1., 4.])
     >>> np.add(B, C)
-    array([ 2.,  0.,  6.])
+    array([2., 0., 6.])
 
 .. seealso::
 
@@ -437,7 +467,7 @@ operate elementwise on an array, producing an array as output.
     `dot`,
     `floor`,
     `inner`,
-    `inv`,
+    `invert`,
     `lexsort`,
     `max`,
     `maximum`,
@@ -460,6 +490,8 @@ operate elementwise on an array, producing an array as output.
     `vectorize`,
     `where`
 
+.. _quickstart.indexing-slicing-and-iterating:
+
 Indexing, Slicing and Iterating
 -------------------------------
 
@@ -477,24 +509,27 @@ and other Python sequences.
     8
     >>> a[2:5]
     array([ 8, 27, 64])
-    >>> a[:6:2] = -1000    # equivalent to a[0:6:2] = -1000; from start to position 6, exclusive, set every 2nd element to -1000
+    # equivalent to a[0:6:2] = 1000;
+    # from start to position 6, exclusive, set every 2nd element to 1000
+    >>> a[:6:2] = 1000
     >>> a
-    array([-1000,     1, -1000,    27, -1000,   125,   216,   343,   512,   729])
+    array([1000,    1, 1000,   27, 1000,  125,  216,  343,  512,  729])
     >>> a[ : :-1]                                 # reversed a
-    array([  729,   512,   343,   216,   125, -1000,    27, -1000,     1, -1000])
+    array([ 729,  512,  343,  216,  125, 1000,   27, 1000,    1, 1000])
     >>> for i in a:
     ...     print(i**(1/3.))
     ...
-    nan
+    9.999999999999998
     1.0
-    nan
+    9.999999999999998
     3.0
-    nan
-    5.0
-    6.0
-    7.0
-    8.0
-    9.0
+    9.999999999999998
+    4.999999999999999
+    5.999999999999999
+    6.999999999999999
+    7.999999999999999
+    8.999999999999998
+
 
 **Multidimensional** arrays can have one index per axis. These indices
 are given in a tuple separated by commas::
@@ -614,11 +649,11 @@ Changing the shape of an array
 
 An array has a shape given by the number of elements along each axis::
 
-    >>> a = np.floor(10*np.random.random((3,4)))
+    >>> a = np.floor(10*rg.random((3,4)))
     >>> a
-    array([[ 2.,  8.,  0.,  6.],
-           [ 4.,  5.,  1.,  1.],
-           [ 8.,  9.,  3.,  6.]])
+    array([[3., 7., 3., 4.],
+           [1., 4., 2., 2.],
+           [7., 2., 4., 9.]])
     >>> a.shape
     (3, 4)
 
@@ -627,19 +662,19 @@ following three commands all return a modified array, but do not change
 the original array::
 
     >>> a.ravel()  # returns the array, flattened
-    array([ 2.,  8.,  0.,  6.,  4.,  5.,  1.,  1.,  8.,  9.,  3.,  6.])
+    array([3., 7., 3., 4., 1., 4., 2., 2., 7., 2., 4., 9.])
     >>> a.reshape(6,2)  # returns the array with a modified shape
-    array([[ 2.,  8.],
-           [ 0.,  6.],
-           [ 4.,  5.],
-           [ 1.,  1.],
-           [ 8.,  9.],
-           [ 3.,  6.]])
+    array([[3., 7.],
+           [3., 4.],
+           [1., 4.],
+           [2., 2.],
+           [7., 2.],
+           [4., 9.]])
     >>> a.T  # returns the array, transposed
-    array([[ 2.,  4.,  8.],
-           [ 8.,  5.,  9.],
-           [ 0.,  1.,  3.],
-           [ 6.,  1.,  6.]])
+    array([[3., 1., 7.],
+           [7., 4., 2.],
+           [3., 2., 4.],
+           [4., 2., 9.]])
     >>> a.T.shape
     (4, 3)
     >>> a.shape
@@ -662,21 +697,21 @@ argument with a modified shape, whereas the
 itself::
 
     >>> a
-    array([[ 2.,  8.,  0.,  6.],
-           [ 4.,  5.,  1.,  1.],
-           [ 8.,  9.,  3.,  6.]])
+    array([[3., 7., 3., 4.],
+           [1., 4., 2., 2.],
+           [7., 2., 4., 9.]])
     >>> a.resize((2,6))
     >>> a
-    array([[ 2.,  8.,  0.,  6.,  4.,  5.],
-           [ 1.,  1.,  8.,  9.,  3.,  6.]])
+    array([[3., 7., 3., 4., 1., 4.],
+           [2., 2., 7., 2., 4., 9.]])
 
 If a dimension is given as -1 in a reshaping operation, the other
 dimensions are automatically calculated::
 
     >>> a.reshape(3,-1)
-    array([[ 2.,  8.,  0.,  6.],
-           [ 4.,  5.,  1.,  1.],
-           [ 8.,  9.,  3.,  6.]])
+    array([[3., 7., 3., 4.],
+           [1., 4., 2., 2.],
+           [7., 2., 4., 9.]])
 
 .. seealso::
 
@@ -685,27 +720,30 @@ dimensions are automatically calculated::
    `resize`,
    `ravel`
 
+
+.. _quickstart.stacking-arrays:
+
 Stacking together different arrays
 ----------------------------------
 
 Several arrays can be stacked together along different axes::
 
-    >>> a = np.floor(10*np.random.random((2,2)))
+    >>> a = np.floor(10*rg.random((2,2)))
     >>> a
-    array([[ 8.,  8.],
-           [ 0.,  0.]])
-    >>> b = np.floor(10*np.random.random((2,2)))
+    array([[9., 7.],
+           [5., 2.]])
+    >>> b = np.floor(10*rg.random((2,2)))
     >>> b
-    array([[ 1.,  8.],
-           [ 0.,  4.]])
+    array([[1., 9.],
+           [5., 1.]])
     >>> np.vstack((a,b))
-    array([[ 8.,  8.],
-           [ 0.,  0.],
-           [ 1.,  8.],
-           [ 0.,  4.]])
+    array([[9., 7.],
+           [5., 2.],
+           [1., 9.],
+           [5., 1.]])
     >>> np.hstack((a,b))
-    array([[ 8.,  8.,  1.,  8.],
-           [ 0.,  0.,  0.,  4.]])
+    array([[9., 7., 1., 9.],
+           [5., 2., 5., 1.]])
 
 The function `column_stack`
 stacks 1D arrays as columns into a 2D array. It is equivalent to
@@ -713,27 +751,33 @@ stacks 1D arrays as columns into a 2D array. It is equivalent to
 
     >>> from numpy import newaxis
     >>> np.column_stack((a,b))     # with 2D arrays
-    array([[ 8.,  8.,  1.,  8.],
-           [ 0.,  0.,  0.,  4.]])
+    array([[9., 7., 1., 9.],
+           [5., 2., 5., 1.]])
     >>> a = np.array([4.,2.])
     >>> b = np.array([3.,8.])
     >>> np.column_stack((a,b))     # returns a 2D array
-    array([[ 4., 3.],
-           [ 2., 8.]])
+    array([[4., 3.],
+           [2., 8.]])
     >>> np.hstack((a,b))           # the result is different
-    array([ 4., 2., 3., 8.])
-    >>> a[:,newaxis]               # this allows to have a 2D columns vector
-    array([[ 4.],
-           [ 2.]])
+    array([4., 2., 3., 8.])
+    >>> a[:,newaxis]               # view `a` as a 2D column vector
+    array([[4.],
+           [2.]])
     >>> np.column_stack((a[:,newaxis],b[:,newaxis]))
-    array([[ 4.,  3.],
-           [ 2.,  8.]])
+    array([[4., 3.],
+           [2., 8.]])
     >>> np.hstack((a[:,newaxis],b[:,newaxis]))   # the result is the same
-    array([[ 4.,  3.],
-           [ 2.,  8.]])
+    array([[4., 3.],
+           [2., 8.]])
+
+On the other hand, the function `row_stack` is equivalent to `vstack`
+for any input arrays. In fact, `row_stack` is an alias for `vstack`::
+
+    >>> np.column_stack is np.hstack
+    False
+    >>> np.row_stack is np.vstack
+    True
 
-On the other hand, the function `ma.row_stack` is equivalent to `vstack`
-for any input arrays.
 In general, for arrays with more than two dimensions,
 `hstack` stacks along their second
 axes, `vstack` stacks along their
@@ -776,25 +820,30 @@ array along its horizontal axis, either by specifying the number of
 equally shaped arrays to return, or by specifying the columns after
 which the division should occur::
 
-    >>> a = np.floor(10*np.random.random((2,12)))
+    >>> a = np.floor(10*rg.random((2,12)))
     >>> a
-    array([[ 9.,  5.,  6.,  3.,  6.,  8.,  0.,  7.,  9.,  7.,  2.,  7.],
-           [ 1.,  4.,  9.,  2.,  2.,  1.,  0.,  6.,  2.,  2.,  4.,  0.]])
-    >>> np.hsplit(a,3)   # Split a into 3
-    [array([[ 9.,  5.,  6.,  3.],
-           [ 1.,  4.,  9.,  2.]]), array([[ 6.,  8.,  0.,  7.],
-           [ 2.,  1.,  0.,  6.]]), array([[ 9.,  7.,  2.,  7.],
-           [ 2.,  2.,  4.,  0.]])]
-    >>> np.hsplit(a,(3,4))   # Split a after the third and the fourth column
-    [array([[ 9.,  5.,  6.],
-           [ 1.,  4.,  9.]]), array([[ 3.],
-           [ 2.]]), array([[ 6.,  8.,  0.,  7.,  9.,  7.,  2.,  7.],
-           [ 2.,  1.,  0.,  6.,  2.,  2.,  4.,  0.]])]
+    array([[6., 7., 6., 9., 0., 5., 4., 0., 6., 8., 5., 2.],
+           [8., 5., 5., 7., 1., 8., 6., 7., 1., 8., 1., 0.]])
+    # Split a into 3
+    >>> np.hsplit(a,3)
+    [array([[6., 7., 6., 9.],
+           [8., 5., 5., 7.]]), array([[0., 5., 4., 0.],
+           [1., 8., 6., 7.]]), array([[6., 8., 5., 2.],
+           [1., 8., 1., 0.]])]
+    # Split a after the third and the fourth column
+    >>> np.hsplit(a,(3,4))
+    [array([[6., 7., 6.],
+           [8., 5., 5.]]), array([[9.],
+           [7.]]), array([[0., 5., 4., 0., 6., 8., 5., 2.],
+           [1., 8., 6., 7., 1., 8., 1., 0.]])]
 
 `vsplit` splits along the vertical
 axis, and `array_split` allows
 one to specify along which axis to split.
 
+
+.. _quickstart.copies-and-views:
+
 Copies and Views
 ================
 
@@ -805,17 +854,16 @@ for beginners. There are three cases:
 No Copy at All
 --------------
 
-Simple assignments make no copy of array objects or of their data.
+Simple assignments make no copy of objects or their data.
 
 ::
 
-    >>> a = np.arange(12)
+    >>> a = np.array([[ 0,  1,  2,  3],
+    ...               [ 4,  5,  6,  7],
+    ...               [ 8,  9, 10, 11]])
     >>> b = a            # no new object is created
     >>> b is a           # a and b are two names for the same ndarray object
     True
-    >>> b.shape = 3,4    # changes the shape of a
-    >>> a.shape
-    (3, 4)
 
 Python passes mutable objects as references, so function calls make no
 copy.
@@ -826,9 +874,9 @@ copy.
     ...     print(id(x))
     ...
     >>> id(a)                           # id is a unique identifier of an object
-    148293216
+    148293216  # may vary
     >>> f(a)
-    148293216
+    148293216  # may vary
 
 View or Shallow Copy
 --------------------
@@ -846,10 +894,10 @@ creates a new array object that looks at the same data.
     >>> c.flags.owndata
     False
     >>>
-    >>> c.shape = 2,6                      # a's shape doesn't change
+    >>> c = c.reshape((2, 6))                      # a's shape doesn't change
     >>> a.shape
     (3, 4)
-    >>> c[0,4] = 1234                      # a's data changes
+    >>> c[0, 4] = 1234                      # a's data changes
     >>> a
     array([[   0,    1,    2,    3],
            [1234,    5,    6,    7],
@@ -857,14 +905,13 @@ creates a new array object that looks at the same data.
 
 Slicing an array returns a view of it::
 
-    >>> s = a[ : , 1:3]     # spaces added for clarity; could also be written "s = a[:,1:3]"
-    >>> s[:] = 10           # s[:] is a view of s. Note the difference between s=10 and s[:]=10
+    >>> s = a[ : , 1:3]     # spaces added for clarity; could also be written "s = a[:, 1:3]"
+    >>> s[:] = 10           # s[:] is a view of s. Note the difference between s = 10 and s[:] = 10
     >>> a
     array([[   0,   10,   10,    3],
            [1234,   10,   10,    7],
            [   8,   10,   10,   11]])
 
-
 Deep Copy
 ---------
 
@@ -917,7 +964,7 @@ Array Creation
     `ogrid`,
     `ones`,
     `ones_like`,
-    `r`,
+    `r_`,
     `zeros`,
     `zeros_like`
 Conversions
@@ -1009,8 +1056,8 @@ element is assumed to be the same along that dimension for the
 After application of the broadcasting rules, the sizes of all arrays
 must match. More details can be found in :doc:`basics.broadcasting`.
 
-Fancy indexing and index tricks
-===============================
+Advanced indexing and index tricks
+==================================
 
 NumPy offers more indexing facilities than regular Python sequences. In
 addition to indexing by integers and slices, as we saw before, arrays
@@ -1022,11 +1069,11 @@ Indexing with Arrays of Indices
 ::
 
     >>> a = np.arange(12)**2                       # the first 12 square numbers
-    >>> i = np.array( [ 1,1,3,8,5 ] )              # an array of indices
+    >>> i = np.array([1, 1, 3, 8, 5])              # an array of indices
     >>> a[i]                                       # the elements of a at the positions i
     array([ 1,  1,  9, 64, 25])
     >>>
-    >>> j = np.array( [ [ 3, 4], [ 9, 7 ] ] )      # a bidimensional array of indices
+    >>> j = np.array([[3, 4], [9, 7]])      # a bidimensional array of indices
     >>> a[j]                                       # the same shape as j
     array([[ 9, 16],
            [81, 49]])
@@ -1038,18 +1085,19 @@ using a palette.
 
 ::
 
-    >>> palette = np.array( [ [0,0,0],                # black
-    ...                       [255,0,0],              # red
-    ...                       [0,255,0],              # green
-    ...                       [0,0,255],              # blue
-    ...                       [255,255,255] ] )       # white
-    >>> image = np.array( [ [ 0, 1, 2, 0 ],           # each value corresponds to a color in the palette
-    ...                     [ 0, 3, 4, 0 ]  ] )
-    >>> palette[image]                            # the (2,4,3) color image
+    >>> palette = np.array([[0, 0, 0],         # black
+    ...                     [255, 0, 0],       # red
+    ...                     [0, 255, 0],       # green
+    ...                     [0, 0, 255],       # blue
+    ...                     [255, 255, 255]])  # white
+    >>> image = np.array([[0, 1, 2, 0],        # each value corresponds to a color in the palette
+    ...                   [0, 3, 4, 0]])
+    >>> palette[image]                         # the (2, 4, 3) color image
     array([[[  0,   0,   0],
             [255,   0,   0],
             [  0, 255,   0],
             [  0,   0,   0]],
+    <BLANKLINE>
            [[  0,   0,   0],
             [  0,   0, 255],
             [255, 255, 255],
@@ -1065,34 +1113,37 @@ indices for each dimension must have the same shape.
     array([[ 0,  1,  2,  3],
            [ 4,  5,  6,  7],
            [ 8,  9, 10, 11]])
-    >>> i = np.array( [ [0,1],                        # indices for the first dim of a
-    ...                 [1,2] ] )
-    >>> j = np.array( [ [2,1],                        # indices for the second dim
-    ...                 [3,3] ] )
+    >>> i = np.array([[0, 1],                     # indices for the first dim of a
+    ...               [1, 2]])
+    >>> j = np.array([[2, 1],                     # indices for the second dim
+    ...               [3, 3]])
     >>>
-    >>> a[i,j]                                     # i and j must have equal shape
+    >>> a[i, j]                                   # i and j must have equal shape
     array([[ 2,  5],
            [ 7, 11]])
     >>>
-    >>> a[i,2]
+    >>> a[i, 2]
     array([[ 2,  6],
            [ 6, 10]])
     >>>
-    >>> a[:,j]                                     # i.e., a[ : , j]
+    >>> a[:, j]                                     # i.e., a[ : , j]
     array([[[ 2,  1],
             [ 3,  3]],
+    <BLANKLINE>
            [[ 6,  5],
             [ 7,  7]],
+    <BLANKLINE>
            [[10,  9],
             [11, 11]]])
 
-Naturally, we can put ``i`` and ``j`` in a sequence (say a list) and
-then do the indexing with the list.
+In Python, ``arr[i, j]`` is exactly the same as ``arr[(i, j)]``---so we can
+put ``i`` and ``j`` in a ``tuple`` and then do the indexing with that.
 
 ::
 
-    >>> l = [i,j]
-    >>> a[l]                                       # equivalent to a[i,j]
+    >>> l = (i, j)
+    # equivalent to a[i, j]
+    >>> a[l]
     array([[ 2,  5],
            [ 7, 11]])
 
@@ -1102,13 +1153,16 @@ of a.
 
 ::
 
-    >>> s = np.array( [i,j] )
-    >>> a[s]                                       # not what we want
+    >>> s = np.array([i, j])
+
+    # not what we want
+    >>> a[s]
     Traceback (most recent call last):
-      File "<stdin>", line 1, in ?
-    IndexError: index (3) out of range (0<=index<=2) in dimension 0
-    >>>
-    >>> a[tuple(s)]                                # same as a[i,j]
+      File "<stdin>", line 1, in <module>
+    IndexError: index 3 is out of bounds for axis 0 with size 3
+
+    # same as a[i, j]
+    >>> a[tuple(s)]
     array([[ 2,  5],
            [ 7, 11]])
 
@@ -1118,27 +1172,29 @@ value of time-dependent series::
     >>> time = np.linspace(20, 145, 5)                 # time scale
     >>> data = np.sin(np.arange(20)).reshape(5,4)      # 4 time-dependent series
     >>> time
-    array([  20.  ,   51.25,   82.5 ,  113.75,  145.  ])
+    array([ 20.  ,  51.25,  82.5 , 113.75, 145.  ])
     >>> data
     array([[ 0.        ,  0.84147098,  0.90929743,  0.14112001],
            [-0.7568025 , -0.95892427, -0.2794155 ,  0.6569866 ],
            [ 0.98935825,  0.41211849, -0.54402111, -0.99999021],
            [-0.53657292,  0.42016704,  0.99060736,  0.65028784],
            [-0.28790332, -0.96139749, -0.75098725,  0.14987721]])
-    >>>
-    >>> ind = data.argmax(axis=0)                  # index of the maxima for each series
+
+    # index of the maxima for each series
+    >>> ind = data.argmax(axis=0)
     >>> ind
     array([2, 0, 3, 1])
-    >>>
-    >>> time_max = time[ind]                       # times corresponding to the maxima
+
+    # times corresponding to the maxima
+    >>> time_max = time[ind]
     >>>
     >>> data_max = data[ind, range(data.shape[1])] # => data[ind[0],0], data[ind[1],1]...
-    >>>
+
     >>> time_max
-    array([  82.5 ,   20.  ,  113.75,   51.25])
+    array([ 82.5 ,  20.  , 113.75,  51.25])
     >>> data_max
-    array([ 0.98935825,  0.84147098,  0.99060736,  0.6569866 ])
-    >>>
+    array([0.98935825, 0.84147098, 0.99060736, 0.6569866 ])
+
     >>> np.all(data_max == data.max(axis=0))
     True
 
@@ -1224,7 +1280,6 @@ set <https://en.wikipedia.org/wiki/Mandelbrot_set>`__:
     ...
     ...     return divtime
     >>> plt.imshow(mandelbrot(400,400))
-    >>> plt.show()
 
 The second way of indexing with booleans is more similar to integer
 indexing; for each dimension of the array we give a 1D boolean array
@@ -1270,8 +1325,11 @@ and c::
     >>> ax,bx,cx = np.ix_(a,b,c)
     >>> ax
     array([[[2]],
+    <BLANKLINE>
            [[3]],
+    <BLANKLINE>
            [[4]],
+    <BLANKLINE>
            [[5]]])
     >>> bx
     array([[[8],
@@ -1286,12 +1344,15 @@ and c::
     array([[[42, 34, 50, 66, 26],
             [27, 22, 32, 42, 17],
             [22, 18, 26, 34, 14]],
+    <BLANKLINE>
            [[43, 35, 51, 67, 27],
             [28, 23, 33, 43, 18],
             [23, 19, 27, 35, 15]],
+    <BLANKLINE>
            [[44, 36, 52, 68, 28],
             [29, 24, 34, 44, 19],
             [24, 20, 28, 36, 16]],
+    <BLANKLINE>
            [[45, 37, 53, 69, 29],
             [30, 25, 35, 45, 20],
             [25, 21, 29, 37, 17]]])
@@ -1315,12 +1376,15 @@ and then use it as::
     array([[[15, 14, 16, 18, 13],
             [12, 11, 13, 15, 10],
             [11, 10, 12, 14,  9]],
+    <BLANKLINE>
            [[16, 15, 17, 19, 14],
             [13, 12, 14, 16, 11],
             [12, 11, 13, 15, 10]],
+    <BLANKLINE>
            [[17, 16, 18, 20, 15],
             [14, 13, 15, 17, 12],
             [13, 12, 14, 16, 11]],
+    <BLANKLINE>
            [[18, 17, 19, 21, 16],
             [15, 14, 16, 18, 13],
             [14, 13, 15, 17, 12]]])
@@ -1351,12 +1415,12 @@ See linalg.py in numpy folder for more.
     >>> import numpy as np
     >>> a = np.array([[1.0, 2.0], [3.0, 4.0]])
     >>> print(a)
-    [[ 1.  2.]
-     [ 3.  4.]]
+    [[1. 2.]
+     [3. 4.]]
 
     >>> a.transpose()
-    array([[ 1.,  3.],
-           [ 2.,  4.]])
+    array([[1., 3.],
+           [2., 4.]])
 
     >>> np.linalg.inv(a)
     array([[-2. ,  1. ],
@@ -1364,8 +1428,8 @@ See linalg.py in numpy folder for more.
 
     >>> u = np.eye(2) # unit 2x2 matrix; "eye" represents "I"
     >>> u
-    array([[ 1.,  0.],
-           [ 0.,  1.]])
+    array([[1., 0.],
+           [0., 1.]])
     >>> j = np.array([[0.0, -1.0], [1.0, 0.0]])
 
     >>> j @ j        # matrix product
@@ -1381,8 +1445,8 @@ See linalg.py in numpy folder for more.
            [ 4.]])
 
     >>> np.linalg.eig(j)
-    (array([ 0.+1.j,  0.-1.j]), array([[ 0.70710678+0.j        ,  0.70710678-0.j        ],
-           [ 0.00000000-0.70710678j,  0.00000000+0.70710678j]]))
+    (array([0.+1.j, 0.-1.j]), array([[0.70710678+0.j        , 0.70710678-0.j        ],
+           [0.        -0.70710678j, 0.        +0.70710678j]]))
 
 ::
 
@@ -1406,15 +1470,16 @@ To change the dimensions of an array, you can omit one of the sizes
 which will then be deduced automatically::
 
     >>> a = np.arange(30)
-    >>> a.shape = 2,-1,3  # -1 means "whatever is needed"
-    >>> a.shape
+    >>> b = a.reshape((2, -1, 3))  # -1 means "whatever is needed"
+    >>> b.shape
     (2, 5, 3)
-    >>> a
+    >>> b
     array([[[ 0,  1,  2],
             [ 3,  4,  5],
             [ 6,  7,  8],
             [ 9, 10, 11],
             [12, 13, 14]],
+    <BLANKLINE>
            [[15, 16, 17],
             [18, 19, 20],
             [21, 22, 23],
@@ -1431,11 +1496,15 @@ functions ``column_stack``, ``dstack``, ``hstack`` and ``vstack``,
 depending on the dimension in which the stacking is to be done. For
 example::
 
-    x = np.arange(0,10,2)                     # x=([0,2,4,6,8])
-    y = np.arange(5)                          # y=([0,1,2,3,4])
-    m = np.vstack([x,y])                      # m=([[0,2,4,6,8],
-                                              #     [0,1,2,3,4]])
-    xy = np.hstack([x,y])                     # xy =([0,2,4,6,8,0,1,2,3,4])
+    >>> x = np.arange(0,10,2)
+    >>> y = np.arange(5)
+    >>> m = np.vstack([x,y])
+    >>> m
+    array([[0, 2, 4, 6, 8],
+           [0, 1, 2, 3, 4]])
+    >>> xy = np.hstack([x,y])
+    >>> xy
+    array([0, 2, 4, 6, 8, 0, 1, 2, 3, 4])
 
 The logic behind those functions in more than two dimensions can be
 strange.
@@ -1448,7 +1517,7 @@ Histograms
 ----------
 
 The NumPy ``histogram`` function applied to an array returns a pair of
-vectors: the histogram of the array and the vector of bins. Beware:
+vectors: the histogram of the array and a vector of the bin edges. Beware:
 ``matplotlib`` also has a function to build histograms (called ``hist``,
 as in Matlab) that differs from the one in NumPy. The main difference is
 that ``pylab.hist`` plots the histogram automatically, while
@@ -1457,17 +1526,16 @@ that ``pylab.hist`` plots the histogram automatically, while
 .. plot::
 
     >>> import numpy as np
+    >>> rg = np.random.default_rng(1)
     >>> import matplotlib.pyplot as plt
     >>> # Build a vector of 10000 normal deviates with variance 0.5^2 and mean 2
     >>> mu, sigma = 2, 0.5
-    >>> v = np.random.normal(mu,sigma,10000)
+    >>> v = rg.normal(mu,sigma,10000)
     >>> # Plot a normalized histogram with 50 bins
     >>> plt.hist(v, bins=50, density=1)       # matplotlib version (plot)
-    >>> plt.show()
     >>> # Compute the histogram with numpy and then plot it
     >>> (n, bins) = np.histogram(v, bins=50, density=True)  # NumPy version (no plot)
     >>> plt.plot(.5*(bins[1:]+bins[:-1]), n)
-    >>> plt.show()
 
 
 Further reading
index f0af917513cf8327199380d7978f56182c608160..7d4846f7794f3ea0911485e2263ae679a8fb1013 100644 (file)
@@ -49,14 +49,31 @@ Using Python from ``conda`` (Anaconda)
 
 Please make sure that you have activated your conda environment.
 See also the `conda user-guide <https://docs.conda.io/projects/conda/en/latest/user-guide/tasks/manage-environments.html#activating-an-environment>`_.
+If you use an external editor/development environment it will have to be set
+up correctly.  See below for solutions for some common setups.
 
-
-Using Anaconda/conda Python within PyCharm
-------------------------------------------
+Using PyCharm with Anaconda/conda Python
+----------------------------------------
 
 There are fairly common issues when using PyCharm together with Anaconda,
 please see the `PyCharm support <https://www.jetbrains.com/help/pycharm/conda-support-creating-conda-virtual-environment.html>`_
 
+Using VSCode with Anaconda/conda Python (or environments)
+---------------------------------------------------------
+
+A commonly reported issue is related to the environment activation within
+VSCode. Please see the `VSCode support <https://code.visualstudio.com/docs/python/environments>`_
+for information on how to correctly set up VSCode with virtual environments
+or conda.
+
+Using Eclipse/PyDev with Anaconda/conda Python (or environments)
+----------------------------------------------------------------
+
+Please see the 
+`Anaconda Documentation <https://docs.anaconda.com/anaconda/user-guide/tasks/integration/eclipse-pydev/>`_
+on how to properly configure Eclipse/PyDev to use Anaconda Python with specific
+conda environments.
+
 
 Raspberry Pi
 ------------
@@ -116,10 +133,8 @@ your system. If you can open a correct python shell, you can also run the
 following in python::
 
     import os
-    PYTHONPATH = os.environ['PYTHONPATH'].split(os.pathsep)
-    print("The PYTHONPATH is:", PYTHONPATH)
-    PATH = os.environ['PATH'].split(os.pathsep)
-    print("The PATH is:", PATH)
+    print("PYTHONPATH:", os.environ.get('PYTHONPATH'))
+    print("PATH:", os.environ.get('PATH'))
 
 This may mainly help you if you are not running the python and/or NumPy
 version you are expecting to run.
diff --git a/doc/source/user/tutorial-svd.rst b/doc/source/user/tutorial-svd.rst
new file mode 100644 (file)
index 0000000..086e0a6
--- /dev/null
@@ -0,0 +1,513 @@
+================================================
+Tutorial: Linear algebra on n-dimensional arrays
+================================================
+
+.. currentmodule:: numpy
+
+.. testsetup::
+
+   import numpy as np
+   np.random.seed(1)
+
+**Prerequisites**
+
+Before reading this tutorial, you should know a bit of Python. If you
+would like to refresh your memory, take a look at the
+:doc:`Python tutorial <python:tutorial/index>`.
+
+If you want to be able to run the examples in this tutorial, you should also
+have `matplotlib <https://matplotlib.org/>`_ and `SciPy <https://scipy.org>`_
+installed on your computer.
+
+**Learner profile**
+
+This tutorial is for people who have a basic understanding of linear
+algebra and arrays in NumPy and want to understand how n-dimensional
+(:math:`n>=2`) arrays are represented and can be manipulated. In particular, if
+you don't know how to apply common functions to n-dimensional arrays (without
+using for-loops), or if you want to understand axis and shape properties for
+n-dimensional arrays, this tutorial might be of help.
+
+**Learning Objectives**
+
+After this tutorial, you should be able to:
+
+- Understand the difference between one-, two- and n-dimensional arrays in
+  NumPy;
+- Understand how to apply some linear algebra operations to n-dimensional
+  arrays without using for-loops;
+- Understand axis and shape properties for n-dimensional arrays.
+
+**Content**
+
+In this tutorial, we will use a `matrix decomposition
+<https://en.wikipedia.org/wiki/Matrix_decomposition>`_ from linear algebra, the
+Singular Value Decomposition, to generate a compressed approximation of an
+image. We'll use the ``face`` image from the `scipy.misc` module:
+
+    >>> from scipy import misc
+    >>> img = misc.face()
+
+.. note::
+
+   If you prefer, you can use your own image as you work through this tutorial.
+   In order to transform your image into a NumPy array that can be manipulated,
+   you can use the ``imread`` function from the `matplotlib.pyplot` submodule.
+   Alternatively, you can use the :func:`imageio.imread` function from the
+   ``imageio`` library. Be aware that if you use your own image, you'll likely
+   need to adapt the steps below. For more information on how images are treated
+   when converted to NumPy arrays, see :std:doc:`user_guide/numpy_images` from
+   the ``scikit-image`` documentation.
+
+Now, ``img`` is a NumPy array, as we can see when using the ``type`` function::
+
+    >>> type(img)
+    <class 'numpy.ndarray'>
+
+We can see the image using the `matplotlib.pyplot.imshow` function::
+
+    >>> import matplotlib.pyplot as plt
+    >>> plt.imshow(img)
+
+.. plot:: user/plot_face.py
+    :align: center
+    :include-source: 0
+
+.. note::
+
+   If you are executing the commands above in the IPython shell, it might be
+   necessary to use the command ``plt.show()`` to show the image window. 
+                    
+**Shape, axis and array properties**
+
+Note that, in linear algebra, the dimension of a vector refers to the number of
+entries in an array. In NumPy, it instead defines the number of axes. For
+example, a 1D array is a vector such as ``[1, 2, 3]``, a 2D array is a matrix,
+and so forth.
+
+First, let's check for the shape of the data in our array. Since this image is
+two-dimensional (the pixels in the image form a rectangle), we might expect a
+two-dimensional array to represent it (a matrix). However, using the ``shape``
+property of this NumPy array gives us a different result::
+
+    >>> img.shape
+    (768, 1024, 3)
+
+The output is a :ref:`tuple <python:tut-tuples>` with three elements, which means
+that this is a three-dimensional array. In fact, since this is a color image, and
+we have used the ``imread`` function to read it, the data is organized in three 2D
+arrays, representing color channels (in this case, red, green and blue - RGB). You
+can see this by looking at the shape above: it indicates that we have an array of
+3 matrices, each having shape 768x1024.
+
+Furthermore, using the ``ndim`` property of this array, we can see that
+
+::
+
+    >>> img.ndim
+    3
+
+NumPy refers to each dimension as an `axis`. Because of how ``imread``
+works, the *first index in the 3rd axis* is the red pixel data for our image. We
+can access this by using the syntax
+
+::
+
+    >>> img[:, :, 0]
+    array([[121, 138, 153, ..., 119, 131, 139],
+           [ 89, 110, 130, ..., 118, 134, 146],
+           [ 73,  94, 115, ..., 117, 133, 144],
+           ...,
+           [ 87,  94, 107, ..., 120, 119, 119],
+           [ 85,  95, 112, ..., 121, 120, 120],
+           [ 85,  97, 111, ..., 120, 119, 118]], dtype=uint8)
+
+From the output above, we can see that every value in ``img[:,:,0]`` is an
+integer value between 0 and 255, representing the level of red in each
+corresponding image pixel (keep in mind that this might be different if you
+use your own image instead of `scipy.misc.face`).
+
+As expected, this is a 768x1024 matrix::
+
+    >>> img[:, :, 0].shape
+    (768, 1024)
+
+Since we are going to perform linear algebra operations on this data, it might
+be more interesting to have real numbers between 0 and 1 in each entry of the
+matrices to represent the RGB values. We can do that by setting
+
+    >>> img_array = img / 255
+
+This operation, dividing an array by a scalar, works because of NumPy's
+:ref:`broadcasting rules <array-broadcasting-in-numpy>`). (Note that in
+real-world applications, it would be better to use, for example, the
+:func:`img_as_float <skimage.img_as_float>` utility function from
+``scikit-image``).
+
+You can check that the above works by doing some tests; for example, inquiring
+about maximum and minimum values for this array::
+
+    >>> img_array.max(), img_array.min()
+    (1.0, 0.0)
+
+or checking the type of data in the array::
+
+    >>> img_array.dtype
+    dtype('float64')
+
+Note that we can assign each color channel to a separate matrix using the slice
+syntax::
+
+    >>> red_array = img_array[:, :, 0]
+    >>> green_array = img_array[:, :, 1]
+    >>> blue_array = img_array[:, :, 2]
+
+**Operations on an axis**
+
+It is possible to use methods from linear algebra to approximate an existing set
+of data. Here, we will use the `SVD (Singular Value Decomposition)
+<https://en.wikipedia.org/wiki/Singular_value_decomposition>`_ to try to rebuild
+an image that uses less singular value information than the original one, while
+still retaining some of its features.
+
+.. note::
+
+    We will use NumPy's linear algebra module, `numpy.linalg`, to
+    perform the operations in this tutorial. Most of the linear algebra
+    functions in this module can also be found in `scipy.linalg`, and
+    users are encouraged to use the `scipy` module for real-world
+    applications. However, it is currently not possible to apply linear
+    algebra operations to n-dimensional arrays using the `scipy.linalg`
+    module. For more information on this, check the
+    :doc:`scipy.linalg Reference<scipy:tutorial/linalg>`.
+
+To proceed, import the linear algebra submodule from NumPy::
+
+    >>> from numpy import linalg
+
+In order to extract information from a given matrix, we can use the SVD to obtain
+3 arrays which can be multiplied to obtain the original matrix. From the theory
+of linear algebra, given a matrix :math:`A`, the following product can be
+computed:
+
+.. math::
+
+   U \Sigma V^T = A
+
+where :math:`U` and :math:`V^T` are square and :math:`\Sigma` is the same size
+as :math:`A`. :math:`\Sigma` is a diagonal matrix and contains the
+`singular values <https://en.wikipedia.org/wiki/Singular_value>`_ of :math:`A`,
+organized from largest to smallest. These values are always non-negative and can
+be used as an indicator of the "importance" of some features represented by the
+matrix :math:`A`.
+
+Let's see how this works in practice with just one matrix first. Note that
+according to `colorimetry <https://en.wikipedia.org/wiki/Grayscale#Colorimetric_(perceptual_luminance-preserving)_conversion_to_grayscale>`_,
+it is possible to obtain a fairly reasonable grayscale version of our color
+image if we apply the formula
+
+.. math::
+
+   Y = 0.2126 R + 0.7152 G + 0.0722 B
+
+where :math:`Y` is the array representing the grayscale image, and :math:`R, G`
+and :math:`B` are the red, green and blue channel arrays we had originally.
+Notice we can use the ``@`` operator (the matrix multiplication operator for
+NumPy arrays, see `numpy.matmul`) for this:
+
+::
+   
+   >>> img_gray = img_array @ [0.2126, 0.7152, 0.0722]
+
+Now, ``img_gray`` has shape
+
+::
+
+   >>> img_gray.shape
+   (768, 1024)
+
+To see if this makes sense in our image, we should use a colormap from
+``matplotlib`` corresponding to the color we wish to see in out image
+(otherwise, ``matplotlib`` will default to a colormap that does not
+correspond to the real data).
+
+In our case, we are approximating the grayscale portion of the image, so we
+will use the colormap ``gray``::
+   
+   >>> plt.imshow(img_gray, cmap="gray")
+
+.. plot:: user/plot_gray.py
+    :align: center
+    :include-source: 0
+
+Now, applying the `linalg.svd` function to this matrix, we obtain the
+following decomposition:
+::
+
+    >>> U, s, Vt = linalg.svd(img_gray)
+
+.. note::
+
+    If you are using your own image, this command might take a while to run,
+    depending on the size of your image and your hardware. Don't worry, this
+    is normal! The SVD can be a pretty intensive computation.
+   
+Let's check that this is what we expected::
+
+    >>> U.shape, s.shape, Vt.shape
+    ((768, 768), (768,), (1024, 1024))
+
+Note that ``s`` has a particular shape: it has only one dimension. This
+means that some linear algebra functions that expect 2d arrays might not work.
+For example, from the theory, one might expect ``s`` and ``Vt`` to be
+compatible for multiplication. However, this is not true as ``s`` does not
+have a second axis. Executing
+
+::
+
+    >>> s @ Vt
+    Traceback (most recent call last):
+      ...
+    ValueError: matmul: Input operand 1 has a mismatch in its core dimension 0,
+    with gufunc signature (n?,k),(k,m?)->(n?,m?) (size 1024 is different from
+    768)
+
+results in a ``ValueError``. This happens because having a one-dimensional
+array for ``s``, in this case, is much more economic in practice than building a
+diagonal matrix with the same data. To reconstruct the original matrix, we can
+rebuild the diagonal matrix :math:`\Sigma` with the elements of ``s`` in its
+diagonal and with the appropriate dimensions for multiplying: in our case,
+:math:`\Sigma` should be 768x1024 since ``U`` is 768x768 and ``Vt`` is
+1024x1024.
+
+::
+
+    >>> import numpy as np
+    >>> Sigma = np.zeros((768, 1024))
+    >>> for i in range(768):
+    ...     Sigma[i, i] = s[i]
+
+Now, we want to check if the reconstructed ``U @ Sigma @ Vt`` is
+close to the original ``img_gray`` matrix.
+
+**Approximation**
+
+The `linalg` module includes a ``norm`` function, which
+computes the norm of a vector or matrix represented in a NumPy array. For
+example, from the SVD explanation above, we would expect the norm of the
+difference between ``img_gray`` and the reconstructed SVD product to be small.
+As expected, you should see something like
+
+::
+
+    >>> linalg.norm(img_gray - U @ Sigma @ Vt)
+    1.3926466851808837e-12
+
+(The actual result of this operation might be different depending on your
+architecture and linear algebra setup. Regardless, you should see a small
+number.)
+
+We could also have used the `numpy.allclose` function to make sure the
+reconstructed product is, in fact, *close* to our original matrix (the
+difference between the two arrays is small)::
+
+    >>> np.allclose(img_gray, U @ Sigma @ Vt)
+    True
+
+To see if an approximation is reasonable, we can check the values in ``s``::
+
+    >>> plt.plot(s)
+
+.. plot:: user/plot_gray_svd.py
+    :align: center
+    :include-source: 0
+    
+In the graph, we can see that although we have 768 singular values in
+``s``, most of those (after the 150th entry or so) are pretty small. So it
+might make sense to use only the information related to the first (say, 50)
+*singular values* to build a more economical approximation to our image.
+
+The idea is to consider all but the first ``k`` singular values in
+``Sigma`` (which are the same as in ``s``) as zeros, keeping
+``U`` and ``Vt`` intact, and computing the product of these matrices
+as the approximation.
+
+For example, if we choose 
+
+::
+
+    >>> k = 10
+
+we can build the approximation by doing
+
+::
+
+    >>> approx = U @ Sigma[:, :k] @ Vt[:k, :]
+
+Note that we had to use only the first ``k`` rows of ``Vt``, since all
+other rows would be multiplied by the zeros corresponding to the singular
+values we eliminated from this approximation.
+
+::
+   
+    >>> plt.imshow(approx, cmap="gray")
+
+.. plot:: user/plot_approx.py
+    :align: center
+    :include-source: 0
+
+Now, you can go ahead and repeat this experiment with other values of `k`, and
+each of your experiments should give you a slightly better (or worse) image
+depending on the value you choose.
+
+**Applying to all colors**
+
+Now we want to do the same kind of operation, but to all three colors. Our
+first instinct might be to repeat the same operation we did above to each color
+matrix individually. However, NumPy's `broadcasting` takes care of this
+for us.
+
+If our array has more than two dimensions, then the SVD can be applied to all
+axes at once. However, the linear algebra functions in NumPy expect to see an
+array of the form ``(N, M, M)``, where the first axis represents the number
+of matrices.
+
+In our case,
+
+::
+
+    >>> img_array.shape
+    (768, 1024, 3)
+
+so we need to permutate the axis on this array to get a shape like
+``(3, 768, 1024)``. Fortunately, the `numpy.transpose` function can do that for
+us:
+
+::
+   
+   np.transpose(x, axes=(i, j, k))
+
+indicates that the axis will be reordered such that the final shape of the
+transposed array will be reordered according to the indices ``(i, j, k)``.
+
+Let's see how this goes for our array::
+
+    >>> img_array_transposed = np.transpose(img_array, (2, 0, 1))
+    >>> img_array_transposed.shape
+    (3, 768, 1024)
+
+Now we are ready to apply the SVD::
+
+    >>> U, s, Vt = linalg.svd(img_array_transposed)
+
+Finally, to obtain the full approximated image, we need to reassemble these
+matrices into the approximation. Now, note that
+
+::
+
+    >>> U.shape, s.shape, Vt.shape
+    ((3, 768, 768), (3, 768), (3, 1024, 1024))
+
+To build the final approximation matrix, we must understand how multiplication
+across different axes works.
+
+**Products with n-dimensional arrays**
+
+If you have worked before with only one- or two-dimensional arrays in NumPy,
+you might use `numpy.dot` and `numpy.matmul` (or the ``@`` operator)
+interchangeably. However, for n-dimensional arrays, they work in very different
+ways. For more details, check the documentation `numpy.matmul`.
+
+Now, to build our approximation, we first need to make sure that our singular
+values are ready for multiplication, so we build our ``Sigma`` matrix similarly
+to what we did before. The ``Sigma`` array must have dimensions
+``(3, 768, 1024)``. In order to add the singular values to the diagonal of
+``Sigma``, we will use the ``fill_diagonal`` function from NumPy, using each of
+the 3 rows in ``s`` as the diagonal for each of the 3 matrices in ``Sigma``:
+
+::
+
+    >>> Sigma = np.zeros((3, 768, 1024))
+    >>> for j in range(3):
+    ...     np.fill_diagonal(Sigma[j, :, :], s[j, :])
+
+Now, if we wish to rebuild the full SVD (with no approximation), we can do
+
+::
+
+    >>> reconstructed = U @ Sigma @ Vt
+
+Note that
+
+::
+
+    >>> reconstructed.shape
+    (3, 768, 1024)
+
+and
+
+::
+
+    >>> plt.imshow(np.transpose(reconstructed, (1, 2, 0)))
+
+.. plot:: user/plot_reconstructed.py
+    :align: center
+    :include-source: 0
+    
+should give you an image indistinguishable from the original one (although we
+may introduce floating point errors for this reconstruction). In fact, 
+you might see a warning message saying `"Clipping input data to the
+valid range for imshow with RGB data ([0..1] for floats or [0..255] for
+integers)."` This is expected from the manipulation we just did on the original
+image.
+
+Now, to do the approximation, we must choose only the first ``k`` singular
+values for each color channel. This can be done using the following syntax::
+
+    >>> approx_img = U @ Sigma[..., :k] @ Vt[..., :k, :]
+
+You can see that we have selected only the first ``k`` components of the last
+axis for ``Sigma`` (this means that we have used only the first ``k`` columns
+of each of the three matrices in the stack), and that we have selected only the
+first ``k`` components in the second-to-last axis of ``Vt`` (this means we have
+selected only the first ``k`` rows from every matrix in the stack ``Vt`` and
+all columns). If you are unfamiliar with the ellipsis syntax, it is a
+placeholder for other axes. For more details, see the documentation on
+:ref:`Indexing <basics.indexing>`.
+
+Now,
+
+::
+
+    >>> approx_img.shape
+    (3, 768, 1024)
+
+which is not the right shape for showing the image. Finally, reordering the axes 
+back to our original shape of ``(768, 1024, 3)``, we can see our approximation::
+
+    >>> plt.imshow(np.transpose(approx_img, (1, 2, 0)))
+
+.. plot:: user/plot_final.py
+    :align: center
+    :include-source: 0
+    
+Even though the image is not as sharp, using a small number of ``k`` singular
+values (compared to the original set of 768 values), we can recover many of the
+distinguishing features from this image.
+
+**Final words**
+
+Of course, this is not the best method to *approximate* an image.
+However, there is, in fact, a result in linear algebra that says that the
+approximation we built above is the best we can get to the original matrix in
+terms of the norm of the difference. For more information, see *G. H. Golub and
+C. F. Van Loan, Matrix Computations, Baltimore, MD, Johns Hopkins University
+Press, 1985*.
+
+**Further reading**
+
+-  :doc:`Python tutorial <python:tutorial/index>`
+-  :ref:`reference`
+-  :doc:`SciPy Tutorial <scipy:tutorial/index>`
+-  `SciPy Lecture Notes <https://scipy-lectures.org>`__
+-  `A matlab, R, IDL, NumPy/SciPy dictionary <http://mathesaurus.sf.net/>`__
diff --git a/doc/source/user/tutorials_index.rst b/doc/source/user/tutorials_index.rst
new file mode 100644 (file)
index 0000000..c5e859f
--- /dev/null
@@ -0,0 +1,19 @@
+.. _tutorials:
+
+################
+NumPy Tutorials
+################
+
+These documents are intended as an introductory overview of NumPy and its 
+features. For detailed reference documentation of the functions and
+classes contained in the package, see the :ref:`API reference <reference>`.
+
+.. toctree::
+   :maxdepth: 1
+
+   basics
+   misc
+   numpy-for-matlab-users
+   tutorial-svd
+   building
+   c-info
index abaa2bfedf0fa6ba9d07c11b9434c66609175d04..8478a77c4efe3faab05d0d07fc5bea769ac03bd9 100644 (file)
@@ -1,3 +1,5 @@
+.. _whatisnumpy:
+
 **************
 What is NumPy?
 **************
diff --git a/doc/summarize.py b/doc/summarize.py
deleted file mode 100755 (executable)
index cfce271..0000000
+++ /dev/null
@@ -1,177 +0,0 @@
-#!/usr/bin/env python
-"""
-summarize.py
-
-Show a summary about which NumPy functions are documented and which are not.
-
-"""
-from __future__ import division, absolute_import, print_function
-
-import os, glob, re, sys, inspect, optparse
-try:
-    # Accessing collections abstract classes from collections
-    # has been deprecated since Python 3.3
-    import collections.abc as collections_abc
-except ImportError:
-    import collections as collections_abc
-sys.path.append(os.path.join(os.path.dirname(__file__), 'sphinxext'))
-from sphinxext.phantom_import import import_phantom_module
-
-from sphinxext.autosummary_generate import get_documented
-
-CUR_DIR = os.path.dirname(__file__)
-SOURCE_DIR = os.path.join(CUR_DIR, 'source', 'reference')
-
-SKIP_LIST = """
-# --- aliases:
-alltrue sometrue bitwise_not cumproduct
-row_stack column_stack product rank
-
-# -- skipped:
-core lib f2py dual doc emath ma rec char distutils oldnumeric numarray
-testing version matlib
-
-add_docstring add_newdoc add_newdocs fastCopyAndTranspose pkgload
-conjugate disp
-
-int0 object0 unicode0 uint0 string_ string0 void0
-
-flagsobj
-
-setup PackageLoader
-
-lib.scimath.arccos lib.scimath.arcsin lib.scimath.arccosh lib.scimath.arcsinh
-lib.scimath.arctanh lib.scimath.log lib.scimath.log2 lib.scimath.log10
-lib.scimath.logn lib.scimath.power lib.scimath.sqrt
-
-# --- numpy.random:
-random random.info random.mtrand random.ranf random.sample random.random
-
-# --- numpy.fft:
-fft fft.Tester fft.bench fft.fftpack fft.fftpack_lite fft.helper
-fft.info fft.test
-
-# --- numpy.linalg:
-linalg linalg.Tester
-linalg.bench linalg.info linalg.lapack_lite linalg.linalg linalg.test
-
-# --- numpy.ctypeslib:
-ctypeslib ctypeslib.test
-
-""".split()
-
-def main():
-    p = optparse.OptionParser(__doc__)
-    p.add_option("-c", "--columns", action="store", type="int", dest="cols",
-                 default=3, help="Maximum number of columns")
-    options, args = p.parse_args()
-
-    if len(args) != 0:
-        p.error('Wrong number of arguments')
-
-    # prepare
-    fn = os.path.join(CUR_DIR, 'dump.xml')
-    if os.path.isfile(fn):
-        import_phantom_module(fn)
-
-    # check
-    documented, undocumented = check_numpy()
-
-    # report
-    in_sections = {}
-    for name, locations in documented.items():
-        for (filename, section, keyword, toctree) in locations:
-            in_sections.setdefault((filename, section, keyword), []).append(name)
-
-    print("Documented")
-    print("==========\n")
-
-    last_filename = None
-    for (filename, section, keyword), names in sorted(in_sections.items()):
-        if filename != last_filename:
-            print("--- %s\n" % filename)
-        last_filename = filename
-        print(" ** ", section)
-        print(format_in_columns(sorted(names), options.cols))
-        print("\n")
-
-    print("")
-    print("Undocumented")
-    print("============\n")
-    print(format_in_columns(sorted(undocumented.keys()), options.cols))
-
-def check_numpy():
-    documented = get_documented(glob.glob(SOURCE_DIR + '/*.rst'))
-    undocumented = {}
-
-    import numpy, numpy.fft, numpy.linalg, numpy.random
-    for mod in [numpy, numpy.fft, numpy.linalg, numpy.random,
-                numpy.ctypeslib, numpy.emath, numpy.ma]:
-        undocumented.update(get_undocumented(documented, mod, skip=SKIP_LIST))
-
-    for d in (documented, undocumented):
-        for k in d.keys():
-            if k.startswith('numpy.'):
-                d[k[6:]] = d[k]
-                del d[k]
-
-    return documented, undocumented
-
-def get_undocumented(documented, module, module_name=None, skip=[]):
-    """
-    Find out which items in NumPy are not documented.
-
-    Returns
-    -------
-    undocumented : dict of bool
-        Dictionary containing True for each documented item name
-        and False for each undocumented one.
-
-    """
-    undocumented = {}
-
-    if module_name is None:
-        module_name = module.__name__
-
-    for name in dir(module):
-        obj = getattr(module, name)
-        if name.startswith('_'): continue
-
-        full_name = '.'.join([module_name, name])
-
-        if full_name in skip: continue
-        if full_name.startswith('numpy.') and full_name[6:] in skip: continue
-        if not (inspect.ismodule(obj) or isinstance(obj, collections_abc.Callable) or inspect.isclass(obj)):
-            continue
-
-        if full_name not in documented:
-            undocumented[full_name] = True
-
-    return undocumented
-
-def format_in_columns(lst, max_columns):
-    """
-    Format a list containing strings to a string containing the items
-    in columns.
-    """
-    lst = [str(_m) for _m in lst]
-    col_len = max([len(_m) for _m in lst]) + 2
-    ncols = 80//col_len
-    if ncols > max_columns:
-        ncols = max_columns
-    if ncols <= 0:
-        ncols = 1
-
-    if len(lst) % ncols == 0:
-        nrows = len(lst)//ncols
-    else:
-        nrows = 1 + len(lst)//ncols
-
-    fmt = ' %%-%ds ' % (col_len-2)
-
-    lines = []
-    for n in range(nrows):
-        lines.append("".join([fmt % x for x in lst[n::nrows]]))
-    return "\n".join(lines)
-
-if __name__ == "__main__": main()
diff --git a/doc_requirements.txt b/doc_requirements.txt
new file mode 100644 (file)
index 0000000..52b51cd
--- /dev/null
@@ -0,0 +1,4 @@
+sphinx>=2.2.0,<3.0
+ipython
+scipy
+matplotlib
index 23bd22e3661b8f30663b6365f3ef398185a5ea87..d5c50d9bf2194a133f36f786a74367520c1f53d5 100644 (file)
@@ -254,20 +254,8 @@ cdef extern from "numpy/arrayobject.h":
             npy_intp *shape "dimensions"
             npy_intp *strides
             dtype descr  # deprecated since NumPy 1.7 !
-            PyObject* base
+            PyObject* base #  NOT PUBLIC, DO NOT USE !
 
-        # Note: This syntax (function definition in pxd files) is an
-        # experimental exception made for __getbuffer__ and __releasebuffer__
-        # -- the details of this may change.
-        def __getbuffer__(ndarray self, Py_buffer* info, int flags):
-            PyObject_GetBuffer(<object>self, info, flags);
-
-        def __releasebuffer__(ndarray self, Py_buffer* info):
-            # We should call a possible tp_bufferrelease(self, info) but no
-            # interface to that is exposed by cython or python. And currently
-            # the function is NULL in numpy, we rely on refcounting to release
-            # info when self is collected
-            pass
 
 
     ctypedef unsigned char      npy_bool
@@ -345,103 +333,107 @@ cdef extern from "numpy/arrayobject.h":
         int len
 
     int _import_array() except -1
+    # A second definition so _import_array isn't marked as used when we use it here.
+    # Do not use - subject to change any time.
+    int __pyx_import_array "_import_array"() except -1
 
     #
     # Macros from ndarrayobject.h
     #
-    bint PyArray_CHKFLAGS(ndarray m, int flags)
-    bint PyArray_IS_C_CONTIGUOUS(ndarray arr)
-    bint PyArray_IS_F_CONTIGUOUS(ndarray arr)
-    bint PyArray_ISCONTIGUOUS(ndarray m)
-    bint PyArray_ISWRITEABLE(ndarray m)
-    bint PyArray_ISALIGNED(ndarray m)
-
-    int PyArray_NDIM(ndarray)
-    bint PyArray_ISONESEGMENT(ndarray)
-    bint PyArray_ISFORTRAN(ndarray)
-    int PyArray_FORTRANIF(ndarray)
-
-    void* PyArray_DATA(ndarray)
-    char* PyArray_BYTES(ndarray)
-    npy_intp* PyArray_DIMS(ndarray)
-    npy_intp* PyArray_STRIDES(ndarray)
-    npy_intp PyArray_DIM(ndarray, size_t)
-    npy_intp PyArray_STRIDE(ndarray, size_t)
-
-    PyObject *PyArray_BASE(ndarray)  # returns borrowed reference!
-    PyArray_Descr *PyArray_DESCR(ndarray) # returns borrowed reference to dtype!
-    int PyArray_FLAGS(ndarray)
-    npy_intp PyArray_ITEMSIZE(ndarray)
-    int PyArray_TYPE(ndarray arr)
+    bint PyArray_CHKFLAGS(ndarray m, int flags) nogil
+    bint PyArray_IS_C_CONTIGUOUS(ndarray arr) nogil
+    bint PyArray_IS_F_CONTIGUOUS(ndarray arr) nogil
+    bint PyArray_ISCONTIGUOUS(ndarray m) nogil
+    bint PyArray_ISWRITEABLE(ndarray m) nogil
+    bint PyArray_ISALIGNED(ndarray m) nogil
+
+    int PyArray_NDIM(ndarray) nogil
+    bint PyArray_ISONESEGMENT(ndarray) nogil
+    bint PyArray_ISFORTRAN(ndarray) nogil
+    int PyArray_FORTRANIF(ndarray) nogil
+
+    void* PyArray_DATA(ndarray) nogil
+    char* PyArray_BYTES(ndarray) nogil
+
+    npy_intp* PyArray_DIMS(ndarray) nogil
+    npy_intp* PyArray_STRIDES(ndarray) nogil
+    npy_intp PyArray_DIM(ndarray, size_t) nogil
+    npy_intp PyArray_STRIDE(ndarray, size_t) nogil
+
+    PyObject *PyArray_BASE(ndarray) nogil  # returns borrowed reference!
+    PyArray_Descr *PyArray_DESCR(ndarray) nogil  # returns borrowed reference to dtype!
+    int PyArray_FLAGS(ndarray) nogil
+    npy_intp PyArray_ITEMSIZE(ndarray) nogil
+    int PyArray_TYPE(ndarray arr) nogil
 
     object PyArray_GETITEM(ndarray arr, void *itemptr)
     int PyArray_SETITEM(ndarray arr, void *itemptr, object obj)
 
-    bint PyTypeNum_ISBOOL(int)
-    bint PyTypeNum_ISUNSIGNED(int)
-    bint PyTypeNum_ISSIGNED(int)
-    bint PyTypeNum_ISINTEGER(int)
-    bint PyTypeNum_ISFLOAT(int)
-    bint PyTypeNum_ISNUMBER(int)
-    bint PyTypeNum_ISSTRING(int)
-    bint PyTypeNum_ISCOMPLEX(int)
-    bint PyTypeNum_ISPYTHON(int)
-    bint PyTypeNum_ISFLEXIBLE(int)
-    bint PyTypeNum_ISUSERDEF(int)
-    bint PyTypeNum_ISEXTENDED(int)
-    bint PyTypeNum_ISOBJECT(int)
-
-    bint PyDataType_ISBOOL(dtype)
-    bint PyDataType_ISUNSIGNED(dtype)
-    bint PyDataType_ISSIGNED(dtype)
-    bint PyDataType_ISINTEGER(dtype)
-    bint PyDataType_ISFLOAT(dtype)
-    bint PyDataType_ISNUMBER(dtype)
-    bint PyDataType_ISSTRING(dtype)
-    bint PyDataType_ISCOMPLEX(dtype)
-    bint PyDataType_ISPYTHON(dtype)
-    bint PyDataType_ISFLEXIBLE(dtype)
-    bint PyDataType_ISUSERDEF(dtype)
-    bint PyDataType_ISEXTENDED(dtype)
-    bint PyDataType_ISOBJECT(dtype)
-    bint PyDataType_HASFIELDS(dtype)
-    bint PyDataType_HASSUBARRAY(dtype)
-
-    bint PyArray_ISBOOL(ndarray)
-    bint PyArray_ISUNSIGNED(ndarray)
-    bint PyArray_ISSIGNED(ndarray)
-    bint PyArray_ISINTEGER(ndarray)
-    bint PyArray_ISFLOAT(ndarray)
-    bint PyArray_ISNUMBER(ndarray)
-    bint PyArray_ISSTRING(ndarray)
-    bint PyArray_ISCOMPLEX(ndarray)
-    bint PyArray_ISPYTHON(ndarray)
-    bint PyArray_ISFLEXIBLE(ndarray)
-    bint PyArray_ISUSERDEF(ndarray)
-    bint PyArray_ISEXTENDED(ndarray)
-    bint PyArray_ISOBJECT(ndarray)
-    bint PyArray_HASFIELDS(ndarray)
-
-    bint PyArray_ISVARIABLE(ndarray)
-
-    bint PyArray_SAFEALIGNEDCOPY(ndarray)
-    bint PyArray_ISNBO(char)              # works on ndarray.byteorder
-    bint PyArray_IsNativeByteOrder(char)  # works on ndarray.byteorder
-    bint PyArray_ISNOTSWAPPED(ndarray)
-    bint PyArray_ISBYTESWAPPED(ndarray)
-
-    bint PyArray_FLAGSWAP(ndarray, int)
-
-    bint PyArray_ISCARRAY(ndarray)
-    bint PyArray_ISCARRAY_RO(ndarray)
-    bint PyArray_ISFARRAY(ndarray)
-    bint PyArray_ISFARRAY_RO(ndarray)
-    bint PyArray_ISBEHAVED(ndarray)
-    bint PyArray_ISBEHAVED_RO(ndarray)
-
-
-    bint PyDataType_ISNOTSWAPPED(dtype)
-    bint PyDataType_ISBYTESWAPPED(dtype)
+    bint PyTypeNum_ISBOOL(int) nogil
+    bint PyTypeNum_ISUNSIGNED(int) nogil
+    bint PyTypeNum_ISSIGNED(int) nogil
+    bint PyTypeNum_ISINTEGER(int) nogil
+    bint PyTypeNum_ISFLOAT(int) nogil
+    bint PyTypeNum_ISNUMBER(int) nogil
+    bint PyTypeNum_ISSTRING(int) nogil
+    bint PyTypeNum_ISCOMPLEX(int) nogil
+    bint PyTypeNum_ISPYTHON(int) nogil
+    bint PyTypeNum_ISFLEXIBLE(int) nogil
+    bint PyTypeNum_ISUSERDEF(int) nogil
+    bint PyTypeNum_ISEXTENDED(int) nogil
+    bint PyTypeNum_ISOBJECT(int) nogil
+
+    bint PyDataType_ISBOOL(dtype) nogil
+    bint PyDataType_ISUNSIGNED(dtype) nogil
+    bint PyDataType_ISSIGNED(dtype) nogil
+    bint PyDataType_ISINTEGER(dtype) nogil
+    bint PyDataType_ISFLOAT(dtype) nogil
+    bint PyDataType_ISNUMBER(dtype) nogil
+    bint PyDataType_ISSTRING(dtype) nogil
+    bint PyDataType_ISCOMPLEX(dtype) nogil
+    bint PyDataType_ISPYTHON(dtype) nogil
+    bint PyDataType_ISFLEXIBLE(dtype) nogil
+    bint PyDataType_ISUSERDEF(dtype) nogil
+    bint PyDataType_ISEXTENDED(dtype) nogil
+    bint PyDataType_ISOBJECT(dtype) nogil
+    bint PyDataType_HASFIELDS(dtype) nogil
+    bint PyDataType_HASSUBARRAY(dtype) nogil
+
+    bint PyArray_ISBOOL(ndarray) nogil
+    bint PyArray_ISUNSIGNED(ndarray) nogil
+    bint PyArray_ISSIGNED(ndarray) nogil
+    bint PyArray_ISINTEGER(ndarray) nogil
+    bint PyArray_ISFLOAT(ndarray) nogil
+    bint PyArray_ISNUMBER(ndarray) nogil
+    bint PyArray_ISSTRING(ndarray) nogil
+    bint PyArray_ISCOMPLEX(ndarray) nogil
+    bint PyArray_ISPYTHON(ndarray) nogil
+    bint PyArray_ISFLEXIBLE(ndarray) nogil
+    bint PyArray_ISUSERDEF(ndarray) nogil
+    bint PyArray_ISEXTENDED(ndarray) nogil
+    bint PyArray_ISOBJECT(ndarray) nogil
+    bint PyArray_HASFIELDS(ndarray) nogil
+
+    bint PyArray_ISVARIABLE(ndarray) nogil
+
+    bint PyArray_SAFEALIGNEDCOPY(ndarray) nogil
+    bint PyArray_ISNBO(char) nogil              # works on ndarray.byteorder
+    bint PyArray_IsNativeByteOrder(char) nogil # works on ndarray.byteorder
+    bint PyArray_ISNOTSWAPPED(ndarray) nogil
+    bint PyArray_ISBYTESWAPPED(ndarray) nogil
+
+    bint PyArray_FLAGSWAP(ndarray, int) nogil
+
+    bint PyArray_ISCARRAY(ndarray) nogil
+    bint PyArray_ISCARRAY_RO(ndarray) nogil
+    bint PyArray_ISFARRAY(ndarray) nogil
+    bint PyArray_ISFARRAY_RO(ndarray) nogil
+    bint PyArray_ISBEHAVED(ndarray) nogil
+    bint PyArray_ISBEHAVED_RO(ndarray) nogil
+
+
+    bint PyDataType_ISNOTSWAPPED(dtype) nogil
+    bint PyDataType_ISBYTESWAPPED(dtype) nogil
 
     bint PyArray_DescrCheck(object)
 
@@ -461,10 +453,11 @@ cdef extern from "numpy/arrayobject.h":
     bint PyArray_IsPythonScalar(object)
     bint PyArray_IsAnyScalar(object)
     bint PyArray_CheckAnyScalar(object)
+
     ndarray PyArray_GETCONTIGUOUS(ndarray)
-    bint PyArray_SAMESHAPE(ndarray, ndarray)
-    npy_intp PyArray_SIZE(ndarray)
-    npy_intp PyArray_NBYTES(ndarray)
+    bint PyArray_SAMESHAPE(ndarray, ndarray) nogil
+    npy_intp PyArray_SIZE(ndarray) nogil
+    npy_intp PyArray_NBYTES(ndarray) nogil
 
     object PyArray_FROM_O(object)
     object PyArray_FROM_OF(object m, int flags)
@@ -477,16 +470,16 @@ cdef extern from "numpy/arrayobject.h":
     npy_intp PyArray_REFCOUNT(object)
     object PyArray_ContiguousFromAny(op, int, int min_depth, int max_depth)
     unsigned char PyArray_EquivArrTypes(ndarray a1, ndarray a2)
-    bint PyArray_EquivByteorders(int b1, int b2)
+    bint PyArray_EquivByteorders(int b1, int b2) nogil
     object PyArray_SimpleNew(int nd, npy_intp* dims, int typenum)
     object PyArray_SimpleNewFromData(int nd, npy_intp* dims, int typenum, void* data)
     #object PyArray_SimpleNewFromDescr(int nd, npy_intp* dims, dtype descr)
     object PyArray_ToScalar(void* data, ndarray arr)
 
-    void* PyArray_GETPTR1(ndarray m, npy_intp i)
-    void* PyArray_GETPTR2(ndarray m, npy_intp i, npy_intp j)
-    void* PyArray_GETPTR3(ndarray m, npy_intp i, npy_intp j, npy_intp k)
-    void* PyArray_GETPTR4(ndarray m, npy_intp i, npy_intp j, npy_intp k, npy_intp l)
+    void* PyArray_GETPTR1(ndarray m, npy_intp i) nogil
+    void* PyArray_GETPTR2(ndarray m, npy_intp i, npy_intp j) nogil
+    void* PyArray_GETPTR3(ndarray m, npy_intp i, npy_intp j, npy_intp k) nogil
+    void* PyArray_GETPTR4(ndarray m, npy_intp i, npy_intp j, npy_intp k, npy_intp l) nogil
 
     void PyArray_XDECREF_ERR(ndarray)
     # Cannot be supported due to out arg
@@ -614,7 +607,7 @@ cdef extern from "numpy/arrayobject.h":
     object PyArray_Choose (ndarray, object, ndarray, NPY_CLIPMODE)
     int PyArray_Sort (ndarray, int, NPY_SORTKIND)
     object PyArray_ArgSort (ndarray, int, NPY_SORTKIND)
-    object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE)
+    object PyArray_SearchSorted (ndarray, object, NPY_SEARCHSIDE, object)
     object PyArray_ArgMax (ndarray, int, ndarray)
     object PyArray_ArgMin (ndarray, int, ndarray)
     object PyArray_Reshape (ndarray, object)
@@ -961,7 +954,7 @@ cdef inline object get_array_base(ndarray arr):
 # Cython code.
 cdef inline int import_array() except -1:
     try:
-        _import_array()
+        __pyx_import_array()
     except Exception:
         raise ImportError("numpy.core.multiarray failed to import")
 
@@ -976,3 +969,10 @@ cdef inline int import_ufunc() except -1:
         _import_umath()
     except Exception:
         raise ImportError("numpy.core.umath failed to import")
+
+cdef extern from *:
+    # Leave a marker that the NumPy declarations came from this file
+    # See https://github.com/cython/cython/issues/3573
+    """
+    /* NumPy API declarations from "numpy/__init__.pxd" */
+    """
index 349914b2f3a776b41b99eeada73fbf24e933eadd..575e8ea3db7a15be1a784d12b78235ed26aa04a4 100644 (file)
@@ -104,8 +104,6 @@ available as array methods, i.e. ``x = np.array([1,2,3]); x.sort()``.
 Exceptions to this rule are documented.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import warnings
 
@@ -143,7 +141,8 @@ else:
     from .core import *
     from . import compat
     from . import lib
-    # FIXME: why have numpy.lib if everything is imported here??
+    # NOTE: to be revisited following future namespace cleanup.
+    # See gh-14454 and gh-15672 for discussion.
     from .lib import *
 
     from . import linalg
@@ -154,16 +153,12 @@ else:
     from . import ma
     from . import matrixlib as _mat
     from .matrixlib import *
-    from .compat import long
 
     # Make these accessible from numpy name-space
     # but not imported in from numpy import *
     # TODO[gh-6103]: Deprecate these
-    if sys.version_info[0] >= 3:
-        from builtins import bool, int, float, complex, object, str
-        unicode = str
-    else:
-        from __builtin__ import bool, int, float, complex, object, unicode, str
+    from builtins import bool, int, float, complex, object, str
+    from .compat import long, unicode
 
     from .core import round, abs, max, min
     # now that numpy modules are imported, can initialize limits
@@ -220,7 +215,7 @@ else:
                                      "{!r}".format(__name__, attr))
 
         def __dir__():
-            return list(globals().keys()) + ['Tester', 'testing']
+            return list(globals().keys() | {'Tester', 'testing'})
 
     else:
         # We don't actually use this ourselves anymore, but I'm not 100% sure that
@@ -258,3 +253,56 @@ else:
 
     _sanity_check()
     del _sanity_check
+
+    def _mac_os_check():
+        """
+        Quick Sanity check for Mac OS look for accelerate build bugs.
+        Testing numpy polyfit calls init_dgelsd(LAPACK)
+        """
+        try:
+            c = array([3., 2., 1.])
+            x = linspace(0, 2, 5)
+            y = polyval(c, x)
+            _ = polyfit(x, y, 2, cov=True)
+        except ValueError:
+            pass
+
+    import sys
+    if sys.platform == "darwin":
+        with warnings.catch_warnings(record=True) as w:
+            _mac_os_check()
+            # Throw runtime error, if the test failed Check for warning and error_message
+            error_message = ""
+            if len(w) > 0:
+                error_message = "{}: {}".format(w[-1].category.__name__, str(w[-1].message))
+                msg = (
+                    "Polyfit sanity test emitted a warning, most likely due "
+                    "to using a buggy Accelerate backend. "
+                    "If you compiled yourself, "
+                    "see site.cfg.example for information. "
+                    "Otherwise report this to the vendor "
+                    "that provided NumPy.\n{}\n".format(
+                        error_message))
+                raise RuntimeError(msg)
+    del _mac_os_check
+
+    # We usually use madvise hugepages support, but on some old kernels it
+    # is slow and thus better avoided.
+    # Specifically kernel version 4.6 had a bug fix which probably fixed this:
+    # https://github.com/torvalds/linux/commit/7cf91a98e607c2f935dbcc177d70011e95b8faff
+    import os
+    use_hugepage = os.environ.get("NUMPY_MADVISE_HUGEPAGE", None)
+    if sys.platform == "linux" and use_hugepage is None:
+        use_hugepage = 1
+        kernel_version = os.uname().release.split(".")[:2]
+        kernel_version = tuple(int(v) for v in kernel_version)
+        if kernel_version < (4, 6):
+            use_hugepage = 0
+    elif use_hugepage is None:
+        # This is not Linux, so it should not matter, just enable anyway
+        use_hugepage = 1
+    else:
+        use_hugepage = int(use_hugepage)
+
+    # Note that this will currently only make a difference on Linux
+    core.multiarray._set_madvise_hugepage(use_hugepage)
index 1d0f69b67d8fabcf0fa02faaf2574f9d917bdfe9..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-from __future__ import division, absolute_import, print_function
index 36dd7584a6e42836913150454adbeb325bb68b34..b26aa12ad9786c38f44ab91144272a07218d1f4b 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 import re
index f5c0761b5837318dfec69146de4378593f429c74..9f44c7729668b4ef4d27fa40fdf4618c1b554167 100644 (file)
@@ -15,8 +15,6 @@ That was not the case when the singleton classes were defined in the numpy
 motivated this module.
 
 """
-from __future__ import division, absolute_import, print_function
-
 __ALL__ = [
     'ModuleDeprecationWarning', 'VisibleDeprecationWarning', '_NoValue'
     ]
@@ -56,7 +54,7 @@ class VisibleDeprecationWarning(UserWarning):
 VisibleDeprecationWarning.__module__ = 'numpy'
 
 
-class _NoValueType(object):
+class _NoValueType:
     """Special keyword value.
 
     The instance of this class may be used as the default value assigned to a
index b25224c2037f8d2d02f97eb7e132ed4423cf978f..ca86aeb22a08f585f5ea908a1bc72db62bce234f 100644 (file)
@@ -15,7 +15,7 @@ Warnings filtering and other runtime settings should be dealt with in the
 whether or not that file is found as follows:
 
 * ``pytest.ini`` is present (develop mode)
-    All warnings except those explicily filtered out are raised as error.
+    All warnings except those explicitly filtered out are raised as error.
 * ``pytest.ini`` is absent (release mode)
     DeprecationWarnings and PendingDeprecationWarnings are ignored, other
     warnings are passed through.
@@ -27,8 +27,6 @@ This module is imported by every numpy subpackage, so lies at the top level to
 simplify circular import issues. For the same reason, it contains no numpy
 imports at module scope, instead importing numpy within function calls.
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import os
 
@@ -44,7 +42,7 @@ def _show_numpy_info():
     print("NumPy relaxed strides checking option:", relaxed_strides)
 
 
-class PytestTester(object):
+class PytestTester:
     """
     Pytest test runner.
 
@@ -127,13 +125,6 @@ class PytestTester(object):
         import pytest
         import warnings
 
-        #FIXME This is no longer needed? Assume it was for use in tests.
-        # cap verbosity at 3, which is equivalent to the pytest '-vv' option
-        #from . import utils
-        #verbose = min(int(verbose), 3)
-        #utils.verbose = verbose
-        #
-
         module = sys.modules[self.module_name]
         module_path = os.path.abspath(module.__path__[0])
 
@@ -162,21 +153,9 @@ class PytestTester(object):
         # When testing matrices, ignore their PendingDeprecationWarnings
         pytest_args += [
             "-W ignore:the matrix subclass is not",
+            "-W ignore:Importing from numpy.matlib is",
             ]
 
-        # Ignore python2.7 -3 warnings
-        pytest_args += [
-            r"-W ignore:sys\.exc_clear\(\) not supported in 3\.x:DeprecationWarning",
-            r"-W ignore:in 3\.x, __setslice__:DeprecationWarning",
-            r"-W ignore:in 3\.x, __getslice__:DeprecationWarning",
-            r"-W ignore:buffer\(\) not supported in 3\.x:DeprecationWarning",
-            r"-W ignore:CObject type is not supported in 3\.x:DeprecationWarning",
-            r"-W ignore:comparing unequal types not supported in 3\.x:DeprecationWarning",
-            r"-W ignore:the commands module has been removed in Python 3\.0:DeprecationWarning",
-            r"-W ignore:The 'new' module has been removed in Python 3\.0:DeprecationWarning",
-            ]
-
-
         if doctests:
             raise ValueError("Doctests not supported")
 
@@ -190,7 +169,13 @@ class PytestTester(object):
             pytest_args += ["--cov=" + module_path]
 
         if label == "fast":
-            pytest_args += ["-m", "not slow"]
+            # not importing at the top level to avoid circular import of module
+            from numpy.testing import IS_PYPY
+            if IS_PYPY:
+                pytest_args += ["-m", "not slow and not slow_pypy"]
+            else:
+                pytest_args += ["-m", "not slow"]
+
         elif label != "full":
             pytest_args += ["-m", label]
 
index 5b371f5c064ba2a2859c34347834125ae5e018ae..afee621b87264f13bf2f70cd5d115e7adc9d397a 100644 (file)
@@ -8,8 +8,6 @@ extensions, which may be included for the following reasons:
   * we may only need a small subset of the copied library/module
 
 """
-from __future__ import division, absolute_import, print_function
-
 from . import _inspect
 from . import py3k
 from ._inspect import getargspec, formatargspec
index 439d0d2c2ff7f67fd6e3ff72f3ec062024f3bcce..9a874a71dd0a53e25a671c51bfdceec850702bfe 100644 (file)
@@ -5,8 +5,6 @@ significantly contributes to numpy import times. Importing this copy has almost
 no overhead.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import types
 
 __all__ = ['getargspec', 'formatargspec']
index 90e17d6d6b994ee74271559a3e48908109d37968..fd9f8bd4217e5047caab9bf62cc8ed0d371338b0 100644 (file)
@@ -1,7 +1,7 @@
 """
 Python 3.X compatibility tools.
 
-While this file was originally intented for Python 2 -> 3 transition,
+While this file was originally intended for Python 2 -> 3 transition,
 it is now used to create a compatibility layer between different
 minor versions of Python 3.
 
@@ -18,76 +18,48 @@ __all__ = ['bytes', 'asbytes', 'isfileobj', 'getexception', 'strchar',
 
 import sys
 import os
-try:
-    from pathlib import Path, PurePath
-except ImportError:
-    Path = PurePath = None
-
-if sys.version_info[0] >= 3:
-    import io
-
-    try:
-        import pickle5 as pickle
-    except ImportError:
-        import pickle
+from pathlib import Path, PurePath
+import io
 
-    long = int
-    integer_types = (int,)
-    basestring = str
-    unicode = str
-    bytes = bytes
-
-    def asunicode(s):
-        if isinstance(s, bytes):
-            return s.decode('latin1')
-        return str(s)
-
-    def asbytes(s):
-        if isinstance(s, bytes):
-            return s
-        return str(s).encode('latin1')
+import abc
+from abc import ABC as abc_ABC
 
-    def asstr(s):
-        if isinstance(s, bytes):
-            return s.decode('latin1')
-        return str(s)
+try:
+    import pickle5 as pickle
+except ImportError:
+    import pickle
 
-    def isfileobj(f):
-        return isinstance(f, (io.FileIO, io.BufferedReader, io.BufferedWriter))
+long = int
+integer_types = (int,)
+basestring = str
+unicode = str
+bytes = bytes
 
-    def open_latin1(filename, mode='r'):
-        return open(filename, mode=mode, encoding='iso-8859-1')
+def asunicode(s):
+    if isinstance(s, bytes):
+        return s.decode('latin1')
+    return str(s)
 
-    def sixu(s):
+def asbytes(s):
+    if isinstance(s, bytes):
         return s
+    return str(s).encode('latin1')
 
-    strchar = 'U'
-
-else:
-    import cpickle as pickle
+def asstr(s):
+    if isinstance(s, bytes):
+        return s.decode('latin1')
+    return str(s)
 
-    bytes = str
-    long = long
-    basestring = basestring
-    unicode = unicode
-    integer_types = (int, long)
-    asbytes = str
-    asstr = str
-    strchar = 'S'
+def isfileobj(f):
+    return isinstance(f, (io.FileIO, io.BufferedReader, io.BufferedWriter))
 
-    def isfileobj(f):
-        return isinstance(f, file)
+def open_latin1(filename, mode='r'):
+    return open(filename, mode=mode, encoding='iso-8859-1')
 
-    def asunicode(s):
-        if isinstance(s, unicode):
-            return s
-        return str(s).decode('ascii')
+def sixu(s):
+    return s
 
-    def open_latin1(filename, mode='r'):
-        return open(filename, mode=mode)
-
-    def sixu(s):
-        return unicode(s, 'unicode_escape')
+strchar = 'U'
 
 def getexception():
     return sys.exc_info()[1]
@@ -113,7 +85,7 @@ def is_pathlib_path(obj):
     return Path is not None and isinstance(obj, Path)
 
 # from Python 3.7
-class contextlib_nullcontext(object):
+class contextlib_nullcontext:
     """Context manager that does no additional processing.
 
     Used as a stand-in for a normal context manager, when a particular
@@ -134,69 +106,30 @@ class contextlib_nullcontext(object):
         pass
 
 
-if sys.version_info[0] >= 3 and sys.version_info[1] >= 4:
-    def npy_load_module(name, fn, info=None):
-        """
-        Load a module.
-
-        .. versionadded:: 1.11.2
-
-        Parameters
-        ----------
-        name : str
-            Full module name.
-        fn : str
-            Path to module file.
-        info : tuple, optional
-            Only here for backward compatibility with Python 2.*.
-
-        Returns
-        -------
-        mod : module
-
-        """
-        import importlib.machinery
-        return importlib.machinery.SourceFileLoader(name, fn).load_module()
-else:
-    def npy_load_module(name, fn, info=None):
-        """
-        Load a module.
-
-        .. versionadded:: 1.11.2
+def npy_load_module(name, fn, info=None):
+    """
+    Load a module.
 
-        Parameters
-        ----------
-        name : str
-            Full module name.
-        fn : str
-            Path to module file.
-        info : tuple, optional
-            Information as returned by `imp.find_module`
-            (suffix, mode, type).
+    .. versionadded:: 1.11.2
 
-        Returns
-        -------
-        mod : module
+    Parameters
+    ----------
+    name : str
+        Full module name.
+    fn : str
+        Path to module file.
+    info : tuple, optional
+        Only here for backward compatibility with Python 2.*.
 
-        """
-        import imp
-        if info is None:
-            path = os.path.dirname(fn)
-            fo, fn, info = imp.find_module(name, [path])
-        else:
-            fo = open(fn, info[1])
-        try:
-            mod = imp.load_module(name, fo, fn, info)
-        finally:
-            fo.close()
-        return mod
+    Returns
+    -------
+    mod : module
 
-# backport abc.ABC
-import abc
-if sys.version_info[:2] >= (3, 4):
-    abc_ABC = abc.ABC
-else:
-    abc_ABC = abc.ABCMeta('ABC', (object,), {'__slots__': ()})
+    """
+    # Explicitly lazy import this to avoid paying the cost
+    # of importing importlib at startup
+    from importlib.machinery import SourceFileLoader
+    return SourceFileLoader(name, fn).load_module()
 
 
 # Backport os.fs_path, os.PathLike, and PurePath.__fspath__
index 882857428cdf0dcfa9a4cc386c1e0591ab7f5f91..c1b34a2cc9528b859e9f40d4eaee8eb35dbf64d6 100644 (file)
@@ -1,10 +1,8 @@
-from __future__ import division, print_function
-
 def configuration(parent_package='',top_path=None):
     from numpy.distutils.misc_util import Configuration
 
     config = Configuration('compat', parent_package, top_path)
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
     return config
 
 if __name__ == '__main__':
index 1543aafaf540cf719176858c17a5cfd9a31a4c26..2b8acbaa06626695db51c2d82e46506beaf0297a 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from os.path import join
 
 from numpy.compat import isfileobj
index 1baf4adda50775ef8ac2cff63125482ff7e7f5c3..20c8a449e9b88eeebd2580c6ecb8c9a687e728d4 100644 (file)
@@ -1,10 +1,9 @@
 """
 Pytest configuration and fixtures for the Numpy test suite.
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 
+import hypothesis
 import pytest
 import numpy
 
@@ -14,6 +13,12 @@ from numpy.core._multiarray_tests import get_fpu_mode
 _old_fpu_mode = None
 _collect_results = {}
 
+# See https://hypothesis.readthedocs.io/en/latest/settings.html
+hypothesis.settings.register_profile(
+    name="numpy-profile", deadline=None, print_blob=True,
+)
+hypothesis.settings.load_profile("numpy-profile")
+
 
 def pytest_configure(config):
     config.addinivalue_line("markers",
@@ -22,6 +27,8 @@ def pytest_configure(config):
         "leaks_references: Tests that are known to leak references.")
     config.addinivalue_line("markers",
         "slow: Tests that are very slow.")
+    config.addinivalue_line("markers",
+        "slow_pypy: Tests that are very slow on pypy.")
 
 
 def pytest_addoption(parser):
index 1efa907c211fe8940421e190630dad5b028d8170..c77885954ef122200acc46b5927e85d60441bdd3 100644 (file)
@@ -6,8 +6,6 @@ are available in the main ``numpy`` namespace - use that instead.
 
 """
 
-from __future__ import division, absolute_import, print_function
-
 from numpy.version import version as __version__
 
 import os
@@ -133,16 +131,11 @@ def _ufunc_reduce(func):
     return _ufunc_reconstruct, (whichmodule(func, name), name)
 
 
-import sys
-if sys.version_info[0] >= 3:
-    import copyreg
-else:
-    import copy_reg as copyreg
+import copyreg
 
 copyreg.pickle(ufunc, _ufunc_reduce, _ufunc_reconstruct)
 # Unclutter namespace (must keep _ufunc_reconstruct for unpickling)
 del copyreg
-del sys
 del _ufunc_reduce
 
 from numpy._pytesttester import PytestTester
index 2f12739040bb1c8852adfb7b3e2c194c6cac9ba3..f43b77c44c08a7c0ce0a764b7066320a2e1ea7f5 100644 (file)
@@ -8,9 +8,6 @@ NOTE: Many of the methods of ndarray have corresponding functions.
       core/fromnumeric.py, core/defmatrix.py up-to-date.
 
 """
-from __future__ import division, absolute_import, print_function
-
-import sys
 
 from numpy.core import numerictypes as _numerictypes
 from numpy.core import dtype
@@ -155,6 +152,8 @@ add_newdoc('numpy.core', 'flatiter', ('copy',
 
 add_newdoc('numpy.core', 'nditer',
     """
+    nditer(op, flags=None, op_flags=None, op_dtypes=None, order='K', casting='safe', op_axes=None, itershape=None, buffersize=0)
+
     Efficient multi-dimensional iterator object to iterate over arrays.
     To get started using this object, see the
     :ref:`introductory guide to array iteration <arrays.nditer>`.
@@ -787,7 +786,7 @@ add_newdoc('numpy.core', 'broadcast', ('reset',
 
 add_newdoc('numpy.core.multiarray', 'array',
     """
-    array(object, dtype=None, copy=True, order='K', subok=False, ndmin=0)
+    array(object, dtype=None, *, copy=True, order='K', subok=False, ndmin=0)
 
     Create an array.
 
@@ -1036,7 +1035,7 @@ add_newdoc('numpy.core.multiarray', 'fromstring',
         A string containing the data.
     dtype : data-type, optional
         The data type of the array; default: float.  For binary input data,
-        the data must be in exactly this format. Most builtin numeric types are 
+        the data must be in exactly this format. Most builtin numeric types are
         supported and extension types may be supported.
 
         .. versionadded:: 1.18.0
@@ -1486,59 +1485,6 @@ add_newdoc('numpy.core.multiarray', 'promote_types',
 
     """)
 
-if sys.version_info.major < 3:
-    add_newdoc('numpy.core.multiarray', 'newbuffer',
-        """
-        newbuffer(size)
-
-        Return a new uninitialized buffer object.
-
-        Parameters
-        ----------
-        size : int
-            Size in bytes of returned buffer object.
-
-        Returns
-        -------
-        newbuffer : buffer object
-            Returned, uninitialized buffer object of `size` bytes.
-
-        """)
-
-    add_newdoc('numpy.core.multiarray', 'getbuffer',
-        """
-        getbuffer(obj [,offset[, size]])
-
-        Create a buffer object from the given object referencing a slice of
-        length size starting at offset.
-
-        Default is the entire buffer. A read-write buffer is attempted followed
-        by a read-only buffer.
-
-        Parameters
-        ----------
-        obj : object
-
-        offset : int, optional
-
-        size : int, optional
-
-        Returns
-        -------
-        buffer_obj : buffer
-
-        Examples
-        --------
-        >>> buf = np.getbuffer(np.ones(5), 1, 3)
-        >>> len(buf)
-        3
-        >>> buf[0]
-        '\\x00'
-        >>> buf
-        <read-write buffer for 0x8af1e70, size 3, offset 1 at 0x8ba4ec0>
-
-        """)
-
 add_newdoc('numpy.core.multiarray', 'c_einsum',
     """
     c_einsum(subscripts, *operands, out=None, dtype=None, order='K',
@@ -2081,25 +2027,22 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('ctypes',
     Examples
     --------
     >>> import ctypes
+    >>> x = np.array([[0, 1], [2, 3]], dtype=np.int32)
     >>> x
     array([[0, 1],
-           [2, 3]])
+           [2, 3]], dtype=int32)
     >>> x.ctypes.data
-    30439712
-    >>> x.ctypes.data_as(ctypes.POINTER(ctypes.c_long))
-    <ctypes.LP_c_long object at 0x01F01300>
-    >>> x.ctypes.data_as(ctypes.POINTER(ctypes.c_long)).contents
-    c_long(0)
-    >>> x.ctypes.data_as(ctypes.POINTER(ctypes.c_longlong)).contents
-    c_longlong(4294967296L)
+    31962608 # may vary
+    >>> x.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32))
+    <__main__.LP_c_uint object at 0x7ff2fc1fc200> # may vary
+    >>> x.ctypes.data_as(ctypes.POINTER(ctypes.c_uint32)).contents
+    c_uint(0)
+    >>> x.ctypes.data_as(ctypes.POINTER(ctypes.c_uint64)).contents
+    c_ulong(4294967296)
     >>> x.ctypes.shape
-    <numpy.core._internal.c_long_Array_2 object at 0x01FFD580>
-    >>> x.ctypes.shape_as(ctypes.c_long)
-    <numpy.core._internal.c_long_Array_2 object at 0x01FCE620>
+    <numpy.core._internal.c_long_Array_2 object at 0x7ff2fc1fce60> # may vary
     >>> x.ctypes.strides
-    <numpy.core._internal.c_long_Array_2 object at 0x01FCE620>
-    >>> x.ctypes.strides_as(ctypes.c_longlong)
-    <numpy.core._internal.c_longlong_Array_2 object at 0x01F01300>
+    <numpy.core._internal.c_long_Array_2 object at 0x7ff2fc1ff320> # may vary
 
     """))
 
@@ -2373,7 +2316,8 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('shape',
     >>> np.zeros((4,2))[::2].shape = (-1,)
     Traceback (most recent call last):
       File "<stdin>", line 1, in <module>
-    AttributeError: incompatible shape for a non-contiguous array
+    AttributeError: Incompatible shape for in-place modification. Use
+    `.reshape()` to make a copy with the desired shape.
 
     See Also
     --------
@@ -2507,7 +2451,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('T',
 
 
 add_newdoc('numpy.core.multiarray', 'ndarray', ('__array__',
-    """ a.__array__(|dtype) -> reference if type unchanged, copy otherwise.
+    """ a.__array__([dtype], /) -> reference if type unchanged, copy otherwise.
 
     Returns either a new reference to self if dtype is not given or a new array
     of provided data type if dtype is different from the current dtype of the
@@ -3953,7 +3897,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('tolist',
 
     Examples
     --------
-    For a 1D array, ``a.tolist()`` is almost the same as ``list(a)``, 
+    For a 1D array, ``a.tolist()`` is almost the same as ``list(a)``,
     except that ``tolist`` changes numpy scalars to Python scalars:
 
     >>> a = np.uint32([1, 2])
@@ -3988,8 +3932,8 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('tolist',
     """))
 
 
-tobytesdoc = """
-    a.{name}(order='C')
+add_newdoc('numpy.core.multiarray', 'ndarray', ('tobytes', """
+    a.tobytes(order='C')
 
     Construct Python bytes containing the raw data bytes in the array.
 
@@ -3999,11 +3943,11 @@ tobytesdoc = """
     unless the F_CONTIGUOUS flag in the array is set, in which case it
     means 'Fortran' order.
 
-    {deprecated}
+    .. versionadded:: 1.9.0
 
     Parameters
     ----------
-    order : {{'C', 'F', None}}, optional
+    order : {'C', 'F', None}, optional
         Order of the data for multidimensional arrays:
         C, Fortran, or the same as for the original array.
 
@@ -4022,18 +3966,19 @@ tobytesdoc = """
     >>> x.tobytes('F')
     b'\\x00\\x00\\x02\\x00\\x01\\x00\\x03\\x00'
 
-    """
+    """))
+
+
+add_newdoc('numpy.core.multiarray', 'ndarray', ('tostring', r"""
+    a.tostring(order='C')
+
+    A compatibility alias for `tobytes`, with exactly the same behavior.
+
+    Despite its name, it returns `bytes` not `str`\ s.
+
+    .. deprecated:: 1.19.0
+    """))
 
-add_newdoc('numpy.core.multiarray', 'ndarray',
-           ('tostring', tobytesdoc.format(name='tostring',
-                                          deprecated=
-                                          'This function is a compatibility '
-                                          'alias for tobytes. Despite its '
-                                          'name it returns bytes not '
-                                          'strings.')))
-add_newdoc('numpy.core.multiarray', 'ndarray',
-           ('tobytes', tobytesdoc.format(name='tobytes',
-                                         deprecated='.. versionadded:: 1.9.0')))
 
 add_newdoc('numpy.core.multiarray', 'ndarray', ('trace',
     """
@@ -4124,21 +4069,26 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('var',
 
 add_newdoc('numpy.core.multiarray', 'ndarray', ('view',
     """
-    a.view(dtype=None, type=None)
+    a.view([dtype][, type])
 
     New view of array with the same data.
 
+    .. note::
+        Passing None for ``dtype`` is different from omitting the parameter,
+        since the former invokes ``dtype(None)`` which is an alias for
+        ``dtype('float_')``.
+
     Parameters
     ----------
     dtype : data-type or ndarray sub-class, optional
-        Data-type descriptor of the returned view, e.g., float32 or int16. The
-        default, None, results in the view having the same data-type as `a`.
+        Data-type descriptor of the returned view, e.g., float32 or int16.
+        Omitting it results in the view having the same data-type as `a`.
         This argument can also be specified as an ndarray sub-class, which
         then specifies the type of the returned object (this is equivalent to
         setting the ``type`` parameter).
     type : Python type, optional
-        Type of the returned view, e.g., ndarray or matrix.  Again, the
-        default None results in type preservation.
+        Type of the returned view, e.g., ndarray or matrix.  Again, omission
+        of the parameter results in type preservation.
 
     Notes
     -----
@@ -4230,7 +4180,7 @@ add_newdoc('numpy.core.multiarray', 'ndarray', ('view',
 
 add_newdoc('numpy.core.umath', 'frompyfunc',
     """
-    frompyfunc(func, nin, nout)
+    frompyfunc(func, nin, nout, *[, identity])
 
     Takes an arbitrary Python function and returns a NumPy ufunc.
 
@@ -4245,6 +4195,13 @@ add_newdoc('numpy.core.umath', 'frompyfunc',
         The number of input arguments.
     nout : int
         The number of objects returned by `func`.
+    identity : object, optional
+        The value to use for the `~numpy.ufunc.identity` attribute of the resulting
+        object. If specified, this is equivalent to setting the underlying
+        C ``identity`` field to ``PyUFunc_IdentityValue``.
+        If omitted, the identity is set to ``PyUFunc_None``. Note that this is
+        _not_ equivalent to setting the identity to ``None``, which implies the
+        operation is reorderable.
 
     Returns
     -------
@@ -4437,6 +4394,14 @@ add_newdoc('numpy.core.umath', '_add_newdoc_ufunc',
     and then throwing away the ufunc.
     """)
 
+add_newdoc('numpy.core.multiarray', '_set_madvise_hugepage',
+    """
+    _set_madvise_hugepage(enabled: bool) -> bool
+
+    Set  or unset use of ``madvise (2)`` MADV_HUGEPAGE support when
+    allocating the array data. Returns the previously set value.
+    See `global_state` for more information.
+    """)
 
 add_newdoc('numpy.core._multiarray_tests', 'format_float_OSprintf_g',
     """
@@ -5044,7 +5009,7 @@ add_newdoc('numpy.core', 'ufunc', ('reduceat',
     """))
 
 add_newdoc('numpy.core', 'ufunc', ('outer',
-    """
+    r"""
     outer(A, B, **kwargs)
 
     Apply the ufunc `op` to all pairs (a, b) with a in `A` and b in `B`.
@@ -5078,7 +5043,13 @@ add_newdoc('numpy.core', 'ufunc', ('outer',
 
     See Also
     --------
-    numpy.outer
+    numpy.outer : A less powerful version of ``np.multiply.outer``
+                  that `ravel`\ s all inputs to 1D. This exists
+                  primarily for compatibility with old code.
+
+    tensordot : ``np.tensordot(a, b, axes=((), ()))`` and
+                ``np.multiply.outer(a, b)`` behave same for all
+                dimensions of a and b.
 
     Examples
     --------
@@ -6871,4 +6842,3 @@ for float_name in ('half', 'single', 'double', 'longdouble'):
         >>> np.{ftype}(-.25).as_integer_ratio()
         (-1, 4)
         """.format(ftype=float_name)))
-
index 0ad4161f4e7587d4864c944e0bb565defbda7bfe..df569f22d97aa03903db18ea7e034df82c82ec0e 100644 (file)
@@ -3,8 +3,6 @@ Functions in the ``as*array`` family that promote array-likes into arrays.
 
 `require` fits this category despite its name not matching this pattern.
 """
-from __future__ import division, absolute_import, print_function
-
 from .overrides import set_module
 from .multiarray import array
 
index df1ff180eb4622201ae1e2120e7b344c5c5673ee..6b0ec59039a82ebd71da017f6de36c1811acba56 100644 (file)
@@ -3,10 +3,6 @@ A place for code to be called from the implementation of np.dtype
 
 String handling is much easier to do correctly in python.
 """
-from __future__ import division, absolute_import, print_function
-
-import sys
-
 import numpy as np
 
 
@@ -19,18 +15,10 @@ _kind_to_stem = {
     'V': 'void',
     'O': 'object',
     'M': 'datetime',
-    'm': 'timedelta'
+    'm': 'timedelta',
+    'S': 'bytes',
+    'U': 'str',
 }
-if sys.version_info[0] >= 3:
-    _kind_to_stem.update({
-        'S': 'bytes',
-        'U': 'str'
-    })
-else:
-    _kind_to_stem.update({
-        'S': 'string',
-        'U': 'unicode'
-    })
 
 
 def _kind_name(dtype):
index 70824128944534526204391ced4ec1a878464e69..6d7cbb244215e03b4140a679b76be46f8e724ea5 100644 (file)
@@ -22,9 +22,10 @@ Unfortunately, this fails because:
 * PEP3118 cannot represent unions, but both numpy and ctypes can
 * ctypes cannot handle big-endian structs with PEP3118 (bpo-32780)
 """
-import _ctypes
-import ctypes
 
+# We delay-import ctypes for distributions that do not include it.
+# While this module is not used unless the user passes in ctypes
+# members, it is eagerly imported from numpy/core/__init__.py.
 import numpy as np
 
 
@@ -39,6 +40,7 @@ def _from_ctypes_structure(t):
                 "ctypes bitfields have no dtype equivalent")
 
     if hasattr(t, "_pack_"):
+        import ctypes
         formats = []
         offsets = []
         names = []
@@ -79,6 +81,7 @@ def _from_ctypes_scalar(t):
 
 
 def _from_ctypes_union(t):
+    import ctypes
     formats = []
     offsets = []
     names = []
@@ -98,6 +101,7 @@ def dtype_from_ctypes_type(t):
     """
     Construct a dtype object from a ctypes type
     """
+    import _ctypes
     if issubclass(t, _ctypes.Array):
         return _from_ctypes_array(t)
     elif issubclass(t, _ctypes._Pointer):
index 88a45561f6192db21197ebefda8afb1223735424..99172e23d9165496958f3fae690d6ef5a75fb47c 100644 (file)
@@ -157,7 +157,6 @@ class _ArrayMemoryError(MemoryError):
     @staticmethod
     def _size_to_string(num_bytes):
         """ Convert a number of bytes into a binary size string """
-        import math
 
         # https://en.wikipedia.org/wiki/Binary_prefix
         LOG2_STEP = 10
index 05e401e0bbef76a6529303afa354e4ce735f107b..1378497bb4130551f5119b49be36da073677876d 100644 (file)
@@ -4,13 +4,11 @@ A place for internal code
 Some things are more easily handled Python.
 
 """
-from __future__ import division, absolute_import, print_function
-
+import ast
 import re
 import sys
 import platform
 
-from numpy.compat import unicode
 from .multiarray import dtype, array, ndarray
 try:
     import ctypes
@@ -20,9 +18,9 @@ except ImportError:
 IS_PYPY = platform.python_implementation() == 'PyPy'
 
 if (sys.byteorder == 'little'):
-    _nbo = b'<'
+    _nbo = '<'
 else:
-    _nbo = b'>'
+    _nbo = '>'
 
 def _makenames_list(adict, align):
     allfields = []
@@ -145,16 +143,16 @@ def _reconstruct(subtype, shape, dtype):
 
 # format_re was originally from numarray by J. Todd Miller
 
-format_re = re.compile(br'(?P<order1>[<>|=]?)'
-                       br'(?P<repeats> *[(]?[ ,0-9]*[)]? *)'
-                       br'(?P<order2>[<>|=]?)'
-                       br'(?P<dtype>[A-Za-z0-9.?]*(?:\[[a-zA-Z0-9,.]+\])?)')
-sep_re = re.compile(br'\s*,\s*')
-space_re = re.compile(br'\s+$')
+format_re = re.compile(r'(?P<order1>[<>|=]?)'
+                       r'(?P<repeats> *[(]?[ ,0-9]*[)]? *)'
+                       r'(?P<order2>[<>|=]?)'
+                       r'(?P<dtype>[A-Za-z0-9.?]*(?:\[[a-zA-Z0-9,.]+\])?)')
+sep_re = re.compile(r'\s*,\s*')
+space_re = re.compile(r'\s+$')
 
 # astr is a string (perhaps comma separated)
 
-_convorder = {b'=': _nbo}
+_convorder = {'=': _nbo}
 
 def _commastring(astr):
     startindex = 0
@@ -179,9 +177,9 @@ def _commastring(astr):
                         (len(result)+1, astr))
                 startindex = mo.end()
 
-        if order2 == b'':
+        if order2 == '':
             order = order1
-        elif order1 == b'':
+        elif order1 == '':
             order = order2
         else:
             order1 = _convorder.get(order1, order1)
@@ -192,18 +190,18 @@ def _commastring(astr):
                     (order1, order2))
             order = order1
 
-        if order in [b'|', b'=', _nbo]:
-            order = b''
+        if order in ['|', '=', _nbo]:
+            order = ''
         dtype = order + dtype
-        if (repeats == b''):
+        if (repeats == ''):
             newitem = dtype
         else:
-            newitem = (dtype, eval(repeats))
+            newitem = (dtype, ast.literal_eval(repeats))
         result.append(newitem)
 
     return result
 
-class dummy_ctype(object):
+class dummy_ctype:
     def __init__(self, cls):
         self._cls = cls
     def __mul__(self, other):
@@ -238,16 +236,16 @@ _getintp_ctype.cache = None
 
 # Used for .ctypes attribute of ndarray
 
-class _missing_ctypes(object):
+class _missing_ctypes:
     def cast(self, num, obj):
         return num.value
 
-    class c_void_p(object):
+    class c_void_p:
         def __init__(self, ptr):
             self.value = ptr
 
 
-class _ctypes(object):
+class _ctypes:
     def __init__(self, array, ptr=None):
         self._arr = array
 
@@ -366,7 +364,7 @@ def _newnames(datatype, order):
     """
     oldnames = datatype.names
     nameslist = list(oldnames)
-    if isinstance(order, (str, unicode)):
+    if isinstance(order, str):
         order = [order]
     seen = set()
     if isinstance(order, (list, tuple)):
@@ -523,7 +521,7 @@ _pep3118_unsupported_map = {
     'X': 'function pointers',
 }
 
-class _Stream(object):
+class _Stream:
     def __init__(self, s):
         self.s = s
         self.byteorder = '@'
@@ -557,7 +555,6 @@ class _Stream(object):
 
     def __bool__(self):
         return bool(self.s)
-    __nonzero__ = __bool__
 
 
 def _dtype_from_pep3118(spec):
@@ -840,12 +837,12 @@ def npy_ctypes_check(cls):
             # # (..., _ctypes._CData, object)
             ctype_base = cls.__mro__[-2]
         # right now, they're part of the _ctypes module
-        return 'ctypes' in ctype_base.__module__
+        return '_ctypes' in ctype_base.__module__
     except Exception:
         return False
 
 
-class recursive(object):
+class recursive:
     '''
     A decorator class for recursive nested functions.
     Naive recursive nested functions hold a reference to themselves:
index 269e509b860ec175acdf27e723b5210497acee62..86ddf4d17d69d6bc7b6182449d095e5aa9ba6122 100644 (file)
@@ -3,8 +3,6 @@ Array methods which are called by both the C-code for the method
 and the Python code for the NumPy-namespace function
 
 """
-from __future__ import division, absolute_import, print_function
-
 import warnings
 
 from numpy.core import multiarray as mu
@@ -23,6 +21,17 @@ umr_prod = um.multiply.reduce
 umr_any = um.logical_or.reduce
 umr_all = um.logical_and.reduce
 
+# Complex types to -> (2,)float view for fast-path computation in _var()
+_complex_to_float = {
+    nt.dtype(nt.csingle) : nt.dtype(nt.single),
+    nt.dtype(nt.cdouble) : nt.dtype(nt.double),
+}
+# Special case for windows: ensure double takes precedence
+if nt.dtype(nt.longdouble) != nt.dtype(nt.double):
+    _complex_to_float.update({
+        nt.dtype(nt.clongdouble) : nt.dtype(nt.longdouble),
+    })
+
 # avoid keyword arguments to speed up parsing, saves about 15%-20% for very
 # small reductions
 def _amax(a, axis=None, out=None, keepdims=False,
@@ -54,7 +63,7 @@ def _count_reduce_items(arr, axis):
         axis = (axis,)
     items = 1
     for ax in axis:
-        items *= arr.shape[ax]
+        items *= arr.shape[mu.normalize_axis_index(ax, arr.ndim)]
     return items
 
 # Numpy 1.17.0, 2019-02-24
@@ -191,8 +200,16 @@ def _var(a, axis=None, dtype=None, out=None, ddof=0, keepdims=False):
     # Note that x may not be inexact and that we need it to be an array,
     # not a scalar.
     x = asanyarray(arr - arrmean)
+
     if issubclass(arr.dtype.type, (nt.floating, nt.integer)):
         x = um.multiply(x, x, out=x)
+    # Fast-paths for built-in complex types
+    elif x.dtype in _complex_to_float:
+        xv = x.view(dtype=(_complex_to_float[x.dtype], (2,)))
+        um.multiply(xv, xv, out=xv)
+        x = um.add(xv[..., 0], xv[..., 1], out=x.real).real
+    # Most general case; includes handling object arrays containing imaginary
+    # numbers and complex types with non-native byteorder
     else:
         x = um.multiply(x, um.conjugate(x), out=x).real
 
index d6e1a1fb732c3f37c34761163402fa1a5f978273..c264314433d795c1b82242172395c27f28524f1f 100644 (file)
@@ -23,7 +23,6 @@ and sometimes other mappings too.
 
 """
 import warnings
-import sys
 
 from numpy.compat import unicode
 from numpy._globals import VisibleDeprecationWarning
@@ -203,22 +202,16 @@ def _set_up_aliases():
                   ('bool_', 'bool'),
                   ('bytes_', 'string'),
                   ('string_', 'string'),
+                  ('str_', 'unicode'),
                   ('unicode_', 'unicode'),
                   ('object_', 'object')]
-    if sys.version_info[0] >= 3:
-        type_pairs.extend([('str_', 'unicode')])
-    else:
-        type_pairs.extend([('str_', 'string')])
     for alias, t in type_pairs:
         allTypes[alias] = allTypes[t]
         sctypeDict[alias] = sctypeDict[t]
     # Remove aliases overriding python types and modules
     to_remove = ['ulong', 'object', 'int', 'float',
-                 'complex', 'bool', 'string', 'datetime', 'timedelta']
-    if sys.version_info[0] >= 3:
-        to_remove.extend(['bytes', 'str'])
-    else:
-        to_remove.extend(['unicode', 'long'])
+                 'complex', 'bool', 'string', 'datetime', 'timedelta',
+                 'bytes', 'str']
 
     for t in to_remove:
         try:
@@ -267,11 +260,8 @@ _set_array_types()
 
 
 # Add additional strings to the sctypeDict
-_toadd = ['int', 'float', 'complex', 'bool', 'object']
-if sys.version_info[0] >= 3:
-    _toadd.extend(['str', 'bytes', ('a', 'bytes_')])
-else:
-    _toadd.extend(['string', ('str', 'string_'), 'unicode', ('a', 'string_')])
+_toadd = ['int', 'float', 'complex', 'bool', 'object',
+          'str', 'bytes', ('a', 'bytes_')]
 
 for name in _toadd:
     if isinstance(name, tuple):
index c3951cc098b5a05d8a8663db2ee751bbaad4d445..454d911cf575fed300b3985601769a17d430e64c 100644 (file)
@@ -3,14 +3,7 @@ Functions for changing global ufunc configuration
 
 This provides helpers which wrap `umath.geterrobj` and `umath.seterrobj`
 """
-from __future__ import division, absolute_import, print_function
-
-try:
-    # Accessing collections abstract classes from collections
-    # has been deprecated since Python 3.3
-    import collections.abc as collections_abc
-except ImportError:
-    import collections as collections_abc
+import collections.abc
 import contextlib
 
 from .overrides import set_module
@@ -290,7 +283,7 @@ def seterrcall(func):
 
     Log error message:
 
-    >>> class Log(object):
+    >>> class Log:
     ...     def write(self, msg):
     ...         print("LOG: %s" % msg)
     ...
@@ -309,8 +302,9 @@ def seterrcall(func):
     OrderedDict([('divide', 'log'), ('invalid', 'log'), ('over', 'log'), ('under', 'log')])
 
     """
-    if func is not None and not isinstance(func, collections_abc.Callable):
-        if not hasattr(func, 'write') or not isinstance(func.write, collections_abc.Callable):
+    if func is not None and not isinstance(func, collections.abc.Callable):
+        if (not hasattr(func, 'write') or
+                not isinstance(func.write, collections.abc.Callable)):
             raise ValueError("Only callable can be used as callback")
     pyvals = umath.geterrobj()
     old = geterrcall()
@@ -365,7 +359,7 @@ def geterrcall():
     return umath.geterrobj()[2]
 
 
-class _unspecified(object):
+class _unspecified:
     pass
 
 
@@ -431,11 +425,9 @@ class errstate(contextlib.ContextDecorator):
     OrderedDict([('divide', 'ignore'), ('invalid', 'ignore'), ('over', 'ignore'), ('under', 'ignore')])
 
     """
-    # Note that we don't want to run the above doctests because they will fail
-    # without a from __future__ import with_statement
 
-    def __init__(self, **kwargs):
-        self.call = kwargs.pop('call', _Unspecified)
+    def __init__(self, *, call=_Unspecified, **kwargs):
+        self.call = call
         self.kwargs = kwargs
 
     def __enter__(self):
index 4010180150c443584404def0b152fea78eb1a311..456ef76f005b988e08e8bb663d391f8724182037 100644 (file)
@@ -3,8 +3,6 @@
 $Id: arrayprint.py,v 1.9 2005/09/13 13:58:44 teoliphant Exp $
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ["array2string", "array_str", "array_repr", "set_string_function",
            "set_printoptions", "get_printoptions", "printoptions",
            "format_float_positional", "format_float_scientific"]
@@ -24,28 +22,21 @@ __docformat__ = 'restructuredtext'
 # scalars are printed inside an ndarray. Only the latter strs are currently
 # user-customizable.
 
-import sys
 import functools
 import numbers
-if sys.version_info[0] >= 3:
-    try:
-        from _thread import get_ident
-    except ImportError:
-        from _dummy_thread import get_ident
-else:
-    try:
-        from thread import get_ident
-    except ImportError:
-        from dummy_thread import get_ident
+try:
+    from _thread import get_ident
+except ImportError:
+    from _dummy_thread import get_ident
 
 import numpy as np
 from . import numerictypes as _nt
-from .umath import absolute, not_equal, isnan, isinf, isfinite, isnat
+from .umath import absolute, isinf, isfinite, isnat
 from . import multiarray
 from .multiarray import (array, dragon4_positional, dragon4_scientific,
                          datetime_as_string, datetime_data, ndarray,
                          set_legacy_print_mode)
-from .fromnumeric import ravel, any
+from .fromnumeric import any
 from .numeric import concatenate, asarray, errstate
 from .numerictypes import (longlong, intc, int_, float_, complex_, bool_,
                            flexible)
@@ -100,7 +91,7 @@ def _make_options_dict(precision=None, threshold=None, edgeitems=None,
 @set_module('numpy')
 def set_printoptions(precision=None, threshold=None, edgeitems=None,
                      linewidth=None, suppress=None, nanstr=None, infstr=None,
-                     formatter=None, sign=None, floatmode=None, **kwarg):
+                     formatter=None, sign=None, floatmode=None, *, legacy=None):
     """
     Set printing options.
 
@@ -249,11 +240,6 @@ def set_printoptions(precision=None, threshold=None, edgeitems=None,
     array([ 0.  ,  1.11,  2.22, ...,  7.78,  8.89, 10.  ])
 
     """
-    legacy = kwarg.pop('legacy', None)
-    if kwarg:
-        msg = "set_printoptions() got unexpected keyword argument '{}'"
-        raise TypeError(msg.format(kwarg.popitem()[0]))
-
     opt = _make_options_dict(precision, threshold, edgeitems, linewidth,
                              suppress, nanstr, infstr, sign, formatter,
                              floatmode, legacy)
@@ -369,23 +355,22 @@ def repr_format(x):
 def str_format(x):
     return str(x)
 
-def _get_formatdict(data, **opt):
-    prec, fmode = opt['precision'], opt['floatmode']
-    supp, sign = opt['suppress'], opt['sign']
-    legacy = opt['legacy']
+def _get_formatdict(data, *, precision, floatmode, suppress, sign, legacy,
+                    formatter, **kwargs):
+    # note: extra arguments in kwargs are ignored
 
     # wrapped in lambdas to avoid taking a code path with the wrong type of data
     formatdict = {
         'bool': lambda: BoolFormat(data),
         'int': lambda: IntegerFormat(data),
-        'float': lambda:
-            FloatingFormat(data, prec, fmode, supp, sign, legacy=legacy),
-        'longfloat': lambda:
-            FloatingFormat(data, prec, fmode, supp, sign, legacy=legacy),
-        'complexfloat': lambda:
-            ComplexFloatingFormat(data, prec, fmode, supp, sign, legacy=legacy),
-        'longcomplexfloat': lambda:
-            ComplexFloatingFormat(data, prec, fmode, supp, sign, legacy=legacy),
+        'float': lambda: FloatingFormat(
+            data, precision, floatmode, suppress, sign, legacy=legacy),
+        'longfloat': lambda: FloatingFormat(
+            data, precision, floatmode, suppress, sign, legacy=legacy),
+        'complexfloat': lambda: ComplexFloatingFormat(
+            data, precision, floatmode, suppress, sign, legacy=legacy),
+        'longcomplexfloat': lambda: ComplexFloatingFormat(
+            data, precision, floatmode, suppress, sign, legacy=legacy),
         'datetime': lambda: DatetimeFormat(data, legacy=legacy),
         'timedelta': lambda: TimedeltaFormat(data),
         'object': lambda: _object_format,
@@ -398,7 +383,6 @@ def _get_formatdict(data, **opt):
     def indirect(x):
         return lambda: x
 
-    formatter = opt['formatter']
     if formatter is not None:
         fkeys = [k for k in formatter.keys() if formatter[k] is not None]
         if 'all' in fkeys:
@@ -525,7 +509,7 @@ def _array2string_dispatcher(
         suppress_small=None, separator=None, prefix=None,
         style=None, formatter=None, threshold=None,
         edgeitems=None, sign=None, floatmode=None, suffix=None,
-        **kwarg):
+        *, legacy=None):
     return (a,)
 
 
@@ -534,7 +518,7 @@ def array2string(a, max_line_width=None, precision=None,
                  suppress_small=None, separator=' ', prefix="",
                  style=np._NoValue, formatter=None, threshold=None,
                  edgeitems=None, sign=None, floatmode=None, suffix="",
-                 **kwarg):
+                 *, legacy=None):
     """
     Return a string representation of an array.
 
@@ -679,10 +663,6 @@ def array2string(a, max_line_width=None, precision=None,
     '[0x0 0x1 0x2]'
 
     """
-    legacy = kwarg.pop('legacy', None)
-    if kwarg:
-        msg = "array2string() got unexpected keyword argument '{}'"
-        raise TypeError(msg.format(kwarg.popitem()[0]))
 
     overrides = _make_options_dict(precision, threshold, edgeitems,
                                    max_line_width, suppress_small, None, None,
@@ -851,15 +831,15 @@ def _none_or_positive_arg(x, name):
         raise ValueError("{} must be >= 0".format(name))
     return x
 
-class FloatingFormat(object):
+class FloatingFormat:
     """ Formatter for subtypes of np.floating """
     def __init__(self, data, precision, floatmode, suppress_small, sign=False,
-                 **kwarg):
+                 *, legacy=None):
         # for backcompatibility, accept bools
         if isinstance(sign, bool):
             sign = '+' if sign else '-'
 
-        self._legacy = kwarg.get('legacy', False)
+        self._legacy = legacy
         if self._legacy == '1.13':
             # when not 0d, legacy does not support '-'
             if data.shape != () and sign == '-':
@@ -1140,7 +1120,7 @@ def format_float_positional(x, precision=None, unique=True,
                               pad_right=pad_right)
 
 
-class IntegerFormat(object):
+class IntegerFormat:
     def __init__(self, data):
         if data.size > 0:
             max_str_len = max(len(str(np.max(data))),
@@ -1153,7 +1133,7 @@ class IntegerFormat(object):
         return self.format % x
 
 
-class BoolFormat(object):
+class BoolFormat:
     def __init__(self, data, **kwargs):
         # add an extra space so " True" and "False" have the same length and
         # array elements align nicely when printed, except in 0d arrays
@@ -1163,23 +1143,27 @@ class BoolFormat(object):
         return self.truestr if x else "False"
 
 
-class ComplexFloatingFormat(object):
+class ComplexFloatingFormat:
     """ Formatter for subtypes of np.complexfloating """
     def __init__(self, x, precision, floatmode, suppress_small,
-                 sign=False, **kwarg):
+                 sign=False, *, legacy=None):
         # for backcompatibility, accept bools
         if isinstance(sign, bool):
             sign = '+' if sign else '-'
 
         floatmode_real = floatmode_imag = floatmode
-        if kwarg.get('legacy', False) == '1.13':
+        if legacy == '1.13':
             floatmode_real = 'maxprec_equal'
             floatmode_imag = 'maxprec'
 
-        self.real_format = FloatingFormat(x.real, precision, floatmode_real,
-                                          suppress_small, sign=sign, **kwarg)
-        self.imag_format = FloatingFormat(x.imag, precision, floatmode_imag,
-                                          suppress_small, sign='+', **kwarg)
+        self.real_format = FloatingFormat(
+            x.real, precision, floatmode_real, suppress_small,
+            sign=sign, legacy=legacy
+        )
+        self.imag_format = FloatingFormat(
+            x.imag, precision, floatmode_imag, suppress_small,
+            sign='+', legacy=legacy
+        )
 
     def __call__(self, x):
         r = self.real_format(x.real)
@@ -1192,7 +1176,7 @@ class ComplexFloatingFormat(object):
         return r + i
 
 
-class _TimelikeFormat(object):
+class _TimelikeFormat:
     def __init__(self, data):
         non_nat = data[~isnat(data)]
         if len(non_nat) > 0:
@@ -1255,7 +1239,7 @@ class TimedeltaFormat(_TimelikeFormat):
         return str(x.astype('i8'))
 
 
-class SubArrayFormat(object):
+class SubArrayFormat:
     def __init__(self, format_function):
         self.format_function = format_function
 
@@ -1265,7 +1249,7 @@ class SubArrayFormat(object):
         return "[" + ", ".join(self.__call__(a) for a in arr) + "]"
 
 
-class StructuredVoidFormat(object):
+class StructuredVoidFormat:
     """
     Formatter for structured np.void objects.
 
index 1d0f69b67d8fabcf0fa02faaf2574f9d917bdfe9..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644 (file)
@@ -1 +0,0 @@
-from __future__ import division, absolute_import, print_function
index 72d2af8b986b51bec2bed6c50726a8982a0c2ace..5daa52d79019c8bf3fc9336c1a64e5ecd3502595 100644 (file)
@@ -49,4 +49,5 @@
 # Add PyUFunc_FromFuncAndDataAndSignatureAndIdentity to ufunc_funcs_api.
 # Version 13 (NumPy 1.17) No change.
 # Version 13 (NumPy 1.18) No change.
+# Version 13 (NumPy 1.19) No change.
 0x0000000d = 5b0e8bbded00b166125974fc71e80a33
index 22afa0320a6d4b7dad0c514fc313b02535e779b3..88dc2d90a4d331e095a0822943de71f8c585da6a 100644 (file)
@@ -6,14 +6,13 @@ See ``find_function`` for how functions should be formatted, and
 specified.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from numpy.distutils.conv_template import process_file as process_c_file
 
-import sys, os, re
 import hashlib
 import io
-
+import os
+import re
+import sys
 import textwrap
 
 from os.path import join
@@ -76,7 +75,7 @@ def _repl(str):
     return str.replace('Bool', 'npy_bool')
 
 
-class StealRef(object):
+class StealRef:
     def __init__(self, arg):
         self.arg = arg # counting from 1
 
@@ -87,7 +86,7 @@ class StealRef(object):
             return 'NPY_STEALS_REF_TO_ARG(%d)' % self.arg
 
 
-class NonNull(object):
+class NonNull:
     def __init__(self, arg):
         self.arg = arg # counting from 1
 
@@ -98,7 +97,7 @@ class NonNull(object):
             return 'NPY_GCC_NONNULL(%d)' % self.arg
 
 
-class Function(object):
+class Function:
     def __init__(self, name, return_type, args, doc=''):
         self.name = name
         self.return_type = _repl(return_type)
@@ -309,7 +308,7 @@ def write_file(filename, data):
 
 
 # Those *Api classes instances know how to output strings for the generated code
-class TypeApi(object):
+class TypeApi:
     def __init__(self, name, index, ptr_cast, api_name):
         self.index = index
         self.name = name
@@ -331,7 +330,7 @@ extern NPY_NO_EXPORT PyTypeObject %(type)s;
 """ % {'type': self.name}
         return astr
 
-class GlobalVarApi(object):
+class GlobalVarApi:
     def __init__(self, name, index, type, api_name):
         self.name = name
         self.index = index
@@ -355,7 +354,7 @@ extern NPY_NO_EXPORT %(type)s %(name)s;
 
 # Dummy to be able to consistently use *Api instances for all items in the
 # array api
-class BoolValuesApi(object):
+class BoolValuesApi:
     def __init__(self, name, index, api_name):
         self.name = name
         self.index = index
@@ -377,7 +376,7 @@ extern NPY_NO_EXPORT PyBoolScalarObject _PyArrayScalar_BoolValues[2];
 """
         return astr
 
-class FunctionApi(object):
+class FunctionApi:
     def __init__(self, name, index, annotations, return_type, args, api_name):
         self.name = name
         self.index = index
index 5e04fb86dd4f4f0458315b7b7b8da6a68966fb0c..fe21bc543d589d631eae99689d69073188a2513d 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, print_function
-
 import os
 import genapi
 
@@ -59,21 +57,12 @@ _import_array(void)
       return -1;
   }
 
-#if PY_VERSION_HEX >= 0x03000000
   if (!PyCapsule_CheckExact(c_api)) {
       PyErr_SetString(PyExc_RuntimeError, "_ARRAY_API is not PyCapsule object");
       Py_DECREF(c_api);
       return -1;
   }
   PyArray_API = (void **)PyCapsule_GetPointer(c_api, NULL);
-#else
-  if (!PyCObject_Check(c_api)) {
-      PyErr_SetString(PyExc_RuntimeError, "_ARRAY_API is not PyCObject object");
-      Py_DECREF(c_api);
-      return -1;
-  }
-  PyArray_API = (void **)PyCObject_AsVoidPtr(c_api);
-#endif
   Py_DECREF(c_api);
   if (PyArray_API == NULL) {
       PyErr_SetString(PyExc_RuntimeError, "_ARRAY_API is NULL pointer");
@@ -120,13 +109,7 @@ _import_array(void)
   return 0;
 }
 
-#if PY_VERSION_HEX >= 0x03000000
-#define NUMPY_IMPORT_ARRAY_RETVAL NULL
-#else
-#define NUMPY_IMPORT_ARRAY_RETVAL
-#endif
-
-#define import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); return NUMPY_IMPORT_ARRAY_RETVAL; } }
+#define import_array() {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); return NULL; } }
 
 #define import_array1(ret) {if (_import_array() < 0) {PyErr_Print(); PyErr_SetString(PyExc_ImportError, "numpy.core.multiarray failed to import"); return ret; } }
 
index 1b0143e88be5af35234a2a53c687b1ff067c685c..04c023675faed9ee9ed57d7d577060b06487303b 100644 (file)
@@ -1,12 +1,9 @@
-from __future__ import division, print_function
-
 import os
 import genapi
 
 import numpy_api
 
-from genapi import \
-        TypeApi, GlobalVarApi, FunctionApi, BoolValuesApi
+from genapi import TypeApi, FunctionApi
 
 h_template = r"""
 #ifdef _UMATHMODULE
@@ -51,21 +48,12 @@ _import_umath(void)
       return -1;
   }
 
-#if PY_VERSION_HEX >= 0x03000000
   if (!PyCapsule_CheckExact(c_api)) {
       PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is not PyCapsule object");
       Py_DECREF(c_api);
       return -1;
   }
   PyUFunc_API = (void **)PyCapsule_GetPointer(c_api, NULL);
-#else
-  if (!PyCObject_Check(c_api)) {
-      PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is not PyCObject object");
-      Py_DECREF(c_api);
-      return -1;
-  }
-  PyUFunc_API = (void **)PyCObject_AsVoidPtr(c_api);
-#endif
   Py_DECREF(c_api);
   if (PyUFunc_API == NULL) {
       PyErr_SetString(PyExc_RuntimeError, "_UFUNC_API is NULL pointer");
@@ -74,12 +62,6 @@ _import_umath(void)
   return 0;
 }
 
-#if PY_VERSION_HEX >= 0x03000000
-#define NUMPY_IMPORT_UMATH_RETVAL NULL
-#else
-#define NUMPY_IMPORT_UMATH_RETVAL
-#endif
-
 #define import_umath() \
     do {\
         UFUNC_NOFPE\
@@ -87,7 +69,7 @@ _import_umath(void)
             PyErr_Print();\
             PyErr_SetString(PyExc_ImportError,\
                     "numpy.core.umath failed to import");\
-            return NUMPY_IMPORT_UMATH_RETVAL;\
+            return NULL;\
         }\
     } while(0)
 
index 6d76f7ca21c41dc0332f8114ee2db463b1982df5..202912c5f31c438ef751ba5f8c6fd64a4f0a7586 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, print_function
-
 import os
 import re
 import struct
@@ -21,16 +19,16 @@ ReorderableNone = "(Py_INCREF(Py_None), Py_None)"
 
 # Sentinel value to specify using the full type description in the
 # function name
-class FullTypeDescr(object):
+class FullTypeDescr:
     pass
 
-class FuncNameSuffix(object):
+class FuncNameSuffix:
     """Stores the suffix to append when generating functions names.
     """
     def __init__(self, suffix):
         self.suffix = suffix
 
-class TypeDescription(object):
+class TypeDescription:
     """Type signature for a ufunc.
 
     Attributes
@@ -120,7 +118,7 @@ def TD(types, f=None, astype=None, in_=None, out=None, simd=None):
         tds.append(TypeDescription(t, f=fd, in_=i, out=o, astype=astype, simd=simdt))
     return tds
 
-class Ufunc(object):
+class Ufunc:
     """Description of a ufunc.
 
     Attributes
@@ -132,7 +130,7 @@ class Ufunc(object):
     type_descriptions : list of TypeDescription objects
     """
     def __init__(self, nin, nout, identity, docstring, typereso,
-                 *type_descriptions, **kwargs):
+                 *type_descriptions, signature=None):
         self.nin = nin
         self.nout = nout
         if identity is None:
@@ -141,23 +139,17 @@ class Ufunc(object):
         self.docstring = docstring
         self.typereso = typereso
         self.type_descriptions = []
-        self.signature = kwargs.pop('signature', None)
+        self.signature = signature
         for td in type_descriptions:
             self.type_descriptions.extend(td)
         for td in self.type_descriptions:
             td.finish_signature(self.nin, self.nout)
-        if kwargs:
-            raise ValueError('unknown kwargs %r' % str(kwargs))
 
 # String-handling utilities to avoid locale-dependence.
 
 import string
-if sys.version_info[0] < 3:
-    UPPER_TABLE = string.maketrans(string.ascii_lowercase,
-                                   string.ascii_uppercase)
-else:
-    UPPER_TABLE = bytes.maketrans(bytes(string.ascii_lowercase, "ascii"),
-                                  bytes(string.ascii_uppercase, "ascii"))
+UPPER_TABLE = bytes.maketrans(bytes(string.ascii_lowercase, "ascii"),
+                              bytes(string.ascii_uppercase, "ascii"))
 
 def english_upper(s):
     """ Apply English case rules to convert ASCII strings to all upper case.
@@ -241,6 +233,7 @@ flts = 'efdg'
 fltsO = flts + O
 fltsP = flts + P
 cmplx = 'FDG'
+cmplxvec = 'FD'
 cmplxO = cmplx + O
 cmplxP = cmplx + P
 inexact = flts + cmplx
@@ -276,7 +269,7 @@ defdict = {
     Ufunc(2, 1, Zero,
           docstrings.get('numpy.core.umath.add'),
           'PyUFunc_AdditionTypeResolver',
-          TD(notimes_or_obj, simd=[('avx2', ints)]),
+          TD(notimes_or_obj, simd=[('avx512f', cmplxvec),('avx2', ints)]),
           [TypeDescription('M', FullTypeDescr, 'Mm', 'M'),
            TypeDescription('m', FullTypeDescr, 'mm', 'm'),
            TypeDescription('M', FullTypeDescr, 'mM', 'M'),
@@ -287,7 +280,7 @@ defdict = {
     Ufunc(2, 1, None, # Zero is only a unit to the right, not the left
           docstrings.get('numpy.core.umath.subtract'),
           'PyUFunc_SubtractionTypeResolver',
-          TD(ints + inexact, simd=[('avx2', ints)]),
+          TD(ints + inexact, simd=[('avx512f', cmplxvec),('avx2', ints)]),
           [TypeDescription('M', FullTypeDescr, 'Mm', 'M'),
            TypeDescription('m', FullTypeDescr, 'mm', 'm'),
            TypeDescription('M', FullTypeDescr, 'MM', 'm'),
@@ -298,7 +291,7 @@ defdict = {
     Ufunc(2, 1, One,
           docstrings.get('numpy.core.umath.multiply'),
           'PyUFunc_MultiplicationTypeResolver',
-          TD(notimes_or_obj, simd=[('avx2', ints)]),
+          TD(notimes_or_obj, simd=[('avx512f', cmplxvec),('avx2', ints)]),
           [TypeDescription('m', FullTypeDescr, 'mq', 'm'),
            TypeDescription('m', FullTypeDescr, 'qm', 'm'),
            TypeDescription('m', FullTypeDescr, 'md', 'm'),
@@ -306,17 +299,7 @@ defdict = {
           ],
           TD(O, f='PyNumber_Multiply'),
           ),
-'divide':
-    Ufunc(2, 1, None, # One is only a unit to the right, not the left
-          docstrings.get('numpy.core.umath.divide'),
-          'PyUFunc_MixedDivisionTypeResolver',
-          TD(intfltcmplx),
-          [TypeDescription('m', FullTypeDescr, 'mq', 'm'),
-           TypeDescription('m', FullTypeDescr, 'md', 'm'),
-           TypeDescription('m', FullTypeDescr, 'mm', 'd'),
-          ],
-          TD(O, f='PyNumber_Divide'),
-          ),
+#'divide' : aliased to true_divide in umathmodule.c:initumath
 'floor_divide':
     Ufunc(2, 1, None, # One is only a unit to the right, not the left
           docstrings.get('numpy.core.umath.floor_divide'),
@@ -343,7 +326,7 @@ defdict = {
     Ufunc(1, 1, None,
           docstrings.get('numpy.core.umath.conjugate'),
           None,
-          TD(ints+flts+cmplx, simd=[('avx2', ints)]),
+          TD(ints+flts+cmplx, simd=[('avx2', ints), ('avx512f', cmplxvec)]),
           TD(P, f='conjugate'),
           ),
 'fmod':
@@ -358,7 +341,7 @@ defdict = {
     Ufunc(1, 1, None,
           docstrings.get('numpy.core.umath.square'),
           None,
-          TD(ints+inexact, simd=[('avx2', ints), ('fma', 'fd'), ('avx512f', 'fd')]),
+          TD(ints+inexact, simd=[('avx2', ints), ('fma', 'fd'), ('avx512f', 'FDfd')]),
           TD(O, f='Py_square'),
           ),
 'reciprocal':
@@ -396,7 +379,7 @@ defdict = {
           docstrings.get('numpy.core.umath.absolute'),
           'PyUFunc_AbsoluteTypeResolver',
           TD(bints+flts+timedeltaonly, simd=[('fma', 'fd'), ('avx512f', 'fd')]),
-          TD(cmplx, out=('f', 'd', 'g')),
+          TD(cmplx, simd=[('avx512f', cmplxvec)], out=('f', 'd', 'g')),
           TD(O, f='PyNumber_Absolute'),
           ),
 '_arg':
@@ -510,14 +493,14 @@ defdict = {
     Ufunc(2, 1, ReorderableNone,
           docstrings.get('numpy.core.umath.maximum'),
           'PyUFunc_SimpleUniformOperationTypeResolver',
-          TD(noobj),
+          TD(noobj, simd=[('avx512f', 'fd')]),
           TD(O, f='npy_ObjectMax')
           ),
 'minimum':
     Ufunc(2, 1, ReorderableNone,
           docstrings.get('numpy.core.umath.minimum'),
           'PyUFunc_SimpleUniformOperationTypeResolver',
-          TD(noobj),
+          TD(noobj, simd=[('avx512f', 'fd')]),
           TD(O, f='npy_ObjectMin')
           ),
 'clip':
@@ -548,7 +531,7 @@ defdict = {
           TD(flts, f="logaddexp", astype={'e':'f'})
           ),
 'logaddexp2':
-    Ufunc(2, 1, None,
+    Ufunc(2, 1, MinusInfinity,
           docstrings.get('numpy.core.umath.logaddexp2'),
           None,
           TD(flts, f="logaddexp2", astype={'e':'f'})
@@ -719,6 +702,7 @@ defdict = {
           None,
           TD('e', f='exp', astype={'e':'f'}),
           TD('f', simd=[('fma', 'f'), ('avx512f', 'f')]),
+          TD('d', simd=[('avx512f', 'd')]),
           TD('fdg' + cmplx, f='exp'),
           TD(P, f='exp'),
           ),
@@ -957,10 +941,6 @@ defdict = {
           ),
 }
 
-if sys.version_info[0] >= 3:
-    # Will be aliased to true_divide in umathmodule.c.src:InitOtherOperators
-    del defdict['divide']
-
 def indent(st, spaces):
     indentation = ' '*spaces
     indented = indentation + st.replace('\n', '\n'+indentation)
@@ -1036,7 +1016,7 @@ def make_arrays(funcdict):
                     for vt in t.simd:
                         code2list.append(textwrap.dedent("""\
                         #ifdef HAVE_ATTRIBUTE_TARGET_{ISA}
-                        if (npy_cpu_supports("{isa}")) {{
+                        if (NPY_CPU_HAVE({ISA})) {{
                             {fname}_functions[{idx}] = {type}_{fname}_{isa};
                         }}
                         #endif
@@ -1095,15 +1075,9 @@ def make_ufuncs(funcdict):
         uf = funcdict[name]
         mlist = []
         docstring = textwrap.dedent(uf.docstring).strip()
-        if sys.version_info[0] < 3:
-            docstring = docstring.encode('string-escape')
-            docstring = docstring.replace(r'"', r'\"')
-        else:
-            docstring = docstring.encode('unicode-escape').decode('ascii')
-            docstring = docstring.replace(r'"', r'\"')
-            # XXX: I don't understand why the following replace is not
-            # necessary in the python 2 case.
-            docstring = docstring.replace(r"'", r"\'")
+        docstring = docstring.encode('unicode-escape').decode('ascii')
+        docstring = docstring.replace(r'"', r'\"')
+        docstring = docstring.replace(r"'", r"\'")
         # Split the docstring because some compilers (like MS) do not like big
         # string literal in C code. We split at endlines because textwrap.wrap
         # do not play well with \n
@@ -1166,7 +1140,6 @@ def make_code(funcdict, filename):
 
         Please make changes to the code generator program (%s)
     **/
-    #include "cpuid.h"
     #include "ufunc_object.h"
     #include "ufunc_type_resolution.h"
     #include "loops.h"
index a71c236fdde4cc918d0a3579e2da9cfc3e69b4e0..916fb537e863443f1acc0a29f08e2387936f7420 100644 (file)
@@ -13,8 +13,6 @@ When adding a function, make sure to use the next integer not used as an index
 exception, so it should hopefully not get unnoticed).
 
 """
-from __future__ import division, absolute_import, print_function
-
 from code_generators.genapi import StealRef, NonNull
 
 # index, type
index 4dec73505ab3e7ee0102cf04ae7723f4a42b5a96..82cd6fb273f2028cff6ddd4eb94948b7c948f876 100644 (file)
@@ -9,7 +9,6 @@ for the ufuncs in numpy.core at the C level when the ufuncs are created
 at compile time.
 
 """
-from __future__ import division, absolute_import, print_function
 import textwrap
 
 docdict = {}
@@ -37,8 +36,8 @@ subst = {
             :ref:`ufunc docs <ufuncs.kwargs>`.
     """).strip(),
     'BROADCASTABLE_2': ("If ``x1.shape != x2.shape``, they must be "
-                        "broadcastable to a common shape (which becomes the "
-                        "shape of the output)."),
+                        "broadcastable to a common\n    shape (which becomes "
+                        "the shape of the output)."),
     'OUT_SCALAR_1': "This is a scalar if `x` is a scalar.",
     'OUT_SCALAR_2': "This is a scalar if both `x1` and `x2` are scalars.",
 }
@@ -117,7 +116,8 @@ add_newdoc('numpy.core.umath', 'add',
     Parameters
     ----------
     x1, x2 : array_like
-        The arrays to be added. $BROADCASTABLE_2
+        The arrays to be added.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -443,7 +443,8 @@ add_newdoc('numpy.core.umath', 'arctan2',
     x1 : array_like, real-valued
         `y`-coordinates.
     x2 : array_like, real-valued
-        `x`-coordinates. $BROADCASTABLE_2
+        `x`-coordinates.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -566,7 +567,8 @@ add_newdoc('numpy.core.umath', 'bitwise_and',
     Parameters
     ----------
     x1, x2 : array_like
-        Only integer and boolean types are handled. $BROADCASTABLE_2
+        Only integer and boolean types are handled.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -619,7 +621,8 @@ add_newdoc('numpy.core.umath', 'bitwise_or',
     Parameters
     ----------
     x1, x2 : array_like
-        Only integer and boolean types are handled. $BROADCASTABLE_2
+        Only integer and boolean types are handled.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -677,7 +680,8 @@ add_newdoc('numpy.core.umath', 'bitwise_xor',
     Parameters
     ----------
     x1, x2 : array_like
-        Only integer and boolean types are handled. $BROADCASTABLE_2
+        Only integer and boolean types are handled.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -987,7 +991,8 @@ add_newdoc('numpy.core.umath', 'heaviside',
     x1 : array_like
         Input values.
     x2 : array_like
-        The value of the function when x1 is 0. $BROADCASTABLE_2
+        The value of the function when x1 is 0.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -1022,7 +1027,8 @@ add_newdoc('numpy.core.umath', 'divide',
     x1 : array_like
         Dividend array.
     x2 : array_like
-        Divisor array. $BROADCASTABLE_2
+        Divisor array.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -1091,7 +1097,8 @@ add_newdoc('numpy.core.umath', 'equal',
     Parameters
     ----------
     x1, x2 : array_like
-        Input arrays. $BROADCASTABLE_2
+        Input arrays.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -1223,7 +1230,7 @@ add_newdoc('numpy.core.umath', 'expm1',
     Parameters
     ----------
     x : array_like
-       Input values.
+        Input values.
     $PARAMS
 
     Returns
@@ -1338,7 +1345,8 @@ add_newdoc('numpy.core.umath', 'floor_divide',
     x1 : array_like
         Numerator.
     x2 : array_like
-        Denominator. $BROADCASTABLE_2
+        Denominator.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -1378,7 +1386,8 @@ add_newdoc('numpy.core.umath', 'fmod',
     x1 : array_like
         Dividend.
     x2 : array_like
-        Divisor. $BROADCASTABLE_2
+        Divisor.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -1428,7 +1437,8 @@ add_newdoc('numpy.core.umath', 'greater',
     Parameters
     ----------
     x1, x2 : array_like
-        Input arrays. $BROADCASTABLE_2
+        Input arrays.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -1464,7 +1474,8 @@ add_newdoc('numpy.core.umath', 'greater_equal',
     Parameters
     ----------
     x1, x2 : array_like
-        Input arrays. $BROADCASTABLE_2
+        Input arrays.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -1497,7 +1508,8 @@ add_newdoc('numpy.core.umath', 'hypot',
     Parameters
     ----------
     x1, x2 : array_like
-        Leg of the triangle(s). $BROADCASTABLE_2
+        Leg of the triangle(s).
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -1823,6 +1835,17 @@ add_newdoc('numpy.core.umath', 'left_shift',
     >>> np.left_shift(5, [1,2,3])
     array([10, 20, 40])
 
+    Note that the dtype of the second argument may change the dtype of the
+    result and can lead to unexpected results in some cases (see
+    :ref:`Casting Rules <ufuncs.casting>`):
+
+    >>> a = np.left_shift(np.uint8(255), 1) # Expect 254
+    >>> print(a, type(a)) # Unexpected result due to upcasting
+    510 <class 'numpy.int64'>
+    >>> b = np.left_shift(np.uint8(255), np.uint8(1))
+    >>> print(b, type(b))
+    254 <class 'numpy.uint8'>
+
     """)
 
 add_newdoc('numpy.core.umath', 'less',
@@ -1832,7 +1855,8 @@ add_newdoc('numpy.core.umath', 'less',
     Parameters
     ----------
     x1, x2 : array_like
-        Input arrays. $BROADCASTABLE_2
+        Input arrays.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -1860,7 +1884,8 @@ add_newdoc('numpy.core.umath', 'less_equal',
     Parameters
     ----------
     x1, x2 : array_like
-        Input arrays. $BROADCASTABLE_2
+        Input arrays.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2044,7 +2069,8 @@ add_newdoc('numpy.core.umath', 'logaddexp',
     Parameters
     ----------
     x1, x2 : array_like
-        Input values. $BROADCASTABLE_2
+        Input values.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2086,7 +2112,8 @@ add_newdoc('numpy.core.umath', 'logaddexp2',
     Parameters
     ----------
     x1, x2 : array_like
-        Input values. $BROADCASTABLE_2
+        Input values.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2177,7 +2204,8 @@ add_newdoc('numpy.core.umath', 'logical_and',
     Parameters
     ----------
     x1, x2 : array_like
-        Input arrays. $BROADCASTABLE_2
+        Input arrays.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2282,7 +2310,8 @@ add_newdoc('numpy.core.umath', 'logical_xor',
     Parameters
     ----------
     x1, x2 : array_like
-        Logical XOR is applied to the elements of `x1` and `x2`. $BROADCASTABLE_2
+        Logical XOR is applied to the elements of `x1` and `x2`.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2329,7 +2358,8 @@ add_newdoc('numpy.core.umath', 'maximum',
     Parameters
     ----------
     x1, x2 : array_like
-        The arrays holding the elements to be compared. $BROADCASTABLE_2
+        The arrays holding the elements to be compared.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2387,7 +2417,8 @@ add_newdoc('numpy.core.umath', 'minimum',
     Parameters
     ----------
     x1, x2 : array_like
-        The arrays holding the elements to be compared. $BROADCASTABLE_2
+        The arrays holding the elements to be compared.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2445,7 +2476,8 @@ add_newdoc('numpy.core.umath', 'fmax',
     Parameters
     ----------
     x1, x2 : array_like
-        The arrays holding the elements to be compared. $BROADCASTABLE_2
+        The arrays holding the elements to be compared.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2502,7 +2534,8 @@ add_newdoc('numpy.core.umath', 'fmin',
     Parameters
     ----------
     x1, x2 : array_like
-        The arrays holding the elements to be compared. $BROADCASTABLE_2
+        The arrays holding the elements to be compared.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2755,7 +2788,8 @@ add_newdoc('numpy.core.umath', 'multiply',
     Parameters
     ----------
     x1, x2 : array_like
-        Input arrays to be multiplied. $BROADCASTABLE_2
+        Input arrays to be multiplied.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2836,7 +2870,8 @@ add_newdoc('numpy.core.umath', 'not_equal',
     Parameters
     ----------
     x1, x2 : array_like
-        Input arrays.  $BROADCASTABLE_2
+        Input arrays.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2885,7 +2920,8 @@ add_newdoc('numpy.core.umath', 'power',
     x1 : array_like
         The bases.
     x2 : array_like
-        The exponents. $BROADCASTABLE_2
+        The exponents.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -2944,7 +2980,8 @@ add_newdoc('numpy.core.umath', 'float_power',
     x1 : array_like
         The bases.
     x2 : array_like
-        The exponents. $BROADCASTABLE_2
+        The exponents.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -3116,7 +3153,8 @@ add_newdoc('numpy.core.umath', 'remainder',
     x1 : array_like
         Dividend array.
     x2 : array_like
-        Divisor array. $BROADCASTABLE_2
+        Divisor array.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -3162,7 +3200,8 @@ add_newdoc('numpy.core.umath', 'divmod',
     x1 : array_like
         Dividend array.
     x2 : array_like
-        Divisor array. $BROADCASTABLE_2
+        Divisor array.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -3201,7 +3240,8 @@ add_newdoc('numpy.core.umath', 'right_shift',
     x1 : array_like, int
         Input values.
     x2 : array_like, int
-        Number of bits to remove at the right of `x1`. $BROADCASTABLE_2
+        Number of bits to remove at the right of `x1`.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -3335,7 +3375,8 @@ add_newdoc('numpy.core.umath', 'copysign',
     x1 : array_like
         Values to change the sign of.
     x2 : array_like
-        The sign of `x2` is copied to `x1`. $BROADCASTABLE_2
+        The sign of `x2` is copied to `x1`.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -3642,7 +3683,8 @@ add_newdoc('numpy.core.umath', 'subtract',
     Parameters
     ----------
     x1, x2 : array_like
-        The arrays to be subtracted from each other. $BROADCASTABLE_2
+        The arrays to be subtracted from each other.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -3783,7 +3825,8 @@ add_newdoc('numpy.core.umath', 'true_divide',
     x1 : array_like
         Dividend array.
     x2 : array_like
-        Divisor array. $BROADCASTABLE_2
+        Divisor array.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -3793,12 +3836,7 @@ add_newdoc('numpy.core.umath', 'true_divide',
 
     Notes
     -----
-    The floor division operator ``//`` was added in Python 2.2 making
-    ``//`` and ``/`` equivalent operators.  The default floor division
-    operation of ``/`` can be replaced by true division with ``from
-    __future__ import division``.
-
-    In Python 3.0, ``//`` is the floor division operator and ``/`` the
+    In Python, ``//`` is the floor division operator and ``/`` the
     true division operator.  The ``true_divide(x1, x2)`` function is
     equivalent to true division in Python.
 
@@ -3808,15 +3846,11 @@ add_newdoc('numpy.core.umath', 'true_divide',
     >>> np.true_divide(x, 4)
     array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ])
 
-    >>> x//4
-    array([0, 0, 0, 0, 1])
-
-    >>> from __future__ import division
     >>> x/4
     array([ 0.  ,  0.25,  0.5 ,  0.75,  1.  ])
+
     >>> x//4
     array([0, 0, 0, 0, 1])
-
     """)
 
 add_newdoc('numpy.core.umath', 'frexp',
@@ -3880,7 +3914,8 @@ add_newdoc('numpy.core.umath', 'ldexp',
     x1 : array_like
         Array of multipliers.
     x2 : array_like, int
-        Array of twos exponents. $BROADCASTABLE_2
+        Array of twos exponents.
+        $BROADCASTABLE_2
     $PARAMS
 
     Returns
@@ -3918,7 +3953,8 @@ add_newdoc('numpy.core.umath', 'gcd',
     Parameters
     ----------
     x1, x2 : array_like, int
-        Arrays of values. $BROADCASTABLE_2
+        Arrays of values.
+        $BROADCASTABLE_2
 
     Returns
     -------
@@ -3948,7 +3984,8 @@ add_newdoc('numpy.core.umath', 'lcm',
     Parameters
     ----------
     x1, x2 : array_like, int
-        Arrays of values. $BROADCASTABLE_2
+        Arrays of values.
+        $BROADCASTABLE_2
 
     Returns
     -------
index 7995dd9931e7ee2aa72711db5e50a340b38b0299..00159c3a8031d8ccd44b226db42090f97014cd9f 100644 (file)
@@ -3,8 +3,6 @@
 The API has is defined by numpy_api_order and ufunc_api_order.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from os.path import dirname
 
 from code_generators.genapi import fullapi_hash
index 2d89d6fe08aff462d376b48433fe7d1f3366f1c0..1d447b86ab0e177c24c26db0a141cb83d5ce27c6 100644 (file)
@@ -15,17 +15,16 @@ available in your version of Python.
 The preferred alias for `defchararray` is `numpy.char`.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import functools
 import sys
-from .numerictypes import string_, unicode_, integer, object_, bool_, character
+from .numerictypes import (
+    string_, unicode_, integer, int_, object_, bool_, character)
 from .numeric import ndarray, compare_chararrays
 from .numeric import array as narray
 from numpy.core.multiarray import _vec_string
 from numpy.core.overrides import set_module
 from numpy.core import overrides
-from numpy.compat import asbytes, long
+from numpy.compat import asbytes
 import numpy
 
 __all__ = [
@@ -42,13 +41,6 @@ __all__ = [
 
 
 _globalvar = 0
-if sys.version_info[0] >= 3:
-    _unicode = str
-    _bytes = bytes
-else:
-    _unicode = unicode
-    _bytes = str
-_len = len
 
 array_function_dispatch = functools.partial(
     overrides.array_function_dispatch, module='numpy.char')
@@ -63,7 +55,7 @@ def _use_unicode(*args):
     result should be unicode.
     """
     for x in args:
-        if (isinstance(x, _unicode) or
+        if (isinstance(x, str) or
                 issubclass(numpy.asarray(x).dtype.type, unicode_)):
             return unicode_
     return string_
@@ -283,9 +275,12 @@ def str_len(a):
 
     See also
     --------
-    __builtin__.len
+    builtins.len
     """
-    return _vec_string(a, integer, '__len__')
+    # Note: __len__, etc. currently return ints, which are not C-integers.
+    # Generally intp would be expected for lengths, although int is sufficient
+    # due to the dtype itemsize limitation.
+    return _vec_string(a, int_, '__len__')
 
 
 @array_function_dispatch(_binary_op_dispatcher)
@@ -345,7 +340,7 @@ def multiply(a, i):
     i_arr = numpy.asarray(i)
     if not issubclass(i_arr.dtype.type, integer):
         raise ValueError("Can only multiply by integers")
-    out_size = _get_num_chars(a_arr) * max(long(i_arr.max()), 0)
+    out_size = _get_num_chars(a_arr) * max(int(i_arr.max()), 0)
     return _vec_string(
         a_arr, (a_arr.dtype.type, out_size), '__mul__', (i_arr,))
 
@@ -358,7 +353,7 @@ def _mod_dispatcher(a, values):
 def mod(a, values):
     """
     Return (a % i), that is pre-Python 2.6 string formatting
-    (iterpolation), element-wise for a pair of array_likes of str
+    (interpolation), element-wise for a pair of array_likes of str
     or unicode.
 
     Parameters
@@ -455,7 +450,7 @@ def center(a, width, fillchar=' '):
     """
     a_arr = numpy.asarray(a)
     width_arr = numpy.asarray(width)
-    size = long(numpy.max(width_arr.flat))
+    size = int(numpy.max(width_arr.flat))
     if numpy.issubdtype(a_arr.dtype, numpy.string_):
         fillchar = asbytes(fillchar)
     return _vec_string(
@@ -509,7 +504,7 @@ def count(a, sub, start=0, end=None):
     array([1, 0, 0])
 
     """
-    return _vec_string(a, integer, 'count', [sub, start] + _clean_args(end))
+    return _vec_string(a, int_, 'count', [sub, start] + _clean_args(end))
 
 
 def _code_dispatcher(a, encoding=None, errors=None):
@@ -719,7 +714,7 @@ def find(a, sub, start=0, end=None):
 
     """
     return _vec_string(
-        a, integer, 'find', [sub, start] + _clean_args(end))
+        a, int_, 'find', [sub, start] + _clean_args(end))
 
 
 @array_function_dispatch(_count_dispatcher)
@@ -748,7 +743,7 @@ def index(a, sub, start=0, end=None):
 
     """
     return _vec_string(
-        a, integer, 'index', [sub, start] + _clean_args(end))
+        a, int_, 'index', [sub, start] + _clean_args(end))
 
 
 @array_function_dispatch(_unary_op_dispatcher)
@@ -1000,7 +995,7 @@ def ljust(a, width, fillchar=' '):
     """
     a_arr = numpy.asarray(a)
     width_arr = numpy.asarray(width)
-    size = long(numpy.max(width_arr.flat))
+    size = int(numpy.max(width_arr.flat))
     if numpy.issubdtype(a_arr.dtype, numpy.string_):
         fillchar = asbytes(fillchar)
     return _vec_string(
@@ -1208,7 +1203,7 @@ def rfind(a, sub, start=0, end=None):
 
     """
     return _vec_string(
-        a, integer, 'rfind', [sub, start] + _clean_args(end))
+        a, int_, 'rfind', [sub, start] + _clean_args(end))
 
 
 @array_function_dispatch(_count_dispatcher)
@@ -1238,7 +1233,7 @@ def rindex(a, sub, start=0, end=None):
 
     """
     return _vec_string(
-        a, integer, 'rindex', [sub, start] + _clean_args(end))
+        a, int_, 'rindex', [sub, start] + _clean_args(end))
 
 
 @array_function_dispatch(_just_dispatcher)
@@ -1270,7 +1265,7 @@ def rjust(a, width, fillchar=' '):
     """
     a_arr = numpy.asarray(a)
     width_arr = numpy.asarray(width)
-    size = long(numpy.max(width_arr.flat))
+    size = int(numpy.max(width_arr.flat))
     if numpy.issubdtype(a_arr.dtype, numpy.string_):
         fillchar = asbytes(fillchar)
     return _vec_string(
@@ -1738,7 +1733,7 @@ def zfill(a, width):
     """
     a_arr = numpy.asarray(a)
     width_arr = numpy.asarray(width)
-    size = long(numpy.max(width_arr.flat))
+    size = int(numpy.max(width_arr.flat))
     return _vec_string(
         a_arr, (a_arr.dtype.type, size), 'zfill', (width_arr,))
 
@@ -1784,7 +1779,7 @@ def isdecimal(a):
     Calls `unicode.isdecimal` element-wise.
 
     Decimal characters include digit characters, and all characters
-    that that can be used to form decimal-radix numbers,
+    that can be used to form decimal-radix numbers,
     e.g. ``U+0660, ARABIC-INDIC DIGIT ZERO``.
 
     Parameters
@@ -1917,7 +1912,7 @@ class chararray(ndarray):
     unicode : bool, optional
         Are the array elements of type unicode (True) or string (False).
         Default is False.
-    buffer : int, optional
+    buffer : object exposing the buffer interface or str, optional
         Memory address of the start of the array data.  Default is None,
         in which case a new array is created.
     offset : int, optional
@@ -1957,13 +1952,13 @@ class chararray(ndarray):
         else:
             dtype = string_
 
-        # force itemsize to be a Python long, since using NumPy integer
+        # force itemsize to be a Python int, since using NumPy integer
         # types results in itemsize.itemsize being used as the size of
         # strings in the new array.
-        itemsize = long(itemsize)
+        itemsize = int(itemsize)
 
-        if sys.version_info[0] >= 3 and isinstance(buffer, _unicode):
-            # On Py3, unicode objects do not have the buffer interface
+        if isinstance(buffer, str):
+            # unicode objects do not have the buffer interface
             filler = buffer
             buffer = None
         else:
@@ -1993,7 +1988,7 @@ class chararray(ndarray):
 
         if isinstance(val, character):
             temp = val.rstrip()
-            if _len(temp) == 0:
+            if len(temp) == 0:
                 val = ''
             else:
                 val = temp
@@ -2112,7 +2107,7 @@ class chararray(ndarray):
     def __mod__(self, i):
         """
         Return (self % i), that is pre-Python 2.6 string formatting
-        (iterpolation), element-wise for a pair of array_likes of `string_`
+        (interpolation), element-wise for a pair of array_likes of `string_`
         or `unicode_`.
 
         See also
@@ -2677,35 +2672,16 @@ def array(obj, itemsize=None, copy=True, unicode=None, order=None):
         be in any order (either C-, Fortran-contiguous, or even
         discontiguous).
     """
-    if isinstance(obj, (_bytes, _unicode)):
+    if isinstance(obj, (bytes, str)):
         if unicode is None:
-            if isinstance(obj, _unicode):
+            if isinstance(obj, str):
                 unicode = True
             else:
                 unicode = False
 
         if itemsize is None:
-            itemsize = _len(obj)
-        shape = _len(obj) // itemsize
-
-        if unicode:
-            if sys.maxunicode == 0xffff:
-                # On a narrow Python build, the buffer for Unicode
-                # strings is UCS2, which doesn't match the buffer for
-                # NumPy Unicode types, which is ALWAYS UCS4.
-                # Therefore, we need to convert the buffer.  On Python
-                # 2.6 and later, we can use the utf_32 codec.  Earlier
-                # versions don't have that codec, so we convert to a
-                # numerical array that matches the input buffer, and
-                # then use NumPy to convert it to UCS4.  All of this
-                # should happen in native endianness.
-                obj = obj.encode('utf_32')
-            else:
-                obj = _unicode(obj)
-        else:
-            # Let the default Unicode -> string encoding (if any) take
-            # precedence.
-            obj = _bytes(obj)
+            itemsize = len(obj)
+        shape = len(obj) // itemsize
 
         return chararray(shape, itemsize=itemsize, unicode=unicode,
                          buffer=obj, order=order)
@@ -2744,7 +2720,7 @@ def array(obj, itemsize=None, copy=True, unicode=None, order=None):
                 (itemsize != obj.itemsize) or
                 (not unicode and isinstance(obj, unicode_)) or
                 (unicode and isinstance(obj, string_))):
-            obj = obj.astype((dtype, long(itemsize)))
+            obj = obj.astype((dtype, int(itemsize)))
         return obj
 
     if isinstance(obj, ndarray) and issubclass(obj.dtype.type, object):
index 3412c3fd5a7e16cebd666e8cef4aee59fd58c986..c46ae173d24d609298ccca8ec32d3ae0da107afb 100644 (file)
@@ -2,11 +2,9 @@
 Implementation of optimized einsum.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import itertools
+import operator
 
-from numpy.compat import basestring
 from numpy.core.multiarray import c_einsum
 from numpy.core.numeric import asanyarray, tensordot
 from numpy.core.overrides import array_function_dispatch
@@ -552,7 +550,7 @@ def _parse_einsum_input(operands):
     if len(operands) == 0:
         raise ValueError("No input operands")
 
-    if isinstance(operands[0], basestring):
+    if isinstance(operands[0], str):
         subscripts = operands[0].replace(" ", "")
         operands = [asanyarray(v) for v in operands[1:]]
 
@@ -579,11 +577,13 @@ def _parse_einsum_input(operands):
             for s in sub:
                 if s is Ellipsis:
                     subscripts += "..."
-                elif isinstance(s, int):
-                    subscripts += einsum_symbols[s]
                 else:
-                    raise TypeError("For this input type lists must contain "
-                                    "either int or Ellipsis")
+                    try:
+                        s = operator.index(s)
+                    except TypeError as e:
+                        raise TypeError("For this input type lists must contain "
+                                        "either int or Ellipsis") from e
+                    subscripts += einsum_symbols[s]
             if num != last:
                 subscripts += ","
 
@@ -592,11 +592,13 @@ def _parse_einsum_input(operands):
             for s in output_list:
                 if s is Ellipsis:
                     subscripts += "..."
-                elif isinstance(s, int):
-                    subscripts += einsum_symbols[s]
                 else:
-                    raise TypeError("For this input type lists must contain "
-                                    "either int or Ellipsis")
+                    try:
+                        s = operator.index(s)
+                    except TypeError as e:
+                        raise TypeError("For this input type lists must contain "
+                                        "either int or Ellipsis") from e
+                    subscripts += einsum_symbols[s]
     # Check for proper "->"
     if ("-" in subscripts) or (">" in subscripts):
         invalid = (subscripts.count("-") > 1) or (subscripts.count(">") > 1)
@@ -691,7 +693,7 @@ def _parse_einsum_input(operands):
     return (input_subscripts, output_subscript, operands)
 
 
-def _einsum_path_dispatcher(*operands, **kwargs):
+def _einsum_path_dispatcher(*operands, optimize=None, einsum_call=None):
     # NOTE: technically, we should only dispatch on array-like arguments, not
     # subscripts (given as strings). But separating operands into
     # arrays/subscripts is a little tricky/slow (given einsum's two supported
@@ -702,7 +704,7 @@ def _einsum_path_dispatcher(*operands, **kwargs):
 
 
 @array_function_dispatch(_einsum_path_dispatcher, module='numpy')
-def einsum_path(*operands, **kwargs):
+def einsum_path(*operands, optimize='greedy', einsum_call=False):
     """
     einsum_path(subscripts, *operands, optimize='greedy')
 
@@ -812,16 +814,8 @@ def einsum_path(*operands, **kwargs):
        5               defg,hd->efgh                               efgh->efgh
     """
 
-    # Make sure all keywords are valid
-    valid_contract_kwargs = ['optimize', 'einsum_call']
-    unknown_kwargs = [k for (k, v) in kwargs.items() if k
-                      not in valid_contract_kwargs]
-    if len(unknown_kwargs):
-        raise TypeError("Did not understand the following kwargs:"
-                        " %s" % unknown_kwargs)
-
     # Figure out what the path really is
-    path_type = kwargs.pop('optimize', True)
+    path_type = optimize
     if path_type is True:
         path_type = 'greedy'
     if path_type is None:
@@ -830,7 +824,7 @@ def einsum_path(*operands, **kwargs):
     memory_limit = None
 
     # No optimization or a named path algorithm
-    if (path_type is False) or isinstance(path_type, basestring):
+    if (path_type is False) or isinstance(path_type, str):
         pass
 
     # Given an explicit path
@@ -838,7 +832,7 @@ def einsum_path(*operands, **kwargs):
         pass
 
     # Path tuple with memory limit
-    elif ((len(path_type) == 2) and isinstance(path_type[0], basestring) and
+    elif ((len(path_type) == 2) and isinstance(path_type[0], str) and
             isinstance(path_type[1], (int, float))):
         memory_limit = int(path_type[1])
         path_type = path_type[0]
@@ -847,7 +841,7 @@ def einsum_path(*operands, **kwargs):
         raise TypeError("Did not understand the path: %s" % str(path_type))
 
     # Hidden option, only einsum should call this
-    einsum_call_arg = kwargs.pop("einsum_call", False)
+    einsum_call_arg = einsum_call
 
     # Python side parsing
     input_subscripts, output_subscript, operands = _parse_einsum_input(operands)
@@ -992,17 +986,16 @@ def einsum_path(*operands, **kwargs):
     return (path, path_print)
 
 
-def _einsum_dispatcher(*operands, **kwargs):
+def _einsum_dispatcher(*operands, out=None, optimize=None, **kwargs):
     # Arguably we dispatch on more arguments that we really should; see note in
     # _einsum_path_dispatcher for why.
-    for op in operands:
-        yield op
-    yield kwargs.get('out')
+    yield from operands
+    yield out
 
 
 # Rewrite einsum to handle different cases
 @array_function_dispatch(_einsum_dispatcher, module='numpy')
-def einsum(*operands, **kwargs):
+def einsum(*operands, out=None, optimize=False, **kwargs):
     """
     einsum(subscripts, *operands, out=None, dtype=None, order='K',
            casting='safe', optimize=False)
@@ -1347,39 +1340,29 @@ def einsum(*operands, **kwargs):
     ...     _ = np.einsum('ijk,ilm,njm,nlk,abc->',a,a,a,a,a, optimize=path)
 
     """
-
-    # Grab non-einsum kwargs; do not optimize by default.
-    optimize_arg = kwargs.pop('optimize', False)
+    # Special handling if out is specified
+    specified_out = out is not None
 
     # If no optimization, run pure einsum
-    if optimize_arg is False:
+    if optimize is False:
+        if specified_out:
+            kwargs['out'] = out
         return c_einsum(*operands, **kwargs)
 
-    valid_einsum_kwargs = ['out', 'dtype', 'order', 'casting']
-    einsum_kwargs = {k: v for (k, v) in kwargs.items() if
-                     k in valid_einsum_kwargs}
-
-    # Make sure all keywords are valid
-    valid_contract_kwargs = ['optimize'] + valid_einsum_kwargs
+    # Check the kwargs to avoid a more cryptic error later, without having to
+    # repeat default values here
+    valid_einsum_kwargs = ['dtype', 'order', 'casting']
     unknown_kwargs = [k for (k, v) in kwargs.items() if
-                      k not in valid_contract_kwargs]
-
+                      k not in valid_einsum_kwargs]
     if len(unknown_kwargs):
         raise TypeError("Did not understand the following kwargs: %s"
                         % unknown_kwargs)
 
-    # Special handeling if out is specified
-    specified_out = False
-    out_array = einsum_kwargs.pop('out', None)
-    if out_array is not None:
-        specified_out = True
 
     # Build the contraction list and operand
-    operands, contraction_list = einsum_path(*operands, optimize=optimize_arg,
+    operands, contraction_list = einsum_path(*operands, optimize=optimize,
                                              einsum_call=True)
 
-    handle_out = False
-
     # Start contraction loop
     for num, contraction in enumerate(contraction_list):
         inds, idx_rm, einsum_str, remaining, blas = contraction
@@ -1410,23 +1393,23 @@ def einsum(*operands, **kwargs):
             # Build a new view if needed
             if (tensor_result != results_index) or handle_out:
                 if handle_out:
-                    einsum_kwargs["out"] = out_array
-                new_view = c_einsum(tensor_result + '->' + results_index, new_view, **einsum_kwargs)
+                    kwargs["out"] = out
+                new_view = c_einsum(tensor_result + '->' + results_index, new_view, **kwargs)
 
         # Call einsum
         else:
             # If out was specified
             if handle_out:
-                einsum_kwargs["out"] = out_array
+                kwargs["out"] = out
 
             # Do the contraction
-            new_view = c_einsum(einsum_str, *tmp_operands, **einsum_kwargs)
+            new_view = c_einsum(einsum_str, *tmp_operands, **kwargs)
 
         # Append new items and dereference what we can
         operands.append(new_view)
         del tmp_operands, new_view
 
     if specified_out:
-        return out_array
+        return out
     else:
         return operands[0]
index d454480a8b47a4a1e6c45f5e850bff5b8e5c3321..285b753141caf10581567873c8d384527e8e596b 100644 (file)
@@ -1,14 +1,11 @@
 """Module containing non-deprecated functions borrowed from Numeric.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import functools
 import types
 import warnings
 
 import numpy as np
-from .. import VisibleDeprecationWarning
 from . import multiarray as mu
 from . import overrides
 from . import umath as um
@@ -255,7 +252,8 @@ def reshape(a, newshape, order='C'):
      >>> c.shape = (20)
      Traceback (most recent call last):
         ...
-     AttributeError: incompatible shape for a non-contiguous array
+     AttributeError: Incompatible shape for in-place modification. Use
+     `.reshape()` to make a copy with the desired shape.
 
     The `order` keyword gives the index ordering both for *fetching* the values
     from `a`, and then *placing* the values into the output array.
@@ -303,8 +301,7 @@ def reshape(a, newshape, order='C'):
 
 def _choose_dispatcher(a, choices, out=None, mode=None):
     yield a
-    for c in choices:
-        yield c
+    yield from choices
     yield out
 
 
@@ -604,15 +601,20 @@ def _transpose_dispatcher(a, axes=None):
 @array_function_dispatch(_transpose_dispatcher)
 def transpose(a, axes=None):
     """
-    Permute the dimensions of an array.
+    Reverse or permute the axes of an array; returns the modified array.
+
+    For an array a with two axes, transpose(a) gives the matrix transpose.
 
     Parameters
     ----------
     a : array_like
         Input array.
-    axes : list of ints, optional
-        By default, reverse the dimensions, otherwise permute the axes
-        according to the values given.
+    axes : tuple or list of ints, optional
+        If specified, it must be a tuple or list which contains a permutation of
+        [0,1,..,N-1] where N is the number of axes of a.  The i'th axis of the
+        returned array will correspond to the axis numbered ``axes[i]`` of the
+        input.  If not specified, defaults to ``range(a.ndim)[::-1]``, which
+        reverses the order of the axes.
 
     Returns
     -------
@@ -797,7 +799,7 @@ def argpartition(a, kth, axis=-1, kind='introselect', order=None):
     partition : Describes partition algorithms used.
     ndarray.partition : Inplace partition.
     argsort : Full indirect sort.
-    take_along_axis : Apply ``index_array`` from argpartition 
+    take_along_axis : Apply ``index_array`` from argpartition
                       to an array as if by calling partition.
 
     Notes
@@ -944,7 +946,7 @@ def sort(a, axis=-1, kind=None, order=None):
     'mergesort' and 'stable' are mapped to radix sort for integer data types. Radix sort is an
     O(n) sort instead of O(n log n).
 
-    .. versionchanged:: 1.17.0
+    .. versionchanged:: 1.18.0
 
     NaT now sorts to the end of arrays for consistency with NaN.
 
@@ -1039,7 +1041,7 @@ def argsort(a, axis=-1, kind=None, order=None):
     lexsort : Indirect stable sort with multiple keys.
     ndarray.sort : Inplace sort.
     argpartition : Indirect partial sort.
-    take_along_axis : Apply ``index_array`` from argsort 
+    take_along_axis : Apply ``index_array`` from argsort
                       to an array as if by calling sort.
 
     Notes
@@ -1136,7 +1138,7 @@ def argmax(a, axis=None, out=None):
     ndarray.argmax, argmin
     amax : The maximum value along a given axis.
     unravel_index : Convert a flat index into an index tuple.
-    take_along_axis : Apply ``np.expand_dims(index_array, axis)`` 
+    take_along_axis : Apply ``np.expand_dims(index_array, axis)``
                       from argmax to an array as if by calling max.
 
     Notes
@@ -1217,7 +1219,7 @@ def argmin(a, axis=None, out=None):
     ndarray.argmin, argmax
     amin : The minimum value along a given axis.
     unravel_index : Convert a flat index into an index tuple.
-    take_along_axis : Apply ``np.expand_dims(index_array, axis)`` 
+    take_along_axis : Apply ``np.expand_dims(index_array, axis)``
                       from argmin to an array as if by calling min.
 
     Notes
@@ -1444,7 +1446,8 @@ def squeeze(a, axis=None):
     squeezed : ndarray
         The input array, but with all or a subset of the
         dimensions of length 1 removed. This is always `a` itself
-        or a view into `a`.
+        or a view into `a`. Note that if all axes are squeezed,
+        the result is a 0d array and not a scalar.
 
     Raises
     ------
@@ -1471,6 +1474,15 @@ def squeeze(a, axis=None):
     ValueError: cannot select an axis to squeeze out which has size not equal to one
     >>> np.squeeze(x, axis=2).shape
     (1, 3)
+    >>> x = np.array([[1234]])
+    >>> x.shape
+    (1, 1)
+    >>> np.squeeze(x)
+    array(1234)  # 0d array
+    >>> np.squeeze(x).shape
+    ()
+    >>> np.squeeze(x)[()]
+    1234
 
     """
     try:
@@ -2028,7 +2040,8 @@ def clip(a, a_min, a_max, out=None, **kwargs):
     is specified, values smaller than 0 become 0, and values larger
     than 1 become 1.
 
-    Equivalent to but faster than ``np.maximum(a_min, np.minimum(a, a_max))``.
+    Equivalent to but faster than ``np.minimum(a_max, np.maximum(a, a_min))``.
+
     No check is performed to ensure ``a_min < a_max``.
 
     Parameters
@@ -2481,6 +2494,14 @@ def ptp(a, axis=None, out=None, keepdims=np._NoValue):
 
     The name of the function comes from the acronym for 'peak to peak'.
 
+    .. warning::
+        `ptp` preserves the data type of the array. This means the
+        return value for an input of signed integers with n bits
+        (e.g. `np.int8`, `np.int16`, etc) is also a signed integer
+        with n bits.  In that case, peak-to-peak values greater than
+        ``2**(n-1)-1`` will be returned as negative values. An example
+        with a work-around is shown below.
+
     Parameters
     ----------
     a : array_like
@@ -2518,16 +2539,33 @@ def ptp(a, axis=None, out=None, keepdims=np._NoValue):
 
     Examples
     --------
-    >>> x = np.arange(4).reshape((2,2))
-    >>> x
-    array([[0, 1],
-           [2, 3]])
+    >>> x = np.array([[4, 9, 2, 10],
+    ...               [6, 9, 7, 12]])
+
+    >>> np.ptp(x, axis=1)
+    array([8, 6])
 
     >>> np.ptp(x, axis=0)
-    array([2, 2])
+    array([2, 0, 5, 2])
 
-    >>> np.ptp(x, axis=1)
-    array([1, 1])
+    >>> np.ptp(x)
+    10
+
+    This example shows that a negative value can be returned when
+    the input is an array of signed integers.
+
+    >>> y = np.array([[1, 127],
+    ...               [0, 127],
+    ...               [-1, 127],
+    ...               [-2, 127]], dtype=np.int8)
+    >>> np.ptp(y, axis=1)
+    array([ 126,  127, -128, -127], dtype=int8)
+
+    A work-around is to use the `view()` method to view the result as
+    unsigned integers with the same bit width:
+
+    >>> np.ptp(y, axis=1).view(np.uint8)
+    array([126, 127, 128, 129], dtype=uint8)
 
     """
     kwargs = {}
index 538ac8b842a6aed1f57e3f9726ce25670b92308c..9e46f0ea5b4c9acecf2c2c3d3ee1a06fcf4a18a4 100644 (file)
@@ -1,13 +1,10 @@
-from __future__ import division, absolute_import, print_function
-
 import functools
 import warnings
 import operator
 import types
 
 from . import numeric as _nx
-from .numeric import (result_type, NaN, shares_memory, MAY_SHARE_BOUNDS,
-                      TooHardError, asanyarray, ndim)
+from .numeric import result_type, NaN, asanyarray, ndim
 from numpy.core.multiarray import add_docstring
 from numpy.core import overrides
 
@@ -113,13 +110,7 @@ def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None,
     >>> plt.show()
 
     """
-    try:
-        num = operator.index(num)
-    except TypeError:
-        raise TypeError(
-            "object of type {} cannot be safely interpreted as an integer."
-                .format(type(num)))
-
+    num = operator.index(num)
     if num < 0:
         raise ValueError("Number of samples, %s, must be non-negative." % num)
     div = (num - 1) if endpoint else num
index 31fa6b9bfafc7eb13d09b03f5433108685ecb328..e2ff493932d71b155fbe7e0cb6c1c01a47f18691 100644 (file)
@@ -1,8 +1,6 @@
 """Machine limits for Float32 and Float64 and (long double) if available...
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['finfo', 'iinfo']
 
 import warnings
@@ -31,12 +29,12 @@ def _fr1(a):
         a.shape = ()
     return a
 
-class MachArLike(object):
+class MachArLike:
     """ Object to simulate MachAr instance """
 
     def __init__(self,
                  ftype,
-                 **kwargs):
+                 *, eps, epsneg, huge, tiny, ibeta, **kwargs):
         params = _MACHAR_PARAMS[ftype]
         float_conv = lambda v: array([v], ftype)
         float_to_float = lambda v : _fr1(float_conv(v))
@@ -44,11 +42,11 @@ class MachArLike(object):
 
         self.title = params['title']
         # Parameter types same as for discovered MachAr object.
-        self.epsilon = self.eps = float_to_float(kwargs.pop('eps'))
-        self.epsneg = float_to_float(kwargs.pop('epsneg'))
-        self.xmax = self.huge = float_to_float(kwargs.pop('huge'))
-        self.xmin = self.tiny = float_to_float(kwargs.pop('tiny'))
-        self.ibeta = params['itype'](kwargs.pop('ibeta'))
+        self.epsilon = self.eps = float_to_float(eps)
+        self.epsneg = float_to_float(epsneg)
+        self.xmax = self.huge = float_to_float(huge)
+        self.xmin = self.tiny = float_to_float(tiny)
+        self.ibeta = params['itype'](ibeta)
         self.__dict__.update(kwargs)
         self.precision = int(-log10(self.eps))
         self.resolution = float_to_float(float_conv(10) ** (-self.precision))
@@ -291,7 +289,7 @@ def _discovered_machar(ftype):
 
 
 @set_module('numpy')
-class finfo(object):
+class finfo:
     """
     finfo(dtype)
 
@@ -302,12 +300,13 @@ class finfo(object):
     bits : int
         The number of bits occupied by the type.
     eps : float
-        The smallest representable positive number such that
-        ``1.0 + eps != 1.0``.  Type of `eps` is an appropriate floating
-        point type.
-    epsneg : floating point number of the appropriate type
-        The smallest representable positive number such that
-        ``1.0 - epsneg != 1.0``.
+        The difference between 1.0 and the next smallest representable float
+        larger than 1.0. For example, for 64-bit binary floats in the IEEE-754
+        standard, ``eps = 2**-52``, approximately 2.22e-16.
+    epsneg : float
+        The difference between 1.0 and the next smallest representable float
+        less than 1.0. For example, for 64-bit binary floats in the IEEE-754
+        standard, ``epsneg = 2**-53``, approximately 1.11e-16.
     iexp : int
         The number of bits in the exponent portion of the floating point
         representation.
@@ -350,6 +349,8 @@ class finfo(object):
     --------
     MachAr : The implementation of the tests that produce this information.
     iinfo : The equivalent for integer data types.
+    spacing : The distance between a value and the nearest adjacent number
+    nextafter : The next floating point value after x1 towards x2
 
     Notes
     -----
@@ -442,7 +443,7 @@ class finfo(object):
 
 
 @set_module('numpy')
-class iinfo(object):
+class iinfo:
     """
     iinfo(type)
 
index 64450e71321329f3d7a070d4eb9295d04d1f1cb4..42a0df76ac6155893072bc3d93cc1e83dd27b490 100644 (file)
@@ -135,7 +135,13 @@ typedef struct {
 } PyScalarObject;
 
 #define PyStringScalarObject PyStringObject
-#define PyUnicodeScalarObject PyUnicodeObject
+#define PyStringScalarObject PyStringObject
+typedef struct {
+        /* note that the PyObject_HEAD macro lives right here */
+        PyUnicodeObject base;
+        Py_UCS4 *obval;
+} PyUnicodeScalarObject;
+
 
 typedef struct {
         PyObject_VAR_HEAD
index 95e9cb0603bb9832a1d3903b1074bcbd9363511a..5ef1f10aa33a9219b561d7c334b7ccecb958b42e 100644 (file)
@@ -45,7 +45,6 @@ extern "C" {
 
 #define PyArray_CheckScalar(m) (PyArray_IsScalar(m, Generic) ||               \
                                 PyArray_IsZeroDim(m))
-#if PY_MAJOR_VERSION >= 3
 #define PyArray_IsPythonNumber(obj)                                           \
         (PyFloat_Check(obj) || PyComplex_Check(obj) ||                        \
          PyLong_Check(obj) || PyBool_Check(obj))
@@ -54,17 +53,6 @@ extern "C" {
 #define PyArray_IsPythonScalar(obj)                                           \
         (PyArray_IsPythonNumber(obj) || PyBytes_Check(obj) ||                 \
          PyUnicode_Check(obj))
-#else
-#define PyArray_IsPythonNumber(obj)                                           \
-        (PyInt_Check(obj) || PyFloat_Check(obj) || PyComplex_Check(obj) ||    \
-         PyLong_Check(obj) || PyBool_Check(obj))
-#define PyArray_IsIntegerScalar(obj) (PyInt_Check(obj)                        \
-              || PyLong_Check(obj)                                            \
-              || PyArray_IsScalar((obj), Integer))
-#define PyArray_IsPythonScalar(obj)                                           \
-        (PyArray_IsPythonNumber(obj) || PyString_Check(obj) ||                \
-         PyUnicode_Check(obj))
-#endif
 
 #define PyArray_IsAnyScalar(obj)                                              \
         (PyArray_IsScalar(obj, Generic) || PyArray_IsPythonScalar(obj))
@@ -226,7 +214,7 @@ PyArray_DiscardWritebackIfCopy(PyArrayObject *arr)
 /*
    Check to see if this key in the dictionary is the "title"
    entry of the tuple (i.e. a duplicate dictionary entry in the fields
-   dict.
+   dict).
 */
 
 static NPY_INLINE int
@@ -248,11 +236,6 @@ NPY_TITLE_KEY_check(PyObject *key, PyObject *value)
     if (PyUnicode_Check(title) && PyUnicode_Check(key)) {
         return PyUnicode_Compare(title, key) == 0 ? 1 : 0;
     }
-#if PY_VERSION_HEX < 0x03000000
-    if (PyString_Check(title) && PyString_Check(key)) {
-        return PyObject_Compare(title, key) == 0 ? 1 : 0;
-    }
-#endif
 #endif
     return 0;
 }
index ad98d562b78c4df2e8775ebf123aa1f9f9f138b5..5b7e8952e430802555d47b94df3f98bb52eb2748 100644 (file)
@@ -353,21 +353,12 @@ struct NpyAuxData_tag {
 
 #define NPY_USE_PYMEM 1
 
+
 #if NPY_USE_PYMEM == 1
-   /* numpy sometimes calls PyArray_malloc() with the GIL released. On Python
-      3.3 and older, it was safe to call PyMem_Malloc() with the GIL released.
-      On Python 3.4 and newer, it's better to use PyMem_RawMalloc() to be able
-      to use tracemalloc. On Python 3.6, calling PyMem_Malloc() with the GIL
-      released is now a fatal error in debug mode. */
-#  if PY_VERSION_HEX >= 0x03040000
-#    define PyArray_malloc PyMem_RawMalloc
-#    define PyArray_free PyMem_RawFree
-#    define PyArray_realloc PyMem_RawRealloc
-#  else
-#    define PyArray_malloc PyMem_Malloc
-#    define PyArray_free PyMem_Free
-#    define PyArray_realloc PyMem_Realloc
-#  endif
+/* use the Raw versions which are safe to call with the GIL released */
+#define PyArray_malloc PyMem_RawMalloc
+#define PyArray_free PyMem_RawFree
+#define PyArray_realloc PyMem_RawRealloc
 #else
 #define PyArray_malloc malloc
 #define PyArray_free free
@@ -1457,9 +1448,8 @@ PyArrayNeighborhoodIter_Next2D(PyArrayNeighborhoodIterObject* iter);
  * checking of correctness when working with these objects in C.
  */
 
-#define PyArray_ISONESEGMENT(m) (PyArray_NDIM(m) == 0 || \
-                             PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS) || \
-                             PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS))
+#define PyArray_ISONESEGMENT(m) (PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS) || \
+                                 PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS))
 
 #define PyArray_ISFORTRAN(m) (PyArray_CHKFLAGS(m, NPY_ARRAY_F_CONTIGUOUS) && \
                              (!PyArray_CHKFLAGS(m, NPY_ARRAY_C_CONTIGUOUS)))
index a6ee21219cc76242a567544745ae465467368599..4404580102a126630ab1ea5f62ef08a157f861c9 100644 (file)
 #define PyArray_DEFAULT NPY_DEFAULT_TYPE
 
 /* These DATETIME bits aren't used internally */
-#if PY_VERSION_HEX >= 0x03000000
 #define PyDataType_GetDatetimeMetaData(descr)                                 \
     ((descr->metadata == NULL) ? NULL :                                       \
         ((PyArray_DatetimeMetaData *)(PyCapsule_GetPointer(                   \
                 PyDict_GetItemString(                                         \
                     descr->metadata, NPY_METADATA_DTSTR), NULL))))
-#else
-#define PyDataType_GetDatetimeMetaData(descr)                                 \
-    ((descr->metadata == NULL) ? NULL :                                       \
-        ((PyArray_DatetimeMetaData *)(PyCObject_AsVoidPtr(                    \
-                PyDict_GetItemString(descr->metadata, NPY_METADATA_DTSTR)))))
-#endif
 
 /*
  * Deprecated as of NumPy 1.7, this kind of shortcut doesn't
index 832bc05995a328b418ec7f32dea69fddbf263d97..798da69572fde841eb351fd31261162e4e19f416 100644 (file)
 #include <Python.h>
 #include <stdio.h>
 
-#if PY_VERSION_HEX >= 0x03000000
 #ifndef NPY_PY3K
 #define NPY_PY3K 1
 #endif
-#endif
 
 #include "numpy/npy_common.h"
 #include "numpy/ndarrayobject.h"
@@ -45,6 +43,7 @@ static NPY_INLINE int PyInt_Check(PyObject *op) {
 #define PyInt_AsLong PyLong_AsLong
 #define PyInt_AS_LONG PyLong_AsLong
 #define PyInt_AsSsize_t PyLong_AsSsize_t
+#define PyNumber_Int PyNumber_Long
 
 /* NOTE:
  *
@@ -61,14 +60,16 @@ static NPY_INLINE int PyInt_Check(PyObject *op) {
     PySlice_GetIndicesEx((PySliceObject *)op, nop, start, end, step, slicelength)
 #endif
 
-/* <2.7.11 and <3.4.4 have the wrong argument type for Py_EnterRecursiveCall */
-#if (PY_VERSION_HEX < 0x02070B00) || \
-    ((0x03000000 <= PY_VERSION_HEX) && (PY_VERSION_HEX < 0x03040400))
-    #define Npy_EnterRecursiveCall(x) Py_EnterRecursiveCall((char *)(x))
-#else
-    #define Npy_EnterRecursiveCall(x) Py_EnterRecursiveCall(x)
+#if PY_VERSION_HEX < 0x030900a4
+    /* Introduced in https://github.com/python/cpython/commit/d2ec81a8c99796b51fb8c49b77a7fe369863226f */
+    #define Py_SET_TYPE(obj, typ) (Py_TYPE(obj) = typ)
+    /* Introduced in https://github.com/python/cpython/commit/b10dc3e7a11fcdb97e285882eba6da92594f90f9 */
+    #define Py_SET_SIZE(obj, size) (Py_SIZE(obj) = size)
 #endif
 
+
+#define Npy_EnterRecursiveCall(x) Py_EnterRecursiveCall(x)
+
 /* Py_SETREF was added in 3.5.2, and only if Py_LIMITED_API is absent */
 #if PY_VERSION_HEX < 0x03050200
     #define Py_SETREF(op, op2)                      \
@@ -79,6 +80,22 @@ static NPY_INLINE int PyInt_Check(PyObject *op) {
         } while (0)
 #endif
 
+/* introduced in https://github.com/python/cpython/commit/a24107b04c1277e3c1105f98aff5bfa3a98b33a0 */
+#if PY_VERSION_HEX < 0x030800A3
+    static NPY_INLINE PyObject *
+    _PyDict_GetItemStringWithError(PyObject *v, const char *key)
+    {
+        PyObject *kv, *rv;
+        kv = PyUnicode_FromString(key);
+        if (kv == NULL) {
+            return NULL;
+        }
+        rv = PyDict_GetItemWithError(v, kv);
+        Py_DECREF(kv);
+        return rv;
+    }
+#endif
+
 /*
  * PyString -> PyBytes
  */
@@ -489,8 +506,6 @@ PyObject_Cmp(PyObject *i1, PyObject *i2, int *cmp)
  * The main job here is to get rid of the improved error handling
  * of PyCapsules. It's a shame...
  */
-#if PY_VERSION_HEX >= 0x03000000
-
 static NPY_INLINE PyObject *
 NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *))
 {
@@ -535,43 +550,9 @@ NpyCapsule_Check(PyObject *ptr)
     return PyCapsule_CheckExact(ptr);
 }
 
-#else
-
-static NPY_INLINE PyObject *
-NpyCapsule_FromVoidPtr(void *ptr, void (*dtor)(void *))
-{
-    return PyCObject_FromVoidPtr(ptr, dtor);
-}
-
-static NPY_INLINE PyObject *
-NpyCapsule_FromVoidPtrAndDesc(void *ptr, void* context,
-        void (*dtor)(void *, void *))
-{
-    return PyCObject_FromVoidPtrAndDesc(ptr, context, dtor);
-}
-
-static NPY_INLINE void *
-NpyCapsule_AsVoidPtr(PyObject *ptr)
-{
-    return PyCObject_AsVoidPtr(ptr);
-}
-
-static NPY_INLINE void *
-NpyCapsule_GetDesc(PyObject *obj)
-{
-    return PyCObject_GetDesc(obj);
-}
-
-static NPY_INLINE int
-NpyCapsule_Check(PyObject *ptr)
-{
-    return PyCObject_Check(ptr);
-}
-
-#endif
-
 #ifdef __cplusplus
 }
 #endif
 
+
 #endif /* _NPY_3KCOMPAT_H_ */
index 27b83f7b57497e63f05f17bb38ae3991fc99118a..c2e7559581640998d1ba339fb18ced5e16e115bd 100644 (file)
@@ -369,18 +369,8 @@ typedef long npy_long;
 typedef float npy_float;
 typedef double npy_double;
 
-/*
- * Hash value compatibility.
- * As of Python 3.2 hash values are of type Py_hash_t.
- * Previous versions use C long.
- */
-#if PY_VERSION_HEX < 0x03020000
-typedef long npy_hash_t;
-#define NPY_SIZEOF_HASH_T NPY_SIZEOF_LONG
-#else
 typedef Py_hash_t npy_hash_t;
 #define NPY_SIZEOF_HASH_T NPY_SIZEOF_INTP
-#endif
 
 /*
  * Disabling C99 complex usage: a lot of C code in numpy/scipy rely on being
index 69e690f2893131bc5f09d3143204bcd98ef5c935..a07f495018f5decc779bb24916b664386dcb9a1d 100644 (file)
@@ -113,53 +113,6 @@ NPY_INLINE static float __npy_nzerof(void)
 #define NPY_SQRT2l    1.414213562373095048801688724209698079L /* sqrt(2) */
 #define NPY_SQRT1_2l  0.707106781186547524400844362104849039L /* 1/sqrt(2) */
 
-/*
- * Constants used in vector implementation of exp(x)
- */
-#define NPY_RINT_CVT_MAGICf 0x1.800000p+23f
-#define NPY_CODY_WAITE_LOGE_2_HIGHf -6.93145752e-1f
-#define NPY_CODY_WAITE_LOGE_2_LOWf -1.42860677e-6f
-#define NPY_COEFF_P0_EXPf 9.999999999980870924916e-01f
-#define NPY_COEFF_P1_EXPf 7.257664613233124478488e-01f
-#define NPY_COEFF_P2_EXPf 2.473615434895520810817e-01f
-#define NPY_COEFF_P3_EXPf 5.114512081637298353406e-02f
-#define NPY_COEFF_P4_EXPf 6.757896990527504603057e-03f
-#define NPY_COEFF_P5_EXPf 5.082762527590693718096e-04f
-#define NPY_COEFF_Q0_EXPf 1.000000000000000000000e+00f
-#define NPY_COEFF_Q1_EXPf -2.742335390411667452936e-01f
-#define NPY_COEFF_Q2_EXPf 2.159509375685829852307e-02f
-
-/*
- * Constants used in vector implementation of log(x)
- */
-#define NPY_COEFF_P0_LOGf 0.000000000000000000000e+00f
-#define NPY_COEFF_P1_LOGf 9.999999999999998702752e-01f
-#define NPY_COEFF_P2_LOGf 2.112677543073053063722e+00f
-#define NPY_COEFF_P3_LOGf 1.480000633576506585156e+00f
-#define NPY_COEFF_P4_LOGf 3.808837741388407920751e-01f
-#define NPY_COEFF_P5_LOGf 2.589979117907922693523e-02f
-#define NPY_COEFF_Q0_LOGf 1.000000000000000000000e+00f
-#define NPY_COEFF_Q1_LOGf 2.612677543073109236779e+00f
-#define NPY_COEFF_Q2_LOGf 2.453006071784736363091e+00f
-#define NPY_COEFF_Q3_LOGf 9.864942958519418960339e-01f
-#define NPY_COEFF_Q4_LOGf 1.546476374983906719538e-01f
-#define NPY_COEFF_Q5_LOGf 5.875095403124574342950e-03f
-/*
- * Constants used in vector implementation of sinf/cosf(x)
- */
-#define NPY_TWO_O_PIf 0x1.45f306p-1f
-#define NPY_CODY_WAITE_PI_O_2_HIGHf -0x1.921fb0p+00f
-#define NPY_CODY_WAITE_PI_O_2_MEDf -0x1.5110b4p-22f
-#define NPY_CODY_WAITE_PI_O_2_LOWf -0x1.846988p-48f
-#define NPY_COEFF_INVF0_COSINEf 0x1.000000p+00f
-#define NPY_COEFF_INVF2_COSINEf -0x1.000000p-01f
-#define NPY_COEFF_INVF4_COSINEf 0x1.55553cp-05f
-#define NPY_COEFF_INVF6_COSINEf -0x1.6c06dcp-10f
-#define NPY_COEFF_INVF8_COSINEf 0x1.98e616p-16f
-#define NPY_COEFF_INVF3_SINEf -0x1.555556p-03f
-#define NPY_COEFF_INVF5_SINEf 0x1.11119ap-07f
-#define NPY_COEFF_INVF7_SINEf -0x1.a06bbap-13f
-#define NPY_COEFF_INVF9_SINEf 0x1.7d3bbcp-19f
 /*
  * Integer functions.
  */
index 4bca82f9f5fc51046f8b4896cabed69d70cce34c..4df4ea43820cb571cb2c9efcad04ae10930f4492 100644 (file)
@@ -40,5 +40,6 @@
 #define NPY_1_16_API_VERSION 0x00000008
 #define NPY_1_17_API_VERSION 0x00000008
 #define NPY_1_18_API_VERSION 0x00000008
+#define NPY_1_19_API_VERSION 0x00000008
 
 #endif
index 5ff4a0041f151d83c39fbe1a69530e55bfb2fc3a..e5d8458429761f8d04d3fc8939f80a3258394442 100644 (file)
@@ -14,8 +14,8 @@ extern "C" {
  */
 typedef void (*PyUFuncGenericFunction)
             (char **args,
-             npy_intp *dimensions,
-             npy_intp *strides,
+             npy_intp const *dimensions,
+             npy_intp const *strides,
              void *innerloopdata);
 
 /*
index 202580bdb0649a6f3995c126f081df97f8423c41..a48dc3d50df48a71d3fa5b3d786c17e27beee2d0 100644 (file)
@@ -5,8 +5,6 @@ floating-point arithmetic system
 Author: Pearu Peterson, September 2003
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['MachAr']
 
 from numpy.core.fromnumeric import any
@@ -16,7 +14,7 @@ from numpy.core.overrides import set_module
 # Need to speed this up...especially for longfloat
 
 @set_module('numpy')
-class MachAr(object):
+class MachAr:
     """
     Diagnosing machine parameters.
 
index 062645551ed5e23265450a0f78a06febdc539e11..cb025736e1f8fa9df60251ddb977011166ef8b86 100644 (file)
@@ -1,9 +1,7 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from .numeric import uint8, ndarray, dtype
 from numpy.compat import (
-    long, basestring, os_fspath, contextlib_nullcontext, is_pathlib_path
+    os_fspath, contextlib_nullcontext, is_pathlib_path
 )
 from numpy.core.overrides import set_module
 
@@ -211,10 +209,12 @@ class memmap(ndarray):
         import os.path
         try:
             mode = mode_equivalents[mode]
-        except KeyError:
+        except KeyError as e:
             if mode not in valid_filemodes:
-                raise ValueError("mode must be one of %s" %
-                                 (valid_filemodes + list(mode_equivalents.keys())))
+                raise ValueError(
+                    "mode must be one of {!r} (got {!r})"
+                    .format(valid_filemodes + list(mode_equivalents.keys()), mode)
+                ) from None
 
         if mode == 'w+' and shape is None:
             raise ValueError("shape must be given")
@@ -244,7 +244,7 @@ class memmap(ndarray):
                 for k in shape:
                     size *= k
 
-            bytes = long(offset + size*_dbytes)
+            bytes = int(offset + size*_dbytes)
 
             if mode in ('w+', 'r+') and flen < bytes:
                 fid.seek(bytes - 1, 0)
@@ -273,7 +273,7 @@ class memmap(ndarray):
                 # special case - if we were constructed with a pathlib.path,
                 # then filename is a path object, not a string
                 self.filename = filename.resolve()
-            elif hasattr(fid, "name") and isinstance(fid.name, basestring):
+            elif hasattr(fid, "name") and isinstance(fid.name, str):
                 # py3 returns int for TemporaryFile().name
                 self.filename = os.path.abspath(fid.name)
             # same as memmap copies (e.g. memmap + 1)
index c0fcc10ffede3372a06bc42d2b63089e202b76f8..2cc2a8e710c1ffcb15be006202f93003910368a7 100644 (file)
@@ -7,17 +7,17 @@ by importing from the extension module.
 """
 
 import functools
-import sys
 import warnings
-import sys
 
 from . import overrides
 from . import _multiarray_umath
-import numpy as np
-from numpy.core._multiarray_umath import *
-from numpy.core._multiarray_umath import (
+from ._multiarray_umath import *  # noqa: F403
+# These imports are needed for backward compatibility,
+# do not change them. issue gh-15518
+# _get_ndarray_c_version is semi-public, on purpose not added to __all__
+from ._multiarray_umath import (
     _fastCopyAndTranspose, _flagdict, _insert, _reconstruct, _vec_string,
-    _ARRAY_API, _monotonicity, _get_ndarray_c_version
+    _ARRAY_API, _monotonicity, _get_ndarray_c_version, _set_madvise_hugepage,
     )
 
 __all__ = [
@@ -33,7 +33,7 @@ __all__ = [
     'digitize', 'dot', 'dragon4_positional', 'dragon4_scientific', 'dtype',
     'empty', 'empty_like', 'error', 'flagsobj', 'flatiter', 'format_longfloat',
     'frombuffer', 'fromfile', 'fromiter', 'fromstring', 'inner',
-    'int_asbuffer', 'interp', 'interp_complex', 'is_busday', 'lexsort',
+    'interp', 'interp_complex', 'is_busday', 'lexsort',
     'matmul', 'may_share_memory', 'min_scalar_type', 'ndarray', 'nditer',
     'nested_iters', 'normalize_axis_index', 'packbits',
     'promote_types', 'putmask', 'ravel_multi_index', 'result_type', 'scalar',
@@ -41,8 +41,6 @@ __all__ = [
     'set_string_function', 'set_typeDict', 'shares_memory', 'test_interrupt',
     'tracemalloc_domain', 'typeinfo', 'unpackbits', 'unravel_index', 'vdot',
     'where', 'zeros']
-if sys.version_info.major < 3:
-    __all__ += ['newbuffer', 'getbuffer']
 
 # For backward compatibility, make sure pickle imports these functions from here
 _reconstruct.__module__ = 'numpy.core.multiarray'
@@ -173,14 +171,15 @@ def concatenate(arrays, axis=None, out=None):
     array_split : Split an array into multiple sub-arrays of equal or
                   near-equal size.
     split : Split array into a list of multiple sub-arrays of equal size.
-    hsplit : Split array into multiple sub-arrays horizontally (column wise)
-    vsplit : Split array into multiple sub-arrays vertically (row wise)
+    hsplit : Split array into multiple sub-arrays horizontally (column wise).
+    vsplit : Split array into multiple sub-arrays vertically (row wise).
     dsplit : Split array into multiple sub-arrays along the 3rd axis (depth).
     stack : Stack a sequence of arrays along a new axis.
-    hstack : Stack arrays in sequence horizontally (column wise)
-    vstack : Stack arrays in sequence vertically (row wise)
-    dstack : Stack arrays in sequence depth wise (along third dimension)
     block : Assemble arrays from blocks.
+    hstack : Stack arrays in sequence horizontally (column wise).
+    vstack : Stack arrays in sequence vertically (row wise).
+    dstack : Stack arrays in sequence depth wise (along third dimension).
+    column_stack : Stack 1-D arrays as columns into a 2-D array.
 
     Notes
     -----
@@ -911,8 +910,9 @@ def bincount(x, weights=None, minlength=None):
 
     >>> np.bincount(np.arange(5, dtype=float))
     Traceback (most recent call last):
-      File "<stdin>", line 1, in <module>
-    TypeError: array cannot be safely cast to required type
+      ...
+    TypeError: Cannot cast array data from dtype('float64') to dtype('int64')
+    according to the rule 'safe'
 
     A possible use of ``bincount`` is to perform sums over
     variable-size chunks of an array, using the ``weights`` keyword.
@@ -1139,7 +1139,7 @@ def packbits(a, axis=None, bitorder='big'):
         ``None`` implies packing the flattened array.
     bitorder : {'big', 'little'}, optional
         The order of the input bits. 'big' will mimic bin(val),
-        ``[0, 0, 0, 0, 0, 0, 1, 1] => 3 = 0b00000011 => ``, 'little' will
+        ``[0, 0, 0, 0, 0, 0, 1, 1] => 3 = 0b00000011``, 'little' will
         reverse the order so ``[1, 1, 0, 0, 0, 0, 0, 0] => 3``.
         Defaults to 'big'.
 
@@ -1267,7 +1267,13 @@ def shares_memory(a, b, max_work=None):
     """
     shares_memory(a, b, max_work=None)
 
-    Determine if two arrays share memory
+    Determine if two arrays share memory.
+
+    .. warning::
+
+       This function can be exponentially slow for some inputs, unless
+       `max_work` is set to a finite number or ``MAY_SHARE_BOUNDS``.
+       If in doubt, use `numpy.may_share_memory` instead.
 
     Parameters
     ----------
@@ -1280,7 +1286,8 @@ def shares_memory(a, b, max_work=None):
 
         max_work=MAY_SHARE_EXACT  (default)
             The problem is solved exactly. In this case, the function returns
-            True only if there is an element shared between the arrays.
+            True only if there is an element shared between the arrays. Finding
+            the exact solution may take extremely long in some cases.
         max_work=MAY_SHARE_BOUNDS
             Only the memory bounds of a and b are checked.
 
@@ -1299,9 +1306,33 @@ def shares_memory(a, b, max_work=None):
 
     Examples
     --------
-    >>> np.may_share_memory(np.array([1,2]), np.array([5,8,9]))
+    >>> x = np.array([1, 2, 3, 4])
+    >>> np.shares_memory(x, np.array([5, 6, 7]))
+    False
+    >>> np.shares_memory(x[::2], x)
+    True
+    >>> np.shares_memory(x[::2], x[1::2])
     False
 
+    Checking whether two arrays share memory is NP-complete, and
+    runtime may increase exponentially in the number of
+    dimensions. Hence, `max_work` should generally be set to a finite
+    number, as it is possible to construct examples that take
+    extremely long to run:
+
+    >>> from numpy.lib.stride_tricks import as_strided
+    >>> x = np.zeros([192163377], dtype=np.int8)
+    >>> x1 = as_strided(x, strides=(36674, 61119, 85569), shape=(1049, 1049, 1049))
+    >>> x2 = as_strided(x[64023025:], strides=(12223, 12224, 1), shape=(1049, 1049, 1))
+    >>> np.shares_memory(x1, x2, max_work=1000)
+    Traceback (most recent call last):
+    ...
+    numpy.TooHardError: Exceeded max_work
+
+    Running ``np.shares_memory(x1, x2)`` without `max_work` set takes
+    around 1 minute for this case. It is possible to find problems
+    that take still significantly longer.
+
     """
     return (a, b)
 
index 1e011e2e73df54642f7f62820f76f59724a0836f..8bd4e241bcebe488e1ed42b182477d9d817e3f51 100644 (file)
@@ -1,15 +1,11 @@
-from __future__ import division, absolute_import, print_function
-
 import functools
 import itertools
 import operator
 import sys
 import warnings
 import numbers
-import contextlib
 
 import numpy as np
-from numpy.compat import pickle, basestring
 from . import multiarray
 from .multiarray import (
     _fastCopyAndTranspose as fastCopyAndTranspose, ALLOW_THREADS,
@@ -17,12 +13,10 @@ from .multiarray import (
     WRAP, arange, array, broadcast, can_cast, compare_chararrays,
     concatenate, copyto, dot, dtype, empty,
     empty_like, flatiter, frombuffer, fromfile, fromiter, fromstring,
-    inner, int_asbuffer, lexsort, matmul, may_share_memory,
+    inner, lexsort, matmul, may_share_memory,
     min_scalar_type, ndarray, nditer, nested_iters, promote_types,
     putmask, result_type, set_numeric_ops, shares_memory, vdot, where,
     zeros, normalize_axis_index)
-if sys.version_info[0] < 3:
-    from .multiarray import newbuffer, getbuffer
 
 from . import overrides
 from . import umath
@@ -39,12 +33,6 @@ bitwise_not = invert
 ufunc = type(sin)
 newaxis = None
 
-if sys.version_info[0] >= 3:
-    import builtins
-else:
-    import __builtin__ as builtins
-
-
 array_function_dispatch = functools.partial(
     overrides.array_function_dispatch, module='numpy')
 
@@ -52,7 +40,7 @@ array_function_dispatch = functools.partial(
 __all__ = [
     'newaxis', 'ndarray', 'flatiter', 'nditer', 'nested_iters', 'ufunc',
     'arange', 'array', 'zeros', 'count_nonzero', 'empty', 'broadcast', 'dtype',
-    'fromstring', 'fromfile', 'frombuffer', 'int_asbuffer', 'where',
+    'fromstring', 'fromfile', 'frombuffer', 'where',
     'argwhere', 'copyto', 'concatenate', 'fastCopyAndTranspose', 'lexsort',
     'set_numeric_ops', 'can_cast', 'promote_types', 'min_scalar_type',
     'result_type', 'isfortran', 'empty_like', 'zeros_like', 'ones_like',
@@ -67,9 +55,6 @@ __all__ = [
     'matmul', 'shares_memory', 'may_share_memory', 'MAY_SHARE_BOUNDS',
     'MAY_SHARE_EXACT', 'TooHardError', 'AxisError']
 
-if sys.version_info[0] < 3:
-    __all__.extend(['getbuffer', 'newbuffer'])
-
 
 @set_module('numpy')
 class ComplexWarning(RuntimeWarning):
@@ -289,7 +274,7 @@ def full(shape, fill_value, dtype=None, order='C'):
     ----------
     shape : int or sequence of ints
         Shape of the new array, e.g., ``(2, 3)`` or ``2``.
-    fill_value : scalar
+    fill_value : scalar or array_like
         Fill value.
     dtype : data-type, optional
         The desired data-type for the array  The default, None, means
@@ -319,6 +304,10 @@ def full(shape, fill_value, dtype=None, order='C'):
     array([[10, 10],
            [10, 10]])
 
+    >>> np.full((2, 2), [1, 2])
+    array([[1, 2],
+           [1, 2]])
+
     """
     if dtype is None:
         dtype = array(fill_value).dtype
@@ -395,12 +384,12 @@ def full_like(a, fill_value, dtype=None, order='K', subok=True, shape=None):
     return res
 
 
-def _count_nonzero_dispatcher(a, axis=None):
+def _count_nonzero_dispatcher(a, axis=None, *, keepdims=None):
     return (a,)
 
 
 @array_function_dispatch(_count_nonzero_dispatcher)
-def count_nonzero(a, axis=None):
+def count_nonzero(a, axis=None, *, keepdims=False):
     """
     Counts the number of non-zero values in the array ``a``.
 
@@ -425,6 +414,13 @@ def count_nonzero(a, axis=None):
 
         .. versionadded:: 1.12.0
 
+    keepdims : bool, optional
+        If this is set to True, the axes that are counted are left
+        in the result as dimensions with size one. With this option,
+        the result will broadcast correctly against the input array.
+
+        .. versionadded:: 1.19.0
+
     Returns
     -------
     count : int or array of int
@@ -440,15 +436,19 @@ def count_nonzero(a, axis=None):
     --------
     >>> np.count_nonzero(np.eye(4))
     4
-    >>> np.count_nonzero([[0,1,7,0,0],[3,0,0,2,19]])
+    >>> a = np.array([[0, 1, 7, 0],
+    ...               [3, 0, 2, 19]])
+    >>> np.count_nonzero(a)
     5
-    >>> np.count_nonzero([[0,1,7,0,0],[3,0,0,2,19]], axis=0)
-    array([1, 1, 1, 1, 1])
-    >>> np.count_nonzero([[0,1,7,0,0],[3,0,0,2,19]], axis=1)
+    >>> np.count_nonzero(a, axis=0)
+    array([1, 1, 2, 1])
+    >>> np.count_nonzero(a, axis=1)
     array([2, 3])
-
+    >>> np.count_nonzero(a, axis=1, keepdims=True)
+    array([[2],
+           [3]])
     """
-    if axis is None:
+    if axis is None and not keepdims:
         return multiarray.count_nonzero(a)
 
     a = asanyarray(a)
@@ -459,7 +459,7 @@ def count_nonzero(a, axis=None):
     else:
         a_bool = a.astype(np.bool_, copy=False)
 
-    return a_bool.sum(axis=axis, dtype=np.intp)
+    return a_bool.sum(axis=axis, dtype=np.intp, keepdims=keepdims)
 
 
 @set_module('numpy')
@@ -635,7 +635,7 @@ _mode_from_name_dict = {'v': 0,
 
 
 def _mode_from_name(mode):
-    if isinstance(mode, basestring):
+    if isinstance(mode, str):
         return _mode_from_name_dict[mode.lower()[0]]
     return mode
 
@@ -857,8 +857,11 @@ def outer(a, b, out=None):
     --------
     inner
     einsum : ``einsum('i,j->ij', a.ravel(), b.ravel())`` is the equivalent.
-    ufunc.outer : A generalization to N dimensions and other operations.
-                  ``np.multiply.outer(a.ravel(), b.ravel())`` is the equivalent.
+    ufunc.outer : A generalization to dimensions other than 1D and other
+                  operations. ``np.multiply.outer(a.ravel(), b.ravel())``
+                  is the equivalent.
+    tensordot : ``np.tensordot(a.ravel(), b.ravel(), axes=((), ()))``
+                is the equivalent.
 
     References
     ----------
@@ -1226,11 +1229,39 @@ def rollaxis(a, axis, start=0):
     a : ndarray
         Input array.
     axis : int
-        The axis to roll backwards.  The positions of the other axes do not
+        The axis to be rolled. The positions of the other axes do not
         change relative to one another.
     start : int, optional
-        The axis is rolled until it lies before this position.  The default,
-        0, results in a "complete" roll.
+        When ``start <= axis``, the axis is rolled back until it lies in
+        this position. When ``start > axis``, the axis is rolled until it
+        lies before this position. The default, 0, results in a "complete"
+        roll. The following table describes how negative values of ``start``
+        are interpreted:
+
+        .. table::
+           :align: left
+
+           +-------------------+----------------------+
+           |     ``start``     | Normalized ``start`` |
+           +===================+======================+
+           | ``-(arr.ndim+1)`` | raise ``AxisError``  |
+           +-------------------+----------------------+
+           | ``-arr.ndim``     | 0                    |
+           +-------------------+----------------------+
+           | |vdots|           | |vdots|              |
+           +-------------------+----------------------+
+           | ``-1``            | ``arr.ndim-1``       |
+           +-------------------+----------------------+
+           | ``0``             | ``0``                |
+           +-------------------+----------------------+
+           | |vdots|           | |vdots|              |
+           +-------------------+----------------------+
+           | ``arr.ndim``      | ``arr.ndim``         |
+           +-------------------+----------------------+
+           | ``arr.ndim + 1``  | raise ``AxisError``  |
+           +-------------------+----------------------+
+           
+        .. |vdots|   unicode:: U+22EE .. Vertical Ellipsis
 
     Returns
     -------
@@ -1723,7 +1754,7 @@ def indices(dimensions, dtype=int, sparse=False):
 
 
 @set_module('numpy')
-def fromfunction(function, shape, **kwargs):
+def fromfunction(function, shape, *, dtype=float, **kwargs):
     """
     Construct an array by executing a function over each coordinate.
 
@@ -1774,7 +1805,6 @@ def fromfunction(function, shape, **kwargs):
            [2, 3, 4]])
 
     """
-    dtype = kwargs.pop('dtype', float)
     args = indices(shape, dtype=dtype)
     return function(*args, **kwargs)
 
@@ -2280,12 +2310,12 @@ def isclose(a, b, rtol=1.e-5, atol=1.e-8, equal_nan=False):
         return cond[()]  # Flatten 0d arrays to scalars
 
 
-def _array_equal_dispatcher(a1, a2):
+def _array_equal_dispatcher(a1, a2, equal_nan=None):
     return (a1, a2)
 
 
 @array_function_dispatch(_array_equal_dispatcher)
-def array_equal(a1, a2):
+def array_equal(a1, a2, equal_nan=False):
     """
     True if two arrays have the same shape and elements, False otherwise.
 
@@ -2293,6 +2323,12 @@ def array_equal(a1, a2):
     ----------
     a1, a2 : array_like
         Input arrays.
+    equal_nan : bool
+        Whether to compare NaN's as equal. If the dtype of a1 and a2 is
+        complex, values will be considered equal if either the real or the
+        imaginary component of a given value is ``nan``.
+
+        .. versionadded:: 1.19.0
 
     Returns
     -------
@@ -2316,7 +2352,21 @@ def array_equal(a1, a2):
     False
     >>> np.array_equal([1, 2], [1, 4])
     False
+    >>> a = np.array([1, np.nan])
+    >>> np.array_equal(a, a)
+    False
+    >>> np.array_equal(a, a, equal_nan=True)
+    True
+
+    When ``equal_nan`` is True, complex values with nan components are
+    considered equal if either the real *or* the imaginary components are nan.
 
+    >>> a = np.array([1 + 1j])
+    >>> b = a.copy()
+    >>> a.real = np.nan
+    >>> b.imag = np.nan
+    >>> np.array_equal(a, b, equal_nan=True)
+    True
     """
     try:
         a1, a2 = asarray(a1), asarray(a2)
@@ -2324,7 +2374,15 @@ def array_equal(a1, a2):
         return False
     if a1.shape != a2.shape:
         return False
-    return bool(asarray(a1 == a2).all())
+    if not equal_nan:
+        return bool(asarray(a1 == a2).all())
+    # Handling NaN values if equal_nan is True
+    a1nan, a2nan = isnan(a1), isnan(a2)
+    # NaN's occur at different locations
+    if not (a1nan == a2nan).all():
+        return False
+    # Shapes of a1, a2 and masks are guaranteed to be consistent by this point
+    return bool(asarray(a1[~a1nan] == a2[~a1nan]).all())
 
 
 def _array_equiv_dispatcher(a1, a2):
index 761c7087caef91864b63dbd7eaa79711c755772f..aac7416126c545024730e767e3d8aaa2dd0d03b0 100644 (file)
@@ -79,14 +79,10 @@ Exported symbols include:
      \\-> object_ (not used much)               (kind=O)
 
 """
-from __future__ import division, absolute_import, print_function
-
 import types as _types
-import sys
 import numbers
 import warnings
 
-from numpy.compat import bytes, long
 from numpy.core.multiarray import (
         typeinfo, ndarray, array, empty, dtype, datetime_data,
         datetime_as_string, busday_offset, busday_count, is_busday,
@@ -122,11 +118,8 @@ from ._dtype import _kind_name
 
 # we don't export these for import *, but we do want them accessible
 # as numerictypes.bool, etc.
-if sys.version_info[0] >= 3:
-    from builtins import bool, int, float, complex, object, str
-    unicode = str
-else:
-    from __builtin__ import bool, int, float, complex, object, unicode, str
+from builtins import bool, int, float, complex, object, str, bytes
+from numpy.compat import long, unicode
 
 
 # We use this later
@@ -319,9 +312,11 @@ def issubclass_(arg1, arg2):
     Examples
     --------
     >>> np.issubclass_(np.int32, int)
-    False # True on Python 2.7
+    False
     >>> np.issubclass_(np.int32, float)
     False
+    >>> np.issubclass_(np.float64, float)
+    True
 
     """
     try:
@@ -392,35 +387,7 @@ def issubdtype(arg1, arg2):
     if not issubclass_(arg1, generic):
         arg1 = dtype(arg1).type
     if not issubclass_(arg2, generic):
-        arg2_orig = arg2
         arg2 = dtype(arg2).type
-        if not isinstance(arg2_orig, dtype):
-            # weird deprecated behaviour, that tried to infer np.floating from
-            # float, and similar less obvious things, such as np.generic from
-            # basestring
-            mro = arg2.mro()
-            arg2 = mro[1] if len(mro) > 1 else mro[0]
-
-            def type_repr(x):
-                """ Helper to produce clear error messages """
-                if not isinstance(x, type):
-                    return repr(x)
-                elif issubclass(x, generic):
-                    return "np.{}".format(x.__name__)
-                else:
-                    return x.__name__
-
-            # 1.14, 2017-08-01
-            warnings.warn(
-                "Conversion of the second argument of issubdtype from `{raw}` "
-                "to `{abstract}` is deprecated. In future, it will be treated "
-                "as `{concrete} == np.dtype({raw}).type`.".format(
-                    raw=type_repr(arg2_orig),
-                    abstract=type_repr(arg2),
-                    concrete=type_repr(dtype(arg2_orig).type)
-                ),
-                FutureWarning, stacklevel=2
-            )
 
     return issubclass(arg1, arg2)
 
index a1cad907562962feed2bd7a6013ee378cbfba665..7e1c0d591020bf2da838448eae46c9dc79a781c7 100644 (file)
@@ -33,9 +33,6 @@ Record arrays allow us to access fields as properties::
   array([2., 2.])
 
 """
-from __future__ import division, absolute_import, print_function
-
-import sys
 import os
 import warnings
 from collections import Counter, OrderedDict
@@ -43,7 +40,7 @@ from collections import Counter, OrderedDict
 from . import numeric as sb
 from . import numerictypes as nt
 from numpy.compat import (
-    isfileobj, bytes, long, unicode, os_fspath, contextlib_nullcontext
+    isfileobj, os_fspath, contextlib_nullcontext
 )
 from numpy.core.overrides import set_module
 from .arrayprint import get_printoptions
@@ -98,7 +95,7 @@ def find_duplicate(list):
 
 
 @set_module('numpy')
-class format_parser(object):
+class format_parser:
     """
     Class to convert formats, names, titles description to a dtype.
 
@@ -160,8 +157,7 @@ class format_parser(object):
     def __init__(self, formats, names, titles, aligned=False, byteorder=None):
         self._parseFormats(formats, aligned)
         self._setfieldnames(names, titles)
-        self._createdescr(byteorder)
-        self.dtype = self._descr
+        self._createdtype(byteorder)
 
     def _parseFormats(self, formats, aligned=False):
         """ Parse the field formats """
@@ -188,10 +184,10 @@ class format_parser(object):
         """convert input field names into a list and assign to the _names
         attribute """
 
-        if (names):
-            if (type(names) in [list, tuple]):
+        if names:
+            if type(names) in [list, tuple]:
                 pass
-            elif isinstance(names, (str, unicode)):
+            elif isinstance(names, str):
                 names = names.split(',')
             else:
                 raise NameError("illegal input names %s" % repr(names))
@@ -211,25 +207,28 @@ class format_parser(object):
         if _dup:
             raise ValueError("Duplicate field names: %s" % _dup)
 
-        if (titles):
+        if titles:
             self._titles = [n.strip() for n in titles[:self._nfields]]
         else:
             self._titles = []
             titles = []
 
-        if (self._nfields > len(titles)):
+        if self._nfields > len(titles):
             self._titles += [None] * (self._nfields - len(titles))
 
-    def _createdescr(self, byteorder):
-        descr = sb.dtype({'names':self._names,
-                          'formats':self._f_formats,
-                          'offsets':self._offsets,
-                          'titles':self._titles})
-        if (byteorder is not None):
+    def _createdtype(self, byteorder):
+        dtype = sb.dtype({
+            'names': self._names,
+            'formats': self._f_formats,
+            'offsets': self._offsets,
+            'titles': self._titles,
+        })
+        if byteorder is not None:
             byteorder = _byteorderconv[byteorder[0]]
-            descr = descr.newbyteorder(byteorder)
+            dtype = dtype.newbyteorder(byteorder)
+
+        self.dtype = dtype
 
-        self._descr = descr
 
 class record(nt.void):
     """A data-type scalar that allows field access as attribute lookup.
@@ -251,7 +250,7 @@ class record(nt.void):
         return super(record, self).__str__()
 
     def __getattribute__(self, attr):
-        if attr in ['setfield', 'getfield', 'dtype']:
+        if attr in ('setfield', 'getfield', 'dtype'):
             return nt.void.__getattribute__(self, attr)
         try:
             return nt.void.__getattribute__(self, attr)
@@ -276,7 +275,7 @@ class record(nt.void):
                     "attribute '%s'" % attr)
 
     def __setattr__(self, attr, val):
-        if attr in ['setfield', 'getfield', 'dtype']:
+        if attr in ('setfield', 'getfield', 'dtype'):
             raise AttributeError("Cannot set '%s' attribute" % attr)
         fielddict = nt.void.__getattribute__(self, 'dtype').fields
         res = fielddict.get(attr, None)
@@ -433,7 +432,7 @@ class recarray(ndarray):
         if dtype is not None:
             descr = sb.dtype(dtype)
         else:
-            descr = format_parser(formats, names, titles, aligned, byteorder)._descr
+            descr = format_parser(formats, names, titles, aligned, byteorder).dtype
 
         if buf is None:
             self = ndarray.__new__(subtype, shape, (record, descr), order=order)
@@ -534,8 +533,7 @@ class recarray(ndarray):
     def __repr__(self):
 
         repr_dtype = self.dtype
-        if (self.dtype.type is record
-                or (not issubclass(self.dtype.type, nt.void))):
+        if self.dtype.type is record or not issubclass(self.dtype.type, nt.void):
             # If this is a full record array (has numpy.record dtype),
             # or if it has a scalar (non-void) dtype with no records,
             # represent it using the rec.array function. Since rec.array
@@ -583,10 +581,44 @@ class recarray(ndarray):
             return self.setfield(val, *res)
 
 
+def _deprecate_shape_0_as_None(shape):
+    if shape == 0:
+        warnings.warn(
+            "Passing `shape=0` to have the shape be inferred is deprecated, "
+            "and in future will be equivalent to `shape=(0,)`. To infer "
+            "the shape and suppress this warning, pass `shape=None` instead.",
+            FutureWarning, stacklevel=3)
+        return None
+    else:
+        return shape
+
+
 def fromarrays(arrayList, dtype=None, shape=None, formats=None,
                names=None, titles=None, aligned=False, byteorder=None):
-    """ create a record array from a (flat) list of arrays
+    """Create a record array from a (flat) list of arrays
+
+    Parameters
+    ----------
+    arrayList : list or tuple
+        List of array-like objects (such as lists, tuples,
+        and ndarrays).
+    dtype : data-type, optional
+        valid dtype for all arrays
+    shape : int or tuple of ints, optional
+        Shape of the resulting array. If not provided, inferred from
+        ``arrayList[0]``.
+    formats, names, titles, aligned, byteorder :
+        If `dtype` is ``None``, these arguments are passed to
+        `numpy.format_parser` to construct a dtype. See that function for
+        detailed documentation.
 
+    Returns
+    -------
+    np.recarray
+        Record array consisting of given arrayList columns.
+
+    Examples
+    --------
     >>> x1=np.array([1,2,3,4])
     >>> x2=np.array(['a','dd','xyz','12'])
     >>> x3=np.array([1.1,2,3,4])
@@ -596,30 +628,39 @@ def fromarrays(arrayList, dtype=None, shape=None, formats=None,
     >>> x1[1]=34
     >>> r.a
     array([1, 2, 3, 4])
+    
+    >>> x1 = np.array([1, 2, 3, 4])
+    >>> x2 = np.array(['a', 'dd', 'xyz', '12'])
+    >>> x3 = np.array([1.1, 2, 3,4])
+    >>> r = np.core.records.fromarrays(
+    ...     [x1, x2, x3],
+    ...     dtype=np.dtype([('a', np.int32), ('b', 'S3'), ('c', np.float32)]))
+    >>> r
+    rec.array([(1, b'a', 1.1), (2, b'dd', 2. ), (3, b'xyz', 3. ),
+               (4, b'12', 4. )],
+              dtype=[('a', '<i4'), ('b', 'S3'), ('c', '<f4')])
     """
 
     arrayList = [sb.asarray(x) for x in arrayList]
 
-    if shape is None or shape == 0:
-        shape = arrayList[0].shape
+    # NumPy 1.19.0, 2020-01-01
+    shape = _deprecate_shape_0_as_None(shape)
 
-    if isinstance(shape, int):
+    if shape is None:
+        shape = arrayList[0].shape
+    elif isinstance(shape, int):
         shape = (shape,)
 
     if formats is None and dtype is None:
         # go through each object in the list to see if it is an ndarray
         # and determine the formats.
-        formats = []
-        for obj in arrayList:
-            formats.append(obj.dtype)
+        formats = [obj.dtype for obj in arrayList]
 
     if dtype is not None:
         descr = sb.dtype(dtype)
-        _names = descr.names
     else:
-        parsed = format_parser(formats, names, titles, aligned, byteorder)
-        _names = parsed._names
-        descr = parsed._descr
+        descr = format_parser(formats, names, titles, aligned, byteorder).dtype
+    _names = descr.names
 
     # Determine shape from data-type.
     if len(descr) != len(arrayList):
@@ -647,20 +688,33 @@ def fromarrays(arrayList, dtype=None, shape=None, formats=None,
 
 def fromrecords(recList, dtype=None, shape=None, formats=None, names=None,
                 titles=None, aligned=False, byteorder=None):
-    """ create a recarray from a list of records in text form
-
-        The data in the same field can be heterogeneous, they will be promoted
-        to the highest data type.  This method is intended for creating
-        smaller record arrays.  If used to create large array without formats
-        defined
+    """Create a recarray from a list of records in text form.
 
-        r=fromrecords([(2,3.,'abc')]*100000)
-
-        it can be slow.
+    Parameters
+    ----------
+    recList : sequence
+        data in the same field may be heterogeneous - they will be promoted
+        to the highest data type.
+    dtype : data-type, optional
+        valid dtype for all arrays
+    shape : int or tuple of ints, optional
+        shape of each array.
+    formats, names, titles, aligned, byteorder :
+        If `dtype` is ``None``, these arguments are passed to
+        `numpy.format_parser` to construct a dtype. See that function for
+        detailed documentation.
+
+        If both `formats` and `dtype` are None, then this will auto-detect
+        formats. Use list of tuples rather than list of lists for faster
+        processing.
 
-        If formats is None, then this will auto-detect formats. Use list of
-        tuples rather than list of lists for faster processing.
+    Returns
+    -------
+    np.recarray
+        record array consisting of given recList rows.
 
+    Examples
+    --------
     >>> r=np.core.records.fromrecords([(456,'dbe',1.2),(2,'de',1.3)],
     ... names='col1,col2,col3')
     >>> print(r[0])
@@ -684,14 +738,16 @@ def fromrecords(recList, dtype=None, shape=None, formats=None, names=None,
     if dtype is not None:
         descr = sb.dtype((record, dtype))
     else:
-        descr = format_parser(formats, names, titles, aligned, byteorder)._descr
+        descr = format_parser(formats, names, titles, aligned, byteorder).dtype
 
     try:
         retval = sb.array(recList, dtype=descr)
     except (TypeError, ValueError):
-        if (shape is None or shape == 0):
+        # NumPy 1.19.0, 2020-01-01
+        shape = _deprecate_shape_0_as_None(shape)
+        if shape is None:
             shape = len(recList)
-        if isinstance(shape, (int, long)):
+        if isinstance(shape, int):
             shape = (shape,)
         if len(shape) > 1:
             raise ValueError("Can only deal with 1-d array.")
@@ -716,8 +772,58 @@ def fromrecords(recList, dtype=None, shape=None, formats=None, names=None,
 
 def fromstring(datastring, dtype=None, shape=None, offset=0, formats=None,
                names=None, titles=None, aligned=False, byteorder=None):
-    """ create a (read-only) record array from binary data contained in
-    a string"""
+    r"""Create a record array from binary data
+
+    Note that despite the name of this function it does not accept `str`
+    instances.
+
+    Parameters
+    ----------
+    datastring : bytes-like
+        Buffer of binary data
+    dtype : data-type, optional
+        Valid dtype for all arrays
+    shape : int or tuple of ints, optional
+        Shape of each array.
+    offset : int, optional
+        Position in the buffer to start reading from.
+    formats, names, titles, aligned, byteorder :
+        If `dtype` is ``None``, these arguments are passed to
+        `numpy.format_parser` to construct a dtype. See that function for
+        detailed documentation.
+
+
+    Returns
+    -------
+    np.recarray
+        Record array view into the data in datastring. This will be readonly
+        if `datastring` is readonly.
+
+    See Also
+    --------
+    numpy.frombuffer
+
+    Examples
+    --------
+    >>> a = b'\x01\x02\x03abc'
+    >>> np.core.records.fromstring(a, dtype='u1,u1,u1,S3')
+    rec.array([(1, 2, 3, b'abc')],
+            dtype=[('f0', 'u1'), ('f1', 'u1'), ('f2', 'u1'), ('f3', 'S3')])
+
+    >>> grades_dtype = [('Name', (np.str_, 10)), ('Marks', np.float64),
+    ...                 ('GradeLevel', np.int32)]
+    >>> grades_array = np.array([('Sam', 33.3, 3), ('Mike', 44.4, 5),
+    ...                         ('Aadi', 66.6, 6)], dtype=grades_dtype)
+    >>> np.core.records.fromstring(grades_array.tobytes(), dtype=grades_dtype)
+    rec.array([('Sam', 33.3, 3), ('Mike', 44.4, 5), ('Aadi', 66.6, 6)],
+            dtype=[('Name', '<U10'), ('Marks', '<f8'), ('GradeLevel', '<i4')])
+
+    >>> s = '\x01\x02\x03abc'
+    >>> np.core.records.fromstring(s, dtype='u1,u1,u1,S3')
+    Traceback (most recent call last)
+       ...
+    TypeError: a bytes-like object is required, not 'str'
+    """
 
     if dtype is None and formats is None:
         raise TypeError("fromstring() needs a 'dtype' or 'formats' argument")
@@ -725,10 +831,14 @@ def fromstring(datastring, dtype=None, shape=None, offset=0, formats=None,
     if dtype is not None:
         descr = sb.dtype(dtype)
     else:
-        descr = format_parser(formats, names, titles, aligned, byteorder)._descr
+        descr = format_parser(formats, names, titles, aligned, byteorder).dtype
 
     itemsize = descr.itemsize
-    if (shape is None or shape == 0 or shape == -1):
+
+    # NumPy 1.19.0, 2020-01-01
+    shape = _deprecate_shape_0_as_None(shape)
+
+    if shape in (None, -1):
         shape = (len(datastring) - offset) // itemsize
 
     _array = recarray(shape, descr, buf=datastring, offset=offset)
@@ -747,10 +857,30 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None,
              names=None, titles=None, aligned=False, byteorder=None):
     """Create an array from binary file data
 
-    If file is a string or a path-like object then that file is opened,
-    else it is assumed to be a file object. The file object must
-    support random access (i.e. it must have tell and seek methods).
+    Parameters
+    ----------
+    fd : str or file type
+        If file is a string or a path-like object then that file is opened,
+        else it is assumed to be a file object. The file object must
+        support random access (i.e. it must have tell and seek methods).
+    dtype : data-type, optional
+        valid dtype for all arrays
+    shape : int or tuple of ints, optional
+        shape of each array.
+    offset : int, optional
+        Position in the file to start reading from.
+    formats, names, titles, aligned, byteorder :
+        If `dtype` is ``None``, these arguments are passed to
+        `numpy.format_parser` to construct a dtype. See that function for
+        detailed documentation
+
+    Returns
+    -------
+    np.recarray
+        record array consisting of data enclosed in file.
 
+    Examples
+    --------
     >>> from tempfile import TemporaryFile
     >>> a = np.empty(10,dtype='f8,i4,a5')
     >>> a[5] = (0.5,10,'abcde')
@@ -771,9 +901,12 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None,
     if dtype is None and formats is None:
         raise TypeError("fromfile() needs a 'dtype' or 'formats' argument")
 
-    if (shape is None or shape == 0):
+    # NumPy 1.19.0, 2020-01-01
+    shape = _deprecate_shape_0_as_None(shape)
+
+    if shape is None:
         shape = (-1,)
-    elif isinstance(shape, (int, long)):
+    elif isinstance(shape, int):
         shape = (shape,)
 
     if isfileobj(fd):
@@ -784,14 +917,14 @@ def fromfile(fd, dtype=None, shape=None, offset=0, formats=None,
         ctx = open(os_fspath(fd), 'rb')
 
     with ctx as fd:
-        if (offset > 0):
+        if offset > 0:
             fd.seek(offset, 1)
         size = get_remaining_size(fd)
 
         if dtype is not None:
             descr = sb.dtype(dtype)
         else:
-            descr = format_parser(formats, names, titles, aligned, byteorder)._descr
+            descr = format_parser(formats, names, titles, aligned, byteorder).dtype
 
         itemsize = descr.itemsize
 
@@ -823,7 +956,7 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None,
     """
 
     if ((isinstance(obj, (type(None), str)) or isfileobj(obj)) and
-           (formats is None) and (dtype is None)):
+           formats is None and dtype is None):
         raise ValueError("Must define formats (or dtype) if object is "
                          "None, string, or an open file")
 
@@ -832,7 +965,7 @@ def array(obj, dtype=None, shape=None, offset=0, strides=None, formats=None,
         dtype = sb.dtype(dtype)
     elif formats is not None:
         dtype = format_parser(formats, names, titles,
-                              aligned, byteorder)._descr
+                              aligned, byteorder).dtype
     else:
         kwds = {'formats': formats,
                 'names': names,
index 974ec4628c72127f65fd2ab4bf6a6cfddefce397..fcc4225459d62a3bf0cc32cb8a5ded093dd46f61 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, print_function
-
 import os
 import sys
 import pickle
@@ -16,7 +14,7 @@ from numpy._build_utils.apple_accelerate import (
     uses_accelerate_framework, get_sgemv_fix
     )
 from numpy.compat import npy_load_module
-from setup_common import *
+from setup_common import *  # noqa: F403
 
 # Set to True to enable relaxed strides checking. This (mostly) means
 # that `strides[dim]` is ignored if `shape[dim] == 1` when setting flags.
@@ -38,7 +36,7 @@ NPY_RELAXED_STRIDES_DEBUG = NPY_RELAXED_STRIDES_DEBUG and NPY_RELAXED_STRIDES_CH
 # Use pickle in all cases, as cPickle is gone in python3 and the difference
 # in time is only in build. -- Charles Harris, 2013-03-30
 
-class CallOnceOnly(object):
+class CallOnceOnly:
     def __init__(self):
         self._check_types = None
         self._check_ieee_macros = None
@@ -394,7 +392,7 @@ def visibility_define(config):
 
 def configuration(parent_package='',top_path=None):
     from numpy.distutils.misc_util import Configuration, dot_join
-    from numpy.distutils.system_info import get_info, dict_append
+    from numpy.distutils.system_info import get_info
 
     config = Configuration('core', parent_package, top_path)
     local_dir = config.local_path
@@ -469,10 +467,6 @@ def configuration(parent_package='',top_path=None):
                 moredefs.append('NPY_DO_NOT_OPTIMIZE_LONGLONG_right_shift')
                 moredefs.append('NPY_DO_NOT_OPTIMIZE_ULONGLONG_right_shift')
 
-            # Py3K check
-            if sys.version_info[0] >= 3:
-                moredefs.append(('NPY_PY3K', 1))
-
             # Generate the config.h file from moredefs
             with open(target, 'w') as target_f:
                 for d in moredefs:
@@ -526,7 +520,7 @@ def configuration(parent_package='',top_path=None):
     def generate_numpyconfig_h(ext, build_dir):
         """Depends on config.h: generate_config_h has to be called before !"""
         # put common include directory in build_dir on search path
-        # allows using code generation in headers headers
+        # allows using code generation in headers
         config.add_include_dirs(join(build_dir, "src", "common"))
         config.add_include_dirs(join(build_dir, "src", "npymath"))
 
@@ -751,6 +745,7 @@ def configuration(parent_package='',top_path=None):
             join('src', 'common', 'ucsnarrow.c'),
             join('src', 'common', 'ufunc_override.c'),
             join('src', 'common', 'numpyos.c'),
+            join('src', 'common', 'npy_cpu_features.c.src'),
             ]
 
     if os.environ.get('NPY_USE_BLAS_ILP64', "0") != "0":
@@ -904,7 +899,6 @@ def configuration(parent_package='',top_path=None):
             join('src', 'umath', 'clip.c.src'),
             join('src', 'umath', 'ufunc_object.c'),
             join('src', 'umath', 'extobj.c'),
-            join('src', 'umath', 'cpuid.c'),
             join('src', 'umath', 'scalarmath.c.src'),
             join('src', 'umath', 'ufunc_type_resolution.c'),
             join('src', 'umath', 'override.c'),
@@ -967,7 +961,7 @@ def configuration(parent_package='',top_path=None):
     config.add_extension('_operand_flag_tests',
                     sources=[join('src', 'umath', '_operand_flag_tests.c.src')])
 
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
     config.add_data_dir('tests/data')
 
     config.make_svn_version_py()
index 6356f08ba3070ade344302dd1bb39c9746aedd4c..63c4a76a9bc73c30778e67bfee3577ed6787d420 100644 (file)
@@ -1,10 +1,7 @@
-from __future__ import division, absolute_import, print_function
-
 # Code common to build tools
 import sys
 import warnings
 import copy
-import binascii
 import textwrap
 
 from numpy.distutils.misc_util import mingw32
@@ -135,11 +132,6 @@ OPTIONAL_INTRINSICS = [("__builtin_isnan", '5.'),
                        ("__builtin_bswap64", '5u'),
                        ("__builtin_expect", '5, 0'),
                        ("__builtin_mul_overflow", '5, 5, (int*)5'),
-                       # broken on OSX 10.11, make sure its not optimized away
-                       ("volatile int r = __builtin_cpu_supports", '"sse"',
-                        "stdio.h", "__BUILTIN_CPU_SUPPORTS"),
-                       ("volatile int r = __builtin_cpu_supports", '"avx512f"',
-                        "stdio.h", "__BUILTIN_CPU_SUPPORTS_AVX512F"),
                        # MMX only needed for icc, but some clangs don't have it
                        ("_m_from_int64", '0', "emmintrin.h"),
                        ("_mm_load_ps", '(float*)0', "xmmintrin.h"),  # SSE
@@ -246,9 +238,9 @@ def check_long_double_representation(cmd):
     # Disable multi-file interprocedural optimization in the Intel compiler on Linux
     # which generates intermediary object files and prevents checking the
     # float representation.
-    elif (sys.platform != "win32" 
-            and cmd.compiler.compiler_type.startswith('intel') 
-            and '-ipo' in cmd.compiler.cc_exe):        
+    elif (sys.platform != "win32"
+            and cmd.compiler.compiler_type.startswith('intel')
+            and '-ipo' in cmd.compiler.cc_exe):
         newcompiler = cmd.compiler.cc_exe.replace(' -ipo', '')
         cmd.compiler.set_executables(
             compiler=newcompiler,
@@ -313,32 +305,15 @@ def pyod(filename):
     We only implement enough to get the necessary information for long double
     representation, this is not intended as a compatible replacement for od.
     """
-    def _pyod2():
-        out = []
-
-        with open(filename, 'rb') as fid:
-            yo = [int(oct(int(binascii.b2a_hex(o), 16))) for o in fid.read()]
-        for i in range(0, len(yo), 16):
-            line = ['%07d' % int(oct(i))]
-            line.extend(['%03d' % c for c in yo[i:i+16]])
-            out.append(" ".join(line))
-        return out
-
-    def _pyod3():
-        out = []
-
-        with open(filename, 'rb') as fid:
-            yo2 = [oct(o)[2:] for o in fid.read()]
-        for i in range(0, len(yo2), 16):
-            line = ['%07d' % int(oct(i)[2:])]
-            line.extend(['%03d' % int(c) for c in yo2[i:i+16]])
-            out.append(" ".join(line))
-        return out
-
-    if sys.version_info[0] < 3:
-        return _pyod2()
-    else:
-        return _pyod3()
+    out = []
+    with open(filename, 'rb') as fid:
+        yo2 = [oct(o)[2:] for o in fid.read()]
+    for i in range(0, len(yo2), 16):
+        line = ['%07d' % int(oct(i)[2:])]
+        line.extend(['%03d' % int(c) for c in yo2[i:i+16]])
+        out.append(" ".join(line))
+    return out
+
 
 _BEFORE_SEQ = ['000', '000', '000', '000', '000', '000', '000', '000',
               '001', '043', '105', '147', '211', '253', '315', '357']
index 31b1c20b974c0b11931e7be401fecf9bfc33cc9a..7a76bbf9dc15312eddd7fd58903c01c66333e4c0 100644 (file)
@@ -1,9 +1,8 @@
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['atleast_1d', 'atleast_2d', 'atleast_3d', 'block', 'hstack',
            'stack', 'vstack']
 
 import functools
+import itertools
 import operator
 import warnings
 
@@ -248,12 +247,13 @@ def vstack(tup):
 
     See Also
     --------
+    concatenate : Join a sequence of arrays along an existing axis.
     stack : Join a sequence of arrays along a new axis.
+    block : Assemble an nd-array from nested lists of blocks.
     hstack : Stack arrays in sequence horizontally (column wise).
-    dstack : Stack arrays in sequence depth wise (along third dimension).
-    concatenate : Join a sequence of arrays along an existing axis.
-    vsplit : Split array into a list of multiple sub-arrays vertically.
-    block : Assemble arrays from blocks.
+    dstack : Stack arrays in sequence depth wise (along third axis).
+    column_stack : Stack 1-D arrays as columns into a 2-D array.
+    vsplit : Split an array into multiple sub-arrays vertically (row-wise).
 
     Examples
     --------
@@ -310,12 +310,13 @@ def hstack(tup):
 
     See Also
     --------
+    concatenate : Join a sequence of arrays along an existing axis.
     stack : Join a sequence of arrays along a new axis.
+    block : Assemble an nd-array from nested lists of blocks.
     vstack : Stack arrays in sequence vertically (row wise).
     dstack : Stack arrays in sequence depth wise (along third axis).
-    concatenate : Join a sequence of arrays along an existing axis.
-    hsplit : Split array along second axis.
-    block : Assemble arrays from blocks.
+    column_stack : Stack 1-D arrays as columns into a 2-D array.
+    hsplit : Split an array into multiple sub-arrays horizontally (column-wise).
 
     Examples
     --------
@@ -386,8 +387,8 @@ def stack(arrays, axis=0, out=None):
     See Also
     --------
     concatenate : Join a sequence of arrays along an existing axis.
+    block : Assemble an nd-array from nested lists of blocks.
     split : Split array into a list of multiple sub-arrays of equal size.
-    block : Assemble arrays from blocks.
 
     Examples
     --------
@@ -532,14 +533,7 @@ def _atleast_nd(a, ndim):
 
 
 def _accumulate(values):
-    # Helper function because Python 2.7 doesn't have
-    # itertools.accumulate
-    value = 0
-    accumulated = []
-    for v in values:
-        value += v
-        accumulated.append(value)
-    return accumulated
+    return list(itertools.accumulate(values))
 
 
 def _concatenate_shapes(shapes, axis):
@@ -678,8 +672,7 @@ def _block_dispatcher(arrays):
     # tuple. Also, we know that list.__array_function__ will never exist.
     if type(arrays) is list:
         for subarrays in arrays:
-            for subarray in _block_dispatcher(subarrays):
-                yield subarray
+            yield from _block_dispatcher(subarrays)
     else:
         yield arrays
 
@@ -732,12 +725,13 @@ def block(arrays):
 
     See Also
     --------
-    concatenate : Join a sequence of arrays together.
-    stack : Stack arrays in sequence along a new dimension.
-    hstack : Stack arrays in sequence horizontally (column wise).
+    concatenate : Join a sequence of arrays along an existing axis.
+    stack : Join a sequence of arrays along a new axis.
     vstack : Stack arrays in sequence vertically (row wise).
-    dstack : Stack arrays in sequence depth wise (along third dimension).
-    vsplit : Split array into a list of multiple sub-arrays vertically.
+    hstack : Stack arrays in sequence horizontally (column wise).
+    dstack : Stack arrays in sequence depth wise (along third axis).
+    column_stack : Stack 1-D arrays as columns into a 2-D array.
+    vsplit : Split an array into multiple sub-arrays vertically (row-wise).
 
     Notes
     -----
index 0ac1b01c6f4c766589172d24ac40ec2bc6f2d878..d626d12608cb9f0e90cc9ea153c017065a7525cd 100644 (file)
@@ -27,9 +27,9 @@
 
 /* See array_assign.h for parameter documentation */
 NPY_NO_EXPORT int
-broadcast_strides(int ndim, npy_intp *shape,
-                int strides_ndim, npy_intp *strides_shape, npy_intp *strides,
-                char *strides_name,
+broadcast_strides(int ndim, npy_intp const *shape,
+                int strides_ndim, npy_intp const *strides_shape, npy_intp const *strides,
+                char const *strides_name,
                 npy_intp *out_strides)
 {
     int idim, idim_start = ndim - strides_ndim;
@@ -84,8 +84,8 @@ broadcast_error: {
 
 /* See array_assign.h for parameter documentation */
 NPY_NO_EXPORT int
-raw_array_is_aligned(int ndim, npy_intp *shape,
-                     char *data, npy_intp *strides, int alignment)
+raw_array_is_aligned(int ndim, npy_intp const *shape,
+                     char *data, npy_intp const *strides, int alignment)
 {
 
     /*
index 69ef56bb4a8c9eac8eab963d128c36ab270459e6..f5d884dd9981d7f2eb6b6db196dd90071447d99a 100644 (file)
@@ -44,8 +44,8 @@ PyArray_AssignRawScalar(PyArrayObject *dst,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-raw_array_assign_scalar(int ndim, npy_intp *shape,
-        PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
+raw_array_assign_scalar(int ndim, npy_intp const *shape,
+        PyArray_Descr *dst_dtype, char *dst_data, npy_intp const *dst_strides,
         PyArray_Descr *src_dtype, char *src_data);
 
 /*
@@ -55,11 +55,11 @@ raw_array_assign_scalar(int ndim, npy_intp *shape,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-raw_array_wheremasked_assign_scalar(int ndim, npy_intp *shape,
-        PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
+raw_array_wheremasked_assign_scalar(int ndim, npy_intp const *shape,
+        PyArray_Descr *dst_dtype, char *dst_data, npy_intp const *dst_strides,
         PyArray_Descr *src_dtype, char *src_data,
         PyArray_Descr *wheremask_dtype, char *wheremask_data,
-        npy_intp *wheremask_strides);
+        npy_intp const *wheremask_strides);
 
 /******** LOW-LEVEL ARRAY MANIPULATION HELPERS ********/
 
@@ -80,9 +80,9 @@ raw_array_wheremasked_assign_scalar(int ndim, npy_intp *shape,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-broadcast_strides(int ndim, npy_intp *shape,
-                int strides_ndim, npy_intp *strides_shape, npy_intp *strides,
-                char *strides_name,
+broadcast_strides(int ndim, npy_intp const *shape,
+                int strides_ndim, npy_intp const *strides_shape, npy_intp const *strides,
+                char const *strides_name,
                 npy_intp *out_strides);
 
 /*
@@ -93,8 +93,8 @@ broadcast_strides(int ndim, npy_intp *shape,
  * cannot-be-aligned, in which case 0 (false) is always returned.
  */
 NPY_NO_EXPORT int
-raw_array_is_aligned(int ndim, npy_intp *shape,
-                     char *data, npy_intp *strides, int alignment);
+raw_array_is_aligned(int ndim, npy_intp const *shape,
+                     char *data, npy_intp const *strides, int alignment);
 
 /*
  * Checks if an array is aligned to its "true alignment"
index d3401aea6ff14b1ce067f32759f7446d9c55e6db..8b7cf1c5be363585b3617b7d09571065a9c607f2 100644 (file)
@@ -7,9 +7,6 @@ _is_basic_python_type(PyTypeObject *tp)
     return (
         /* Basic number types */
         tp == &PyBool_Type ||
-#if !defined(NPY_PY3K)
-        tp == &PyInt_Type ||
-#endif
         tp == &PyLong_Type ||
         tp == &PyFloat_Type ||
         tp == &PyComplex_Type ||
@@ -22,9 +19,6 @@ _is_basic_python_type(PyTypeObject *tp)
         tp == &PyFrozenSet_Type ||
         tp == &PyUnicode_Type ||
         tp == &PyBytes_Type ||
-#if !defined(NPY_PY3K)
-        tp == &PyString_Type ||
-#endif
 
         /* other builtins */
         tp == &PySlice_Type ||
@@ -50,25 +44,21 @@ _is_basic_python_type(PyTypeObject *tp)
  * there is no such attribute, and NULL with an exception on failure.
  */
 static NPY_INLINE PyObject *
-maybe_get_attr(PyObject *obj, char *name)
+maybe_get_attr(PyObject *obj, char const *name)
 {
     PyTypeObject *tp = Py_TYPE(obj);
     PyObject *res = (PyObject *)NULL;
 
     /* Attribute referenced by (char *)name */
     if (tp->tp_getattr != NULL) {
-        res = (*tp->tp_getattr)(obj, name);
+        res = (*tp->tp_getattr)(obj, (char *)name);
         if (res == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
             PyErr_Clear();
         }
     }
     /* Attribute referenced by (PyObject *)name */
     else if (tp->tp_getattro != NULL) {
-#if defined(NPY_PY3K)
         PyObject *w = PyUnicode_InternFromString(name);
-#else
-        PyObject *w = PyString_InternFromString(name);
-#endif
         if (w == NULL) {
             return (PyObject *)NULL;
         }
@@ -91,7 +81,7 @@ maybe_get_attr(PyObject *obj, char *name)
  * In future, could be made more like _Py_LookupSpecial
  */
 static NPY_INLINE PyObject *
-PyArray_LookupSpecial(PyObject *obj, char *name)
+PyArray_LookupSpecial(PyObject *obj, char const *name)
 {
     PyTypeObject *tp = Py_TYPE(obj);
 
@@ -111,7 +101,7 @@ PyArray_LookupSpecial(PyObject *obj, char *name)
  * Kept for backwards compatibility. In future, we should deprecate this.
  */
 static NPY_INLINE PyObject *
-PyArray_LookupSpecial_OnInstance(PyObject *obj, char *name)
+PyArray_LookupSpecial_OnInstance(PyObject *obj, char const *name)
 {
     PyTypeObject *tp = Py_TYPE(obj);
 
index bacd274732484e14d58849302d1957c17ade1b11..f2f12a55b17329a2f76cba095452906bb022a850 100644 (file)
@@ -306,30 +306,30 @@ PyArray_CastRawArrays(npy_intp count,
 NPY_NO_EXPORT npy_intp
 PyArray_TransferNDimToStrided(npy_intp ndim,
                 char *dst, npy_intp dst_stride,
-                char *src, npy_intp *src_strides, npy_intp src_strides_inc,
-                npy_intp *coords, npy_intp coords_inc,
-                npy_intp *shape, npy_intp shape_inc,
+                char *src, npy_intp const *src_strides, npy_intp src_strides_inc,
+                npy_intp const *coords, npy_intp coords_inc,
+                npy_intp const *shape, npy_intp shape_inc,
                 npy_intp count, npy_intp src_itemsize,
                 PyArray_StridedUnaryOp *stransfer,
                 NpyAuxData *transferdata);
 
 NPY_NO_EXPORT npy_intp
 PyArray_TransferStridedToNDim(npy_intp ndim,
-                char *dst, npy_intp *dst_strides, npy_intp dst_strides_inc,
+                char *dst, npy_intp const *dst_strides, npy_intp dst_strides_inc,
                 char *src, npy_intp src_stride,
-                npy_intp *coords, npy_intp coords_inc,
-                npy_intp *shape, npy_intp shape_inc,
+                npy_intp const *coords, npy_intp coords_inc,
+                npy_intp const *shape, npy_intp shape_inc,
                 npy_intp count, npy_intp src_itemsize,
                 PyArray_StridedUnaryOp *stransfer,
                 NpyAuxData *transferdata);
 
 NPY_NO_EXPORT npy_intp
 PyArray_TransferMaskedStridedToNDim(npy_intp ndim,
-                char *dst, npy_intp *dst_strides, npy_intp dst_strides_inc,
+                char *dst, npy_intp const *dst_strides, npy_intp dst_strides_inc,
                 char *src, npy_intp src_stride,
                 npy_bool *mask, npy_intp mask_stride,
-                npy_intp *coords, npy_intp coords_inc,
-                npy_intp *shape, npy_intp shape_inc,
+                npy_intp const *coords, npy_intp coords_inc,
+                npy_intp const *shape, npy_intp shape_inc,
                 npy_intp count, npy_intp src_itemsize,
                 PyArray_MaskedStridedUnaryOp *stransfer,
                 NpyAuxData *data);
@@ -365,8 +365,8 @@ mapiter_set(PyArrayMapIterObject *mit);
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-PyArray_PrepareOneRawArrayIter(int ndim, npy_intp *shape,
-                            char *data, npy_intp *strides,
+PyArray_PrepareOneRawArrayIter(int ndim, npy_intp const *shape,
+                            char *data, npy_intp const *strides,
                             int *out_ndim, npy_intp *out_shape,
                             char **out_data, npy_intp *out_strides);
 
@@ -387,9 +387,9 @@ PyArray_PrepareOneRawArrayIter(int ndim, npy_intp *shape,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-PyArray_PrepareTwoRawArrayIter(int ndim, npy_intp *shape,
-                            char *dataA, npy_intp *stridesA,
-                            char *dataB, npy_intp *stridesB,
+PyArray_PrepareTwoRawArrayIter(int ndim, npy_intp const *shape,
+                            char *dataA, npy_intp const *stridesA,
+                            char *dataB, npy_intp const *stridesB,
                             int *out_ndim, npy_intp *out_shape,
                             char **out_dataA, npy_intp *out_stridesA,
                             char **out_dataB, npy_intp *out_stridesB);
@@ -411,10 +411,10 @@ PyArray_PrepareTwoRawArrayIter(int ndim, npy_intp *shape,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-PyArray_PrepareThreeRawArrayIter(int ndim, npy_intp *shape,
-                            char *dataA, npy_intp *stridesA,
-                            char *dataB, npy_intp *stridesB,
-                            char *dataC, npy_intp *stridesC,
+PyArray_PrepareThreeRawArrayIter(int ndim, npy_intp const *shape,
+                            char *dataA, npy_intp const *stridesA,
+                            char *dataB, npy_intp const *stridesB,
+                            char *dataC, npy_intp const *stridesC,
                             int *out_ndim, npy_intp *out_shape,
                             char **out_dataA, npy_intp *out_stridesA,
                             char **out_dataB, npy_intp *out_stridesB,
@@ -638,7 +638,7 @@ npy_bswap8_unaligned(char * x)
  *
  * Here is example code for a single array:
  *
- *      if (PyArray_TRIVIALLY_ITERABLE(self) {
+ *      if (PyArray_TRIVIALLY_ITERABLE(self)) {
  *          char *data;
  *          npy_intp count, stride;
  *
@@ -656,7 +656,7 @@ npy_bswap8_unaligned(char * x)
  *
  * Here is example code for a pair of arrays:
  *
- *      if (PyArray_TRIVIALLY_ITERABLE_PAIR(a1, a2) {
+ *      if (PyArray_TRIVIALLY_ITERABLE_PAIR(a1, a2)) {
  *          char *data1, *data2;
  *          npy_intp count, stride1, stride2;
  *
index 21db1893b3d10c0282e7af96ca6045846e6b969a..9da33bfc1f76fac81e528ad27e104b6f3f2668ce 100644 (file)
   ends up considering all values x3=0...5 separately.
 
   The upper bound for work done is prod(shape_a)*prod(shape_b), which scales
-  faster than than work done by binary ufuncs, after broadcasting,
+  faster than work done by binary ufuncs, after broadcasting,
   prod(shape_a). The bound may be loose, but it is possible to construct hard
   instances where ufunc is faster (adapted from [2,3])::
 
index eedfbe364923ed0b6a663be39b4f7a5624977205..aebe241a56940b3d1643a9b02379a8166be5e8fd 100644 (file)
@@ -2,6 +2,7 @@
 #define _NPY_NPY_CONFIG_H_
 
 #include "config.h"
+#include "npy_cpu_features.h"
 #include "numpy/numpyconfig.h"
 #include "numpy/npy_cpu.h"
 #include "numpy/npy_os.h"
diff --git a/numpy/core/src/common/npy_cpu_features.c.src b/numpy/core/src/common/npy_cpu_features.c.src
new file mode 100644 (file)
index 0000000..e7faea5
--- /dev/null
@@ -0,0 +1,421 @@
+#include "npy_cpu_features.h"
+#include "numpy/npy_common.h" // for NPY_INLINE
+#include "numpy/npy_cpu.h" // To guarantee of having CPU definitions in scope.
+
+/******************** Private Definitions *********************/
+
+// Hold all CPU features boolean values
+static unsigned char npy__cpu_have[NPY_CPU_FEATURE_MAX];
+
+/******************** Private Declarations *********************/
+
+// Almost detect all CPU features in runtime
+static void
+npy__cpu_init_features(void);
+
+/******************** Public Definitions *********************/
+
+NPY_VISIBILITY_HIDDEN int
+npy_cpu_have(int feature_id)
+{
+    if (feature_id <= NPY_CPU_FEATURE_NONE || feature_id >= NPY_CPU_FEATURE_MAX)
+        return 0;
+    return npy__cpu_have[feature_id];
+}
+
+NPY_VISIBILITY_HIDDEN int
+npy_cpu_init(void)
+{
+    npy__cpu_init_features();
+    return 0;
+}
+
+NPY_VISIBILITY_HIDDEN PyObject *
+npy_cpu_features_dict(void)
+{
+    PyObject *dict = PyDict_New();
+    if (dict) {
+    /**begin repeat
+     * #feature = MMX, SSE, SSE2, SSE3, SSSE3, SSE41, POPCNT, SSE42,
+     *            AVX, F16C, XOP, FMA4, FMA3, AVX2, AVX512F,
+     *            AVX512CD, AVX512ER, AVX512PF, AVX5124FMAPS, AVX5124VNNIW,
+     *            AVX512VPOPCNTDQ, AVX512VL, AVX512BW, AVX512DQ, AVX512VNNI,
+     *            AVX512IFMA, AVX512VBMI, AVX512VBMI2, AVX512BITALG,
+     *            AVX512_KNL, AVX512_KNM, AVX512_SKX, AVX512_CLX, AVX512_CNL, AVX512_ICL,
+     *            VSX, VSX2, VSX3,
+     *            NEON, NEON_FP16, NEON_VFPV4, ASIMD, FPHP, ASIMDHP, ASIMDDP, ASIMDFHM#
+    */
+        if (PyDict_SetItemString(dict, "@feature@",
+            npy__cpu_have[NPY_CPU_FEATURE_@feature@] ? Py_True : Py_False) < 0) {
+            Py_DECREF(dict);
+            return NULL;
+        }
+    /**end repeat**/
+    }
+    return dict;
+}
+
+/****************************************************************
+ * This section is reserved to defining @npy__cpu_init_features
+ * for each CPU architecture, please try to keep it clean. Ty
+ ****************************************************************/
+
+/***************** X86 ******************/
+
+#if defined(NPY_CPU_AMD64) || defined(NPY_CPU_X86)
+
+#ifdef _MSC_VER
+    #include <intrin.h>
+#elif defined(__INTEL_COMPILER)
+    #include <immintrin.h>
+#endif
+
+static int
+npy__cpu_getxcr0(void)
+{
+#if defined(_MSC_VER) || defined (__INTEL_COMPILER)
+    return _xgetbv(0);
+#elif defined(__GNUC__) || defined(__clang__)
+    /* named form of xgetbv not supported on OSX, so must use byte form, see:
+     * https://github.com/asmjit/asmjit/issues/78
+    */
+    unsigned int eax, edx;
+    __asm(".byte 0x0F, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
+    return eax;
+#else
+    return 0;
+#endif
+}
+
+static void
+npy__cpu_cpuid(int reg[4], int func_id)
+{
+#if defined(_MSC_VER)
+    __cpuidex(reg, func_id, 0);
+#elif defined(__INTEL_COMPILER)
+    __cpuid(reg, func_id);
+#elif defined(__GNUC__) || defined(__clang__)
+    #if defined(NPY_CPU_X86) && defined(__PIC__)
+        // %ebx may be the PIC register
+        __asm__("xchg{l}\t{%%}ebx, %1\n\t"
+                "cpuid\n\t"
+                "xchg{l}\t{%%}ebx, %1\n\t"
+                : "=a" (reg[0]), "=r" (reg[1]), "=c" (reg[2]),
+                  "=d" (reg[3])
+                : "a" (func_id), "c" (0)
+        );
+    #else
+        __asm__("cpuid\n\t"
+                : "=a" (reg[0]), "=b" (reg[1]), "=c" (reg[2]),
+                  "=d" (reg[3])
+                : "a" (func_id), "c" (0)
+        );
+    #endif
+#else
+    reg[0] = 0;
+#endif
+}
+
+static void
+npy__cpu_init_features(void)
+{
+    memset(npy__cpu_have, 0, sizeof(npy__cpu_have[0]) * NPY_CPU_FEATURE_MAX);
+
+    // validate platform support
+    int reg[] = {0, 0, 0, 0};
+    npy__cpu_cpuid(reg, 0);
+    if (reg[0] == 0) {
+       npy__cpu_have[NPY_CPU_FEATURE_MMX]  = 1;
+       npy__cpu_have[NPY_CPU_FEATURE_SSE]  = 1;
+       npy__cpu_have[NPY_CPU_FEATURE_SSE2] = 1;
+       #ifdef NPY_CPU_AMD64
+           npy__cpu_have[NPY_CPU_FEATURE_SSE3] = 1;
+       #endif
+       return;
+    }
+
+    npy__cpu_cpuid(reg, 1);
+    npy__cpu_have[NPY_CPU_FEATURE_MMX]    = (reg[3] & (1 << 23)) != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_SSE]    = (reg[3] & (1 << 25)) != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_SSE2]   = (reg[3] & (1 << 26)) != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_SSE3]   = (reg[2] & (1 << 0))  != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_SSSE3]  = (reg[2] & (1 << 9))  != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_SSE41]  = (reg[2] & (1 << 19)) != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_POPCNT] = (reg[2] & (1 << 23)) != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_SSE42]  = (reg[2] & (1 << 20)) != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_F16C]   = (reg[2] & (1 << 29)) != 0;
+
+    // check OSXSAVE
+    if ((reg[2] & (1 << 27)) == 0)
+        return;
+    // check AVX OS support
+    int xcr = npy__cpu_getxcr0();
+    if ((xcr & 6) != 6)
+        return;
+    npy__cpu_have[NPY_CPU_FEATURE_AVX]    = (reg[2] & (1 << 28)) != 0;
+    if (!npy__cpu_have[NPY_CPU_FEATURE_AVX])
+        return;
+    npy__cpu_have[NPY_CPU_FEATURE_FMA3]   = (reg[2] & (1 << 12)) != 0;
+
+    // second call to the cpuid to get extended AMD feature bits
+    npy__cpu_cpuid(reg, 0x80000001);
+    npy__cpu_have[NPY_CPU_FEATURE_XOP]    = (reg[2] & (1 << 11)) != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_FMA4]   = (reg[2] & (1 << 16)) != 0;
+
+    // third call to the cpuid to get extended AVX2 & AVX512 feature bits
+    npy__cpu_cpuid(reg, 7);
+    npy__cpu_have[NPY_CPU_FEATURE_AVX2]   = (reg[1] & (1 << 5))  != 0;
+    if (!npy__cpu_have[NPY_CPU_FEATURE_AVX2])
+        return;
+    // detect AVX2 & FMA3
+    npy__cpu_have[NPY_CPU_FEATURE_FMA]    = npy__cpu_have[NPY_CPU_FEATURE_FMA3];
+
+    // check AVX512 OS support
+    if ((xcr & 0xe6) != 0xe6)
+        return;
+    npy__cpu_have[NPY_CPU_FEATURE_AVX512F]  = (reg[1] & (1 << 16)) != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_AVX512CD] = (reg[1] & (1 << 28)) != 0;
+    if (npy__cpu_have[NPY_CPU_FEATURE_AVX512F] && npy__cpu_have[NPY_CPU_FEATURE_AVX512CD]) {
+        // Knights Landing
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512PF]        = (reg[1] & (1 << 26)) != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512ER]        = (reg[1] & (1 << 27)) != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512_KNL]      = npy__cpu_have[NPY_CPU_FEATURE_AVX512ER] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512PF];
+        // Knights Mill
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512VPOPCNTDQ] = (reg[2] & (1 << 14)) != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX5124VNNIW]    = (reg[3] & (1 << 2))  != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX5124FMAPS]    = (reg[3] & (1 << 3))  != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512_KNM]      = npy__cpu_have[NPY_CPU_FEATURE_AVX512_KNL] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX5124FMAPS] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX5124VNNIW] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512VPOPCNTDQ];
+
+        // Skylake-X
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512DQ]        = (reg[1] & (1 << 17)) != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512BW]        = (reg[1] & (1 << 30)) != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512VL]        = (reg[1] & (1 << 31)) != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512_SKX]      = npy__cpu_have[NPY_CPU_FEATURE_AVX512BW] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512DQ] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512VL];
+        // Cascade Lake
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512VNNI]      = (reg[2] & (1 << 11)) != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512_CLX]      = npy__cpu_have[NPY_CPU_FEATURE_AVX512_SKX] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512VNNI];
+
+        // Cannon Lake
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512IFMA]      = (reg[1] & (1 << 21)) != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512VBMI]      = (reg[2] & (1 << 1))  != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512_CNL]      = npy__cpu_have[NPY_CPU_FEATURE_AVX512_SKX] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512IFMA] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512VBMI];
+        // Ice Lake
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512VBMI2]     = (reg[2] & (1 << 6))  != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512BITALG]    = (reg[2] & (1 << 12)) != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_AVX512_ICL]      = npy__cpu_have[NPY_CPU_FEATURE_AVX512_CLX] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512_CNL] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512VBMI2] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512BITALG] &&
+                                                         npy__cpu_have[NPY_CPU_FEATURE_AVX512VPOPCNTDQ];
+    }
+}
+
+/***************** POWER ******************/
+
+#elif defined(NPY_CPU_PPC64) || defined(NPY_CPU_PPC64LE)
+
+#ifdef __linux__
+    #include <sys/auxv.h>
+    #ifndef AT_HWCAP2
+        #define AT_HWCAP2 26
+    #endif
+    #ifndef PPC_FEATURE2_ARCH_3_00
+        #define PPC_FEATURE2_ARCH_3_00 0x00800000
+    #endif
+#endif
+
+static void
+npy__cpu_init_features(void)
+{
+    memset(npy__cpu_have, 0, sizeof(npy__cpu_have[0]) * NPY_CPU_FEATURE_MAX);
+#ifdef __linux__
+    unsigned int hwcap = getauxval(AT_HWCAP);
+    if ((hwcap & PPC_FEATURE_HAS_VSX) == 0)
+        return;
+
+    hwcap = getauxval(AT_HWCAP2);
+    if (hwcap & PPC_FEATURE2_ARCH_3_00)
+    {
+        npy__cpu_have[NPY_CPU_FEATURE_VSX]  =
+        npy__cpu_have[NPY_CPU_FEATURE_VSX2] =
+        npy__cpu_have[NPY_CPU_FEATURE_VSX3] = 1;
+        return;
+    }
+    npy__cpu_have[NPY_CPU_FEATURE_VSX2] = (hwcap & PPC_FEATURE2_ARCH_2_07) != 0;
+    npy__cpu_have[NPY_CPU_FEATURE_VSX]  = 1;
+// TODO: AIX, FreeBSD
+#else
+    npy__cpu_have[NPY_CPU_FEATURE_VSX]  = 1;
+    #if defined(NPY_CPU_PPC64LE) || defined(NPY_HAVE_VSX2)
+    npy__cpu_have[NPY_CPU_FEATURE_VSX2] = 1;
+    #endif
+    #ifdef NPY_HAVE_VSX3
+    npy__cpu_have[NPY_CPU_FEATURE_VSX3] = 1;
+    #endif
+#endif
+}
+
+/***************** ARM ******************/
+
+#elif defined(__arm__) || defined(__aarch64__)
+
+static NPY_INLINE void
+npy__cpu_init_features_arm8(void)
+{
+    npy__cpu_have[NPY_CPU_FEATURE_NEON]       =
+    npy__cpu_have[NPY_CPU_FEATURE_NEON_FP16]  =
+    npy__cpu_have[NPY_CPU_FEATURE_NEON_VFPV4] =
+    npy__cpu_have[NPY_CPU_FEATURE_ASIMD]      = 1;
+}
+
+#ifdef __linux__
+/*
+ * we aren't sure of what kind kernel or clib we deal with
+ * so we play it safe
+*/
+#include <stdio.h>
+#include <fcntl.h>
+
+#define NPY__HWCAP  16
+#define NPY__HWCAP2 26
+
+// arch/arm/include/uapi/asm/hwcap.h
+#define NPY__HWCAP_HALF   (1 << 1)
+#define NPY__HWCAP_NEON   (1 << 12)
+#define NPY__HWCAP_VFPv3  (1 << 13)
+#define NPY__HWCAP_VFPv4  (1 << 16)
+#define NPY__HWCAP2_AES   (1 << 0)
+#define NPY__HWCAP2_PMULL (1 << 1)
+#define NPY__HWCAP2_SHA1  (1 << 2)
+#define NPY__HWCAP2_SHA2  (1 << 3)
+#define NPY__HWCAP2_CRC32 (1 << 4)
+// arch/arm64/include/uapi/asm/hwcap.h
+#define NPY__HWCAP_FP       (1 << 0)
+#define NPY__HWCAP_ASIMD    (1 << 1)
+#define NPY__HWCAP_FPHP     (1 << 9)
+#define NPY__HWCAP_ASIMDHP  (1 << 10)
+#define NPY__HWCAP_ASIMDDP  (1 << 20)
+#define NPY__HWCAP_ASIMDFHM (1 << 23)
+
+__attribute__((weak)) unsigned long getauxval(unsigned long); // linker should handle it
+static int
+npy__cpu_init_features_linux(void)
+{
+    unsigned long hwcap = 0, hwcap2 = 0;
+    if (getauxval != 0) {
+        hwcap = getauxval(NPY__HWCAP);
+    #ifdef __arm__
+        hwcap2 = getauxval(NPY__HWCAP2);
+    #endif
+    } else {
+        unsigned long auxv[2];
+        int fd = open("/proc/self/auxv", O_RDONLY);
+        if (fd >= 0) {
+            while (read(fd, &auxv, sizeof(auxv)) == sizeof(auxv)) {
+                if (auxv[0] == NPY__HWCAP) {
+                    hwcap = auxv[1];
+                }
+            #ifdef __arm__
+                else if (auxv[0] == NPY__HWCAP2) {
+                    hwcap2 = auxv[1];
+                }
+            #endif
+                // detect the end
+                else if (auxv[0] == 0 && auxv[1] == 0) {
+                    break;
+                }
+            }
+            close(fd);
+        }
+    }
+    if (hwcap == 0 && hwcap2 == 0) {
+        /*
+         * FIXME: failback to compiler definitions,
+         * BTW we can parse /proc/cpuinfo for badly patched kernels
+        */
+        return 0;
+    }
+#ifdef __arm__
+    // Detect Arm8 (aarch32 state)
+    if ((hwcap2 & NPY__HWCAP2_AES)  || (hwcap2 & NPY__HWCAP2_SHA1)  ||
+        (hwcap2 & NPY__HWCAP2_SHA2) || (hwcap2 & NPY__HWCAP2_PMULL) ||
+        (hwcap2 & NPY__HWCAP2_CRC32))
+    {
+        hwcap = hwcap2;
+#else
+    if (1)
+    {
+        if (!(hwcap & (NPY__HWCAP_FP | NPY__HWCAP_ASIMD))) {
+            // Is this could happen? maybe disabled by kernel
+            // BTW this will break the baseline of AARCH64
+            return 1;
+        }
+#endif
+        npy__cpu_have[NPY_CPU_FEATURE_FPHP]       = (hwcap & NPY__HWCAP_FPHP)     != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_ASIMDHP]    = (hwcap & NPY__HWCAP_ASIMDHP)  != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_ASIMDDP]    = (hwcap & NPY__HWCAP_ASIMDDP)  != 0;
+        npy__cpu_have[NPY_CPU_FEATURE_ASIMDFHM]   = (hwcap & NPY__HWCAP_ASIMDFHM) != 0;
+        npy__cpu_init_features_arm8();
+    } else {
+        npy__cpu_have[NPY_CPU_FEATURE_NEON]       = (hwcap & NPY__HWCAP_NEON)   != 0;
+        if (npy__cpu_have[NPY_CPU_FEATURE_NEON]) {
+            npy__cpu_have[NPY_CPU_FEATURE_NEON_FP16]  = (hwcap & NPY__HWCAP_HALF) != 0;
+            npy__cpu_have[NPY_CPU_FEATURE_NEON_VFPV4] = (hwcap & NPY__HWCAP_VFPv4) != 0;
+        }
+    }
+    return 1;
+}
+#endif
+
+static void
+npy__cpu_init_features(void)
+{
+    memset(npy__cpu_have, 0, sizeof(npy__cpu_have[0]) * NPY_CPU_FEATURE_MAX);
+#ifdef __linux__
+    if (npy__cpu_init_features_linux())
+        return;
+#endif
+    // We have nothing else todo
+#if defined(NPY_HAVE_NEON_ARM8) || defined(__aarch64__) || (defined(__ARM_ARCH) && __ARM_ARCH >= 8)
+    #if defined(NPY_HAVE_FPHP) || defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
+    npy__cpu_have[NPY_CPU_FEATURE_FPHP] = 1;
+    #endif
+    #if defined(NPY_HAVE_ASIMDHP) || defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)
+    npy__cpu_have[NPY_CPU_FEATURE_ASIMDHP] = 1;
+    #endif
+    #if defined(NPY_HAVE_ASIMDDP) || defined(__ARM_FEATURE_DOTPROD)
+    npy__cpu_have[NPY_CPU_FEATURE_ASIMDDP] = 1;
+    #endif
+    #if defined(NPY_HAVE_ASIMDFHM) || defined(__ARM_FEATURE_FP16FML)
+    npy__cpu_have[NPY_CPU_FEATURE_ASIMDFHM] = 1;
+    #endif
+    npy__cpu_init_features_arm8();
+#else
+    #if defined(NPY_HAVE_NEON) || defined(__ARM_NEON__)
+        npy__cpu_have[NPY_CPU_FEATURE_NEON] = 1;
+    #endif
+    #if defined(NPY_HAVE_NEON_FP16) || defined(__ARM_FP16_FORMAT_IEEE) || (defined(__ARM_FP) && (__ARM_FP & 2))
+        npy__cpu_have[NPY_CPU_FEATURE_NEON_FP16] = npy__cpu_have[NPY_CPU_FEATURE_NEON];
+    #endif
+    #if defined(NPY_HAVE_NEON_VFPV4) || defined(__ARM_FEATURE_FMA)
+        npy__cpu_have[NPY_CPU_FEATURE_NEON_VFPV4] = npy__cpu_have[NPY_CPU_FEATURE_NEON];
+    #endif
+#endif
+}
+
+/*********** Unsupported ARCH ***********/
+#else
+static void
+npy__cpu_init_features(void)
+{
+}
+#endif
diff --git a/numpy/core/src/common/npy_cpu_features.h b/numpy/core/src/common/npy_cpu_features.h
new file mode 100644 (file)
index 0000000..0e89013
--- /dev/null
@@ -0,0 +1,117 @@
+#ifndef _NPY_CPU_FEATURES_H_
+#define _NPY_CPU_FEATURES_H_
+
+#include "numpy/numpyconfig.h" // for NPY_VISIBILITY_HIDDEN
+#include <Python.h> // for PyObject
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum npy_cpu_features
+{
+    NPY_CPU_FEATURE_NONE = 0,
+    // X86
+    NPY_CPU_FEATURE_MMX               = 1,
+    NPY_CPU_FEATURE_SSE               = 2,
+    NPY_CPU_FEATURE_SSE2              = 3,
+    NPY_CPU_FEATURE_SSE3              = 4,
+    NPY_CPU_FEATURE_SSSE3             = 5,
+    NPY_CPU_FEATURE_SSE41             = 6,
+    NPY_CPU_FEATURE_POPCNT            = 7,
+    NPY_CPU_FEATURE_SSE42             = 8,
+    NPY_CPU_FEATURE_AVX               = 9,
+    NPY_CPU_FEATURE_F16C              = 10,
+    NPY_CPU_FEATURE_XOP               = 11,
+    NPY_CPU_FEATURE_FMA4              = 12,
+    NPY_CPU_FEATURE_FMA3              = 13,
+    NPY_CPU_FEATURE_AVX2              = 14,
+    NPY_CPU_FEATURE_FMA               = 15, // AVX2 & FMA3, provides backward compatibility
+
+    NPY_CPU_FEATURE_AVX512F           = 30,
+    NPY_CPU_FEATURE_AVX512CD          = 31,
+    NPY_CPU_FEATURE_AVX512ER          = 32,
+    NPY_CPU_FEATURE_AVX512PF          = 33,
+    NPY_CPU_FEATURE_AVX5124FMAPS      = 34,
+    NPY_CPU_FEATURE_AVX5124VNNIW      = 35,
+    NPY_CPU_FEATURE_AVX512VPOPCNTDQ   = 36,
+    NPY_CPU_FEATURE_AVX512BW          = 37,
+    NPY_CPU_FEATURE_AVX512DQ          = 38,
+    NPY_CPU_FEATURE_AVX512VL          = 39,
+    NPY_CPU_FEATURE_AVX512IFMA        = 40,
+    NPY_CPU_FEATURE_AVX512VBMI        = 41,
+    NPY_CPU_FEATURE_AVX512VNNI        = 42,
+    NPY_CPU_FEATURE_AVX512VBMI2       = 43,
+    NPY_CPU_FEATURE_AVX512BITALG      = 44,
+
+    // X86 CPU Groups
+    // Knights Landing (F,CD,ER,PF)
+    NPY_CPU_FEATURE_AVX512_KNL        = 101,
+    // Knights Mill    (F,CD,ER,PF,4FMAPS,4VNNIW,VPOPCNTDQ)
+    NPY_CPU_FEATURE_AVX512_KNM        = 102,
+    // Skylake-X       (F,CD,BW,DQ,VL)
+    NPY_CPU_FEATURE_AVX512_SKX        = 103,
+    // Cascade Lake    (F,CD,BW,DQ,VL,VNNI)
+    NPY_CPU_FEATURE_AVX512_CLX        = 104,
+    // Cannon Lake     (F,CD,BW,DQ,VL,IFMA,VBMI)
+    NPY_CPU_FEATURE_AVX512_CNL        = 105,
+    // Ice Lake        (F,CD,BW,DQ,VL,IFMA,VBMI,VNNI,VBMI2,BITALG,VPOPCNTDQ)
+    NPY_CPU_FEATURE_AVX512_ICL        = 106,
+
+    // IBM/POWER VSX
+    // POWER7
+    NPY_CPU_FEATURE_VSX               = 200,
+    // POWER8
+    NPY_CPU_FEATURE_VSX2              = 201,
+    // POWER9
+    NPY_CPU_FEATURE_VSX3              = 202,
+
+    // ARM
+    NPY_CPU_FEATURE_NEON              = 300,
+    NPY_CPU_FEATURE_NEON_FP16         = 301,
+    // FMA
+    NPY_CPU_FEATURE_NEON_VFPV4        = 302,
+    // Advanced SIMD
+    NPY_CPU_FEATURE_ASIMD             = 303,
+    // ARMv8.2 half-precision
+    NPY_CPU_FEATURE_FPHP              = 304,
+    // ARMv8.2 half-precision vector arithm
+    NPY_CPU_FEATURE_ASIMDHP           = 305,
+    // ARMv8.2 dot product
+    NPY_CPU_FEATURE_ASIMDDP           = 306,
+    // ARMv8.2 single&half-precision multiply
+    NPY_CPU_FEATURE_ASIMDFHM          = 307,
+
+    NPY_CPU_FEATURE_MAX
+};
+
+/*
+ * Initialize CPU features
+ * return 0 on success otherwise return -1
+*/
+NPY_VISIBILITY_HIDDEN int
+npy_cpu_init(void);
+
+/*
+ * return 0 if CPU feature isn't available
+ * note: `npy_cpu_init` must be called first otherwise it will always return 0
+*/
+NPY_VISIBILITY_HIDDEN int
+npy_cpu_have(int feature_id);
+
+#define NPY_CPU_HAVE(FEATURE_NAME) \
+npy_cpu_have(NPY_CPU_FEATURE_##FEATURE_NAME)
+
+/*
+ * return a new dictionary contains CPU feature names
+ * with runtime availability.
+ * same as npy_cpu_have, `npy_cpu_init` must be called first.
+ */
+NPY_VISIBILITY_HIDDEN PyObject *
+npy_cpu_features_dict(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _NPY_CPU_FEATURES_H_
index c580e0cce9a181439609c194fd3f9f56793a5049..260e02a64b1b48b6b76b9c9ca48ffeb8e0fa3d0d 100644 (file)
@@ -100,16 +100,12 @@ done:
 static PyObject *
 _PyLong_Bytes(PyObject *long_obj) {
     PyObject *bytes;
-#if defined(NPY_PY3K)
     PyObject *unicode = PyObject_Str(long_obj);
     if (unicode == NULL) {
         return NULL;
     }
     bytes = PyUnicode_AsUTF8String(unicode);
     Py_DECREF(unicode);
-#else
-    bytes = PyObject_Str(long_obj);
-#endif
     return bytes;
 }
 
index d60b1ca1731bbc70bc33aae2720c1dfee8fe5a88..42a71777bb421386fb247561f359c53b1c9f7213 100644 (file)
@@ -248,7 +248,7 @@ check_ascii_format(const char *format)
  * Fix the generated string: make sure the decimal is ., that exponent has a
  * minimal number of digits, and that it has a decimal + one digit after that
  * decimal if decimal argument != 0 (Same effect that 'Z' format in
- * PyOS_ascii_formatd
+ * PyOS_ascii_formatd)
  */
 static char*
 fix_ascii_format(char* buf, size_t buflen, int decimal)
@@ -283,7 +283,7 @@ fix_ascii_format(char* buf, size_t buflen, int decimal)
  *      converting.
  *      - value: The value to convert
  *      - decimal: if != 0, always has a decimal, and at leasat one digit after
- *      the decimal. This has the same effect as passing 'Z' in the origianl
+ *      the decimal. This has the same effect as passing 'Z' in the original
  *      PyOS_ascii_formatd
  *
  * This is similar to PyOS_ascii_formatd in python > 2.6, except that it does
index 8e293e9f2d9ef13678e4fe76daf62661800ca785..3ef5d687820b8db293b597e6a6e933a8b3d85786 100644 (file)
 #include "ctors.h"
 
 /*
- * Functions only needed on narrow builds of Python for converting back and
- * forth between the NumPy Unicode data-type (always 4-bytes) and the
- * Python Unicode scalar (2-bytes on a narrow build).
- */
-
-/*
- * The ucs2 buffer must be large enough to hold 2*ucs4length characters
- * due to the use of surrogate pairs.
+ * This file originally contained functions only needed on narrow builds of
+ * Python for converting back and forth between the NumPy Unicode data-type
+ * (always 4-bytes) and the Python Unicode scalar (2-bytes on a narrow build).
  *
- * The return value is the number of ucs2 bytes used-up which
- * is ucs4length + number of surrogate pairs found.
- *
- * Values above 0xffff are converted to surrogate pairs.
+ * This "narrow" interface is now deprecated in python and unused in NumPy.
  */
-NPY_NO_EXPORT int
-PyUCS2Buffer_FromUCS4(Py_UNICODE *ucs2, npy_ucs4 *ucs4, int ucs4length)
-{
-    int i;
-    int numucs2 = 0;
-    npy_ucs4 chr;
-    for (i = 0; i < ucs4length; i++) {
-        chr = *ucs4++;
-        if (chr > 0xffff) {
-            numucs2++;
-            chr -= 0x10000L;
-            *ucs2++ = 0xD800 + (Py_UNICODE) (chr >> 10);
-            *ucs2++ = 0xDC00 + (Py_UNICODE) (chr & 0x03FF);
-        }
-        else {
-            *ucs2++ = (Py_UNICODE) chr;
-        }
-        numucs2++;
-    }
-    return numucs2;
-}
-
-
-/*
- * This converts a UCS2 buffer of the given length to UCS4 buffer.
- * It converts up to ucs4len characters of UCS2
- *
- * It returns the number of characters converted which can
- * be less than ucs2len if there are surrogate pairs in ucs2.
- *
- * The return value is the actual size of the used part of the ucs4 buffer.
- */
-NPY_NO_EXPORT int
-PyUCS2Buffer_AsUCS4(Py_UNICODE *ucs2, npy_ucs4 *ucs4, int ucs2len, int ucs4len)
-{
-    int i;
-    npy_ucs4 chr;
-    Py_UNICODE ch;
-    int numchars=0;
-
-    for (i = 0; (i < ucs2len) && (numchars < ucs4len); i++) {
-        ch = *ucs2++;
-        if (ch >= 0xd800 && ch <= 0xdfff) {
-            /* surrogate pair */
-            chr = ((npy_ucs4)(ch-0xd800)) << 10;
-            chr += *ucs2++ + 0x2400;  /* -0xdc00 + 0x10000 */
-            i++;
-        }
-        else {
-            chr = (npy_ucs4) ch;
-        }
-        *ucs4++ = chr;
-        numchars++;
-    }
-    return numchars;
-}
 
 /*
  * Returns a PyUnicodeObject initialized from a buffer containing
@@ -107,68 +43,32 @@ PyUCS2Buffer_AsUCS4(Py_UNICODE *ucs2, npy_ucs4 *ucs4, int ucs2len, int ucs4len)
  * new_reference: PyUnicodeObject
  */
 NPY_NO_EXPORT PyUnicodeObject *
-PyUnicode_FromUCS4(char *src, Py_ssize_t size, int swap, int align)
+PyUnicode_FromUCS4(char const *src_char, Py_ssize_t size, int swap, int align)
 {
     Py_ssize_t ucs4len = size / sizeof(npy_ucs4);
-    npy_ucs4 *buf = (npy_ucs4 *)src;
-    int alloc = 0;
-    PyUnicodeObject *ret;
+    npy_ucs4 const *src = (npy_ucs4 const *)src_char;
+    npy_ucs4 *buf = NULL;
 
     /* swap and align if needed */
     if (swap || align) {
         buf = (npy_ucs4 *)malloc(size);
         if (buf == NULL) {
             PyErr_NoMemory();
-            goto fail;
+            return NULL;
         }
-        alloc = 1;
         memcpy(buf, src, size);
         if (swap) {
             byte_swap_vector(buf, ucs4len, sizeof(npy_ucs4));
         }
+        src = buf;
     }
 
     /* trim trailing zeros */
-    while (ucs4len > 0 && buf[ucs4len - 1] == 0) {
+    while (ucs4len > 0 && src[ucs4len - 1] == 0) {
         ucs4len--;
     }
-
-    /* produce PyUnicode object */
-#ifdef Py_UNICODE_WIDE
-    {
-        ret = (PyUnicodeObject *)PyUnicode_FromUnicode((Py_UNICODE*)buf,
-                                                       (Py_ssize_t) ucs4len);
-        if (ret == NULL) {
-            goto fail;
-        }
-    }
-#else
-    {
-        Py_ssize_t tmpsiz = 2 * sizeof(Py_UNICODE) * ucs4len;
-        Py_ssize_t ucs2len;
-        Py_UNICODE *tmp;
-
-        if ((tmp = (Py_UNICODE *)malloc(tmpsiz)) == NULL) {
-            PyErr_NoMemory();
-            goto fail;
-        }
-        ucs2len = PyUCS2Buffer_FromUCS4(tmp, buf, ucs4len);
-        ret = (PyUnicodeObject *)PyUnicode_FromUnicode(tmp, (Py_ssize_t) ucs2len);
-        free(tmp);
-        if (ret == NULL) {
-            goto fail;
-        }
-    }
-#endif
-
-    if (alloc) {
-        free(buf);
-    }
+    PyUnicodeObject *ret = (PyUnicodeObject *)PyUnicode_FromKindAndData(
+        PyUnicode_4BYTE_KIND, src, ucs4len);
+    free(buf);
     return ret;
-
-fail:
-    if (alloc) {
-        free(buf);
-    }
-    return NULL;
 }
index fe31a5e25b43b34e7cc393ac1aff1ef901dc5051..c811e1f2c52c9ab0cdcab9940afc1acdf60fdaa3 100644 (file)
@@ -1,12 +1,6 @@
 #ifndef _NPY_UCSNARROW_H_
 #define _NPY_UCSNARROW_H_
 
-NPY_NO_EXPORT int
-PyUCS2Buffer_FromUCS4(Py_UNICODE *ucs2, npy_ucs4 *ucs4, int ucs4length);
-
-NPY_NO_EXPORT int
-PyUCS2Buffer_AsUCS4(Py_UNICODE *ucs2, npy_ucs4 *ucs4, int ucs2len, int ucs4len);
-
 NPY_NO_EXPORT PyUnicodeObject *
 PyUnicode_FromUCS4(char *src, Py_ssize_t size, int swap, int align);
 
index 3f699bcddc9d726b3fc7f4fc3ba659b165b84097..d510f185acf3b30c9c0897bc85ae3e2c973fbdde 100644 (file)
@@ -94,8 +94,11 @@ PyUFuncOverride_GetOutObjects(PyObject *kwds, PyObject **out_kwd_obj, PyObject *
         return -1;
     }
     /* borrowed reference */
-    *out_kwd_obj = PyDict_GetItemString(kwds, "out");
+    *out_kwd_obj = _PyDict_GetItemStringWithError(kwds, "out");
     if (*out_kwd_obj == NULL) {
+        if (PyErr_Occurred()) {
+            return -1;
+        }
         Py_INCREF(Py_None);
         *out_kwd_obj = Py_None;
         return 0;
index 718199f704a795f8703941f8ffaa0293447adcf0..e26875736d234a148114d816e79dc5f69ab9ef20 100644 (file)
@@ -16,7 +16,6 @@ static struct PyMethodDef methods[] = {
 };
 
 
-#if defined(NPY_PY3K)
 static struct PyModuleDef moduledef = {
         PyModuleDef_HEAD_INIT,
         "dummy",
@@ -28,10 +27,8 @@ static struct PyModuleDef moduledef = {
         NULL,
         NULL
 };
-#endif
 
 /* Initialization function for the module */
-#if defined(NPY_PY3K)
 PyMODINIT_FUNC PyInit__dummy(void) {
     PyObject *m;
     m = PyModule_Create(&moduledef);
@@ -40,9 +37,3 @@ PyMODINIT_FUNC PyInit__dummy(void) {
     }
     return m;
 }
-#else
-PyMODINIT_FUNC
-init_dummy(void) {
-    Py_InitModule("_dummy", methods);
-}
-#endif
index 3db1254d488a524502dea0b8604ae6c4885d2815..20f7a132ce9179f3321389eebca6b04d4d6719c1 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef _NPY_PRIVATE__DATETIME_H_
 #define _NPY_PRIVATE__DATETIME_H_
 
-extern NPY_NO_EXPORT char *_datetime_strings[NPY_DATETIME_NUMUNITS];
+extern NPY_NO_EXPORT char const *_datetime_strings[NPY_DATETIME_NUMUNITS];
 extern NPY_NO_EXPORT int _days_per_month_table[2][12];
 
 NPY_NO_EXPORT void
@@ -68,7 +68,7 @@ days_to_month_number(npy_datetime days);
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-parse_datetime_metadata_from_metastr(char *metastr, Py_ssize_t len,
+parse_datetime_metadata_from_metastr(char const *metastr, Py_ssize_t len,
                                     PyArray_DatetimeMetaData *out_meta);
 
 
@@ -78,7 +78,7 @@ parse_datetime_metadata_from_metastr(char *metastr, Py_ssize_t len,
  * contain its string length.
  */
 NPY_NO_EXPORT PyArray_Descr *
-parse_dtype_from_datetime_typestr(char *typestr, Py_ssize_t len);
+parse_dtype_from_datetime_typestr(char const *typestr, Py_ssize_t len);
 
 /*
  * Converts a substring given by 'str' and 'len' into
@@ -88,7 +88,7 @@ parse_dtype_from_datetime_typestr(char *typestr, Py_ssize_t len);
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT NPY_DATETIMEUNIT
-parse_datetime_unit_from_string(char *str, Py_ssize_t len, char *metastr);
+parse_datetime_unit_from_string(char const *str, Py_ssize_t len, char const *metastr);
 
 /*
  * Translate divisors into multiples of smaller units.
@@ -99,7 +99,7 @@ parse_datetime_unit_from_string(char *str, Py_ssize_t len, char *metastr);
  */
 NPY_NO_EXPORT int
 convert_datetime_divisor_to_multiple(PyArray_DatetimeMetaData *meta,
-                                    int den, char *metastr);
+                                    int den, char const *metastr);
 
 /*
  * Determines whether the 'divisor' metadata divides evenly into
index fa2efb428124be6360f2c0e311cb41c50b8736e7..3185598852b4e8b28bb4fbc0e215c4db633cbab6 100644 (file)
@@ -55,7 +55,7 @@ EXPORT(void*) forward_pointer(void *x)
  * #typenum = NPY_DOUBLE, NPY_INT#
  */
 static int copy_@name@(PyArrayIterObject *itx, PyArrayNeighborhoodIterObject *niterx,
-        npy_intp *bounds,
+        npy_intp const *bounds,
         PyObject **out)
 {
     npy_intp i, j;
@@ -97,7 +97,7 @@ static int copy_@name@(PyArrayIterObject *itx, PyArrayNeighborhoodIterObject *ni
 /**end repeat**/
 
 static int copy_object(PyArrayIterObject *itx, PyArrayNeighborhoodIterObject *niterx,
-        npy_intp *bounds,
+        npy_intp const *bounds,
         PyObject **out)
 {
     npy_intp i, j;
@@ -251,7 +251,7 @@ clean_ax:
 static int
 copy_double_double(PyArrayNeighborhoodIterObject *itx,
         PyArrayNeighborhoodIterObject *niterx,
-        npy_intp *bounds,
+        npy_intp const *bounds,
         PyObject **out)
 {
     npy_intp i, j;
@@ -771,30 +771,6 @@ npy_discard(PyObject* NPY_UNUSED(self), PyObject* args)
     Py_RETURN_NONE;
 }
 
-#if !defined(NPY_PY3K)
-static PyObject *
-int_subclass(PyObject *dummy, PyObject *args)
-{
-
-  PyObject *result = NULL;
-  PyObject *scalar_object = NULL;
-
-  if (!PyArg_UnpackTuple(args, "test_int_subclass", 1, 1, &scalar_object))
-    return NULL;
-
-  if (PyInt_Check(scalar_object))
-    result = Py_True;
-  else
-    result = Py_False;
-
-  Py_INCREF(result);
-
-  return result;
-
-}
-#endif
-
-
 /*
  * Create python string from a FLAG and or the corresponding PyBuf flag
  * for the use in get_buffer_info.
@@ -1210,11 +1186,7 @@ array_solve_diophantine(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject
 
         for (j = 0; j < nterms; ++j) {
             PyObject *obj;
-#if defined(NPY_PY3K)
             obj = PyLong_FromSsize_t(x[j]);
-#else
-            obj = PyInt_FromSsize_t(x[j]);
-#endif
             if (obj == NULL) {
                 goto fail;
             }
@@ -1905,21 +1877,21 @@ PrintFloat_Printf_g(PyObject *obj, int precision)
     char str[1024];
 
     if (PyArray_IsScalar(obj, Half)) {
-        npy_half x = ((PyHalfScalarObject *)obj)->obval;
+        npy_half x = PyArrayScalar_VAL(obj, Half);
         PyOS_snprintf(str, sizeof(str), "%.*g", precision,
                       npy_half_to_double(x));
     }
     else if (PyArray_IsScalar(obj, Float)) {
-        npy_float x = ((PyFloatScalarObject *)obj)->obval;
+        npy_float x = PyArrayScalar_VAL(obj, Float);
         PyOS_snprintf(str, sizeof(str), "%.*g", precision, x);
     }
     else if (PyArray_IsScalar(obj, Double)) {
-        npy_double x = ((PyDoubleScalarObject *)obj)->obval;
+        npy_double x = PyArrayScalar_VAL(obj, Double);
         PyOS_snprintf(str, sizeof(str), "%.*g", precision, x);
         /* would be better to use lg, but not available in C90 */
     }
     else if (PyArray_IsScalar(obj, LongDouble)) {
-        npy_longdouble x = ((PyLongDoubleScalarObject *)obj)->obval;
+        npy_longdouble x = PyArrayScalar_VAL(obj, LongDouble);
         PyOS_snprintf(str, sizeof(str), "%.*Lg", precision, x);
     }
     else{
@@ -1966,6 +1938,114 @@ getset_numericops(PyObject* NPY_UNUSED(self), PyObject* NPY_UNUSED(args))
     return ret;
 }
 
+static PyObject *
+run_byteorder_converter(PyObject* NPY_UNUSED(self), PyObject *args)
+{
+    char byteorder;
+    if (!PyArg_ParseTuple(args, "O&", PyArray_ByteorderConverter, &byteorder)) {
+        return NULL;
+    }
+    switch (byteorder) {
+        case NPY_BIG: return PyUnicode_FromString("NPY_BIG");
+        case NPY_LITTLE: return PyUnicode_FromString("NPY_LITTLE");
+        case NPY_NATIVE: return PyUnicode_FromString("NPY_NATIVE");
+        case NPY_SWAP: return PyUnicode_FromString("NPY_SWAP");
+        case NPY_IGNORE: return PyUnicode_FromString("NPY_IGNORE");
+    }
+    return PyInt_FromLong(byteorder);
+}
+
+static PyObject *
+run_sortkind_converter(PyObject* NPY_UNUSED(self), PyObject *args)
+{
+    NPY_SORTKIND kind;
+    if (!PyArg_ParseTuple(args, "O&", PyArray_SortkindConverter, &kind)) {
+        return NULL;
+    }
+    switch (kind) {
+        case NPY_QUICKSORT: return PyUnicode_FromString("NPY_QUICKSORT");
+        case NPY_HEAPSORT: return PyUnicode_FromString("NPY_HEAPSORT");
+        case NPY_STABLESORT: return PyUnicode_FromString("NPY_STABLESORT");
+    }
+    return PyInt_FromLong(kind);
+}
+
+static PyObject *
+run_selectkind_converter(PyObject* NPY_UNUSED(self), PyObject *args)
+{
+    NPY_SELECTKIND kind;
+    if (!PyArg_ParseTuple(args, "O&", PyArray_SelectkindConverter, &kind)) {
+        return NULL;
+    }
+    switch (kind) {
+        case NPY_INTROSELECT: return PyUnicode_FromString("NPY_INTROSELECT");
+    }
+    return PyInt_FromLong(kind);
+}
+
+static PyObject *
+run_searchside_converter(PyObject* NPY_UNUSED(self), PyObject *args)
+{
+    NPY_SEARCHSIDE side;
+    if (!PyArg_ParseTuple(args, "O&", PyArray_SearchsideConverter, &side)) {
+        return NULL;
+    }
+    switch (side) {
+        case NPY_SEARCHLEFT: return PyUnicode_FromString("NPY_SEARCHLEFT");
+        case NPY_SEARCHRIGHT: return PyUnicode_FromString("NPY_SEARCHRIGHT");
+    }
+    return PyInt_FromLong(side);
+}
+
+static PyObject *
+run_order_converter(PyObject* NPY_UNUSED(self), PyObject *args)
+{
+    NPY_ORDER order;
+    if (!PyArg_ParseTuple(args, "O&", PyArray_OrderConverter, &order)) {
+        return NULL;
+    }
+    switch (order) {
+        case NPY_ANYORDER: return PyUnicode_FromString("NPY_ANYORDER");
+        case NPY_CORDER: return PyUnicode_FromString("NPY_CORDER");
+        case NPY_FORTRANORDER: return PyUnicode_FromString("NPY_FORTRANORDER");
+        case NPY_KEEPORDER: return PyUnicode_FromString("NPY_KEEPORDER");
+    }
+    return PyInt_FromLong(order);
+}
+
+static PyObject *
+run_clipmode_converter(PyObject* NPY_UNUSED(self), PyObject *args)
+{
+    NPY_CLIPMODE mode;
+    if (!PyArg_ParseTuple(args, "O&", PyArray_ClipmodeConverter, &mode)) {
+        return NULL;
+    }
+    switch (mode) {
+        case NPY_CLIP: return PyUnicode_FromString("NPY_CLIP");
+        case NPY_WRAP: return PyUnicode_FromString("NPY_WRAP");
+        case NPY_RAISE: return PyUnicode_FromString("NPY_RAISE");
+    }
+    return PyInt_FromLong(mode);
+}
+
+static PyObject *
+run_casting_converter(PyObject* NPY_UNUSED(self), PyObject *args)
+{
+    NPY_CASTING casting;
+    if (!PyArg_ParseTuple(args, "O&", PyArray_CastingConverter, &casting)) {
+        return NULL;
+    }
+    switch (casting) {
+        case NPY_NO_CASTING: return PyUnicode_FromString("NPY_NO_CASTING");
+        case NPY_EQUIV_CASTING: return PyUnicode_FromString("NPY_EQUIV_CASTING");
+        case NPY_SAFE_CASTING: return PyUnicode_FromString("NPY_SAFE_CASTING");
+        case NPY_SAME_KIND_CASTING: return PyUnicode_FromString("NPY_SAME_KIND_CASTING");
+        case NPY_UNSAFE_CASTING: return PyUnicode_FromString("NPY_UNSAFE_CASTING");
+    }
+    return PyInt_FromLong(casting);
+}
+
+
 static PyMethodDef Multiarray_TestsMethods[] = {
     {"IsPythonScalar",
         IsPythonScalar,
@@ -2018,11 +2098,6 @@ static PyMethodDef Multiarray_TestsMethods[] = {
     {"npy_discard",
         npy_discard,
         METH_O, NULL},
-#if !defined(NPY_PY3K)
-    {"test_int_subclass",
-        int_subclass,
-        METH_VARARGS, NULL},
-#endif
     {"get_buffer_info",
         get_buffer_info,
         METH_VARARGS, NULL},
@@ -2122,11 +2197,31 @@ static PyMethodDef Multiarray_TestsMethods[] = {
     {"get_struct_alignments",
         get_struct_alignments,
         METH_VARARGS, NULL},
+    {"run_byteorder_converter",
+        run_byteorder_converter,
+        METH_VARARGS, NULL},
+    {"run_sortkind_converter",
+        run_sortkind_converter,
+        METH_VARARGS, NULL},
+    {"run_selectkind_converter",
+        run_selectkind_converter,
+        METH_VARARGS, NULL},
+    {"run_searchside_converter",
+        run_searchside_converter,
+        METH_VARARGS, NULL},
+    {"run_order_converter",
+        run_order_converter,
+        METH_VARARGS, NULL},
+    {"run_clipmode_converter",
+        run_clipmode_converter,
+        METH_VARARGS, NULL},
+    {"run_casting_converter",
+        run_casting_converter,
+        METH_VARARGS, NULL},
     {NULL, NULL, 0, NULL}        /* Sentinel */
 };
 
 
-#if defined(NPY_PY3K)
 static struct PyModuleDef moduledef = {
         PyModuleDef_HEAD_INIT,
         "_multiarray_tests",
@@ -2138,33 +2233,21 @@ static struct PyModuleDef moduledef = {
         NULL,
         NULL
 };
-#endif
 
-#if defined(NPY_PY3K)
-#define RETVAL m
 PyMODINIT_FUNC PyInit__multiarray_tests(void)
-#else
-#define RETVAL
-PyMODINIT_FUNC
-init_multiarray_tests(void)
-#endif
 {
     PyObject *m;
 
-#if defined(NPY_PY3K)
     m = PyModule_Create(&moduledef);
-#else
-    m = Py_InitModule("_multiarray_tests", Multiarray_TestsMethods);
-#endif
     if (m == NULL) {
-        return RETVAL;
+        return m;
     }
     import_array();
     if (PyErr_Occurred()) {
         PyErr_SetString(PyExc_RuntimeError,
                         "cannot load _multiarray_tests module.");
     }
-    return RETVAL;
+    return m;
 }
 
 NPY_NO_EXPORT int
index a7f34cbe5821dc573e2155d28c9e7e355753fafc..795fc731564bc49044c0f3f25e8ee30ad6d92bf4 100644 (file)
@@ -47,12 +47,33 @@ typedef struct {
 static cache_bucket datacache[NBUCKETS];
 static cache_bucket dimcache[NBUCKETS_DIM];
 
+static int _madvise_hugepage = 1;
+
+
+/*
+ * This function enables or disables the use of `MADV_HUGEPAGE` on Linux
+ * by modifying the global static `_madvise_hugepage`.
+ * It returns the previous value of `_madvise_hugepage`.
+ *
+ * It is exposed to Python as `np.core.multiarray._set_madvise_hugepage`.
+ */
+NPY_NO_EXPORT PyObject *
+_set_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *enabled_obj)
+{
+    int was_enabled = _madvise_hugepage;
+    int enabled = PyObject_IsTrue(enabled_obj);
+    if (enabled < 0) {
+        return NULL;
+    }
+    _madvise_hugepage = enabled;
+    if (was_enabled) {
+        Py_RETURN_TRUE;
+    }
+    Py_RETURN_FALSE;
+}
+
+
 /* as the cache is managed in global variables verify the GIL is held */
-#if defined(NPY_PY3K)
-#define NPY_CHECK_GIL_HELD() PyGILState_Check()
-#else
-#define NPY_CHECK_GIL_HELD() 1
-#endif
 
 /*
  * very simplistic small memory block cache to avoid more expensive libc
@@ -67,7 +88,7 @@ _npy_alloc_cache(npy_uintp nelem, npy_uintp esz, npy_uint msz,
     void * p;
     assert((esz == 1 && cache == datacache) ||
            (esz == sizeof(npy_intp) && cache == dimcache));
-    assert(NPY_CHECK_GIL_HELD());
+    assert(PyGILState_Check());
     if (nelem < msz) {
         if (cache[nelem].available > 0) {
             return cache[nelem].ptrs[--(cache[nelem].available)];
@@ -80,7 +101,7 @@ _npy_alloc_cache(npy_uintp nelem, npy_uintp esz, npy_uint msz,
 #endif
 #ifdef NPY_OS_LINUX
         /* allow kernel allocating huge pages for large arrays */
-        if (NPY_UNLIKELY(nelem * esz >= ((1u<<22u)))) {
+        if (NPY_UNLIKELY(nelem * esz >= ((1u<<22u))) && _madvise_hugepage) {
             npy_uintp offset = 4096u - (npy_uintp)p % (4096u);
             npy_uintp length = nelem * esz - offset;
             /**
@@ -102,7 +123,7 @@ static NPY_INLINE void
 _npy_free_cache(void * p, npy_uintp nelem, npy_uint msz,
                 cache_bucket * cache, void (*dealloc)(void *))
 {
-    assert(NPY_CHECK_GIL_HELD());
+    assert(PyGILState_Check());
     if (p != NULL && nelem < msz) {
         if (cache[nelem].available < NCACHE) {
             cache[nelem].ptrs[cache[nelem].available++] = p;
index 2b69efc352058f4af94f5affd0239486423db056..15e31ebb5f2ff998968b961c7c0a1eb26ee1dd76 100644 (file)
@@ -6,6 +6,9 @@
 
 #define NPY_TRACE_DOMAIN 389047
 
+NPY_NO_EXPORT PyObject *
+_set_madvise_hugepage(PyObject *NPY_UNUSED(self), PyObject *enabled_obj);
+
 NPY_NO_EXPORT void *
 npy_alloc_cache(npy_uintp sz);
 
index 7ff33ebd7ba6dddb41f497ab067416fea8d4fc0c..b8dc7d516be182a617016a0cda2cfdeef8aa6fa3 100644 (file)
@@ -29,8 +29,8 @@
  * elements, as required by the copy/casting code in lowlevel_strided_loops.c
  */
 NPY_NO_EXPORT int
-copycast_isaligned(int ndim, npy_intp *shape,
-        PyArray_Descr *dtype, char *data, npy_intp *strides)
+copycast_isaligned(int ndim, npy_intp const *shape,
+        PyArray_Descr *dtype, char *data, npy_intp const *strides)
 {
     int aligned;
     int big_aln, small_aln;
@@ -72,9 +72,9 @@ copycast_isaligned(int ndim, npy_intp *shape,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-raw_array_assign_array(int ndim, npy_intp *shape,
-        PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
-        PyArray_Descr *src_dtype, char *src_data, npy_intp *src_strides)
+raw_array_assign_array(int ndim, npy_intp const *shape,
+        PyArray_Descr *dst_dtype, char *dst_data, npy_intp const *dst_strides,
+        PyArray_Descr *src_dtype, char *src_data, npy_intp const *src_strides)
 {
     int idim;
     npy_intp shape_it[NPY_MAXDIMS];
@@ -152,11 +152,11 @@ raw_array_assign_array(int ndim, npy_intp *shape,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-raw_array_wheremasked_assign_array(int ndim, npy_intp *shape,
-        PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
-        PyArray_Descr *src_dtype, char *src_data, npy_intp *src_strides,
+raw_array_wheremasked_assign_array(int ndim, npy_intp const *shape,
+        PyArray_Descr *dst_dtype, char *dst_data, npy_intp const *dst_strides,
+        PyArray_Descr *src_dtype, char *src_data, npy_intp const *src_strides,
         PyArray_Descr *wheremask_dtype, char *wheremask_data,
-        npy_intp *wheremask_strides)
+        npy_intp const *wheremask_strides)
 {
     int idim;
     npy_intp shape_it[NPY_MAXDIMS];
@@ -305,19 +305,8 @@ PyArray_AssignArray(PyArrayObject *dst, PyArrayObject *src,
     /* Check the casting rule */
     if (!PyArray_CanCastTypeTo(PyArray_DESCR(src),
                                 PyArray_DESCR(dst), casting)) {
-        PyObject *errmsg;
-        errmsg = PyUString_FromString("Cannot cast scalar from ");
-        PyUString_ConcatAndDel(&errmsg,
-                PyObject_Repr((PyObject *)PyArray_DESCR(src)));
-        PyUString_ConcatAndDel(&errmsg,
-                PyUString_FromString(" to "));
-        PyUString_ConcatAndDel(&errmsg,
-                PyObject_Repr((PyObject *)PyArray_DESCR(dst)));
-        PyUString_ConcatAndDel(&errmsg,
-                PyUString_FromFormat(" according to the rule %s",
-                        npy_casting_to_string(casting)));
-        PyErr_SetObject(PyExc_TypeError, errmsg);
-        Py_DECREF(errmsg);
+        npy_set_invalid_cast_error(
+                PyArray_DESCR(src), PyArray_DESCR(dst), casting, NPY_FALSE);
         goto fail;
     }
 
index ecb5be47b50a60c7812b1a1ee43d9e8fe05dc15b..41eb75f1c4c5511159defe8dfc1a166c91c94e7a 100644 (file)
@@ -30,8 +30,8 @@
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-raw_array_assign_scalar(int ndim, npy_intp *shape,
-        PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
+raw_array_assign_scalar(int ndim, npy_intp const *shape,
+        PyArray_Descr *dst_dtype, char *dst_data, npy_intp const *dst_strides,
         PyArray_Descr *src_dtype, char *src_data)
 {
     int idim;
@@ -101,11 +101,11 @@ raw_array_assign_scalar(int ndim, npy_intp *shape,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-raw_array_wheremasked_assign_scalar(int ndim, npy_intp *shape,
-        PyArray_Descr *dst_dtype, char *dst_data, npy_intp *dst_strides,
+raw_array_wheremasked_assign_scalar(int ndim, npy_intp const *shape,
+        PyArray_Descr *dst_dtype, char *dst_data, npy_intp const *dst_strides,
         PyArray_Descr *src_dtype, char *src_data,
         PyArray_Descr *wheremask_dtype, char *wheremask_data,
-        npy_intp *wheremask_strides)
+        npy_intp const *wheremask_strides)
 {
     int idim;
     npy_intp shape_it[NPY_MAXDIMS], dst_strides_it[NPY_MAXDIMS];
@@ -203,19 +203,8 @@ PyArray_AssignRawScalar(PyArrayObject *dst,
     /* Check the casting rule */
     if (!can_cast_scalar_to(src_dtype, src_data,
                             PyArray_DESCR(dst), casting)) {
-        PyObject *errmsg;
-        errmsg = PyUString_FromString("Cannot cast scalar from ");
-        PyUString_ConcatAndDel(&errmsg,
-                PyObject_Repr((PyObject *)src_dtype));
-        PyUString_ConcatAndDel(&errmsg,
-                PyUString_FromString(" to "));
-        PyUString_ConcatAndDel(&errmsg,
-                PyObject_Repr((PyObject *)PyArray_DESCR(dst)));
-        PyUString_ConcatAndDel(&errmsg,
-                PyUString_FromFormat(" according to the rule %s",
-                        npy_casting_to_string(casting)));
-        PyErr_SetObject(PyExc_TypeError, errmsg);
-        Py_DECREF(errmsg);
+        npy_set_invalid_cast_error(
+                src_dtype, PyArray_DESCR(dst), casting, NPY_TRUE);
         return -1;
     }
 
index a5cebfbd864604ed33f90cddf57fb8986694ad13..dedaf38eb6d1f4981f0cf24808964c584c6f4f7f 100644 (file)
@@ -41,6 +41,7 @@ maintainer email:  oliphant.travis@ieee.org
 #include "arraytypes.h"
 #include "scalartypes.h"
 #include "arrayobject.h"
+#include "conversion_utils.h"
 #include "ctors.h"
 #include "methods.h"
 #include "descriptor.h"
@@ -278,8 +279,8 @@ PyArray_CopyObject(PyArrayObject *dest, PyObject *src_object)
      * Get either an array object we can copy from, or its parameters
      * if there isn't a convenient array available.
      */
-    if (PyArray_GetArrayParamsFromObject(src_object, PyArray_DESCR(dest),
-                0, &dtype, &ndim, dims, &src, NULL) < 0) {
+    if (PyArray_GetArrayParamsFromObject_int(src_object,
+                PyArray_DESCR(dest), 0, &dtype, &ndim, dims, &src) < 0) {
         Py_DECREF(src_object);
         return -1;
     }
@@ -388,7 +389,7 @@ PyArray_CopyObject(PyArrayObject *dest, PyObject *src_object)
 /*NUMPY_API
  */
 NPY_NO_EXPORT int
-PyArray_TypeNumFromName(char *str)
+PyArray_TypeNumFromName(char const *str)
 {
     int i;
     PyArray_Descr *descr;
@@ -614,7 +615,7 @@ PyArray_SetDatetimeParseFunction(PyObject *NPY_UNUSED(op))
 /*NUMPY_API
  */
 NPY_NO_EXPORT int
-PyArray_CompareUCS4(npy_ucs4 *s1, npy_ucs4 *s2, size_t len)
+PyArray_CompareUCS4(npy_ucs4 const *s1, npy_ucs4 const *s2, size_t len)
 {
     npy_ucs4 c1, c2;
     while(len-- > 0) {
@@ -703,35 +704,40 @@ PyArray_FailUnlessWriteable(PyArrayObject *obj, const char *name)
    If they are NULL terminated, then stop comparison.
 */
 static int
-_myunincmp(npy_ucs4 *s1, npy_ucs4 *s2, int len1, int len2)
+_myunincmp(npy_ucs4 const *s1, npy_ucs4 const *s2, int len1, int len2)
 {
-    npy_ucs4 *sptr;
-    npy_ucs4 *s1t=s1, *s2t=s2;
+    npy_ucs4 const *sptr;
+    npy_ucs4 *s1t = NULL;
+    npy_ucs4 *s2t = NULL;
     int val;
     npy_intp size;
     int diff;
 
+    /* Replace `s1` and `s2` with aligned copies if needed */
     if ((npy_intp)s1 % sizeof(npy_ucs4) != 0) {
         size = len1*sizeof(npy_ucs4);
         s1t = malloc(size);
         memcpy(s1t, s1, size);
+        s1 = s1t;
     }
     if ((npy_intp)s2 % sizeof(npy_ucs4) != 0) {
         size = len2*sizeof(npy_ucs4);
         s2t = malloc(size);
         memcpy(s2t, s2, size);
+        s2 = s1t;
     }
-    val = PyArray_CompareUCS4(s1t, s2t, PyArray_MIN(len1,len2));
+
+    val = PyArray_CompareUCS4(s1, s2, PyArray_MIN(len1,len2));
     if ((val != 0) || (len1 == len2)) {
         goto finish;
     }
     if (len2 > len1) {
-        sptr = s2t+len1;
+        sptr = s2+len1;
         val = -1;
         diff = len2-len1;
     }
     else {
-        sptr = s1t+len2;
+        sptr = s1+len2;
         val = 1;
         diff=len1-len2;
     }
@@ -744,10 +750,11 @@ _myunincmp(npy_ucs4 *s1, npy_ucs4 *s2, int len1, int len2)
     val = 0;
 
  finish:
-    if (s1t != s1) {
+    /* Cleanup the aligned copies */
+    if (s1t) {
         free(s1t);
     }
-    if (s2t != s2) {
+    if (s2t) {
         free(s2t);
     }
     return val;
@@ -763,9 +770,9 @@ _myunincmp(npy_ucs4 *s1, npy_ucs4 *s2, int len1, int len2)
  * If they are NULL terminated, then stop comparison.
  */
 static int
-_mystrncmp(char *s1, char *s2, int len1, int len2)
+_mystrncmp(char const *s1, char const *s2, int len1, int len2)
 {
-    char *sptr;
+    char const *sptr;
     int val;
     int diff;
 
@@ -827,7 +834,7 @@ static void _unistripw(npy_ucs4 *s, int n)
 
 
 static char *
-_char_copy_n_strip(char *original, char *temp, int nc)
+_char_copy_n_strip(char const *original, char *temp, int nc)
 {
     if (nc > SMALL_STRING) {
         temp = malloc(nc);
@@ -850,7 +857,7 @@ _char_release(char *ptr, int nc)
 }
 
 static char *
-_uni_copy_n_strip(char *original, char *temp, int nc)
+_uni_copy_n_strip(char const *original, char *temp, int nc)
 {
     if (nc*sizeof(npy_ucs4) > SMALL_STRING) {
         temp = malloc(nc*sizeof(npy_ucs4));
@@ -919,7 +926,7 @@ _compare_strings(PyArrayObject *result, PyArrayMultiIterObject *multi,
     int N1, N2;
     int (*compfunc)(void *, void *, int, int);
     void (*relfunc)(char *, int);
-    char* (*stripfunc)(char *, char *, int);
+    char* (*stripfunc)(char const *, char *, int);
 
     compfunc = func;
     dptr = (npy_bool *)PyArray_DATA(result);
@@ -998,22 +1005,18 @@ _strings_richcompare(PyArrayObject *self, PyArrayObject *other, int cmp_op,
 {
     PyArrayObject *result;
     PyArrayMultiIterObject *mit;
-    int val, cast = 0;
+    int val;
 
     /* Cast arrays to a common type */
     if (PyArray_TYPE(self) != PyArray_DESCR(other)->type_num) {
-#if defined(NPY_PY3K)
         /*
          * Comparison between Bytes and Unicode is not defined in Py3K;
          * we follow.
          */
         Py_INCREF(Py_NotImplemented);
         return Py_NotImplemented;
-#else
-        cast = 1;
-#endif  /* define(NPY_PY3K) */
     }
-    if (cast || (PyArray_ISNOTSWAPPED(self) != PyArray_ISNOTSWAPPED(other))) {
+    if (PyArray_ISNOTSWAPPED(self) != PyArray_ISNOTSWAPPED(other)) {
         PyObject *new;
         if (PyArray_TYPE(self) == NPY_STRING &&
                 PyArray_DESCR(other)->type_num == NPY_UNICODE) {
@@ -1121,7 +1124,7 @@ _void_compare(PyArrayObject *self, PyArrayObject *other, int cmp_op)
 
         op = (cmp_op == Py_EQ ? n_ops.logical_and : n_ops.logical_or);
         while (PyDict_Next(PyArray_DESCR(self)->fields, &pos, &key, &value)) {
-            if NPY_TITLE_KEY(key, value) {
+            if (NPY_TITLE_KEY(key, value)) {
                 continue;
             }
             a = array_subscript_asarray(self, key);
@@ -1327,18 +1330,9 @@ _failed_comparison_workaround(PyArrayObject *self, PyObject *other, int cmp_op)
         /*
          * For LE, LT, GT, GE and a flexible self or other, we return
          * NotImplemented, which is the correct answer since the ufuncs do
-         * not in fact implement loops for those.  On python 3 this will
-         * get us the desired TypeError, but on python 2, one gets strange
-         * ordering, so we emit a warning.
+         * not in fact implement loops for those.  This will get us the
+         * desired TypeError.
          */
-#if !defined(NPY_PY3K)
-        /* 2015-05-14, 1.10 */
-        if (DEPRECATE(
-                "unorderable dtypes; returning scalar but in "
-                "the future this will be an error") < 0) {
-            goto fail;
-        }
-#endif
         Py_XDECREF(exc);
         Py_XDECREF(val);
         Py_XDECREF(tb);
@@ -1544,9 +1538,8 @@ array_richcompare(PyArrayObject *self, PyObject *other, int cmp_op)
          *   - If other is not convertible to an array, pass on the error
          *     (MHvK, 2018-06-18: not sure about this, but it's what we have).
          *
-         * However, for backwards compatibilty, we cannot yet return arrays,
-         * so we raise warnings instead.  Furthermore, we warn on python2
-         * for LT, LE, GE, GT, since fall-back behaviour is poorly defined.
+         * However, for backwards compatibility, we cannot yet return arrays,
+         * so we raise warnings instead.
          */
         result = _failed_comparison_workaround(self, other, cmp_op);
     }
@@ -1601,7 +1594,7 @@ PyArray_ElementStrides(PyObject *obj)
 /*NUMPY_API*/
 NPY_NO_EXPORT npy_bool
 PyArray_CheckStrides(int elsize, int nd, npy_intp numbytes, npy_intp offset,
-                     npy_intp *dims, npy_intp *newstrides)
+                     npy_intp const *dims, npy_intp const *newstrides)
 {
     npy_intp begin, end;
     npy_intp lower_offset;
@@ -1632,7 +1625,7 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
     PyArray_Descr *descr = NULL;
     int itemsize;
     PyArray_Dims dims = {NULL, 0};
-    PyArray_Dims strides = {NULL, 0};
+    PyArray_Dims strides = {NULL, -1};
     PyArray_Chunk buffer;
     npy_longlong offset = 0;
     NPY_ORDER order = NPY_CORDER;
@@ -1653,7 +1646,7 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
                                      PyArray_BufferConverter,
                                      &buffer,
                                      &offset,
-                                     &PyArray_IntpConverter,
+                                     &PyArray_OptionalIntpConverter,
                                      &strides,
                                      &PyArray_OrderConverter,
                                      &order)) {
@@ -1668,7 +1661,7 @@ array_new(PyTypeObject *subtype, PyObject *args, PyObject *kwds)
 
     itemsize = descr->elsize;
 
-    if (strides.ptr != NULL) {
+    if (strides.len != -1) {
         npy_intp nb, off;
         if (strides.len != dims.len) {
             PyErr_SetString(PyExc_ValueError,
@@ -1788,71 +1781,29 @@ array_free(PyObject * v)
 
 
 NPY_NO_EXPORT PyTypeObject PyArray_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.ndarray",                            /* tp_name */
-    NPY_SIZEOF_PYARRAYOBJECT,                   /* tp_basicsize */
-    0,                                          /* tp_itemsize */
+    .tp_name = "numpy.ndarray",
+    .tp_basicsize = NPY_SIZEOF_PYARRAYOBJECT,
     /* methods */
-    (destructor)array_dealloc,                  /* tp_dealloc */
-    (printfunc)NULL,                            /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    (reprfunc)array_repr,                       /* tp_repr */
-    &array_as_number,                           /* tp_as_number */
-    &array_as_sequence,                         /* tp_as_sequence */
-    &array_as_mapping,                          /* tp_as_mapping */
+    .tp_dealloc = (destructor)array_dealloc,
+    .tp_repr = (reprfunc)array_repr,
+    .tp_as_number = &array_as_number,
+    .tp_as_sequence = &array_as_sequence,
+    .tp_as_mapping = &array_as_mapping,
     /*
      * The tp_hash slot will be set PyObject_HashNotImplemented when the
      * module is loaded.
      */
-    (hashfunc)0,                                /* tp_hash */
-    (ternaryfunc)0,                             /* tp_call */
-    (reprfunc)array_str,                        /* tp_str */
-    (getattrofunc)0,                            /* tp_getattro */
-    (setattrofunc)0,                            /* tp_setattro */
-    &array_as_buffer,                           /* tp_as_buffer */
-    (Py_TPFLAGS_DEFAULT
-#if !defined(NPY_PY3K)
-     | Py_TPFLAGS_CHECKTYPES
-     | Py_TPFLAGS_HAVE_NEWBUFFER
-#endif
-     | Py_TPFLAGS_BASETYPE),                    /* tp_flags */
-    0,                                          /* tp_doc */
-
-    (traverseproc)0,                            /* tp_traverse */
-    (inquiry)0,                                 /* tp_clear */
-    (richcmpfunc)array_richcompare,             /* tp_richcompare */
-    offsetof(PyArrayObject_fields, weakreflist), /* tp_weaklistoffset */
-    (getiterfunc)array_iter,                    /* tp_iter */
-    (iternextfunc)0,                            /* tp_iternext */
-    array_methods,                              /* tp_methods */
-    0,                                          /* tp_members */
-    array_getsetlist,                           /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    (initproc)0,                                /* tp_init */
-    (allocfunc)array_alloc,                     /* tp_alloc */
-    (newfunc)array_new,                         /* tp_new */
-    (freefunc)array_free,                       /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_str = (reprfunc)array_str,
+    .tp_as_buffer = &array_as_buffer,
+    .tp_flags =(Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE),
+
+    .tp_richcompare = (richcmpfunc)array_richcompare,
+    .tp_weaklistoffset = offsetof(PyArrayObject_fields, weakreflist),
+    .tp_iter = (getiterfunc)array_iter,
+    .tp_methods = array_methods,
+    .tp_getset = array_getsetlist,
+    .tp_alloc = (allocfunc)array_alloc,
+    .tp_new = (newfunc)array_new,
+    .tp_free = (freefunc)array_free,
 };
index 6ec060db502a5e4e834ae016b948e5e4c2b7f439..38d5f21eb357519a24a8272faf2fd85cd6fb5362 100644 (file)
@@ -210,7 +210,7 @@ static int
     @type@ temp;  /* ensures alignment */
 
     if (PyArray_IsScalar(op, @kind@)) {
-        temp = ((Py@kind@ScalarObject *)op)->obval;
+        temp = PyArrayScalar_VAL(op, @kind@);
     }
     else {
         temp = (@type@)@func2@(op);
@@ -291,7 +291,7 @@ static int
     }
 
     if (PyArray_IsScalar(op, @kind@)){
-        temp = ((Py@kind@ScalarObject *)op)->obval;
+        temp = PyArrayScalar_VAL(op, @kind@);
     }
     else {
         if (op == Py_None) {
@@ -330,11 +330,7 @@ string_to_long_double(PyObject*op)
     /* Convert python long objects to a longdouble, without precision or range
      * loss via a double.
      */
-    if ((PyLong_Check(op) && !PyBool_Check(op))
-#if !defined(NPY_PY3K)
-        || (PyInt_Check(op) && !PyBool_Check(op))
-#endif
-    ) {
+    if ((PyLong_Check(op) && !PyBool_Check(op))) {
         return npy_longdouble_from_PyLong(op);
     }
 
@@ -410,7 +406,7 @@ LONGDOUBLE_setitem(PyObject *op, void *ov, void *vap)
     }
 
     if (PyArray_IsScalar(op, LongDouble)) {
-        temp = ((PyLongDoubleScalarObject *)op)->obval;
+        temp = PyArrayScalar_VAL(op, LongDouble);
     }
     else {
         /* In case something funny happened in PyArray_IsScalar */
@@ -454,12 +450,6 @@ static int
 UNICODE_setitem(PyObject *op, void *ov, void *vap)
 {
     PyArrayObject *ap = vap;
-    PyObject *temp;
-    Py_UNICODE *ptr;
-    int datalen;
-#ifndef Py_UNICODE_WIDE
-    char *buffer;
-#endif
 
     if (PyArray_IsZeroDim(op)) {
         return convert_to_scalar_and_retry(op, ov, vap, UNICODE_setitem);
@@ -470,7 +460,8 @@ UNICODE_setitem(PyObject *op, void *ov, void *vap)
                 "setting an array element with a sequence");
         return -1;
     }
-#if defined(NPY_PY3K)
+
+    PyObject *temp;
     if (PyBytes_Check(op)) {
         /* Try to decode from ASCII */
         temp = PyUnicode_FromEncodedObject(op, "ASCII", "strict");
@@ -479,23 +470,29 @@ UNICODE_setitem(PyObject *op, void *ov, void *vap)
         }
     }
     else if ((temp=PyObject_Str(op)) == NULL) {
-#else
-    if ((temp=PyObject_Unicode(op)) == NULL) {
-#endif
         return -1;
     }
-    ptr = PyUnicode_AS_UNICODE(temp);
-    if ((ptr == NULL) || (PyErr_Occurred())) {
+
+    /* truncate if needed */
+    Py_ssize_t max_len = PyArray_DESCR(ap)->elsize >> 2;
+    Py_ssize_t actual_len = PyUnicode_GetLength(temp);
+    if (actual_len < 0) {
         Py_DECREF(temp);
         return -1;
     }
-    datalen = PyUnicode_GET_DATA_SIZE(temp);
+    if (actual_len > max_len) {
+        Py_SETREF(temp, PyUnicode_Substring(temp, 0, max_len));
+        if (temp == NULL) {
+            return -1;
+        }
+        actual_len = max_len;
+    }
 
-#ifdef Py_UNICODE_WIDE
-    memcpy(ov, ptr, PyArray_MIN(PyArray_DESCR(ap)->elsize, datalen));
-#else
+    Py_ssize_t num_bytes = actual_len * 4;
+
+    char *buffer;
     if (!PyArray_ISALIGNED(ap)) {
-        buffer = PyArray_malloc(PyArray_DESCR(ap)->elsize);
+        buffer = PyArray_malloc(num_bytes);
         if (buffer == NULL) {
             Py_DECREF(temp);
             PyErr_NoMemory();
@@ -505,20 +502,23 @@ UNICODE_setitem(PyObject *op, void *ov, void *vap)
     else {
         buffer = ov;
     }
-    datalen = PyUCS2Buffer_AsUCS4(ptr, (npy_ucs4 *)buffer,
-            datalen >> 1, PyArray_DESCR(ap)->elsize >> 2);
-    datalen <<= 2;
+    if (PyUnicode_AsUCS4(temp, (Py_UCS4 *)buffer, actual_len, 0) == NULL) {
+        PyArray_free(buffer);
+        Py_DECREF(temp);
+        return -1;
+    }
+
     if (!PyArray_ISALIGNED(ap)) {
-        memcpy(ov, buffer, datalen);
+        memcpy(ov, buffer, num_bytes);
         PyArray_free(buffer);
     }
-#endif
+
     /* Fill in the rest of the space with 0 */
-    if (PyArray_DESCR(ap)->elsize > datalen) {
-        memset((char*)ov + datalen, 0, (PyArray_DESCR(ap)->elsize - datalen));
+    if (PyArray_DESCR(ap)->elsize > num_bytes) {
+        memset((char*)ov + num_bytes, 0, (PyArray_DESCR(ap)->elsize - num_bytes));
     }
     if (PyArray_ISBYTESWAPPED(ap)) {
-        byte_swap_vector(ov, PyArray_DESCR(ap)->elsize >> 2, 4);
+        byte_swap_vector(ov, actual_len, 4);
     }
     Py_DECREF(temp);
     return 0;
@@ -561,7 +561,6 @@ STRING_setitem(PyObject *op, void *ov, void *vap)
                 "setting an array element with a sequence");
         return -1;
     }
-#if defined(NPY_PY3K)
     if (PyUnicode_Check(op)) {
         /* Assume ASCII codec -- function similarly as Python 2 */
         temp = PyUnicode_AsASCIIString(op);
@@ -588,11 +587,6 @@ STRING_setitem(PyObject *op, void *ov, void *vap)
             return -1;
         }
     }
-#else
-    if ((temp = PyObject_Str(op)) == NULL) {
-        return -1;
-    }
-#endif
     if (PyBytes_AsStringAndSize(temp, &ptr, &len) < 0) {
         Py_DECREF(temp);
         return -1;
@@ -748,7 +742,7 @@ _setup_field(int i, PyArray_Descr *descr, PyArrayObject *arr,
     }
 
     ((PyArrayObject_fields *)(arr))->descr = new;
-    if ((new->alignment > 1) && 
+    if ((new->alignment > 1) &&
                 ((((uintptr_t)dstdata + offset) % new->alignment) != 0)) {
         PyArray_CLEARFLAGS(arr, NPY_ARRAY_ALIGNED);
     }
@@ -836,7 +830,7 @@ VOID_setitem(PyObject *op, void *input, void *vap)
             if (names_size != PyTuple_Size(op)) {
                 errmsg = PyUString_FromFormat(
                         "could not assign tuple of length %zd to structure "
-                        "with %" NPY_INTP_FMT " fields.", 
+                        "with %" NPY_INTP_FMT " fields.",
                         PyTuple_Size(op), names_size);
                 PyErr_SetObject(PyExc_ValueError, errmsg);
                 Py_DECREF(errmsg);
@@ -919,7 +913,6 @@ VOID_setitem(PyObject *op, void *input, void *vap)
      * undiscerning case: It interprets any object as a buffer
      * and reads as many bytes as possible, padding with 0.
      */
-#if defined(NPY_PY3K)
     {
         Py_buffer view;
 
@@ -933,20 +926,6 @@ VOID_setitem(PyObject *op, void *input, void *vap)
         PyBuffer_Release(&view);
         _dealloc_cached_buffer_info(op);
     }
-#else
-    {
-        const void *buffer;
-        Py_ssize_t buflen;
-
-        if (PyObject_AsReadBuffer(op, &buffer, &buflen) < 0) {
-            return -1;
-        }
-        memcpy(ip, buffer, PyArray_MIN(buflen, itemsize));
-        if (itemsize > buflen) {
-            memset(ip + buflen, 0, itemsize - buflen);
-        }
-    }
-#endif
     return 0;
 }
 
@@ -1510,6 +1489,7 @@ OBJECT_to_@TOTYPE@(void *input, void *output, npy_intp n,
  *
  * #from = STRING*23, UNICODE*23, VOID*23#
  * #fromtyp = npy_char*69#
+ * #is_string_to_bool = 1, 0*22, 1, 0*22, 0*23#
  * #to = (BOOL,
  *           BYTE, UBYTE, SHORT, USHORT, INT, UINT,
  *           LONG, ULONG, LONGLONG, ULONGLONG,
@@ -1527,16 +1507,8 @@ OBJECT_to_@TOTYPE@(void *input, void *output, npy_intp n,
  * #oskip = 1*18,(PyArray_DESCR(aop)->elsize)*3,1*2,
  *          1*18,(PyArray_DESCR(aop)->elsize)*3,1*2,
  *          1*18,(PyArray_DESCR(aop)->elsize)*3,1*2#
- * #convert = 1*14, 0, 1*3, 0*3, 1*2,
- *            1*14, 0, 1*3, 0*3, 1*2,
- *            0*23#
- * #convstr = (Int*9, Long*2, Float*4, Complex*3, Tuple*3, Long*2)*3#
  */
 
-#if @convert@
-
-#define IS_@from@
-
 static void
 @from@_to_@to@(void *input, void *output, npy_intp n,
         void *vaip, void *aop)
@@ -1550,70 +1522,17 @@ static void
     int oskip = @oskip@;
 
     for (i = 0; i < n; i++, ip+=skip, op+=oskip) {
-        PyObject *new;
         PyObject *temp = PyArray_Scalar(ip, PyArray_DESCR(aip), (PyObject *)aip);
         if (temp == NULL) {
             return;
         }
-
-#if defined(NPY_PY3K) && defined(IS_STRING)
-        /* Work around some Python 3K */
-        new = PyUnicode_FromEncodedObject(temp, "ascii", "strict");
-        Py_DECREF(temp);
-        temp = new;
+#if @is_string_to_bool@
+        /* Legacy behaviour converts strings to integers before going to bool */
+        Py_SETREF(temp, PyNumber_Long(temp));
         if (temp == NULL) {
             return;
         }
 #endif
-        /* convert from Python object to needed one */
-        {
-            PyObject *args;
-
-            /* call out to the Python builtin given by convstr */
-            args = Py_BuildValue("(N)", temp);
-#if defined(NPY_PY3K)
-#define PyInt_Type PyLong_Type
-#endif
-            new = Py@convstr@_Type.tp_new(&Py@convstr@_Type, args, NULL);
-#if defined(NPY_PY3K)
-#undef PyInt_Type
-#endif
-            Py_DECREF(args);
-            temp = new;
-            if (temp == NULL) {
-                return;
-            }
-        }
-
-        if (@to@_setitem(temp, op, aop)) {
-            Py_DECREF(temp);
-            return;
-        }
-        Py_DECREF(temp);
-    }
-}
-
-#undef IS_@from@
-
-#else
-
-static void
-@from@_to_@to@(void *input, void *output, npy_intp n,
-        void *vaip, void *aop)
-{
-    @fromtyp@ *ip = input;
-    @totyp@ *op = output;
-    PyArrayObject *aip = vaip;
-
-    npy_intp i;
-    int skip = PyArray_DESCR(aip)->elsize;
-    int oskip = @oskip@;
-
-    for (i = 0; i < n; i++, ip+=skip, op+=oskip) {
-        PyObject *temp = PyArray_Scalar(ip, PyArray_DESCR(aip), (PyObject *)aip);
-        if (temp == NULL) {
-            return;
-        }
         if (@to@_setitem(temp, op, aop)) {
             Py_DECREF(temp);
             return;
@@ -1622,7 +1541,6 @@ static void
     }
 }
 
-#endif
 
 /**end repeat**/
 
@@ -2325,6 +2243,7 @@ static void
 STRING_copyswapn (char *dst, npy_intp dstride, char *src, npy_intp sstride,
                   npy_intp n, int NPY_UNUSED(swap), PyArrayObject *arr)
 {
+    assert(arr != NULL);
     if (arr == NULL) {
         return;
     }
@@ -2339,6 +2258,7 @@ VOID_copyswapn (char *dst, npy_intp dstride, char *src, npy_intp sstride,
 {
     PyArray_Descr *descr;
 
+    assert(arr != NULL);
     if (arr == NULL) {
         return;
     }
@@ -2429,6 +2349,7 @@ VOID_copyswap (char *dst, char *src, int swap, PyArrayObject *arr)
 {
     PyArray_Descr *descr;
 
+    assert(arr != NULL);
     if (arr == NULL) {
         return;
     }
@@ -2510,6 +2431,7 @@ UNICODE_copyswapn (char *dst, npy_intp dstride, char *src, npy_intp sstride,
 {
     int itemsize;
 
+    assert(arr != NULL);
     if (arr == NULL) {
         return;
     }
@@ -2537,6 +2459,7 @@ UNICODE_copyswapn (char *dst, npy_intp dstride, char *src, npy_intp sstride,
 static void
 STRING_copyswap(char *dst, char *src, int NPY_UNUSED(swap), PyArrayObject *arr)
 {
+    assert(arr != NULL);
     if (arr == NULL) {
         return;
     }
@@ -2549,6 +2472,7 @@ UNICODE_copyswap (char *dst, char *src, int swap, PyArrayObject *arr)
 {
     int itemsize;
 
+    assert(arr != NULL);
     if (arr == NULL) {
         return;
     }
@@ -2679,12 +2603,6 @@ STRING_nonzero (char *ip, PyArrayObject *ap)
     return nonz;
 }
 
-#ifdef Py_UNICODE_WIDE
-#define PyArray_UCS4_ISSPACE Py_UNICODE_ISSPACE
-#else
-#define PyArray_UCS4_ISSPACE(ch) Py_STRING_ISSPACE((char)ch)
-#endif
-
 static npy_bool
 UNICODE_nonzero (npy_ucs4 *ip, PyArrayObject *ap)
 {
@@ -2710,7 +2628,7 @@ UNICODE_nonzero (npy_ucs4 *ip, PyArrayObject *ap)
         if (*ip == '\0') {
             seen_null = NPY_TRUE;
         }
-        else if (seen_null || !PyArray_UCS4_ISSPACE(*ip)) {
+        else if (seen_null || !Py_UNICODE_ISSPACE(*ip)) {
             nonz = NPY_TRUE;
             break;
         }
@@ -3000,7 +2918,7 @@ OBJECT_compare(PyObject **ip1, PyObject **ip2, PyArrayObject *NPY_UNUSED(ap))
 
     ret = PyObject_RichCompareBool(*ip1, *ip2, Py_LT);
     if (ret < 0) {
-        /* error occurred, avoid the next call to PyObject_RichCompareBool */ 
+        /* error occurred, avoid the next call to PyObject_RichCompareBool */
         return 0;
     }
     if (ret == 1) {
@@ -3921,172 +3839,6 @@ static void
 /**end repeat**/
 
 
-/*
- *****************************************************************************
- **                              FASTPUTMASK                                **
- *****************************************************************************
- */
-
-
-/**begin repeat
- *
- * #name = BOOL,
- *         BYTE, UBYTE, SHORT, USHORT, INT, UINT,
- *         LONG, ULONG, LONGLONG, ULONGLONG,
- *         HALF, FLOAT, DOUBLE, LONGDOUBLE,
- *         CFLOAT, CDOUBLE, CLONGDOUBLE,
- *         DATETIME, TIMEDELTA#
- * #type = npy_bool, npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
- *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
- *         npy_half, npy_float, npy_double, npy_longdouble,
- *         npy_cfloat, npy_cdouble, npy_clongdouble,
- *         npy_datetime, npy_timedelta#
-*/
-static void
-@name@_fastputmask(@type@ *in, npy_bool *mask, npy_intp ni, @type@ *vals,
-        npy_intp nv)
-{
-    npy_intp i, j;
-
-    if (nv == 1) {
-        @type@ s_val = *vals;
-        for (i = 0; i < ni; i++) {
-            if (mask[i]) {
-                in[i] = s_val;
-            }
-        }
-    }
-    else {
-        for (i = 0, j = 0; i < ni; i++, j++) {
-            if (j >= nv) {
-                j = 0;
-            }
-            if (mask[i]) {
-                in[i] = vals[j];
-            }
-        }
-    }
-    return;
-}
-/**end repeat**/
-
-#define OBJECT_fastputmask NULL
-
-
-/*
- *****************************************************************************
- **                                FASTTAKE                                 **
- *****************************************************************************
- */
-
-
-/**begin repeat
- *
- * #name = BOOL,
- *         BYTE, UBYTE, SHORT, USHORT, INT, UINT,
- *         LONG, ULONG, LONGLONG, ULONGLONG,
- *         HALF, FLOAT, DOUBLE, LONGDOUBLE,
- *         CFLOAT, CDOUBLE, CLONGDOUBLE,
- *         DATETIME, TIMEDELTA#
- * #type = npy_bool,
- *         npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
- *         npy_long, npy_ulong, npy_longlong, npy_ulonglong,
- *         npy_half, npy_float, npy_double, npy_longdouble,
- *         npy_cfloat, npy_cdouble, npy_clongdouble,
- *         npy_datetime, npy_timedelta#
-*/
-static int
-@name@_fasttake(@type@ *dest, @type@ *src, npy_intp *indarray,
-                    npy_intp nindarray, npy_intp n_outer,
-                    npy_intp m_middle, npy_intp nelem,
-                    NPY_CLIPMODE clipmode)
-{
-    npy_intp i, j, k, tmp;
-    NPY_BEGIN_THREADS_DEF;
-
-    NPY_BEGIN_THREADS;
-
-    switch(clipmode) {
-    case NPY_RAISE:
-        for (i = 0; i < n_outer; i++) {
-            for (j = 0; j < m_middle; j++) {
-                tmp = indarray[j];
-                /*
-                 * We don't know what axis we're operating on,
-                 * so don't report it in case of an error.
-                 */
-                if (check_and_adjust_index(&tmp, nindarray, -1, _save) < 0) {
-                    return 1;
-                }
-                if (NPY_LIKELY(nelem == 1)) {
-                    *dest++ = *(src + tmp);
-                }
-                else {
-                    for (k = 0; k < nelem; k++) {
-                        *dest++ = *(src + tmp*nelem + k);
-                    }
-                }
-            }
-            src += nelem*nindarray;
-        }
-        break;
-    case NPY_WRAP:
-        for (i = 0; i < n_outer; i++) {
-            for (j = 0; j < m_middle; j++) {
-                tmp = indarray[j];
-                if (tmp < 0) {
-                    while (tmp < 0) {
-                        tmp += nindarray;
-                    }
-                }
-                else if (tmp >= nindarray) {
-                    while (tmp >= nindarray) {
-                        tmp -= nindarray;
-                    }
-                }
-                if (NPY_LIKELY(nelem == 1)) {
-                    *dest++ = *(src+tmp);
-                }
-                else {
-                    for (k = 0; k < nelem; k++) {
-                        *dest++ = *(src+tmp*nelem+k);
-                    }
-                }
-            }
-            src += nelem*nindarray;
-        }
-        break;
-    case NPY_CLIP:
-        for (i = 0; i < n_outer; i++) {
-            for (j = 0; j < m_middle; j++) {
-                tmp = indarray[j];
-                if (tmp < 0) {
-                    tmp = 0;
-                }
-                else if (tmp >= nindarray) {
-                    tmp = nindarray - 1;
-                }
-                if (NPY_LIKELY(nelem == 1)) {
-                    *dest++ = *(src + tmp);
-                }
-                else {
-                    for (k = 0; k < nelem; k++) {
-                        *dest++ = *(src + tmp*nelem + k);
-                    }
-                }
-            }
-            src += nelem*nindarray;
-        }
-        break;
-    }
-
-    NPY_END_THREADS;
-    return 0;
-}
-/**end repeat**/
-
-#define OBJECT_fasttake NULL
-
 /*
  *****************************************************************************
  **                       small correlate                                   **
@@ -4094,7 +3846,7 @@ static int
  */
 
 /*
- * Compute correlation of data with with small kernels
+ * Compute correlation of data with small kernels
  * Calling a BLAS dot product for the inner loop of the correlation is overkill
  * for small kernels. It is faster to compute it directly.
  * Intended to be used by _pyarray_correlate so no input verifications is done
@@ -4193,7 +3945,7 @@ _datetime_dtype_metadata_clone(NpyAuxData *data)
 }
 
 /*
- * Allcoate and initialize a PyArray_DatetimeDTypeMetaData object
+ * Allocate and initialize a PyArray_DatetimeDTypeMetaData object
  */
 static NpyAuxData*
 _create_datetime_metadata(NPY_DATETIMEUNIT base, int num)
@@ -4429,7 +4181,7 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = {
         #if @rsort@
             aradixsort_@suff@
         #else
-            atimsort_@suff@            
+            atimsort_@suff@
         #endif
     },
 #else
@@ -4445,8 +4197,8 @@ static PyArray_ArrFuncs _Py@NAME@_ArrFuncs = {
     NULL,
     NULL,
     (PyArray_FastClipFunc*)NULL,
-    (PyArray_FastPutmaskFunc*)@from@_fastputmask,
-    (PyArray_FastTakeFunc*)@from@_fasttake,
+    (PyArray_FastPutmaskFunc*)NULL,
+    (PyArray_FastTakeFunc*)NULL,
     (PyArray_ArgFunc*)@from@_argmin
 };
 
@@ -4722,7 +4474,7 @@ set_typeinfo(PyObject *dict)
     infodict = PyDict_New();
     if (infodict == NULL) return -1;
 
-
+    int ret;
     /**begin repeat
      *
      * #name = BOOL,
@@ -4765,10 +4517,15 @@ set_typeinfo(PyObject *dict)
         &Py@Name@ArrType_Type
     );
     if (s == NULL) {
+        Py_DECREF(infodict);
         return -1;
     }
-    PyDict_SetItemString(infodict, "@name@", s);
+    ret = PyDict_SetItemString(infodict, "@name@", s);
     Py_DECREF(s);
+    if (ret < 0) {
+        Py_DECREF(infodict);
+        return -1;
+    }
 
 
     /**end repeat**/
@@ -4788,10 +4545,15 @@ set_typeinfo(PyObject *dict)
         _ALIGN(@type@), &Py@Name@ArrType_Type
     );
     if (s == NULL) {
+        Py_DECREF(infodict);
         return -1;
     }
-    PyDict_SetItemString(infodict, "@name@", s);
+    ret = PyDict_SetItemString(infodict, "@name@", s);
     Py_DECREF(s);
+    if (ret < 0) {
+        Py_DECREF(infodict);
+        return -1;
+    }
 
     /**end repeat**/
 
@@ -4801,37 +4563,57 @@ set_typeinfo(PyObject *dict)
         &PyObjectArrType_Type
     );
     if (s == NULL) {
+        Py_DECREF(infodict);
         return -1;
     }
-    PyDict_SetItemString(infodict, "OBJECT", s);
+    ret = PyDict_SetItemString(infodict, "OBJECT", s);
     Py_DECREF(s);
+    if (ret < 0) {
+        Py_DECREF(infodict);
+        return -1;
+    }
     s = PyArray_typeinfo(
         NPY_STRINGLTR, NPY_STRING, 0, _ALIGN(char),
         &PyStringArrType_Type
     );
     if (s == NULL) {
+        Py_DECREF(infodict);
         return -1;
     }
-    PyDict_SetItemString(infodict, "STRING", s);
+    ret = PyDict_SetItemString(infodict, "STRING", s);
     Py_DECREF(s);
+    if (ret < 0) {
+        Py_DECREF(infodict);
+        return -1;
+    }
     s = PyArray_typeinfo(
         NPY_UNICODELTR, NPY_UNICODE, 0, _ALIGN(npy_ucs4),
         &PyUnicodeArrType_Type
     );
     if (s == NULL) {
+        Py_DECREF(infodict);
         return -1;
     }
-    PyDict_SetItemString(infodict, "UNICODE", s);
+    ret = PyDict_SetItemString(infodict, "UNICODE", s);
     Py_DECREF(s);
+    if (ret < 0) {
+        Py_DECREF(infodict);
+        return -1;
+    }
     s = PyArray_typeinfo(
         NPY_VOIDLTR, NPY_VOID, 0, _ALIGN(char),
         &PyVoidArrType_Type
     );
     if (s == NULL) {
+        Py_DECREF(infodict);
         return -1;
     }
-    PyDict_SetItemString(infodict, "VOID", s);
+    ret = PyDict_SetItemString(infodict, "VOID", s);
     Py_DECREF(s);
+    if (ret < 0) {
+        Py_DECREF(infodict);
+        return -1;
+    }
     s = PyArray_typeinforanged(
         NPY_DATETIMELTR, NPY_DATETIME, NPY_BITSOF_DATETIME,
         _ALIGN(npy_datetime),
@@ -4840,10 +4622,15 @@ set_typeinfo(PyObject *dict)
         &PyDatetimeArrType_Type
     );
     if (s == NULL) {
+        Py_DECREF(infodict);
         return -1;
     }
-    PyDict_SetItemString(infodict, "DATETIME", s);
+    ret = PyDict_SetItemString(infodict, "DATETIME", s);
     Py_DECREF(s);
+    if (ret < 0) {
+        Py_DECREF(infodict);
+        return -1;
+    }
     s = PyArray_typeinforanged(
         NPY_TIMEDELTALTR, NPY_TIMEDELTA, NPY_BITSOF_TIMEDELTA,
         _ALIGN(npy_timedelta),
@@ -4852,15 +4639,23 @@ set_typeinfo(PyObject *dict)
         &PyTimedeltaArrType_Type
     );
     if (s == NULL) {
+        Py_DECREF(infodict);
         return -1;
     }
-    PyDict_SetItemString(infodict, "TIMEDELTA", s);
+    ret = PyDict_SetItemString(infodict, "TIMEDELTA", s);
     Py_DECREF(s);
+    if (ret < 0) {
+        Py_DECREF(infodict);
+        return -1;
+    }
 
-#define SETTYPE(name)                           \
-    Py_INCREF(&Py##name##ArrType_Type);         \
-    PyDict_SetItemString(infodict, #name,       \
-            (PyObject *)&Py##name##ArrType_Type)
+#define SETTYPE(name)                                   \
+    Py_INCREF(&Py##name##ArrType_Type);                 \
+    if (PyDict_SetItemString(infodict, #name,           \
+            (PyObject *)&Py##name##ArrType_Type) < 0) { \
+        Py_DECREF(infodict);                            \
+        return -1;                                      \
+    }
 
     SETTYPE(Generic);
     SETTYPE(Number);
@@ -4875,8 +4670,11 @@ set_typeinfo(PyObject *dict)
 
 #undef SETTYPE
 
-    PyDict_SetItemString(dict, "typeinfo", infodict);
+    ret = PyDict_SetItemString(dict, "typeinfo", infodict);
     Py_DECREF(infodict);
+    if (ret < 0) {
+        return -1;
+    }
     return 0;
 }
 
index 0edadee982c23562ee4f107b40effe45267438f5..9a1f7b2307e03d0dd90b0104b689338ad5597aa2 100644 (file)
  ****************   Implement Buffer Protocol ****************************
  *************************************************************************/
 
-/* removed multiple segment interface */
-
-#if !defined(NPY_PY3K)
-static Py_ssize_t
-array_getsegcount(PyArrayObject *self, Py_ssize_t *lenp)
-{
-    if (lenp) {
-        *lenp = PyArray_NBYTES(self);
-    }
-    if (PyArray_ISONESEGMENT(self)) {
-        return 1;
-    }
-    if (lenp) {
-        *lenp = 0;
-    }
-    return 0;
-}
-
-static Py_ssize_t
-array_getreadbuf(PyArrayObject *self, Py_ssize_t segment, void **ptrptr)
-{
-    if (segment != 0) {
-        PyErr_SetString(PyExc_ValueError,
-                        "accessing non-existing array segment");
-        return -1;
-    }
-    if (PyArray_ISONESEGMENT(self)) {
-        *ptrptr = PyArray_DATA(self);
-        return PyArray_NBYTES(self);
-    }
-    PyErr_SetString(PyExc_ValueError, "array is not a single segment");
-    *ptrptr = NULL;
-    return -1;
-}
-
-
-static Py_ssize_t
-array_getwritebuf(PyArrayObject *self, Py_ssize_t segment, void **ptrptr)
-{
-    if (PyArray_FailUnlessWriteable(self, "buffer source array") < 0) {
-        return -1;
-    }
-    return array_getreadbuf(self, segment, (void **) ptrptr);
-}
-
-static Py_ssize_t
-array_getcharbuf(PyArrayObject *self, Py_ssize_t segment, constchar **ptrptr)
-{
-    return array_getreadbuf(self, segment, (void **) ptrptr);
-}
-#endif /* !defined(NPY_PY3K) */
-
-
 /*************************************************************************
  * PEP 3118 buffer protocol
  *
@@ -151,13 +98,8 @@ _append_field_name(_tmp_string_t *str, PyObject *name)
     char *p;
     Py_ssize_t len;
     PyObject *tmp;
-#if defined(NPY_PY3K)
     /* FIXME: XXX -- should it use UTF-8 here? */
     tmp = PyUnicode_AsUTF8String(name);
-#else
-    tmp = name;
-    Py_INCREF(tmp);
-#endif
     if (tmp == NULL || PyBytes_AsStringAndSize(tmp, &p, &len) < 0) {
         PyErr_Clear();
         PyErr_SetString(PyExc_ValueError, "invalid field name");
@@ -523,7 +465,7 @@ _buffer_info_new(PyObject *obj)
         /*
          * Special case datetime64 scalars to remain backward compatible.
          * This will change in a future version.
-         * Note arrays of datetime64 and strutured arrays with datetime64
+         * Note arrays of datetime64 and structured arrays with datetime64
          * fields will not hit this code path and are currently unsupported
          * in _buffer_format_string.
          */
@@ -890,11 +832,6 @@ gentype_getbuffer(PyObject *self, Py_buffer *view, int flags)
     descr = PyArray_DescrFromScalar(self);
     view->buf = (void *)scalar_value(self, descr);
     elsize = descr->elsize;
-#ifndef Py_UNICODE_WIDE
-    if (descr->type_num == NPY_UNICODE) {
-        elsize >>= 1;
-    }
-#endif
     view->len = elsize;
     if (PyArray_IsScalar(self, Datetime) || PyArray_IsScalar(self, Timedelta)) {
         elsize = 1; /* descr->elsize,char is 8,'M', but we return 1,'B' */
@@ -952,12 +889,6 @@ _dealloc_cached_buffer_info(PyObject *self)
 /*************************************************************************/
 
 NPY_NO_EXPORT PyBufferProcs array_as_buffer = {
-#if !defined(NPY_PY3K)
-    (readbufferproc)array_getreadbuf,       /*bf_getreadbuffer*/
-    (writebufferproc)array_getwritebuf,     /*bf_getwritebuffer*/
-    (segcountproc)array_getsegcount,        /*bf_getsegcount*/
-    (charbufferproc)array_getcharbuf,       /*bf_getcharbuffer*/
-#endif
     (getbufferproc)array_getbuffer,
     (releasebufferproc)0,
 };
@@ -968,13 +899,13 @@ NPY_NO_EXPORT PyBufferProcs array_as_buffer = {
  */
 
 static int
-_descriptor_from_pep3118_format_fast(char *s, PyObject **result);
+_descriptor_from_pep3118_format_fast(char const *s, PyObject **result);
 
 static int
 _pep3118_letter_to_type(char letter, int native, int complex);
 
 NPY_NO_EXPORT PyArray_Descr*
-_descriptor_from_pep3118_format(char *s)
+_descriptor_from_pep3118_format(char const *s)
 {
     char *buf, *p;
     int in_name = 0;
@@ -1059,7 +990,7 @@ _descriptor_from_pep3118_format(char *s)
  */
 
 static int
-_descriptor_from_pep3118_format_fast(char *s, PyObject **result)
+_descriptor_from_pep3118_format_fast(char const *s, PyObject **result)
 {
     PyArray_Descr *descr;
 
index 1d72a52273a71da053e6bc6fad5bd52922c37fe6..92ab75053c9df6b41dbf90b9495fc29589058ca0 100644 (file)
@@ -772,11 +772,7 @@ PyArray_Mean(PyArrayObject *self, int axis, int rtype, PyArrayObject *out)
         return NULL;
     }
     if (!out) {
-#if defined(NPY_PY3K)
         ret = PyNumber_TrueDivide(obj1, obj2);
-#else
-        ret = PyNumber_Divide(obj1, obj2);
-#endif
     }
     else {
         ret = PyObject_CallFunction(n_ops.divide, "OOO", out, obj2, out);
@@ -930,14 +926,15 @@ PyArray_Clip(PyArrayObject *self, PyObject *min, PyObject *max, PyArrayObject *o
         }
     }
 
-    /* NumPy 1.17.0, 2019-02-24 */
-    if (DEPRECATE(
-            "->f->fastclip is deprecated. Use PyUFunc_RegisterLoopForDescr to "
-            "attach a custom loop to np.core.umath.clip, np.minimum, and "
-            "np.maximum") < 0) {
-        return NULL;
-    }
-    /* everything below can be removed once this deprecation completes */
+    /*
+     * NumPy 1.17.0, 2019-02-24
+     * NumPy 1.19.0, 2020-01-15
+     *
+     * Setting `->f->fastclip to anything but NULL has been deprecated in 1.19
+     * the code path below was previously deprecated since 1.17.
+     * (the deprecation moved to registration time instead of execution time)
+     * everything below can be removed once this deprecation completes
+     */
 
     if (func == NULL
         || (min != NULL && !PyArray_CheckAnyScalar(min))
index c991f74288b31265a88afcf128cf189439ea7cca..0150ae10ee183a84be25b0d33aeca0f8ece882ad 100644 (file)
@@ -121,6 +121,57 @@ PyArray_DTypeFromObject(PyObject *obj, int maxdims, PyArray_Descr **out_dtype)
     return res;
 }
 
+/*
+ * Get a suitable string dtype by calling `__str__`.
+ * For `np.bytes_`, this assumes an ASCII encoding.
+ */
+static PyArray_Descr *
+PyArray_DTypeFromObjectStringDiscovery(
+        PyObject *obj, PyArray_Descr *last_dtype, int string_type)
+{
+    int itemsize;
+
+    if (string_type == NPY_STRING) {
+        PyObject *temp = PyObject_Str(obj);
+        if (temp == NULL) {
+            return NULL;
+        }
+        /* assume that when we do the encoding elsewhere we'll use ASCII */
+        itemsize = PyUnicode_GetLength(temp);
+        Py_DECREF(temp);
+        if (itemsize < 0) {
+            return NULL;
+        }
+    }
+    else if (string_type == NPY_UNICODE) {
+        PyObject *temp = PyObject_Str(obj);
+        if (temp == NULL) {
+            return NULL;
+        }
+        itemsize = PyUnicode_GetLength(temp);
+        Py_DECREF(temp);
+        if (itemsize < 0) {
+            return NULL;
+        }
+        itemsize *= 4;  /* convert UCS4 codepoints to bytes */
+    }
+    else {
+        return NULL;
+    }
+    if (last_dtype != NULL &&
+            last_dtype->type_num == string_type &&
+            last_dtype->elsize >= itemsize) {
+        Py_INCREF(last_dtype);
+        return last_dtype;
+    }
+    PyArray_Descr *dtype = PyArray_DescrNewFromType(string_type);
+    if (dtype == NULL) {
+        return NULL;
+    }
+    dtype->elsize = itemsize;
+    return dtype;
+}
+
 NPY_NO_EXPORT int
 PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
                               PyArray_Descr **out_dtype, int string_type)
@@ -158,50 +209,17 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
             }
         }
         else {
-            int itemsize;
-            PyObject *temp;
-
-            if (string_type == NPY_STRING) {
-                if ((temp = PyObject_Str(obj)) == NULL) {
-                    goto fail;
-                }
-#if defined(NPY_PY3K)
-    #if PY_VERSION_HEX >= 0x03030000
-                itemsize = PyUnicode_GetLength(temp);
-    #else
-                itemsize = PyUnicode_GET_SIZE(temp);
-    #endif
-#else
-                itemsize = PyString_GET_SIZE(temp);
-#endif
-            }
-            else if (string_type == NPY_UNICODE) {
-#if defined(NPY_PY3K)
-                if ((temp = PyObject_Str(obj)) == NULL) {
-#else
-                if ((temp = PyObject_Unicode(obj)) == NULL) {
-#endif
-                    goto fail;
-                }
-                itemsize = PyUnicode_GET_DATA_SIZE(temp);
-#ifndef Py_UNICODE_WIDE
-                itemsize <<= 1;
-#endif
-            }
-            else {
+            dtype = PyArray_DTypeFromObjectStringDiscovery(
+                    obj, *out_dtype, string_type);
+            if (dtype == NULL) {
                 goto fail;
             }
-            Py_DECREF(temp);
-            if (*out_dtype != NULL &&
-                    (*out_dtype)->type_num == string_type &&
-                    (*out_dtype)->elsize >= itemsize) {
+
+            /* nothing to do, dtype is already correct */
+            if (dtype == *out_dtype){
+                Py_DECREF(dtype);
                 return 0;
             }
-            dtype = PyArray_DescrNewFromType(string_type);
-            if (dtype == NULL) {
-                goto fail;
-            }
-            dtype->elsize = itemsize;
         }
         goto promote_types;
     }
@@ -210,54 +228,19 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
     dtype = _array_find_python_scalar_type(obj);
     if (dtype != NULL) {
         if (string_type) {
-            int itemsize;
-            PyObject *temp;
-
             /* dtype is not used in this (string discovery) branch */
             Py_DECREF(dtype);
-            dtype = NULL;
-
-            if (string_type == NPY_STRING) {
-                if ((temp = PyObject_Str(obj)) == NULL) {
-                    goto fail;
-                }
-#if defined(NPY_PY3K)
-    #if PY_VERSION_HEX >= 0x03030000
-                itemsize = PyUnicode_GetLength(temp);
-    #else
-                itemsize = PyUnicode_GET_SIZE(temp);
-    #endif
-#else
-                itemsize = PyString_GET_SIZE(temp);
-#endif
-            }
-            else if (string_type == NPY_UNICODE) {
-#if defined(NPY_PY3K)
-                if ((temp = PyObject_Str(obj)) == NULL) {
-#else
-                if ((temp = PyObject_Unicode(obj)) == NULL) {
-#endif
-                    goto fail;
-                }
-                itemsize = PyUnicode_GET_DATA_SIZE(temp);
-#ifndef Py_UNICODE_WIDE
-                itemsize <<= 1;
-#endif
-            }
-            else {
+            dtype = PyArray_DTypeFromObjectStringDiscovery(
+                    obj, *out_dtype, string_type);
+            if (dtype == NULL) {
                 goto fail;
             }
-            Py_DECREF(temp);
-            if (*out_dtype != NULL &&
-                    (*out_dtype)->type_num == string_type &&
-                    (*out_dtype)->elsize >= itemsize) {
+
+            /* nothing to do, dtype is already correct */
+            if (dtype == *out_dtype){
+                Py_DECREF(dtype);
                 return 0;
             }
-            dtype = PyArray_DescrNewFromType(string_type);
-            if (dtype == NULL) {
-                goto fail;
-            }
-            dtype->elsize = itemsize;
         }
         goto promote_types;
     }
@@ -282,10 +265,11 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
 
     /* Check if it's a Unicode string */
     if (PyUnicode_Check(obj)) {
-        int itemsize = PyUnicode_GET_DATA_SIZE(obj);
-#ifndef Py_UNICODE_WIDE
-        itemsize <<= 1;
-#endif
+        int itemsize = PyUnicode_GetLength(obj);
+        if (itemsize < 0) {
+            goto fail;
+        }
+        itemsize *= 4;
 
         /*
          * If it's already a big enough unicode object,
@@ -340,24 +324,21 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
     if (ip != NULL) {
         if (PyDict_Check(ip)) {
             PyObject *typestr;
-#if defined(NPY_PY3K)
             PyObject *tmp = NULL;
-#endif
-            typestr = PyDict_GetItemString(ip, "typestr");
-#if defined(NPY_PY3K)
+            typestr = _PyDict_GetItemStringWithError(ip, "typestr");
+            if (typestr == NULL && PyErr_Occurred()) {
+                goto fail;
+            }
             /* Allow unicode type strings */
             if (typestr && PyUnicode_Check(typestr)) {
                 tmp = PyUnicode_AsASCIIString(typestr);
                 typestr = tmp;
             }
-#endif
             if (typestr && PyBytes_Check(typestr)) {
                 dtype =_array_typedescr_fromstr(PyBytes_AS_STRING(typestr));
-#if defined(NPY_PY3K)
                 if (tmp == typestr) {
                     Py_DECREF(tmp);
                 }
-#endif
                 Py_DECREF(ip);
                 if (dtype == NULL) {
                     goto fail;
@@ -397,19 +378,6 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
         PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
     }
 
-    /* The old buffer interface */
-#if !defined(NPY_PY3K)
-    if (PyBuffer_Check(obj)) {
-        dtype = PyArray_DescrNewFromType(NPY_VOID);
-        if (dtype == NULL) {
-            goto fail;
-        }
-        dtype->elsize = Py_TYPE(obj)->tp_as_sequence->sq_length(obj);
-        PyErr_Clear();
-        goto promote_types;
-    }
-#endif
-
     /* The __array__ attribute */
     ip = PyArray_LookupSpecial_OnInstance(obj, "__array__");
     if (ip != NULL) {
@@ -478,9 +446,6 @@ PyArray_DTypeFromObjectHelper(PyObject *obj, int maxdims,
     if (common_type != NULL && !string_type &&
             (common_type == &PyFloat_Type ||
 /* TODO: we could add longs if we add a range check */
-#if !defined(NPY_PY3K)
-             common_type == &PyInt_Type ||
-#endif
              common_type == &PyBool_Type ||
              common_type == &PyComplex_Type)) {
         size = 1;
@@ -554,7 +519,7 @@ fail:
 
 /* new reference */
 NPY_NO_EXPORT PyArray_Descr *
-_array_typedescr_fromstr(char *c_str)
+_array_typedescr_fromstr(char const *c_str)
 {
     PyArray_Descr *descr = NULL;
     PyObject *stringobj = PyString_FromString(c_str);
@@ -612,12 +577,7 @@ NPY_NO_EXPORT npy_bool
 _IsWriteable(PyArrayObject *ap)
 {
     PyObject *base = PyArray_BASE(ap);
-#if defined(NPY_PY3K)
     Py_buffer view;
-#else
-    void *dummy;
-    Py_ssize_t n;
-#endif
 
     /*
      * C-data wrapping arrays may not own their data while not having a base;
@@ -661,7 +621,6 @@ _IsWriteable(PyArrayObject *ap)
         assert(!PyArray_CHKFLAGS(ap, NPY_ARRAY_OWNDATA));
     }
 
-#if defined(NPY_PY3K)
     if (PyObject_GetBuffer(base, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
         PyErr_Clear();
         return NPY_FALSE;
@@ -675,12 +634,6 @@ _IsWriteable(PyArrayObject *ap)
      * _dealloc_cached_buffer_info, but in this case leave it in the cache to
      * speed up future calls to _IsWriteable.
      */
-#else
-    if (PyObject_AsWriteBuffer(base, &dummy, &n) < 0) {
-        PyErr_Clear();
-        return NPY_FALSE;
-    }
-#endif
     return NPY_TRUE;
 }
 
@@ -695,7 +648,7 @@ _IsWriteable(PyArrayObject *ap)
  * @return Python unicode string
  */
 NPY_NO_EXPORT PyObject *
-convert_shape_to_string(npy_intp n, npy_intp *vals, char *ending)
+convert_shape_to_string(npy_intp n, npy_intp const *vals, char *ending)
 {
     npy_intp i;
     PyObject *ret, *tmp;
@@ -945,5 +898,3 @@ new_array_for_sum(PyArrayObject *ap1, PyArrayObject *ap2, PyArrayObject* out,
     }
 }
 
-
-
index 7eee9ddc5db688c61ce9a2f6e2ec18f861eb7884..4913eb202f22a5f7a05e6d6bc3061b7e1af15a51 100644 (file)
@@ -49,7 +49,7 @@ NPY_NO_EXPORT PyArray_Descr *
 _array_find_python_scalar_type(PyObject *op);
 
 NPY_NO_EXPORT PyArray_Descr *
-_array_typedescr_fromstr(char *str);
+_array_typedescr_fromstr(char const *str);
 
 NPY_NO_EXPORT char *
 index2ptr(PyArrayObject *mp, npy_intp i);
@@ -61,7 +61,7 @@ NPY_NO_EXPORT npy_bool
 _IsWriteable(PyArrayObject *ap);
 
 NPY_NO_EXPORT PyObject *
-convert_shape_to_string(npy_intp n, npy_intp *vals, char *ending);
+convert_shape_to_string(npy_intp n, npy_intp const *vals, char *ending);
 
 /*
  * Sets ValueError with "matrices not aligned" message for np.dot and friends
@@ -235,7 +235,7 @@ npy_uint_alignment(int itemsize)
         default:
             break;
     }
-    
+
     return alignment;
 }
 
@@ -343,3 +343,4 @@ new_array_for_sum(PyArrayObject *ap1, PyArrayObject *ap2, PyArrayObject* out,
                   int nd, npy_intp dimensions[], int typenum, PyArrayObject **result);
 
 #endif
+
index 055d3e60f0b3af693e37bc9fdaf9ac0965c904f9..5cf18049d734476a08bd885a99d11d1e67e36679 100644 (file)
@@ -1159,12 +1159,12 @@ fail:
 }
 
 
-/* 
+/*
  * Inner loop for unravel_index
  * order must be NPY_CORDER or NPY_FORTRANORDER
  */
 static int
-unravel_index_loop(int unravel_ndim, npy_intp *unravel_dims,
+unravel_index_loop(int unravel_ndim, npy_intp const *unravel_dims,
                    npy_intp unravel_size, npy_intp count,
                    char *indices, npy_intp indices_stride,
                    npy_intp *coords, NPY_ORDER order)
@@ -1186,7 +1186,7 @@ unravel_index_loop(int unravel_ndim, npy_intp *unravel_dims,
         }
         idx = idx_start;
         for (i = 0; i < unravel_ndim; ++i) {
-            /* 
+            /*
              * Using a local seems to enable single-divide optimization
              * but only if the / precedes the %
              */
@@ -1242,15 +1242,25 @@ arr_unravel_index(PyObject *self, PyObject *args, PyObject *kwds)
      */
     if (kwds) {
         PyObject *dims_item, *shape_item;
-        dims_item = PyDict_GetItemString(kwds, "dims");
-        shape_item = PyDict_GetItemString(kwds, "shape");
+        dims_item = _PyDict_GetItemStringWithError(kwds, "dims");
+        if (dims_item == NULL && PyErr_Occurred()){
+            return NULL;
+        }
+        shape_item = _PyDict_GetItemStringWithError(kwds, "shape");
+        if (shape_item == NULL && PyErr_Occurred()){
+            return NULL;
+        }
         if (dims_item != NULL && shape_item == NULL) {
             if (DEPRECATE("'shape' argument should be"
                           " used instead of 'dims'") < 0) {
                 return NULL;
             }
-            PyDict_SetItemString(kwds, "shape", dims_item);
-            PyDict_DelItemString(kwds, "dims");
+            if (PyDict_SetItemString(kwds, "shape", dims_item) < 0) {
+                return NULL;
+            }
+            if (PyDict_DelItemString(kwds, "dims") < 0) {
+                return NULL;
+            }
         }
     }
 
@@ -1415,7 +1425,7 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
     #else
     char *docstr;
     #endif
-    static char *msg = "already has a docstring";
+    static char *msg = "already has a different docstring";
     PyObject *tp_dict = PyArrayDescr_Type.tp_dict;
     PyObject *myobj;
     static PyTypeObject *PyMemberDescr_TypePtr = NULL;
@@ -1429,25 +1439,33 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
 
     if (PyGetSetDescr_TypePtr == NULL) {
         /* Get "subdescr" */
-        myobj = PyDict_GetItemString(tp_dict, "fields");
+        myobj = _PyDict_GetItemStringWithError(tp_dict, "fields");
+        if (myobj == NULL && PyErr_Occurred()) {
+            return NULL;
+        }
         if (myobj != NULL) {
             PyGetSetDescr_TypePtr = Py_TYPE(myobj);
         }
     }
     if (PyMemberDescr_TypePtr == NULL) {
-        myobj = PyDict_GetItemString(tp_dict, "alignment");
+        myobj = _PyDict_GetItemStringWithError(tp_dict, "alignment");
+        if (myobj == NULL && PyErr_Occurred()) {
+            return NULL;
+        }
         if (myobj != NULL) {
             PyMemberDescr_TypePtr = Py_TYPE(myobj);
         }
     }
     if (PyMethodDescr_TypePtr == NULL) {
-        myobj = PyDict_GetItemString(tp_dict, "newbyteorder");
+        myobj = _PyDict_GetItemStringWithError(tp_dict, "newbyteorder");
+        if (myobj == NULL && PyErr_Occurred()) {
+            return NULL;
+        }
         if (myobj != NULL) {
             PyMethodDescr_TypePtr = Py_TYPE(myobj);
         }
     }
 
-#if defined(NPY_PY3K)
     if (!PyArg_ParseTuple(args, "OO!:add_docstring", &obj, &PyUnicode_Type, &str)) {
         return NULL;
     }
@@ -1456,13 +1474,6 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
     if (docstr == NULL) {
         return NULL;
     }
-#else
-    if (!PyArg_ParseTuple(args, "OO!:add_docstring", &obj, &PyString_Type, &str)) {
-        return NULL;
-    }
-
-    docstr = PyString_AS_STRING(str);
-#endif
 
 #define _TESTDOC1(typebase) (Py_TYPE(obj) == &Py##typebase##_Type)
 #define _TESTDOC2(typebase) (Py_TYPE(obj) == Py##typebase##_TypePtr)
@@ -1471,7 +1482,7 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
         if (!(doc)) {                                                   \
             doc = docstr;                                               \
         }                                                               \
-        else {                                                          \
+        else if (strcmp(doc, docstr) != 0) {                            \
             PyErr_Format(PyExc_RuntimeError, "%s method %s", name, msg); \
             return NULL;                                                \
         }                                                               \
@@ -1496,7 +1507,12 @@ arr_add_docstring(PyObject *NPY_UNUSED(dummy), PyObject *args)
         PyObject *doc_attr;
 
         doc_attr = PyObject_GetAttrString(obj, "__doc__");
-        if (doc_attr != NULL && doc_attr != Py_None) {
+        if (doc_attr != NULL && doc_attr != Py_None &&
+                (PyUnicode_Compare(doc_attr, str) != 0)) {
+            if (PyErr_Occurred()) {
+                /* error during PyUnicode_Compare */
+                return NULL;
+            }
             PyErr_Format(PyExc_RuntimeError, "object %s", msg);
             return NULL;
         }
index ca126b4b1347563a4ad226f6e17b9cd1cadfe94b..14d5468672f4534277c409b76d22da3bff01769c 100644 (file)
@@ -137,6 +137,20 @@ PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq)
     return NPY_SUCCEED;
 }
 
+/*
+ * Like PyArray_IntpConverter, but leaves `seq` untouched if `None` is passed
+ * rather than treating `None` as `()`.
+ */
+NPY_NO_EXPORT int
+PyArray_OptionalIntpConverter(PyObject *obj, PyArray_Dims *seq)
+{
+    if (obj == Py_None) {
+        return NPY_SUCCEED;
+    }
+
+    return PyArray_IntpConverter(obj, seq);
+}
+
 /*NUMPY_API
  * Get buffer chunk from object
  *
@@ -152,11 +166,7 @@ PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq)
 NPY_NO_EXPORT int
 PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
 {
-#if defined(NPY_PY3K)
     Py_buffer view;
-#else
-    Py_ssize_t buflen;
-#endif
 
     buf->ptr = NULL;
     buf->flags = NPY_ARRAY_BEHAVED;
@@ -165,7 +175,6 @@ PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
         return NPY_SUCCEED;
     }
 
-#if defined(NPY_PY3K)
     if (PyObject_GetBuffer(obj, &view,
                 PyBUF_ANY_CONTIGUOUS|PyBUF_WRITABLE|PyBUF_SIMPLE) != 0) {
         PyErr_Clear();
@@ -192,22 +201,6 @@ PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf)
     if (PyMemoryView_Check(obj)) {
         buf->base = PyMemoryView_GET_BASE(obj);
     }
-#else
-    if (PyObject_AsWriteBuffer(obj, &(buf->ptr), &buflen) < 0) {
-        PyErr_Clear();
-        buf->flags &= ~NPY_ARRAY_WRITEABLE;
-        if (PyObject_AsReadBuffer(obj, (const void **)&(buf->ptr),
-                                  &buflen) < 0) {
-            return NPY_FAIL;
-        }
-    }
-    buf->len = (npy_intp) buflen;
-
-    /* Point to the base of the buffer object if present */
-    if (PyBuffer_Check(obj)) {
-        buf->base = ((PyArray_Chunk *)obj)->base;
-    }
-#endif
     if (buf->base == NULL) {
         buf->base = obj;
     }
@@ -329,100 +322,112 @@ PyArray_BoolConverter(PyObject *object, npy_bool *val)
     return NPY_SUCCEED;
 }
 
-/*NUMPY_API
- * Convert object to endian
- */
-NPY_NO_EXPORT int
-PyArray_ByteorderConverter(PyObject *obj, char *endian)
+static int
+string_converter_helper(
+    PyObject *object,
+    void *out,
+    int (*str_func)(char const*, Py_ssize_t, void*),
+    char const *name,
+    char const *message)
 {
-    char *str;
-    PyObject *tmp = NULL;
-
-    if (PyUnicode_Check(obj)) {
-        obj = tmp = PyUnicode_AsASCIIString(obj);
+    /* allow bytes for compatibility */
+    PyObject *str_object = NULL;
+    if (PyBytes_Check(object)) {
+        str_object = PyUnicode_FromEncodedObject(object, NULL, NULL);
+        if (str_object == NULL) {
+            PyErr_Format(PyExc_ValueError,
+                "%s %s (got %R)", name, message, object);
+            return NPY_FAIL;
+        }
     }
-
-    *endian = NPY_SWAP;
-    str = PyBytes_AsString(obj);
-    if (!str) {
-        Py_XDECREF(tmp);
+    else if (PyUnicode_Check(object)) {
+        str_object = object;
+        Py_INCREF(str_object);
+    }
+    else {
+        PyErr_Format(PyExc_TypeError,
+            "%s must be str, not %s", name, Py_TYPE(object)->tp_name);
         return NPY_FAIL;
     }
-    if (strlen(str) < 1) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Byteorder string must be at least length 1");
-        Py_XDECREF(tmp);
+
+    Py_ssize_t length;
+    char const *str = PyUnicode_AsUTF8AndSize(str_object, &length);
+    if (str == NULL) {
+        Py_DECREF(str_object);
         return NPY_FAIL;
     }
-    *endian = str[0];
-    if (str[0] != NPY_BIG && str[0] != NPY_LITTLE
-        && str[0] != NPY_NATIVE && str[0] != NPY_IGNORE) {
-        if (str[0] == 'b' || str[0] == 'B') {
-            *endian = NPY_BIG;
-        }
-        else if (str[0] == 'l' || str[0] == 'L') {
-            *endian = NPY_LITTLE;
-        }
-        else if (str[0] == 'n' || str[0] == 'N') {
-            *endian = NPY_NATIVE;
-        }
-        else if (str[0] == 'i' || str[0] == 'I') {
-            *endian = NPY_IGNORE;
-        }
-        else if (str[0] == 's' || str[0] == 'S') {
-            *endian = NPY_SWAP;
-        }
-        else {
+
+    int ret = str_func(str, length, out);
+    Py_DECREF(str_object);
+    if (ret < 0) {
             PyErr_Format(PyExc_ValueError,
-                         "%s is an unrecognized byteorder",
-                         str);
-            Py_XDECREF(tmp);
-            return NPY_FAIL;
-        }
+                "%s %s (got %R)", name, message, object);
+        return NPY_FAIL;
     }
-    Py_XDECREF(tmp);
     return NPY_SUCCEED;
 }
 
-/*NUMPY_API
- * Convert object to sort kind
- */
-NPY_NO_EXPORT int
-PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sortkind)
+static int byteorder_parser(char const *str, Py_ssize_t length, void *data)
 {
-    char *str;
-    PyObject *tmp = NULL;
+    char *endian = (char *)data;
 
-    if (obj == Py_None) {
-        *sortkind = NPY_QUICKSORT;
-        return NPY_SUCCEED;
+    if (length < 1) {
+        return -1;
     }
-
-    if (PyUnicode_Check(obj)) {
-        obj = tmp = PyUnicode_AsASCIIString(obj);
-        if (obj == NULL) {
-            return NPY_FAIL;
-        }
+    else if (str[0] == NPY_BIG || str[0] == NPY_LITTLE
+        || str[0] == NPY_NATIVE || str[0] == NPY_IGNORE) {
+        *endian = str[0];
+        return 0;
+    }
+    else if (str[0] == 'b' || str[0] == 'B') {
+        *endian = NPY_BIG;
+        return 0;
+    }
+    else if (str[0] == 'l' || str[0] == 'L') {
+        *endian = NPY_LITTLE;
+        return 0;
+    }
+    else if (str[0] == 'n' || str[0] == 'N') {
+        *endian = NPY_NATIVE;
+        return 0;
     }
+    else if (str[0] == 'i' || str[0] == 'I') {
+        *endian = NPY_IGNORE;
+        return 0;
+    }
+    else if (str[0] == 's' || str[0] == 'S') {
+        *endian = NPY_SWAP;
+        return 0;
+    }
+    else {
+        return -1;
+    }
+}
+
+/*NUMPY_API
+ * Convert object to endian
+ */
+NPY_NO_EXPORT int
+PyArray_ByteorderConverter(PyObject *obj, char *endian)
+{
+    return string_converter_helper(
+        obj, (void *)endian, byteorder_parser, "byteorder", "not recognized");
+}
 
-    *sortkind = NPY_QUICKSORT;
+static int sortkind_parser(char const *str, Py_ssize_t length, void *data)
+{
+    NPY_SORTKIND *sortkind = (NPY_SORTKIND *)data;
 
-    str = PyBytes_AsString(obj);
-    if (!str) {
-        Py_XDECREF(tmp);
-        return NPY_FAIL;
-    }
-    if (strlen(str) < 1) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Sort kind string must be at least length 1");
-        Py_XDECREF(tmp);
-        return NPY_FAIL;
+    if (length < 1) {
+        return -1;
     }
     if (str[0] == 'q' || str[0] == 'Q') {
         *sortkind = NPY_QUICKSORT;
+        return 0;
     }
     else if (str[0] == 'h' || str[0] == 'H') {
         *sortkind = NPY_HEAPSORT;
+        return 0;
     }
     else if (str[0] == 'm' || str[0] == 'M') {
         /*
@@ -431,6 +436,7 @@ PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sortkind)
          * allowing other types of stable sorts to be used.
          */
         *sortkind = NPY_MERGESORT;
+        return 0;
     }
     else if (str[0] == 's' || str[0] == 'S') {
         /*
@@ -442,16 +448,39 @@ PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sortkind)
          *  Which one is used depends on the data type.
          */
         *sortkind = NPY_STABLESORT;
+        return 0;
     }
     else {
-        PyErr_Format(PyExc_ValueError,
-                     "%s is an unrecognized kind of sort",
-                     str);
-        Py_XDECREF(tmp);
-        return NPY_FAIL;
+        return -1;
+    }
+}
+
+/*NUMPY_API
+ * Convert object to sort kind
+ */
+NPY_NO_EXPORT int
+PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sortkind)
+{
+    /* Leave the desired default from the caller for Py_None */
+    if (obj == Py_None) {
+        return NPY_SUCCEED;
+    }
+    return string_converter_helper(
+        obj, (void *)sortkind, sortkind_parser, "sort kind",
+        "must be one of 'quick', 'heap', or 'stable'");
+}
+
+static int selectkind_parser(char const *str, Py_ssize_t length, void *data)
+{
+    NPY_SELECTKIND *selectkind = (NPY_SELECTKIND *)data;
+
+    if (length == 11 && strcmp(str, "introselect") == 0) {
+        *selectkind = NPY_INTROSELECT;
+        return 0;
+    }
+    else {
+        return -1;
     }
-    Py_XDECREF(tmp);
-    return NPY_SUCCEED;
 }
 
 /*NUMPY_API
@@ -460,40 +489,29 @@ PyArray_SortkindConverter(PyObject *obj, NPY_SORTKIND *sortkind)
 NPY_NO_EXPORT int
 PyArray_SelectkindConverter(PyObject *obj, NPY_SELECTKIND *selectkind)
 {
-    char *str;
-    PyObject *tmp = NULL;
+    return string_converter_helper(
+        obj, (void *)selectkind, selectkind_parser, "select kind",
+        "must be 'introselect'");
+}
 
-    if (PyUnicode_Check(obj)) {
-        obj = tmp = PyUnicode_AsASCIIString(obj);
-        if (obj == NULL) {
-            return NPY_FAIL;
-        }
-    }
+static int searchside_parser(char const *str, Py_ssize_t length, void *data)
+{
+    NPY_SEARCHSIDE *side = (NPY_SEARCHSIDE *)data;
 
-    *selectkind = NPY_INTROSELECT;
-    str = PyBytes_AsString(obj);
-    if (!str) {
-        Py_XDECREF(tmp);
-        return NPY_FAIL;
+    if (length < 1) {
+        return -1;
     }
-    if (strlen(str) < 1) {
-        PyErr_SetString(PyExc_ValueError,
-                        "Select kind string must be at least length 1");
-        Py_XDECREF(tmp);
-        return NPY_FAIL;
+    else if (str[0] == 'l' || str[0] == 'L') {
+        *side = NPY_SEARCHLEFT;
+        return 0;
     }
-    if (strcmp(str, "introselect") == 0) {
-        *selectkind = NPY_INTROSELECT;
+    else if (str[0] == 'r' || str[0] == 'R') {
+        *side = NPY_SEARCHRIGHT;
+        return 0;
     }
     else {
-        PyErr_Format(PyExc_ValueError,
-                     "%s is an unrecognized kind of select",
-                     str);
-        Py_XDECREF(tmp);
-        return NPY_FAIL;
+        return -1;
     }
-    Py_XDECREF(tmp);
-    return NPY_SUCCEED;
 }
 
 /*NUMPY_API
@@ -502,36 +520,36 @@ PyArray_SelectkindConverter(PyObject *obj, NPY_SELECTKIND *selectkind)
 NPY_NO_EXPORT int
 PyArray_SearchsideConverter(PyObject *obj, void *addr)
 {
-    NPY_SEARCHSIDE *side = (NPY_SEARCHSIDE *)addr;
-    char *str;
-    PyObject *tmp = NULL;
+    return string_converter_helper(
+        obj, addr, searchside_parser, "search side",
+        "must be 'left' or 'right'");
+}
 
-    if (PyUnicode_Check(obj)) {
-        obj = tmp = PyUnicode_AsASCIIString(obj);
+static int order_parser(char const *str, Py_ssize_t length, void *data)
+{
+    NPY_ORDER *val = (NPY_ORDER *)data;
+    if (length != 1) {
+        return -1;
     }
-
-    str = PyBytes_AsString(obj);
-    if (!str || strlen(str) < 1) {
-        PyErr_SetString(PyExc_ValueError,
-                        "expected nonempty string for keyword 'side'");
-        Py_XDECREF(tmp);
-        return NPY_FAIL;
+    if (str[0] == 'C' || str[0] == 'c') {
+        *val = NPY_CORDER;
+        return 0;
     }
-
-    if (str[0] == 'l' || str[0] == 'L') {
-        *side = NPY_SEARCHLEFT;
+    else if (str[0] == 'F' || str[0] == 'f') {
+        *val = NPY_FORTRANORDER;
+        return 0;
     }
-    else if (str[0] == 'r' || str[0] == 'R') {
-        *side = NPY_SEARCHRIGHT;
+    else if (str[0] == 'A' || str[0] == 'a') {
+        *val = NPY_ANYORDER;
+        return 0;
+    }
+    else if (str[0] == 'K' || str[0] == 'k') {
+        *val = NPY_KEEPORDER;
+        return 0;
     }
     else {
-        PyErr_Format(PyExc_ValueError,
-                     "'%s' is an invalid value for keyword 'side'", str);
-        Py_XDECREF(tmp);
-        return NPY_FAIL;
+        return -1;
     }
-    Py_XDECREF(tmp);
-    return NPY_SUCCEED;
 }
 
 /*NUMPY_API
@@ -540,59 +558,36 @@ PyArray_SearchsideConverter(PyObject *obj, void *addr)
 NPY_NO_EXPORT int
 PyArray_OrderConverter(PyObject *object, NPY_ORDER *val)
 {
-    char *str;
-    /* Leave the desired default from the caller for NULL/Py_None */
-    if (object == NULL || object == Py_None) {
+    /* Leave the desired default from the caller for Py_None */
+    if (object == Py_None) {
         return NPY_SUCCEED;
     }
-    else if (PyUnicode_Check(object)) {
-        PyObject *tmp;
-        int ret;
-        tmp = PyUnicode_AsASCIIString(object);
-        if (tmp == NULL) {
-            PyErr_SetString(PyExc_ValueError,
-                "Invalid unicode string passed in for the array ordering. "
-                "Please pass in 'C', 'F', 'A' or 'K' instead");
-            return NPY_FAIL;
-        }
-        ret = PyArray_OrderConverter(tmp, val);
-        Py_DECREF(tmp);
-        return ret;
-    }
-    else if (!PyBytes_Check(object) || PyBytes_GET_SIZE(object) < 1) {
-        PyErr_SetString(PyExc_ValueError,
-            "Non-string object detected for the array ordering. "
-            "Please pass in 'C', 'F', 'A', or 'K' instead");
-        return NPY_FAIL;
+    return string_converter_helper(
+        object, (void *)val, order_parser, "order",
+        "must be one of 'C', 'F', 'A', or 'K'");
+}
+
+static int clipmode_parser(char const *str, Py_ssize_t length, void *data)
+{
+    NPY_CLIPMODE *val = (NPY_CLIPMODE *)data;
+    if (length < 1) {
+        return -1;
+    }
+    if (str[0] == 'C' || str[0] == 'c') {
+        *val = NPY_CLIP;
+        return 0;
+    }
+    else if (str[0] == 'W' || str[0] == 'w') {
+        *val = NPY_WRAP;
+        return 0;
+    }
+    else if (str[0] == 'R' || str[0] == 'r') {
+        *val = NPY_RAISE;
+        return 0;
     }
     else {
-        str = PyBytes_AS_STRING(object);
-        if (strlen(str) != 1) {
-            PyErr_SetString(PyExc_ValueError,
-                "Non-string object detected for the array ordering. "
-                "Please pass in 'C', 'F', 'A', or 'K' instead");
-            return NPY_FAIL;
-        }
-
-        if (str[0] == 'C' || str[0] == 'c') {
-            *val = NPY_CORDER;
-        }
-        else if (str[0] == 'F' || str[0] == 'f') {
-            *val = NPY_FORTRANORDER;
-        }
-        else if (str[0] == 'A' || str[0] == 'a') {
-            *val = NPY_ANYORDER;
-        }
-        else if (str[0] == 'K' || str[0] == 'k') {
-            *val = NPY_KEEPORDER;
-        }
-        else {
-            PyErr_SetString(PyExc_TypeError,
-                            "order not understood");
-            return NPY_FAIL;
-        }
+        return -1;
     }
-    return NPY_SUCCEED;
 }
 
 /*NUMPY_API
@@ -604,36 +599,14 @@ PyArray_ClipmodeConverter(PyObject *object, NPY_CLIPMODE *val)
     if (object == NULL || object == Py_None) {
         *val = NPY_RAISE;
     }
-    else if (PyBytes_Check(object)) {
-        char *str;
-        str = PyBytes_AS_STRING(object);
-        if (str[0] == 'C' || str[0] == 'c') {
-            *val = NPY_CLIP;
-        }
-        else if (str[0] == 'W' || str[0] == 'w') {
-            *val = NPY_WRAP;
-        }
-        else if (str[0] == 'R' || str[0] == 'r') {
-            *val = NPY_RAISE;
-        }
-        else {
-            PyErr_SetString(PyExc_TypeError,
-                            "clipmode not understood");
-            return NPY_FAIL;
-        }
-    }
-    else if (PyUnicode_Check(object)) {
-        PyObject *tmp;
-        int ret;
-        tmp = PyUnicode_AsASCIIString(object);
-        if (tmp == NULL) {
-            return NPY_FAIL;
-        }
-        ret = PyArray_ClipmodeConverter(tmp, val);
-        Py_DECREF(tmp);
-        return ret;
+
+    else if (PyBytes_Check(object) || PyUnicode_Check(object)) {
+        return string_converter_helper(
+            object, (void *)val, clipmode_parser, "clipmode",
+            "must be one of 'clip', 'raise', or 'wrap'");
     }
     else {
+        /* For users passing `np.RAISE`, `np.WRAP`, `np.CLIP` */
         int number = PyArray_PyIntAsInt(object);
         if (error_converting(number)) {
             goto fail;
@@ -643,7 +616,8 @@ PyArray_ClipmodeConverter(PyObject *object, NPY_CLIPMODE *val)
             *val = (NPY_CLIPMODE) number;
         }
         else {
-            goto fail;
+            PyErr_Format(PyExc_ValueError,
+                    "integer clipmode must be np.RAISE, np.WRAP, or np.CLIP");
         }
     }
     return NPY_SUCCEED;
@@ -697,66 +671,56 @@ PyArray_ConvertClipmodeSequence(PyObject *object, NPY_CLIPMODE *modes, int n)
     return NPY_SUCCEED;
 }
 
+static int casting_parser(char const *str, Py_ssize_t length, void *data)
+{
+    NPY_CASTING *casting = (NPY_CASTING *)data;
+    if (length < 2) {
+        return -1;
+    }
+    switch (str[2]) {
+    case 0:
+        if (length == 2 && strcmp(str, "no") == 0) {
+            *casting = NPY_NO_CASTING;
+            return 0;
+        }
+        break;
+    case 'u':
+        if (length == 5 && strcmp(str, "equiv") == 0) {
+            *casting = NPY_EQUIV_CASTING;
+            return 0;
+        }
+        break;
+    case 'f':
+        if (length == 4 && strcmp(str, "safe") == 0) {
+            *casting = NPY_SAFE_CASTING;
+            return 0;
+        }
+        break;
+    case 'm':
+        if (length == 9 && strcmp(str, "same_kind") == 0) {
+            *casting = NPY_SAME_KIND_CASTING;
+            return 0;
+        }
+        break;
+    case 's':
+        if (length == 6 && strcmp(str, "unsafe") == 0) {
+            *casting = NPY_UNSAFE_CASTING;
+            return 0;
+        }
+        break;
+    }
+    return -1;
+}
+
 /*NUMPY_API
  * Convert any Python object, *obj*, to an NPY_CASTING enum.
  */
 NPY_NO_EXPORT int
 PyArray_CastingConverter(PyObject *obj, NPY_CASTING *casting)
 {
-    char *str = NULL;
-    Py_ssize_t length = 0;
-
-    if (PyUnicode_Check(obj)) {
-        PyObject *str_obj;
-        int ret;
-        str_obj = PyUnicode_AsASCIIString(obj);
-        if (str_obj == NULL) {
-            return 0;
-        }
-        ret = PyArray_CastingConverter(str_obj, casting);
-        Py_DECREF(str_obj);
-        return ret;
-    }
-
-    if (PyBytes_AsStringAndSize(obj, &str, &length) < 0) {
-        return 0;
-    }
-
-    if (length >= 2) switch (str[2]) {
-        case 0:
-            if (strcmp(str, "no") == 0) {
-                *casting = NPY_NO_CASTING;
-                return 1;
-            }
-            break;
-        case 'u':
-            if (strcmp(str, "equiv") == 0) {
-                *casting = NPY_EQUIV_CASTING;
-                return 1;
-            }
-            break;
-        case 'f':
-            if (strcmp(str, "safe") == 0) {
-                *casting = NPY_SAFE_CASTING;
-                return 1;
-            }
-            break;
-        case 'm':
-            if (strcmp(str, "same_kind") == 0) {
-                *casting = NPY_SAME_KIND_CASTING;
-                return 1;
-            }
-            break;
-        case 's':
-            if (strcmp(str, "unsafe") == 0) {
-                *casting = NPY_UNSAFE_CASTING;
-                return 1;
-            }
-            break;
-    }
-
-    PyErr_SetString(PyExc_ValueError,
-            "casting must be one of 'no', 'equiv', 'safe', "
+    return string_converter_helper(
+        obj, (void *)casting, casting_parser, "casting",
+            "must be one of 'no', 'equiv', 'safe', "
             "'same_kind', or 'unsafe'");
     return 0;
 }
@@ -812,18 +776,6 @@ PyArray_PyIntAsIntp_ErrMsg(PyObject *o, const char * msg)
      * Since it is the usual case, first check if o is an integer. This is
      * an exact check, since otherwise __index__ is used.
      */
-#if !defined(NPY_PY3K)
-    if (PyInt_CheckExact(o)) {
-  #if (NPY_SIZEOF_LONG <= NPY_SIZEOF_INTP)
-        /* No overflow is possible, so we can just return */
-        return PyInt_AS_LONG(o);
-  #else
-        long_value = PyInt_AS_LONG(o);
-        goto overflow_check;
-  #endif
-    }
-    else
-#endif
     if (PyLong_CheckExact(o)) {
 #if (NPY_SIZEOF_LONG < NPY_SIZEOF_INTP)
         long_value = PyLong_AsLongLong(o);
@@ -1145,7 +1097,7 @@ PyArray_TypestrConvert(int itemsize, int gentype)
   PyArray_IntTupleFromIntp
 */
 NPY_NO_EXPORT PyObject *
-PyArray_IntTupleFromIntp(int len, npy_intp *vals)
+PyArray_IntTupleFromIntp(int len, npy_intp const *vals)
 {
     int i;
     PyObject *intTuple = PyTuple_New(len);
index cd43f25c38d3ef048101c7a0b439b52e832e3c85..bee0c6064d050849cd9969bb5a2bfbbe8e820f3e 100644 (file)
@@ -6,6 +6,9 @@
 NPY_NO_EXPORT int
 PyArray_IntpConverter(PyObject *obj, PyArray_Dims *seq);
 
+NPY_NO_EXPORT int
+PyArray_OptionalIntpConverter(PyObject *obj, PyArray_Dims *seq);
+
 NPY_NO_EXPORT int
 PyArray_BufferConverter(PyObject *obj, PyArray_Chunk *buf);
 
@@ -37,7 +40,7 @@ NPY_NO_EXPORT int
 PyArray_TypestrConvert(int itemsize, int gentype);
 
 NPY_NO_EXPORT PyObject *
-PyArray_IntTupleFromIntp(int len, npy_intp *vals);
+PyArray_IntTupleFromIntp(int len, npy_intp const *vals);
 
 NPY_NO_EXPORT int
 PyArray_SelectkindConverter(PyObject *obj, NPY_SELECTKIND *selectkind);
index aa4e40e66b5253d2929e6408db28a39a6d3a4e31..e7cbeaa7724e820139d71baf86e1fbc9f98efa87 100644 (file)
@@ -262,18 +262,12 @@ PyArray_ToFile(PyArrayObject *self, FILE *fp, char *sep, char *format)
                     return -1;
                 }
             }
-#if defined(NPY_PY3K)
             byteobj = PyUnicode_AsASCIIString(strobj);
-#else
-            byteobj = strobj;
-#endif
             NPY_BEGIN_ALLOW_THREADS;
             n2 = PyBytes_GET_SIZE(byteobj);
             n = fwrite(PyBytes_AS_STRING(byteobj), 1, n2, fp);
             NPY_END_ALLOW_THREADS;
-#if defined(NPY_PY3K)
             Py_DECREF(byteobj);
-#endif
             if (n < n2) {
                 PyErr_Format(PyExc_IOError,
                         "problem writing element %" NPY_INTP_FMT
index 14025a5f91e675d629220fe55b595c6d3dcdd061..0390c92fc3b7ae998605dc21f4b9edfe265baab4 100644 (file)
@@ -13,6 +13,7 @@
 #include "numpy/npy_math.h"
 
 #include "common.h"
+#include "ctors.h"
 #include "scalartypes.h"
 #include "mapping.h"
 
@@ -259,11 +260,11 @@ PyArray_AdaptFlexibleDType(PyObject *data_obj, PyArray_Descr *data_dtype,
                             int ndim = 0;
                             npy_intp dims[NPY_MAXDIMS];
                             list = PyArray_ToList((PyArrayObject *)data_obj);
-                            result = PyArray_GetArrayParamsFromObject(
+                            result = PyArray_GetArrayParamsFromObject_int(
                                     list,
                                     retval,
                                     0, &dtype,
-                                    &ndim, dims, &arr, NULL);
+                                    &ndim, dims, &arr);
                             Py_DECREF(list);
                             Py_XDECREF(arr);
                             if (result < 0) {
@@ -984,6 +985,54 @@ PyArray_CanCastArrayTo(PyArrayObject *arr, PyArray_Descr *to,
     return PyArray_CanCastTypeTo(from, to, casting);
 }
 
+
+NPY_NO_EXPORT const char *
+npy_casting_to_string(NPY_CASTING casting)
+{
+    switch (casting) {
+        case NPY_NO_CASTING:
+            return "'no'";
+        case NPY_EQUIV_CASTING:
+            return "'equiv'";
+        case NPY_SAFE_CASTING:
+            return "'safe'";
+        case NPY_SAME_KIND_CASTING:
+            return "'same_kind'";
+        case NPY_UNSAFE_CASTING:
+            return "'unsafe'";
+        default:
+            return "<unknown>";
+    }
+}
+
+
+/**
+ * Helper function to set a useful error when casting is not possible.
+ *
+ * @param src_dtype
+ * @param dst_dtype
+ * @param casting
+ * @param scalar Whether this was a "scalar" cast (includes 0-D array with
+ *               PyArray_CanCastArrayTo result).
+ */
+NPY_NO_EXPORT void
+npy_set_invalid_cast_error(
+        PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
+        NPY_CASTING casting, npy_bool scalar)
+{
+    char *msg;
+
+    if (!scalar) {
+        msg = "Cannot cast array data from %R to %R according to the rule %s";
+    }
+    else {
+        msg = "Cannot cast scalar from %R to %R according to the rule %s";
+    }
+    PyErr_Format(PyExc_TypeError,
+            msg, src_dtype, dst_dtype, npy_casting_to_string(casting));
+}
+
+
 /*NUMPY_API
  * See if array scalars can be cast.
  *
@@ -2125,15 +2174,19 @@ PyArray_ObjectType(PyObject *op, int minimum_type)
 
 /* Raises error when len(op) == 0 */
 
-/*NUMPY_API*/
+/*NUMPY_API
+ *
+ * This function is only used in one place within NumPy and should
+ * generally be avoided. It is provided mainly for backward compatibility.
+ *
+ * The user of the function has to free the returned array.
+ */
 NPY_NO_EXPORT PyArrayObject **
 PyArray_ConvertToCommonType(PyObject *op, int *retn)
 {
-    int i, n, allscalars = 0;
+    int i, n;
+    PyArray_Descr *common_descr = NULL;
     PyArrayObject **mps = NULL;
-    PyArray_Descr *intype = NULL, *stype = NULL;
-    PyArray_Descr *newtype = NULL;
-    NPY_SCALARKIND scalarkind = NPY_NOSCALAR, intypekind = NPY_NOSCALAR;
 
     *retn = n = PySequence_Length(op);
     if (n == 0) {
@@ -2169,94 +2222,41 @@ PyArray_ConvertToCommonType(PyObject *op, int *retn)
     }
 
     for (i = 0; i < n; i++) {
-        PyObject *otmp = PySequence_GetItem(op, i);
-        if (otmp == NULL) {
+        /* Convert everything to an array, this could be optimized away */
+        PyObject *tmp = PySequence_GetItem(op, i);
+        if (tmp == NULL) {
             goto fail;
         }
-        if (!PyArray_CheckAnyScalar(otmp)) {
-            newtype = PyArray_DescrFromObject(otmp, intype);
-            Py_DECREF(otmp);
-            Py_XDECREF(intype);
-            if (newtype == NULL) {
-                goto fail;
-            }
-            intype = newtype;
-            intypekind = PyArray_ScalarKind(intype->type_num, NULL);
-        }
-        else {
-            newtype = PyArray_DescrFromObject(otmp, stype);
-            Py_DECREF(otmp);
-            Py_XDECREF(stype);
-            if (newtype == NULL) {
-                goto fail;
-            }
-            stype = newtype;
-            scalarkind = PyArray_ScalarKind(newtype->type_num, NULL);
-            mps[i] = (PyArrayObject *)Py_None;
-            Py_INCREF(Py_None);
-        }
-    }
-    if (intype == NULL) {
-        /* all scalars */
-        allscalars = 1;
-        intype = stype;
-        Py_INCREF(intype);
-        for (i = 0; i < n; i++) {
-            Py_XDECREF(mps[i]);
-            mps[i] = NULL;
-        }
-    }
-    else if ((stype != NULL) && (intypekind != scalarkind)) {
-        /*
-         * we need to upconvert to type that
-         * handles both intype and stype
-         * also don't forcecast the scalars.
-         */
-        if (!PyArray_CanCoerceScalar(stype->type_num,
-                                     intype->type_num,
-                                     scalarkind)) {
-            newtype = PyArray_PromoteTypes(intype, stype);
-            Py_XDECREF(intype);
-            intype = newtype;
-            if (newtype == NULL) {
-                goto fail;
-            }
-        }
-        for (i = 0; i < n; i++) {
-            Py_XDECREF(mps[i]);
-            mps[i] = NULL;
+
+        mps[i] = (PyArrayObject *)PyArray_FROM_O(tmp);
+        Py_DECREF(tmp);
+        if (mps[i] == NULL) {
+            goto fail;
         }
     }
 
+    common_descr = PyArray_ResultType(n, mps, 0, NULL);
+    if (common_descr == NULL) {
+        goto fail;
+    }
 
-    /* Make sure all arrays are actual array objects. */
+    /* Make sure all arrays are contiguous and have the correct dtype. */
     for (i = 0; i < n; i++) {
         int flags = NPY_ARRAY_CARRAY;
-        PyObject *otmp = PySequence_GetItem(op, i);
+        PyArrayObject *tmp = mps[i];
 
-        if (otmp == NULL) {
-            goto fail;
-        }
-        if (!allscalars && ((PyObject *)(mps[i]) == Py_None)) {
-            /* forcecast scalars */
-            flags |= NPY_ARRAY_FORCECAST;
-            Py_DECREF(Py_None);
-        }
-        Py_INCREF(intype);
-        mps[i] = (PyArrayObject*)PyArray_FromAny(otmp, intype, 0, 0,
-                                                 flags, NULL);
-        Py_DECREF(otmp);
+        Py_INCREF(common_descr);
+        mps[i] = (PyArrayObject *)PyArray_FromArray(tmp, common_descr, flags);
+        Py_DECREF(tmp);
         if (mps[i] == NULL) {
             goto fail;
         }
     }
-    Py_DECREF(intype);
-    Py_XDECREF(stype);
+    Py_DECREF(common_descr);
     return mps;
 
  fail:
-    Py_XDECREF(intype);
-    Py_XDECREF(stype);
+    Py_XDECREF(common_descr);
     *retn = 0;
     for (i = 0; i < n; i++) {
         Py_XDECREF(mps[i]);
index 72867ead8d30d5c82601e82a7086e7f17a4547f7..4a7d851874e9a9a0b7b6576b3ad1fb76a3515a73 100644 (file)
@@ -22,6 +22,14 @@ NPY_NO_EXPORT int
 should_use_min_scalar(npy_intp narrs, PyArrayObject **arr,
                       npy_intp ndtypes, PyArray_Descr **dtypes);
 
+NPY_NO_EXPORT const char *
+npy_casting_to_string(NPY_CASTING casting);
+
+NPY_NO_EXPORT void
+npy_set_invalid_cast_error(
+        PyArray_Descr *src_dtype, PyArray_Descr *dst_dtype,
+        NPY_CASTING casting, npy_bool scalar);
+
 /*
  * This function calls Py_DECREF on flex_dtype, and replaces it with
  * a new dtype that has been adapted based on the values in data_dtype
index 7276add75bbe80f3ef2d0babcf97e4d155cdec46..14e64b647f8fcebbf13c4aead199dc7b0c3a2d9c 100644 (file)
@@ -21,7 +21,6 @@
 #include "shape.h"
 #include "npy_buffer.h"
 #include "lowlevel_strided_loops.h"
-#include "methods.h"
 #include "_datetime.h"
 #include "datetime_strings.h"
 #include "array_assign.h"
@@ -41,7 +40,7 @@
  */
 
 /*
- * Scanning function for next element parsing and seperator skipping.
+ * Scanning function for next element parsing and separator skipping.
  * These functions return:
  *   - 0 to indicate more data to read
  *   - -1 when reading stopped at the end of the string/file
@@ -53,6 +52,9 @@
 typedef int (*next_element)(void **, void *, PyArray_Descr *, void *);
 typedef int (*skip_separator)(void **, const char *, void *);
 
+static PyObject *
+_array_from_array_like(PyObject *op,
+        PyArray_Descr *requested_dtype, npy_bool writeable, PyObject *context);
 
 static npy_bool
 string_is_fully_read(char const* start, char const* end) {
@@ -481,6 +483,8 @@ setArrayFromSequence(PyArrayObject *a, PyObject *s,
     /* INCREF on entry DECREF on exit */
     Py_INCREF(s);
 
+    PyObject *seq = NULL;
+
     if (PyArray_Check(s)) {
         if (!(PyArray_CheckExact(s))) {
             /*
@@ -509,10 +513,30 @@ setArrayFromSequence(PyArrayObject *a, PyObject *s,
         goto fail;
     }
 
-    slen = PySequence_Length(s);
-    if (slen < 0) {
+    /* Try __array__ before using s as a sequence */
+    PyObject *tmp = _array_from_array_like(s, NULL, 0, NULL);
+    if (tmp == NULL) {
+        goto fail;
+    }
+    else if (tmp == Py_NotImplemented) {
+        Py_DECREF(tmp);
+    }
+    else {
+        int r = PyArray_CopyInto(dst, (PyArrayObject *)tmp);
+        Py_DECREF(tmp);
+        if (r < 0) {
+            goto fail;
+        }
+        Py_DECREF(s);
+        return 0;
+    }
+
+    seq = PySequence_Fast(s, "Could not convert object to sequence");
+    if (seq == NULL) {
         goto fail;
     }
+    slen = PySequence_Fast_GET_SIZE(seq);
+
     /*
      * Either the dimensions match, or the sequence has length 1 and can
      * be broadcast to the destination.
@@ -526,14 +550,9 @@ setArrayFromSequence(PyArrayObject *a, PyObject *s,
 
     /* Broadcast the one element from the sequence to all the outputs */
     if (slen == 1) {
-        PyObject *o;
+        PyObject *o = PySequence_Fast_GET_ITEM(seq, 0);
         npy_intp alen = PyArray_DIM(a, dim);
 
-        o = PySequence_GetItem(s, 0);
-        if (o == NULL) {
-            goto fail;
-        }
-
         for (i = 0; i < alen; i++) {
             if ((PyArray_NDIM(a) - dim) > 1) {
                 PyArrayObject * tmp =
@@ -550,26 +569,18 @@ setArrayFromSequence(PyArrayObject *a, PyObject *s,
                 res = PyArray_SETITEM(dst, b, o);
             }
             if (res < 0) {
-                Py_DECREF(o);
                 goto fail;
             }
         }
-        Py_DECREF(o);
     }
     /* Copy element by element */
     else {
-        PyObject * seq;
-        seq = PySequence_Fast(s, "Could not convert object to sequence");
-        if (seq == NULL) {
-            goto fail;
-        }
         for (i = 0; i < slen; i++) {
             PyObject * o = PySequence_Fast_GET_ITEM(seq, i);
             if ((PyArray_NDIM(a) - dim) > 1) {
                 PyArrayObject * tmp =
                     (PyArrayObject *)array_item_asarray(dst, i);
                 if (tmp == NULL) {
-                    Py_DECREF(seq);
                     goto fail;
                 }
 
@@ -581,17 +592,17 @@ setArrayFromSequence(PyArrayObject *a, PyObject *s,
                 res = PyArray_SETITEM(dst, b, o);
             }
             if (res < 0) {
-                Py_DECREF(seq);
                 goto fail;
             }
         }
-        Py_DECREF(seq);
     }
 
+    Py_DECREF(seq);
     Py_DECREF(s);
     return 0;
 
  fail:
+    Py_XDECREF(seq);
     Py_DECREF(s);
     return res;
 }
@@ -629,13 +640,7 @@ discover_itemsize(PyObject *s, int nd, int *itemsize, int string_type)
     }
 
     if ((nd == 0) || PyString_Check(s) ||
-#if defined(NPY_PY3K)
-            PyMemoryView_Check(s) ||
-#else
-            PyBuffer_Check(s) ||
-#endif
-            PyUnicode_Check(s)) {
-
+            PyMemoryView_Check(s) || PyUnicode_Check(s)) {
         /* If an object has no length, leave it be */
         if (string_type && s != NULL &&
                 !PyString_Check(s) && !PyUnicode_Check(s)) {
@@ -644,11 +649,7 @@ discover_itemsize(PyObject *s, int nd, int *itemsize, int string_type)
                 s_string = PyObject_Str(s);
             }
             else {
-#if defined(NPY_PY3K)
                 s_string = PyObject_Str(s);
-#else
-                s_string = PyObject_Unicode(s);
-#endif
             }
             if (s_string) {
                 n = PyObject_Length(s_string);
@@ -688,6 +689,25 @@ discover_itemsize(PyObject *s, int nd, int *itemsize, int string_type)
     return 0;
 }
 
+
+typedef enum {
+    DISCOVERED_OK = 0,
+    DISCOVERED_RAGGED = 1,
+    DISCOVERED_OBJECT = 2
+} discovered_t;
+
+
+static void
+_discover_dimensions_array(PyArrayObject *arr, int *maxndim, npy_intp *d) {
+    if (PyArray_NDIM(arr) < *maxndim) {
+        *maxndim = PyArray_NDIM(arr);
+    }
+    for (int i = 0; i < *maxndim; i++) {
+        d[i] = PyArray_DIM(arr, i);
+    }
+}
+
+
 /*
  * Take an arbitrary object and discover how many dimensions it
  * has, filling in the dimensions as we go.
@@ -695,11 +715,10 @@ discover_itemsize(PyObject *s, int nd, int *itemsize, int string_type)
 static int
 discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
                                     int stop_at_string, int stop_at_tuple,
-                                    int *out_is_object)
+                                    discovered_t *out_is_object)
 {
     PyObject *e;
     npy_intp n, i;
-    Py_buffer buffer_view;
     PyObject * seq;
 
     if (*maxndim == 0) {
@@ -708,15 +727,7 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
 
     /* obj is an Array */
     if (PyArray_Check(obj)) {
-        PyArrayObject *arr = (PyArrayObject *)obj;
-
-        if (PyArray_NDIM(arr) < *maxndim) {
-            *maxndim = PyArray_NDIM(arr);
-        }
-
-        for (i=0; i<*maxndim; i++) {
-            d[i] = PyArray_DIM(arr,i);
-        }
+        _discover_dimensions_array((PyArrayObject *)obj, maxndim, d);
         return 0;
     }
 
@@ -736,10 +747,6 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
 
     /* obj is a String */
     if (PyString_Check(obj) ||
-#if defined(NPY_PY3K)
-#else
-            PyBuffer_Check(obj) ||
-#endif
             PyUnicode_Check(obj)) {
         if (stop_at_string) {
             *maxndim = 0;
@@ -757,111 +764,24 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
         return 0;
     }
 
-    /* obj is a PEP 3118 buffer */
-    /* PEP 3118 buffer interface */
-    if (PyObject_CheckBuffer(obj) == 1) {
-        memset(&buffer_view, 0, sizeof(Py_buffer));
-        if (PyObject_GetBuffer(obj, &buffer_view,
-                    PyBUF_STRIDES|PyBUF_SIMPLE) == 0 ||
-                PyObject_GetBuffer(obj, &buffer_view,
-                    PyBUF_ND|PyBUF_SIMPLE) == 0) {
-            int nd = buffer_view.ndim;
-
-            if (nd < *maxndim) {
-                *maxndim = nd;
-            }
-            for (i = 0; i < *maxndim; i++) {
-                d[i] = buffer_view.shape[i];
-            }
-            PyBuffer_Release(&buffer_view);
-            _dealloc_cached_buffer_info(obj);
-            return 0;
-        }
-        else if (PyErr_Occurred()) {
-            if (PyErr_ExceptionMatches(PyExc_BufferError) ||
-                    PyErr_ExceptionMatches(PyExc_TypeError)) {
-                PyErr_Clear();
-            } else {
-                return -1;
-            }
-        }
-        else if (PyObject_GetBuffer(obj, &buffer_view, PyBUF_SIMPLE) == 0) {
-            d[0] = buffer_view.len;
-            *maxndim = 1;
-            PyBuffer_Release(&buffer_view);
-            _dealloc_cached_buffer_info(obj);
-            return 0;
-        }
-        else if (PyErr_Occurred()) {
-            if (PyErr_ExceptionMatches(PyExc_BufferError) ||
-                    PyErr_ExceptionMatches(PyExc_TypeError)) {
-                PyErr_Clear();
-            } else {
-                return -1;
-            }
-        }
-    }
-
-    /* obj has the __array_struct__ interface */
-    e = PyArray_LookupSpecial_OnInstance(obj, "__array_struct__");
-    if (e != NULL) {
-        int nd = -1;
-
-        if (NpyCapsule_Check(e)) {
-            PyArrayInterface *inter;
-            inter = (PyArrayInterface *)NpyCapsule_AsVoidPtr(e);
-            if (inter->two == 2) {
-                nd = inter->nd;
-                if (nd >= 0) {
-                    if (nd < *maxndim) {
-                        *maxndim = nd;
-                    }
-                    for (i=0; i<*maxndim; i++) {
-                        d[i] = inter->shape[i];
-                    }
-                }
-            }
-        }
+    /*
+     * In the future, the result of `_array_from_array_like` should possibly
+     * be cached. This may require passing the correct dtype/writable
+     * information already in the dimension discovery step (if they are
+     * distinct steps).
+     */
+    e = _array_from_array_like(obj, NULL, NPY_FALSE, NULL);
+    if (e == Py_NotImplemented) {
         Py_DECREF(e);
-        if (nd >= 0) {
-            return 0;
-        }
-    }
-    else if (PyErr_Occurred()) {
-        PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
     }
-
-
-    /* obj has the __array_interface__ interface */
-    e = PyArray_LookupSpecial_OnInstance(obj, "__array_interface__");
-    if (e != NULL) {
-        int nd = -1;
-        if (PyDict_Check(e)) {
-            PyObject *new;
-            new = PyDict_GetItemString(e, "shape");
-            if (new && PyTuple_Check(new)) {
-                nd = PyTuple_GET_SIZE(new);
-                if (nd < *maxndim) {
-                    *maxndim = nd;
-                }
-                for (i=0; i<*maxndim; i++) {
-                    d[i] = PyInt_AsSsize_t(PyTuple_GET_ITEM(new, i));
-                    if (d[i] < 0) {
-                        PyErr_SetString(PyExc_RuntimeError,
-                                "Invalid shape in __array_interface__");
-                        Py_DECREF(e);
-                        return -1;
-                    }
-                }
-            }
-        }
+    else if (e != NULL) {
+        _discover_dimensions_array((PyArrayObject *)e, maxndim, d);
         Py_DECREF(e);
-        if (nd >= 0) {
-            return 0;
-        }
+        return 0;
     }
     else if (PyErr_Occurred()) {
-        PyErr_Clear(); /* TODO[gh-14801]: propagate crashes during attribute access? */
+        /* TODO[gh-14801]: propagate crashes during attribute access? */
+        PyErr_Clear();
     }
 
     seq = PySequence_Fast(obj, "Could not convert object to sequence");
@@ -881,7 +801,7 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
         if (PyErr_ExceptionMatches(PyExc_KeyError)) {
             PyErr_Clear();
             *maxndim = 0;
-            *out_is_object = 1;
+            *out_is_object = DISCOVERED_OBJECT;
             return 0;
         }
         else {
@@ -940,7 +860,7 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
         *maxndim = all_elems_maxndim + 1;
         if (!all_dimensions_match) {
             /* typically results in an array containing variable-length lists */
-            *out_is_object = 1;
+            *out_is_object = DISCOVERED_RAGGED;
         }
     }
 
@@ -949,8 +869,8 @@ discover_dimensions(PyObject *obj, int *maxndim, npy_intp *d, int check_it,
     return 0;
 }
 
-static PyObject *
-raise_memory_error(int nd, npy_intp *dims, PyArray_Descr *descr)
+static void
+raise_memory_error(int nd, npy_intp const *dims, PyArray_Descr *descr)
 {
     static PyObject *exc_type = NULL;
 
@@ -974,12 +894,12 @@ raise_memory_error(int nd, npy_intp *dims, PyArray_Descr *descr)
     }
     PyErr_SetObject(exc_type, exc_value);
     Py_DECREF(exc_value);
-    return NULL;
+    return;
 
 fail:
     /* we couldn't raise the formatted exception for some reason */
     PyErr_WriteUnraisable(NULL);
-    return PyErr_NoMemory();
+    PyErr_NoMemory();
 }
 
 /*
@@ -1159,10 +1079,10 @@ PyArray_NewFromDescr_int(
             data = npy_alloc_cache(nbytes);
         }
         if (data == NULL) {
-            return raise_memory_error(fa->nd, fa->dimensions, descr);
+            raise_memory_error(fa->nd, fa->dimensions, descr);
+            goto fail;
         }
         fa->flags |= NPY_ARRAY_OWNDATA;
-
     }
     else {
         /*
@@ -1280,8 +1200,8 @@ PyArray_NewFromDescrAndBase(
  *             NPY_ANYORDER - Fortran if prototype is Fortran, C otherwise.
  *             NPY_KEEPORDER - Keeps the axis ordering of prototype.
  * dtype     - If not NULL, overrides the data type of the result.
- * ndim      - If not 0 and dims not NULL, overrides the shape of the result.
- * dims      - If not NULL and ndim not 0, overrides the shape of the result.
+ * ndim      - If not -1, overrides the shape of the result.
+ * dims      - If ndim is not -1, overrides the shape of the result.
  * subok     - If 1, use the prototype's array subtype, otherwise
  *             always create a base-class array.
  *
@@ -1294,7 +1214,7 @@ PyArray_NewLikeArrayWithShape(PyArrayObject *prototype, NPY_ORDER order,
 {
     PyObject *ret = NULL;
 
-    if (dims == NULL) {
+    if (ndim == -1) {
         ndim = PyArray_NDIM(prototype);
         dims = PyArray_DIMS(prototype);
     }
@@ -1391,7 +1311,7 @@ NPY_NO_EXPORT PyObject *
 PyArray_NewLikeArray(PyArrayObject *prototype, NPY_ORDER order,
                      PyArray_Descr *dtype, int subok)
 {
-    return PyArray_NewLikeArrayWithShape(prototype, order, dtype, 0, NULL, subok);
+    return PyArray_NewLikeArrayWithShape(prototype, order, dtype, -1, NULL, subok);
 }
 
 /*NUMPY_API
@@ -1578,7 +1498,107 @@ fail:
 
 }
 
-/*NUMPY_API
+
+/**
+ * Attempts to extract an array from an array-like object.
+ *
+ * array-like is defined as either
+ *
+ * * an object implementing the PEP 3118 buffer interface;
+ * * an object with __array_struct__ or __array_interface__ attributes;
+ * * an object with an __array__ function.
+ *
+ * @param op The object to convert to an array
+ * @param requested_type a requested dtype instance, may be NULL; The result
+ *                       DType may be used, but is not enforced.
+ * @param writeable whether the result must be writeable.
+ * @param context Unused parameter, must be NULL (should be removed later).
+ *
+ * @returns The array object, Py_NotImplemented if op is not array-like,
+ *          or NULL with an error set. (A new reference to Py_NotImplemented
+ *          is returned.)
+ */
+static PyObject *
+_array_from_array_like(PyObject *op,
+        PyArray_Descr *requested_dtype, npy_bool writeable, PyObject *context) {
+    PyObject* tmp;
+
+    /*
+     * If op supports the PEP 3118 buffer interface.
+     * We skip bytes and unicode since they are considered scalars. Unicode
+     * would fail but bytes would be incorrectly converted to a uint8 array.
+     */
+    if (!PyBytes_Check(op) && !PyUnicode_Check(op)) {
+        PyObject *memoryview = PyMemoryView_FromObject(op);
+        if (memoryview == NULL) {
+            PyErr_Clear();
+        }
+        else {
+            tmp = _array_from_buffer_3118(memoryview);
+            Py_DECREF(memoryview);
+            if (tmp == NULL) {
+                return NULL;
+            }
+
+            if (writeable
+                && PyArray_FailUnlessWriteable(
+                        (PyArrayObject *)tmp, "PEP 3118 buffer") < 0) {
+                Py_DECREF(tmp);
+                return NULL;
+            }
+
+            return tmp;
+        }
+    }
+
+    /*
+     * If op supports the __array_struct__ or __array_interface__ interface.
+     */
+    tmp = PyArray_FromStructInterface(op);
+    if (tmp == NULL) {
+        return NULL;
+    }
+    if (tmp == Py_NotImplemented) {
+        /* Until the return, NotImplemented is always a borrowed reference*/
+        tmp = PyArray_FromInterface(op);
+        if (tmp == NULL) {
+            return NULL;
+        }
+    }
+
+    /*
+     * If op supplies the __array__ function.
+     * The documentation says this should produce a copy, so
+     * we skip this method if writeable is true, because the intent
+     * of writeable is to modify the operand.
+     * XXX: If the implementation is wrong, and/or if actual
+     *      usage requires this behave differently,
+     *      this should be changed!
+     */
+    if (!writeable && tmp == Py_NotImplemented) {
+        tmp = PyArray_FromArrayAttr(op, requested_dtype, context);
+        if (tmp == NULL) {
+            return NULL;
+        }
+    }
+
+    if (tmp != Py_NotImplemented) {
+        if (writeable &&
+                PyArray_FailUnlessWriteable((PyArrayObject *)tmp,
+                        "array interface object") < 0) {
+            Py_DECREF(tmp);
+            return NULL;
+        }
+        return tmp;
+    }
+
+    /* Until here Py_NotImplemented was borrowed */
+    Py_INCREF(Py_NotImplemented);
+    return Py_NotImplemented;
+}
+
+
+/*
  * Retrieves the array parameters for viewing/converting an arbitrary
  * PyObject* to a NumPy array. This allows the "innate type and shape"
  * of Python list-of-lists to be discovered without
@@ -1635,12 +1655,12 @@ fail:
  *      ... use arr ...
  */
 NPY_NO_EXPORT int
-PyArray_GetArrayParamsFromObject(PyObject *op,
+PyArray_GetArrayParamsFromObject_int(PyObject *op,
                         PyArray_Descr *requested_dtype,
                         npy_bool writeable,
                         PyArray_Descr **out_dtype,
                         int *out_ndim, npy_intp *out_dims,
-                        PyArrayObject **out_arr, PyObject *context)
+                        PyArrayObject **out_arr)
 {
     PyObject *tmp;
 
@@ -1685,71 +1705,22 @@ PyArray_GetArrayParamsFromObject(PyObject *op,
         return 0;
     }
 
-    /* If op supports the PEP 3118 buffer interface */
-    if (!PyBytes_Check(op) && !PyUnicode_Check(op)) {
-
-        PyObject *memoryview = PyMemoryView_FromObject(op);
-        if (memoryview == NULL) {
-            PyErr_Clear();
-        }
-        else {
-            PyObject *arr = _array_from_buffer_3118(memoryview);
-            Py_DECREF(memoryview);
-            if (arr == NULL) {
-                return -1;
-            }
-            if (writeable
-                    && PyArray_FailUnlessWriteable((PyArrayObject *)arr, "PEP 3118 buffer") < 0) {
-                Py_DECREF(arr);
-                return -1;
-            }
-            *out_arr = (PyArrayObject *)arr;
-            return 0;
-        }
-    }
-
-    /* If op supports the __array_struct__ or __array_interface__ interface */
-    tmp = PyArray_FromStructInterface(op);
+    /* If op is an array-like */
+    tmp = _array_from_array_like(op, requested_dtype, writeable, NULL);
     if (tmp == NULL) {
         return -1;
     }
-    if (tmp == Py_NotImplemented) {
-        tmp = PyArray_FromInterface(op);
-        if (tmp == NULL) {
-            return -1;
-        }
-    }
-    if (tmp != Py_NotImplemented) {
-        if (writeable
-            && PyArray_FailUnlessWriteable((PyArrayObject *)tmp,
-                                           "array interface object") < 0) {
-            Py_DECREF(tmp);
-            return -1;
-        }
-        *out_arr = (PyArrayObject *)tmp;
-        return (*out_arr) == NULL ? -1 : 0;
+    else if (tmp != Py_NotImplemented) {
+        *out_arr = (PyArrayObject*) tmp;
+        return 0;
     }
-
-    /*
-     * If op supplies the __array__ function.
-     * The documentation says this should produce a copy, so
-     * we skip this method if writeable is true, because the intent
-     * of writeable is to modify the operand.
-     * XXX: If the implementation is wrong, and/or if actual
-     *      usage requires this behave differently,
-     *      this should be changed!
-     */
-    if (!writeable) {
-        tmp = PyArray_FromArrayAttr(op, requested_dtype, context);
-        if (tmp != Py_NotImplemented) {
-            *out_arr = (PyArrayObject *)tmp;
-            return (*out_arr) == NULL ? -1 : 0;
-        }
+    else {
+        Py_DECREF(Py_NotImplemented);
     }
 
     /* Try to treat op as a list of lists */
     if (!writeable && PySequence_Check(op)) {
-        int check_it, stop_at_string, stop_at_tuple, is_object;
+        int check_it, stop_at_string, stop_at_tuple;
         int type_num, type;
 
         /*
@@ -1799,7 +1770,7 @@ PyArray_GetArrayParamsFromObject(PyObject *op,
                          ((*out_dtype)->names || (*out_dtype)->subarray));
 
         *out_ndim = NPY_MAXDIMS;
-        is_object = 0;
+        discovered_t is_object = DISCOVERED_OK;
         if (discover_dimensions(
                 op, out_ndim, out_dims, check_it,
                 stop_at_string, stop_at_tuple, &is_object) < 0) {
@@ -1816,7 +1787,27 @@ PyArray_GetArrayParamsFromObject(PyObject *op,
             return 0;
         }
         /* If object arrays are forced */
-        if (is_object) {
+        if (is_object != DISCOVERED_OK) {
+            static PyObject *visibleDeprecationWarning = NULL;
+            npy_cache_import(
+                "numpy", "VisibleDeprecationWarning",
+                &visibleDeprecationWarning);
+            if (visibleDeprecationWarning == NULL) {
+                return -1;
+            }
+            if (is_object == DISCOVERED_RAGGED && requested_dtype == NULL) {
+                /* NumPy 1.19, 2019-11-01 */
+                if (PyErr_WarnEx(visibleDeprecationWarning, "Creating an "
+                        "ndarray from ragged nested sequences (which is a "
+                        "list-or-tuple of lists-or-tuples-or ndarrays with "
+                        "different lengths or shapes) is deprecated. If you "
+                        "meant to do this, you must specify 'dtype=object' "
+                        "when creating the ndarray", 1) < 0)
+                {
+                    return -1;
+                }
+            }
+            /* either DISCOVERED_OBJECT or there is a requested_dtype */
             Py_DECREF(*out_dtype);
             *out_dtype = PyArray_DescrFromType(NPY_OBJECT);
             if (*out_dtype == NULL) {
@@ -1882,6 +1873,38 @@ PyArray_GetArrayParamsFromObject(PyObject *op,
     return -1;
 }
 
+
+/*NUMPY_API*/
+NPY_NO_EXPORT int
+PyArray_GetArrayParamsFromObject(PyObject *op,
+                                     PyArray_Descr *requested_dtype,
+                                     npy_bool writeable,
+                                     PyArray_Descr **out_dtype,
+                                     int *out_ndim, npy_intp *out_dims,
+                                     PyArrayObject **out_arr, PyObject *context)
+{
+    /* NumPy 1.19, 2020-01-24 */
+    if (DEPRECATE(
+            "PyArray_GetArrayParamsFromObject() C-API function is deprecated "
+            "and expected to be removed rapidly. If you are using it (i.e. see "
+            "this warning/error), please notify the NumPy developers. "
+            "As of now it is expected that any use case is served similarly "
+            "well by `PyArray_FromAny()` and this function is unused outside "
+            "of NumPy itself.") < 0) {
+        return -1;
+    }
+
+    if (context != NULL) {
+        PyErr_SetString(PyExc_RuntimeError, "'context' must be NULL");
+        return -1;
+    }
+
+    return PyArray_GetArrayParamsFromObject_int(op,
+            requested_dtype, writeable, out_dtype, out_ndim, out_dims,
+            out_arr);
+}
+
+
 /*NUMPY_API
  * Does not check for NPY_ARRAY_ENSURECOPY and NPY_ARRAY_NOTSWAPPED in flags
  * Steals a reference to newtype --- which can be NULL
@@ -1899,17 +1922,21 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
     int ndim = 0;
     npy_intp dims[NPY_MAXDIMS];
 
+    if (context != NULL) {
+        PyErr_SetString(PyExc_RuntimeError, "'context' must be NULL");
+        return NULL;
+    }
+
     /* Get either the array or its parameters if it isn't an array */
-    if (PyArray_GetArrayParamsFromObject(op, newtype,
-                        0, &dtype,
-                        &ndim, dims, &arr, context) < 0) {
+    if (PyArray_GetArrayParamsFromObject_int(op,
+                newtype, 0, &dtype, &ndim, dims, &arr) < 0) {
         Py_XDECREF(newtype);
         return NULL;
     }
 
     /* If the requested dtype is flexible, adapt it */
     if (newtype != NULL) {
-        newtype = PyArray_AdaptFlexibleDType(op,
+        newtype = PyArray_AdaptFlexibleDType((arr == NULL) ? op : (PyObject *)arr,
                     (dtype == NULL) ? PyArray_DESCR(arr) : dtype,
                     newtype);
         if (newtype == NULL) {
@@ -2002,12 +2029,14 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
             PyErr_SetString(PyExc_ValueError,
                             "object of too small depth for desired array");
             Py_DECREF(arr);
+            Py_XDECREF(newtype);
             ret = NULL;
         }
         else if (max_depth != 0 && PyArray_NDIM(arr) > max_depth) {
             PyErr_SetString(PyExc_ValueError,
                             "object too deep for desired array");
             Py_DECREF(arr);
+            Py_XDECREF(newtype);
             ret = NULL;
         }
         else {
@@ -2063,6 +2092,8 @@ PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
  *
  * NPY_ARRAY_FORCECAST will cause a cast to occur regardless of whether or not
  * it is safe.
+ *
+ * context is passed through to PyArray_GetArrayParamsFromObject
  */
 
 /*NUMPY_API
@@ -2141,41 +2172,9 @@ PyArray_FromArray(PyArrayObject *arr, PyArray_Descr *newtype, int flags)
 
     /* Raise an error if the casting rule isn't followed */
     if (!PyArray_CanCastArrayTo(arr, newtype, casting)) {
-        PyObject *errmsg;
-        PyArray_Descr *arr_descr = NULL;
-        PyObject *arr_descr_repr = NULL;
-        PyObject *newtype_repr = NULL;
-
         PyErr_Clear();
-        errmsg = PyUString_FromString("Cannot cast array data from ");
-        arr_descr = PyArray_DESCR(arr);
-        if (arr_descr == NULL) {
-            Py_DECREF(newtype);
-            Py_DECREF(errmsg);
-            return NULL;
-        }
-        arr_descr_repr = PyObject_Repr((PyObject *)arr_descr);
-        if (arr_descr_repr == NULL) {
-            Py_DECREF(newtype);
-            Py_DECREF(errmsg);
-            return NULL;
-        }
-        PyUString_ConcatAndDel(&errmsg, arr_descr_repr);
-        PyUString_ConcatAndDel(&errmsg,
-                PyUString_FromString(" to "));
-        newtype_repr = PyObject_Repr((PyObject *)newtype);
-        if (newtype_repr == NULL) {
-            Py_DECREF(newtype);
-            Py_DECREF(errmsg);
-            return NULL;
-        }
-        PyUString_ConcatAndDel(&errmsg, newtype_repr);
-        PyUString_ConcatAndDel(&errmsg,
-                PyUString_FromFormat(" according to the rule %s",
-                        npy_casting_to_string(casting)));
-        PyErr_SetObject(PyExc_TypeError, errmsg);
-        Py_DECREF(errmsg);
-
+        npy_set_invalid_cast_error(
+                PyArray_DESCR(arr), newtype, casting, PyArray_NDIM(arr) == 0);
         Py_DECREF(newtype);
         return NULL;
     }
@@ -2352,9 +2351,7 @@ PyArray_FromStructInterface(PyObject *input)
 NPY_NO_EXPORT int
 _is_default_descr(PyObject *descr, PyObject *typestr) {
     PyObject *tuple, *name, *typestr2;
-#if defined(NPY_PY3K)
     PyObject *tmp = NULL;
-#endif
     int ret = 0;
 
     if (!PyList_Check(descr) || PyList_GET_SIZE(descr) != 1) {
@@ -2369,7 +2366,6 @@ _is_default_descr(PyObject *descr, PyObject *typestr) {
         return 0;
     }
     typestr2 = PyTuple_GET_ITEM(tuple, 1);
-#if defined(NPY_PY3K)
     /* Allow unicode type strings */
     if (PyUnicode_Check(typestr2)) {
         tmp = PyUnicode_AsASCIIString(typestr2);
@@ -2378,14 +2374,11 @@ _is_default_descr(PyObject *descr, PyObject *typestr) {
         }
         typestr2 = tmp;
     }
-#endif
     if (PyBytes_Check(typestr2) &&
             PyObject_RichCompareBool(typestr, typestr2, Py_EQ)) {
         ret = 1;
     }
-#if defined(NPY_PY3K)
     Py_XDECREF(tmp);
-#endif
 
     return ret;
 }
@@ -2402,11 +2395,7 @@ PyArray_FromInterface(PyObject *origin)
     PyArrayObject *ret;
     PyArray_Descr *dtype = NULL;
     char *data = NULL;
-#if defined(NPY_PY3K)
     Py_buffer view;
-#else
-    Py_ssize_t buffer_len;
-#endif
     int res, i, n;
     npy_intp dims[NPY_MAXDIMS], strides[NPY_MAXDIMS];
     int dataflags = NPY_ARRAY_BEHAVED;
@@ -2427,14 +2416,16 @@ PyArray_FromInterface(PyObject *origin)
     }
 
     /* Get type string from interface specification */
-    attr = PyDict_GetItemString(iface, "typestr");
+    attr = _PyDict_GetItemStringWithError(iface, "typestr");
     if (attr == NULL) {
         Py_DECREF(iface);
-        PyErr_SetString(PyExc_ValueError,
-                "Missing __array_interface__ typestr");
+        if (!PyErr_Occurred()) {
+            PyErr_SetString(PyExc_ValueError,
+                    "Missing __array_interface__ typestr");
+        }
         return NULL;
     }
-#if defined(NPY_PY3K)
+
     /* Allow unicode type strings */
     if (PyUnicode_Check(attr)) {
         PyObject *tmp = PyUnicode_AsASCIIString(attr);
@@ -2446,7 +2437,7 @@ PyArray_FromInterface(PyObject *origin)
     else {
         Py_INCREF(attr);
     }
-#endif
+
     if (!PyBytes_Check(attr)) {
         PyErr_SetString(PyExc_TypeError,
                     "__array_interface__ typestr must be a string");
@@ -2463,7 +2454,10 @@ PyArray_FromInterface(PyObject *origin)
      * the 'descr' attribute.
      */
     if (dtype->type_num == NPY_VOID) {
-        PyObject *descr = PyDict_GetItemString(iface, "descr");
+        PyObject *descr = _PyDict_GetItemStringWithError(iface, "descr");
+        if (descr == NULL && PyErr_Occurred()) {
+            goto fail;
+        }
         PyArray_Descr *new_dtype = NULL;
 
         if (descr != NULL && !_is_default_descr(descr, attr) &&
@@ -2474,15 +2468,20 @@ PyArray_FromInterface(PyObject *origin)
         }
     }
 
-#if defined(NPY_PY3K)
     Py_DECREF(attr);  /* Pairs with the unicode handling above */
-#endif
 
     /* Get shape tuple from interface specification */
-    attr = PyDict_GetItemString(iface, "shape");
+    attr = _PyDict_GetItemStringWithError(iface, "shape");
     if (attr == NULL) {
+        if (PyErr_Occurred()) {
+            return NULL;
+        }
         /* Shape must be specified when 'data' is specified */
-        if (PyDict_GetItemString(iface, "data") != NULL) {
+        PyObject *data = _PyDict_GetItemStringWithError(iface, "data");
+        if (data == NULL && PyErr_Occurred()) {
+            return NULL;
+        }
+        else if (data != NULL) {
             Py_DECREF(iface);
             PyErr_SetString(PyExc_ValueError,
                     "Missing __array_interface__ shape");
@@ -2513,7 +2512,10 @@ PyArray_FromInterface(PyObject *origin)
     }
 
     /* Get data buffer from interface specification */
-    attr = PyDict_GetItemString(iface, "data");
+    attr = _PyDict_GetItemStringWithError(iface, "data");
+    if (attr == NULL && PyErr_Occurred()){
+        return NULL;
+    }
 
     /* Case for data access through pointer */
     if (attr && PyTuple_Check(attr)) {
@@ -2557,7 +2559,6 @@ PyArray_FromInterface(PyObject *origin)
         else {
             base = origin;
         }
-#if defined(NPY_PY3K)
         if (PyObject_GetBuffer(base, &view,
                     PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
             PyErr_Clear();
@@ -2576,21 +2577,13 @@ PyArray_FromInterface(PyObject *origin)
          */
         PyBuffer_Release(&view);
         _dealloc_cached_buffer_info(base);
-#else
-        res = PyObject_AsWriteBuffer(base, (void **)&data, &buffer_len);
-        if (res < 0) {
-            PyErr_Clear();
-            res = PyObject_AsReadBuffer(
-                        base, (const void **)&data, &buffer_len);
-            if (res < 0) {
-                goto fail;
-            }
-            dataflags &= ~NPY_ARRAY_WRITEABLE;
-        }
-#endif
+
         /* Get offset number from interface specification */
-        attr = PyDict_GetItemString(iface, "offset");
-        if (attr) {
+        attr = _PyDict_GetItemStringWithError(iface, "offset");
+        if (attr == NULL && PyErr_Occurred()) {
+            goto fail;
+        }
+        else if (attr) {
             npy_longlong num = PyLong_AsLongLong(attr);
             if (error_converting(num)) {
                 PyErr_SetString(PyExc_TypeError,
@@ -2625,7 +2618,10 @@ PyArray_FromInterface(PyObject *origin)
             goto fail;
         }
     }
-    attr = PyDict_GetItemString(iface, "strides");
+    attr = _PyDict_GetItemStringWithError(iface, "strides");
+    if (attr == NULL && PyErr_Occurred()){
+        return NULL;
+    }
     if (attr != NULL && attr != Py_None) {
         if (!PyTuple_Check(attr)) {
             PyErr_SetString(PyExc_TypeError,
@@ -2661,13 +2657,18 @@ PyArray_FromInterface(PyObject *origin)
     return NULL;
 }
 
-/*NUMPY_API*/
+/*NUMPY_API
+ */
 NPY_NO_EXPORT PyObject *
 PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context)
 {
     PyObject *new;
     PyObject *array_meth;
 
+    if (context != NULL) {
+        PyErr_SetString(PyExc_RuntimeError, "'context' must be NULL");
+        return NULL;
+    }
     array_meth = PyArray_LookupSpecial_OnInstance(op, "__array__");
     if (array_meth == NULL) {
         if (PyErr_Occurred()) {
@@ -2675,29 +2676,11 @@ PyArray_FromArrayAttr(PyObject *op, PyArray_Descr *typecode, PyObject *context)
         }
         return Py_NotImplemented;
     }
-    if (context == NULL) {
-        if (typecode == NULL) {
-            new = PyObject_CallFunction(array_meth, NULL);
-        }
-        else {
-            new = PyObject_CallFunction(array_meth, "O", typecode);
-        }
+    if (typecode == NULL) {
+        new = PyObject_CallFunction(array_meth, NULL);
     }
     else {
-        if (typecode == NULL) {
-            new = PyObject_CallFunction(array_meth, "OO", Py_None, context);
-            if (new == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
-                PyErr_Clear();
-                new = PyObject_CallFunction(array_meth, "");
-            }
-        }
-        else {
-            new = PyObject_CallFunction(array_meth, "OO", typecode, context);
-            if (new == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
-                PyErr_Clear();
-                new = PyObject_CallFunction(array_meth, "O", typecode);
-            }
-        }
+        new = PyObject_CallFunction(array_meth, "O", typecode);
     }
     Py_DECREF(array_meth);
     if (new == NULL) {
@@ -3590,7 +3573,7 @@ array_fromfile_binary(FILE *fp, PyArray_Descr *dtype, npy_intp num, size_t *nrea
  */
 #define FROM_BUFFER_SIZE 4096
 static PyArrayObject *
-array_from_text(PyArray_Descr *dtype, npy_intp num, char *sep, size_t *nread,
+array_from_text(PyArray_Descr *dtype, npy_intp num, char const *sep, size_t *nread,
                 void *stream, next_element next, skip_separator skip_sep,
                 void *stream_data)
 {
@@ -3780,9 +3763,7 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
 {
     PyArrayObject *ret;
     char *data;
-#if defined(NPY_PY3K)
     Py_buffer view;
-#endif
     Py_ssize_t ts;
     npy_intp s, n;
     int itemsize;
@@ -3803,7 +3784,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
         return NULL;
     }
 
-#if defined(NPY_PY3K)
     if (PyObject_GetBuffer(buf, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
         writeable = 0;
         PyErr_Clear();
@@ -3822,16 +3802,6 @@ PyArray_FromBuffer(PyObject *buf, PyArray_Descr *type,
      */
     PyBuffer_Release(&view);
     _dealloc_cached_buffer_info(buf);
-#else
-    if (PyObject_AsWriteBuffer(buf, (void *)&data, &ts) == -1) {
-        writeable = 0;
-        PyErr_Clear();
-        if (PyObject_AsReadBuffer(buf, (void *)&data, &ts) == -1) {
-            Py_DECREF(type);
-            return NULL;
-        }
-    }
-#endif
 
     if ((offset < 0) || (offset > ts)) {
         PyErr_Format(PyExc_ValueError,
index 4768e4efd86f1dd293008157b402c7514810a4da..9e63cd7d2eb9cf0be77133965eb9e1d01eb68a6f 100644 (file)
@@ -30,6 +30,14 @@ PyArray_New(
         PyTypeObject *, int nd, npy_intp const *,
         int, npy_intp const*, void *, int, int, PyObject *);
 
+NPY_NO_EXPORT int
+PyArray_GetArrayParamsFromObject_int(PyObject *op,
+         PyArray_Descr *requested_dtype,
+         npy_bool writeable,
+         PyArray_Descr **out_dtype,
+         int *out_ndim, npy_intp *out_dims,
+         PyArrayObject **out_arr);
+
 NPY_NO_EXPORT PyObject *
 PyArray_FromAny(PyObject *op, PyArray_Descr *newtype, int min_depth,
                 int max_depth, int flags, PyObject *context);
index 72a3df89c9a8742fa1daa3c30ed6c9c86526b0f5..cfe80189897b594c1ada2a760d30af79f31b166c 100644 (file)
@@ -22,9 +22,9 @@
 
 #include "common.h"
 #include "numpy/arrayscalars.h"
-#include "methods.h"
 #include "_datetime.h"
 #include "datetime_strings.h"
+#include "convert_datatype.h"
 
 /*
  * Computes the python `ret, d = divmod(d, unit)`.
@@ -71,7 +71,7 @@ numpy_pydatetime_import(void)
 }
 
 /* Exported as DATETIMEUNITS in multiarraymodule.c */
-NPY_NO_EXPORT char *_datetime_strings[NPY_DATETIME_NUMUNITS] = {
+NPY_NO_EXPORT char const *_datetime_strings[NPY_DATETIME_NUMUNITS] = {
     "Y",
     "M",
     "W",
@@ -692,6 +692,14 @@ get_datetime_metadata_from_dtype(PyArray_Descr *dtype)
     return &(((PyArray_DatetimeDTypeMetaData *)dtype->c_metadata)->meta);
 }
 
+/* strtol does not know whether to put a const qualifier on endptr, wrap
+ * it so we can put this cast in one place.
+ */
+NPY_NO_EXPORT long int
+strtol_const(char const *str, char const **endptr, int base) {
+    return strtol(str, (char**)endptr, base);
+}
+
 /*
  * Converts a substring given by 'str' and 'len' into
  * a date time unit multiplier + enum value, which are populated
@@ -702,15 +710,15 @@ get_datetime_metadata_from_dtype(PyArray_Descr *dtype)
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-parse_datetime_extended_unit_from_string(char *str, Py_ssize_t len,
-                                    char *metastr,
+parse_datetime_extended_unit_from_string(char const *str, Py_ssize_t len,
+                                    char const *metastr,
                                     PyArray_DatetimeMetaData *out_meta)
 {
-    char *substr = str, *substrend = NULL;
+    char const *substr = str, *substrend = NULL;
     int den = 1;
 
     /* First comes an optional integer multiplier */
-    out_meta->num = (int)strtol(substr, &substrend, 10);
+    out_meta->num = (int)strtol_const(substr, &substrend, 10);
     if (substr == substrend) {
         out_meta->num = 1;
     }
@@ -735,7 +743,7 @@ parse_datetime_extended_unit_from_string(char *str, Py_ssize_t len,
     /* Next comes an optional integer denominator */
     if (substr-str < len && *substr == '/') {
         substr++;
-        den = (int)strtol(substr, &substrend, 10);
+        den = (int)strtol_const(substr, &substrend, 10);
         /* If the '/' exists, there must be a number followed by ']' */
         if (substr == substrend || *substrend != ']') {
             goto bad_input;
@@ -776,10 +784,10 @@ bad_input:
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-parse_datetime_metadata_from_metastr(char *metastr, Py_ssize_t len,
+parse_datetime_metadata_from_metastr(char const *metastr, Py_ssize_t len,
                                     PyArray_DatetimeMetaData *out_meta)
 {
-    char *substr = metastr, *substrend = NULL;
+    char const *substr = metastr, *substrend = NULL;
 
     /* Treat the empty string as generic units */
     if (len == 0) {
@@ -837,10 +845,10 @@ bad_input:
  * The "type" string should be NULL-terminated.
  */
 NPY_NO_EXPORT PyArray_Descr *
-parse_dtype_from_datetime_typestr(char *typestr, Py_ssize_t len)
+parse_dtype_from_datetime_typestr(char const *typestr, Py_ssize_t len)
 {
     PyArray_DatetimeMetaData meta;
-    char *metastr = NULL;
+    char const *metastr = NULL;
     int is_timedelta = 0;
     Py_ssize_t metalen = 0;
 
@@ -923,7 +931,7 @@ static NPY_DATETIMEUNIT _multiples_table[16][4] = {
  */
 NPY_NO_EXPORT int
 convert_datetime_divisor_to_multiple(PyArray_DatetimeMetaData *meta,
-                                    int den, char *metastr)
+                                    int den, char const *metastr)
 {
     int i, num, ind;
     NPY_DATETIMEUNIT *totry;
@@ -1671,7 +1679,7 @@ datetime_type_promotion(PyArray_Descr *type1, PyArray_Descr *type2)
  * Returns NPY_DATETIMEUNIT on success, NPY_FR_ERROR on failure.
  */
 NPY_NO_EXPORT NPY_DATETIMEUNIT
-parse_datetime_unit_from_string(char *str, Py_ssize_t len, char *metastr)
+parse_datetime_unit_from_string(char const *str, Py_ssize_t len, char const *metastr)
 {
     /* Use switch statements so the compiler can make it fast */
     if (len == 1) {
@@ -1956,7 +1964,7 @@ append_metastr_to_string(PyArray_DatetimeMetaData *meta,
 {
     PyObject *res;
     int num;
-    char *basestr;
+    char const *basestr;
 
     if (ret == NULL) {
         return NULL;
index cdeb65d0e10eae94f2caec1219d271e89e6581d3..d3cce8a370da96345ca9397cb829da00d7908a27 100644 (file)
@@ -1012,7 +1012,7 @@ array_busday_offset(PyObject *NPY_UNUSED(self),
 
         /* This steals the datetime_dtype reference */
         dates = (PyArrayObject *)PyArray_FromAny(dates_in, datetime_dtype,
-                                                0, 0, 0, dates_in);
+                                                0, 0, 0, NULL);
         if (dates == NULL) {
             goto fail;
         }
@@ -1021,7 +1021,7 @@ array_busday_offset(PyObject *NPY_UNUSED(self),
     /* Make 'offsets' into an array */
     offsets = (PyArrayObject *)PyArray_FromAny(offsets_in,
                             PyArray_DescrFromType(NPY_INT64),
-                            0, 0, 0, offsets_in);
+                            0, 0, 0, NULL);
     if (offsets == NULL) {
         goto fail;
     }
@@ -1142,7 +1142,7 @@ array_busday_count(PyObject *NPY_UNUSED(self),
         /* This steals the datetime_dtype reference */
         dates_begin = (PyArrayObject *)PyArray_FromAny(dates_begin_in,
                                                 datetime_dtype,
-                                                0, 0, 0, dates_begin_in);
+                                                0, 0, 0, NULL);
         if (dates_begin == NULL) {
             goto fail;
         }
@@ -1165,7 +1165,7 @@ array_busday_count(PyObject *NPY_UNUSED(self),
         /* This steals the datetime_dtype reference */
         dates_end = (PyArrayObject *)PyArray_FromAny(dates_end_in,
                                                 datetime_dtype,
-                                                0, 0, 0, dates_end_in);
+                                                0, 0, 0, NULL);
         if (dates_end == NULL) {
             goto fail;
         }
@@ -1286,7 +1286,7 @@ array_is_busday(PyObject *NPY_UNUSED(self),
         /* This steals the datetime_dtype reference */
         dates = (PyArrayObject *)PyArray_FromAny(dates_in,
                                                 datetime_dtype,
-                                                0, 0, 0, dates_in);
+                                                0, 0, 0, NULL);
         if (dates == NULL) {
             goto fail;
         }
index 7a26868e8d38d86bf8fe1504d88dcdb01dbf75a8..6936a803f15551d3c2273a238d78f82e768098e6 100644 (file)
@@ -293,7 +293,7 @@ PyArray_HolidaysConverter(PyObject *dates_in, npy_holidayslist *holidays)
 
         /* This steals the datetime_dtype reference */
         dates = (PyArrayObject *)PyArray_FromAny(dates_in, datetime_dtype,
-                                                0, 0, 0, dates_in);
+                                                0, 0, 0, NULL);
         if (dates == NULL) {
             goto fail;
         }
@@ -493,61 +493,12 @@ static PyGetSetDef busdaycalendar_getsets[] = {
 };
 
 NPY_NO_EXPORT PyTypeObject NpyBusDayCalendar_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.busdaycalendar",                     /* tp_name */
-    sizeof(NpyBusDayCalendar),                  /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)busdaycalendar_dealloc,         /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    busdaycalendar_getsets,                     /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    (initproc)busdaycalendar_init,              /* tp_init */
-    0,                                          /* tp_alloc */
-    busdaycalendar_new,                         /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.busdaycalendar",
+    .tp_basicsize = sizeof(NpyBusDayCalendar),
+    .tp_dealloc = (destructor)busdaycalendar_dealloc,
+    .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_getset = busdaycalendar_getsets,
+    .tp_init = (initproc)busdaycalendar_init,
+    .tp_new = busdaycalendar_new,
 };
index dfc01494f97c727b1604185d0c0a1364208b08f0..f847c7ea8e9c33f5190e41c55c4645acfcf75bfa 100644 (file)
@@ -20,7 +20,7 @@
 #include "npy_pycompat.h"
 
 #include "numpy/arrayscalars.h"
-#include "methods.h"
+#include "convert_datatype.h"
 #include "_datetime.h"
 #include "datetime_strings.h"
 
@@ -218,7 +218,7 @@ convert_datetimestruct_utc_to_local(npy_datetimestruct *out_dts_local,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-parse_iso_8601_datetime(char *str, Py_ssize_t len,
+parse_iso_8601_datetime(char const *str, Py_ssize_t len,
                     NPY_DATETIMEUNIT unit,
                     NPY_CASTING casting,
                     npy_datetimestruct *out,
@@ -227,7 +227,7 @@ parse_iso_8601_datetime(char *str, Py_ssize_t len,
 {
     int year_leap = 0;
     int i, numdigits;
-    char *substr;
+    char const *substr;
     Py_ssize_t sublen;
     NPY_DATETIMEUNIT bestunit;
 
@@ -1487,7 +1487,6 @@ array_datetime_as_string(PyObject *NPY_UNUSED(self), PyObject *args,
 
     /* Get a string size long enough for any datetimes we're given */
     strsize = get_datetime_iso_8601_strlen(local, unit);
-#if defined(NPY_PY3K)
     /*
      * For Python3, allocate the output array as a UNICODE array, so
      * that it will behave as strings properly
@@ -1504,7 +1503,6 @@ array_datetime_as_string(PyObject *NPY_UNUSED(self), PyObject *args,
         op_dtypes[1] = NULL;
         goto fail;
     }
-#endif
     /* Create the iteration string data type (always ASCII string) */
     op_dtypes[1] = PyArray_DescrNewFromType(NPY_STRING);
     if (op_dtypes[1] == NULL) {
index 4e60ce9298fe86b5f2e8f256fc24cadb6ee32985..148369595f18f2568368cb026bdf5233d62b60c6 100644 (file)
@@ -33,7 +33,7 @@
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-parse_iso_8601_datetime(char *str, Py_ssize_t len,
+parse_iso_8601_datetime(char const *str, Py_ssize_t len,
                     NPY_DATETIMEUNIT unit,
                     NPY_CASTING casting,
                     npy_datetimestruct *out,
index d4e18e4579ff9fe3379090e197b35886cf44b56d..b26a26abf6ae30548d2e5da15e389190a7a3b24d 100644 (file)
 static PyObject *typeDict = NULL;   /* Must be explicitly loaded */
 
 static PyArray_Descr *
-_use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag);
+_try_convert_from_inherit_tuple(PyArray_Descr *type, PyObject *newobj);
 
 static PyArray_Descr *
-_arraydescr_from_ctypes_type(PyTypeObject *type)
+_convert_from_any(PyObject *obj, int align);
+
+/*
+ * This function creates a dtype object when the object is a ctypes subclass.
+ *
+ * Returns `Py_NotImplemented` if the type is not a ctypes subclass.
+ */
+static PyArray_Descr *
+_try_convert_from_ctypes_type(PyTypeObject *type)
 {
     PyObject *_numpy_dtype_ctypes;
     PyObject *res;
 
+    if (!npy_ctypes_check(type)) {
+        Py_INCREF(Py_NotImplemented);
+        return (PyArray_Descr *)Py_NotImplemented;
+    }
+
     /* Call the python function of the same name. */
     _numpy_dtype_ctypes = PyImport_ImportModule("numpy.core._dtype_ctypes");
     if (_numpy_dtype_ctypes == NULL) {
@@ -72,25 +85,21 @@ _arraydescr_from_ctypes_type(PyTypeObject *type)
     return (PyArray_Descr *)res;
 }
 
+static PyArray_Descr *
+_convert_from_any(PyObject *obj, int align);
+
 /*
  * This function creates a dtype object when the object has a "dtype" attribute,
  * and it can be converted to a dtype object.
  *
- * Returns a new reference to a dtype object, or NULL
- * if this is not possible.
- * When the return value is true, the dtype attribute should have been used
- * and parsed. Currently the only failure mode for a 1 return is a
- * RecursionError and the descriptor is set to NULL.
- * When the return value is false, no error will be set.
+ * Returns `Py_NotImplemented` if this is not possible.
+ * Currently the only failure mode for a NULL return is a RecursionError.
  */
-int
-_arraydescr_from_dtype_attr(PyObject *obj, PyArray_Descr **newdescr)
+static PyArray_Descr *
+_try_convert_from_dtype_attr(PyObject *obj)
 {
-    PyObject *dtypedescr;
-    int ret;
-
     /* For arbitrary objects that have a "dtype" attribute */
-    dtypedescr = PyObject_GetAttrString(obj, "dtype");
+    PyObject *dtypedescr = PyObject_GetAttrString(obj, "dtype");
     if (dtypedescr == NULL) {
         /*
          * This can be reached due to recursion limit being hit while fetching
@@ -103,26 +112,33 @@ _arraydescr_from_dtype_attr(PyObject *obj, PyArray_Descr **newdescr)
             " while trying to convert the given data type from its "
             "`.dtype` attribute.") != 0) {
         Py_DECREF(dtypedescr);
-        return 1;
+        return NULL;
     }
 
-    ret = PyArray_DescrConverter(dtypedescr, newdescr);
-
+    PyArray_Descr *newdescr = _convert_from_any(dtypedescr, 0);
     Py_DECREF(dtypedescr);
     Py_LeaveRecursiveCall();
-    if (ret != NPY_SUCCEED) {
+    if (newdescr == NULL) {
         goto fail;
     }
 
-    return 1;
+    return newdescr;
 
   fail:
     /* Ignore all but recursion errors, to give ctypes a full try. */
     if (!PyErr_ExceptionMatches(PyExc_RecursionError)) {
         PyErr_Clear();
-        return 0;
+        Py_INCREF(Py_NotImplemented);
+        return (PyArray_Descr *)Py_NotImplemented;
     }
-    return 1;
+    return NULL;
+}
+
+/* Expose to another file with a prefixed name */
+NPY_NO_EXPORT PyArray_Descr *
+_arraydescr_try_convert_from_dtype_attr(PyObject *obj)
+{
+    return _try_convert_from_dtype_attr(obj);
 }
 
 /*
@@ -199,7 +215,7 @@ _check_for_commastring(const char *type, Py_ssize_t len)
 #undef _chk_byteorder
 
 static int
-is_datetime_typestr(char *type, Py_ssize_t len)
+is_datetime_typestr(char const *type, Py_ssize_t len)
 {
     if (len < 2) {
         return 0;
@@ -225,34 +241,26 @@ is_datetime_typestr(char *type, Py_ssize_t len)
 static PyArray_Descr *
 _convert_from_tuple(PyObject *obj, int align)
 {
-    PyArray_Descr *type, *res;
-    PyObject *val;
-    int errflag;
-
     if (PyTuple_GET_SIZE(obj) != 2) {
+        PyErr_Format(PyExc_TypeError, 
+               "Tuple must have size 2, but has size %zd",
+               PyTuple_GET_SIZE(obj));
         return NULL;
     }
-    if (align) {
-        if (!PyArray_DescrAlignConverter(PyTuple_GET_ITEM(obj, 0), &type)) {
-            return NULL;
-        }
+    PyArray_Descr *type = _convert_from_any(PyTuple_GET_ITEM(obj, 0), align);
+    if (type == NULL) {
+        return NULL;
     }
-    else {
-        if (!PyArray_DescrConverter(PyTuple_GET_ITEM(obj, 0), &type)) {
-            return NULL;
-        }
-    }    
-    val = PyTuple_GET_ITEM(obj,1);
+    PyObject *val = PyTuple_GET_ITEM(obj,1);
     /* try to interpret next item as a type */
-    res = _use_inherit(type, val, &errflag);
-    if (res || errflag) {
+    PyArray_Descr *res = _try_convert_from_inherit_tuple(type, val);
+    if ((PyObject *)res != Py_NotImplemented) {
         Py_DECREF(type);
         return res;
     }
-    PyErr_Clear();
+    Py_DECREF(res);
     /*
-     * We get here if res was NULL but errflag wasn't set
-     * --- i.e. the conversion to a data-descr failed in _use_inherit
+     * We get here if _try_convert_from_inherit_tuple failed without crashing
      */
     if (PyDataType_ISUNSIZED(type)) {
         /* interpret next item as a typesize */
@@ -291,11 +299,6 @@ _convert_from_tuple(PyObject *obj, int align)
          * a new fields attribute.
          */
         PyArray_Dims shape = {NULL, -1};
-        PyArray_Descr *newdescr = NULL;
-        npy_intp items;
-        int i, overflowed;
-        int nbytes;
-
         if (!(PyArray_IntpConverter(val, &shape)) || (shape.len > NPY_MAXDIMS)) {
             PyErr_SetString(PyExc_ValueError,
                     "invalid shape in fixed-type tuple.");
@@ -322,7 +325,7 @@ _convert_from_tuple(PyObject *obj, int align)
         }
 
         /* validate and set shape */
-        for (i=0; i < shape.len; i++) {
+        for (int i=0; i < shape.len; i++) {
             if (shape.ptr[i] < 0) {
                 PyErr_SetString(PyExc_ValueError,
                                 "invalid shape in fixed-type tuple: "
@@ -336,7 +339,9 @@ _convert_from_tuple(PyObject *obj, int align)
                 goto fail;
             }
         }
-        items = PyArray_OverflowMultiplyList(shape.ptr, shape.len);
+        npy_intp items = PyArray_OverflowMultiplyList(shape.ptr, shape.len);
+        int overflowed;
+        int nbytes;
         if (items < 0 || items > NPY_MAX_INT) {
             overflowed = 1;
         }
@@ -350,13 +355,14 @@ _convert_from_tuple(PyObject *obj, int align)
                             "bytes must fit into a C int.");
             goto fail;
         }
-        newdescr = PyArray_DescrNewFromType(NPY_VOID);
+        PyArray_Descr *newdescr = PyArray_DescrNewFromType(NPY_VOID);
         if (newdescr == NULL) {
             goto fail;
         }
         newdescr->elsize = nbytes;
         newdescr->subarray = PyArray_malloc(sizeof(PyArray_ArrayDescr));
         if (newdescr->subarray == NULL) {
+            Py_DECREF(newdescr);
             PyErr_NoMemory();
             goto fail;
         }
@@ -375,13 +381,15 @@ _convert_from_tuple(PyObject *obj, int align)
          */
         newdescr->subarray->shape = PyTuple_New(shape.len);
         if (newdescr->subarray->shape == NULL) {
+            Py_DECREF(newdescr);
             goto fail;
         }
-        for (i=0; i < shape.len; i++) {
+        for (int i=0; i < shape.len; i++) {
             PyTuple_SET_ITEM(newdescr->subarray->shape, i,
                              PyInt_FromLong((long)shape.ptr[i]));
 
             if (PyTuple_GET_ITEM(newdescr->subarray->shape, i) == NULL) {
+                Py_DECREF(newdescr);
                 goto fail;
             }
         }
@@ -391,7 +399,6 @@ _convert_from_tuple(PyObject *obj, int align)
 
     fail:
         Py_XDECREF(type);
-        Py_XDECREF(newdescr);
         npy_free_cache_dim_obj(shape);
         return NULL;
     }
@@ -410,138 +417,125 @@ _convert_from_tuple(PyObject *obj, int align)
 static PyArray_Descr *
 _convert_from_array_descr(PyObject *obj, int align)
 {
-    int n, i, totalsize;
-    int ret;
-    PyObject *fields, *item, *newobj;
-    PyObject *name, *tup, *title;
-    PyObject *nameslist;
-    PyArray_Descr *new;
-    PyArray_Descr *conv;
+    int n = PyList_GET_SIZE(obj);
+    PyObject *nameslist = PyTuple_New(n);
+    if (!nameslist) {
+        return NULL;
+    }
+
     /* Types with fields need the Python C API for field access */
     char dtypeflags = NPY_NEEDS_PYAPI;
     int maxalign = 0;
-
-    n = PyList_GET_SIZE(obj);
-    nameslist = PyTuple_New(n);
-    if (!nameslist) {
+    int totalsize = 0;
+    PyObject *fields = PyDict_New();
+    if (!fields) {
         return NULL;
     }
-    totalsize = 0;
-    fields = PyDict_New();
-    for (i = 0; i < n; i++) {
-        item = PyList_GET_ITEM(obj, i);
+    for (int i = 0; i < n; i++) {
+        PyObject *item = PyList_GET_ITEM(obj, i);
         if (!PyTuple_Check(item) || (PyTuple_GET_SIZE(item) < 2)) {
+            PyErr_Format(PyExc_TypeError, 
+                        "Field elements must be 2- or 3-tuples, got '%R'", 
+                        item);
             goto fail;
         }
-        name = PyTuple_GET_ITEM(item, 0);
+        PyObject *name = PyTuple_GET_ITEM(item, 0);
+        PyObject *title;
         if (PyBaseString_Check(name)) {
             title = NULL;
         }
         else if (PyTuple_Check(name)) {
             if (PyTuple_GET_SIZE(name) != 2) {
+                PyErr_Format(PyExc_TypeError, 
+                               "If a tuple, the first element of a field tuple must have "
+                               "two elements, not %zd",
+                               PyTuple_GET_SIZE(name));
                 goto fail;
             }
             title = PyTuple_GET_ITEM(name, 0);
             name = PyTuple_GET_ITEM(name, 1);
             if (!PyBaseString_Check(name)) {
+                PyErr_SetString(PyExc_TypeError, "Field name must be a str");
                 goto fail;
             }
         }
         else {
+            PyErr_SetString(PyExc_TypeError, 
+                                   "First element of field tuple is "
+                                   "neither a tuple nor str");
             goto fail;
         }
 
         /* Insert name into nameslist */
         Py_INCREF(name);
 
-#if !defined(NPY_PY3K)
-        /* convert unicode name to ascii on Python 2 if possible */ 
-        if (PyUnicode_Check(name)) {
-            PyObject *tmp = PyUnicode_AsASCIIString(name);
-            Py_DECREF(name);
-            if (tmp == NULL) { 
-                goto fail;
-            }
-            name = tmp;
-        }
-#endif
         if (PyUString_GET_SIZE(name) == 0) {
             Py_DECREF(name);
             if (title == NULL) {
                 name = PyUString_FromFormat("f%d", i);
+                if (name == NULL) {
+                    goto fail;
+                }
             }
-#if defined(NPY_PY3K)
             /* On Py3, allow only non-empty Unicode strings as field names */
             else if (PyUString_Check(title) && PyUString_GET_SIZE(title) > 0) {
                 name = title;
                 Py_INCREF(name);
             }
             else {
+                PyErr_SetString(PyExc_TypeError, "Field titles must be non-empty strings");
                 goto fail;
             }
-#else
-            else {
-                name = title;
-                Py_INCREF(name);
-            }
-#endif
         }
         PyTuple_SET_ITEM(nameslist, i, name);
 
         /* Process rest */
-
+        PyArray_Descr *conv;
         if (PyTuple_GET_SIZE(item) == 2) {
-            if (align) {
-                ret = PyArray_DescrAlignConverter(PyTuple_GET_ITEM(item, 1),
-                                                        &conv);
-            }
-            else {
-                ret = PyArray_DescrConverter(PyTuple_GET_ITEM(item, 1), &conv);
+            conv = _convert_from_any(PyTuple_GET_ITEM(item, 1), align);
+            if (conv == NULL) {
+                goto fail;
             }
         }
         else if (PyTuple_GET_SIZE(item) == 3) {
-            newobj = PyTuple_GetSlice(item, 1, 3);
-            if (align) {
-                ret = PyArray_DescrAlignConverter(newobj, &conv);
-            }
-            else {
-                ret = PyArray_DescrConverter(newobj, &conv);
-            }
+            PyObject *newobj = PyTuple_GetSlice(item, 1, 3);
+            conv = _convert_from_any(newobj, align);
             Py_DECREF(newobj);
+            if (conv == NULL) {
+                goto fail;
+            }
         }
         else {
+            PyErr_Format(PyExc_TypeError,
+                    "Field elements must be tuples with at most 3 elements, got '%R'", item);
             goto fail;
         }
-        if (ret == NPY_FAIL) {
-            goto fail;
-        }
-
-        if ((PyDict_GetItem(fields, name) != NULL)
+        if ((PyDict_GetItemWithError(fields, name) != NULL)
              || (title
                  && PyBaseString_Check(title)
-                 && (PyDict_GetItem(fields, title) != NULL))) {
-#if defined(NPY_PY3K)
-            name = PyUnicode_AsUTF8String(name);
-#endif
+                 && (PyDict_GetItemWithError(fields, title) != NULL))) {
             PyErr_Format(PyExc_ValueError,
-                    "field '%s' occurs more than once", PyString_AsString(name));
-#if defined(NPY_PY3K)
-            Py_DECREF(name);
-#endif
+                    "field %R occurs more than once", name);
+            Py_DECREF(conv);
+            goto fail;
+        }
+        else if (PyErr_Occurred()) {
+            /* Dict lookup crashed */
             Py_DECREF(conv);
             goto fail;
         }
         dtypeflags |= (conv->flags & NPY_FROM_FIELDS);
         if (align) {
-            int _align;
-
-            _align = conv->alignment;
+            int _align = conv->alignment;
             if (_align > 1) {
                 totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, _align);
             }
             maxalign = PyArray_MAX(maxalign, _align);
         }
-        tup = PyTuple_New((title == NULL ? 2 : 3));
+        PyObject *tup = PyTuple_New((title == NULL ? 2 : 3));
+        if (tup == NULL) {
+            goto fail;
+        }
         PyTuple_SET_ITEM(tup, 0, (PyObject *)conv);
         PyTuple_SET_ITEM(tup, 1, PyInt_FromLong((long) totalsize));
 
@@ -553,19 +547,29 @@ _convert_from_array_descr(PyObject *obj, int align)
         if (title != NULL) {
             Py_INCREF(title);
             PyTuple_SET_ITEM(tup, 2, title);
-            PyDict_SetItem(fields, name, tup);
+            if (PyDict_SetItem(fields, name, tup) < 0) {
+                goto fail;
+            }
             if (PyBaseString_Check(title)) {
-                if (PyDict_GetItem(fields, title) != NULL) {
+                PyObject *existing = PyDict_GetItemWithError(fields, title);
+                if (existing == NULL && PyErr_Occurred()) {
+                    goto fail;
+                }
+                if (existing != NULL) {
                     PyErr_SetString(PyExc_ValueError,
                             "title already used as a name or title.");
                     Py_DECREF(tup);
                     goto fail;
                 }
-                PyDict_SetItem(fields, title, tup);
+                if (PyDict_SetItem(fields, title, tup) < 0) {
+                    goto fail;
+                }
             }
         }
         else {
-            PyDict_SetItem(fields, name, tup);
+            if (PyDict_SetItem(fields, name, tup) < 0) {
+                goto fail;
+            }
         }
 
         totalsize += conv->elsize;
@@ -576,7 +580,7 @@ _convert_from_array_descr(PyObject *obj, int align)
         totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, maxalign);
     }
 
-    new = PyArray_DescrNewFromType(NPY_VOID);
+    PyArray_Descr *new = PyArray_DescrNewFromType(NPY_VOID);
     if (new == NULL) {
         Py_XDECREF(fields);
         Py_XDECREF(nameslist);
@@ -609,69 +613,81 @@ _convert_from_array_descr(PyObject *obj, int align)
 static PyArray_Descr *
 _convert_from_list(PyObject *obj, int align)
 {
-    int n, i;
-    int totalsize;
-    PyObject *fields;
-    PyArray_Descr *conv = NULL;
-    PyArray_Descr *new;
-    PyObject *key, *tup;
-    PyObject *nameslist = NULL;
-    int ret;
-    int maxalign = 0;
-    /* Types with fields need the Python C API for field access */
-    char dtypeflags = NPY_NEEDS_PYAPI;
-
-    n = PyList_GET_SIZE(obj);
+    int n = PyList_GET_SIZE(obj);
     /*
      * Ignore any empty string at end which _internal._commastring
      * can produce
      */
-    key = PyList_GET_ITEM(obj, n-1);
-    if (PyBytes_Check(key) && PyBytes_GET_SIZE(key) == 0) {
-        n = n - 1;
+    PyObject *last_item = PyList_GET_ITEM(obj, n-1);
+    if (PyUnicode_Check(last_item)) {
+        Py_ssize_t s = PySequence_Size(last_item);
+        if (s < 0) {
+            return NULL;
+        }
+        if (s == 0) {
+            n = n - 1;
+        }
     }
-    /* End ignore code.*/
-    totalsize = 0;
     if (n == 0) {
+        PyErr_SetString(PyExc_ValueError, "Expected at least one field name");
         return NULL;
     }
-    nameslist = PyTuple_New(n);
+    PyObject *nameslist = PyTuple_New(n);
     if (!nameslist) {
         return NULL;
     }
-    fields = PyDict_New();
-    for (i = 0; i < n; i++) {
-        tup = PyTuple_New(2);
-        key = PyUString_FromFormat("f%d", i);
-        if (align) {
-            ret = PyArray_DescrAlignConverter(PyList_GET_ITEM(obj, i), &conv);
-        }
-        else {
-            ret = PyArray_DescrConverter(PyList_GET_ITEM(obj, i), &conv);
-        }
-        if (ret == NPY_FAIL) {
-            Py_DECREF(tup);
-            Py_DECREF(key);
+    PyObject *fields = PyDict_New();
+    if (!fields) {
+        Py_DECREF(nameslist);
+        return NULL;
+    }
+
+    /* Types with fields need the Python C API for field access */
+    char dtypeflags = NPY_NEEDS_PYAPI;
+    int maxalign = 0;
+    int totalsize = 0;
+    for (int i = 0; i < n; i++) {
+        PyArray_Descr *conv = _convert_from_any(
+                PyList_GET_ITEM(obj, i), align);
+        if (conv == NULL) {
             goto fail;
         }
         dtypeflags |= (conv->flags & NPY_FROM_FIELDS);
-        PyTuple_SET_ITEM(tup, 0, (PyObject *)conv);
         if (align) {
-            int _align;
-
-            _align = conv->alignment;
+            int _align = conv->alignment;
             if (_align > 1) {
                 totalsize = NPY_NEXT_ALIGNED_OFFSET(totalsize, _align);
             }
             maxalign = PyArray_MAX(maxalign, _align);
         }
-        PyTuple_SET_ITEM(tup, 1, PyInt_FromLong((long) totalsize));
-        PyDict_SetItem(fields, key, tup);
-        Py_DECREF(tup);
+        PyObject *size_obj = PyInt_FromLong((long) totalsize);
+        if (!size_obj) {
+            Py_DECREF(conv);
+            goto fail;
+        }
+        PyObject *tup = PyTuple_New(2);
+        if (!tup) {
+            Py_DECREF(size_obj);
+            Py_DECREF(conv);
+            goto fail;
+        }
+        PyTuple_SET_ITEM(tup, 0, (PyObject *)conv);
+        PyTuple_SET_ITEM(tup, 1, size_obj);
+        PyObject *key = PyUString_FromFormat("f%d", i);
+        if (!key) {
+            Py_DECREF(tup);
+            goto fail;
+        }
+        /* steals a reference to key */
         PyTuple_SET_ITEM(nameslist, i, key);
+        int ret = PyDict_SetItem(fields, key, tup);
+        Py_DECREF(tup);
+        if (ret < 0) {
+            goto fail;
+        }
         totalsize += conv->elsize;
     }
-    new = PyArray_DescrNewFromType(NPY_VOID);
+    PyArray_Descr *new = PyArray_DescrNewFromType(NPY_VOID);
     new->fields = fields;
     new->names = nameslist;
     new->flags = dtypeflags;
@@ -710,10 +726,7 @@ _convert_from_commastring(PyObject *obj, int align)
     PyObject *listobj;
     PyArray_Descr *res;
     PyObject *_numpy_internal;
-
-    if (!PyBytes_Check(obj)) {
-        return NULL;
-    }
+    assert(PyUnicode_Check(obj));
     _numpy_internal = PyImport_ImportModule("numpy.core._internal");
     if (_numpy_internal == NULL) {
         return NULL;
@@ -730,22 +743,12 @@ _convert_from_commastring(PyObject *obj, int align)
         return NULL;
     }
     if (PyList_GET_SIZE(listobj) == 1) {
-        int retcode;
-        retcode = PyArray_DescrConverter(PyList_GET_ITEM(listobj, 0),
-                                                &res);
-        if (retcode == NPY_FAIL) {
-            res = NULL;
-        }
+        res = _convert_from_any(PyList_GET_ITEM(listobj, 0), align);
     }
     else {
         res = _convert_from_list(listobj, align);
     }
     Py_DECREF(listobj);
-    if (!res && !PyErr_Occurred()) {
-        PyErr_SetString(PyExc_ValueError,
-                "invalid data-type");
-        return NULL;
-    }
     return res;
 }
 
@@ -766,7 +769,7 @@ _is_tuple_of_integers(PyObject *obj)
 }
 
 /*
- * helper function for _use_inherit to disallow dtypes of the form
+ * helper function for _try_convert_from_inherit_tuple to disallow dtypes of the form
  * (old_dtype, new_dtype) where either of the dtypes contains python
  * objects - these dtypes are not useful and can be a source of segfaults,
  * when an attempt is made to interpret a python object as a different dtype
@@ -775,7 +778,7 @@ _is_tuple_of_integers(PyObject *obj)
  * people have been using to add a field to an object array without fields
  */
 static int
-invalid_union_object_dtype(PyArray_Descr *new, PyArray_Descr *conv)
+_validate_union_object_dtype(PyArray_Descr *new, PyArray_Descr *conv)
 {
     PyObject *name, *tup;
     PyArray_Descr *dtype;
@@ -793,8 +796,12 @@ invalid_union_object_dtype(PyArray_Descr *new, PyArray_Descr *conv)
     if (name == NULL) {
         return -1;
     }
-    tup = PyDict_GetItem(conv->fields, name);
+    tup = PyDict_GetItemWithError(conv->fields, name);
     if (tup == NULL) {
+        if (!PyErr_Occurred()) {
+            /* fields was missing the name it claimed to contain */
+            PyErr_BadInternalCall();
+        }
         return -1;
     }
     dtype = (PyArray_Descr *)PyTuple_GET_ITEM(tup, 0);
@@ -827,21 +834,26 @@ fail:
  * a['real'] and a['imag'] to an int32 array.
  *
  * leave type reference alone
+ *
+ * Returns `Py_NotImplemented` if the second tuple item is not
+ * appropriate.
  */
 static PyArray_Descr *
-_use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag)
+_try_convert_from_inherit_tuple(PyArray_Descr *type, PyObject *newobj)
 {
-    PyArray_Descr *new;
-    PyArray_Descr *conv;
-
-    *errflag = 0;
-    if (PyArray_IsScalar(newobj, Integer)
-            || _is_tuple_of_integers(newobj)
-            || !PyArray_DescrConverter(newobj, &conv)) {
-        return NULL;
+    if (PyArray_IsScalar(newobj, Integer) || _is_tuple_of_integers(newobj)) {
+        /* It's a subarray or flexible type instead */
+        Py_INCREF(Py_NotImplemented);
+        return (PyArray_Descr *)Py_NotImplemented;
+    }
+    PyArray_Descr *conv = _convert_from_any(newobj, 0);
+    if (conv == NULL) {
+        /* Let someone else try to convert this */
+        PyErr_Clear();
+        Py_INCREF(Py_NotImplemented);
+        return (PyArray_Descr *)Py_NotImplemented;
     }
-    *errflag = 1;
-    new = PyArray_DescrNew(type);
+    PyArray_Descr *new = PyArray_DescrNew(type);
     if (new == NULL) {
         goto fail;
     }
@@ -854,7 +866,7 @@ _use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag)
         Py_DECREF(new);
         goto fail;
     }
-    else if (invalid_union_object_dtype(new, conv)) {
+    else if (_validate_union_object_dtype(new, conv) < 0) {
         Py_DECREF(new);
         goto fail;
     }
@@ -875,7 +887,6 @@ _use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag)
     }
     new->flags = conv->flags;
     Py_DECREF(conv);
-    *errflag = 0;
     return new;
 
  fail:
@@ -895,7 +906,7 @@ _use_inherit(PyArray_Descr *type, PyObject *newobj, int *errflag)
  * Returns 0 on success, -1 if an exception is raised.
  */
 static int
-validate_object_field_overlap(PyArray_Descr *dtype)
+_validate_object_field_overlap(PyArray_Descr *dtype)
 {
     PyObject *names, *fields, *key, *tup, *title;
     Py_ssize_t i, j, names_size;
@@ -912,8 +923,12 @@ validate_object_field_overlap(PyArray_Descr *dtype)
         if (key == NULL) {
             return -1;
         }
-        tup = PyDict_GetItem(fields, key);
+        tup = PyDict_GetItemWithError(fields, key);
         if (tup == NULL) {
+            if (!PyErr_Occurred()) {
+                /* fields was missing the name it claimed to contain */
+                PyErr_BadInternalCall();
+            }
             return -1;
         }
         if (!PyArg_ParseTuple(tup, "Oi|O", &fld_dtype, &fld_offset, &title)) {
@@ -928,8 +943,12 @@ validate_object_field_overlap(PyArray_Descr *dtype)
                     if (key == NULL) {
                         return -1;
                     }
-                    tup = PyDict_GetItem(fields, key);
+                    tup = PyDict_GetItemWithError(fields, key);
                     if (tup == NULL) {
+                        if (!PyErr_Occurred()) {
+                            /* fields was missing the name it claimed to contain */
+                            PyErr_BadInternalCall();
+                        }
                         return -1;
                     }
                     if (!PyArg_ParseTuple(tup, "Oi|O", &fld2_dtype,
@@ -991,7 +1010,7 @@ validate_object_field_overlap(PyArray_Descr *dtype)
  * then it will be checked for conformity and used directly.
  */
 static PyArray_Descr *
-_use_fields_dict(PyObject *obj, int align)
+_convert_from_field_dict(PyObject *obj, int align)
 {
     PyObject *_numpy_internal;
     PyArray_Descr *res;
@@ -1012,48 +1031,34 @@ _use_fields_dict(PyObject *obj, int align)
 static PyArray_Descr *
 _convert_from_dict(PyObject *obj, int align)
 {
-    PyArray_Descr *new;
-    PyObject *fields = NULL;
-    PyObject *names  = NULL;
-    PyObject *offsets= NULL;
-    PyObject *descrs = NULL;
-    PyObject *titles = NULL;
-    PyObject *metadata, *tmp;
-    int n, i;
-    int totalsize, itemsize;
-    int maxalign = 0;
-    /* Types with fields need the Python C API for field access */
-    char dtypeflags = NPY_NEEDS_PYAPI;
-    int has_out_of_order_fields = 0;
-
-    fields = PyDict_New();
+    PyObject *fields = PyDict_New();
     if (fields == NULL) {
         return (PyArray_Descr *)PyErr_NoMemory();
     }
     /*
      * Use PyMapping_GetItemString to support dictproxy objects as well.
      */
-    names = PyMapping_GetItemString(obj, "names");
+    PyObject *names = PyMapping_GetItemString(obj, "names");
     if (names == NULL) {
         Py_DECREF(fields);
         /* XXX should check this is a KeyError */
         PyErr_Clear();
-        return _use_fields_dict(obj, align);
+        return _convert_from_field_dict(obj, align);
     }
-    descrs = PyMapping_GetItemString(obj, "formats");
+    PyObject *descrs = PyMapping_GetItemString(obj, "formats");
     if (descrs == NULL) {
         Py_DECREF(fields);
         /* XXX should check this is a KeyError */
         PyErr_Clear();
         Py_DECREF(names);
-        return _use_fields_dict(obj, align);
+        return _convert_from_field_dict(obj, align);
     }
-    n = PyObject_Length(names);
-    offsets = PyMapping_GetItemString(obj, "offsets");
+    int n = PyObject_Length(names);
+    PyObject *offsets = PyMapping_GetItemString(obj, "offsets");
     if (!offsets) {
         PyErr_Clear();
     }
-    titles = PyMapping_GetItemString(obj, "titles");
+    PyObject *titles = PyMapping_GetItemString(obj, "titles");
     if (!titles) {
         PyErr_Clear();
     }
@@ -1071,7 +1076,7 @@ _convert_from_dict(PyObject *obj, int align)
      * If a property 'aligned' is in the dict, it overrides the align flag
      * to be True if it not already true.
      */
-    tmp = PyMapping_GetItemString(obj, "aligned");
+    PyObject *tmp = PyMapping_GetItemString(obj, "aligned");
     if (tmp == NULL) {
         PyErr_Clear();
     } else {
@@ -1088,16 +1093,16 @@ _convert_from_dict(PyObject *obj, int align)
         Py_DECREF(tmp);
     }
 
-    totalsize = 0;
-    for (i = 0; i < n; i++) {
-        PyObject *tup, *descr, *ind, *title, *name, *off;
-        int len, ret, _align = 1;
-        PyArray_Descr *newdescr;
-
+    /* Types with fields need the Python C API for field access */
+    char dtypeflags = NPY_NEEDS_PYAPI;
+    int totalsize = 0;
+    int maxalign = 0;
+    int has_out_of_order_fields = 0;
+    for (int i = 0; i < n; i++) {
         /* Build item to insert (descr, offset, [title])*/
-        len = 2;
-        title = NULL;
-        ind = PyInt_FromLong(i);
+        int len = 2;
+        PyObject *title = NULL;
+        PyObject *ind = PyInt_FromLong(i);
         if (titles) {
             title=PyObject_GetItem(titles, ind);
             if (title && title != Py_None) {
@@ -1108,39 +1113,34 @@ _convert_from_dict(PyObject *obj, int align)
             }
             PyErr_Clear();
         }
-        tup = PyTuple_New(len);
-        descr = PyObject_GetItem(descrs, ind);
+        PyObject *tup = PyTuple_New(len);
+        PyObject *descr = PyObject_GetItem(descrs, ind);
         if (!descr) {
             Py_DECREF(tup);
             Py_DECREF(ind);
             goto fail;
         }
-        if (align) {
-            ret = PyArray_DescrAlignConverter(descr, &newdescr);
-        }
-        else {
-            ret = PyArray_DescrConverter(descr, &newdescr);
-        }
+        PyArray_Descr *newdescr = _convert_from_any(descr, align);
         Py_DECREF(descr);
-        if (ret == NPY_FAIL) {
+        if (newdescr == NULL) {
             Py_DECREF(tup);
             Py_DECREF(ind);
             goto fail;
         }
         PyTuple_SET_ITEM(tup, 0, (PyObject *)newdescr);
+        int _align = 1;
         if (align) {
             _align = newdescr->alignment;
             maxalign = PyArray_MAX(maxalign,_align);
         }
         if (offsets) {
-            long offset;
-            off = PyObject_GetItem(offsets, ind);
+            PyObject *off = PyObject_GetItem(offsets, ind);
             if (!off) {
                 Py_DECREF(tup);
                 Py_DECREF(ind);
                 goto fail;
             }
-            offset = PyArray_PyIntAsInt(off);
+            long offset = PyArray_PyIntAsInt(off);
             if (error_converting(offset)) {
                 Py_DECREF(off);
                 Py_DECREF(tup);
@@ -1168,7 +1168,9 @@ _convert_from_dict(PyObject *obj, int align)
                         "not divisible by the field alignment %d "
                         "with align=True",
                         offset, newdescr->alignment);
-                ret = NPY_FAIL;
+                Py_DECREF(ind);
+                Py_DECREF(tup);
+                goto fail;
             }
             else if (offset + newdescr->elsize > totalsize) {
                 totalsize = offset + newdescr->elsize;
@@ -1181,15 +1183,10 @@ _convert_from_dict(PyObject *obj, int align)
             PyTuple_SET_ITEM(tup, 1, PyInt_FromLong(totalsize));
             totalsize += newdescr->elsize;
         }
-        if (ret == NPY_FAIL) {
-            Py_DECREF(ind);
-            Py_DECREF(tup);
-            goto fail;
-        }
         if (len == 3) {
             PyTuple_SET_ITEM(tup, 2, title);
         }
-        name = PyObject_GetItem(names, ind);
+        PyObject *name = PyObject_GetItem(names, ind);
         Py_DECREF(ind);
         if (!name) {
             Py_DECREF(tup);
@@ -1203,33 +1200,46 @@ _convert_from_dict(PyObject *obj, int align)
         }
 
         /* Insert into dictionary */
-        if (PyDict_GetItem(fields, name) != NULL) {
+        if (PyDict_GetItemWithError(fields, name) != NULL) {
             PyErr_SetString(PyExc_ValueError,
                     "name already used as a name or title");
             Py_DECREF(tup);
             goto fail;
         }
-        PyDict_SetItem(fields, name, tup);
+        else if (PyErr_Occurred()) {
+            /* MemoryError during dict lookup */
+            Py_DECREF(tup);
+            goto fail;
+        }
+        int ret = PyDict_SetItem(fields, name, tup);
         Py_DECREF(name);
+        if (ret < 0) {
+            Py_DECREF(tup);
+            goto fail;
+        }
         if (len == 3) {
             if (PyBaseString_Check(title)) {
-                if (PyDict_GetItem(fields, title) != NULL) {
+                if (PyDict_GetItemWithError(fields, title) != NULL) {
                     PyErr_SetString(PyExc_ValueError,
                             "title already used as a name or title.");
                     Py_DECREF(tup);
                     goto fail;
                 }
-                PyDict_SetItem(fields, title, tup);
+                else if (PyErr_Occurred()) {
+                    /* MemoryError during dict lookup */
+                    goto fail;
+                }
+                if (PyDict_SetItem(fields, title, tup) < 0) {
+                    Py_DECREF(tup);
+                    goto fail;
+                }
             }
         }
         Py_DECREF(tup);
-        if (ret == NPY_FAIL) {
-            goto fail;
-        }
         dtypeflags |= (newdescr->flags & NPY_FROM_FIELDS);
     }
 
-    new = PyArray_DescrNewFromType(NPY_VOID);
+    PyArray_Descr *new = PyArray_DescrNewFromType(NPY_VOID);
     if (new == NULL) {
         goto fail;
     }
@@ -1259,7 +1269,7 @@ _convert_from_dict(PyObject *obj, int align)
      * need to verify that no OBJECT types overlap with something else.
      */
     if (has_out_of_order_fields && PyDataType_REFCHK(new)) {
-        if (validate_object_field_overlap(new) < 0) {
+        if (_validate_object_field_overlap(new) < 0) {
             Py_DECREF(new);
             goto fail;
         }
@@ -1275,7 +1285,7 @@ _convert_from_dict(PyObject *obj, int align)
     if (tmp == NULL) {
         PyErr_Clear();
     } else {
-        itemsize = (int)PyArray_PyIntAsInt(tmp);
+        int itemsize = (int)PyArray_PyIntAsInt(tmp);
         Py_DECREF(tmp);
         if (error_converting(itemsize)) {
             Py_DECREF(new);
@@ -1304,7 +1314,7 @@ _convert_from_dict(PyObject *obj, int align)
     }
 
     /* Add the metadata if provided */
-    metadata = PyMapping_GetItemString(obj, "metadata");
+    PyObject *metadata = PyMapping_GetItemString(obj, "metadata");
 
     if (metadata == NULL) {
         PyErr_Clear();
@@ -1366,6 +1376,153 @@ PyArray_DescrConverter2(PyObject *obj, PyArray_Descr **at)
     }
 }
 
+/**
+ * Get a dtype instance from a python type
+ */
+static PyArray_Descr *
+_convert_from_type(PyObject *obj) {
+    PyTypeObject *typ = (PyTypeObject*)obj;
+
+    if (PyType_IsSubtype(typ, &PyGenericArrType_Type)) {
+        return PyArray_DescrFromTypeObject(obj);
+    }
+    else if (typ == &PyLong_Type) {
+        return PyArray_DescrFromType(NPY_LONG);
+    }
+    else if (typ == &PyFloat_Type) {
+        return PyArray_DescrFromType(NPY_DOUBLE);
+    }
+    else if (typ == &PyComplex_Type) {
+        return PyArray_DescrFromType(NPY_CDOUBLE);
+    }
+    else if (typ == &PyBool_Type) {
+        return PyArray_DescrFromType(NPY_BOOL);
+    }
+    else if (typ == &PyBytes_Type) {
+        /*
+         * TODO: This should be deprecated, and have special handling for
+         *       dtype=bytes/"S" in coercion: It should not rely on "S0".
+         */
+        return PyArray_DescrFromType(NPY_STRING);
+    }
+    else if (typ == &PyUnicode_Type) {
+        /*
+         * TODO: This should be deprecated, and have special handling for
+         *       dtype=str/"U" in coercion: It should not rely on "U0".
+         */
+        return PyArray_DescrFromType(NPY_UNICODE);
+    }
+    else if (typ == &PyMemoryView_Type) {
+        return PyArray_DescrFromType(NPY_VOID);
+    }
+    else if (typ == &PyBaseObject_Type) {
+        return PyArray_DescrFromType(NPY_OBJECT);
+    }
+    else {
+        PyArray_Descr *ret = _try_convert_from_dtype_attr(obj);
+        if ((PyObject *)ret != Py_NotImplemented) {
+            return ret;
+        }
+        Py_DECREF(ret);
+
+        /*
+         * Note: this comes after _try_convert_from_dtype_attr because the ctypes
+         * type might override the dtype if numpy does not otherwise
+         * support it.
+         */
+        ret = _try_convert_from_ctypes_type(typ);
+        if ((PyObject *)ret != Py_NotImplemented) {
+            return ret;
+        }
+        Py_DECREF(ret);
+
+        /*
+         * All other classes are treated as object. This can be convenient
+         * to convey an intention of using it for a specific python type
+         * and possibly allow converting to a new type-specific dtype in the future. It may make sense to
+         * only allow this only within `dtype=...` keyword argument context
+         * in the future.
+         */
+        return PyArray_DescrFromType(NPY_OBJECT);
+    }
+}
+
+
+static PyArray_Descr *
+_convert_from_str(PyObject *obj, int align);
+
+static PyArray_Descr *
+_convert_from_any(PyObject *obj, int align)
+{
+    /* default */
+    if (obj == Py_None) {
+        return PyArray_DescrFromType(NPY_DEFAULT_TYPE);
+    }
+    else if (PyArray_DescrCheck(obj)) {
+        PyArray_Descr *ret = (PyArray_Descr *)obj;
+        Py_INCREF(ret);
+        return ret;
+    }
+    else if (PyType_Check(obj)) {
+        return _convert_from_type(obj);
+    }
+    /* or a typecode string */
+    else if (PyBytes_Check(obj)) {
+        /* Allow bytes format strings: convert to unicode */
+        PyObject *obj2 = PyUnicode_FromEncodedObject(obj, NULL, NULL);
+        if (obj2 == NULL) {
+            /* Convert the exception into a TypeError */
+            if (PyErr_ExceptionMatches(PyExc_UnicodeDecodeError)) {
+                PyErr_SetString(PyExc_TypeError,
+                        "data type not understood");
+            }
+            return NULL;
+        }
+        PyArray_Descr *ret = _convert_from_str(obj2, align);
+        Py_DECREF(obj2);
+        return ret;
+    }
+    else if (PyUnicode_Check(obj)) {
+        return _convert_from_str(obj, align);
+    }
+    else if (PyTuple_Check(obj)) {
+        /* or a tuple */
+        return _convert_from_tuple(obj, align);
+    }
+    else if (PyList_Check(obj)) {
+        /* or a list */
+        return _convert_from_array_descr(obj, align);
+    }
+    else if (PyDict_Check(obj) || PyDictProxy_Check(obj)) {
+        /* or a dictionary */
+        return _convert_from_dict(obj, align);
+    }
+    else if (PyArray_Check(obj)) {
+        PyErr_SetString(PyExc_TypeError, "Cannot construct a dtype from an array");
+        return NULL;
+    }
+    else {
+        PyArray_Descr *ret = _try_convert_from_dtype_attr(obj);
+        if ((PyObject *)ret != Py_NotImplemented) {
+            return ret;
+        }
+        Py_DECREF(ret);
+        /*
+         * Note: this comes after _try_convert_from_dtype_attr because the ctypes
+         * type might override the dtype if numpy does not otherwise
+         * support it.
+         */
+        ret = _try_convert_from_ctypes_type(Py_TYPE(obj));
+        if ((PyObject *)ret != Py_NotImplemented) {
+            return ret;
+        }
+        Py_DECREF(ret);
+        PyErr_Format(PyExc_TypeError, "Cannot interpret '%R' as a data type", obj);
+        return NULL;
+    }
+}
+
+
 /*NUMPY_API
  * Get typenum from an object -- None goes to NPY_DEFAULT_TYPE
  * This function takes a Python object representing a type and converts it
@@ -1384,367 +1541,187 @@ PyArray_DescrConverter2(PyObject *obj, PyArray_Descr **at)
 NPY_NO_EXPORT int
 PyArray_DescrConverter(PyObject *obj, PyArray_Descr **at)
 {
-    int check_num = NPY_NOTYPE + 10;
-    int elsize = 0;
-    char endian = '=';
-
-    *at = NULL;
+    *at = _convert_from_any(obj, 0);
+    return (*at) ? NPY_SUCCEED : NPY_FAIL;
+}
 
-    /* default */
-    if (obj == Py_None) {
-        *at = PyArray_DescrFromType(NPY_DEFAULT_TYPE);
-        return NPY_SUCCEED;
+/** Convert a bytestring specification into a dtype */
+static PyArray_Descr *
+_convert_from_str(PyObject *obj, int align)
+{
+    /* Check for a string typecode. */
+    Py_ssize_t len = 0;
+    char const *type = PyUnicode_AsUTF8AndSize(obj, &len);
+    if (type == NULL) {
+        return NULL;
     }
 
-    if (PyArray_DescrCheck(obj)) {
-        *at = (PyArray_Descr *)obj;
-        Py_INCREF(*at);
-        return NPY_SUCCEED;
+    /* Empty string is invalid */
+    if (len == 0) {
+        goto fail;
     }
 
-    if (PyType_Check(obj)) {
-        if (PyType_IsSubtype((PyTypeObject *)obj, &PyGenericArrType_Type)) {
-            *at = PyArray_DescrFromTypeObject(obj);
-            return (*at) ? NPY_SUCCEED : NPY_FAIL;
-        }
-        check_num = NPY_OBJECT;
-#if !defined(NPY_PY3K)
-        if (obj == (PyObject *)(&PyInt_Type)) {
-            check_num = NPY_LONG;
-        }
-        else if (obj == (PyObject *)(&PyLong_Type)) {
-            check_num = NPY_LONGLONG;
-        }
-#else
-        if (obj == (PyObject *)(&PyLong_Type)) {
-            check_num = NPY_LONG;
-        }
-#endif
-        else if (obj == (PyObject *)(&PyFloat_Type)) {
-            check_num = NPY_DOUBLE;
-        }
-        else if (obj == (PyObject *)(&PyComplex_Type)) {
-            check_num = NPY_CDOUBLE;
-        }
-        else if (obj == (PyObject *)(&PyBool_Type)) {
-            check_num = NPY_BOOL;
-        }
-        else if (obj == (PyObject *)(&PyBytes_Type)) {
-            check_num = NPY_STRING;
-        }
-        else if (obj == (PyObject *)(&PyUnicode_Type)) {
-            check_num = NPY_UNICODE;
-        }
-#if defined(NPY_PY3K)
-        else if (obj == (PyObject *)(&PyMemoryView_Type)) {
-#else
-        else if (obj == (PyObject *)(&PyBuffer_Type)) {
-#endif
-            check_num = NPY_VOID;
-        }
-        else {
-            if (_arraydescr_from_dtype_attr(obj, at)) {
-                /*
-                 * Using dtype attribute, *at may be NULL if a
-                 * RecursionError occurred.
-                 */
-                if (*at == NULL) {
-                    goto error;
-                }
-                return NPY_SUCCEED;
-            }
-            /*
-             * Note: this comes after _arraydescr_from_dtype_attr because the ctypes
-             * type might override the dtype if numpy does not otherwise
-             * support it.
-             */
-            if (npy_ctypes_check((PyTypeObject *)obj)) {
-                *at = _arraydescr_from_ctypes_type((PyTypeObject *)obj);
-                return *at ? NPY_SUCCEED : NPY_FAIL;
-            }
-        }
-        goto finish;
+    /* check for commas present or first (or second) element a digit */
+    if (_check_for_commastring(type, len)) {
+        return _convert_from_commastring(obj, align);
     }
 
-    /* or a typecode string */
-
-    if (PyUnicode_Check(obj)) {
-        /* Allow unicode format strings: convert to bytes */
-        int retval;
-        PyObject *obj2;
-        obj2 = PyUnicode_AsASCIIString(obj);
-        if (obj2 == NULL) {
-            /* Convert the exception into a TypeError */
-            PyObject *err = PyErr_Occurred();
-            if (PyErr_GivenExceptionMatches(err, PyExc_UnicodeEncodeError)) {
-                PyErr_SetString(PyExc_TypeError,
-                        "data type not understood");
-            }
-            return NPY_FAIL;
-        }
-        retval = PyArray_DescrConverter(obj2, at);
-        Py_DECREF(obj2);
-        return retval;
+    /* Process the endian character. '|' is replaced by '='*/
+    char endian = '=';
+    switch (type[0]) {
+        case '>':
+        case '<':
+        case '=':
+            endian = type[0];
+            ++type;
+            --len;
+            break;
+
+        case '|':
+            endian = '=';
+            ++type;
+            --len;
+            break;
+    }
+
+    /* Just an endian character is invalid */
+    if (len == 0) {
+        goto fail;
     }
 
-    if (PyBytes_Check(obj)) {
-        char *type = NULL;
-        Py_ssize_t len = 0;
-
-        /* Check for a string typecode. */
-        if (PyBytes_AsStringAndSize(obj, &type, &len) < 0) {
-            goto error;
-        }
-
-        /* Empty string is invalid */
-        if (len == 0) {
-            goto fail;
+    /* Check for datetime format */
+    if (is_datetime_typestr(type, len)) {
+        PyArray_Descr *ret = parse_dtype_from_datetime_typestr(type, len);
+        if (ret == NULL) {
+            return NULL;
         }
-
-        /* check for commas present or first (or second) element a digit */
-        if (_check_for_commastring(type, len)) {
-            *at = _convert_from_commastring(obj, 0);
-            return (*at) ? NPY_SUCCEED : NPY_FAIL;
+        /* ret has byte order '=' at this point */
+        if (!PyArray_ISNBO(endian)) {
+            ret->byteorder = endian;
         }
+        return ret;
+    }
 
-        /* Process the endian character. '|' is replaced by '='*/
-        switch (type[0]) {
-            case '>':
-            case '<':
-            case '=':
-                endian = type[0];
-                ++type;
-                --len;
-                break;
-
-            case '|':
-                endian = '=';
-                ++type;
-                --len;
-                break;
-        }
+    int check_num = NPY_NOTYPE + 10;
+    int elsize = 0;
+    /* A typecode like 'd' */
+    if (len == 1) {
+        /* Python byte string characters are unsigned */
+        check_num = (unsigned char) type[0];
+    }
+    /* A kind + size like 'f8' */
+    else {
+        char *typeend = NULL;
+        int kind;
 
-        /* Just an endian character is invalid */
-        if (len == 0) {
-            goto fail;
-        }
+        /* Parse the integer, make sure it's the rest of the string */
+        elsize = (int)strtol(type + 1, &typeend, 10);
+        if (typeend - type == len) {
 
-        /* Check for datetime format */
-        if (is_datetime_typestr(type, len)) {
-            *at = parse_dtype_from_datetime_typestr(type, len);
-            if (*at == NULL) {
-                return NPY_FAIL;
-            }
-            /* *at has byte order '=' at this point */
-            if (!PyArray_ISNBO(endian)) {
-                (*at)->byteorder = endian;
-            }
-            return NPY_SUCCEED;
-        }
+            kind = type[0];
+            switch (kind) {
+                case NPY_STRINGLTR:
+                case NPY_STRINGLTR2:
+                    check_num = NPY_STRING;
+                    break;
 
-        /* A typecode like 'd' */
-        if (len == 1) {
-            /* Python byte string characters are unsigned */
-            check_num = (unsigned char) type[0];
-        }
-        /* A kind + size like 'f8' */
-        else {
-            char *typeend = NULL;
-            int kind;
-
-            /* Parse the integer, make sure it's the rest of the string */
-            elsize = (int)strtol(type + 1, &typeend, 10);
-            if (typeend - type == len) {
-
-                kind = type[0];
-                switch (kind) {
-                    case NPY_STRINGLTR:
-                    case NPY_STRINGLTR2:
-                        check_num = NPY_STRING;
-                        break;
-
-                    /*
-                     * When specifying length of UNICODE
-                     * the number of characters is given to match
-                     * the STRING interface.  Each character can be
-                     * more than one byte and itemsize must be
-                     * the number of bytes.
-                     */
-                    case NPY_UNICODELTR:
-                        check_num = NPY_UNICODE;
-                        elsize <<= 2;
-                        break;
-
-                    case NPY_VOIDLTR:
-                        check_num = NPY_VOID;
-                        break;
-
-                    default:
-                        if (elsize == 0) {
-                            check_num = NPY_NOTYPE+10;
-                        }
-                        /* Support for generic processing c8, i4, f8, etc...*/
-                        else {
-                            check_num = PyArray_TypestrConvert(elsize, kind);
-                            if (check_num == NPY_NOTYPE) {
-                                check_num += 10;
-                            }
-                            elsize = 0;
+                /*
+                 * When specifying length of UNICODE
+                 * the number of characters is given to match
+                 * the STRING interface.  Each character can be
+                 * more than one byte and itemsize must be
+                 * the number of bytes.
+                 */
+                case NPY_UNICODELTR:
+                    check_num = NPY_UNICODE;
+                    elsize <<= 2;
+                    break;
+
+                case NPY_VOIDLTR:
+                    check_num = NPY_VOID;
+                    break;
+
+                default:
+                    if (elsize == 0) {
+                        check_num = NPY_NOTYPE+10;
+                    }
+                    /* Support for generic processing c8, i4, f8, etc...*/
+                    else {
+                        check_num = PyArray_TypestrConvert(elsize, kind);
+                        if (check_num == NPY_NOTYPE) {
+                            check_num += 10;
                         }
-                }
+                        elsize = 0;
+                    }
             }
         }
     }
-    else if (PyTuple_Check(obj)) {
-        /* or a tuple */
-        *at = _convert_from_tuple(obj, 0);
-        if (*at == NULL){
-            if (PyErr_Occurred()) {
-                return NPY_FAIL;
-            }
-            goto fail;
-        }
-        return NPY_SUCCEED;
+
+    if (PyErr_Occurred()) {
+        goto fail;
     }
-    else if (PyList_Check(obj)) {
-        /* or a list */
-        *at = _convert_from_array_descr(obj,0);
-        if (*at == NULL) {
-            if (PyErr_Occurred()) {
-                return NPY_FAIL;
-            }
+
+    PyArray_Descr *ret;
+    if ((check_num == NPY_NOTYPE + 10) ||
+            (ret = PyArray_DescrFromType(check_num)) == NULL) {
+        PyErr_Clear();
+        /* Now check to see if the object is registered in typeDict */
+        if (typeDict == NULL) {
             goto fail;
         }
-        return NPY_SUCCEED;
-    }
-    else if (PyDict_Check(obj) || PyDictProxy_Check(obj)) {
-        /* or a dictionary */
-        *at = _convert_from_dict(obj,0);
-        if (*at == NULL) {
+        PyObject *item = PyDict_GetItemWithError(typeDict, obj);
+        if (item == NULL) {
             if (PyErr_Occurred()) {
-                return NPY_FAIL;
+                return NULL;
             }
             goto fail;
         }
-        return NPY_SUCCEED;
-    }
-    else if (PyArray_Check(obj)) {
-        goto fail;
-    }
-    else {
-        if (_arraydescr_from_dtype_attr(obj, at)) {
-            /*
-             * Using dtype attribute, *at may be NULL if a
-             * RecursionError occurred.
-             */
-            if (*at == NULL) {
-                goto error;
-            }
-            return NPY_SUCCEED;
-        }
-        /*
-         * Note: this comes after _arraydescr_from_dtype_attr because the ctypes
-         * type might override the dtype if numpy does not otherwise
-         * support it.
-         */
-        if (npy_ctypes_check(Py_TYPE(obj))) {
-            *at = _arraydescr_from_ctypes_type(Py_TYPE(obj));
-            return *at ? NPY_SUCCEED : NPY_FAIL;
-        }
-        goto fail;
-    }
-    if (PyErr_Occurred()) {
-        goto fail;
-    }
 
-finish:
-    if ((check_num == NPY_NOTYPE + 10) ||
-            (*at = PyArray_DescrFromType(check_num)) == NULL) {
-        PyErr_Clear();
-        /* Now check to see if the object is registered in typeDict */
-        if (typeDict != NULL) {
-            PyObject *item = NULL;
-#if defined(NPY_PY3K)
-            if (PyBytes_Check(obj)) {
-                PyObject *tmp;
-                tmp = PyUnicode_FromEncodedObject(obj, "ascii", "strict");
-                if (tmp == NULL) {
+        /* Check for a deprecated Numeric-style typecode */
+        char *dep_tps[] = {"Bool", "Complex", "Float", "Int",
+                           "Object0", "String0", "Timedelta64",
+                           "Unicode0", "UInt", "Void0"};
+        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) {
+                if (DEPRECATE("Numeric-style type codes are "
+                              "deprecated and will result in "
+                              "an error in the future.") < 0) {
                     goto fail;
                 }
-                item = PyDict_GetItem(typeDict, tmp);
-                Py_DECREF(tmp);
-            }
-            else {
-                item = PyDict_GetItem(typeDict, obj);
-            }
-#else
-            item = PyDict_GetItem(typeDict, obj);
-#endif
-            if (item) {
-                /* Check for a deprecated Numeric-style typecode */
-                if (PyBytes_Check(obj)) {
-                    char *type = NULL;
-                    Py_ssize_t len = 0;
-                    char *dep_tps[] = {"Bool", "Complex", "Float", "Int",
-                                       "Object0", "String0", "Timedelta64",
-                                       "Unicode0", "UInt", "Void0"};
-                    int ndep_tps = sizeof(dep_tps) / sizeof(dep_tps[0]);
-                    int i;
-
-                    if (PyBytes_AsStringAndSize(obj, &type, &len) < 0) {
-                        goto error;
-                    }
-                    for (i = 0; i < ndep_tps; ++i) {
-                        char *dep_tp = dep_tps[i];
-
-                        if (strncmp(type, dep_tp, strlen(dep_tp)) == 0) {
-                            if (DEPRECATE("Numeric-style type codes are "
-                                          "deprecated and will result in "
-                                          "an error in the future.") < 0) {
-                                goto fail;
-                            }
-                        }
-                    }
-                }
-                return PyArray_DescrConverter(item, at);
             }
         }
-        goto fail;
+        /*
+         * Probably only ever dispatches to `_convert_from_type`, but who
+         * knows what users are injecting into `np.typeDict`.
+         */
+        return _convert_from_any(item, align);
     }
 
-    if (PyDataType_ISUNSIZED(*at) && (*at)->elsize != elsize) {
-        PyArray_DESCR_REPLACE(*at);
-        if (*at == NULL) {
-            goto error;
+    if (PyDataType_ISUNSIZED(ret) && ret->elsize != elsize) {
+        PyArray_DESCR_REPLACE(ret);
+        if (ret == NULL) {
+            return NULL;
         }
-        (*at)->elsize = elsize;
+        ret->elsize = elsize;
     }
     if (endian != '=' && PyArray_ISNBO(endian)) {
         endian = '=';
     }
-    if (endian != '=' && (*at)->byteorder != '|'
-        && (*at)->byteorder != endian) {
-        PyArray_DESCR_REPLACE(*at);
-        if (*at == NULL) {
-            goto error;
+    if (endian != '=' && ret->byteorder != '|' && ret->byteorder != endian) {
+        PyArray_DESCR_REPLACE(ret);
+        if (ret == NULL) {
+            return NULL;
         }
-        (*at)->byteorder = endian;
+        ret->byteorder = endian;
     }
-    return NPY_SUCCEED;
+    return ret;
 
 fail:
-    if (PyBytes_Check(obj)) {
-        PyErr_Format(PyExc_TypeError,
-                "data type \"%s\" not understood", PyBytes_AS_STRING(obj));
-    }
-    else {
-        PyErr_SetString(PyExc_TypeError,
-                "data type not understood");
-    }
-
-error:
-    *at = NULL;
-    return NPY_FAIL;
+    PyErr_Format(PyExc_TypeError, "data type %R not understood", obj);
+    return NULL;
 }
 
 /** Array Descr Objects for dynamic types **/
@@ -2038,7 +2015,7 @@ _arraydescr_isnative(PyArray_Descr *self)
         int offset;
         Py_ssize_t pos = 0;
         while (PyDict_Next(self->fields, &pos, &key, &value)) {
-            if NPY_TITLE_KEY(key, value) {
+            if (NPY_TITLE_KEY(key, value)) {
                 continue;
             }
             if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset, &title)) {
@@ -2179,7 +2156,14 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val)
     self->hash = -1;
     /* Update dictionary keys in fields */
     new_names = PySequence_Tuple(val);
+    if (new_names == NULL) {
+        return -1;
+    }
     new_fields = PyDict_New();
+    if (new_fields == NULL) {
+        Py_DECREF(new_names);
+        return -1;
+    }
     for (i = 0; i < N; i++) {
         PyObject *key;
         PyObject *item;
@@ -2187,20 +2171,35 @@ arraydescr_names_set(PyArray_Descr *self, PyObject *val)
         int ret;
         key = PyTuple_GET_ITEM(self->names, i);
         /* Borrowed references to item and new_key */
-        item = PyDict_GetItem(self->fields, key);
+        item = PyDict_GetItemWithError(self->fields, key);
+        if (item == NULL) {
+            if (!PyErr_Occurred()) {
+                /* fields was missing the name it claimed to contain */
+                PyErr_BadInternalCall();
+            }
+            Py_DECREF(new_names);
+            Py_DECREF(new_fields);
+            return -1;
+        }
         new_key = PyTuple_GET_ITEM(new_names, i);
         /* Check for duplicates */
         ret = PyDict_Contains(new_fields, new_key);
-        if (ret != 0) {
-            if (ret < 0) {
-                PyErr_Clear();
-            }
+        if (ret < 0) {
+            Py_DECREF(new_names);
+            Py_DECREF(new_fields);
+            return -1;
+        }
+        else if (ret != 0) {
             PyErr_SetString(PyExc_ValueError, "Duplicate field names given.");
             Py_DECREF(new_names);
             Py_DECREF(new_fields);
             return -1;
         }
-        PyDict_SetItem(new_fields, new_key, item);
+        if (PyDict_SetItem(new_fields, new_key, item) < 0) {
+            Py_DECREF(new_names);
+            Py_DECREF(new_fields);
+            return -1;
+        }
     }
 
     /* Replace names */
@@ -2281,12 +2280,8 @@ arraydescr_new(PyTypeObject *NPY_UNUSED(subtype),
         return NULL;
     }
 
-    if (align) {
-        if (!PyArray_DescrAlignConverter(odescr, &conv)) {
-            return NULL;
-        }
-    }
-    else if (!PyArray_DescrConverter(odescr, &conv)) {
+    conv = _convert_from_any(odescr, align);
+    if (conv == NULL) {
         return NULL;
     }
 
@@ -2439,7 +2434,7 @@ arraydescr_reduce(PyArray_Descr *self, PyObject *NPY_UNUSED(args))
         }
         obj = PyUString_FromFormat("%c%d",self->kind, elsize);
     }
-    PyTuple_SET_ITEM(ret, 1, Py_BuildValue("(Nii)", obj, 0, 1));
+    PyTuple_SET_ITEM(ret, 1, Py_BuildValue("(NOO)", obj, Py_False, Py_True));
 
     /*
      * Now return the state which is at least byteorder,
@@ -2530,7 +2525,7 @@ _descr_find_object(PyArray_Descr *self)
         Py_ssize_t pos = 0;
 
         while (PyDict_Next(self->fields, &pos, &key, &value)) {
-            if NPY_TITLE_KEY(key, value) {
+            if (NPY_TITLE_KEY(key, value)) {
                 continue;
             }
             if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset, &title)) {
@@ -2639,8 +2634,12 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
         if (fields != Py_None) {
             PyObject *key, *list;
             key = PyInt_FromLong(-1);
-            list = PyDict_GetItem(fields, key);
+            list = PyDict_GetItemWithError(fields, key);
             if (!list) {
+                if (!PyErr_Occurred()) {
+                    /* fields was missing the name it claimed to contain */
+                    PyErr_BadInternalCall();
+                }
                 return NULL;
             }
             Py_INCREF(list);
@@ -2733,11 +2732,7 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
         subarray_shape = PyTuple_GET_ITEM(subarray, 1);
         if (PyNumber_Check(subarray_shape)) {
             PyObject *tmp;
-#if defined(NPY_PY3K)
             tmp = PyNumber_Long(subarray_shape);
-#else
-            tmp = PyNumber_Int(subarray_shape);
-#endif
             if (tmp == NULL) {
                 return NULL;
             }
@@ -2792,7 +2787,6 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
             }
         }
         else {
-#if defined(NPY_PY3K)
             /*
              * To support pickle.load(f, encoding='bytes') for loading Py2
              * generated pickles on Py3, we need to be more lenient and convert
@@ -2816,8 +2810,12 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
 
             for (i = 0; i < PyTuple_GET_SIZE(names); ++i) {
                 name = PyTuple_GET_ITEM(names, i);
-                field = PyDict_GetItem(fields, name);
+                field = PyDict_GetItemWithError(fields, name);
                 if (!field) {
+                    if (!PyErr_Occurred()) {
+                        /* fields was missing the name it claimed to contain */
+                        PyErr_BadInternalCall();
+                    }
                     return NULL;
                 }
 
@@ -2837,11 +2835,6 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
                     return NULL;
                 }
             }
-#else
-            PyErr_Format(PyExc_ValueError,
-                "non-string names in Numpy dtype unpickling");
-            return NULL;
-#endif
         }
     }
 
@@ -2930,35 +2923,8 @@ arraydescr_setstate(PyArray_Descr *self, PyObject *args)
 NPY_NO_EXPORT int
 PyArray_DescrAlignConverter(PyObject *obj, PyArray_Descr **at)
 {
-    if (PyDict_Check(obj) || PyDictProxy_Check(obj)) {
-        *at =  _convert_from_dict(obj, 1);
-    }
-    else if (PyBytes_Check(obj)) {
-        *at = _convert_from_commastring(obj, 1);
-    }
-    else if (PyUnicode_Check(obj)) {
-        PyObject *tmp;
-        tmp = PyUnicode_AsASCIIString(obj);
-        *at = _convert_from_commastring(tmp, 1);
-        Py_DECREF(tmp);
-    }
-    else if (PyTuple_Check(obj)) {
-        *at = _convert_from_tuple(obj, 1);
-    }
-    else if (PyList_Check(obj)) {
-        *at = _convert_from_array_descr(obj, 1);
-    }
-    else {
-        return PyArray_DescrConverter(obj, at);
-    }
-    if (*at == NULL) {
-        if (!PyErr_Occurred()) {
-            PyErr_SetString(PyExc_ValueError,
-                    "data-type-descriptor not understood");
-        }
-        return NPY_FAIL;
-    }
-    return NPY_SUCCEED;
+    *at = _convert_from_any(obj, 1);
+    return (*at) ? NPY_SUCCEED : NPY_FAIL;
 }
 
 /*NUMPY_API
@@ -2969,32 +2935,13 @@ PyArray_DescrAlignConverter(PyObject *obj, PyArray_Descr **at)
 NPY_NO_EXPORT int
 PyArray_DescrAlignConverter2(PyObject *obj, PyArray_Descr **at)
 {
-    if (PyDict_Check(obj) || PyDictProxy_Check(obj)) {
-        *at =  _convert_from_dict(obj, 1);
-    }
-    else if (PyBytes_Check(obj)) {
-        *at = _convert_from_commastring(obj, 1);
-    }
-    else if (PyUnicode_Check(obj)) {
-        PyObject *tmp;
-        tmp = PyUnicode_AsASCIIString(obj);
-        *at = _convert_from_commastring(tmp, 1);
-        Py_DECREF(tmp);
-    }
-    else if (PyList_Check(obj)) {
-        *at = _convert_from_array_descr(obj, 1);
+    if (obj == Py_None) {
+        *at = NULL;
+        return NPY_SUCCEED;
     }
     else {
-        return PyArray_DescrConverter2(obj, at);
+        return PyArray_DescrAlignConverter(obj, at);
     }
-    if (*at == NULL) {
-        if (!PyErr_Occurred()) {
-            PyErr_SetString(PyExc_ValueError,
-                    "data-type-descriptor not understood");
-        }
-        return NPY_FAIL;
-    }
-    return NPY_SUCCEED;
 }
 
 
@@ -3052,7 +2999,7 @@ PyArray_DescrNewByteorder(PyArray_Descr *self, char newendian)
         newfields = PyDict_New();
         /* make new dictionary with replaced PyArray_Descr Objects */
         while (PyDict_Next(self->fields, &pos, &key, &value)) {
-            if NPY_TITLE_KEY(key, value) {
+            if (NPY_TITLE_KEY(key, value)) {
                 continue;
             }
             if (!PyUString_Check(key) || !PyTuple_Check(value) ||
@@ -3076,8 +3023,13 @@ PyArray_DescrNewByteorder(PyArray_Descr *self, char newendian)
                 Py_INCREF(old);
                 PyTuple_SET_ITEM(newvalue, i, old);
             }
-            PyDict_SetItem(newfields, key, newvalue);
+            int ret = PyDict_SetItem(newfields, key, newvalue);
             Py_DECREF(newvalue);
+            if (ret < 0) {
+                Py_DECREF(newfields);
+                Py_DECREF(new);
+                return NULL;
+            }
         }
         Py_DECREF(new->fields);
         new->fields = newfields;
@@ -3214,71 +3166,41 @@ arraydescr_str(PyArray_Descr *dtype)
 static PyObject *
 arraydescr_richcompare(PyArray_Descr *self, PyObject *other, int cmp_op)
 {
-    PyArray_Descr *new = NULL;
-    PyObject *result = Py_NotImplemented;
-    if (!PyArray_DescrCheck(other)) {
-        if (PyArray_DescrConverter(other, &new) == NPY_FAIL) {
-            return NULL;
-        }
-    }
-    else {
-        new = (PyArray_Descr *)other;
-        Py_INCREF(new);
+    PyArray_Descr *new = _convert_from_any(other, 0);
+    if (new == NULL) {
+        return NULL;
     }
+
+    npy_bool ret;
     switch (cmp_op) {
     case Py_LT:
-        if (!PyArray_EquivTypes(self, new) && PyArray_CanCastTo(self, new)) {
-            result = Py_True;
-        }
-        else {
-            result = Py_False;
-        }
-        break;
+        ret = !PyArray_EquivTypes(self, new) && PyArray_CanCastTo(self, new);
+        Py_DECREF(new);
+        return PyBool_FromLong(ret);
     case Py_LE:
-        if (PyArray_CanCastTo(self, new)) {
-            result = Py_True;
-        }
-        else {
-            result = Py_False;
-        }
-        break;
+        ret = PyArray_CanCastTo(self, new);
+        Py_DECREF(new);
+        return PyBool_FromLong(ret);
     case Py_EQ:
-        if (PyArray_EquivTypes(self, new)) {
-            result = Py_True;
-        }
-        else {
-            result = Py_False;
-        }
-        break;
+        ret = PyArray_EquivTypes(self, new);
+        Py_DECREF(new);
+        return PyBool_FromLong(ret);
     case Py_NE:
-        if (PyArray_EquivTypes(self, new))
-            result = Py_False;
-        else
-            result = Py_True;
-        break;
+        ret = !PyArray_EquivTypes(self, new);
+        Py_DECREF(new);
+        return PyBool_FromLong(ret);
     case Py_GT:
-        if (!PyArray_EquivTypes(self, new) && PyArray_CanCastTo(new, self)) {
-            result = Py_True;
-        }
-        else {
-            result = Py_False;
-        }
-        break;
+        ret = !PyArray_EquivTypes(self, new) && PyArray_CanCastTo(new, self);
+        Py_DECREF(new);
+        return PyBool_FromLong(ret);
     case Py_GE:
-        if (PyArray_CanCastTo(new, self)) {
-            result = Py_True;
-        }
-        else {
-            result = Py_False;
-        }
-        break;
+        ret = PyArray_CanCastTo(new, self);
+        Py_DECREF(new);
+        return PyBool_FromLong(ret);
     default:
-        result = Py_NotImplemented;
+        Py_DECREF(new);
+        Py_RETURN_NOTIMPLEMENTED;
     }
-
-    Py_XDECREF(new);
-    Py_INCREF(result);
-    return result;
 }
 
 static int
@@ -3290,20 +3212,7 @@ descr_nonzero(PyObject *NPY_UNUSED(self))
 }
 
 static PyNumberMethods descr_as_number = {
-    (binaryfunc)0,                          /* nb_add */
-    (binaryfunc)0,                          /* nb_subtract */
-    (binaryfunc)0,                          /* nb_multiply */
-    #if defined(NPY_PY3K)
-    #else
-    (binaryfunc)0,                          /* nb_divide */
-    #endif
-    (binaryfunc)0,                          /* nb_remainder */
-    (binaryfunc)0,                          /* nb_divmod */
-    (ternaryfunc)0,                         /* nb_power */
-    (unaryfunc)0,                           /* nb_negative */
-    (unaryfunc)0,                           /* nb_positive */
-    (unaryfunc)0,                           /* nb_absolute */
-    (inquiry)descr_nonzero,                 /* nb_nonzero */
+    .nb_bool = (inquiry)descr_nonzero,
 };
 
 /*************************************************************************
@@ -3336,7 +3245,7 @@ descr_repeat(PyObject *self, Py_ssize_t length)
     if (tup == NULL) {
         return NULL;
     }
-    PyArray_DescrConverter(tup, &new);
+    new = _convert_from_any(tup, 0);
     Py_DECREF(tup);
     return (PyObject *)new;
 }
@@ -3345,20 +3254,7 @@ static int
 _check_has_fields(PyArray_Descr *self)
 {
     if (!PyDataType_HASFIELDS(self)) {
-        PyObject *astr = arraydescr_str(self);
-        if (astr == NULL) {
-            return -1;
-        }
-#if defined(NPY_PY3K)
-        {
-            PyObject *bstr = PyUnicode_AsUnicodeEscapeString(astr);
-            Py_DECREF(astr);
-            astr = bstr;
-        }
-#endif
-        PyErr_Format(PyExc_KeyError,
-                "There are no fields in dtype %s.", PyBytes_AsString(astr));
-        Py_DECREF(astr);
+        PyErr_Format(PyExc_KeyError, "There are no fields in dtype %S.", self);
         return -1;
     }
     else {
@@ -3369,26 +3265,15 @@ _check_has_fields(PyArray_Descr *self)
 static PyObject *
 _subscript_by_name(PyArray_Descr *self, PyObject *op)
 {
-    PyObject *obj = PyDict_GetItem(self->fields, op);
-    PyObject *descr;
-    PyObject *s;
-
+    PyObject *obj = PyDict_GetItemWithError(self->fields, op);
     if (obj == NULL) {
-        if (PyUnicode_Check(op)) {
-            s = PyUnicode_AsUnicodeEscapeString(op);
-        }
-        else {
-            s = op;
-        }
-
-        PyErr_Format(PyExc_KeyError,
-                "Field named \'%s\' not found.", PyBytes_AsString(s));
-        if (s != op) {
-            Py_DECREF(s);
+        if (!PyErr_Occurred()) {
+            PyErr_Format(PyExc_KeyError,
+                    "Field named %R not found.", op);
         }
         return NULL;
     }
-    descr = PyTuple_GET_ITEM(obj, 0);
+    PyObject *descr = PyTuple_GET_ITEM(obj, 0);
     Py_INCREF(descr);
     return descr;
 }
@@ -3462,9 +3347,11 @@ arraydescr_field_subset_view(PyArray_Descr *self, PyObject *ind)
          */
         PyTuple_SET_ITEM(names, i, name);
 
-        tup = PyDict_GetItem(self->fields, name);
+        tup = PyDict_GetItemWithError(self->fields, name);
         if (tup == NULL) {
-            PyErr_SetObject(PyExc_KeyError, name);
+            if (!PyErr_Occurred()) {
+                PyErr_SetObject(PyExc_KeyError, name);
+            }
             goto fail;
         }
 
@@ -3570,61 +3457,20 @@ static PyMappingMethods descr_as_mapping = {
 /****************** End of Mapping Protocol ******************************/
 
 NPY_NO_EXPORT PyTypeObject PyArrayDescr_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.dtype",                              /* tp_name */
-    sizeof(PyArray_Descr),                      /* tp_basicsize */
-    0,                                          /* tp_itemsize */
+    .tp_name = "numpy.dtype",
+    .tp_basicsize = sizeof(PyArray_Descr),
     /* methods */
-    (destructor)arraydescr_dealloc,             /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    (void *)0,                                  /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    (reprfunc)arraydescr_repr,                  /* tp_repr */
-    &descr_as_number,                           /* tp_as_number */
-    &descr_as_sequence,                         /* tp_as_sequence */
-    &descr_as_mapping,                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    (reprfunc)arraydescr_str,                   /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    (richcmpfunc)arraydescr_richcompare,        /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    arraydescr_methods,                         /* tp_methods */
-    arraydescr_members,                         /* tp_members */
-    arraydescr_getsets,                         /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    arraydescr_new,                             /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_dealloc = (destructor)arraydescr_dealloc,
+    .tp_repr = (reprfunc)arraydescr_repr,
+    .tp_as_number = &descr_as_number,
+    .tp_as_sequence = &descr_as_sequence,
+    .tp_as_mapping = &descr_as_mapping,
+    .tp_str = (reprfunc)arraydescr_str,
+    .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_richcompare = (richcmpfunc)arraydescr_richcompare,
+    .tp_methods = arraydescr_methods,
+    .tp_members = arraydescr_members,
+    .tp_getset = arraydescr_getsets,
+    .tp_new = arraydescr_new,
 };
index 6024c5e77c3bbee4e29f4fc4be7bd83bd5945ee7..fc9e0895b88ef8c157b7aa3819bae32e3647f336 100644 (file)
@@ -7,8 +7,8 @@ NPY_NO_EXPORT PyObject *arraydescr_protocol_descr_get(PyArray_Descr *self);
 NPY_NO_EXPORT PyObject *
 array_set_typeDict(PyObject *NPY_UNUSED(ignored), PyObject *args);
 
-int
-_arraydescr_from_dtype_attr(PyObject *obj, PyArray_Descr **newdescr);
+NPY_NO_EXPORT PyArray_Descr *
+_arraydescr_try_convert_from_dtype_attr(PyObject *obj);
 
 
 NPY_NO_EXPORT int
@@ -26,6 +26,6 @@ is_dtype_struct_simple_unaligned_layout(PyArray_Descr *dtype);
 NPY_NO_EXPORT PyArray_Descr *
 arraydescr_field_subset_view(PyArray_Descr *self, PyObject *ind);
 
-extern NPY_NO_EXPORT char *_datetime_strings[];
+extern NPY_NO_EXPORT char const *_datetime_strings[];
 
 #endif
index 1694596e99e45b820c0061bb52ea8ad7f4b9ace8..553d0effb60251f0fbeab5dca59310814f6fd090 100644 (file)
@@ -1565,8 +1565,8 @@ Dragon4(BigInt *bigints, const npy_int32 exponent,
 /* Options struct for easy passing of Dragon4 options.
  *
  *   scientific - boolean controlling whether scientific notation is used
- *   digit_mode - whether to use unique or fixed fracional output
- *   cutoff_mode - whether 'precision' refers to toal digits, or digits past
+ *   digit_mode - whether to use unique or fixed fractional output
+ *   cutoff_mode - whether 'precision' refers to all digits, or digits past
  *                 the decimal point.
  *   precision - When negative, prints as many digits as needed for a unique
  *               number. When positive specifies the maximum number of
@@ -3183,19 +3183,19 @@ Dragon4_Positional(PyObject *obj, DigitMode digit_mode, CutoffMode cutoff_mode,
     opt.exp_digits = -1;
 
     if (PyArray_IsScalar(obj, Half)) {
-        npy_half x = ((PyHalfScalarObject *)obj)->obval;
+        npy_half x = PyArrayScalar_VAL(obj, Half);
         return Dragon4_Positional_Half_opt(&x, &opt);
     }
     else if (PyArray_IsScalar(obj, Float)) {
-        npy_float x = ((PyFloatScalarObject *)obj)->obval;
+        npy_float x = PyArrayScalar_VAL(obj, Float);
         return Dragon4_Positional_Float_opt(&x, &opt);
     }
     else if (PyArray_IsScalar(obj, Double)) {
-        npy_double x = ((PyDoubleScalarObject *)obj)->obval;
+        npy_double x = PyArrayScalar_VAL(obj, Double);
         return Dragon4_Positional_Double_opt(&x, &opt);
     }
     else if (PyArray_IsScalar(obj, LongDouble)) {
-        npy_longdouble x = ((PyLongDoubleScalarObject *)obj)->obval;
+        npy_longdouble x = PyArrayScalar_VAL(obj, LongDouble);
         return Dragon4_Positional_LongDouble_opt(&x, &opt);
     }
 
@@ -3224,19 +3224,19 @@ Dragon4_Scientific(PyObject *obj, DigitMode digit_mode, int precision,
     opt.exp_digits = exp_digits;
 
     if (PyArray_IsScalar(obj, Half)) {
-        npy_half x = ((PyHalfScalarObject *)obj)->obval;
+        npy_half x = PyArrayScalar_VAL(obj, Half);
         return Dragon4_Scientific_Half_opt(&x, &opt);
     }
     else if (PyArray_IsScalar(obj, Float)) {
-        npy_float x = ((PyFloatScalarObject *)obj)->obval;
+        npy_float x = PyArrayScalar_VAL(obj, Float);
         return Dragon4_Scientific_Float_opt(&x, &opt);
     }
     else if (PyArray_IsScalar(obj, Double)) {
-        npy_double x = ((PyDoubleScalarObject *)obj)->obval;
+        npy_double x = PyArrayScalar_VAL(obj, Double);
         return Dragon4_Scientific_Double_opt(&x, &opt);
     }
     else if (PyArray_IsScalar(obj, LongDouble)) {
-        npy_longdouble x = ((PyLongDoubleScalarObject *)obj)->obval;
+        npy_longdouble x = PyArrayScalar_VAL(obj, LongDouble);
         return Dragon4_Scientific_LongDouble_opt(&x, &opt);
     }
 
index ef0dd4a0141cb49b703a6699b719f49c1c88ef8d..ecaa680ecf8ac139e5c249d77bac6971dd57b1a8 100644 (file)
@@ -312,6 +312,7 @@ typedef struct {
     NpyAuxData *wrappeddata, *todata, *fromdata;
     npy_intp src_itemsize, dst_itemsize;
     char *bufferin, *bufferout;
+    npy_bool init_dest, out_needs_api;
 } _align_wrap_data;
 
 /* transfer data free function */
@@ -372,6 +373,9 @@ static NpyAuxData *_align_wrap_data_clone(NpyAuxData *data)
         }
     }
 
+    newdata->init_dest = d->init_dest;
+    newdata->out_needs_api = d->out_needs_api;
+
     return (NpyAuxData *)newdata;
 }
 
@@ -391,57 +395,26 @@ _strided_to_strided_contig_align_wrap(char *dst, npy_intp dst_stride,
             *todata = d->todata,
             *fromdata = d->fromdata;
     char *bufferin = d->bufferin, *bufferout = d->bufferout;
+    npy_bool init_dest = d->init_dest, out_needs_api = d->out_needs_api;
 
     for(;;) {
-        if (N > NPY_LOWLEVEL_BUFFER_BLOCKSIZE) {
-            tobuffer(bufferin, inner_src_itemsize, src, src_stride,
-                                    NPY_LOWLEVEL_BUFFER_BLOCKSIZE,
-                                    src_itemsize, todata);
-            wrapped(bufferout, dst_itemsize, bufferin, inner_src_itemsize,
-                                    NPY_LOWLEVEL_BUFFER_BLOCKSIZE,
-                                    inner_src_itemsize, wrappeddata);
-            frombuffer(dst, dst_stride, bufferout, dst_itemsize,
-                                    NPY_LOWLEVEL_BUFFER_BLOCKSIZE,
-                                    dst_itemsize, fromdata);
-            N -= NPY_LOWLEVEL_BUFFER_BLOCKSIZE;
-            src += NPY_LOWLEVEL_BUFFER_BLOCKSIZE*src_stride;
-            dst += NPY_LOWLEVEL_BUFFER_BLOCKSIZE*dst_stride;
-        }
-        else {
-            tobuffer(bufferin, inner_src_itemsize, src, src_stride, N,
-                                            src_itemsize, todata);
-            wrapped(bufferout, dst_itemsize, bufferin, inner_src_itemsize, N,
-                                            inner_src_itemsize, wrappeddata);
-            frombuffer(dst, dst_stride, bufferout, dst_itemsize, N,
-                                            dst_itemsize, fromdata);
+        /*
+         * The caller does not know if a previous call resulted in a Python
+         * exception. Much of the Python API is unsafe while an exception is in
+         * flight, so just skip all the work. Someone higher in the call stack
+         * will check for errors and propagate them.
+         */
+        if (out_needs_api && PyErr_Occurred()) {
             return;
         }
-    }
-}
-
-static void
-_strided_to_strided_contig_align_wrap_init_dest(char *dst, npy_intp dst_stride,
-                        char *src, npy_intp src_stride,
-                        npy_intp N, npy_intp src_itemsize,
-                        NpyAuxData *data)
-{
-    _align_wrap_data *d = (_align_wrap_data *)data;
-    PyArray_StridedUnaryOp *wrapped = d->wrapped,
-            *tobuffer = d->tobuffer,
-            *frombuffer = d->frombuffer;
-    npy_intp inner_src_itemsize = d->src_itemsize,
-             dst_itemsize = d->dst_itemsize;
-    NpyAuxData *wrappeddata = d->wrappeddata,
-            *todata = d->todata,
-            *fromdata = d->fromdata;
-    char *bufferin = d->bufferin, *bufferout = d->bufferout;
-
-    for(;;) {
         if (N > NPY_LOWLEVEL_BUFFER_BLOCKSIZE) {
             tobuffer(bufferin, inner_src_itemsize, src, src_stride,
                                     NPY_LOWLEVEL_BUFFER_BLOCKSIZE,
                                     src_itemsize, todata);
-            memset(bufferout, 0, dst_itemsize*NPY_LOWLEVEL_BUFFER_BLOCKSIZE);
+            if (init_dest) {
+                memset(bufferout, 0,
+                        dst_itemsize*NPY_LOWLEVEL_BUFFER_BLOCKSIZE);
+            }
             wrapped(bufferout, dst_itemsize, bufferin, inner_src_itemsize,
                                     NPY_LOWLEVEL_BUFFER_BLOCKSIZE,
                                     inner_src_itemsize, wrappeddata);
@@ -455,7 +428,9 @@ _strided_to_strided_contig_align_wrap_init_dest(char *dst, npy_intp dst_stride,
         else {
             tobuffer(bufferin, inner_src_itemsize, src, src_stride, N,
                                             src_itemsize, todata);
-            memset(bufferout, 0, dst_itemsize*N);
+            if (init_dest) {
+                memset(bufferout, 0, dst_itemsize*N);
+            }
             wrapped(bufferout, dst_itemsize, bufferin, inner_src_itemsize, N,
                                             inner_src_itemsize, wrappeddata);
             frombuffer(dst, dst_stride, bufferout, dst_itemsize, N,
@@ -477,6 +452,7 @@ _strided_to_strided_contig_align_wrap_init_dest(char *dst, npy_intp dst_stride,
  * wrapped - contig to contig transfer function being wrapped
  * wrappeddata - data for wrapped
  * init_dest - 1 means to memset the dest buffer to 0 before calling wrapped.
+ * out_needs_api - if NPY_TRUE, check for (and break on) Python API errors.
  *
  * Returns NPY_SUCCEED or NPY_FAIL.
  */
@@ -487,6 +463,7 @@ wrap_aligned_contig_transfer_function(
             PyArray_StridedUnaryOp *frombuffer, NpyAuxData *fromdata,
             PyArray_StridedUnaryOp *wrapped, NpyAuxData *wrappeddata,
             int init_dest,
+            int out_needs_api,
             PyArray_StridedUnaryOp **out_stransfer,
             NpyAuxData **out_transferdata)
 {
@@ -519,14 +496,11 @@ wrap_aligned_contig_transfer_function(
     data->bufferin = (char *)data + basedatasize;
     data->bufferout = data->bufferin +
                 NPY_LOWLEVEL_BUFFER_BLOCKSIZE*src_itemsize;
+    data->init_dest = (npy_bool) init_dest;
+    data->out_needs_api = (npy_bool) out_needs_api;
 
     /* Set the function and data */
-    if (init_dest) {
-        *out_stransfer = &_strided_to_strided_contig_align_wrap_init_dest;
-    }
-    else {
-        *out_stransfer = &_strided_to_strided_contig_align_wrap;
-    }
+    *out_stransfer = &_strided_to_strided_contig_align_wrap;
     *out_transferdata = (NpyAuxData *)data;
 
     return NPY_SUCCEED;
@@ -1171,6 +1145,7 @@ get_datetime_to_unicode_transfer_function(int aligned,
                         frombuffer, fromdata,
                         caststransfer, castdata,
                         PyDataType_FLAGCHK(str_dtype, NPY_NEEDS_INIT),
+                        *out_needs_api,
                         out_stransfer, out_transferdata) != NPY_SUCCEED) {
         NPY_AUXDATA_FREE(castdata);
         NPY_AUXDATA_FREE(todata);
@@ -1293,6 +1268,7 @@ get_unicode_to_datetime_transfer_function(int aligned,
                         frombuffer, fromdata,
                         caststransfer, castdata,
                         PyDataType_FLAGCHK(dst_dtype, NPY_NEEDS_INIT),
+                        *out_needs_api,
                         out_stransfer, out_transferdata) != NPY_SUCCEED) {
         Py_DECREF(str_dtype);
         NPY_AUXDATA_FREE(castdata);
@@ -1613,6 +1589,7 @@ get_cast_transfer_function(int aligned,
                             frombuffer, fromdata,
                             caststransfer, castdata,
                             PyDataType_FLAGCHK(dst_dtype, NPY_NEEDS_INIT),
+                            *out_needs_api,
                             out_stransfer, out_transferdata) != NPY_SUCCEED) {
             NPY_AUXDATA_FREE(castdata);
             NPY_AUXDATA_FREE(todata);
@@ -3832,8 +3809,8 @@ PyArray_CastRawArrays(npy_intp count,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-PyArray_PrepareOneRawArrayIter(int ndim, npy_intp *shape,
-                            char *data, npy_intp *strides,
+PyArray_PrepareOneRawArrayIter(int ndim, npy_intp const *shape,
+                            char *data, npy_intp const *strides,
                             int *out_ndim, npy_intp *out_shape,
                             char **out_data, npy_intp *out_strides)
 {
@@ -3953,9 +3930,9 @@ PyArray_PrepareOneRawArrayIter(int ndim, npy_intp *shape,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-PyArray_PrepareTwoRawArrayIter(int ndim, npy_intp *shape,
-                            char *dataA, npy_intp *stridesA,
-                            char *dataB, npy_intp *stridesB,
+PyArray_PrepareTwoRawArrayIter(int ndim, npy_intp const *shape,
+                            char *dataA, npy_intp const *stridesA,
+                            char *dataB, npy_intp const *stridesB,
                             int *out_ndim, npy_intp *out_shape,
                             char **out_dataA, npy_intp *out_stridesA,
                             char **out_dataB, npy_intp *out_stridesB)
@@ -4077,10 +4054,10 @@ PyArray_PrepareTwoRawArrayIter(int ndim, npy_intp *shape,
  * Returns 0 on success, -1 on failure.
  */
 NPY_NO_EXPORT int
-PyArray_PrepareThreeRawArrayIter(int ndim, npy_intp *shape,
-                            char *dataA, npy_intp *stridesA,
-                            char *dataB, npy_intp *stridesB,
-                            char *dataC, npy_intp *stridesC,
+PyArray_PrepareThreeRawArrayIter(int ndim, npy_intp const *shape,
+                            char *dataA, npy_intp const *stridesA,
+                            char *dataB, npy_intp const *stridesB,
+                            char *dataC, npy_intp const *stridesC,
                             int *out_ndim, npy_intp *out_shape,
                             char **out_dataA, npy_intp *out_stridesA,
                             char **out_dataB, npy_intp *out_stridesB,
index 58af4409192148d9c49f4eba80c058b5b8dcba6a..1cc557825867ada56a5bca9abdbb07de1b3a73b2 100644 (file)
  */
 static void
 @name@_sum_of_products_@noplabel@(int nop, char **dataptr,
-                                npy_intp *strides, npy_intp count)
+                                npy_intp const *strides, npy_intp count)
 {
 #if (@nop@ == 1) || (@nop@ <= 3 && !@complex@)
     char *data0 = dataptr[0];
@@ -206,7 +206,7 @@ static void
 
 static void
 @name@_sum_of_products_contig_one(int nop, char **dataptr,
-                                npy_intp *NPY_UNUSED(strides), npy_intp count)
+                                npy_intp const *NPY_UNUSED(strides), npy_intp count)
 {
     @type@ *data0 = (@type@ *)dataptr[0];
     @type@ *data_out = (@type@ *)dataptr[1];
@@ -268,7 +268,7 @@ finish_after_unrolled_loop:
 
 static void
 @name@_sum_of_products_contig_two(int nop, char **dataptr,
-                                npy_intp *NPY_UNUSED(strides), npy_intp count)
+                                npy_intp const *NPY_UNUSED(strides), npy_intp count)
 {
     @type@ *data0 = (@type@ *)dataptr[0];
     @type@ *data1 = (@type@ *)dataptr[1];
@@ -354,7 +354,7 @@ finish_after_unrolled_loop:
 /* Some extra specializations for the two operand case */
 static void
 @name@_sum_of_products_stride0_contig_outcontig_two(int nop, char **dataptr,
-                                npy_intp *NPY_UNUSED(strides), npy_intp count)
+                                npy_intp const *NPY_UNUSED(strides), npy_intp count)
 {
     @temptype@ value0 = @from@(*(@type@ *)dataptr[0]);
     @type@ *data1 = (@type@ *)dataptr[1];
@@ -483,7 +483,7 @@ finish_after_unrolled_loop:
 
 static void
 @name@_sum_of_products_contig_stride0_outcontig_two(int nop, char **dataptr,
-                                npy_intp *NPY_UNUSED(strides), npy_intp count)
+                                npy_intp const *NPY_UNUSED(strides), npy_intp count)
 {
     @type@ *data0 = (@type@ *)dataptr[0];
     @temptype@ value1 = @from@(*(@type@ *)dataptr[1]);
@@ -567,7 +567,7 @@ finish_after_unrolled_loop:
 
 static void
 @name@_sum_of_products_contig_contig_outstride0_two(int nop, char **dataptr,
-                                npy_intp *NPY_UNUSED(strides), npy_intp count)
+                                npy_intp const *NPY_UNUSED(strides), npy_intp count)
 {
     @type@ *data0 = (@type@ *)dataptr[0];
     @type@ *data1 = (@type@ *)dataptr[1];
@@ -727,7 +727,7 @@ finish_after_unrolled_loop:
 
 static void
 @name@_sum_of_products_stride0_contig_outstride0_two(int nop, char **dataptr,
-                                npy_intp *NPY_UNUSED(strides), npy_intp count)
+                                npy_intp const *NPY_UNUSED(strides), npy_intp count)
 {
     @temptype@ value0 = @from@(*(@type@ *)dataptr[0]);
     @type@ *data1 = (@type@ *)dataptr[1];
@@ -826,7 +826,7 @@ finish_after_unrolled_loop:
 
 static void
 @name@_sum_of_products_contig_stride0_outstride0_two(int nop, char **dataptr,
-                                npy_intp *NPY_UNUSED(strides), npy_intp count)
+                                npy_intp const *NPY_UNUSED(strides), npy_intp count)
 {
     @type@ *data0 = (@type@ *)dataptr[0];
     @temptype@ value1 = @from@(*(@type@ *)dataptr[1]);
@@ -927,7 +927,7 @@ finish_after_unrolled_loop:
 
 static void
 @name@_sum_of_products_contig_three(int nop, char **dataptr,
-                                npy_intp *NPY_UNUSED(strides), npy_intp count)
+                                npy_intp const *NPY_UNUSED(strides), npy_intp count)
 {
     @type@ *data0 = (@type@ *)dataptr[0];
     @type@ *data1 = (@type@ *)dataptr[1];
@@ -971,7 +971,7 @@ static void
 
 static void
 @name@_sum_of_products_contig_@noplabel@(int nop, char **dataptr,
-                                npy_intp *NPY_UNUSED(strides), npy_intp count)
+                                npy_intp const *NPY_UNUSED(strides), npy_intp count)
 {
     NPY_EINSUM_DBG_PRINT1("@name@_sum_of_products_contig_@noplabel@ (%d)\n",
                                                     (int)count);
@@ -1024,7 +1024,7 @@ static void
 
 static void
 @name@_sum_of_products_contig_outstride0_one(int nop, char **dataptr,
-                                npy_intp *strides, npy_intp count)
+                                npy_intp const *strides, npy_intp count)
 {
 #if @complex@
     @temptype@ accum_re = 0, accum_im = 0;
@@ -1201,7 +1201,7 @@ finish_after_unrolled_loop:
 
 static void
 @name@_sum_of_products_outstride0_@noplabel@(int nop, char **dataptr,
-                                npy_intp *strides, npy_intp count)
+                                npy_intp const *strides, npy_intp count)
 {
 #if @complex@
     @temptype@ accum_re = 0, accum_im = 0;
@@ -1319,7 +1319,7 @@ static void
 
 static void
 bool_sum_of_products_@noplabel@(int nop, char **dataptr,
-                                npy_intp *strides, npy_intp count)
+                                npy_intp const *strides, npy_intp count)
 {
 #if (@nop@ <= 3)
     char *data0 = dataptr[0];
@@ -1376,7 +1376,7 @@ bool_sum_of_products_@noplabel@(int nop, char **dataptr,
 
 static void
 bool_sum_of_products_contig_@noplabel@(int nop, char **dataptr,
-                                npy_intp *strides, npy_intp count)
+                                npy_intp const *strides, npy_intp count)
 {
 #if (@nop@ <= 3)
     char *data0 = dataptr[0];
@@ -1484,7 +1484,7 @@ finish_after_unrolled_loop:
 
 static void
 bool_sum_of_products_outstride0_@noplabel@(int nop, char **dataptr,
-                                npy_intp *strides, npy_intp count)
+                                npy_intp const *strides, npy_intp count)
 {
     npy_bool accum = 0;
 
@@ -1538,7 +1538,7 @@ bool_sum_of_products_outstride0_@noplabel@(int nop, char **dataptr,
 
 /**end repeat**/
 
-typedef void (*sum_of_products_fn)(int, char **, npy_intp *, npy_intp);
+typedef void (*sum_of_products_fn)(int, char **, npy_intp const*, npy_intp);
 
 /* These tables need to match up with the type enum */
 static sum_of_products_fn
@@ -1720,7 +1720,7 @@ static sum_of_products_fn _unspecialized_table[NPY_NTYPES][4] = {
 
 static sum_of_products_fn
 get_sum_of_products_function(int nop, int type_num,
-                             npy_intp itemsize, npy_intp *fixed_strides)
+                             npy_intp itemsize, npy_intp const *fixed_strides)
 {
     int iop;
 
@@ -2152,6 +2152,11 @@ get_combined_dims_view(PyArrayObject *op, int iop, char *labels)
         }
         /* A repeated label, find the original one and merge them. */
         else {
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
+#endif
             int i = icombinemap[idim + label];
 
             icombinemap[idim] = -1;
@@ -2164,6 +2169,9 @@ get_combined_dims_view(PyArrayObject *op, int iop, char *labels)
                 return NULL;
             }
             new_strides[i] += stride;
+#ifdef __GNUC__
+#pragma GCC diagnostic pop
+#endif
         }
     }
 
index a66b9d40d277a6481edfd29b0ec630cee05b0c7d..d5f24e75a8f5ffd3300e097cad8e0a03c7adf790 100644 (file)
@@ -727,47 +727,25 @@ arrayflags_print(PyArrayFlagsObject *self)
     );
 }
 
-static int
-arrayflags_compare(PyArrayFlagsObject *self, PyArrayFlagsObject *other)
-{
-    if (self->flags == other->flags) {
-        return 0;
-    }
-    else if (self->flags < other->flags) {
-        return -1;
-    }
-    else {
-        return 1;
-    }
-}
-
-
 static PyObject*
 arrayflags_richcompare(PyObject *self, PyObject *other, int cmp_op)
 {
-    PyObject *result = Py_NotImplemented;
-    int cmp;
-
-    if (cmp_op != Py_EQ && cmp_op != Py_NE) {
-        PyErr_SetString(PyExc_TypeError,
-                        "undefined comparison for flag object");
-        return NULL;
+    if (!PyObject_TypeCheck(other, &PyArrayFlags_Type)) {
+        Py_RETURN_NOTIMPLEMENTED;
     }
 
-    if (PyObject_TypeCheck(other, &PyArrayFlags_Type)) {
-        cmp = arrayflags_compare((PyArrayFlagsObject *)self,
-                                 (PyArrayFlagsObject *)other);
+    npy_bool eq = ((PyArrayFlagsObject*) self)->flags ==
+                   ((PyArrayFlagsObject*) other)->flags;
 
-        if (cmp_op == Py_EQ) {
-            result = (cmp == 0) ? Py_True : Py_False;
-        }
-        else if (cmp_op == Py_NE) {
-            result = (cmp != 0) ? Py_True : Py_False;
-        }
+    if (cmp_op == Py_EQ) {
+        return PyBool_FromLong(eq);
+    }
+    else if (cmp_op == Py_NE) {
+        return PyBool_FromLong(!eq);
+    }
+    else {
+        Py_RETURN_NOTIMPLEMENTED;
     }
-
-    Py_INCREF(result);
-    return result;
 }
 
 static PyMappingMethods arrayflags_as_mapping = {
@@ -793,61 +771,15 @@ arrayflags_new(PyTypeObject *NPY_UNUSED(self), PyObject *args, PyObject *NPY_UNU
 }
 
 NPY_NO_EXPORT PyTypeObject PyArrayFlags_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.flagsobj",
-    sizeof(PyArrayFlagsObject),
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)arrayflags_dealloc,             /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    (cmpfunc)arrayflags_compare,                /* tp_compare */
-#endif
-    (reprfunc)arrayflags_print,                 /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    &arrayflags_as_mapping,                     /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    (reprfunc)arrayflags_print,                 /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    arrayflags_richcompare,                     /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    arrayflags_getsets,                         /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    arrayflags_new,                             /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.flagsobj",
+    .tp_basicsize = sizeof(PyArrayFlagsObject),
+    .tp_dealloc = (destructor)arrayflags_dealloc,
+    .tp_repr = (reprfunc)arrayflags_print,
+    .tp_as_mapping = &arrayflags_as_mapping,
+    .tp_str = (reprfunc)arrayflags_print,
+    .tp_flags =Py_TPFLAGS_DEFAULT,
+    .tp_richcompare = arrayflags_richcompare,
+    .tp_getset = arrayflags_getsets,
+    .tp_new = arrayflags_new,
 };
index b405ab0992fad67c690315b3486bb0a05248644a..80a1cd4a1783760a067f84b91a6b6fcf32cf648e 100644 (file)
@@ -13,6 +13,7 @@
 #include "npy_import.h"
 
 #include "common.h"
+#include "conversion_utils.h"
 #include "ctors.h"
 #include "scalartypes.h"
 #include "descriptor.h"
@@ -62,8 +63,8 @@ array_shape_set(PyArrayObject *self, PyObject *val)
     if (PyArray_DATA(ret) != PyArray_DATA(self)) {
         Py_DECREF(ret);
         PyErr_SetString(PyExc_AttributeError,
-                        "incompatible shape for a non-contiguous "\
-                        "array");
+                        "Incompatible shape for in-place modification. Use "
+                        "`.reshape()` to make a copy with the desired shape.");
         return -1;
     }
 
@@ -110,26 +111,21 @@ array_strides_get(PyArrayObject *self)
 static int
 array_strides_set(PyArrayObject *self, PyObject *obj)
 {
-    PyArray_Dims newstrides = {NULL, 0};
+    PyArray_Dims newstrides = {NULL, -1};
     PyArrayObject *new;
     npy_intp numbytes = 0;
     npy_intp offset = 0;
     npy_intp lower_offset = 0;
     npy_intp upper_offset = 0;
-#if defined(NPY_PY3K)
     Py_buffer view;
-#else
-    Py_ssize_t buf_len;
-    char *buf;
-#endif
 
     if (obj == NULL) {
         PyErr_SetString(PyExc_AttributeError,
                 "Cannot delete array strides");
         return -1;
     }
-    if (!PyArray_IntpConverter(obj, &newstrides) ||
-        newstrides.ptr == NULL) {
+    if (!PyArray_OptionalIntpConverter(obj, &newstrides) ||
+        newstrides.len == -1) {
         PyErr_SetString(PyExc_TypeError, "invalid strides");
         return -1;
     }
@@ -146,7 +142,6 @@ array_strides_set(PyArrayObject *self, PyObject *obj)
      * Get the available memory through the buffer interface on
      * PyArray_BASE(new) or if that fails from the current new
      */
-#if defined(NPY_PY3K)
     if (PyArray_BASE(new) &&
             PyObject_GetBuffer(PyArray_BASE(new), &view, PyBUF_SIMPLE) >= 0) {
         offset = PyArray_BYTES(self) - (char *)view.buf;
@@ -154,14 +149,6 @@ array_strides_set(PyArrayObject *self, PyObject *obj)
         PyBuffer_Release(&view);
         _dealloc_cached_buffer_info((PyObject*)new);
     }
-#else
-    if (PyArray_BASE(new) &&
-            PyObject_AsReadBuffer(PyArray_BASE(new), (const void **)&buf,
-                                  &buf_len) >= 0) {
-        offset = PyArray_BYTES(self) - buf;
-        numbytes = buf_len + offset;
-    }
-#endif
     else {
         PyErr_Clear();
         offset_bounds_from_strides(PyArray_ITEMSIZE(new), PyArray_NDIM(new),
@@ -292,31 +279,56 @@ array_interface_get(PyArrayObject *self)
         Py_DECREF(dict);
         return NULL;
     }
+    int ret;
 
     /* dataptr */
     obj = array_dataptr_get(self);
-    PyDict_SetItemString(dict, "data", obj);
+    ret = PyDict_SetItemString(dict, "data", obj);
     Py_DECREF(obj);
+    if (ret < 0) {
+        Py_DECREF(dict);
+        return NULL;
+    }
 
     obj = array_protocol_strides_get(self);
-    PyDict_SetItemString(dict, "strides", obj);
+    ret = PyDict_SetItemString(dict, "strides", obj);
     Py_DECREF(obj);
+    if (ret < 0) {
+        Py_DECREF(dict);
+        return NULL;
+    }
 
     obj = array_protocol_descr_get(self);
-    PyDict_SetItemString(dict, "descr", obj);
+    ret = PyDict_SetItemString(dict, "descr", obj);
     Py_DECREF(obj);
+    if (ret < 0) {
+        Py_DECREF(dict);
+        return NULL;
+    }
 
     obj = arraydescr_protocol_typestr_get(PyArray_DESCR(self));
-    PyDict_SetItemString(dict, "typestr", obj);
+    ret = PyDict_SetItemString(dict, "typestr", obj);
     Py_DECREF(obj);
+    if (ret < 0) {
+        Py_DECREF(dict);
+        return NULL;
+    }
 
     obj = array_shape_get(self);
-    PyDict_SetItemString(dict, "shape", obj);
+    ret = PyDict_SetItemString(dict, "shape", obj);
     Py_DECREF(obj);
+    if (ret < 0) {
+        Py_DECREF(dict);
+        return NULL;
+    }
 
     obj = PyInt_FromLong(3);
-    PyDict_SetItemString(dict, "version", obj);
+    ret = PyDict_SetItemString(dict, "version", obj);
     Py_DECREF(obj);
+    if (ret < 0) {
+        Py_DECREF(dict);
+        return NULL;
+    }
 
     return dict;
 }
@@ -324,23 +336,7 @@ array_interface_get(PyArrayObject *self)
 static PyObject *
 array_data_get(PyArrayObject *self)
 {
-#if defined(NPY_PY3K)
     return PyMemoryView_FromObject((PyObject *)self);
-#else
-    npy_intp nbytes;
-    if (!(PyArray_ISONESEGMENT(self))) {
-        PyErr_SetString(PyExc_AttributeError, "cannot get single-"\
-                        "segment buffer for discontiguous array");
-        return NULL;
-    }
-    nbytes = PyArray_NBYTES(self);
-    if (PyArray_ISWRITEABLE(self)) {
-        return PyBuffer_FromReadWriteObject((PyObject *)self, 0, (Py_ssize_t) nbytes);
-    }
-    else {
-        return PyBuffer_FromObject((PyObject *)self, 0, (Py_ssize_t) nbytes);
-    }
-#endif
 }
 
 static int
@@ -349,9 +345,7 @@ array_data_set(PyArrayObject *self, PyObject *op)
     void *buf;
     Py_ssize_t buf_len;
     int writeable=1;
-#if defined(NPY_PY3K)
     Py_buffer view;
-#endif
 
     /* 2016-19-02, 1.12 */
     int ret = DEPRECATE("Assigning the 'data' attribute is an "
@@ -366,7 +360,6 @@ array_data_set(PyArrayObject *self, PyObject *op)
                 "Cannot delete array data");
         return -1;
     }
-#if defined(NPY_PY3K)
     if (PyObject_GetBuffer(op, &view, PyBUF_WRITABLE|PyBUF_SIMPLE) < 0) {
         writeable = 0;
         PyErr_Clear();
@@ -384,18 +377,7 @@ array_data_set(PyArrayObject *self, PyObject *op)
      */
     PyBuffer_Release(&view);
     _dealloc_cached_buffer_info(op);
-#else
-    if (PyObject_AsWriteBuffer(op, &buf, &buf_len) < 0) {
-        PyErr_Clear();
-        writeable = 0;
-        if (PyObject_AsReadBuffer(op, (const void **)&buf, &buf_len) < 0) {
-            PyErr_Clear();
-            PyErr_SetString(PyExc_AttributeError,
-                    "object does not have single-segment buffer interface");
-            return -1;
-        }
-    }
-#endif
+
     if (!PyArray_ISONESEGMENT(self)) {
         PyErr_SetString(PyExc_AttributeError,
                 "cannot set single-segment buffer for discontiguous array");
index a6ac902d306fd658fb0d2ec97e72043b566f70d6..45c019f493e5cdef5c6a3c85a7d0652135f3df28 100644 (file)
 #include "lowlevel_strided_loops.h"
 #include "array_assign.h"
 
-#include "item_selection.h"
 #include "npy_sort.h"
 #include "npy_partition.h"
 #include "npy_binsearch.h"
 #include "alloc.h"
+#include "arraytypes.h"
+
+
+
+static NPY_GCC_OPT_3 NPY_INLINE int
+npy_fasttake_impl(
+        char *dest, char *src, const npy_intp *indices,
+        npy_intp n, npy_intp m, npy_intp max_item,
+        npy_intp nelem, npy_intp chunk,
+        NPY_CLIPMODE clipmode, npy_intp itemsize, int needs_refcounting,
+        PyArray_Descr *dtype, int axis)
+{
+    NPY_BEGIN_THREADS_DEF;
+    NPY_BEGIN_THREADS_DESCR(dtype);
+    switch (clipmode) {
+        case NPY_RAISE:
+            for (npy_intp i = 0; i < n; i++) {
+                for (npy_intp j = 0; j < m; j++) {
+                    npy_intp tmp = indices[j];
+                    if (check_and_adjust_index(&tmp, max_item, axis,
+                                               _save) < 0) {
+                        return -1;
+                    }
+                    char *tmp_src = src + tmp * chunk;
+                    if (needs_refcounting) {
+                        for (npy_intp k = 0; k < nelem; k++) {
+                            PyArray_Item_INCREF(tmp_src, dtype);
+                            PyArray_Item_XDECREF(dest, dtype);
+                            memmove(dest, tmp_src, itemsize);
+                            dest += itemsize;
+                            tmp_src += itemsize;
+                        }
+                    }
+                    else {
+                        memmove(dest, tmp_src, chunk);
+                        dest += chunk;
+                    }
+                }
+                src += chunk*max_item;
+            }
+            break;
+        case NPY_WRAP:
+            for (npy_intp i = 0; i < n; i++) {
+                for (npy_intp j = 0; j < m; j++) {
+                    npy_intp tmp = indices[j];
+                    if (tmp < 0) {
+                        while (tmp < 0) {
+                            tmp += max_item;
+                        }
+                    }
+                    else if (tmp >= max_item) {
+                        while (tmp >= max_item) {
+                            tmp -= max_item;
+                        }
+                    }
+                    char *tmp_src = src + tmp * chunk;
+                    if (needs_refcounting) {
+                        for (npy_intp k = 0; k < nelem; k++) {
+                            PyArray_Item_INCREF(tmp_src, dtype);
+                            PyArray_Item_XDECREF(dest, dtype);
+                            memmove(dest, tmp_src, itemsize);
+                            dest += itemsize;
+                            tmp_src += itemsize;
+                        }
+                    }
+                    else {
+                        memmove(dest, tmp_src, chunk);
+                        dest += chunk;
+                    }
+                }
+                src += chunk*max_item;
+            }
+            break;
+        case NPY_CLIP:
+            for (npy_intp i = 0; i < n; i++) {
+                for (npy_intp j = 0; j < m; j++) {
+                    npy_intp tmp = indices[j];
+                    if (tmp < 0) {
+                        tmp = 0;
+                    }
+                    else if (tmp >= max_item) {
+                        tmp = max_item - 1;
+                    }
+                    char *tmp_src = src + tmp * chunk;
+                    if (needs_refcounting) {
+                        for (npy_intp k = 0; k < nelem; k++) {
+                            PyArray_Item_INCREF(tmp_src, dtype);
+                            PyArray_Item_XDECREF(dest, dtype);
+                            memmove(dest, tmp_src, itemsize);
+                            dest += itemsize;
+                            tmp_src += itemsize;
+                        }
+                    }
+                    else {
+                        memmove(dest, tmp_src, chunk);
+                        dest += chunk;
+                    }
+                }
+                src += chunk*max_item;
+            }
+            break;
+    }
+
+    NPY_END_THREADS;
+    return 0;
+}
+
+
+/*
+ * Helper function instantiating npy_fasttake_impl in different branches
+ * to allow the compiler to optimize each to the specific itemsize.
+ */
+static NPY_GCC_OPT_3 int
+npy_fasttake(
+        char *dest, char *src, const npy_intp *indices,
+        npy_intp n, npy_intp m, npy_intp max_item,
+        npy_intp nelem, npy_intp chunk,
+        NPY_CLIPMODE clipmode, npy_intp itemsize, int needs_refcounting,
+        PyArray_Descr *dtype, int axis)
+{
+    if (!needs_refcounting) {
+        if (chunk == 1) {
+            return npy_fasttake_impl(
+                    dest, src, indices, n, m, max_item, nelem, chunk,
+                    clipmode, itemsize, needs_refcounting, dtype, axis);
+        }
+        if (chunk == 2) {
+            return npy_fasttake_impl(
+                    dest, src, indices, n, m, max_item, nelem, chunk,
+                    clipmode, itemsize, needs_refcounting, dtype, axis);
+        }
+        if (chunk == 4) {
+            return npy_fasttake_impl(
+                    dest, src, indices, n, m, max_item, nelem, chunk,
+                    clipmode, itemsize, needs_refcounting, dtype, axis);
+        }
+        if (chunk == 8) {
+            return npy_fasttake_impl(
+                    dest, src, indices, n, m, max_item, nelem, chunk,
+                    clipmode, itemsize, needs_refcounting, dtype, axis);
+        }
+        if (chunk == 16) {
+            return npy_fasttake_impl(
+                    dest, src, indices, n, m, max_item, nelem, chunk,
+                    clipmode, itemsize, needs_refcounting, dtype, axis);
+        }
+        if (chunk == 32) {
+            return npy_fasttake_impl(
+                    dest, src, indices, n, m, max_item, nelem, chunk,
+                    clipmode, itemsize, needs_refcounting, dtype, axis);
+        }
+    }
+
+    return npy_fasttake_impl(
+            dest, src, indices, n, m, max_item, nelem, chunk,
+            clipmode, itemsize, needs_refcounting, dtype, axis);
+}
+
 
 /*NUMPY_API
  * Take
@@ -35,12 +192,10 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
                  PyArrayObject *out, NPY_CLIPMODE clipmode)
 {
     PyArray_Descr *dtype;
-    PyArray_FastTakeFunc *func;
     PyArrayObject *obj = NULL, *self, *indices;
-    npy_intp nd, i, j, n, m, k, max_item, tmp, chunk, itemsize, nelem;
+    npy_intp nd, i, n, m, max_item, chunk, itemsize, nelem;
     npy_intp shape[NPY_MAXDIMS];
-    char *src, *dest, *tmp_src;
-    int err;
+
     npy_bool needs_refcounting;
 
     indices = NULL;
@@ -122,9 +277,10 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
     nelem = chunk;
     itemsize = PyArray_ITEMSIZE(obj);
     chunk = chunk * itemsize;
-    src = PyArray_DATA(self);
-    dest = PyArray_DATA(obj);
+    char *src = PyArray_DATA(self);
+    char *dest = PyArray_DATA(obj);
     needs_refcounting = PyDataType_REFCHK(PyArray_DESCR(self));
+    npy_intp *indices_data = (npy_intp *)PyArray_DATA(indices);
 
     if ((max_item == 0) && (PyArray_SIZE(obj) != 0)) {
         /* Index error, since that is the usual error for raise mode */
@@ -133,107 +289,10 @@ PyArray_TakeFrom(PyArrayObject *self0, PyObject *indices0, int axis,
         goto fail;
     }
 
-    func = PyArray_DESCR(self)->f->fasttake;
-    if (func == NULL) {
-        NPY_BEGIN_THREADS_DEF;
-        NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(self));
-        switch(clipmode) {
-        case NPY_RAISE:
-            for (i = 0; i < n; i++) {
-                for (j = 0; j < m; j++) {
-                    tmp = ((npy_intp *)(PyArray_DATA(indices)))[j];
-                    if (check_and_adjust_index(&tmp, max_item, axis,
-                                               _save) < 0) {
-                        goto fail;
-                    }
-                    tmp_src = src + tmp * chunk;
-                    if (needs_refcounting) {
-                        for (k=0; k < nelem; k++) {
-                            PyArray_Item_INCREF(tmp_src, PyArray_DESCR(self));
-                            PyArray_Item_XDECREF(dest, PyArray_DESCR(self));
-                            memmove(dest, tmp_src, itemsize);
-                            dest += itemsize;
-                            tmp_src += itemsize;
-                        }
-                    }
-                    else {
-                        memmove(dest, tmp_src, chunk);
-                        dest += chunk;
-                    }
-                }
-                src += chunk*max_item;
-            }
-            break;
-        case NPY_WRAP:
-            for (i = 0; i < n; i++) {
-                for (j = 0; j < m; j++) {
-                    tmp = ((npy_intp *)(PyArray_DATA(indices)))[j];
-                    if (tmp < 0) {
-                        while (tmp < 0) {
-                            tmp += max_item;
-                        }
-                    }
-                    else if (tmp >= max_item) {
-                        while (tmp >= max_item) {
-                            tmp -= max_item;
-                        }
-                    }
-                    tmp_src = src + tmp * chunk;
-                    if (needs_refcounting) {
-                        for (k=0; k < nelem; k++) {
-                            PyArray_Item_INCREF(tmp_src, PyArray_DESCR(self));
-                            PyArray_Item_XDECREF(dest, PyArray_DESCR(self));
-                            memmove(dest, tmp_src, itemsize);
-                            dest += itemsize;
-                            tmp_src += itemsize;
-                        }
-                    }
-                    else {
-                        memmove(dest, tmp_src, chunk);
-                        dest += chunk;
-                    }
-                }
-                src += chunk*max_item;
-            }
-            break;
-        case NPY_CLIP:
-            for (i = 0; i < n; i++) {
-                for (j = 0; j < m; j++) {
-                    tmp = ((npy_intp *)(PyArray_DATA(indices)))[j];
-                    if (tmp < 0) {
-                        tmp = 0;
-                    }
-                    else if (tmp >= max_item) {
-                        tmp = max_item - 1;
-                    }
-                    tmp_src = src + tmp * chunk;
-                    if (needs_refcounting) {
-                        for (k=0; k < nelem; k++) {
-                            PyArray_Item_INCREF(tmp_src, PyArray_DESCR(self));
-                            PyArray_Item_XDECREF(dest, PyArray_DESCR(self));
-                            memmove(dest, tmp_src, itemsize);
-                            dest += itemsize;
-                            tmp_src += itemsize;
-                        }
-                    }
-                    else {
-                        memmove(dest, tmp_src, chunk);
-                        dest += chunk;
-                    }
-                }
-                src += chunk*max_item;
-            }
-            break;
-        }
-        NPY_END_THREADS;
-    }
-    else {
-        /* no gil release, need it for error reporting */
-        err = func(dest, src, (npy_intp *)(PyArray_DATA(indices)),
-                    max_item, n, m, nelem, clipmode);
-        if (err) {
-            goto fail;
-        }
+    if (npy_fasttake(
+            dest, src, indices_data, n, m, max_item, nelem, chunk,
+            clipmode, itemsize, needs_refcounting, dtype, axis) < 0) {
+        goto fail;
     }
 
     Py_XDECREF(indices);
@@ -431,16 +490,78 @@ PyArray_PutTo(PyArrayObject *self, PyObject* values0, PyObject *indices0,
     return NULL;
 }
 
+
+static NPY_GCC_OPT_3 NPY_INLINE void
+npy_fastputmask_impl(
+        char *dest, char *src, const npy_bool *mask_data,
+        npy_intp ni, npy_intp nv, npy_intp chunk)
+{
+    if (nv == 1) {
+        for (npy_intp i = 0; i < ni; i++) {
+            if (mask_data[i]) {
+                memmove(dest, src, chunk);
+            }
+            dest += chunk;
+        }
+    }
+    else {
+        char *tmp_src = src;
+        for (npy_intp i = 0, j = 0; i < ni; i++, j++) {
+            if (NPY_UNLIKELY(j >= nv)) {
+                j = 0;
+                tmp_src = src;
+            }
+            if (mask_data[i]) {
+                memmove(dest, tmp_src, chunk);
+            }
+            dest += chunk;
+            tmp_src += chunk;
+        }
+    }
+}
+
+
+/*
+ * Helper function instantiating npy_fastput_impl in different branches
+ * to allow the compiler to optimize each to the specific itemsize.
+ */
+static NPY_GCC_OPT_3 void
+npy_fastputmask(
+        char *dest, char *src, npy_bool *mask_data,
+        npy_intp ni, npy_intp nv, npy_intp chunk)
+{
+    if (chunk == 1) {
+        return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+    }
+    if (chunk == 2) {
+        return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+    }
+    if (chunk == 4) {
+        return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+    }
+    if (chunk == 8) {
+        return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+    }
+    if (chunk == 16) {
+        return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+    }
+    if (chunk == 32) {
+        return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+    }
+
+    return npy_fastputmask_impl(dest, src, mask_data, ni, nv, chunk);
+}
+
+
 /*NUMPY_API
  * Put values into an array according to a mask.
  */
 NPY_NO_EXPORT PyObject *
 PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
 {
-    PyArray_FastPutmaskFunc *func;
     PyArrayObject *mask, *values;
     PyArray_Descr *dtype;
-    npy_intp i, j, chunk, ni, nv;
+    npy_intp chunk, ni, nv;
     char *src, *dest;
     npy_bool *mask_data;
     int copied = 0;
@@ -505,7 +626,7 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
     dest = PyArray_DATA(self);
 
     if (PyDataType_REFCHK(PyArray_DESCR(self))) {
-        for (i = 0, j = 0; i < ni; i++, j++) {
+        for (npy_intp i = 0, j = 0; i < ni; i++, j++) {
             if (j >= nv) {
                 j = 0;
             }
@@ -522,20 +643,7 @@ PyArray_PutMask(PyArrayObject *self, PyObject* values0, PyObject* mask0)
     else {
         NPY_BEGIN_THREADS_DEF;
         NPY_BEGIN_THREADS_DESCR(PyArray_DESCR(self));
-        func = PyArray_DESCR(self)->f->fastputmask;
-        if (func == NULL) {
-            for (i = 0, j = 0; i < ni; i++, j++) {
-                if (j >= nv) {
-                    j = 0;
-                }
-                if (mask_data[i]) {
-                    memmove(dest + i*chunk, src + j*chunk, chunk);
-                }
-            }
-        }
-        else {
-            func(dest, mask_data, ni, src, nv);
-        }
+        npy_fastputmask(dest, src, mask_data, ni, nv, chunk);
         NPY_END_THREADS;
     }
 
@@ -825,7 +933,7 @@ PyArray_Choose(PyArrayObject *ip, PyObject *op, PyArrayObject *out,
  */
 static int
 _new_sortlike(PyArrayObject *op, int axis, PyArray_SortFunc *sort,
-              PyArray_PartitionFunc *part, npy_intp *kth, npy_intp nkth)
+              PyArray_PartitionFunc *part, npy_intp const *kth, npy_intp nkth)
 {
     npy_intp N = PyArray_DIM(op, axis);
     npy_intp elsize = (npy_intp)PyArray_ITEMSIZE(op);
@@ -953,7 +1061,7 @@ fail:
 static PyObject*
 _new_argsortlike(PyArrayObject *op, int axis, PyArray_ArgSortFunc *argsort,
                  PyArray_ArgPartitionFunc *argpart,
-                 npy_intp *kth, npy_intp nkth)
+                 npy_intp const *kth, npy_intp nkth)
 {
     npy_intp N = PyArray_DIM(op, axis);
     npy_intp elsize = (npy_intp)PyArray_ITEMSIZE(op);
@@ -1059,12 +1167,10 @@ _new_argsortlike(PyArrayObject *op, int axis, PyArray_ArgSortFunc *argsort,
 
         if (argpart == NULL) {
             ret = argsort(valptr, idxptr, N, op);
-#if defined(NPY_PY3K)
             /* Object comparisons may raise an exception in Python 3 */
             if (hasrefs && PyErr_Occurred()) {
                 ret = -1;
             }
-#endif
             if (ret < 0) {
                 goto fail;
             }
@@ -1075,12 +1181,10 @@ _new_argsortlike(PyArrayObject *op, int axis, PyArray_ArgSortFunc *argsort,
 
             for (i = 0; i < nkth; ++i) {
                 ret = argpart(valptr, idxptr, N, kth[i], pivots, &npiv, op);
-#if defined(NPY_PY3K)
                 /* Object comparisons may raise an exception in Python 3 */
                 if (hasrefs && PyErr_Occurred()) {
                     ret = -1;
                 }
-#endif
                 if (ret < 0) {
                     goto fail;
                 }
@@ -1460,6 +1564,16 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
 
     /* Now we can check the axis */
     nd = PyArray_NDIM(mps[0]);
+    /*
+    * Special case letting axis={-1,0} slip through for scalars,
+    * for backwards compatibility reasons.
+    */
+    if (nd == 0 && (axis == 0 || axis == -1)) {
+        /* TODO: can we deprecate this? */
+    }
+    else if (check_and_adjust_axis(&axis, nd) < 0) {
+        goto fail;
+    }
     if ((nd == 0) || (PyArray_SIZE(mps[0]) <= 1)) {
         /* empty/single element case */
         ret = (PyArrayObject *)PyArray_NewFromDescr(
@@ -1475,9 +1589,6 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
         }
         goto finish;
     }
-    if (check_and_adjust_axis(&axis, nd) < 0) {
-        goto fail;
-    }
 
     for (i = 0; i < n; i++) {
         its[i] = (PyArrayIterObject *)PyArray_IterAllButAxis(
@@ -1566,12 +1677,8 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
                     _strided_byte_swap(valbuffer, (npy_intp) elsize, N, elsize);
                 }
                 rcode = argsort(valbuffer, (npy_intp *)indbuffer, N, mps[j]);
-#if defined(NPY_PY3K)
                 if (rcode < 0 || (PyDataType_REFCHK(PyArray_DESCR(mps[j]))
                             && PyErr_Occurred())) {
-#else
-                if (rcode < 0) {
-#endif
                     PyDataMem_FREE(valbuffer);
                     PyDataMem_FREE(indbuffer);
                     free(swaps);
@@ -1601,12 +1708,8 @@ PyArray_LexSort(PyObject *sort_keys, int axis)
                 }
                 rcode = argsort(its[j]->dataptr,
                         (npy_intp *)rit->dataptr, N, mps[j]);
-#if defined(NPY_PY3K)
                 if (rcode < 0 || (PyDataType_REFCHK(PyArray_DESCR(mps[j]))
                             && PyErr_Occurred())) {
-#else
-                if (rcode < 0) {
-#endif
                     goto fail;
                 }
                 PyArray_ITER_NEXT(its[j]);
@@ -2028,7 +2131,7 @@ count_nonzero_bytes_384(const npy_uint64 * w)
  * Returns -1 on error.
  */
 NPY_NO_EXPORT npy_intp
-count_boolean_trues(int ndim, char *data, npy_intp *ashape, npy_intp *astrides)
+count_boolean_trues(int ndim, char *data, npy_intp const *ashape, npy_intp const *astrides)
 {
     int idim;
     npy_intp shape[NPY_MAXDIMS], strides[NPY_MAXDIMS];
@@ -2392,7 +2495,7 @@ PyArray_Nonzero(PyArrayObject *self)
             Py_DECREF(ret);
             return NULL;
         }
-        
+
         needs_api = NpyIter_IterationNeedsAPI(iter);
 
         NPY_BEGIN_THREADS_NDITER(iter);
@@ -2436,7 +2539,7 @@ finish:
         Py_DECREF(ret);
         return NULL;
     }
-    
+
     /* if executed `nonzero()` check for miscount due to side-effect */
     if (!is_bool && added_count != nonzero_count) {
         PyErr_SetString(PyExc_RuntimeError,
index 2276b4db7bcb39a2381e102af28210818554257b..c1c8b5567b624efdbd24dc79579226bf45f58541 100644 (file)
@@ -8,7 +8,7 @@
  * Returns -1 on error.
  */
 NPY_NO_EXPORT npy_intp
-count_boolean_trues(int ndim, char *data, npy_intp *ashape, npy_intp *astrides);
+count_boolean_trues(int ndim, char *data, npy_intp const *ashape, npy_intp const *astrides);
 
 /*
  * Gets a single item from the array, based on a single multi-index
index e66bb36aa9a3edc370b6a8d6fa1f788f55ac22b5..c71b7b770c07494bf045dc6be8a5c2baa5b9c1f5 100644 (file)
@@ -172,7 +172,7 @@ NPY_NO_EXPORT PyObject *
 PyArray_IterNew(PyObject *obj)
 {
     /*
-     * Note that internall PyArray_RawIterBaseInit may be called directly on a
+     * Note that internally PyArray_RawIterBaseInit may be called directly on a
      * statically allocated PyArrayIterObject.
      */
     PyArrayIterObject *it;
@@ -1102,63 +1102,17 @@ static PyGetSetDef iter_getsets[] = {
 };
 
 NPY_NO_EXPORT PyTypeObject PyArrayIter_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.flatiter",                           /* tp_name */
-    sizeof(PyArrayIterObject),                  /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)arrayiter_dealloc,              /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    &iter_as_mapping,                           /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    (richcmpfunc)iter_richcompare,              /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    (iternextfunc)arrayiter_next,               /* tp_iternext */
-    iter_methods,                               /* tp_methods */
-    iter_members,                               /* tp_members */
-    iter_getsets,                               /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.flatiter",
+    .tp_basicsize = sizeof(PyArrayIterObject),
+    .tp_dealloc = (destructor)arrayiter_dealloc,
+    .tp_as_mapping = &iter_as_mapping,
+    .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_richcompare = (richcmpfunc)iter_richcompare,
+    .tp_iternext = (iternextfunc)arrayiter_next,
+    .tp_methods = iter_methods,
+    .tp_members = iter_members,
+    .tp_getset = iter_getsets,
 };
 
 /** END of Array Iterator **/
@@ -1560,63 +1514,16 @@ static PyMethodDef arraymultiter_methods[] = {
 };
 
 NPY_NO_EXPORT PyTypeObject PyArrayMultiIter_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.broadcast",                          /* tp_name */
-    sizeof(PyArrayMultiIterObject),             /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)arraymultiter_dealloc,          /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    (iternextfunc)arraymultiter_next,           /* tp_iternext */
-    arraymultiter_methods,                      /* tp_methods */
-    arraymultiter_members,                      /* tp_members */
-    arraymultiter_getsetlist,                   /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    (initproc)0,                                /* tp_init */
-    0,                                          /* tp_alloc */
-    arraymultiter_new,                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.broadcast",
+    .tp_basicsize = sizeof(PyArrayMultiIterObject),
+    .tp_dealloc = (destructor)arraymultiter_dealloc,
+    .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_iternext = (iternextfunc)arraymultiter_next,
+    .tp_methods = arraymultiter_methods,
+    .tp_members = arraymultiter_members,
+    .tp_getset = arraymultiter_getsetlist,
+    .tp_new = arraymultiter_new,
 };
 
 /*========================= Neighborhood iterator ======================*/
@@ -1890,60 +1797,9 @@ static void neighiter_dealloc(PyArrayNeighborhoodIterObject* iter)
 }
 
 NPY_NO_EXPORT PyTypeObject PyArrayNeighborhoodIter_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.neigh_internal_iter",                /* tp_name*/
-    sizeof(PyArrayNeighborhoodIterObject),      /* tp_basicsize*/
-    0,                                          /* tp_itemsize*/
-    (destructor)neighiter_dealloc,              /* tp_dealloc*/
-    0,                                          /* tp_print*/
-    0,                                          /* tp_getattr*/
-    0,                                          /* tp_setattr*/
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr*/
-    0,                                          /* tp_as_number*/
-    0,                                          /* tp_as_sequence*/
-    0,                                          /* tp_as_mapping*/
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call*/
-    0,                                          /* tp_str*/
-    0,                                          /* tp_getattro*/
-    0,                                          /* tp_setattro*/
-    0,                                          /* tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags*/
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    (iternextfunc)0,                            /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    (initproc)0,                                /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.neigh_internal_iter",
+    .tp_basicsize = sizeof(PyArrayNeighborhoodIterObject),
+    .tp_dealloc = (destructor)neighiter_dealloc,
+    .tp_flags = Py_TPFLAGS_DEFAULT,
 };
index 63b2a88424fa3569886923f9951d24777d07e889..d234c366c7cf00fd9c49a5874fd5b106b3c23f30 100644 (file)
@@ -974,9 +974,9 @@ PyArray_GetStridedNumericCastFn(int aligned, npy_intp src_stride,
 NPY_NO_EXPORT npy_intp
 PyArray_TransferNDimToStrided(npy_intp ndim,
                 char *dst, npy_intp dst_stride,
-                char *src, npy_intp *src_strides, npy_intp src_strides_inc,
-                npy_intp *coords, npy_intp coords_inc,
-                npy_intp *shape, npy_intp shape_inc,
+                char *src, npy_intp const *src_strides, npy_intp src_strides_inc,
+                npy_intp const *coords, npy_intp coords_inc,
+                npy_intp const *shape, npy_intp shape_inc,
                 npy_intp count, npy_intp src_itemsize,
                 PyArray_StridedUnaryOp *stransfer,
                 NpyAuxData *data)
@@ -1092,10 +1092,10 @@ PyArray_TransferNDimToStrided(npy_intp ndim,
 /* See documentation of arguments in lowlevel_strided_loops.h */
 NPY_NO_EXPORT npy_intp
 PyArray_TransferStridedToNDim(npy_intp ndim,
-                char *dst, npy_intp *dst_strides, npy_intp dst_strides_inc,
+                char *dst, npy_intp const *dst_strides, npy_intp dst_strides_inc,
                 char *src, npy_intp src_stride,
-                npy_intp *coords, npy_intp coords_inc,
-                npy_intp *shape, npy_intp shape_inc,
+                npy_intp const *coords, npy_intp coords_inc,
+                npy_intp const *shape, npy_intp shape_inc,
                 npy_intp count, npy_intp src_itemsize,
                 PyArray_StridedUnaryOp *stransfer,
                 NpyAuxData *data)
@@ -1211,11 +1211,11 @@ PyArray_TransferStridedToNDim(npy_intp ndim,
 /* See documentation of arguments in lowlevel_strided_loops.h */
 NPY_NO_EXPORT npy_intp
 PyArray_TransferMaskedStridedToNDim(npy_intp ndim,
-                char *dst, npy_intp *dst_strides, npy_intp dst_strides_inc,
+                char *dst, npy_intp const *dst_strides, npy_intp dst_strides_inc,
                 char *src, npy_intp src_stride,
                 npy_uint8 *mask, npy_intp mask_stride,
-                npy_intp *coords, npy_intp coords_inc,
-                npy_intp *shape, npy_intp shape_inc,
+                npy_intp const *coords, npy_intp coords_inc,
+                npy_intp const *shape, npy_intp shape_inc,
                 npy_intp count, npy_intp src_itemsize,
                 PyArray_MaskedStridedUnaryOp *stransfer,
                 NpyAuxData *data)
index 8dcd28c84dc86247db719a5dcb4f3e38d200f349..43dbde2f18609b4d7bfa78d9994022e413c09eb5 100644 (file)
@@ -227,11 +227,7 @@ unpack_indices(PyObject *index, PyObject **result, npy_intp result_n)
 
     /* Obvious single-entry cases */
     if (0  /* to aid macros below */
-#if !defined(NPY_PY3K)
-            || PyInt_CheckExact(index)
-#else
             || PyLong_CheckExact(index)
-#endif
             || index == Py_None
             || PySlice_Check(index)
             || PyArray_Check(index)
@@ -481,11 +477,7 @@ prepare_index(PyArrayObject *self, PyObject *index,
              *
              * Check for integers first, purely for performance
              */
-#if !defined(NPY_PY3K)
-            if (PyInt_CheckExact(obj) || !PyArray_Check(obj)) {
-#else
             if (PyLong_CheckExact(obj) || !PyArray_Check(obj)) {
-#endif
                 npy_intp ind = PyArray_PyIntAsIntp(obj);
 
                 if (error_converting(ind)) {
@@ -735,8 +727,11 @@ prepare_index(PyArrayObject *self, PyObject *index,
         }
     }
     else if (used_ndim > PyArray_NDIM(self)) {
-        PyErr_SetString(PyExc_IndexError,
-                        "too many indices for array");
+        PyErr_Format(PyExc_IndexError,
+                     "too many indices for array: "
+                     "array is %d-dimensional, but %d were indexed",
+                     PyArray_NDIM(self),
+                     used_ndim);
         goto failed_building_indices;
     }
     else if (index_ndim == 0) {
@@ -1412,8 +1407,11 @@ _get_field_view(PyArrayObject *arr, PyObject *ind, PyArrayObject **view)
         npy_intp offset;
 
         /* get the field offset and dtype */
-        tup = PyDict_GetItem(PyArray_DESCR(arr)->fields, ind);
-        if (tup == NULL){
+        tup = PyDict_GetItemWithError(PyArray_DESCR(arr)->fields, ind);
+        if (tup == NULL && PyErr_Occurred()) {
+            return 0;
+        }
+        else if (tup == NULL){
             PyObject *errmsg = PyUString_FromString("no field of name ");
             PyUString_Concat(&errmsg, ind);
             PyErr_SetObject(PyExc_ValueError, errmsg);
@@ -2691,7 +2689,7 @@ PyArray_MapIterNew(npy_index_info *indices , int index_num, int index_type,
     if (mit->numiter == 0) {
         /*
          * For MapIterArray, it is possible that there is no fancy index.
-         * to support this case, add a dummy iterator.
+         * to support this case, add a dummy iterator.
          * Since it is 0-d its transpose, etc. does not matter.
          */
 
@@ -3340,61 +3338,9 @@ arraymapiter_dealloc(PyArrayMapIterObject *mit)
  * to a[indexobj].flat but the latter gets to use slice syntax.
  */
 NPY_NO_EXPORT PyTypeObject PyArrayMapIter_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.mapiter",                            /* tp_name */
-    sizeof(PyArrayMapIterObject),               /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)arraymapiter_dealloc,           /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.mapiter",
+    .tp_basicsize = sizeof(PyArrayMapIterObject),
+    .tp_dealloc = (destructor)arraymapiter_dealloc,
+    .tp_flags = Py_TPFLAGS_DEFAULT,
 };
index bf0316242f95c2e2d976325a2b1ddd18b45470c8..e2026ec1c3ab1afaca0b84020d39d347a87b6612 100644 (file)
@@ -64,7 +64,11 @@ get_forwarding_ndarray_method(const char *name)
     if (module_methods == NULL) {
         return NULL;
     }
-    callable = PyDict_GetItemString(PyModule_GetDict(module_methods), name);
+    callable = _PyDict_GetItemStringWithError(PyModule_GetDict(module_methods), name);
+    if (callable == NULL && PyErr_Occurred()) {
+        Py_DECREF(module_methods);
+        return NULL;
+    }
     if (callable == NULL) {
         Py_DECREF(module_methods);
         PyErr_Format(PyExc_RuntimeError,
@@ -562,6 +566,23 @@ array_tobytes(PyArrayObject *self, PyObject *args, PyObject *kwds)
     return PyArray_ToString(self, order);
 }
 
+static PyObject *
+array_tostring(PyArrayObject *self, PyObject *args, PyObject *kwds)
+{
+    NPY_ORDER order = NPY_CORDER;
+    static char *kwlist[] = {"order", NULL};
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O&:tostring", kwlist,
+                                     PyArray_OrderConverter, &order)) {
+        return NULL;
+    }
+    /* 2020-03-30, NumPy 1.19 */
+    if (DEPRECATE("tostring() is deprecated. Use tobytes() instead.") < 0) {
+        return NULL;
+    }
+    return PyArray_ToString(self, order);
+}
+
 
 /* This should grow an order= keyword to be consistent
  */
@@ -768,24 +789,6 @@ array_setscalar(PyArrayObject *self, PyObject *args)
     }
 }
 
-NPY_NO_EXPORT const char *
-npy_casting_to_string(NPY_CASTING casting)
-{
-    switch (casting) {
-        case NPY_NO_CASTING:
-            return "'no'";
-        case NPY_EQUIV_CASTING:
-            return "'equiv'";
-        case NPY_SAFE_CASTING:
-            return "'safe'";
-        case NPY_SAME_KIND_CASTING:
-            return "'same_kind'";
-        case NPY_UNSAFE_CASTING:
-            return "'unsafe'";
-        default:
-            return "<unknown>";
-    }
-}
 
 static PyObject *
 array_astype(PyArrayObject *self, PyObject *args, PyObject *kwds)
@@ -855,19 +858,8 @@ array_astype(PyArrayObject *self, PyObject *args, PyObject *kwds)
         return (PyObject *)ret;
     }
     else {
-        PyObject *errmsg;
-        errmsg = PyUString_FromString("Cannot cast array from ");
-        PyUString_ConcatAndDel(&errmsg,
-                PyObject_Repr((PyObject *)PyArray_DESCR(self)));
-        PyUString_ConcatAndDel(&errmsg,
-                PyUString_FromString(" to "));
-        PyUString_ConcatAndDel(&errmsg,
-                PyObject_Repr((PyObject *)dtype));
-        PyUString_ConcatAndDel(&errmsg,
-                PyUString_FromFormat(" according to the rule %s",
-                        npy_casting_to_string(casting)));
-        PyErr_SetObject(PyExc_TypeError, errmsg);
-        Py_DECREF(errmsg);
+        npy_set_invalid_cast_error(
+                PyArray_DESCR(self), dtype, casting, PyArray_NDIM(self) == 0);
         Py_DECREF(dtype);
         return NULL;
     }
@@ -1469,7 +1461,7 @@ array_argpartition(PyArrayObject *self, PyObject *args, PyObject *kwds)
 static PyObject *
 array_searchsorted(PyArrayObject *self, PyObject *args, PyObject *kwds)
 {
-    static char *kwlist[] = {"keys", "side", "sorter", NULL};
+    static char *kwlist[] = {"v", "side", "sorter", NULL};
     PyObject *keys;
     PyObject *sorter;
     NPY_SEARCHSIDE side = NPY_SEARCHLEFT;
@@ -1499,7 +1491,7 @@ _deepcopy_call(char *iptr, char *optr, PyArray_Descr *dtype,
         int offset;
         Py_ssize_t pos = 0;
         while (PyDict_Next(dtype->fields, &pos, &key, &value)) {
-            if NPY_TITLE_KEY(key, value) {
+            if (NPY_TITLE_KEY(key, value)) {
                 continue;
             }
             if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset,
@@ -1768,18 +1760,18 @@ array_reduce_ex_picklebuffer(PyArrayObject *self, int protocol)
 #if PY_VERSION_HEX >= 0x03080000
     /* we expect protocol 5 to be available in Python 3.8 */
     pickle_module = PyImport_ImportModule("pickle");
-#elif PY_VERSION_HEX >= 0x03050000
+#elif PY_VERSION_HEX >= 0x03060000
     pickle_module = PyImport_ImportModule("pickle5");
     if (pickle_module == NULL) {
         /* for protocol 5, raise a clear ImportError if pickle5 is not found
          */
         PyErr_SetString(PyExc_ImportError, "Using pickle protocol 5 "
-                "requires the pickle5 module for Python >=3.5 and <3.8");
+                "requires the pickle5 module for Python >=3.6 and <3.8");
         return NULL;
     }
 #else
     PyErr_SetString(PyExc_ValueError, "pickle protocol 5 is not available "
-                                      "for Python < 3.5");
+                                      "for Python < 3.6");
     return NULL;
 #endif
     if (pickle_module == NULL){
@@ -1868,13 +1860,8 @@ array_reduce_ex(PyArrayObject *self, PyObject *args)
          * method that involves using a temporary bytes allocation. */
         return array_reduce_ex_regular(self, protocol);
     }
-    else if (protocol == 5) {
-        return array_reduce_ex_picklebuffer(self, protocol);
-    }
     else {
-        PyErr_Format(PyExc_ValueError,
-                     "__reduce_ex__ called with protocol > 5");
-        return NULL;
+        return array_reduce_ex_picklebuffer(self, protocol);
     }
 }
 
@@ -1954,7 +1941,6 @@ array_setstate(PyArrayObject *self, PyObject *args)
     else {
         Py_INCREF(rawdata);
 
-#if defined(NPY_PY3K)
         /* Backward compatibility with Python 2 NumPy pickles */
         if (PyUnicode_Check(rawdata)) {
             PyObject *tmp;
@@ -1969,7 +1955,6 @@ array_setstate(PyArrayObject *self, PyObject *args)
                 return NULL;
             }
         }
-#endif
 
         if (!PyBytes_Check(rawdata)) {
             PyErr_SetString(PyExc_TypeError,
@@ -2030,14 +2015,9 @@ array_setstate(PyArrayObject *self, PyObject *args)
     if (!PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
         int swap = PyArray_ISBYTESWAPPED(self);
         fa->data = datastr;
-#ifndef NPY_PY3K
-        /* Check that the string is not interned */
-        if (!IsAligned(self) || swap || PyString_CHECK_INTERNED(rawdata)) {
-#else
         /* Bytes should always be considered immutable, but we just grab the
          * pointer if they are large, to save memory. */
         if (!IsAligned(self) || swap || (len <= 1000)) {
-#endif
             npy_intp num = PyArray_NBYTES(self);
             if (num == 0) {
                 Py_DECREF(rawdata);
@@ -2641,51 +2621,6 @@ array_complex(PyArrayObject *self, PyObject *NPY_UNUSED(args))
     return c;
 }
 
-#ifndef NPY_PY3K
-
-static PyObject *
-array_getslice(PyArrayObject *self, PyObject *args)
-{
-    PyObject *start, *stop, *slice, *result;
-    if (!PyArg_ParseTuple(args, "OO:__getslice__", &start, &stop)) {
-        return NULL;
-    }
-
-    slice = PySlice_New(start, stop, NULL);
-    if (slice == NULL) {
-        return NULL;
-    }
-
-    /* Deliberately delegate to subclasses */
-    result = PyObject_GetItem((PyObject *)self, slice);
-    Py_DECREF(slice);
-    return result;
-}
-
-static PyObject *
-array_setslice(PyArrayObject *self, PyObject *args)
-{
-    PyObject *start, *stop, *value, *slice;
-    if (!PyArg_ParseTuple(args, "OOO:__setslice__", &start, &stop, &value)) {
-        return NULL;
-    }
-
-    slice = PySlice_New(start, stop, NULL);
-    if (slice == NULL) {
-        return NULL;
-    }
-
-    /* Deliberately delegate to subclasses */
-    if (PyObject_SetItem((PyObject *)self, slice, value) < 0) {
-        Py_DECREF(slice);
-        return NULL;
-    }
-    Py_DECREF(slice);
-    Py_RETURN_NONE;
-}
-
-#endif
-
 NPY_NO_EXPORT PyMethodDef array_methods[] = {
 
     /* for subtypes */
@@ -2705,12 +2640,6 @@ NPY_NO_EXPORT PyMethodDef array_methods[] = {
         (PyCFunction)array_function,
         METH_VARARGS | METH_KEYWORDS, NULL},
 
-#ifndef NPY_PY3K
-    {"__unicode__",
-        (PyCFunction)array_unicode,
-        METH_NOARGS, NULL},
-#endif
-
     /* for the sys module */
     {"__sizeof__",
         (PyCFunction) array_sizeof,
@@ -2749,23 +2678,6 @@ NPY_NO_EXPORT PyMethodDef array_methods[] = {
         (PyCFunction) array_format,
         METH_VARARGS, NULL},
 
-#ifndef NPY_PY3K
-    /*
-     * While we could put these in `tp_sequence`, its' easier to define them
-     * in terms of PyObject* arguments.
-     *
-     * We must provide these for compatibility with code that calls them
-     * directly. They are already deprecated at a language level in python 2.7,
-     * but are removed outright in python 3.
-     */
-    {"__getslice__",
-        (PyCFunction) array_getslice,
-        METH_VARARGS, NULL},
-    {"__setslice__",
-        (PyCFunction) array_setslice,
-        METH_VARARGS, NULL},
-#endif
-
     /* Original and Extended methods added 2005 */
     {"all",
         (PyCFunction)array_all,
@@ -2915,7 +2827,7 @@ NPY_NO_EXPORT PyMethodDef array_methods[] = {
         (PyCFunction)array_tolist,
         METH_VARARGS, NULL},
     {"tostring",
-        (PyCFunction)array_tobytes,
+        (PyCFunction)array_tostring,
         METH_VARARGS | METH_KEYWORDS, NULL},
     {"trace",
         (PyCFunction)array_trace,
index 7a9a24a002055f1d7dd4261442f672823200dac2..c0de23c35601322553d41ce112368a88cb5c21e1 100644 (file)
@@ -5,8 +5,6 @@
 
 extern NPY_NO_EXPORT PyMethodDef array_methods[];
 
-NPY_NO_EXPORT const char *
-npy_casting_to_string(NPY_CASTING casting);
 
 /*
  * Pathlib support, takes a borrowed reference and returns a new one.
index 9169814c24fc72879e7f91a78b2bf9407fa1b8c7..a9f673d93a233dc748a61eac2bf0420723851fca 100644 (file)
@@ -34,6 +34,7 @@
 NPY_NO_EXPORT int NPY_NUMUSERTYPES = 0;
 
 /* Internal APIs */
+#include "alloc.h"
 #include "arrayfunction_override.h"
 #include "arraytypes.h"
 #include "arrayobject.h"
@@ -161,7 +162,7 @@ PyArray_MultiplyList(npy_intp const *l1, int n)
  * Multiply a List of Non-negative numbers with over-flow detection.
  */
 NPY_NO_EXPORT npy_intp
-PyArray_OverflowMultiplyList(npy_intp *l1, int n)
+PyArray_OverflowMultiplyList(npy_intp const *l1, int n)
 {
     npy_intp prod = 1;
     int i;
@@ -1559,7 +1560,6 @@ _prepend_ones(PyArrayObject *arr, int nd, int ndmin, NPY_ORDER order)
     return ret;
 }
 
-
 #define STRIDING_OK(op, order) \
                 ((order) == NPY_ANYORDER || \
                  (order) == NPY_KEEPORDER || \
@@ -1583,8 +1583,9 @@ _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
                          "ndmin", NULL};
 
     if (PyTuple_GET_SIZE(args) > 2) {
-        PyErr_SetString(PyExc_ValueError,
-                        "only 2 non-keyword arguments accepted");
+        PyErr_Format(PyExc_TypeError,
+                     "array() takes from 1 to 2 positional arguments but "
+                     "%zd were given", PyTuple_GET_SIZE(args));
         return NULL;
     }
 
@@ -1601,7 +1602,10 @@ _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
             dtype_obj = PyTuple_GET_ITEM(args, 1);
         }
         else if (kws) {
-            dtype_obj = PyDict_GetItem(kws, npy_ma_str_dtype);
+            dtype_obj = PyDict_GetItemWithError(kws, npy_ma_str_dtype);
+            if (dtype_obj == NULL && PyErr_Occurred()) {
+                return NULL;
+            }
             if (dtype_obj == NULL) {
                 dtype_obj = Py_None;
             }
@@ -1618,7 +1622,10 @@ _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
         else {
             /* fast path for copy=False rest default (np.asarray) */
             PyObject * copy_obj, * order_obj, *ndmin_obj;
-            copy_obj = PyDict_GetItem(kws, npy_ma_str_copy);
+            copy_obj = PyDict_GetItemWithError(kws, npy_ma_str_copy);
+            if (copy_obj == NULL && PyErr_Occurred()) {
+                return NULL;
+            }
             if (copy_obj != Py_False) {
                 goto full_path;
             }
@@ -1627,14 +1634,20 @@ _array_fromobject(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kws)
             /* order does not matter for contiguous 1d arrays */
             if (PyArray_NDIM((PyArrayObject*)op) > 1 ||
                 !PyArray_IS_C_CONTIGUOUS((PyArrayObject*)op)) {
-                order_obj = PyDict_GetItem(kws, npy_ma_str_order);
-                if (order_obj != Py_None && order_obj != NULL) {
+                order_obj = PyDict_GetItemWithError(kws, npy_ma_str_order);
+                if (order_obj == NULL && PyErr_Occurred()) {
+                    return NULL;
+                }
+                else if (order_obj != Py_None && order_obj != NULL) {
                     goto full_path;
                 }
             }
 
-            ndmin_obj = PyDict_GetItem(kws, npy_ma_str_ndmin);
-            if (ndmin_obj) {
+            ndmin_obj = PyDict_GetItemWithError(kws, npy_ma_str_ndmin);
+            if (ndmin_obj == NULL && PyErr_Occurred()) {
+                return NULL;
+            }
+            else if (ndmin_obj) {
                 long t = PyLong_AsLong(ndmin_obj);
                 if (error_converting(t)) {
                     goto clean_type;
@@ -1845,19 +1858,21 @@ array_empty_like(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
     NPY_ORDER order = NPY_KEEPORDER;
     PyArrayObject *ret = NULL;
     int subok = 1;
-    PyArray_Dims shape = {NULL, 0};
+    /* -1 is a special value meaning "not specified" */
+    PyArray_Dims shape = {NULL, -1};
 
     if (!PyArg_ParseTupleAndKeywords(args, kwds, "O&|O&O&iO&:empty_like", kwlist,
                 &PyArray_Converter, &prototype,
                 &PyArray_DescrConverter2, &dtype,
                 &PyArray_OrderConverter, &order,
                 &subok,
-                &PyArray_IntpConverter, &shape)) {
+                &PyArray_OptionalIntpConverter, &shape)) {
         goto fail;
     }
     /* steals the reference to dtype if it's not NULL */
     ret = (PyArrayObject *)PyArray_NewLikeArrayWithShape(prototype, order, dtype,
                                                          shape.len, shape.ptr, subok);
+    npy_free_cache_dim_obj(shape);
     if (!ret) {
         goto fail;
     }
@@ -1891,8 +1906,17 @@ array_scalar(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
                 &PyArrayDescr_Type, &typecode, &obj)) {
         return NULL;
     }
+    if (PyDataType_FLAGCHK(typecode, NPY_LIST_PICKLE)) {
+        if (!PySequence_Check(obj)) {
+            PyErr_SetString(PyExc_TypeError,
+                            "found non-sequence while unpickling scalar with "
+                            "NPY_LIST_PICKLE set");
+            return NULL;
+        }
+        dptr = &obj;
+    }
 
-    if (PyDataType_FLAGCHK(typecode, NPY_ITEM_IS_POINTER)) {
+    else if (PyDataType_FLAGCHK(typecode, NPY_ITEM_IS_POINTER)) {
         if (obj == NULL) {
             obj = Py_None;
         }
@@ -1911,7 +1935,6 @@ array_scalar(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
             alloc = 1;
         }
         else {
-#if defined(NPY_PY3K)
             /* Backward compatibility with Python 2 NumPy pickles */
             if (PyUnicode_Check(obj)) {
                 tmpobj = PyUnicode_AsLatin1String(obj);
@@ -1925,8 +1948,6 @@ array_scalar(PyObject *NPY_UNUSED(ignored), PyObject *args, PyObject *kwds)
                     return NULL;
                 }
             }
-#endif
-
             if (!PyString_Check(obj)) {
                 PyErr_SetString(PyExc_TypeError,
                         "initializing object must be a string");
@@ -2011,11 +2032,7 @@ array_count_nonzero(PyObject *NPY_UNUSED(self), PyObject *args, PyObject *kwds)
     if (count == -1) {
         return NULL;
     }
-#if defined(NPY_PY3K)
     return PyLong_FromSsize_t(count);
-#else
-    return PyInt_FromSsize_t(count);
-#endif
 }
 
 static PyObject *
@@ -2422,7 +2439,6 @@ einsum_list_to_subscripts(PyObject *obj, char *subscripts, int subsize)
     }
     size = PySequence_Size(obj);
 
-
     for (i = 0; i < size; ++i) {
         item = PySequence_Fast_GET_ITEM(obj, i);
         /* Ellipsis */
@@ -2445,8 +2461,16 @@ einsum_list_to_subscripts(PyObject *obj, char *subscripts, int subsize)
             ellipsis = 1;
         }
         /* Subscript */
-        else if (PyInt_Check(item) || PyLong_Check(item)) {
-            long s = PyInt_AsLong(item);
+        else {
+            npy_intp s = PyArray_PyIntAsIntp(item);
+            /* Invalid */
+            if (error_converting(s)) {
+                PyErr_SetString(PyExc_TypeError,
+                        "each subscript must be either an integer "
+                        "or an ellipsis");
+                Py_DECREF(obj);
+                return -1;
+            }
             npy_bool bad_input = 0;
 
             if (subindex + 1 >= subsize) {
@@ -2456,7 +2480,7 @@ einsum_list_to_subscripts(PyObject *obj, char *subscripts, int subsize)
                 return -1;
             }
 
-            if ( s < 0 ) {
+            if (s < 0) {
                 bad_input = 1;
             }
             else if (s < 26) {
@@ -2474,16 +2498,9 @@ einsum_list_to_subscripts(PyObject *obj, char *subscripts, int subsize)
                         "subscript is not within the valid range [0, 52)");
                 Py_DECREF(obj);
                 return -1;
-            }
-        }
-        /* Invalid */
-        else {
-            PyErr_SetString(PyExc_ValueError,
-                    "each subscript must be either an integer "
-                    "or an ellipsis");
-            Py_DECREF(obj);
-            return -1;
+            }              
         }
+        
     }
 
     Py_DECREF(obj);
@@ -2630,13 +2647,11 @@ array_einsum(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
         while (PyDict_Next(kwds, &pos, &key, &value)) {
             char *str = NULL;
 
-#if defined(NPY_PY3K)
             Py_XDECREF(str_key_obj);
             str_key_obj = PyUnicode_AsASCIIString(key);
             if (str_key_obj != NULL) {
                 key = str_key_obj;
             }
-#endif
 
             str = PyBytes_AsString(key);
 
@@ -3276,142 +3291,16 @@ array_datetime_data(PyObject *NPY_UNUSED(dummy), PyObject *args)
     }
 
     meta = get_datetime_metadata_from_dtype(dtype);
-    Py_DECREF(dtype);
     if (meta == NULL) {
+        Py_DECREF(dtype);
         return NULL;
     }
 
-    return convert_datetime_metadata_to_tuple(meta);
-}
-
-#if !defined(NPY_PY3K)
-static PyObject *
-new_buffer(PyObject *NPY_UNUSED(dummy), PyObject *args)
-{
-    int size;
-
-    if (!PyArg_ParseTuple(args, "i:buffer", &size)) {
-        return NULL;
-    }
-    return PyBuffer_New(size);
-}
-
-static PyObject *
-buffer_buffer(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
-{
-    PyObject *obj;
-    Py_ssize_t offset = 0, n;
-    Py_ssize_t size = Py_END_OF_BUFFER;
-    void *unused;
-    static char *kwlist[] = {"object", "offset", "size", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds,
-                "O|" NPY_SSIZE_T_PYFMT NPY_SSIZE_T_PYFMT ":get_buffer", kwlist,
-                &obj, &offset, &size)) {
-        return NULL;
-    }
-    if (PyObject_AsWriteBuffer(obj, &unused, &n) < 0) {
-        PyErr_Clear();
-        return PyBuffer_FromObject(obj, offset, size);
-    }
-    else {
-        return PyBuffer_FromReadWriteObject(obj, offset, size);
-    }
-}
-#endif
-
-#ifndef _MSC_VER
-#include <setjmp.h>
-#include <signal.h>
-jmp_buf _NPY_SIGSEGV_BUF;
-static void
-_SigSegv_Handler(int signum)
-{
-    longjmp(_NPY_SIGSEGV_BUF, signum);
-}
-#endif
-
-#define _test_code() { \
-        test = *((char*)memptr); \
-        if (!ro) { \
-            *((char *)memptr) = '\0'; \
-            *((char *)memptr) = test; \
-        } \
-        test = *((char*)memptr+size-1); \
-        if (!ro) { \
-            *((char *)memptr+size-1) = '\0'; \
-            *((char *)memptr+size-1) = test; \
-        } \
-    }
-
-static PyObject *
-as_buffer(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds)
-{
-    PyObject *mem;
-    Py_ssize_t size;
-    npy_bool ro = NPY_FALSE, check = NPY_TRUE;
-    void *memptr;
-    static char *kwlist[] = {"mem", "size", "readonly", "check", NULL};
-
-    if (!PyArg_ParseTupleAndKeywords(args, kwds,
-                "O" NPY_SSIZE_T_PYFMT "|O&O&:int_asbuffer", kwlist,
-                &mem, &size, PyArray_BoolConverter, &ro,
-                PyArray_BoolConverter, &check)) {
-        return NULL;
-    }
-    memptr = PyLong_AsVoidPtr(mem);
-    if (memptr == NULL) {
-        return NULL;
-    }
-    if (check) {
-        /*
-         * Try to dereference the start and end of the memory region
-         * Catch segfault and report error if it occurs
-         */
-        char test;
-        int err = 0;
-
-#ifdef _MSC_VER
-        __try {
-            _test_code();
-        }
-        __except(1) {
-            err = 1;
-        }
-#else
-        PyOS_sighandler_t _npy_sig_save;
-        _npy_sig_save = PyOS_setsig(SIGSEGV, _SigSegv_Handler);
-        if (setjmp(_NPY_SIGSEGV_BUF) == 0) {
-            _test_code();
-        }
-        else {
-            err = 1;
-        }
-        PyOS_setsig(SIGSEGV, _npy_sig_save);
-#endif
-        if (err) {
-            PyErr_SetString(PyExc_ValueError,
-                    "cannot use memory location as a buffer.");
-            return NULL;
-        }
-    }
-
-
-#if defined(NPY_PY3K)
-    PyErr_SetString(PyExc_RuntimeError,
-            "XXX -- not implemented!");
-    return NULL;
-#else
-    if (ro) {
-        return PyBuffer_FromMemory(memptr, size);
-    }
-    return PyBuffer_FromReadWriteMemory(memptr, size);
-#endif
+    PyObject *res = convert_datetime_metadata_to_tuple(meta);
+    Py_DECREF(dtype);
+    return res;
 }
 
-#undef _test_code
-
-
 /*
  * Prints floating-point scalars using the Dragon4 algorithm, scientific mode.
  * See docstring of `np.format_float_scientific` for description of arguments.
@@ -3992,11 +3881,6 @@ array_shares_memory_impl(PyObject *args, PyObject *kwds, Py_ssize_t default_max_
             goto fail;
         }
     }
-#if !defined(NPY_PY3K)
-    else if (PyInt_Check(max_work_obj)) {
-        max_work = PyInt_AsSsize_t(max_work_obj);
-    }
-#endif
     else {
         PyErr_SetString(PyExc_ValueError, "max_work must be an integer");
         goto fail;
@@ -4220,17 +4104,6 @@ static struct PyMethodDef array_module_methods[] = {
     {"is_busday",
         (PyCFunction)array_is_busday,
         METH_VARARGS | METH_KEYWORDS, NULL},
-#if !defined(NPY_PY3K)
-    {"newbuffer",
-        (PyCFunction)new_buffer,
-        METH_VARARGS, NULL},
-    {"getbuffer",
-        (PyCFunction)buffer_buffer,
-        METH_VARARGS | METH_KEYWORDS, NULL},
-#endif
-    {"int_asbuffer",
-        (PyCFunction)as_buffer,
-        METH_VARARGS | METH_KEYWORDS, NULL},
     {"format_longfloat",
         (PyCFunction)format_longfloat,
         METH_VARARGS | METH_KEYWORDS, NULL},
@@ -4290,6 +4163,8 @@ static struct PyMethodDef array_module_methods[] = {
         METH_VARARGS, NULL},
     {"_add_newdoc_ufunc", (PyCFunction)add_newdoc_ufunc,
         METH_VARARGS, NULL},
+    {"_set_madvise_hugepage", (PyCFunction)_set_madvise_hugepage,
+        METH_O, NULL},
     {NULL, NULL, 0, NULL}                /* sentinel */
 };
 
@@ -4310,11 +4185,6 @@ setup_scalartypes(PyObject *NPY_UNUSED(dict))
     if (PyType_Ready(&PyBool_Type) < 0) {
         return -1;
     }
-#if !defined(NPY_PY3K)
-    if (PyType_Ready(&PyInt_Type) < 0) {
-        return -1;
-    }
-#endif
     if (PyType_Ready(&PyFloat_Type) < 0) {
         return -1;
     }
@@ -4365,27 +4235,6 @@ setup_scalartypes(PyObject *NPY_UNUSED(dict))
         return -1;                                                      \
     }
 
-/*
- * In Py3K, int is no longer a fixed-width integer type, so don't
- * inherit numpy.int_ from it.
- */
-#if defined(NPY_PY3K)
-#define INHERIT_INT(child, parent2)                                     \
-    SINGLE_INHERIT(child, parent2);
-#else
-#define INHERIT_INT(child, parent2)                                     \
-    Py##child##ArrType_Type.tp_flags |= Py_TPFLAGS_INT_SUBCLASS;        \
-    DUAL_INHERIT(child, Int, parent2);
-#endif
-
-#if defined(NPY_PY3K)
-#define DUAL_INHERIT_COMPARE(child, parent1, parent2)
-#else
-#define DUAL_INHERIT_COMPARE(child, parent1, parent2)                   \
-    Py##child##ArrType_Type.tp_compare =                                \
-        Py##parent1##_Type.tp_compare;
-#endif
-
 #define DUAL_INHERIT2(child, parent1, parent2)                          \
     Py##child##ArrType_Type.tp_base = &Py##parent1##_Type;              \
     Py##child##ArrType_Type.tp_bases =                                  \
@@ -4393,7 +4242,6 @@ setup_scalartypes(PyObject *NPY_UNUSED(dict))
                       &Py##parent2##ArrType_Type);                      \
     Py##child##ArrType_Type.tp_richcompare =                            \
         Py##parent1##_Type.tp_richcompare;                              \
-    DUAL_INHERIT_COMPARE(child, parent1, parent2)                       \
     Py##child##ArrType_Type.tp_hash = Py##parent1##_Type.tp_hash;       \
     if (PyType_Ready(&Py##child##ArrType_Type) < 0) {                   \
         PyErr_Print();                                                  \
@@ -4406,20 +4254,9 @@ setup_scalartypes(PyObject *NPY_UNUSED(dict))
     SINGLE_INHERIT(Bool, Generic);
     SINGLE_INHERIT(Byte, SignedInteger);
     SINGLE_INHERIT(Short, SignedInteger);
-
-#if NPY_SIZEOF_INT == NPY_SIZEOF_LONG
-    INHERIT_INT(Int, SignedInteger);
-#else
     SINGLE_INHERIT(Int, SignedInteger);
-#endif
-
-    INHERIT_INT(Long, SignedInteger);
-
-#if NPY_SIZEOF_LONGLONG == NPY_SIZEOF_LONG
-    INHERIT_INT(LongLong, SignedInteger);
-#else
+    SINGLE_INHERIT(Long, SignedInteger);
     SINGLE_INHERIT(LongLong, SignedInteger);
-#endif
 
     /* Datetime doesn't fit in any category */
     SINGLE_INHERIT(Datetime, Generic);
@@ -4458,9 +4295,7 @@ setup_scalartypes(PyObject *NPY_UNUSED(dict))
 
 #undef SINGLE_INHERIT
 #undef DUAL_INHERIT
-#undef INHERIT_INT
 #undef DUAL_INHERIT2
-#undef DUAL_INHERIT_COMPARE
 
     /*
      * Clean up string and unicode array types so they act more like
@@ -4542,7 +4377,6 @@ intern_strings(void)
            npy_ma_str_ndmin && npy_ma_str_axis1 && npy_ma_str_axis2;
 }
 
-#if defined(NPY_PY3K)
 static struct PyModuleDef moduledef = {
         PyModuleDef_HEAD_INIT,
         "_multiarray_umath",
@@ -4554,25 +4388,19 @@ static struct PyModuleDef moduledef = {
         NULL,
         NULL
 };
-#endif
 
 /* Initialization function for the module */
-#if defined(NPY_PY3K)
-#define RETVAL(x) x
 PyMODINIT_FUNC PyInit__multiarray_umath(void) {
-#else
-#define RETVAL(x)
-PyMODINIT_FUNC init_multiarray_umath(void) {
-#endif
     PyObject *m, *d, *s;
     PyObject *c_api;
 
+    /* Initialize CPU features */
+    if (npy_cpu_init() < 0) {
+        goto err;
+    }
+
     /* Create the module and add the functions */
-#if defined(NPY_PY3K)
     m = PyModule_Create(&moduledef);
-#else
-    m = Py_InitModule("_multiarray_umath", array_module_methods);
-#endif
     if (!m) {
         goto err;
     }
@@ -4696,6 +4524,16 @@ PyMODINIT_FUNC init_multiarray_umath(void) {
     PyDict_SetItemString(d, "__version__", s);
     Py_DECREF(s);
 
+    s = npy_cpu_features_dict();
+    if (s == NULL) {
+        goto err;
+    }
+    if (PyDict_SetItemString(d, "__cpu_features__", s) < 0) {
+        Py_DECREF(s);
+        goto err;
+    }
+    Py_DECREF(s);
+
     s = NpyCapsule_FromVoidPtr((void *)_datetime_strings, NULL);
     if (s == NULL) {
         goto err;
@@ -4757,12 +4595,12 @@ PyMODINIT_FUNC init_multiarray_umath(void) {
     if (initumath(m) != 0) {
         goto err;
     }
-    return RETVAL(m);
+    return m;
 
  err:
     if (!PyErr_Occurred()) {
         PyErr_SetString(PyExc_RuntimeError,
                         "cannot load multiarray module.");
     }
-    return RETVAL(NULL);
+    return NULL;
 }
index 5e770338deabb591f9ad6954da0f5b3fe9b25b06..620c7d59335bfc130495c619867ccec64be03174 100644 (file)
@@ -56,7 +56,7 @@ static int
 npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itflags,
                     char **op_dataptr,
                     const npy_uint32 *op_flags, int **op_axes,
-                    npy_intp *itershape);
+                    npy_intp const *itershape);
 static void
 npyiter_replace_axisdata(NpyIter *iter, int iop,
                       PyArrayObject *op,
@@ -80,7 +80,7 @@ npyiter_get_common_dtype(int nop, PyArrayObject **op,
 static PyArrayObject *
 npyiter_new_temp_array(NpyIter *iter, PyTypeObject *subtype,
                 npy_uint32 flags, npyiter_opitflags *op_itflags,
-                int op_ndim, npy_intp *shape,
+                int op_ndim, npy_intp const *shape,
                 PyArray_Descr *op_dtype, const int *op_axes);
 static int
 npyiter_allocate_arrays(NpyIter *iter,
@@ -1308,21 +1308,11 @@ npyiter_check_casting(int nop, PyArrayObject **op,
                         !PyArray_CanCastArrayTo(op[iop],
                                           op_dtype[iop],
                                           casting)) {
-                PyObject *errmsg;
-                errmsg = PyUString_FromFormat(
-                        "Iterator operand %d dtype could not be cast from ",
-                        iop);
-                PyUString_ConcatAndDel(&errmsg,
-                        PyObject_Repr((PyObject *)PyArray_DESCR(op[iop])));
-                PyUString_ConcatAndDel(&errmsg,
-                        PyUString_FromString(" to "));
-                PyUString_ConcatAndDel(&errmsg,
-                        PyObject_Repr((PyObject *)op_dtype[iop]));
-                PyUString_ConcatAndDel(&errmsg,
-                        PyUString_FromFormat(" according to the rule %s",
-                                npyiter_casting_to_string(casting)));
-                PyErr_SetObject(PyExc_TypeError, errmsg);
-                Py_DECREF(errmsg);
+                PyErr_Format(PyExc_TypeError,
+                        "Iterator operand %d dtype could not be cast from "
+                        "%R to %R according to the rule %s",
+                        iop, PyArray_DESCR(op[iop]), op_dtype[iop],
+                        npyiter_casting_to_string(casting));
                 return 0;
             }
             /* Check write (temp -> op) casting */
@@ -1330,22 +1320,12 @@ npyiter_check_casting(int nop, PyArrayObject **op,
                         !PyArray_CanCastTypeTo(op_dtype[iop],
                                           PyArray_DESCR(op[iop]),
                                           casting)) {
-                PyObject *errmsg;
-                errmsg = PyUString_FromString(
-                        "Iterator requested dtype could not be cast from ");
-                PyUString_ConcatAndDel(&errmsg,
-                        PyObject_Repr((PyObject *)op_dtype[iop]));
-                PyUString_ConcatAndDel(&errmsg,
-                        PyUString_FromString(" to "));
-                PyUString_ConcatAndDel(&errmsg,
-                        PyObject_Repr((PyObject *)PyArray_DESCR(op[iop])));
-                PyUString_ConcatAndDel(&errmsg,
-                        PyUString_FromFormat(", the operand %d dtype, "
-                                "according to the rule %s",
-                                iop,
-                                npyiter_casting_to_string(casting)));
-                PyErr_SetObject(PyExc_TypeError, errmsg);
-                Py_DECREF(errmsg);
+                PyErr_Format(PyExc_TypeError,
+                        "Iterator requested dtype could not be cast from "
+                        "%R to %R, the operand %d dtype, "
+                        "according to the rule %s",
+                        op_dtype[iop], PyArray_DESCR(op[iop]), iop,
+                        npyiter_casting_to_string(casting));
                 return 0;
             }
 
@@ -1424,7 +1404,7 @@ static int
 npyiter_fill_axisdata(NpyIter *iter, npy_uint32 flags, npyiter_opitflags *op_itflags,
                     char **op_dataptr,
                     const npy_uint32 *op_flags, int **op_axes,
-                    npy_intp *itershape)
+                    npy_intp const *itershape)
 {
     npy_uint32 itflags = NIT_ITFLAGS(iter);
     int idim, ndim = NIT_NDIM(iter);
@@ -2476,7 +2456,7 @@ npyiter_get_common_dtype(int nop, PyArrayObject **op,
 static PyArrayObject *
 npyiter_new_temp_array(NpyIter *iter, PyTypeObject *subtype,
                 npy_uint32 flags, npyiter_opitflags *op_itflags,
-                int op_ndim, npy_intp *shape,
+                int op_ndim, npy_intp const *shape,
                 PyArray_Descr *op_dtype, const int *op_axes)
 {
     npy_uint32 itflags = NIT_ITFLAGS(iter);
index 246f9d3827cfb1e8f3089b279e8ad1088c8a5041..7f31a5096d1fe46d8276de9f1d3407d8db112e26 100644 (file)
@@ -17,6 +17,7 @@
 #include "npy_pycompat.h"
 #include "alloc.h"
 #include "common.h"
+#include "conversion_utils.h"
 #include "ctors.h"
 
 /* Functions not part of the public NumPy C API */
@@ -231,50 +232,6 @@ NpyIter_GlobalFlagsConverter(PyObject *flags_in, npy_uint32 *flags)
     return 1;
 }
 
-/* TODO: Use PyArray_OrderConverter once 'K' is added there */
-static int
-npyiter_order_converter(PyObject *order_in, NPY_ORDER *order)
-{
-    char *str = NULL;
-    Py_ssize_t length = 0;
-
-    if (PyUnicode_Check(order_in)) {
-        /* accept unicode input */
-        PyObject *str_obj;
-        int ret;
-        str_obj = PyUnicode_AsASCIIString(order_in);
-        if (str_obj == NULL) {
-            return 0;
-        }
-        ret = npyiter_order_converter(str_obj, order);
-        Py_DECREF(str_obj);
-        return ret;
-    }
-
-    if (PyBytes_AsStringAndSize(order_in, &str, &length) < 0) {
-        return 0;
-    }
-
-    if (length == 1) switch (str[0]) {
-        case 'C':
-            *order = NPY_CORDER;
-            return 1;
-        case 'F':
-            *order = NPY_FORTRANORDER;
-            return 1;
-        case 'A':
-            *order = NPY_ANYORDER;
-            return 1;
-        case 'K':
-            *order = NPY_KEEPORDER;
-            return 1;
-    }
-
-    PyErr_SetString(PyExc_ValueError,
-                    "order must be one of 'C', 'F', 'A', or 'K'");
-    return 0;
-}
-
 static int
 NpyIter_OpFlagsConverter(PyObject *op_flags_in,
                          npy_uint32 *op_flags)
@@ -748,7 +705,7 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds)
     int oa_ndim = -1;
     int op_axes_arrays[NPY_MAXARGS][NPY_MAXDIMS];
     int *op_axes[NPY_MAXARGS];
-    PyArray_Dims itershape = {NULL, 0};
+    PyArray_Dims itershape = {NULL, -1};
     int buffersize = 0;
 
     if (self->iter != NULL) {
@@ -762,10 +719,10 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds)
                     NpyIter_GlobalFlagsConverter, &flags,
                     &op_flags_in,
                     &op_dtypes_in,
-                    npyiter_order_converter, &order,
+                    PyArray_OrderConverter, &order,
                     PyArray_CastingConverter, &casting,
                     &op_axes_in,
-                    PyArray_IntpConverter, &itershape,
+                    PyArray_OptionalIntpConverter, &itershape,
                     &buffersize)) {
         npy_free_cache_dim_obj(itershape);
         return -1;
@@ -800,7 +757,7 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds)
         }
     }
 
-    if (itershape.len > 0) {
+    if (itershape.len != -1) {
         if (oa_ndim == -1) {
             oa_ndim = itershape.len;
             memset(op_axes, 0, sizeof(op_axes[0]) * nop);
@@ -812,10 +769,6 @@ npyiter_init(NewNpyArrayIterObject *self, PyObject *args, PyObject *kwds)
             goto fail;
         }
     }
-    else if (itershape.ptr != NULL) {
-        npy_free_cache_dim_obj(itershape);
-        itershape.ptr = NULL;
-    }
 
     self->iter = NpyIter_AdvancedNew(nop, op, flags, order, casting, op_flags,
                                   op_request_dtypes,
@@ -895,7 +848,7 @@ NpyIter_NestedIters(PyObject *NPY_UNUSED(self),
                     NpyIter_GlobalFlagsConverter, &flags,
                     &op_flags_in,
                     &op_dtypes_in,
-                    npyiter_order_converter, &order,
+                    PyArray_OrderConverter, &order,
                     PyArray_CastingConverter, &casting,
                     &buffersize)) {
         return NULL;
@@ -2490,61 +2443,17 @@ NPY_NO_EXPORT PyMappingMethods npyiter_as_mapping = {
 };
 
 NPY_NO_EXPORT PyTypeObject NpyIter_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.nditer",                             /* tp_name */
-    sizeof(NewNpyArrayIterObject),              /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)npyiter_dealloc,                /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    &npyiter_as_sequence,                       /* tp_as_sequence */
-    &npyiter_as_mapping,                        /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    (iternextfunc)npyiter_next,                 /* tp_iternext */
-    npyiter_methods,                            /* tp_methods */
-    npyiter_members,                            /* tp_members */
-    npyiter_getsets,                            /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    (initproc)npyiter_init,                     /* tp_init */
-    0,                                          /* tp_alloc */
-    npyiter_new,                                /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.nditer",
+    .tp_basicsize = sizeof(NewNpyArrayIterObject),
+    .tp_dealloc = (destructor)npyiter_dealloc,
+    .tp_as_sequence = &npyiter_as_sequence,
+    .tp_as_mapping = &npyiter_as_mapping,
+    .tp_flags = Py_TPFLAGS_DEFAULT,
+    .tp_iternext = (iternextfunc)npyiter_next,
+    .tp_methods = npyiter_methods,
+    .tp_members = npyiter_members,
+    .tp_getset = npyiter_getsets,
+    .tp_init = (initproc)npyiter_init,
+    .tp_new = npyiter_new,
 };
index fae413c85e1c2d1e05666c0b8aa0353b216a4ee2..2eb97c4b94ce512177b7cd79c3a1d5aa5d3531fc 100644 (file)
@@ -7,7 +7,7 @@ NPY_NO_EXPORT void
 _dealloc_cached_buffer_info(PyObject *self);
 
 NPY_NO_EXPORT PyArray_Descr*
-_descriptor_from_pep3118_format(char *s);
+_descriptor_from_pep3118_format(char const *s);
 
 NPY_NO_EXPORT int
 gentype_getbuffer(PyObject *obj, Py_buffer *view, int flags);
index dabc866ffb786547d5cc38ee6771eafb1e14dedd..19ac7d7f9cd683185dbdb33950fe82c6a62708eb 100644 (file)
@@ -32,10 +32,6 @@ static PyObject *
 array_inplace_subtract(PyArrayObject *m1, PyObject *m2);
 static PyObject *
 array_inplace_multiply(PyArrayObject *m1, PyObject *m2);
-#if !defined(NPY_PY3K)
-static PyObject *
-array_inplace_divide(PyArrayObject *m1, PyObject *m2);
-#endif
 static PyObject *
 array_inplace_true_divide(PyArrayObject *m1, PyObject *m2);
 static PyObject *
@@ -61,8 +57,11 @@ array_inplace_power(PyArrayObject *a1, PyObject *o2, PyObject *NPY_UNUSED(modulo
  */
 
 /* FIXME - macro contains a return */
-#define SET(op)   temp = PyDict_GetItemString(dict, #op); \
-    if (temp != NULL) { \
+#define SET(op)   temp = _PyDict_GetItemStringWithError(dict, #op); \
+    if (temp == NULL && PyErr_Occurred()) { \
+        return -1; \
+    } \
+    else if (temp != NULL) { \
         if (!(PyCallable_Check(temp))) { \
             return -1; \
         } \
@@ -353,20 +352,6 @@ array_multiply(PyArrayObject *m1, PyObject *m2)
     return PyArray_GenericBinaryFunction(m1, m2, n_ops.multiply);
 }
 
-#if !defined(NPY_PY3K)
-static PyObject *
-array_divide(PyArrayObject *m1, PyObject *m2)
-{
-    PyObject *res;
-
-    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_divide, array_divide);
-    if (try_binary_elide(m1, m2, &array_inplace_divide, &res, 0)) {
-        return res;
-    }
-    return PyArray_GenericBinaryFunction(m1, m2, n_ops.divide);
-}
-#endif
-
 static PyObject *
 array_remainder(PyArrayObject *m1, PyObject *m2)
 {
@@ -381,7 +366,6 @@ array_divmod(PyArrayObject *m1, PyObject *m2)
     return PyArray_GenericBinaryFunction(m1, m2, n_ops.divmod);
 }
 
-#if PY_VERSION_HEX >= 0x03050000
 /* Need this to be version dependent on account of the slot check */
 static PyObject *
 array_matrix_multiply(PyArrayObject *m1, PyObject *m2)
@@ -399,7 +383,6 @@ array_inplace_matrix_multiply(
                     "Use 'a = a @ b' instead of 'a @= b'.");
     return NULL;
 }
-#endif
 
 /*
  * Determine if object is a scalar and if so, convert the object
@@ -728,16 +711,6 @@ array_inplace_multiply(PyArrayObject *m1, PyObject *m2)
     return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.multiply);
 }
 
-#if !defined(NPY_PY3K)
-static PyObject *
-array_inplace_divide(PyArrayObject *m1, PyObject *m2)
-{
-    INPLACE_GIVE_UP_IF_NEEDED(
-            m1, m2, nb_inplace_divide, array_inplace_divide);
-    return PyArray_GenericInplaceBinaryFunction(m1, m2, n_ops.divide);
-}
-#endif
-
 static PyObject *
 array_inplace_remainder(PyArrayObject *m1, PyObject *m2)
 {
@@ -931,67 +904,12 @@ array_float(PyArrayObject *v)
     return array_scalar_forward(v, &PyNumber_Float, " in ndarray.__float__");
 }
 
-#if defined(NPY_PY3K)
-
 NPY_NO_EXPORT PyObject *
 array_int(PyArrayObject *v)
 {
     return array_scalar_forward(v, &PyNumber_Long, " in ndarray.__int__");
 }
 
-#else
-
-NPY_NO_EXPORT PyObject *
-array_int(PyArrayObject *v)
-{
-    return array_scalar_forward(v, &PyNumber_Int, " in ndarray.__int__");
-}
-
-NPY_NO_EXPORT PyObject *
-array_long(PyArrayObject *v)
-{
-    return array_scalar_forward(v, &PyNumber_Long, " in ndarray.__long__");
-}
-
-/* hex and oct aren't exposed to the C api, but we need a function pointer */
-static PyObject *
-_PyNumber_Oct(PyObject *o) {
-    PyObject *res;
-    PyObject *mod = PyImport_ImportModule("__builtin__");
-    if (mod == NULL) {
-        return NULL;
-    }
-    res = PyObject_CallMethod(mod, "oct", "(O)", o);
-    Py_DECREF(mod);
-    return res;
-}
-
-static PyObject *
-_PyNumber_Hex(PyObject *o) {
-    PyObject *res;
-    PyObject *mod = PyImport_ImportModule("__builtin__");
-    if (mod == NULL) {
-        return NULL;
-    }
-    res = PyObject_CallMethod(mod, "hex", "(O)", o);
-    Py_DECREF(mod);
-    return res;
-}
-
-NPY_NO_EXPORT PyObject *
-array_oct(PyArrayObject *v)
-{
-    return array_scalar_forward(v, &_PyNumber_Oct, " in ndarray.__oct__");
-}
-
-NPY_NO_EXPORT PyObject *
-array_hex(PyArrayObject *v)
-{
-    return array_scalar_forward(v, &_PyNumber_Hex, " in ndarray.__hex__");
-}
-
-#endif
-
 static PyObject *
 array_index(PyArrayObject *v)
 {
@@ -1005,65 +923,43 @@ array_index(PyArrayObject *v)
 
 
 NPY_NO_EXPORT PyNumberMethods array_as_number = {
-    (binaryfunc)array_add,                      /*nb_add*/
-    (binaryfunc)array_subtract,                 /*nb_subtract*/
-    (binaryfunc)array_multiply,                 /*nb_multiply*/
-#if !defined(NPY_PY3K)
-    (binaryfunc)array_divide,                   /*nb_divide*/
-#endif
-    (binaryfunc)array_remainder,                /*nb_remainder*/
-    (binaryfunc)array_divmod,                   /*nb_divmod*/
-    (ternaryfunc)array_power,                   /*nb_power*/
-    (unaryfunc)array_negative,                  /*nb_neg*/
-    (unaryfunc)array_positive,                  /*nb_pos*/
-    (unaryfunc)array_absolute,                  /*(unaryfunc)array_abs,*/
-    (inquiry)_array_nonzero,                    /*nb_nonzero*/
-    (unaryfunc)array_invert,                    /*nb_invert*/
-    (binaryfunc)array_left_shift,               /*nb_lshift*/
-    (binaryfunc)array_right_shift,              /*nb_rshift*/
-    (binaryfunc)array_bitwise_and,              /*nb_and*/
-    (binaryfunc)array_bitwise_xor,              /*nb_xor*/
-    (binaryfunc)array_bitwise_or,               /*nb_or*/
-#if !defined(NPY_PY3K)
-    0,                                          /*nb_coerce*/
-#endif
-    (unaryfunc)array_int,                       /*nb_int*/
-#if defined(NPY_PY3K)
-    0,                                          /*nb_reserved*/
-#else
-    (unaryfunc)array_long,                      /*nb_long*/
-#endif
-    (unaryfunc)array_float,                     /*nb_float*/
-#if !defined(NPY_PY3K)
-    (unaryfunc)array_oct,                       /*nb_oct*/
-    (unaryfunc)array_hex,                       /*nb_hex*/
-#endif
-
-    /*
-     * This code adds augmented assignment functionality
-     * that was made available in Python 2.0
-     */
-    (binaryfunc)array_inplace_add,              /*nb_inplace_add*/
-    (binaryfunc)array_inplace_subtract,         /*nb_inplace_subtract*/
-    (binaryfunc)array_inplace_multiply,         /*nb_inplace_multiply*/
-#if !defined(NPY_PY3K)
-    (binaryfunc)array_inplace_divide,           /*nb_inplace_divide*/
-#endif
-    (binaryfunc)array_inplace_remainder,        /*nb_inplace_remainder*/
-    (ternaryfunc)array_inplace_power,           /*nb_inplace_power*/
-    (binaryfunc)array_inplace_left_shift,       /*nb_inplace_lshift*/
-    (binaryfunc)array_inplace_right_shift,      /*nb_inplace_rshift*/
-    (binaryfunc)array_inplace_bitwise_and,      /*nb_inplace_and*/
-    (binaryfunc)array_inplace_bitwise_xor,      /*nb_inplace_xor*/
-    (binaryfunc)array_inplace_bitwise_or,       /*nb_inplace_or*/
-
-    (binaryfunc)array_floor_divide,             /*nb_floor_divide*/
-    (binaryfunc)array_true_divide,              /*nb_true_divide*/
-    (binaryfunc)array_inplace_floor_divide,     /*nb_inplace_floor_divide*/
-    (binaryfunc)array_inplace_true_divide,      /*nb_inplace_true_divide*/
-    (unaryfunc)array_index,                     /*nb_index */
-#if PY_VERSION_HEX >= 0x03050000
-    (binaryfunc)array_matrix_multiply,          /*nb_matrix_multiply*/
-    (binaryfunc)array_inplace_matrix_multiply,  /*nb_inplace_matrix_multiply*/
-#endif
+    .nb_add = (binaryfunc)array_add,
+    .nb_subtract = (binaryfunc)array_subtract,
+    .nb_multiply = (binaryfunc)array_multiply,
+    .nb_remainder = (binaryfunc)array_remainder,
+    .nb_divmod = (binaryfunc)array_divmod,
+    .nb_power = (ternaryfunc)array_power,
+    .nb_negative = (unaryfunc)array_negative,
+    .nb_positive = (unaryfunc)array_positive,
+    .nb_absolute = (unaryfunc)array_absolute,
+    .nb_bool = (inquiry)_array_nonzero,
+    .nb_invert = (unaryfunc)array_invert,
+    .nb_lshift = (binaryfunc)array_left_shift,
+    .nb_rshift = (binaryfunc)array_right_shift,
+    .nb_and = (binaryfunc)array_bitwise_and,
+    .nb_xor = (binaryfunc)array_bitwise_xor,
+    .nb_or = (binaryfunc)array_bitwise_or,
+
+    .nb_int = (unaryfunc)array_int,
+    .nb_float = (unaryfunc)array_float,
+    .nb_index = (unaryfunc)array_index,
+
+    .nb_inplace_add = (binaryfunc)array_inplace_add,
+    .nb_inplace_subtract = (binaryfunc)array_inplace_subtract,
+    .nb_inplace_multiply = (binaryfunc)array_inplace_multiply,
+    .nb_inplace_remainder = (binaryfunc)array_inplace_remainder,
+    .nb_inplace_power = (ternaryfunc)array_inplace_power,
+    .nb_inplace_lshift = (binaryfunc)array_inplace_left_shift,
+    .nb_inplace_rshift = (binaryfunc)array_inplace_right_shift,
+    .nb_inplace_and = (binaryfunc)array_inplace_bitwise_and,
+    .nb_inplace_xor = (binaryfunc)array_inplace_bitwise_xor,
+    .nb_inplace_or = (binaryfunc)array_inplace_bitwise_or,
+
+    .nb_floor_divide = (binaryfunc)array_floor_divide,
+    .nb_true_divide = (binaryfunc)array_true_divide,
+    .nb_inplace_floor_divide = (binaryfunc)array_inplace_floor_divide,
+    .nb_inplace_true_divide = (binaryfunc)array_inplace_true_divide,
+
+    .nb_matrix_multiply = (binaryfunc)array_matrix_multiply,
+    .nb_inplace_matrix_multiply = (binaryfunc)array_inplace_matrix_multiply,
 };
index 6033929d97650fd2c3589a55f47b583983b0e9be..c869b5eea63aa775619908594f77f893938aa80c 100644 (file)
@@ -46,7 +46,7 @@ PyArray_Item_INCREF(char *data, PyArray_Descr *descr)
         Py_ssize_t pos = 0;
 
         while (PyDict_Next(descr->fields, &pos, &key, &value)) {
-            if NPY_TITLE_KEY(key, value) {
+            if (NPY_TITLE_KEY(key, value)) {
                 continue;
             }
             if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset,
@@ -108,7 +108,7 @@ PyArray_Item_XDECREF(char *data, PyArray_Descr *descr)
             Py_ssize_t pos = 0;
 
             while (PyDict_Next(descr->fields, &pos, &key, &value)) {
-                if NPY_TITLE_KEY(key, value) {
+                if (NPY_TITLE_KEY(key, value)) {
                     continue;
                 }
                 if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset,
@@ -318,7 +318,7 @@ _fillobject(char *optr, PyObject *obj, PyArray_Descr *dtype)
         Py_ssize_t pos = 0;
 
         while (PyDict_Next(dtype->fields, &pos, &key, &value)) {
-            if NPY_TITLE_KEY(key, value) {
+            if (NPY_TITLE_KEY(key, value)) {
                 continue;
             }
             if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset, &title)) {
index b669a3e76477016d5e899e347c2cfe69143b66b9..f3c440dc625a4b0c30726c369adf8eeb04588046 100644 (file)
@@ -45,7 +45,7 @@ scalar_value(PyObject *scalar, PyArray_Descr *descr)
         type_num = descr->type_num;
     }
     switch (type_num) {
-#define CASE(ut,lt) case NPY_##ut: return &(((Py##lt##ScalarObject *)scalar)->obval)
+#define CASE(ut,lt) case NPY_##ut: return &PyArrayScalar_VAL(scalar, lt)
         CASE(BOOL, Bool);
         CASE(BYTE, Byte);
         CASE(UBYTE, UByte);
@@ -71,9 +71,19 @@ scalar_value(PyObject *scalar, PyArray_Descr *descr)
         case NPY_STRING:
             return (void *)PyString_AS_STRING(scalar);
         case NPY_UNICODE:
-            return (void *)PyUnicode_AS_DATA(scalar);
+            /* lazy initialization, to reduce the memory used by string scalars */
+            if (PyArrayScalar_VAL(scalar, Unicode) == NULL) {
+                Py_UCS4 *raw_data = PyUnicode_AsUCS4Copy(scalar);
+                if (raw_data == NULL) {
+                    return NULL;
+                }
+                PyArrayScalar_VAL(scalar, Unicode) = raw_data;
+                return (void *)raw_data;
+            }
+            return PyArrayScalar_VAL(scalar, Unicode);
         case NPY_VOID:
-            return ((PyVoidScalarObject *)scalar)->obval;
+            /* Note: no & needed here, so can't use CASE */
+            return PyArrayScalar_VAL(scalar, Void);
     }
 
     /*
@@ -81,14 +91,13 @@ scalar_value(PyObject *scalar, PyArray_Descr *descr)
      * scalar it inherits from.
      */
 
-#define _CHK(cls) (PyObject_IsInstance(scalar, \
-            (PyObject *)&Py##cls##ArrType_Type))
-#define _OBJ(lt) &(((Py##lt##ScalarObject *)scalar)->obval)
-#define _IFCASE(cls) if _CHK(cls) return _OBJ(cls)
+#define _CHK(cls) PyObject_IsInstance(scalar, \
+            (PyObject *)&Py##cls##ArrType_Type)
+#define _IFCASE(cls) if (_CHK(cls)) return &PyArrayScalar_VAL(scalar, cls)
 
-    if _CHK(Number) {
-        if _CHK(Integer) {
-            if _CHK(SignedInteger) {
+    if (_CHK(Number)) {
+        if (_CHK(Integer)) {
+            if (_CHK(SignedInteger)) {
                 _IFCASE(Byte);
                 _IFCASE(Short);
                 _IFCASE(Int);
@@ -107,7 +116,7 @@ scalar_value(PyObject *scalar, PyArray_Descr *descr)
         }
         else {
             /* Inexact */
-            if _CHK(Floating) {
+            if (_CHK(Floating)) {
                 _IFCASE(Half);
                 _IFCASE(Float);
                 _IFCASE(Double);
@@ -122,10 +131,10 @@ scalar_value(PyObject *scalar, PyArray_Descr *descr)
         }
     }
     else if (_CHK(Bool)) {
-        return _OBJ(Bool);
+        return &PyArrayScalar_VAL(scalar, Bool);
     }
     else if (_CHK(Datetime)) {
-        return _OBJ(Datetime);
+        return &PyArrayScalar_VAL(scalar, Datetime);
     }
     else if (_CHK(Flexible)) {
         if (_CHK(String)) {
@@ -135,7 +144,8 @@ scalar_value(PyObject *scalar, PyArray_Descr *descr)
             return (void *)PyUnicode_AS_DATA(scalar);
         }
         if (_CHK(Void)) {
-            return ((PyVoidScalarObject *)scalar)->obval;
+            /* Note: no & needed here, so can't use _IFCASE */
+            return PyArrayScalar_VAL(scalar, Void);
         }
     }
     else {
@@ -156,7 +166,6 @@ scalar_value(PyObject *scalar, PyArray_Descr *descr)
     }
     return (void *)memloc;
 #undef _IFCASE
-#undef _OBJ
 #undef _CHK
 }
 
@@ -319,21 +328,10 @@ PyArray_FromScalar(PyObject *scalar, PyArray_Descr *outcode)
 
     memptr = scalar_value(scalar, typecode);
 
-#ifndef Py_UNICODE_WIDE
-    if (typecode->type_num == NPY_UNICODE) {
-        PyUCS2Buffer_AsUCS4((Py_UNICODE *)memptr,
-                (npy_ucs4 *)PyArray_DATA(r),
-                PyUnicode_GET_SIZE(scalar),
-                PyArray_ITEMSIZE(r) >> 2);
-    }
-    else
-#endif
-    {
-        memcpy(PyArray_DATA(r), memptr, PyArray_ITEMSIZE(r));
-        if (PyDataType_FLAGCHK(typecode, NPY_ITEM_HASOBJECT)) {
-            /* Need to INCREF just the PyObject portion */
-            PyArray_Item_INCREF(memptr, typecode);
-        }
+    memcpy(PyArray_DATA(r), memptr, PyArray_ITEMSIZE(r));
+    if (PyDataType_FLAGCHK(typecode, NPY_ITEM_HASOBJECT)) {
+        /* Need to INCREF just the PyObject portion */
+        PyArray_Item_INCREF(memptr, typecode);
     }
 
 finish:
@@ -425,37 +423,69 @@ PyArray_ScalarFromObject(PyObject *object)
 NPY_NO_EXPORT PyArray_Descr *
 PyArray_DescrFromTypeObject(PyObject *type)
 {
-    int typenum;
-    PyArray_Descr *new, *conv = NULL;
-
     /* if it's a builtin type, then use the typenumber */
-    typenum = _typenum_fromtypeobj(type,1);
+    int typenum = _typenum_fromtypeobj(type,1);
     if (typenum != NPY_NOTYPE) {
-        new = PyArray_DescrFromType(typenum);
-        return new;
+        return PyArray_DescrFromType(typenum);
     }
 
     /* Check the generic types */
     if ((type == (PyObject *) &PyNumberArrType_Type) ||
             (type == (PyObject *) &PyInexactArrType_Type) ||
             (type == (PyObject *) &PyFloatingArrType_Type)) {
+        if (DEPRECATE("Converting `np.inexact` or `np.floating` to "
+                      "a dtype is deprecated. The current result is `float64` "
+                      "which is not strictly correct.") < 0) {
+            return NULL;
+        }
         typenum = NPY_DOUBLE;
     }
     else if (type == (PyObject *)&PyComplexFloatingArrType_Type) {
+        if (DEPRECATE("Converting `np.complex` to a dtype is deprecated. "
+                      "The current result is `complex128` which is not "
+                      "strictly correct.") < 0) {
+            return NULL;
+        }
         typenum = NPY_CDOUBLE;
     }
     else if ((type == (PyObject *)&PyIntegerArrType_Type) ||
             (type == (PyObject *)&PySignedIntegerArrType_Type)) {
+        if (DEPRECATE("Converting `np.integer` or `np.signedinteger` to "
+                      "a dtype is deprecated. The current result is "
+                      "`np.dtype(np.int_)` which is not strictly correct. "
+                      "Note that the result depends on the system. To ensure "
+                      "stable results use may want to use `np.int64` or "
+                      "`np.int32`.") < 0) {
+            return NULL;
+        }
         typenum = NPY_LONG;
     }
     else if (type == (PyObject *) &PyUnsignedIntegerArrType_Type) {
+        if (DEPRECATE("Converting `np.unsignedinteger` to a dtype is "
+                      "deprecated. The current result is `np.dtype(np.uint)` "
+                      "which is not strictly correct. Note that the result "
+                      "depends on the system. To ensure stable results you may "
+                      "want to use `np.uint64` or `np.uint32`.") < 0) {
+            return NULL;
+        }
         typenum = NPY_ULONG;
     }
     else if (type == (PyObject *) &PyCharacterArrType_Type) {
+        if (DEPRECATE("Converting `np.character` to a dtype is deprecated. "
+                      "The current result is `np.dtype(np.str_)` "
+                      "which is not strictly correct. Note that `np.character` "
+                      "is generally deprecated and 'S1' should be used.") < 0) {
+            return NULL;
+        }
         typenum = NPY_STRING;
     }
     else if ((type == (PyObject *) &PyGenericArrType_Type) ||
             (type == (PyObject *) &PyFlexibleArrType_Type)) {
+        if (DEPRECATE("Converting `np.generic` to a dtype is "
+                      "deprecated. The current result is `np.dtype(np.void)` "
+                      "which is not strictly correct.") < 0) {
+            return NULL;
+        }
         typenum = NPY_VOID;
     }
 
@@ -470,11 +500,12 @@ PyArray_DescrFromTypeObject(PyObject *type)
 
     /* Do special thing for VOID sub-types */
     if (PyType_IsSubtype((PyTypeObject *)type, &PyVoidArrType_Type)) {
-        new = PyArray_DescrNewFromType(NPY_VOID);
+        PyArray_Descr *new = PyArray_DescrNewFromType(NPY_VOID);
         if (new == NULL) {
             return NULL;
         }
-        if (_arraydescr_from_dtype_attr(type, &conv)) {
+        PyArray_Descr *conv = _arraydescr_try_convert_from_dtype_attr(type);
+        if ((PyObject *)conv != Py_NotImplemented) {
             if (conv == NULL) {
                 Py_DECREF(new);
                 return NULL;
@@ -486,8 +517,8 @@ PyArray_DescrFromTypeObject(PyObject *type)
             new->elsize = conv->elsize;
             new->subarray = conv->subarray;
             conv->subarray = NULL;
-            Py_DECREF(conv);
         }
+        Py_DECREF(conv);
         Py_XDECREF(new->typeobj);
         new->typeobj = (PyTypeObject *)type;
         Py_INCREF(type);
@@ -564,6 +595,9 @@ PyArray_DescrFromScalar(PyObject *sc)
     }
 
     descr = PyArray_DescrFromTypeObject((PyObject *)Py_TYPE(sc));
+    if (descr == NULL) {
+        return NULL;
+    }
     if (PyDataType_ISUNSIZED(descr)) {
         PyArray_DESCR_REPLACE(descr);
         type_num = descr->type_num;
@@ -571,10 +605,7 @@ PyArray_DescrFromScalar(PyObject *sc)
             descr->elsize = PyString_GET_SIZE(sc);
         }
         else if (type_num == NPY_UNICODE) {
-            descr->elsize = PyUnicode_GET_DATA_SIZE(sc);
-#ifndef Py_UNICODE_WIDE
-            descr->elsize <<= 1;
-#endif
+            descr->elsize = PyUnicode_GET_LENGTH(sc) * 4;
         }
         else {
             PyArray_Descr *dtype;
@@ -656,25 +687,31 @@ PyArray_Scalar(void *data, PyArray_Descr *descr, PyObject *base)
             itemsize = (((itemsize - 1) >> 2) + 1) << 2;
         }
     }
-#if PY_VERSION_HEX >= 0x03030000
     if (type_num == NPY_UNICODE) {
-        PyObject *u, *args;
-        int byteorder;
-
-#if NPY_BYTE_ORDER == NPY_LITTLE_ENDIAN
-        byteorder = -1;
-#elif NPY_BYTE_ORDER == NPY_BIG_ENDIAN
-        byteorder = +1;
-#else
-        #error Endianness undefined ?
-#endif
-        if (swap) byteorder *= -1;
-
-        u = PyUnicode_DecodeUTF32(data, itemsize, NULL, &byteorder);
+        /* we need the full string length here, else copyswap will write too
+           many bytes */
+        void *buff = PyArray_malloc(descr->elsize);
+        if (buff == NULL) {
+            return PyErr_NoMemory();
+        }
+        /* copyswap needs an array object, but only actually cares about the
+         * dtype
+         */
+        PyArrayObject_fields dummy_arr;
+        if (base == NULL) {
+            dummy_arr.descr = descr;
+            base = (PyObject *)&dummy_arr;
+        }
+        copyswap(buff, data, swap, base);
+
+        /* truncation occurs here */
+        PyObject *u = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, buff, itemsize / 4);
+        PyArray_free(buff);
         if (u == NULL) {
             return NULL;
         }
-        args = Py_BuildValue("(O)", u);
+
+        PyObject *args = Py_BuildValue("(O)", u);
         if (args == NULL) {
             Py_DECREF(u);
             return NULL;
@@ -684,7 +721,6 @@ PyArray_Scalar(void *data, PyArray_Descr *descr, PyObject *base)
         Py_DECREF(args);
         return obj;
     }
-#endif
     if (type->tp_itemsize != 0) {
         /* String type */
         obj = type->tp_alloc(type, itemsize);
@@ -710,92 +746,16 @@ PyArray_Scalar(void *data, PyArray_Descr *descr, PyObject *base)
         if (type_num == NPY_STRING) {
             destptr = PyString_AS_STRING(obj);
             ((PyStringObject *)obj)->ob_shash = -1;
-#if !defined(NPY_PY3K)
-            ((PyStringObject *)obj)->ob_sstate = SSTATE_NOT_INTERNED;
-#endif
             memcpy(destptr, data, itemsize);
             return obj;
         }
-#if PY_VERSION_HEX < 0x03030000
-        else if (type_num == NPY_UNICODE) {
-            /* tp_alloc inherited from Python PyBaseObject_Type */
-            PyUnicodeObject *uni = (PyUnicodeObject*)obj;
-            size_t length = itemsize >> 2;
-            Py_UNICODE *dst;
-#ifndef Py_UNICODE_WIDE
-            char *buffer;
-            Py_UNICODE *tmp;
-            int alloc = 0;
-
-            length *= 2;
-#endif
-            /* Set uni->str so that object can be deallocated on failure */
-            uni->str = NULL;
-            uni->defenc = NULL;
-            uni->hash = -1;
-            dst = PyObject_MALLOC(sizeof(Py_UNICODE) * (length + 1));
-            if (dst == NULL) {
-                Py_DECREF(obj);
-                PyErr_NoMemory();
-                return NULL;
-            }
-#ifdef Py_UNICODE_WIDE
-            memcpy(dst, data, itemsize);
-            if (swap) {
-                byte_swap_vector(dst, length, 4);
-            }
-            uni->str = dst;
-            uni->str[length] = 0;
-            uni->length = length;
-#else
-            /* need aligned data buffer */
-            if ((swap) || ((((npy_intp)data) % descr->alignment) != 0)) {
-                buffer = malloc(itemsize);
-                if (buffer == NULL) {
-                    PyObject_FREE(dst);
-                    Py_DECREF(obj);
-                    PyErr_NoMemory();
-                }
-                alloc = 1;
-                memcpy(buffer, data, itemsize);
-                if (swap) {
-                    byte_swap_vector(buffer, itemsize >> 2, 4);
-                }
-            }
-            else {
-                buffer = data;
-            }
-
-            /*
-             * Allocated enough for 2-characters per itemsize.
-             * Now convert from the data-buffer
-             */
-            length = PyUCS2Buffer_FromUCS4(dst,
-                    (npy_ucs4 *)buffer, itemsize >> 2);
-            if (alloc) {
-                free(buffer);
-            }
-            /* Resize the unicode result */
-            tmp = PyObject_REALLOC(dst, sizeof(Py_UNICODE)*(length + 1));
-            if (tmp == NULL) {
-                PyObject_FREE(dst);
-                Py_DECREF(obj);
-                return NULL;
-            }
-            uni->str = tmp;
-            uni->str[length] = 0;
-            uni->length = length;
-#endif
-            return obj;
-        }
-#endif /* PY_VERSION_HEX < 0x03030000 */
         else {
             PyVoidScalarObject *vobj = (PyVoidScalarObject *)obj;
             vobj->base = NULL;
             vobj->descr = descr;
             Py_INCREF(descr);
             vobj->obval = NULL;
-            Py_SIZE(vobj) = itemsize;
+            Py_SET_SIZE(vobj, itemsize);
             vobj->flags = NPY_ARRAY_CARRAY | NPY_ARRAY_F_CONTIGUOUS | NPY_ARRAY_OWNDATA;
             swap = 0;
             if (PyDataType_HASFIELDS(descr)) {
index 5da7f77386731dd43bd749d2bc5d903e8471724c..bf8e03bd2863d3010fd3406d5d328741831f943a 100644 (file)
@@ -54,63 +54,9 @@ NPY_NO_EXPORT PyTypeObject PyTimeIntegerArrType_Type;
  *         Floating, ComplexFloating, Flexible, Character#
  */
 NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.@name@",                             /* tp_name*/
-    sizeof(PyObject),                           /* tp_basicsize*/
-    0,                                          /* tp_itemsize */
-    /* methods */
-    0,                                          /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    0,                                          /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.@name@",
+    .tp_basicsize = sizeof(PyObject),
 };
 /**end repeat**/
 
@@ -226,20 +172,6 @@ gentype_@name@(PyObject *m1, PyObject *m2)
 
 /**end repeat**/
 
-#if !defined(NPY_PY3K)
-/**begin repeat
- *
- * #name = divide#
- */
-static PyObject *
-gentype_@name@(PyObject *m1, PyObject *m2)
-{
-    BINOP_GIVE_UP_IF_NEEDED(m1, m2, nb_@name@, gentype_@name@);
-    return PyArray_Type.tp_as_number->nb_@name@(m1, m2);
-}
-/**end repeat**/
-#endif
-
 /* Get a nested slot, or NULL if absent */
 #define GET_NESTED_SLOT(type, group, slot) \
     ((type)->group == NULL ? NULL : (type)->group->slot)
@@ -293,27 +225,6 @@ gentype_@name@(PyObject *m1)
 }
 /**end repeat**/
 
-#if !defined(NPY_PY3K)
-/**begin repeat
- *
- * #name = long, oct, hex#
- */
-static PyObject *
-gentype_@name@(PyObject *m1)
-{
-    PyObject *arr, *ret;
-
-    arr = PyArray_FromScalar(m1, NULL);
-    if (arr == NULL) {
-        return NULL;
-    }
-    ret = Py_TYPE(arr)->tp_as_number->nb_@name@(arr);
-    Py_DECREF(arr);
-    return ret;
-}
-/**end repeat**/
-#endif
-
 static int
 gentype_nonzero_number(PyObject *m1)
 {
@@ -324,11 +235,7 @@ gentype_nonzero_number(PyObject *m1)
     if (arr == NULL) {
         return -1;
     }
-#if defined(NPY_PY3K)
     ret = Py_TYPE(arr)->tp_as_number->nb_bool(arr);
-#else
-    ret = Py_TYPE(arr)->tp_as_number->nb_nonzero(arr);
-#endif
     Py_DECREF(arr);
     return ret;
 }
@@ -356,21 +263,9 @@ gentype_format(PyObject *self, PyObject *args)
     PyObject *format_spec;
     PyObject *obj, *ret;
 
-#if defined(NPY_PY3K)
     if (!PyArg_ParseTuple(args, "U:__format__", &format_spec)) {
         return NULL;
     }
-#else
-    if (!PyArg_ParseTuple(args, "O:__format__", &format_spec)) {
-        return NULL;
-    }
-
-    if (!PyUnicode_Check(format_spec) && !PyString_Check(format_spec)) {
-        PyErr_SetString(PyExc_TypeError,
-                "format must be a string");
-        return NULL;
-    }
-#endif
 
     /*
      * Convert to an appropriate Python type and call its format.
@@ -378,14 +273,10 @@ gentype_format(PyObject *self, PyObject *args)
      *       because it throws away precision.
      */
     if (Py_TYPE(self) == &PyBoolArrType_Type) {
-        obj = PyBool_FromLong(((PyBoolScalarObject *)self)->obval);
+        obj = PyBool_FromLong(PyArrayScalar_VAL(self, Bool));
     }
     else if (PyArray_IsScalar(self, Integer)) {
-#if defined(NPY_PY3K)
         obj = Py_TYPE(self)->tp_as_number->nb_int(self);
-#else
-        obj = Py_TYPE(self)->tp_as_number->nb_long(self);
-#endif
     }
     else if (PyArray_IsScalar(self, Floating)) {
         obj = Py_TYPE(self)->tp_as_number->nb_float(self);
@@ -454,6 +345,10 @@ format_@name@(@type@ val, npy_bool scientific,
  * over-ride repr and str of array-scalar strings and unicode to
  * remove NULL bytes and then call the corresponding functions
  * of string and unicode.
+ *
+ * FIXME:
+ *   is this really a good idea?
+ *   stop using Py_UNICODE here.
  */
 
 /**begin repeat
@@ -967,7 +862,7 @@ static PyObject *
 static PyObject *
 @name@type_@kind@(PyObject *self)
 {
-    return @name@type_@kind@_either(((Py@Name@ScalarObject *)self)->obval,
+    return @name@type_@kind@_either(PyArrayScalar_VAL(self, @Name@),
                                   TrimMode_LeaveOneZero, TrimMode_DptZeros, 0);
 }
 
@@ -975,7 +870,7 @@ static PyObject *
 c@name@type_@kind@(PyObject *self)
 {
     PyObject *rstr, *istr, *ret;
-    npy_c@name@ val = ((PyC@Name@ScalarObject *)self)->obval;
+    npy_c@name@ val = PyArrayScalar_VAL(self, C@Name@);
     TrimMode trim = TrimMode_DptZeros;
 
     if (npy_legacy_print_mode == 113) {
@@ -1039,7 +934,7 @@ c@name@type_@kind@(PyObject *self)
 static PyObject *
 halftype_@kind@(PyObject *self)
 {
-    npy_half val = ((PyHalfScalarObject *)self)->obval;
+    npy_half val = PyArrayScalar_VAL(self, Half);
     float floatval = npy_half_to_float(val);
     float absval;
 
@@ -1077,85 +972,29 @@ static PyObject *
     return npy_longdouble_to_PyLong(val);
 }
 
-#if !defined(NPY_PY3K)
-
-/**begin repeat1
- * #name = int, hex, oct#
- */
-static PyObject *
-@char@longdoubletype_@name@(PyObject *self)
-{
-    PyObject *ret;
-    PyObject *obj = @char@longdoubletype_long(self);
-    if (obj == NULL) {
-        return NULL;
-    }
-    ret = Py_TYPE(obj)->tp_as_number->nb_@name@(obj);
-    Py_DECREF(obj);
-    return ret;
-}
-/**end repeat1**/
-
-#endif /* !defined(NPY_PY3K) */
-
 /**end repeat**/
 
 static PyNumberMethods gentype_as_number = {
-    (binaryfunc)gentype_add,                     /*nb_add*/
-    (binaryfunc)gentype_subtract,                /*nb_subtract*/
-    (binaryfunc)gentype_multiply,                /*nb_multiply*/
-#if !defined(NPY_PY3K)
-    (binaryfunc)gentype_divide,                  /*nb_divide*/
-#endif
-    (binaryfunc)gentype_remainder,               /*nb_remainder*/
-    (binaryfunc)gentype_divmod,                  /*nb_divmod*/
-    (ternaryfunc)gentype_power,                  /*nb_power*/
-    (unaryfunc)gentype_negative,
-    (unaryfunc)gentype_positive,                 /*nb_pos*/
-    (unaryfunc)gentype_absolute,                 /*(unaryfunc)gentype_abs,*/
-    (inquiry)gentype_nonzero_number,             /*nb_nonzero*/
-    (unaryfunc)gentype_invert,                   /*nb_invert*/
-    (binaryfunc)gentype_lshift,                  /*nb_lshift*/
-    (binaryfunc)gentype_rshift,                  /*nb_rshift*/
-    (binaryfunc)gentype_and,                     /*nb_and*/
-    (binaryfunc)gentype_xor,                     /*nb_xor*/
-    (binaryfunc)gentype_or,                      /*nb_or*/
-#if !defined(NPY_PY3K)
-    0,                                           /*nb_coerce*/
-#endif
-    (unaryfunc)gentype_int,                      /*nb_int*/
-#if defined(NPY_PY3K)
-    0,                                           /*nb_reserved*/
-#else
-    (unaryfunc)gentype_long,                     /*nb_long*/
-#endif
-    (unaryfunc)gentype_float,                    /*nb_float*/
-#if !defined(NPY_PY3K)
-    (unaryfunc)gentype_oct,                      /*nb_oct*/
-    (unaryfunc)gentype_hex,                      /*nb_hex*/
-#endif
-    0,                                           /*inplace_add*/
-    0,                                           /*inplace_subtract*/
-    0,                                           /*inplace_multiply*/
-#if !defined(NPY_PY3K)
-    0,                                           /*inplace_divide*/
-#endif
-    0,                                           /*inplace_remainder*/
-    0,                                           /*inplace_power*/
-    0,                                           /*inplace_lshift*/
-    0,                                           /*inplace_rshift*/
-    0,                                           /*inplace_and*/
-    0,                                           /*inplace_xor*/
-    0,                                           /*inplace_or*/
-    (binaryfunc)gentype_floor_divide,            /*nb_floor_divide*/
-    (binaryfunc)gentype_true_divide,             /*nb_true_divide*/
-    0,                                           /*nb_inplace_floor_divide*/
-    0,                                           /*nb_inplace_true_divide*/
-    (unaryfunc)NULL,                             /*nb_index*/
-#if PY_VERSION_HEX >= 0x03050000
-    0,                                           /*np_matmul*/
-    0,                                           /*np_inplace_matmul*/
-#endif
+    .nb_add = (binaryfunc)gentype_add,
+    .nb_subtract = (binaryfunc)gentype_subtract,
+    .nb_multiply = (binaryfunc)gentype_multiply,
+    .nb_remainder = (binaryfunc)gentype_remainder,
+    .nb_divmod = (binaryfunc)gentype_divmod,
+    .nb_power = (ternaryfunc)gentype_power,
+    .nb_negative = (unaryfunc)gentype_negative,
+    .nb_positive = (unaryfunc)gentype_positive,
+    .nb_absolute = (unaryfunc)gentype_absolute,
+    .nb_bool = (inquiry)gentype_nonzero_number,
+    .nb_invert = (unaryfunc)gentype_invert,
+    .nb_lshift = (binaryfunc)gentype_lshift,
+    .nb_rshift = (binaryfunc)gentype_rshift,
+    .nb_and = (binaryfunc)gentype_and,
+    .nb_xor = (binaryfunc)gentype_xor,
+    .nb_or = (binaryfunc)gentype_or,
+    .nb_int = (unaryfunc)gentype_int,
+    .nb_float = (unaryfunc)gentype_float,
+    .nb_floor_divide = (binaryfunc)gentype_floor_divide,
+    .nb_true_divide = (binaryfunc)gentype_true_divide,
 };
 
 
@@ -1246,11 +1085,7 @@ inttype_denominator_get(PyObject *self)
 static PyObject *
 gentype_data_get(PyObject *self)
 {
-#if defined(NPY_PY3K)
     return PyMemoryView_FromObject(self);
-#else
-    return PyBuffer_FromObject(self, 0, Py_END_OF_BUFFER);
-#endif
 }
 
 
@@ -1263,11 +1098,6 @@ gentype_itemsize_get(PyObject *self)
 
     typecode = PyArray_DescrFromScalar(self);
     elsize = typecode->elsize;
-#ifndef Py_UNICODE_WIDE
-    if (typecode->type_num == NPY_UNICODE) {
-        elsize >>= 1;
-    }
-#endif
     ret = PyInt_FromLong((long) elsize);
     Py_DECREF(typecode);
     return ret;
@@ -1293,7 +1123,6 @@ gentype_sizeof(PyObject *self)
     return PyLong_FromSsize_t(nbytes);
 }
 
-#if PY_VERSION_HEX >= 0x03000000
 NPY_NO_EXPORT void
 gentype_struct_free(PyObject *ptr)
 {
@@ -1307,17 +1136,6 @@ gentype_struct_free(PyObject *ptr)
     PyArray_free(arrif->shape);
     PyArray_free(arrif);
 }
-#else
-NPY_NO_EXPORT void
-gentype_struct_free(void *ptr, void *arg)
-{
-    PyArrayInterface *arrif = (PyArrayInterface *)ptr;
-    Py_DECREF((PyObject *)arg);
-    Py_XDECREF(arrif->descr);
-    PyArray_free(arrif->shape);
-    PyArray_free(arrif);
-}
-#endif
 
 static PyObject *
 gentype_struct_get(PyObject *self)
@@ -1438,7 +1256,7 @@ gentype_real_get(PyObject *self)
         return ret;
     }
     else if (PyArray_IsScalar(self, Object)) {
-        PyObject *obj = ((PyObjectScalarObject *)self)->obval;
+        PyObject *obj = PyArrayScalar_VAL(self, Object);
         ret = PyObject_GetAttrString(obj, "real");
         if (ret != NULL) {
             return ret;
@@ -1463,7 +1281,7 @@ gentype_imag_get(PyObject *self)
         ret = PyArray_Scalar(ptr + typecode->elsize, typecode, NULL);
     }
     else if (PyArray_IsScalar(self, Object)) {
-        PyObject *obj = ((PyObjectScalarObject *)self)->obval;
+        PyObject *obj = PyArrayScalar_VAL(self, Object);
         PyArray_Descr *newtype;
         ret = PyObject_GetAttrString(obj, "imag");
         if (ret == NULL) {
@@ -1671,9 +1489,6 @@ gentype_itemset(PyObject *NPY_UNUSED(self), PyObject *NPY_UNUSED(args))
     return NULL;
 }
 
-static Py_ssize_t
-gentype_getreadbuf(PyObject *, Py_ssize_t, void **);
-
 static PyObject *
 gentype_byteswap(PyObject *self, PyObject *args, PyObject *kwds)
 {
@@ -1696,8 +1511,9 @@ gentype_byteswap(PyObject *self, PyObject *args, PyObject *kwds)
         PyObject *new;
         char *newmem;
 
-        gentype_getreadbuf(self, 0, (void **)&data);
         descr = PyArray_DescrFromScalar(self);
+        data = (void *)scalar_value(self, descr);
+
         newmem = PyObject_Malloc(descr->elsize);
         if (newmem == NULL) {
             Py_DECREF(descr);
@@ -1733,6 +1549,58 @@ gentype_@name@(PyObject *self, PyObject *args, PyObject *kwds)
 }
 /**end repeat**/
 
+
+/**begin repeat
+ * #name = integer, floating, complexfloating#
+ * #complex = 0, 0, 1#
+ */
+static PyObject *
+@name@type_dunder_round(PyObject *self, PyObject *args, PyObject *kwds)
+{
+    static char *kwlist[] = {"ndigits", NULL};
+    PyObject *ndigits = Py_None;
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:__round__", kwlist, &ndigits)) {
+        return NULL;
+    }
+
+#if @complex@
+    if (DEPRECATE("The Python built-in `round` is deprecated for complex "
+                  "scalars, and will raise a `TypeError` in a future release. "
+                  "Use `np.round` or `scalar.round` instead.") < 0) {
+        return NULL;
+    }
+#endif
+
+    PyObject *tup;
+    if (ndigits == Py_None) {
+        tup = PyTuple_Pack(0);
+    }
+    else {
+        tup = PyTuple_Pack(1, ndigits);
+    }
+
+    if (tup == NULL) {
+        return NULL;
+    }
+
+    PyObject *obj = gentype_round(self, tup, NULL);
+    Py_DECREF(tup);
+    if (obj == NULL) {
+        return NULL;
+    }
+
+#if !@complex@
+    if (ndigits == Py_None) {
+        PyObject *ret = PyNumber_Long(obj);
+        Py_DECREF(obj);
+        return ret;
+    }
+#endif
+
+    return obj;
+}
+/**end repeat**/
+
 static PyObject *
 voidtype_getfield(PyVoidScalarObject *self, PyObject *args, PyObject *kwds)
 {
@@ -1831,9 +1699,7 @@ static PyObject *
 gentype_reduce(PyObject *self, PyObject *NPY_UNUSED(args))
 {
     PyObject *ret = NULL, *obj = NULL, *mod = NULL;
-#if defined(NPY_PY3K)
     Py_buffer view;
-#endif
     const char *buffer;
     Py_ssize_t buflen;
 
@@ -1843,13 +1709,7 @@ gentype_reduce(PyObject *self, PyObject *NPY_UNUSED(args))
         return NULL;
     }
 
-#if defined(NPY_PY3K)
-    if (PyArray_IsScalar(self, Unicode)) {
-        /* Unicode on Python 3 does not expose the buffer interface */
-        buffer = PyUnicode_AS_DATA(self);
-        buflen = PyUnicode_GET_DATA_SIZE(self);
-    }
-    else if (PyObject_GetBuffer(self, &view, PyBUF_SIMPLE) >= 0) {
+    if (PyObject_GetBuffer(self, &view, PyBUF_SIMPLE) >= 0) {
         buffer = view.buf;
         buflen = view.len;
         /*
@@ -1865,12 +1725,6 @@ gentype_reduce(PyObject *self, PyObject *NPY_UNUSED(args))
         Py_DECREF(ret);
         return NULL;
     }
-#else
-    if (PyObject_AsReadBuffer(self, (const void **)&buffer, &buflen)<0) {
-        Py_DECREF(ret);
-        return NULL;
-    }
-#endif
 
     mod = PyImport_ImportModule("numpy.core._multiarray_umath");
     if (mod == NULL) {
@@ -1884,52 +1738,39 @@ gentype_reduce(PyObject *self, PyObject *NPY_UNUSED(args))
     PyTuple_SET_ITEM(ret, 0, obj);
     obj = PyObject_GetAttrString((PyObject *)self, "dtype");
     if (PyArray_IsScalar(self, Object)) {
-        mod = ((PyObjectScalarObject *)self)->obval;
-        PyTuple_SET_ITEM(ret, 1, Py_BuildValue("NO", obj, mod));
+        PyObject *val = PyArrayScalar_VAL(self, Object);
+        PyObject *tup = Py_BuildValue("NO", obj, val);
+        if (tup == NULL) {
+            return NULL;
+        }
+        PyTuple_SET_ITEM(ret, 1, tup);
     }
-    else {
-#ifndef Py_UNICODE_WIDE
-        /*
-         * We need to expand the buffer so that we always write
-         * UCS4 to disk for pickle of unicode scalars.
-         *
-         * This could be in a unicode_reduce function, but
-         * that would require re-factoring.
-         */
-        int alloc = 0;
-        char *tmp;
-        int newlen;
-
-        if (PyArray_IsScalar(self, Unicode)) {
-            tmp = PyArray_malloc(buflen*2);
-            if (tmp == NULL) {
-                Py_DECREF(ret);
-                return PyErr_NoMemory();
-            }
-            alloc = 1;
-            newlen = PyUCS2Buffer_AsUCS4((Py_UNICODE *)buffer,
-                    (npy_ucs4 *)tmp,
-                    buflen / 2, buflen / 2);
-            buflen = newlen*4;
-            buffer = tmp;
+    else if (obj && PyDataType_FLAGCHK((PyArray_Descr *)obj, NPY_LIST_PICKLE)) {
+        /* a structured dtype with an object in a field */
+        PyArrayObject *arr = (PyArrayObject *)PyArray_FromScalar(self, NULL);
+        if (arr == NULL) {
+            return NULL;
         }
-#endif
+        /* arr.item() */
+        PyObject *val = PyArray_GETITEM(arr, PyArray_DATA(arr));
+        Py_DECREF(arr);
+        if (val == NULL) {
+            return NULL;
+        }
+        PyObject *tup = Py_BuildValue("NN", obj, val);
+        if (tup == NULL) {
+            return NULL;
+        }
+        PyTuple_SET_ITEM(ret, 1, tup);
+    }
+    else {
         mod = PyBytes_FromStringAndSize(buffer, buflen);
         if (mod == NULL) {
             Py_DECREF(ret);
-#ifndef Py_UNICODE_WIDE
-            ret = NULL;
-            goto fail;
-#else
             return NULL;
-#endif
         }
         PyTuple_SET_ITEM(ret, 1,
                 Py_BuildValue("NN", obj, mod));
-#ifndef Py_UNICODE_WIDE
-fail:
-        if (alloc) PyArray_free((char *)buffer);
-#endif
     }
     return ret;
 }
@@ -2267,12 +2108,6 @@ static PyMethodDef gentype_methods[] = {
     {"round",
         (PyCFunction)gentype_round,
         METH_VARARGS | METH_KEYWORDS, NULL},
-#if defined(NPY_PY3K)
-    /* Hook for the round() builtin */
-    {"__round__",
-        (PyCFunction)gentype_round,
-        METH_VARARGS | METH_KEYWORDS, NULL},
-#endif
     /* For the format function */
     {"__format__",
         gentype_format,
@@ -2342,6 +2177,18 @@ static PyMethodDef @name@type_methods[] = {
 };
 /**end repeat**/
 
+/**begin repeat
+ * #name = integer,floating, complexfloating#
+ */
+static PyMethodDef @name@type_methods[] = {
+    /* Hook for the round() builtin */
+    {"__round__",
+        (PyCFunction)@name@type_dunder_round,
+        METH_VARARGS | METH_KEYWORDS, NULL},
+    {NULL, NULL, 0, NULL} /* sentinel */
+};
+/**end repeat**/
+
 /**begin repeat
  * #name = half,float,double,longdouble#
  */
@@ -2533,164 +2380,32 @@ fail:
 }
 
 static PyMappingMethods voidtype_as_mapping = {
-    (lenfunc)voidtype_length,                    /*mp_length*/
-    (binaryfunc)voidtype_subscript,              /*mp_subscript*/
-    (objobjargproc)voidtype_ass_subscript,       /*mp_ass_subscript*/
+    .mp_length = (lenfunc)voidtype_length,
+    .mp_subscript = (binaryfunc)voidtype_subscript,
+    .mp_ass_subscript = (objobjargproc)voidtype_ass_subscript,
 };
 
 
 static PySequenceMethods voidtype_as_sequence = {
-    (lenfunc)voidtype_length,                    /*sq_length*/
-    0,                                           /*sq_concat*/
-    0,                                           /*sq_repeat*/
-    (ssizeargfunc)voidtype_item,                 /*sq_item*/
-    0,                                           /*sq_slice*/
-    (ssizeobjargproc)voidtype_ass_item,          /*sq_ass_item*/
-    0,                                           /* ssq_ass_slice */
-    0,                                           /* sq_contains */
-    0,                                           /* sq_inplace_concat */
-    0,                                           /* sq_inplace_repeat */
+    .sq_length = (lenfunc)voidtype_length,
+    .sq_item = (ssizeargfunc)voidtype_item,
+    .sq_ass_item = (ssizeobjargproc)voidtype_ass_item,
 };
 
 
-static Py_ssize_t
-gentype_getreadbuf(PyObject *self, Py_ssize_t segment, void **ptrptr)
-{
-    int numbytes;
-    PyArray_Descr *outcode;
-
-    if (segment != 0) {
-        PyErr_SetString(PyExc_SystemError,
-                "Accessing non-existent array segment");
-        return -1;
-    }
-
-    outcode = PyArray_DescrFromScalar(self);
-    numbytes = outcode->elsize;
-    *ptrptr = (void *)scalar_value(self, outcode);
-
-#ifndef Py_UNICODE_WIDE
-    if (outcode->type_num == NPY_UNICODE) {
-        numbytes >>= 1;
-    }
-#endif
-    Py_DECREF(outcode);
-    return numbytes;
-}
-
-#if !defined(NPY_PY3K)
-static Py_ssize_t
-gentype_getsegcount(PyObject *self, Py_ssize_t *lenp)
-{
-    PyArray_Descr *outcode;
-
-    outcode = PyArray_DescrFromScalar(self);
-    if (lenp) {
-        *lenp = outcode->elsize;
-#ifndef Py_UNICODE_WIDE
-        if (outcode->type_num == NPY_UNICODE) {
-            *lenp >>= 1;
-        }
-#endif
-    }
-    Py_DECREF(outcode);
-    return 1;
-}
-
-static Py_ssize_t
-gentype_getcharbuf(PyObject *self, Py_ssize_t segment, constchar **ptrptr)
-{
-    if (PyArray_IsScalar(self, String) ||
-            PyArray_IsScalar(self, Unicode)) {
-        return gentype_getreadbuf(self, segment, (void **)ptrptr);
-    }
-    else {
-        PyErr_SetString(PyExc_TypeError,
-                "Non-character array cannot be interpreted "\
-                "as character buffer.");
-        return -1;
-    }
-}
-#endif /* !defined(NPY_PY3K) */
-
 static PyBufferProcs gentype_as_buffer = {
-#if !defined(NPY_PY3K)
-    gentype_getreadbuf,                          /* bf_getreadbuffer*/
-    NULL,                                        /* bf_getwritebuffer*/
-    gentype_getsegcount,                         /* bf_getsegcount*/
-    gentype_getcharbuf,                          /* bf_getcharbuffer*/
-#endif
-    gentype_getbuffer,                           /* bf_getbuffer */
-    NULL,                                        /* bf_releasebuffer */
+    .bf_getbuffer = gentype_getbuffer,
+    /* release buffer not defined (see buffer.c) */
 };
 
 
-#if defined(NPY_PY3K)
 #define BASEFLAGS Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE
 #define LEAFFLAGS  Py_TPFLAGS_DEFAULT
-#else
-#define BASEFLAGS Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | Py_TPFLAGS_CHECKTYPES
-#define LEAFFLAGS  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES
-#endif
 
 NPY_NO_EXPORT PyTypeObject PyGenericArrType_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.generic",                            /* tp_name*/
-    sizeof(PyObject),                           /* tp_basicsize*/
-    0,                                          /* tp_itemsize */
-    /* methods */
-    0,                                          /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    0,                                          /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.generic",
+    .tp_basicsize = sizeof(PyObject),
 };
 
 static void
@@ -2709,183 +2424,163 @@ void_dealloc(PyVoidScalarObject *v)
 static void
 object_arrtype_dealloc(PyObject *v)
 {
-    Py_XDECREF(((PyObjectScalarObject *)v)->obval);
+    Py_XDECREF(PyArrayScalar_VAL(v, Object));
     Py_TYPE(v)->tp_free(v);
 }
 
-/*
- * string and unicode inherit from Python Type first and so GET_ITEM
- * is different to get to the Python Type.
- *
- * ok is a work-around for a bug in complex_new that doesn't allocate
- *  memory from the sub-types memory allocator.
- */
-
-#define _WORK(num)  \
-    if (type->tp_bases && (PyTuple_GET_SIZE(type->tp_bases)==2)) { \
-        PyTypeObject *sup; \
-        /* We are inheriting from a Python type as well so \
-           give it first dibs on conversion */ \
-        sup = (PyTypeObject *)PyTuple_GET_ITEM(type->tp_bases, num); \
-        /* Prevent recursion */ \
-        if (thisfunc != sup->tp_new) { \
-            robj = sup->tp_new(type, args, kwds); \
-            if (robj != NULL) goto finish;        \
-            if (PyTuple_GET_SIZE(args)!=1) return NULL; \
-            PyErr_Clear(); \
-        } \
-        /* now do default conversion */ \
-    }
-
-#define _WORK1 _WORK(1)
-#define _WORKz _WORK(0)
-#define _WORK0
+static void
+unicode_arrtype_dealloc(PyObject *v)
+{
+    /* note: may be null if it was never requested */
+    PyMem_Free(PyArrayScalar_VAL(v, Unicode));
+    /* delegate to the base class */
+    PyUnicode_Type.tp_dealloc(v);
+}
 
 /**begin repeat
  * #name = byte, short, int, long, longlong, ubyte, ushort, uint, ulong,
  *         ulonglong, half, float, double, longdouble, cfloat, cdouble,
- *         clongdouble, string, unicode, object#
+ *         clongdouble, string, unicode#
  * #Name = Byte, Short, Int, Long, LongLong, UByte, UShort, UInt, ULong,
  *         ULongLong, Half, Float, Double, LongDouble, CFloat, CDouble,
- *         CLongDouble, String, Unicode, Object#
+ *         CLongDouble, String, Unicode#
  * #TYPE = BYTE, SHORT, INT, LONG, LONGLONG, UBYTE, USHORT, UINT, ULONG,
  *         ULONGLONG, HALF, FLOAT, DOUBLE, LONGDOUBLE, CFLOAT, CDOUBLE,
- *         CLONGDOUBLE, STRING, UNICODE, OBJECT#
- * #work = 0,0,1,1,1,0,0,0,0,0,0,0,1,0,0,0,0,z,z,0#
- * #default = 0*17,1*2,2#
+ *         CLONGDOUBLE, STRING, UNICODE#
  */
 
-#define _NPY_UNUSED2_1
-#define _NPY_UNUSED2_z
-#define _NPY_UNUSED2_0 NPY_UNUSED
-#define _NPY_UNUSED1_0
-#define _NPY_UNUSED1_1
-#define _NPY_UNUSED1_2 NPY_UNUSED
+/* used as a pattern for testing token equality */
+#define _@TYPE@_IS_@TYPE@
 
 static PyObject *
-@name@_arrtype_new(PyTypeObject *_NPY_UNUSED1_@default@(type), PyObject *args, PyObject *_NPY_UNUSED2_@work@(kwds))
+@name@_arrtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
-    PyObject *obj = NULL;
-    PyObject *robj;
-    PyArrayObject *arr;
-    PyArray_Descr *typecode = NULL;
-#if (@work@ != 0) || (@default@ == 1)
-    void *thisfunc = (void *)@name@_arrtype_new;
+    /* allow base-class (if any) to do conversion */
+#if defined(_@TYPE@_IS_UNICODE)
+    PyObject *from_superclass = PyUnicode_Type.tp_new(type, args, kwds);
+#elif defined(_@TYPE@_IS_STRING)
+    PyObject *from_superclass = PyBytes_Type.tp_new(type, args, kwds);
+#elif defined(_@TYPE@_IS_DOUBLE)
+    PyObject *from_superclass = PyFloat_Type.tp_new(type, args, kwds);
+#endif
+#if defined(_@TYPE@_IS_UNICODE) || defined(_@TYPE@_IS_STRING) || defined(_@TYPE@_IS_DOUBLE)
+    if (from_superclass == NULL) {
+        /* don't clear the exception unless numpy can handle the arguments */
+        if (PyTuple_GET_SIZE(args) != 1 || (kwds && PyDict_Size(kwds) != 0)) {
+            return NULL;
+        }
+        PyErr_Clear();
+    }
+    else {
+#if defined(_@TYPE@_IS_UNICODE)
+        PyArrayScalar_VAL(from_superclass, Unicode) = NULL;
 #endif
-#if !(@default@ == 2)
-    int itemsize;
-    void *dest, *src;
+        return from_superclass;
+    }
 #endif
 
-    /*
-     * allow base-class (if any) to do conversion
-     * If successful, this will jump to finish:
-     */
-    _WORK@work@
-
     /* TODO: include type name in error message, which is not @name@ */
-    if (!PyArg_ParseTuple(args, "|O", &obj)) {
+    PyObject *obj = NULL;
+    char *kwnames[] = {"", NULL};  /* positional-only */
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwnames, &obj)) {
         return NULL;
     }
-    typecode = PyArray_DescrFromType(NPY_@TYPE@);
+    PyArray_Descr *typecode = PyArray_DescrFromType(NPY_@TYPE@);
     if (typecode == NULL) {
         return NULL;
     }
-    /*
-     * typecode is new reference and stolen by
-     * PyArray_FromAny but not PyArray_Scalar
-     */
     if (obj == NULL) {
-#if @default@ == 0
-        robj = PyArray_Scalar(NULL, typecode, NULL);
+        PyObject *robj = PyArray_Scalar(NULL, typecode, NULL);
+        Py_DECREF(typecode);
         if (robj == NULL) {
-            Py_DECREF(typecode);
             return NULL;
         }
-        memset(&((Py@Name@ScalarObject *)robj)->obval, 0, sizeof(npy_@name@));
-#elif @default@ == 1
-        robj = PyArray_Scalar(NULL, typecode, NULL);
-#elif @default@ == 2
-        Py_INCREF(Py_None);
-        robj = Py_None;
+#if !defined(_@TYPE@_IS_STRING) && !defined(_@TYPE@_IS_UNICODE)
+        memset(&PyArrayScalar_VAL(robj, @Name@), 0, sizeof(npy_@name@));
 #endif
-        Py_DECREF(typecode);
-        goto finish;
+        return robj;
     }
 
-    /*
-     * It is expected at this point that robj is a PyArrayScalar
-     * (even for Object Data Type)
-     */
-    arr = (PyArrayObject *)PyArray_FromAny(obj, typecode,
-                                    0, 0, NPY_ARRAY_FORCECAST, NULL);
-    if ((arr == NULL) || (PyArray_NDIM(arr) > 0)) {
+    /* PyArray_FromAny steals a reference, reclaim it before it's gone */
+    Py_INCREF(typecode);
+    PyArrayObject *arr = (PyArrayObject *)PyArray_FromAny(
+            obj, typecode, 0, 0, NPY_ARRAY_FORCECAST, NULL);
+    if (arr == NULL) {
+        Py_DECREF(typecode);
+        return NULL;
+    }
+    if (PyArray_NDIM(arr) > 0) {
+        Py_DECREF(typecode);
         return (PyObject *)arr;
     }
-    /* 0-d array */
-    robj = PyArray_ToScalar(PyArray_DATA(arr), arr);
+
+    /* Convert the 0-d array to a scalar*/
+    PyObject *robj = PyArray_ToScalar(PyArray_DATA(arr), arr);
     Py_DECREF(arr);
 
-finish:
-    /*
-     * In OBJECT case, robj is no longer a
-     * PyArrayScalar at this point but the
-     * remaining code assumes it is
-     */
-#if @default@ == 2
-    return robj;
-#else
-    /* Normal return */
-    if ((robj == NULL) || (Py_TYPE(robj) == type)) {
+    if (robj == NULL || Py_TYPE(robj) == type) {
+        Py_DECREF(typecode);
         return robj;
     }
 
     /*
-     * This return path occurs when the requested type is not created
-     * but another scalar object is created instead (i.e. when
-     * the base-class does the conversion in _WORK macro)
+     * `typecode` does not contain any subclass information, as it was thrown
+     * out by the call to `PyArray_DescrFromType` - we need to add this back.
+     *
+     * FIXME[gh-15467]: This branch is also hit for the "shadowed" builtin
+     * types like `longdouble` (which on platforms where they are the same size
+     * is shadowed by `double`), because `PyArray_FromAny` returns the
+     * shadowing type rather than the requested one.
      */
 
     /* Need to allocate new type and copy data-area over */
+    int itemsize;
     if (type->tp_itemsize) {
         itemsize = PyBytes_GET_SIZE(robj);
     }
     else {
         itemsize = 0;
     }
-    obj = type->tp_alloc(type, itemsize);
-    if (obj == NULL) {
+    PyObject *new_obj = type->tp_alloc(type, itemsize);
+    if (new_obj == NULL) {
         Py_DECREF(robj);
+        Py_DECREF(typecode);
         return NULL;
     }
-    /* typecode will be NULL */
-    typecode = PyArray_DescrFromType(NPY_@TYPE@);
-    dest = scalar_value(obj, typecode);
-    src = scalar_value(robj, typecode);
+    void *dest = scalar_value(new_obj, typecode);
+    void *src = scalar_value(robj, typecode);
     Py_DECREF(typecode);
-#if @default@ == 0
-    *((npy_@name@ *)dest) = *((npy_@name@ *)src);
-#elif @default@ == 1 /* unicode and strings */
+#if defined(_@TYPE@_IS_STRING) || defined(_@TYPE@_IS_UNICODE)
     if (itemsize == 0) { /* unicode */
-#if PY_VERSION_HEX >= 0x03030000
         itemsize = PyUnicode_GetLength(robj) * PyUnicode_KIND(robj);
-#else
-        itemsize = ((PyUnicodeObject *)robj)->length * sizeof(Py_UNICODE);
-#endif
     }
     memcpy(dest, src, itemsize);
-    /* @default@ == 2 won't get here */
+#else
+    *((npy_@name@ *)dest) = *((npy_@name@ *)src);
 #endif
     Py_DECREF(robj);
-    return obj;
-#endif
+    return new_obj;
 }
+#undef _@TYPE@_IS_@TYPE@
+
 /**end repeat**/
 
-#undef _WORK1
-#undef _WORKz
-#undef _WORK0
-#undef _WORK
+static PyObject *
+object_arrtype_new(PyTypeObject *NPY_UNUSED(type), PyObject *args, PyObject *kwds)
+{
+    PyObject *obj = Py_None;
+    char *kwnames[] = {"", NULL};  /* positional-only */
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:object_", kwnames, &obj)) {
+        return NULL;
+    }
+    PyArray_Descr *typecode = PyArray_DescrFromType(NPY_OBJECT);
+    if (typecode == NULL) {
+        return NULL;
+    }
+    PyArrayObject *arr = (PyArrayObject *)PyArray_FromAny(obj, typecode,
+                                    0, 0, NPY_ARRAY_FORCECAST, NULL);
+    return PyArray_Return(arr);
+}
 
 /**begin repeat
  * #name = datetime, timedelta#
@@ -2900,8 +2595,8 @@ static PyObject *
     PyObject *obj = NULL, *meta_obj = NULL;
     Py@Name@ScalarObject *ret;
 
-    /* TODO: include type name in error message, which is not @name@ */
-    if (!PyArg_ParseTuple(args, "|OO", &obj, &meta_obj)) {
+    char *kwnames[] = {"", "", NULL};  /* positional-only */
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwnames, &obj, &meta_obj)) {
         return NULL;
     }
 
@@ -2954,12 +2649,13 @@ static PyObject *
 
 /* bool->tp_new only returns Py_True or Py_False */
 static PyObject *
-bool_arrtype_new(PyTypeObject *NPY_UNUSED(type), PyObject *args, PyObject *NPY_UNUSED(kwds))
+bool_arrtype_new(PyTypeObject *NPY_UNUSED(type), PyObject *args, PyObject *kwds)
 {
     PyObject *obj = NULL;
     PyArrayObject *arr;
 
-    if (!PyArg_ParseTuple(args, "|O:bool_", &obj)) {
+    char *kwnames[] = {"", NULL};  /* positional-only */
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|O:bool_", kwnames, &obj)) {
         return NULL;
     }
     if (obj == NULL) {
@@ -3057,74 +2753,20 @@ bool_index(PyObject *a)
 
 /* Arithmetic methods -- only so we can override &, |, ^. */
 NPY_NO_EXPORT PyNumberMethods bool_arrtype_as_number = {
-    0,                                           /* nb_add */
-    0,                                           /* nb_subtract */
-    0,                                           /* nb_multiply */
-#if defined(NPY_PY3K)
-#else
-    0,                                           /* nb_divide */
-#endif
-    0,                                           /* nb_remainder */
-    0,                                           /* nb_divmod */
-    0,                                           /* nb_power */
-    0,                                           /* nb_negative */
-    0,                                           /* nb_positive */
-    0,                                           /* nb_absolute */
-    (inquiry)bool_arrtype_nonzero,               /* nb_nonzero / nb_bool */
-    0,                                           /* nb_invert */
-    0,                                           /* nb_lshift */
-    0,                                           /* nb_rshift */
-    (binaryfunc)bool_arrtype_and,                /* nb_and */
-    (binaryfunc)bool_arrtype_xor,                /* nb_xor */
-    (binaryfunc)bool_arrtype_or,                 /* nb_or */
-#if defined(NPY_PY3K)
-#else
-    0,                                           /* nb_coerce */
-#endif
-    0,                                           /* nb_int */
-#if defined(NPY_PY3K)
-    0,                                           /* nb_reserved */
-#else
-    0,                                           /* nb_long */
-#endif
-    0,                                           /* nb_float */
-#if defined(NPY_PY3K)
-#else
-    0,                                           /* nb_oct */
-    0,                                           /* nb_hex */
-#endif
-    /* Added in release 2.0 */
-    0,                                           /* nb_inplace_add */
-    0,                                           /* nb_inplace_subtract */
-    0,                                           /* nb_inplace_multiply */
-#if defined(NPY_PY3K)
-#else
-    0,                                           /* nb_inplace_divide */
-#endif
-    0,                                           /* nb_inplace_remainder */
-    0,                                           /* nb_inplace_power */
-    0,                                           /* nb_inplace_lshift */
-    0,                                           /* nb_inplace_rshift */
-    0,                                           /* nb_inplace_and */
-    0,                                           /* nb_inplace_xor */
-    0,                                           /* nb_inplace_or */
-    /* Added in release 2.2 */
-    /* The following require the Py_TPFLAGS_HAVE_CLASS flag */
-    0,                                           /* nb_floor_divide */
-    0,                                           /* nb_true_divide */
-    0,                                           /* nb_inplace_floor_divide */
-    0,                                           /* nb_inplace_true_divide */
-    /* Added in release 2.5 */
-    0,                                           /* nb_index */
+    .nb_bool = (inquiry)bool_arrtype_nonzero,
+    .nb_and = (binaryfunc)bool_arrtype_and,
+    .nb_xor = (binaryfunc)bool_arrtype_xor,
+    .nb_or = (binaryfunc)bool_arrtype_or,
 };
 
 static PyObject *
-void_arrtype_new(PyTypeObject *type, PyObject *args, PyObject *NPY_UNUSED(kwds))
+void_arrtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
 {
     PyObject *obj, *arr;
     PyObject *new = NULL;
 
-    if (!PyArg_ParseTuple(args, "O:void", &obj)) {
+    char *kwnames[] = {"", NULL};  /* positional-only */
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O:void", kwnames, &obj)) {
         return NULL;
     }
     /*
@@ -3136,11 +2778,7 @@ void_arrtype_new(PyTypeObject *type, PyObject *args, PyObject *NPY_UNUSED(kwds))
             (PyArray_Check(obj) &&
                      PyArray_NDIM((PyArrayObject *)obj)==0 &&
                      PyArray_ISINTEGER((PyArrayObject *)obj))) {
-#if defined(NPY_PY3K)
         new = Py_TYPE(obj)->tp_as_number->nb_int(obj);
-#else
-        new = Py_TYPE(obj)->tp_as_number->nb_long(obj);
-#endif
     }
     if (new && PyLong_Check(new)) {
         PyObject *ret;
@@ -3164,7 +2802,7 @@ void_arrtype_new(PyTypeObject *type, PyObject *args, PyObject *NPY_UNUSED(kwds))
             return PyErr_NoMemory();
         }
         ((PyVoidScalarObject *)ret)->obval = destptr;
-        Py_SIZE((PyVoidScalarObject *)ret) = (int) memu;
+        Py_SET_SIZE((PyVoidScalarObject *)ret, (int) memu);
         ((PyVoidScalarObject *)ret)->descr =
             PyArray_DescrNewFromType(NPY_VOID);
         ((PyVoidScalarObject *)ret)->descr->elsize = (int) memu;
@@ -3188,7 +2826,7 @@ void_arrtype_new(PyTypeObject *type, PyObject *args, PyObject *NPY_UNUSED(kwds))
 static npy_hash_t
 @lname@_arrtype_hash(PyObject *obj)
 {
-    return (npy_hash_t)(((Py@name@ScalarObject *)obj)->obval);
+    return (npy_hash_t)(PyArrayScalar_VAL(obj, @name@));
 }
 /**end repeat**/
 
@@ -3199,7 +2837,7 @@ static npy_hash_t
 static npy_hash_t
 @lname@_arrtype_hash(PyObject *obj)
 {
-    npy_hash_t x = (npy_hash_t)(((Py@name@ScalarObject *)obj)->obval);
+    npy_hash_t x = (npy_hash_t)(PyArrayScalar_VAL(obj, @name@));
     if (x == -1) {
         x = -2;
     }
@@ -3210,34 +2848,30 @@ static npy_hash_t
 static npy_hash_t
 ulong_arrtype_hash(PyObject *obj)
 {
-    PyObject * l = PyLong_FromUnsignedLong(((PyULongScalarObject*)obj)->obval);
+    PyObject * l = PyLong_FromUnsignedLong(PyArrayScalar_VAL(obj, ULong));
     npy_hash_t x = PyObject_Hash(l);
     Py_DECREF(l);
     return x;
 }
 
-#if (NPY_SIZEOF_INT != NPY_SIZEOF_LONG) || defined(NPY_PY3K)
 static npy_hash_t
 int_arrtype_hash(PyObject *obj)
 {
-    npy_hash_t x = (npy_hash_t)(((PyIntScalarObject *)obj)->obval);
+    npy_hash_t x = (npy_hash_t)(PyArrayScalar_VAL(obj, Int));
     if (x == -1) {
         x = -2;
     }
     return x;
 }
-#endif
 
-#if defined(NPY_PY3K)
 static npy_hash_t
 long_arrtype_hash(PyObject *obj)
 {
-    PyObject * l = PyLong_FromLong(((PyLongScalarObject*)obj)->obval);
+    PyObject * l = PyLong_FromLong(PyArrayScalar_VAL(obj, Long));
     npy_hash_t x = PyObject_Hash(l);
     Py_DECREF(l);
     return x;
 }
-#endif
 
 /**begin repeat
  * #char = ,u#
@@ -3248,7 +2882,7 @@ static NPY_INLINE npy_hash_t
 @char@longlong_arrtype_hash(PyObject *obj)
 {
     PyObject * l = PyLong_From@Word@LongLong(
-                                 ((Py@Char@LongLongScalarObject*)obj)->obval);
+                                 PyArrayScalar_VAL(obj, @Char@LongLong));
     npy_hash_t x = PyObject_Hash(l);
     Py_DECREF(l);
     return x;
@@ -3264,7 +2898,7 @@ static NPY_INLINE npy_hash_t
 static npy_hash_t
 @lname@_arrtype_hash(PyObject *obj)
 {
-    npy_hash_t x = (npy_hash_t)(((Py@name@ScalarObject *)obj)->obval);
+    npy_hash_t x = (npy_hash_t)(PyArrayScalar_VAL(obj, @name@));
     if (x == -1) {
         x = -2;
     }
@@ -3275,7 +2909,7 @@ static npy_hash_t
 @lname@_arrtype_hash(PyObject *obj)
 {
     npy_hash_t y;
-    npy_longlong x = (((Py@name@ScalarObject *)obj)->obval);
+    npy_longlong x = (PyArrayScalar_VAL(obj, @name@));
 
     if ((x <= LONG_MAX)) {
         y = (npy_hash_t) x;
@@ -3308,7 +2942,7 @@ static npy_hash_t
 static npy_hash_t
 @lname@_arrtype_hash(PyObject *obj)
 {
-    return _Py_HashDouble((double) ((Py@name@ScalarObject *)obj)->obval);
+    return _Py_HashDouble((double) PyArrayScalar_VAL(obj, @name@));
 }
 
 /* borrowed from complex_hash */
@@ -3317,13 +2951,13 @@ c@lname@_arrtype_hash(PyObject *obj)
 {
     npy_hash_t hashreal, hashimag, combined;
     hashreal = _Py_HashDouble((double)
-            (((PyC@name@ScalarObject *)obj)->obval).real);
+            PyArrayScalar_VAL(obj, C@name@).real);
 
     if (hashreal == -1) {
         return -1;
     }
     hashimag = _Py_HashDouble((double)
-            (((PyC@name@ScalarObject *)obj)->obval).imag);
+            PyArrayScalar_VAL(obj, C@name@).imag);
     if (hashimag == -1) {
         return -1;
     }
@@ -3338,13 +2972,13 @@ c@lname@_arrtype_hash(PyObject *obj)
 static npy_hash_t
 half_arrtype_hash(PyObject *obj)
 {
-    return _Py_HashDouble(npy_half_to_double(((PyHalfScalarObject *)obj)->obval));
+    return _Py_HashDouble(npy_half_to_double(PyArrayScalar_VAL(obj, Half)));
 }
 
 static npy_hash_t
 object_arrtype_hash(PyObject *obj)
 {
-    return PyObject_Hash(((PyObjectScalarObject *)obj)->obval);
+    return PyObject_Hash(PyArrayScalar_VAL(obj, Object));
 }
 
 /* we used to just hash the pointer */
@@ -3459,90 +3093,20 @@ object_arrtype_inplace_repeat(PyObjectScalarObject *self, Py_ssize_t count)
 }
 
 static PySequenceMethods object_arrtype_as_sequence = {
-    (lenfunc)object_arrtype_length,              /*sq_length*/
-    (binaryfunc)object_arrtype_concat,           /*sq_concat*/
-    (ssizeargfunc)object_arrtype_repeat,         /*sq_repeat*/
-    0,                                           /*sq_item*/
-    0,                                           /*sq_slice*/
-    0,                                           /* sq_ass_item */
-    0,                                           /* sq_ass_slice */
-    (objobjproc)object_arrtype_contains,         /* sq_contains */
-    (binaryfunc)object_arrtype_inplace_concat,   /* sq_inplace_concat */
-    (ssizeargfunc)object_arrtype_inplace_repeat, /* sq_inplace_repeat */
+    .sq_length = (lenfunc)object_arrtype_length,
+    .sq_concat = (binaryfunc)object_arrtype_concat,
+    .sq_repeat = (ssizeargfunc)object_arrtype_repeat,
+    .sq_contains = (objobjproc)object_arrtype_contains,
+    .sq_inplace_concat = (binaryfunc)object_arrtype_inplace_concat,
+    .sq_inplace_repeat = (ssizeargfunc)object_arrtype_inplace_repeat,
 };
 
 static PyMappingMethods object_arrtype_as_mapping = {
-    (lenfunc)object_arrtype_length,
-    (binaryfunc)object_arrtype_subscript,
-    (objobjargproc)object_arrtype_ass_subscript,
+    .mp_length = (lenfunc)object_arrtype_length,
+    .mp_subscript = (binaryfunc)object_arrtype_subscript,
+    .mp_ass_subscript = (objobjargproc)object_arrtype_ass_subscript,
 };
 
-#if !defined(NPY_PY3K)
-static Py_ssize_t
-object_arrtype_getsegcount(PyObjectScalarObject *self, Py_ssize_t *lenp)
-{
-    Py_ssize_t newlen;
-    int cnt;
-    PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer;
-
-    if (pb == NULL ||
-            pb->bf_getsegcount == NULL ||
-            (cnt = (*pb->bf_getsegcount)(self->obval, &newlen)) != 1) {
-        return 0;
-    }
-    if (lenp) {
-        *lenp = newlen;
-    }
-    return cnt;
-}
-
-static Py_ssize_t
-object_arrtype_getreadbuf(PyObjectScalarObject *self, Py_ssize_t segment, void **ptrptr)
-{
-    PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer;
-
-    if (pb == NULL ||
-            pb->bf_getreadbuffer == NULL ||
-            pb->bf_getsegcount == NULL) {
-        PyErr_SetString(PyExc_TypeError,
-                "expected a readable buffer object");
-        return -1;
-    }
-    return (*pb->bf_getreadbuffer)(self->obval, segment, ptrptr);
-}
-
-static Py_ssize_t
-object_arrtype_getwritebuf(PyObjectScalarObject *self, Py_ssize_t segment, void **ptrptr)
-{
-    PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer;
-
-    if (pb == NULL ||
-            pb->bf_getwritebuffer == NULL ||
-            pb->bf_getsegcount == NULL) {
-        PyErr_SetString(PyExc_TypeError,
-                "expected a writeable buffer object");
-        return -1;
-    }
-    return (*pb->bf_getwritebuffer)(self->obval, segment, ptrptr);
-}
-
-static Py_ssize_t
-object_arrtype_getcharbuf(PyObjectScalarObject *self, Py_ssize_t segment,
-                          constchar **ptrptr)
-{
-    PyBufferProcs *pb = Py_TYPE(self->obval)->tp_as_buffer;
-
-    if (pb == NULL ||
-            pb->bf_getcharbuffer == NULL ||
-            pb->bf_getsegcount == NULL) {
-        PyErr_SetString(PyExc_TypeError,
-                "expected a character buffer object");
-        return -1;
-    }
-    return (*pb->bf_getcharbuffer)(self->obval, segment, ptrptr);
-}
-#endif
-
 static int
 object_arrtype_getbuffer(PyObjectScalarObject *self, Py_buffer *view, int flags)
 {
@@ -3570,14 +3134,8 @@ object_arrtype_releasebuffer(PyObjectScalarObject *self, Py_buffer *view)
 }
 
 static PyBufferProcs object_arrtype_as_buffer = {
-#if !defined(NPY_PY3K)
-    (readbufferproc)object_arrtype_getreadbuf,
-    (writebufferproc)object_arrtype_getwritebuf,
-    (segcountproc)object_arrtype_getsegcount,
-    (charbufferproc)object_arrtype_getcharbuf,
-#endif
-    (getbufferproc)object_arrtype_getbuffer,
-    (releasebufferproc)object_arrtype_releasebuffer,
+    .bf_getbuffer = (getbufferproc)object_arrtype_getbuffer,
+    .bf_releasebuffer = (releasebufferproc)object_arrtype_releasebuffer,
 };
 
 static PyObject *
@@ -3587,62 +3145,16 @@ object_arrtype_call(PyObjectScalarObject *obj, PyObject *args, PyObject *kwds)
 }
 
 NPY_NO_EXPORT PyTypeObject PyObjectArrType_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.object_",                            /* tp_name*/
-    sizeof(PyObjectScalarObject),               /* tp_basicsize*/
-    0,                                          /* tp_itemsize */
-    (destructor)object_arrtype_dealloc,         /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    &object_arrtype_as_sequence,                /* tp_as_sequence */
-    &object_arrtype_as_mapping,                 /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    (ternaryfunc)object_arrtype_call,           /* tp_call */
-    0,                                          /* tp_str */
-    (getattrofunc)object_arrtype_getattro,      /* tp_getattro */
-    (setattrofunc)object_arrtype_setattro,      /* tp_setattro */
-    &object_arrtype_as_buffer,                  /* tp_as_buffer */
-    0,                                          /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.object_",
+    .tp_basicsize = sizeof(PyObjectScalarObject),
+    .tp_dealloc = (destructor)object_arrtype_dealloc,
+    .tp_as_sequence = &object_arrtype_as_sequence,
+    .tp_as_mapping = &object_arrtype_as_mapping,
+    .tp_call = (ternaryfunc)object_arrtype_call,
+    .tp_getattro = (getattrofunc)object_arrtype_getattro,
+    .tp_setattro = (setattrofunc)object_arrtype_setattro,
+    .tp_as_buffer = &object_arrtype_as_buffer,
 };
 
 static PyObject *
@@ -3671,13 +3183,8 @@ gen_arrtype_subscript(PyObject *self, PyObject *key)
 
 #define NAME_bool "bool"
 #define NAME_void "void"
-#if defined(NPY_PY3K)
 #define NAME_string "bytes"
 #define NAME_unicode "str"
-#else
-#define NAME_string "string"
-#define NAME_unicode "unicode"
-#endif
 
 /**begin repeat
  * #name = bool, string, unicode, void#
@@ -3685,62 +3192,9 @@ gen_arrtype_subscript(PyObject *self, PyObject *key)
  * #ex = _,_,_,#
  */
 NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy." NAME_@name@ "@ex@",                /* tp_name*/
-    sizeof(Py@NAME@ScalarObject),               /* tp_basicsize*/
-    0,                                          /* tp_itemsize */
-    0,                                          /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    0,                                          /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy." NAME_@name@ "@ex@",
+    .tp_basicsize = sizeof(Py@NAME@ScalarObject),
 };
 /**end repeat**/
 
@@ -3774,72 +3228,18 @@ NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = {
 #define _THIS_SIZE "256"
 #endif
 NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.@name@" _THIS_SIZE,                  /* tp_name*/
-    sizeof(Py@NAME@ScalarObject),               /* tp_basicsize*/
-    0,                                          /* tp_itemsize */
-    0,                                          /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call */
-    0,                                          /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    0,                                          /* tp_flags */
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.@name@" _THIS_SIZE,
+    .tp_basicsize = sizeof(Py@NAME@ScalarObject),
 };
 
+
 #undef _THIS_SIZE
 /**end repeat**/
 
 
 static PyMappingMethods gentype_as_mapping = {
-    NULL,
-    (binaryfunc)gen_arrtype_subscript,
-    NULL
+    .mp_subscript = (binaryfunc)gen_arrtype_subscript,
 };
 
 
@@ -3865,62 +3265,10 @@ static PyMappingMethods gentype_as_mapping = {
 #endif
 
 NPY_NO_EXPORT PyTypeObject Py@NAME@ArrType_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(0, 0)
-#else
-    PyObject_HEAD_INIT(0)
-    0,                                          /* ob_size */
-#endif
-    "numpy.@name@" _THIS_SIZE,                  /* tp_name*/
-    sizeof(Py@NAME@ScalarObject),               /* tp_basicsize*/
-    0,                                          /* tp_itemsize*/
-    0,                                          /* tp_dealloc*/
-    0,                                          /* tp_print*/
-    0,                                          /* tp_getattr*/
-    0,                                          /* tp_setattr*/
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    0,                                          /* tp_repr*/
-    0,                                          /* tp_as_number*/
-    0,                                          /* tp_as_sequence*/
-    0,                                          /* tp_as_mapping*/
-    0,                                          /* tp_hash */
-    0,                                          /* tp_call*/
-    0,                                          /* tp_str*/
-    0,                                          /* tp_getattro*/
-    0,                                          /* tp_setattro*/
-    0,                                          /* tp_as_buffer*/
-    Py_TPFLAGS_DEFAULT,                         /* tp_flags*/
-    0,                                          /* tp_doc */
-    0,                                          /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    0,                                          /* tp_methods */
-    0,                                          /* tp_members */
-    0,                                          /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.@name@" _THIS_SIZE,
+    .tp_basicsize = sizeof(Py@NAME@ScalarObject),
+    .tp_flags = Py_TPFLAGS_DEFAULT,
 };
 #undef _THIS_SIZE
 
@@ -4253,38 +3601,6 @@ initialize_casting_tables(void)
     }
 }
 
-#ifndef NPY_PY3K
-/*
- * In python2, the `float` and `complex` types still implement the obsolete
- * "tp_print" method, which uses CPython's float-printing routines to print the
- * float.  Numpy's float_/cfloat inherit from Python float/complex, but
- * override its tp_repr and tp_str methods. In order to avoid an inconsistency
- * with the inherited tp_print, we need to override it too.
- *
- * In python3 the tp_print method is reserved/unused.
- */
-static int
-doubletype_print(PyObject *o, FILE *fp, int flags)
-{
-    int ret;
-    PyObject *to_print;
-    if (flags & Py_PRINT_RAW) {
-        to_print = PyObject_Str(o);
-    }
-    else {
-        to_print = PyObject_Repr(o);
-    }
-
-    if (to_print == NULL) {
-        return -1;
-    }
-
-    ret = PyObject_Print(to_print, fp, Py_PRINT_RAW);
-    Py_DECREF(to_print);
-    return ret;
-}
-#endif
-
 static PyNumberMethods longdoubletype_as_number;
 static PyNumberMethods clongdoubletype_as_number;
 static void init_basetypes(void);
@@ -4336,12 +3652,6 @@ initialize_numeric_types(void)
 
     /**end repeat**/
 
-#ifndef NPY_PY3K
-    PyDoubleArrType_Type.tp_print = &doubletype_print;
-    PyCDoubleArrType_Type.tp_print = &doubletype_print;
-#endif
-
-
     PyBoolArrType_Type.tp_as_number->nb_index = (unaryfunc)bool_index;
 
     PyStringArrType_Type.tp_alloc = NULL;
@@ -4388,6 +3698,9 @@ initialize_numeric_types(void)
 
     /**end repeat**/
 
+    PyUnicodeArrType_Type.tp_dealloc = unicode_arrtype_dealloc;
+    PyUnicodeArrType_Type.tp_as_buffer = &gentype_as_buffer;
+
     /**begin repeat
      * #name = bool, byte, short, ubyte, ushort, uint, ulong, ulonglong,
      *         half, float, longdouble, cfloat, clongdouble, void, object,
@@ -4402,8 +3715,8 @@ initialize_numeric_types(void)
     /**end repeat**/
 
     /**begin repeat
-     * #name = cfloat, clongdouble#
-     * #NAME = CFloat, CLongDouble#
+     * #name = cfloat, clongdouble, floating, integer, complexfloating#
+     * #NAME = CFloat, CLongDouble, Floating, Integer, ComplexFloating#
      */
 
     Py@NAME@ArrType_Type.tp_methods = @name@type_methods;
@@ -4419,20 +3732,14 @@ initialize_numeric_types(void)
 
     /**end repeat**/
 
-#if (NPY_SIZEOF_INT != NPY_SIZEOF_LONG) || defined(NPY_PY3K)
     /* We won't be inheriting from Python Int type. */
     PyIntArrType_Type.tp_hash = int_arrtype_hash;
-#endif
 
-#if defined(NPY_PY3K)
     /* We won't be inheriting from Python Int type. */
     PyLongArrType_Type.tp_hash = long_arrtype_hash;
-#endif
 
-#if (NPY_SIZEOF_LONG != NPY_SIZEOF_LONGLONG) || defined(NPY_PY3K)
     /* We won't be inheriting from Python Int type. */
     PyLongLongArrType_Type.tp_hash = longlong_arrtype_hash;
-#endif
 
     /**begin repeat
      * #name = repr, str#
@@ -4475,14 +3782,7 @@ initialize_numeric_types(void)
      * does not return a normal Python type
      */
     @char@longdoubletype_as_number.nb_float = @char@longdoubletype_float;
-#if defined(NPY_PY3K)
     @char@longdoubletype_as_number.nb_int  = @char@longdoubletype_long;
-#else
-    @char@longdoubletype_as_number.nb_int  = @char@longdoubletype_int;
-    @char@longdoubletype_as_number.nb_long = @char@longdoubletype_long;
-    @char@longdoubletype_as_number.nb_hex  = @char@longdoubletype_hex;
-    @char@longdoubletype_as_number.nb_oct  = @char@longdoubletype_oct;
-#endif
 
     Py@CHAR@LongDoubleArrType_Type.tp_as_number = &@char@longdoubletype_as_number;
     Py@CHAR@LongDoubleArrType_Type.tp_repr = @char@longdoubletype_repr;
index 83b188128aafb179dda8122c23b62f5c08f61268..861f2c943e987f01cf52f7b605f35662777dd30b 100644 (file)
@@ -19,13 +19,8 @@ initialize_casting_tables(void);
 NPY_NO_EXPORT void
 initialize_numeric_types(void);
 
-#if PY_VERSION_HEX >= 0x03000000
 NPY_NO_EXPORT void
 gentype_struct_free(PyObject *ptr);
-#else
-NPY_NO_EXPORT void
-gentype_struct_free(void *ptr, void *arg);
-#endif
 
 NPY_NO_EXPORT int
 is_anyscalar_exact(PyObject *obj);
index 4e31f003b3be3978921ef77fa48f4e64ef25f089..30507112d13869c6c9edc31e6eaabe1041a39e53 100644 (file)
@@ -317,7 +317,7 @@ _putzero(char *optr, PyObject *zero, PyArray_Descr *dtype)
         int offset;
         Py_ssize_t pos = 0;
         while (PyDict_Next(dtype->fields, &pos, &key, &value)) {
-            if NPY_TITLE_KEY(key, value) {
+            if (NPY_TITLE_KEY(key, value)) {
                 continue;
             }
             if (!PyArg_ParseTuple(value, "Oi|O", &new, &offset, &title)) {
@@ -981,7 +981,7 @@ PyArray_Flatten(PyArrayObject *a, NPY_ORDER order)
 
 /* See shape.h for parameters documentation */
 NPY_NO_EXPORT PyObject *
-build_shape_string(npy_intp n, npy_intp *vals)
+build_shape_string(npy_intp n, npy_intp const *vals)
 {
     npy_intp i;
     PyObject *ret, *tmp;
index 0451a463e5fab8172a593b335f5fa10e5574f173..d252925569baf8a9b077c4d426b0075b83403a2c 100644 (file)
@@ -6,7 +6,7 @@
  * A negative value in 'vals' gets interpreted as newaxis.
  */
 NPY_NO_EXPORT PyObject *
-build_shape_string(npy_intp n, npy_intp *vals);
+build_shape_string(npy_intp n, npy_intp const *vals);
 
 /*
  * Creates a sorted stride perm matching the KEEPORDER behavior
index 495d897b23e4a582489abfe61fff0f9f4ba4cd58..363cbdba2d012692d0bb04b8b0aa779aad297b9c 100644 (file)
@@ -64,7 +64,7 @@ extend_str(char **strp, Py_ssize_t n, Py_ssize_t *maxp)
 
 static int
 dump_data(char **string, Py_ssize_t *n, Py_ssize_t *max_n, char *data, int nd,
-          npy_intp *dimensions, npy_intp *strides, PyArrayObject* self)
+          npy_intp const *dimensions, npy_intp const *strides, PyArrayObject* self)
 {
     PyObject *op = NULL, *sp = NULL;
     char *ostring;
@@ -168,15 +168,13 @@ array_repr_builtin(PyArrayObject *self, int repr)
 NPY_NO_EXPORT PyObject *
 array_repr(PyArrayObject *self)
 {
-    PyObject *s, *arglist;
+    PyObject *s;
 
     if (PyArray_ReprFunction == NULL) {
         s = array_repr_builtin(self, 1);
     }
     else {
-        arglist = Py_BuildValue("(O)", self);
-        s = PyEval_CallObject(PyArray_ReprFunction, arglist);
-        Py_DECREF(arglist);
+        s = PyObject_CallFunctionObjArgs(PyArray_ReprFunction, self, NULL);
     }
     return s;
 }
@@ -185,15 +183,13 @@ array_repr(PyArrayObject *self)
 NPY_NO_EXPORT PyObject *
 array_str(PyArrayObject *self)
 {
-    PyObject *s, *arglist;
+    PyObject *s;
 
     if (PyArray_StrFunction == NULL) {
         s = array_repr_builtin(self, 0);
     }
     else {
-        arglist = Py_BuildValue("(O)", self);
-        s = PyEval_CallObject(PyArray_StrFunction, arglist);
-        Py_DECREF(arglist);
+        s = PyObject_CallFunctionObjArgs(PyArray_StrFunction, self, NULL);
     }
     return s;
 }
@@ -226,34 +222,3 @@ array_format(PyArrayObject *self, PyObject *args)
     }
 }
 
-#ifndef NPY_PY3K
-
-NPY_NO_EXPORT PyObject *
-array_unicode(PyArrayObject *self)
-{
-    PyObject *uni;
-
-    if (PyArray_NDIM(self) == 0) {
-        PyObject *item = PyArray_ToScalar(PyArray_DATA(self), self);
-        if (item == NULL){
-            return NULL;
-        }
-
-        /* defer to invoking `unicode` on the scalar */
-        uni = PyObject_CallFunctionObjArgs(
-            (PyObject *)&PyUnicode_Type, item, NULL);
-        Py_DECREF(item);
-    }
-    else {
-        /* Do what unicode(self) would normally do */
-        PyObject *str = PyObject_Str((PyObject *)self);
-        if (str == NULL){
-            return NULL;
-        }
-        uni = PyUnicode_FromObject(str);
-        Py_DECREF(str);
-    }
-    return uni;
-}
-
-#endif
index 7e869d926da999e953fc9dbf9fabc7a1794ae324..5dd661a20dc404690cf3ebf3346fb5396c78bcf0 100644 (file)
@@ -13,9 +13,4 @@ array_str(PyArrayObject *self);
 NPY_NO_EXPORT PyObject *
 array_format(PyArrayObject *self, PyObject *args);
 
-#ifndef NPY_PY3K
-    NPY_NO_EXPORT PyObject *
-    array_unicode(PyArrayObject *self);
-#endif
-
 #endif
index 14c4f27cbdce1d36affdc2652f9b22304d01e254..b0563b3c0ef87b1e4a7e51fbf55c39e46e32289a 100644 (file)
@@ -5,8 +5,10 @@
  */
 #include "typeinfo.h"
 
-/* In python 2, this is not exported from Python.h */
+#if (defined(PYPY_VERSION_NUM) && (PYPY_VERSION_NUM <= 0x07030000))
+/* PyPy issue 3160 */
 #include <structseq.h>
+#endif
 
 #define NPY_NO_DEPRECATED_API NPY_API_VERSION
 #define _MULTIARRAYMODULE
@@ -58,11 +60,7 @@ PyArray_typeinfo(
     PyObject *entry = PyStructSequence_New(&PyArray_typeinfoType);
     if (entry == NULL)
         return NULL;
-#if defined(NPY_PY3K)
     PyStructSequence_SET_ITEM(entry, 0, Py_BuildValue("C", typechar));
-#else
-    PyStructSequence_SET_ITEM(entry, 0, Py_BuildValue("c", typechar));
-#endif
     PyStructSequence_SET_ITEM(entry, 1, Py_BuildValue("i", typenum));
     PyStructSequence_SET_ITEM(entry, 2, Py_BuildValue("i", nbits));
     PyStructSequence_SET_ITEM(entry, 3, Py_BuildValue("i", align));
@@ -84,11 +82,7 @@ PyArray_typeinforanged(
     PyObject *entry = PyStructSequence_New(&PyArray_typeinforangedType);
     if (entry == NULL)
         return NULL;
-#if defined(NPY_PY3K)
     PyStructSequence_SET_ITEM(entry, 0, Py_BuildValue("C", typechar));
-#else
-    PyStructSequence_SET_ITEM(entry, 0, Py_BuildValue("c", typechar));
-#endif
     PyStructSequence_SET_ITEM(entry, 1, Py_BuildValue("i", typenum));
     PyStructSequence_SET_ITEM(entry, 2, Py_BuildValue("i", nbits));
     PyStructSequence_SET_ITEM(entry, 3, Py_BuildValue("i", align));
@@ -104,10 +98,8 @@ PyArray_typeinforanged(
     return entry;
 }
 
-/* Python version only needed for backport to 2.7 */
-#if (PY_VERSION_HEX < 0x03040000) \
-    || (defined(PYPY_VERSION_NUM) && (PYPY_VERSION_NUM < 0x07020000))
-
+/* Python version needed for older PyPy */
+#if (defined(PYPY_VERSION_NUM) && (PYPY_VERSION_NUM < 0x07020000))
     static int
     PyStructSequence_InitType2(PyTypeObject *type, PyStructSequence_Desc *desc) {
         PyStructSequence_InitType(type, desc);
index 2e8fb514f337a5efc9a7f78820affaba94b489ee..997467b4d677dfabd4efa3cf65e5f39be1d6670a 100644 (file)
@@ -128,6 +128,44 @@ PyArray_InitArrFuncs(PyArray_ArrFuncs *f)
     f->cancastto = NULL;
 }
 
+
+static int
+test_deprecated_arrfuncs_members(PyArray_ArrFuncs *f) {
+    /* NumPy 1.19, 2020-01-15 */
+    if (f->fastputmask != NULL) {
+        if (DEPRECATE(
+                "The ->f->fastputmask member of custom dtypes is ignored; "
+                "setting it may be an error in the future.\n"
+                "The custom dtype you are using must be revised, but "
+                "results will not be affected.") < 0) {
+            return -1;
+        }
+    }
+    /* NumPy 1.19, 2020-01-15 */
+    if (f->fasttake != NULL) {
+        if (DEPRECATE(
+                "The ->f->fastputmask member of custom dtypes is ignored; "
+                "setting it may be an error in the future.\n"
+                "The custom dtype you are using must be revised, but "
+                "results will not be affected.") < 0) {
+            return -1;
+        }
+    }
+    /* NumPy 1.19, 2020-01-15 */
+    if (f->fastclip != NULL) {
+        /* fastclip was already deprecated at execution time in 1.17. */
+        if (DEPRECATE(
+                "The ->f->fastclip member of custom dtypes is deprecated; "
+                "setting it will be an error in the future.\n"
+                "The custom dtype you are using must be changed to use "
+                "PyUFunc_RegisterLoopForDescr to attach a custom loop to "
+                "np.core.umath.clip, np.minimum, and np.maximum") < 0) {
+            return -1;
+        }
+    }
+    return 0;
+}
+
 /*
   returns typenum to associate with this type >=NPY_USERDEF.
   needs the userdecrs table and PyArray_NUMUSER variables
@@ -176,6 +214,11 @@ PyArray_RegisterDataType(PyArray_Descr *descr)
         PyErr_SetString(PyExc_ValueError, "missing typeobject");
         return -1;
     }
+
+    if (test_deprecated_arrfuncs_members(f) < 0) {
+        return -1;
+    }
+
     userdescrs = realloc(userdescrs,
                          (NPY_NUMUSERTYPES+1)*sizeof(void *));
     if (userdescrs == NULL) {
index 84af86009752b98efde4dff82b4bb346756685b2..cbaa11e43c3180c55f7223ca9c15da47c9475ca2 100644 (file)
@@ -115,10 +115,7 @@ npy_half npy_half_nextafter(npy_half x, npy_half y)
 {
     npy_half ret;
 
-    if (!npy_half_isfinite(x) || npy_half_isnan(y)) {
-#if NPY_HALF_GENERATE_INVALID
-        npy_set_floatstatus_invalid();
-#endif
+    if (npy_half_isnan(x) || npy_half_isnan(y)) {
         ret = NPY_HALF_NAN;
     } else if (npy_half_eq_nonan(x, y)) {
         ret = x;
@@ -138,7 +135,7 @@ npy_half npy_half_nextafter(npy_half x, npy_half y)
         }
     }
 #if NPY_HALF_GENERATE_OVERFLOW
-    if (npy_half_isinf(ret)) {
+    if (npy_half_isinf(ret) && npy_half_isfinite(x)) {
         npy_set_floatstatus_overflow();
     }
 #endif
index 551a9c6329b750798943f4a18bb3162e1c97ad45..d22a5c507750e2bff57dde6a58dd7599369240d5 100644 (file)
@@ -14,7 +14,7 @@ static PyMethodDef TestMethods[] = {
 
 
 static void
-inplace_add(char **args, npy_intp *dimensions, npy_intp *steps, void *data)
+inplace_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *data)
 {
     npy_intp i;
     npy_intp n = dimensions[0];
@@ -39,7 +39,6 @@ static char types[2] = {NPY_LONG, NPY_LONG};
 
 static void *data[1] = {NULL};
 
-#if defined(NPY_PY3K)
 static struct PyModuleDef moduledef = {
     PyModuleDef_HEAD_INIT,
     "_operand_flag_tests",
@@ -52,22 +51,12 @@ static struct PyModuleDef moduledef = {
     NULL
 };
 
-#define RETVAL m
 PyMODINIT_FUNC PyInit__operand_flag_tests(void)
 {
-#else
-#define RETVAL
-PyMODINIT_FUNC init_operand_flag_tests(void)
-{
-#endif
     PyObject *m = NULL;
     PyObject *ufunc;
 
-#if defined(NPY_PY3K)
     m = PyModule_Create(&moduledef);
-#else
-    m = Py_InitModule("_operand_flag_tests", TestMethods);
-#endif
     if (m == NULL) {
         goto fail;
     }
@@ -87,19 +76,16 @@ PyMODINIT_FUNC init_operand_flag_tests(void)
     ((PyUFuncObject*)ufunc)->iter_flags = NPY_ITER_REDUCE_OK;
     PyModule_AddObject(m, "inplace_add", (PyObject*)ufunc);
 
-    return RETVAL;
+    return m;
 
 fail:
     if (!PyErr_Occurred()) {
         PyErr_SetString(PyExc_RuntimeError,
                         "cannot load _operand_flag_tests module.");
     }
-#if defined(NPY_PY3K)
     if (m) {
         Py_DECREF(m);
         m = NULL;
     }
-#endif
-    return RETVAL;
-
+    return m;
 }
index 615e395c748632bee5fc2852a4062a17d334dc64..13e33d0a51e4727977ed23b5d4c8472a1f8ce006 100644 (file)
@@ -609,9 +609,6 @@ static PyNumberMethods pyrational_as_number = {
     pyrational_add,          /* nb_add */
     pyrational_subtract,     /* nb_subtract */
     pyrational_multiply,     /* nb_multiply */
-#if PY_MAJOR_VERSION < 3
-    pyrational_divide,       /* nb_divide */
-#endif
     pyrational_remainder,    /* nb_remainder */
     0,                       /* nb_divmod */
     0,                       /* nb_power */
@@ -625,27 +622,13 @@ static PyNumberMethods pyrational_as_number = {
     0,                       /* nb_and */
     0,                       /* nb_xor */
     0,                       /* nb_or */
-#if PY_MAJOR_VERSION < 3
-    0,                       /* nb_coerce */
-#endif
     pyrational_int,          /* nb_int */
-#if PY_MAJOR_VERSION < 3
-    pyrational_int,          /* nb_long */
-#else
     0,                       /* reserved */
-#endif
     pyrational_float,        /* nb_float */
-#if PY_MAJOR_VERSION < 3
-    0,                       /* nb_oct */
-    0,                       /* nb_hex */
-#endif
 
     0,                       /* nb_inplace_add */
     0,                       /* nb_inplace_subtract */
     0,                       /* nb_inplace_multiply */
-#if PY_MAJOR_VERSION < 3
-    0,                       /* nb_inplace_divide */
-#endif
     0,                       /* nb_inplace_remainder */
     0,                       /* nb_inplace_power */
     0,                       /* nb_inplace_lshift */
@@ -678,12 +661,7 @@ static PyGetSetDef pyrational_getset[] = {
 };
 
 static PyTypeObject PyRational_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                        /* ob_size */
-#endif
     "rational",                               /* tp_name */
     sizeof(PyRational),                       /* tp_basicsize */
     0,                                        /* tp_itemsize */
@@ -691,11 +669,7 @@ static PyTypeObject PyRational_Type = {
     0,                                        /* tp_print */
     0,                                        /* tp_getattr */
     0,                                        /* tp_setattr */
-#if defined(NPY_PY3K)
     0,                                        /* tp_reserved */
-#else
-    0,                                        /* tp_compare */
-#endif
     pyrational_repr,                          /* tp_repr */
     &pyrational_as_number,                    /* tp_as_number */
     0,                                        /* tp_as_sequence */
@@ -962,8 +936,8 @@ DEFINE_CAST(npy_bool,rational,rational y = make_rational_int(x);)
 DEFINE_CAST(rational,npy_bool,npy_bool y = rational_nonzero(x);)
 
 #define BINARY_UFUNC(name,intype0,intype1,outtype,exp) \
-    void name(char** args, npy_intpdimensions, \
-              npy_intpsteps, void* data) { \
+    void name(char** args, npy_intp const *dimensions, \
+              npy_intp const *steps, void* data) { \
         npy_intp is0 = steps[0], is1 = steps[1], \
             os = steps[2], n = *dimensions; \
         char *i0 = args[0], *i1 = args[1], *o = args[2]; \
@@ -998,8 +972,8 @@ BINARY_UFUNC(gcd_ufunc,npy_int64,npy_int64,npy_int64,gcd(x,y))
 BINARY_UFUNC(lcm_ufunc,npy_int64,npy_int64,npy_int64,lcm(x,y))
 
 #define UNARY_UFUNC(name,type,exp) \
-    void rational_ufunc_##name(char** args, npy_intpdimensions, \
-                               npy_intpsteps, void* data) { \
+    void rational_ufunc_##name(char** args, npy_intp const *dimensions, \
+                               npy_intp const *steps, void* data) { \
         npy_intp is = steps[0], os = steps[1], n = *dimensions; \
         char *i = args[0], *o = args[1]; \
         int k; \
@@ -1022,7 +996,7 @@ UNARY_UFUNC(numerator,npy_int64,x.n)
 UNARY_UFUNC(denominator,npy_int64,d(x))
 
 static NPY_INLINE void
-rational_matrix_multiply(char **args, npy_intp *dimensions, npy_intp *steps)
+rational_matrix_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
     /* pointers to data for input and output arrays */
     char *ip1 = args[0];
@@ -1067,8 +1041,8 @@ rational_matrix_multiply(char **args, npy_intp *dimensions, npy_intp *steps)
 
 
 static void
-rational_gufunc_matrix_multiply(char **args, npy_intp *dimensions,
-                                npy_intp *steps, void *NPY_UNUSED(func))
+rational_gufunc_matrix_multiply(char **args, npy_intp const *dimensions,
+                                npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /* outer dimensions counter */
     npy_intp N_;
@@ -1092,8 +1066,8 @@ rational_gufunc_matrix_multiply(char **args, npy_intp *dimensions,
 
 
 static void
-rational_ufunc_test_add(char** args, npy_intpdimensions,
-                        npy_intpsteps, void* data) {
+rational_ufunc_test_add(char** args, npy_intp const *dimensions,
+                        npy_intp const *steps, void* data) {
     npy_intp is0 = steps[0], is1 = steps[1], os = steps[2], n = *dimensions;
     char *i0 = args[0], *i1 = args[1], *o = args[2];
     int k;
@@ -1108,8 +1082,8 @@ rational_ufunc_test_add(char** args, npy_intp* dimensions,
 
 
 static void
-rational_ufunc_test_add_rationals(char** args, npy_intpdimensions,
-                        npy_intpsteps, void* data) {
+rational_ufunc_test_add_rationals(char** args, npy_intp const *dimensions,
+                        npy_intp const *steps, void* data) {
     npy_intp is0 = steps[0], is1 = steps[1], os = steps[2], n = *dimensions;
     char *i0 = args[0], *i1 = args[1], *o = args[2];
     int k;
@@ -1126,7 +1100,6 @@ PyMethodDef module_methods[] = {
     {0} /* sentinel */
 };
 
-#if defined(NPY_PY3K)
 static struct PyModuleDef moduledef = {
     PyModuleDef_HEAD_INIT,
     "_rational_tests",
@@ -1138,16 +1111,8 @@ static struct PyModuleDef moduledef = {
     NULL,
     NULL
 };
-#endif
 
-#if defined(NPY_PY3K)
-#define RETVAL m
 PyMODINIT_FUNC PyInit__rational_tests(void) {
-#else
-#define RETVAL
-PyMODINIT_FUNC init_rational_tests(void) {
-#endif
-
     PyObject *m = NULL;
     PyObject* numpy_str;
     PyObject* numpy;
@@ -1193,7 +1158,7 @@ PyMODINIT_FUNC init_rational_tests(void) {
     npyrational_arrfuncs.fill = npyrational_fill;
     npyrational_arrfuncs.fillwithscalar = npyrational_fillwithscalar;
     /* Left undefined: scanfunc, fromstr, sort, argsort */
-    Py_TYPE(&npyrational_descr) = &PyArrayDescr_Type;
+    Py_SET_TYPE(&npyrational_descr, &PyArrayDescr_Type);
     npy_rational = PyArray_RegisterDataType(&npyrational_descr);
     if (npy_rational<0) {
         goto fail;
@@ -1292,11 +1257,7 @@ PyMODINIT_FUNC init_rational_tests(void) {
     REGISTER_UFUNC_UNARY(sign)
 
     /* Create module */
-#if defined(NPY_PY3K)
     m = PyModule_Create(&moduledef);
-#else
-    m = Py_InitModule("_rational_tests", module_methods);
-#endif
 
     if (!m) {
         goto fail;
@@ -1392,18 +1353,16 @@ PyMODINIT_FUNC init_rational_tests(void) {
     GCD_LCM_UFUNC(gcd,NPY_INT64,"greatest common denominator of two integers");
     GCD_LCM_UFUNC(lcm,NPY_INT64,"least common multiple of two integers");
 
-    return RETVAL;
+    return m;
 
 fail:
     if (!PyErr_Occurred()) {
         PyErr_SetString(PyExc_RuntimeError,
                         "cannot load _rational_tests module.");
     }
-#if defined(NPY_PY3K)
     if (m) {
         Py_DECREF(m);
         m = NULL;
     }
-#endif
-    return RETVAL;
+    return m;
 }
index 3eaac73e1d8d932865b06ae48c3d27220ed381c7..d602656c85e7d78ebedea6cf44e70a0d1eec7139 100644 (file)
  * docs.python.org .
  */
 
-static void add_uint64_triplet(char **args, npy_intp *dimensions,
-                            npy_intp* steps, void* data)
+static void add_uint64_triplet(char **args,
+                               npy_intp const *dimensions,
+                               npy_intp const* steps,
+                               void* data)
 {
     npy_intp i;
     npy_intp is1=steps[0];
@@ -100,7 +102,6 @@ static PyMethodDef StructUfuncTestMethods[] = {
     {NULL, NULL, 0, NULL}
 };
 
-#if defined(NPY_PY3K)
 static struct PyModuleDef moduledef = {
     PyModuleDef_HEAD_INIT,
     "_struct_ufunc_tests",
@@ -112,31 +113,18 @@ static struct PyModuleDef moduledef = {
     NULL,
     NULL
 };
-#endif
 
-#if defined(NPY_PY3K)
 PyMODINIT_FUNC PyInit__struct_ufunc_tests(void)
-#else
-PyMODINIT_FUNC init_struct_ufunc_tests(void)
-#endif
 {
     PyObject *m, *add_triplet, *d;
     PyObject *dtype_dict;
     PyArray_Descr *dtype;
     PyArray_Descr *dtypes[3];
 
-#if defined(NPY_PY3K)
     m = PyModule_Create(&moduledef);
-#else
-    m = Py_InitModule("_struct_ufunc_tests", StructUfuncTestMethods);
-#endif
 
     if (m == NULL) {
-#if defined(NPY_PY3K)
         return NULL;
-#else
-        return;
-#endif
     }
 
     import_array();
@@ -166,7 +154,5 @@ PyMODINIT_FUNC init_struct_ufunc_tests(void)
 
     PyDict_SetItemString(d, "add_triplet", add_triplet);
     Py_DECREF(add_triplet);
-#if defined(NPY_PY3K)
     return m;
-#endif
 }
index 6c3bcce7133a7daff2c7f1eab706964afa38a226..abc8d78c4f52b8c1d84bfd54d8ae158e1c895868 100644 (file)
@@ -71,7 +71,7 @@ char *inner1d_signature = "(i),(i)->()";
  */
 
 static void
-@TYPE@_inner1d(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_inner1d(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     INIT_OUTER_LOOP_3
     npy_intp di = dimensions[0];
@@ -106,7 +106,7 @@ char *innerwt_signature = "(i),(i),(i)->()";
  */
 
 static void
-@TYPE@_innerwt(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_innerwt(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     INIT_OUTER_LOOP_4
     npy_intp di = dimensions[0];
@@ -143,7 +143,7 @@ char *matmul_signature = "(m?,n),(n,p?)->(m?,p?)";
  */
 
 static void
-@TYPE@_matrix_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_matrix_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /* no BLAS is available */
     INIT_OUTER_LOOP_3
@@ -212,7 +212,7 @@ char *cross1d_signature = "(3),(3)->(3)";
  *        out[n, 2] = in1[n, 0]*in2[n, 1] - in1[n, 1]*in2[n, 0]
  */
 static void
-@TYPE@_cross1d(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_cross1d(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     INIT_OUTER_LOOP_3
     npy_intp is1=steps[0], is2=steps[1], os = steps[2];
@@ -252,7 +252,7 @@ char *euclidean_pdist_signature = "(n,d)->(p)";
  */
 
 static void
-@TYPE@_euclidean_pdist(char **args, npy_intp *dimensions, npy_intp *steps,
+@TYPE@_euclidean_pdist(char **args, npy_intp const *dimensions, npy_intp const *steps,
                        void *NPY_UNUSED(func))
 {
     INIT_OUTER_LOOP_2
@@ -308,7 +308,7 @@ char *cumsum_signature = "(i)->(i)";
 */
 
 static void
-@TYPE@_cumsum(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_cumsum(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     INIT_OUTER_LOOP_2
     npy_intp di = dimensions[0];
@@ -586,7 +586,6 @@ static PyMethodDef UMath_TestsMethods[] = {
     {NULL, NULL, 0, NULL}        /* Sentinel */
 };
 
-#if defined(NPY_PY3K)
 static struct PyModuleDef moduledef = {
         PyModuleDef_HEAD_INIT,
         "_umath_tests",
@@ -598,31 +597,26 @@ static struct PyModuleDef moduledef = {
         NULL,
         NULL
 };
-#endif
 
 /* Initialization function for the module */
-#if defined(NPY_PY3K)
-#define RETVAL(x) x
 PyMODINIT_FUNC PyInit__umath_tests(void) {
-#else
-#define RETVAL(x)
-PyMODINIT_FUNC init_umath_tests(void) {
-#endif
     PyObject *m;
     PyObject *d;
     PyObject *version;
 
-#if defined(NPY_PY3K)
     m = PyModule_Create(&moduledef);
-#else
-    m = Py_InitModule("_umath_tests", UMath_TestsMethods);
-#endif
     if (m == NULL) {
-        return RETVAL(NULL);
+        return NULL;
     }
 
     import_array();
+    if (PyErr_Occurred()) {
+        return NULL;
+    }
     import_ufunc();
+    if (PyErr_Occurred()) {
+        return NULL;
+    }
 
     d = PyModule_GetDict(m);
 
@@ -636,8 +630,8 @@ PyMODINIT_FUNC init_umath_tests(void) {
         PyErr_Print();
         PyErr_SetString(PyExc_RuntimeError,
                         "cannot load _umath_tests module.");
-        return RETVAL(NULL);
+        return NULL;
     }
 
-    return RETVAL(m);
+    return m;
 }
index 30fa3d2b35a3414ca3eb5e7dc055e10c3e95f4fe..9c4bac2d14d5b6839e84944670b97ef6e6f9ee30 100644 (file)
@@ -79,7 +79,7 @@
     _NPY_@name@_MIN(_NPY_@name@_MAX((x), (min)), (max))
 
 NPY_NO_EXPORT void
-@name@_clip(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@name@_clip(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (steps[1] == 0 && steps[2] == 0) {
         /* min and max are constant throughout the loop, the most common case */
index d77971ad79460475ab2b272061203354e91dd5a4..f16856cdfdd9945709d979bf837717f56d35980a 100644 (file)
@@ -12,7 +12,7 @@
  *         DATETIME, TIMEDELTA#
  */
 NPY_NO_EXPORT void
-@name@_clip(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@name@_clip(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat**/
 
 #endif
diff --git a/numpy/core/src/umath/cpuid.c b/numpy/core/src/umath/cpuid.c
deleted file mode 100644 (file)
index 72c6493..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#define _UMATHMODULE
-#define _MULTIARRAYMODULE
-#define NPY_NO_DEPRECATED_API NPY_API_VERSION
-
-#include <Python.h>
-
-#include "npy_config.h"
-
-#include "cpuid.h"
-
-#define XCR_XFEATURE_ENABLED_MASK 0x0
-#define XSTATE_SSE 0x2
-#define XSTATE_YMM 0x4
-#define XSTATE_ZMM 0x70
-
-/*
- * verify the OS supports avx instructions
- * it can be disabled in some OS, e.g. with the nosavex boot option of linux
- */
-static NPY_INLINE
-int os_avx_support(void)
-{
-#if HAVE_XGETBV
-    /*
-     * use bytes for xgetbv to avoid issues with compiler not knowing the
-     * instruction
-     */
-    unsigned int eax, edx;
-    unsigned int ecx = XCR_XFEATURE_ENABLED_MASK;
-    __asm__("xgetbv" : "=a" (eax), "=d" (edx) : "c" (ecx));
-    return (eax & (XSTATE_SSE | XSTATE_YMM)) == (XSTATE_SSE | XSTATE_YMM);
-#else
-    return 0;
-#endif
-}
-
-static NPY_INLINE
-int os_avx512_support(void)
-{
-#if HAVE_XGETBV
-    unsigned int eax, edx;
-    unsigned int ecx = XCR_XFEATURE_ENABLED_MASK;
-    unsigned int xcr0 = XSTATE_ZMM | XSTATE_YMM | XSTATE_SSE;
-    __asm__("xgetbv" : "=a" (eax), "=d" (edx) : "c" (ecx));
-    return (eax & xcr0) == xcr0;
-#else
-    return 0;
-#endif
-}
-
-static NPY_INLINE
-int cpu_supports_fma(void)
-{
-#ifdef __x86_64__
-    unsigned int feature = 0x01;
-    unsigned int a, b, c, d;
-    __asm__ volatile (
-        "cpuid"                                "\n\t"
-       : "=a" (a), "=b" (b), "=c" (c), "=d" (d)
-       : "a" (feature));
-    /*
-     * FMA is the 12th bit of ECX
-     */
-    return (c >> 12) & 1;
-#else
-    return 0;
-#endif
-}
-
-/*
- * Primitive cpu feature detect function
- * Currently only supports checking for avx on gcc compatible compilers.
- */
-NPY_NO_EXPORT int
-npy_cpu_supports(const char * feature)
-{
-#ifdef HAVE___BUILTIN_CPU_SUPPORTS
-    if (strcmp(feature, "avx512f") == 0) {
-#ifdef HAVE___BUILTIN_CPU_SUPPORTS_AVX512F
-        return __builtin_cpu_supports("avx512f") && os_avx512_support();
-#else
-        return 0;
-#endif
-    }
-    else if (strcmp(feature, "fma") == 0) {
-        return cpu_supports_fma() && __builtin_cpu_supports("avx2") && os_avx_support();
-    }
-    else if (strcmp(feature, "avx2") == 0) {
-        return __builtin_cpu_supports("avx2") && os_avx_support();
-    }
-    else if (strcmp(feature, "avx") == 0) {
-        return __builtin_cpu_supports("avx") && os_avx_support();
-    }
-#endif
-
-    return 0;
-}
diff --git a/numpy/core/src/umath/cpuid.h b/numpy/core/src/umath/cpuid.h
deleted file mode 100644 (file)
index 33702ed..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef _NPY_PRIVATE__CPUID_H_
-#define _NPY_PRIVATE__CPUID_H_
-
-#include <numpy/ndarraytypes.h>  /* for NPY_NO_EXPORT */
-
-NPY_NO_EXPORT int
-npy_cpu_supports(const char * feature);
-
-#endif
index aea1815e8c7d07f70d02b33baa6e99e8e4b6403f..3404a0c6afbd68ef828c1d885d944caf33f13451 100644 (file)
@@ -165,7 +165,7 @@ get_global_ext_obj(void)
         if (thedict == NULL) {
             thedict = PyEval_GetBuiltins();
         }
-        ref = PyDict_GetItem(thedict, npy_um_str_pyvals_name);
+        ref = PyDict_GetItemWithError(thedict, npy_um_str_pyvals_name);
 #if USE_USE_DEFAULTS==1
     }
 #endif
@@ -290,6 +290,9 @@ _check_ufunc_fperr(int errmask, PyObject *extobj, const char *ufunc_name) {
     /* Get error object globals */
     if (extobj == NULL) {
         extobj = get_global_ext_obj();
+        if (extobj == NULL && PyErr_Occurred()) {
+            return -1;
+        }
     }
     if (_extract_pyvals(extobj, ufunc_name,
                         NULL, NULL, &errobj) < 0) {
@@ -311,6 +314,9 @@ _get_bufsize_errmask(PyObject * extobj, const char *ufunc_name,
     /* Get the buffersize and errormask */
     if (extobj == NULL) {
         extobj = get_global_ext_obj();
+        if (extobj == NULL && PyErr_Occurred()) {
+            return -1;
+        }
     }
     if (_extract_pyvals(extobj, ufunc_name,
                         buffersize, errormask, NULL) < 0) {
index ae6d69a3e7cc397b97c39428a3e313c6ac51a364..74bf016436dd12299b337ea1c9b9b1d854bdedf7 100644 (file)
@@ -4,13 +4,17 @@
  * These expect to have access to the arguments of a typical ufunc loop,
  *
  *     char **args
- *     npy_intp *dimensions
- *     npy_intp *steps
+ *     npy_intp const *dimensions
+ *     npy_intp const *steps
  */
 #ifndef _NPY_UMATH_FAST_LOOP_MACROS_H_
 #define _NPY_UMATH_FAST_LOOP_MACROS_H_
 
-#include "simd.inc"
+static NPY_INLINE npy_uintp
+abs_ptrdiff(char *a, char *b)
+{
+    return (a > b) ? (a - b) : (b - a);
+}
 
 /**
  * Simple unoptimized loop macros that iterate over the ufunc arguments in
index 10ed66e50ef23fc46172f47ca250ece001d80978..273779ee8c42c2376dbb993cd00966d895f88655 100644 (file)
@@ -38,11 +38,7 @@ Py_reciprocal(PyObject *o)
     if (!one) {
         return NULL;
     }
-#if defined(NPY_PY3K)
     result = PyNumber_TrueDivide(one, o);
-#else
-    result = PyNumber_Divide(one, o);
-#endif
     Py_DECREF(one);
     return result;
 }
@@ -197,8 +193,7 @@ npy_ObjectGCD(PyObject *i1, PyObject *i2)
 {
     PyObject *gcd = NULL;
 
-    /* use math.gcd if available, and valid on the provided types */
-#if PY_VERSION_HEX >= 0x03050000
+    /* use math.gcd if valid on the provided types */
     {
         static PyObject *math_gcd_func = NULL;
 
@@ -213,7 +208,6 @@ npy_ObjectGCD(PyObject *i1, PyObject *i2)
         /* silence errors, and fall back on pure-python gcd */
         PyErr_Clear();
     }
-#endif
 
     /* otherwise, use our internal one, written in python */
     {
@@ -360,9 +354,9 @@ nc_exp2@c@(@ctype@ *x, @ctype@ *r)
 static void
 nc_expm1@c@(@ctype@ *x, @ctype@ *r)
 {
-    @ftype@ a = npy_exp@c@(x->real);
-    r->real = a*npy_cos@c@(x->imag) - 1.0@c@;
-    r->imag = a*npy_sin@c@(x->imag);
+    @ftype@ a = npy_sin@c@(x->imag / 2);
+    r->real = npy_expm1@c@(x->real) * npy_cos@c@(x->imag) - 2 * a * a;
+    r->imag = npy_exp@c@(x->real) * npy_sin@c@(x->imag);
     return;
 }
 
index 8a2e5bc40f14247415762a91bd35c313d009d4b3..a59a9acf5aef36313bcb3a4f91ddbb44b568099b 100644 (file)
@@ -38,6 +38,9 @@
 #define NPY_MAX_SIMD_SIZE 1024
 #endif
 
+/** Provides the various *_LOOP macros */
+#include "fast_loop_macros.h"
+
 /*
  * include vectorized functions and dispatchers
  * this file is safe to include also for generic builds
  */
 #include "simd.inc"
 
-/** Provides the various *_LOOP macros */
-#include "fast_loop_macros.h"
-
-
 /******************************************************************************
  **                          GENERIC FLOAT LOOPS                             **
  *****************************************************************************/
@@ -63,7 +62,7 @@
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_@c@_@c@(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_@c@_@c@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     typedef @type@ func_type(@type@);
     func_type *f = (func_type *)func;
@@ -75,7 +74,7 @@ PyUFunc_@c@_@c@(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_@c@@c@_@c@(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_@c@@c@_@c@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     typedef @type@ func_type(@type@, @type@);
     func_type *f = (func_type *)func;
@@ -101,7 +100,7 @@ PyUFunc_@c@@c@_@c@(char **args, npy_intp *dimensions, npy_intp *steps, void *fun
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_@c1@_@c1@_As_@c2@_@c2@(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_@c1@_@c1@_As_@c2@_@c2@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     typedef @type2@ func_type(@type2@);
     func_type *f = (func_type *)func;
@@ -112,7 +111,7 @@ PyUFunc_@c1@_@c1@_As_@c2@_@c2@(char **args, npy_intp *dimensions, npy_intp *step
 }
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_@c1@@c1@_@c1@_As_@c2@@c2@_@c2@(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_@c1@@c1@_@c1@_As_@c2@@c2@_@c2@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     typedef @type2@ func_type(@type2@, @type2@);
     func_type *f = (func_type *)func;
@@ -137,7 +136,7 @@ PyUFunc_@c1@@c1@_@c1@_As_@c2@@c2@_@c2@(char **args, npy_intp *dimensions, npy_in
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_@c@_@c@(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_@c@_@c@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     typedef void func_type(@type@ *, @type@ *);
     func_type *f = (func_type *)func;
@@ -150,7 +149,7 @@ PyUFunc_@c@_@c@(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_@c@@c@_@c@(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_@c@@c@_@c@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     typedef void func_type(@type@ *, @type@ *, @type@ *);
     func_type *f = (func_type *)func;
@@ -167,7 +166,7 @@ PyUFunc_@c@@c@_@c@(char **args, npy_intp *dimensions, npy_intp *steps, void *fun
 /* indirect loops with casting */
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_F_F_As_D_D(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_F_F_As_D_D(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     typedef void func_type(npy_cdouble *, npy_cdouble *);
     func_type *f = (func_type *)func;
@@ -183,7 +182,7 @@ PyUFunc_F_F_As_D_D(char **args, npy_intp *dimensions, npy_intp *steps, void *fun
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_FF_F_As_DD_D(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_FF_F_As_DD_D(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     typedef void func_type(npy_cdouble *, npy_cdouble *, npy_cdouble *);
     func_type *f = (func_type *)func;
@@ -206,7 +205,7 @@ PyUFunc_FF_F_As_DD_D(char **args, npy_intp *dimensions, npy_intp *steps, void *f
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_O_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_O_O(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     unaryfunc f = (unaryfunc)func;
     UNARY_LOOP {
@@ -223,13 +222,9 @@ PyUFunc_O_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_O_O_method(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_O_O_method(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     char *meth = (char *)func;
-    PyObject *tup = PyTuple_New(0);
-    if (tup == NULL) {
-        return;
-    }
     UNARY_LOOP {
         PyObject *in1 = *(PyObject **)ip1;
         PyObject **out = (PyObject **)op1;
@@ -248,25 +243,22 @@ PyUFunc_O_O_method(char **args, npy_intp *dimensions, npy_intp *steps, void *fun
                          "type %s which has no callable %s method",
                          i, type->tp_name, meth);
             npy_PyErr_ChainExceptionsCause(exc, val, tb);
-            Py_DECREF(tup);
             Py_XDECREF(func);
             return;
         }
-        ret = PyObject_Call(func, tup, NULL);
+        ret = PyObject_CallObject(func, NULL);
         Py_DECREF(func);
         if (ret == NULL) {
-            Py_DECREF(tup);
             return;
         }
         Py_XDECREF(*out);
         *out = ret;
     }
-    Py_DECREF(tup);
 }
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_OO_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_OO_O(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     binaryfunc f = (binaryfunc)func;
     BINARY_LOOP {
@@ -283,7 +275,7 @@ PyUFunc_OO_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
 }
 
 NPY_NO_EXPORT void
-PyUFunc_OOO_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_OOO_O(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     ternaryfunc f = (ternaryfunc)func;
     TERNARY_LOOP {
@@ -306,7 +298,7 @@ PyUFunc_OOO_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_OO_O_method(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_OO_O_method(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     char *meth = (char *)func;
     BINARY_LOOP {
@@ -330,7 +322,7 @@ PyUFunc_OO_O_method(char **args, npy_intp *dimensions, npy_intp *steps, void *fu
 
 /*UFUNC_API*/
 NPY_NO_EXPORT void
-PyUFunc_On_Om(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
+PyUFunc_On_Om(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func)
 {
     npy_intp n =  dimensions[0];
     PyUFunc_PyFuncData *data = (PyUFunc_PyFuncData *)func;
@@ -360,7 +352,7 @@ PyUFunc_On_Om(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
             PyTuple_SET_ITEM(arglist, j, in);
             Py_INCREF(in);
         }
-        result = PyEval_CallObject(tocall, arglist);
+        result = PyObject_CallObject(tocall, arglist);
         Py_DECREF(arglist);
         if (result == NULL) {
             return;
@@ -411,7 +403,7 @@ PyUFunc_On_Om(char **args, npy_intp *dimensions, npy_intp *steps, void *func)
  **/
 
 NPY_NO_EXPORT void
-BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+BOOL_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         npy_bool in1 = *((npy_bool *)ip1) != 0;
@@ -430,7 +422,7 @@ BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
  **/
 
 NPY_NO_EXPORT void
-BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+BOOL_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if(IS_BINARY_REDUCE) {
 #ifdef NPY_HAVE_SSE2_INTRINSICS
@@ -500,7 +492,7 @@ BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
  * #OP =  !=, ==#
  **/
 NPY_NO_EXPORT void
-BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+BOOL_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (run_unary_simd_@kind@_BOOL(args, dimensions, steps)) {
         return;
@@ -515,7 +507,7 @@ BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
 /**end repeat**/
 
 NPY_NO_EXPORT void
-BOOL__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+BOOL__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     OUTPUT_LOOP {
         *((npy_bool *)op1) = 1;
@@ -529,7 +521,7 @@ BOOL__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UN
  * #val = NPY_FALSE, NPY_FALSE, NPY_TRUE#
  **/
 NPY_NO_EXPORT void
-BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+BOOL_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /*
      * The (void)in; suppresses an unused variable warning raised by gcc and allows
@@ -562,7 +554,7 @@ BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
 #define @TYPE@_fmin @TYPE@_minimum
 
 NPY_NO_EXPORT void
-@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     OUTPUT_LOOP {
         *((@type@ *)op1) = 1;
@@ -570,7 +562,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_positive(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = +in);
 }
@@ -584,7 +576,7 @@ NPY_NO_EXPORT void
 
 #if @CHK@
 NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_square@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_square@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = in * in);
 }
@@ -592,7 +584,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
 
 #if @CHK@
 NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_reciprocal@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_reciprocal@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = 1.0 / in);
 }
@@ -600,7 +592,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
 
 #if @CHK@
 NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_conjugate@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_conjugate@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = in);
 }
@@ -608,7 +600,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
 
 #if @CHK@
 NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_negative@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_negative@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = -in);
 }
@@ -616,7 +608,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
 
 #if @CHK@
 NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_logical_not@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_logical_not@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(@type@, npy_bool, *out = !in);
 }
@@ -624,7 +616,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
 
 #if @CHK@
 NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_invert@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_invert@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = ~in);
 }
@@ -638,7 +630,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
 
 #if @CHK@
 NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_@kind@@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (IS_BINARY_REDUCE) {
         BINARY_REDUCE_LOOP(@type@) {
@@ -668,7 +660,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
 #define UINT_left_shift_needs_clear_floatstatus
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_left_shift@isa@(char **args, npy_intp *dimensions, npy_intp *steps,
+@TYPE@_left_shift@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps,
                   void *NPY_UNUSED(func))
 {
     BINARY_LOOP_FAST(@type@, @type@, *out = npy_lshift@c@(in1, in2));
@@ -688,7 +680,7 @@ NPY_NO_EXPORT
 NPY_GCC_OPT_3
 #endif
 void
-@TYPE@_right_shift@isa@(char **args, npy_intp *dimensions, npy_intp *steps,
+@TYPE@_right_shift@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps,
                    void *NPY_UNUSED(func))
 {
     BINARY_LOOP_FAST(@type@, @type@, *out = npy_rshift@c@(in1, in2));
@@ -703,7 +695,7 @@ void
 
 #if @CHK@
 NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_@kind@@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /*
      * gcc vectorization of this is not good (PR60575) but manual integer
@@ -717,7 +709,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
 
 #if @CHK@
 NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
-@TYPE@_logical_xor@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_logical_xor@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const int t1 = !!*(@type@ *)ip1;
@@ -735,7 +727,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 @ATTR@ void
  **/
 
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (IS_BINARY_REDUCE) {
         BINARY_REDUCE_LOOP(@type@) {
@@ -756,7 +748,7 @@ NPY_NO_EXPORT void
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_power(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_power(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         @type@ in1 = *(@type@ *)ip1;
@@ -796,7 +788,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_fmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_fmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -818,7 +810,7 @@ NPY_NO_EXPORT void
  * #val = NPY_FALSE, NPY_FALSE, NPY_TRUE#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /*
      * The (void)in; suppresses an unused variable warning raised by gcc and allows
@@ -837,19 +829,19 @@ NPY_NO_EXPORT void
  */
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = (in >= 0) ? in : -in);
 }
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = in > 0 ? 1 : (in < 0 ? -1 : 0));
 }
 
 NPY_NO_EXPORT void
-@TYPE@_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -875,7 +867,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -898,7 +890,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP_TWO_OUT {
         const @type@ in1 = *(@type@ *)ip1;
@@ -929,7 +921,7 @@ NPY_NO_EXPORT void
  * #kind = gcd, lcm#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -948,19 +940,19 @@ NPY_NO_EXPORT void
  */
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = in);
 }
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(@type@, @type@, *out = in > 0 ? 1 : 0);
 }
 
 NPY_NO_EXPORT void
-@TYPE@_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -976,7 +968,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -992,7 +984,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP_TWO_OUT {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1013,7 +1005,7 @@ NPY_NO_EXPORT void
  * #kind = gcd, lcm#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1032,7 +1024,7 @@ NPY_NO_EXPORT void
  */
 
 NPY_NO_EXPORT void
-TIMEDELTA_negative(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_negative(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1046,7 +1038,7 @@ TIMEDELTA_negative(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_positive(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1055,7 +1047,7 @@ TIMEDELTA_positive(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1069,7 +1061,7 @@ TIMEDELTA_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1083,7 +1075,7 @@ TIMEDELTA_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU
  */
 
 NPY_NO_EXPORT void
-@TYPE@_isnat(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_isnat(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1092,7 +1084,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_isfinite(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_isfinite(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1101,13 +1093,13 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_isinf(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_isinf(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(npy_bool, npy_bool, (void)in; *out = NPY_FALSE);
 }
 
 NPY_NO_EXPORT void
-@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     OUTPUT_LOOP {
         *((@type@ *)op1) = 1;
@@ -1119,7 +1111,7 @@ NPY_NO_EXPORT void
  * #OP =  ==, >, >=, <, <=#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1132,7 +1124,7 @@ NPY_NO_EXPORT void
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_not_equal(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_not_equal(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1149,7 +1141,7 @@ NPY_NO_EXPORT void
  * #OP =  >, <#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1172,7 +1164,7 @@ NPY_NO_EXPORT void
  * #OP =  >=, <=#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1193,7 +1185,7 @@ NPY_NO_EXPORT void
 /**end repeat**/
 
 NPY_NO_EXPORT void
-DATETIME_Mm_M_add(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+DATETIME_Mm_M_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     BINARY_LOOP {
         const npy_datetime in1 = *(npy_datetime *)ip1;
@@ -1208,7 +1200,7 @@ DATETIME_Mm_M_add(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_
 }
 
 NPY_NO_EXPORT void
-DATETIME_mM_M_add(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+DATETIME_mM_M_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1223,7 +1215,7 @@ DATETIME_mM_M_add(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_m_add(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_mm_m_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1238,7 +1230,7 @@ TIMEDELTA_mm_m_add(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY
 }
 
 NPY_NO_EXPORT void
-DATETIME_Mm_M_subtract(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+DATETIME_Mm_M_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_datetime in1 = *(npy_datetime *)ip1;
@@ -1253,7 +1245,7 @@ DATETIME_Mm_M_subtract(char **args, npy_intp *dimensions, npy_intp *steps, void
 }
 
 NPY_NO_EXPORT void
-DATETIME_MM_m_subtract(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+DATETIME_MM_m_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_datetime in1 = *(npy_datetime *)ip1;
@@ -1268,7 +1260,7 @@ DATETIME_MM_m_subtract(char **args, npy_intp *dimensions, npy_intp *steps, void
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_m_subtract(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_mm_m_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1284,7 +1276,7 @@ TIMEDELTA_mm_m_subtract(char **args, npy_intp *dimensions, npy_intp *steps, void
 
 /* Note: Assuming 'q' == NPY_LONGLONG */
 NPY_NO_EXPORT void
-TIMEDELTA_mq_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_mq_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1300,7 +1292,7 @@ TIMEDELTA_mq_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void
 
 /* Note: Assuming 'q' == NPY_LONGLONG */
 NPY_NO_EXPORT void
-TIMEDELTA_qm_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_qm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_int64 in1 = *(npy_int64 *)ip1;
@@ -1315,7 +1307,7 @@ TIMEDELTA_qm_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_md_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_md_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1336,7 +1328,7 @@ TIMEDELTA_md_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_dm_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_dm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const double in1 = *(double *)ip1;
@@ -1358,7 +1350,7 @@ TIMEDELTA_dm_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void
 
 /* Note: Assuming 'q' == NPY_LONGLONG */
 NPY_NO_EXPORT void
-TIMEDELTA_mq_m_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_mq_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1373,7 +1365,7 @@ TIMEDELTA_mq_m_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_md_m_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_md_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1394,7 +1386,7 @@ TIMEDELTA_md_m_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_d_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_mm_d_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1409,7 +1401,7 @@ TIMEDELTA_mm_d_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_m_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_mm_m_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1437,7 +1429,7 @@ TIMEDELTA_mm_m_remainder(char **args, npy_intp *dimensions, npy_intp *steps, voi
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_q_floor_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_mm_q_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1462,7 +1454,7 @@ TIMEDELTA_mm_q_floor_divide(char **args, npy_intp *dimensions, npy_intp *steps,
 }
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_qm_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+TIMEDELTA_mm_qm_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP_TWO_OUT {
         const npy_timedelta in1 = *(npy_timedelta *)ip1;
@@ -1506,7 +1498,7 @@ TIMEDELTA_mm_qm_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void
  */
 
 NPY_NO_EXPORT void
-@TYPE@_sqrt(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_sqrt(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (!run_unary_simd_sqrt_@TYPE@(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -1530,7 +1522,7 @@ NPY_NO_EXPORT void
 */
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_@func@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_@func@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     UNARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1548,7 +1540,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 void
  */
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-FLOAT_@func@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+FLOAT_@func@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     UNARY_LOOP {
        const npy_float in1 = *(npy_float *)ip1;
@@ -1558,6 +1550,15 @@ FLOAT_@func@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSE
 
 /**end repeat**/
 
+NPY_NO_EXPORT NPY_GCC_OPT_3 void
+DOUBLE_exp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
+{
+    UNARY_LOOP {
+        const npy_double in1 = *(npy_double *)ip1;
+        *(npy_double *)op1 = npy_exp(in1);
+    }
+}
+
 /**begin repeat
  * #isa = avx512f, fma#
  * #ISA = AVX512F, FMA#
@@ -1571,7 +1572,7 @@ FLOAT_@func@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSE
  */
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_sqrt_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_sqrt_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     if (!run_unary_@isa@_sqrt_@TYPE@(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -1582,7 +1583,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 void
 }
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_absolute_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_absolute_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     if (!run_unary_@isa@_absolute_@TYPE@(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -1596,7 +1597,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 void
 }
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_square_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_square_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     if (!run_unary_@isa@_square_@TYPE@(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -1607,7 +1608,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 void
 }
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_reciprocal_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_reciprocal_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     if (!run_unary_@isa@_reciprocal_@TYPE@(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -1623,7 +1624,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 void
  */
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_@func@_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     if (!run_unary_@isa@_@func@_@TYPE@(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -1642,7 +1643,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 void
  */
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-FLOAT_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+FLOAT_@func@_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     if (!run_unary_@isa@_@func@_FLOAT(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -1671,7 +1672,7 @@ FLOAT_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY
  */
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-FLOAT_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+FLOAT_@func@_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     if (!run_unary_@isa@_sincos_FLOAT(args, dimensions, steps, @enum@)) {
         UNARY_LOOP {
@@ -1688,6 +1689,17 @@ FLOAT_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY
 /**end repeat1**/
 /**end repeat**/
 
+NPY_NO_EXPORT NPY_GCC_OPT_3 void
+DOUBLE_exp_avx512f(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
+{
+    if (!run_unary_avx512f_exp_DOUBLE(args, dimensions, steps)) {
+        UNARY_LOOP {
+            const npy_double in1 = *(npy_double *)ip1;
+            *(npy_double *)op1 = npy_exp(in1);
+        }
+    }
+}
+
 
 /**begin repeat
  * Float types
@@ -1784,7 +1796,7 @@ pairwise_sum_@TYPE@(char *a, npy_intp n, npy_intp stride)
  * # PW = 1, 0, 0, 0#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (IS_BINARY_REDUCE) {
 #if @PW@
@@ -1815,7 +1827,7 @@ NPY_NO_EXPORT void
  * #OP = ==, !=, <, <=, >, >=, &&, ||#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (!run_binary_simd_@kind@_@TYPE@(args, dimensions, steps)) {
         BINARY_LOOP {
@@ -1824,11 +1836,12 @@ NPY_NO_EXPORT void
             *((npy_bool *)op1) = in1 @OP@ in2;
         }
     }
+    npy_clear_floatstatus_barrier((char*)dimensions);
 }
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_logical_xor(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_logical_xor(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const int t1 = !!*(@type@ *)ip1;
@@ -1838,7 +1851,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_logical_not(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_logical_not(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1851,7 +1864,7 @@ NPY_NO_EXPORT void
  * #func = npy_isnan, npy_isinf, npy_isfinite, npy_signbit#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (!run_@kind@_simd_@TYPE@(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -1864,7 +1877,7 @@ NPY_NO_EXPORT void
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_spacing(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_spacing(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1873,7 +1886,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_copysign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_copysign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1883,7 +1896,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_nextafter(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_nextafter(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1897,7 +1910,35 @@ NPY_NO_EXPORT void
  * #OP =  >=, <=#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@_avx512f(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
+{
+    /*  */
+    if (IS_BINARY_REDUCE) {
+        if (!run_unary_reduce_simd_@kind@_@TYPE@(args, dimensions, steps)) {
+            BINARY_REDUCE_LOOP(@type@) {
+                const @type@ in2 = *(@type@ *)ip2;
+                /* Order of operations important for MSVC 2015 */
+                io1 = (io1 @OP@ in2 || npy_isnan(io1)) ? io1 : in2;
+            }
+            *((@type@ *)iop1) = io1;
+        }
+    }
+    else {
+        if (!run_binary_avx512f_@kind@_@TYPE@(args, dimensions, steps)) {
+            BINARY_LOOP {
+                @type@ in1 = *(@type@ *)ip1;
+                const @type@ in2 = *(@type@ *)ip2;
+                /* Order of operations important for MSVC 2015 */
+                in1 = (in1 @OP@ in2 || npy_isnan(in1)) ? in1 : in2;
+                *((@type@ *)op1) = in1;
+            }
+        }
+    }
+    npy_clear_floatstatus_barrier((char*)dimensions);
+}
+
+NPY_NO_EXPORT void
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /*  */
     if (IS_BINARY_REDUCE) {
@@ -1928,7 +1969,7 @@ NPY_NO_EXPORT void
  * #OP =  >=, <=#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /*  */
     if (IS_BINARY_REDUCE) {
@@ -1952,7 +1993,7 @@ NPY_NO_EXPORT void
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_floor_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1963,7 +2004,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1973,7 +2014,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP_TWO_OUT {
         const @type@ in1 = *(@type@ *)ip1;
@@ -1983,7 +2024,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_square(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_square(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     char * margs[] = {args[0], args[0], args[1]};
     npy_intp msteps[] = {steps[0], steps[0], steps[1]};
@@ -1996,7 +2037,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_reciprocal(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_reciprocal(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     @type@ one = 1.@c@;
     char * margs[] = {(char*)&one, args[0], args[1]};
@@ -2010,7 +2051,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     OUTPUT_LOOP {
         *((@type@ *)op1) = 1;
@@ -2018,7 +2059,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_conjugate(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_conjugate(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -2027,7 +2068,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (!run_unary_simd_absolute_@TYPE@(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -2041,7 +2082,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_negative(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_negative(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (!run_unary_simd_negative_@TYPE@(args, dimensions, steps)) {
         UNARY_LOOP {
@@ -2052,7 +2093,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_positive(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -2061,17 +2102,18 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /* Sign of nan is nan */
     UNARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
         *((@type@ *)op1) = in1 > 0 ? 1 : (in1 < 0 ? -1 : (in1 == 0 ? 0 : in1));
     }
+    npy_clear_floatstatus_barrier((char*)dimensions);
 }
 
 NPY_NO_EXPORT void
-@TYPE@_modf(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_modf(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_TWO_OUT {
         const @type@ in1 = *(@type@ *)ip1;
@@ -2080,7 +2122,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_frexp(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_frexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_TWO_OUT {
         const @type@ in1 = *(@type@ *)ip1;
@@ -2089,7 +2131,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_ldexp(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_ldexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @type@ in1 = *(@type@ *)ip1;
@@ -2099,7 +2141,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_ldexp_long(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_ldexp_long(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /*
      * Additional loop to handle npy_long integer inputs (cf. #866, #1633).
@@ -2146,7 +2188,7 @@ NPY_NO_EXPORT void
  * # PW = 1, 0, 0, 0#
  */
 NPY_NO_EXPORT void
-HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (IS_BINARY_REDUCE) {
         char *iop1 = args[0];
@@ -2181,7 +2223,7 @@ HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
  *       npy_half_ge, _HALF_LOGICAL_AND, _HALF_LOGICAL_OR#
  */
 NPY_NO_EXPORT void
-HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2194,7 +2236,7 @@ HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
 #undef _HALF_LOGICAL_OR
 
 NPY_NO_EXPORT void
-HALF_logical_xor(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_logical_xor(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const int in1 = !npy_half_iszero(*(npy_half *)ip1);
@@ -2204,7 +2246,7 @@ HALF_logical_xor(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_U
 }
 
 NPY_NO_EXPORT void
-HALF_logical_not(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_logical_not(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2217,7 +2259,7 @@ HALF_logical_not(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_U
  * #func = npy_half_isnan, npy_half_isinf, npy_half_isfinite, npy_half_signbit#
  **/
 NPY_NO_EXPORT void
-HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2228,7 +2270,7 @@ HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
 /**end repeat**/
 
 NPY_NO_EXPORT void
-HALF_spacing(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_spacing(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2237,7 +2279,7 @@ HALF_spacing(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSE
 }
 
 NPY_NO_EXPORT void
-HALF_copysign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_copysign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2247,7 +2289,7 @@ HALF_copysign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUS
 }
 
 NPY_NO_EXPORT void
-HALF_nextafter(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_nextafter(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2261,7 +2303,7 @@ HALF_nextafter(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU
  * #OP =  npy_half_ge, npy_half_le#
  **/
 NPY_NO_EXPORT void
-HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /*  */
     BINARY_LOOP {
@@ -2278,7 +2320,7 @@ HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
  * #OP =  npy_half_ge, npy_half_le#
  **/
 NPY_NO_EXPORT void
-HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /*  */
     BINARY_LOOP {
@@ -2291,7 +2333,7 @@ HALF_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
 /**end repeat**/
 
 NPY_NO_EXPORT void
-HALF_floor_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2302,7 +2344,7 @@ HALF_floor_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_
 }
 
 NPY_NO_EXPORT void
-HALF_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2312,7 +2354,7 @@ HALF_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU
 }
 
 NPY_NO_EXPORT void
-HALF_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP_TWO_OUT {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2322,7 +2364,7 @@ HALF_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
 }
 
 NPY_NO_EXPORT void
-HALF_square(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+HALF_square(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     UNARY_LOOP {
         const float in1 = npy_half_to_float(*(npy_half *)ip1);
@@ -2331,7 +2373,7 @@ HALF_square(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
 }
 
 NPY_NO_EXPORT void
-HALF_reciprocal(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+HALF_reciprocal(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     UNARY_LOOP {
         const float in1 = npy_half_to_float(*(npy_half *)ip1);
@@ -2340,7 +2382,7 @@ HALF_reciprocal(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UN
 }
 
 NPY_NO_EXPORT void
-HALF__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+HALF__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     OUTPUT_LOOP {
         *((npy_half *)op1) = NPY_HALF_ONE;
@@ -2348,7 +2390,7 @@ HALF__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UN
 }
 
 NPY_NO_EXPORT void
-HALF_conjugate(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_conjugate(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2357,13 +2399,13 @@ HALF_conjugate(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU
 }
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-HALF_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_FAST(npy_half, npy_half, *out = in&0x7fffu);
 }
 
 NPY_NO_EXPORT void
-HALF_negative(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_negative(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2372,7 +2414,7 @@ HALF_negative(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUS
 }
 
 NPY_NO_EXPORT void
-HALF_positive(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const npy_half in1 = *(npy_half *)ip1;
@@ -2381,7 +2423,7 @@ HALF_positive(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUS
 }
 
 NPY_NO_EXPORT void
-HALF_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /* Sign of nan is nan */
     UNARY_LOOP {
@@ -2393,7 +2435,7 @@ HALF_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(f
 }
 
 NPY_NO_EXPORT void
-HALF_modf(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_modf(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     float temp;
 
@@ -2405,7 +2447,7 @@ HALF_modf(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(f
 }
 
 NPY_NO_EXPORT void
-HALF_frexp(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_frexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP_TWO_OUT {
         const float in1 = npy_half_to_float(*(npy_half *)ip1);
@@ -2414,7 +2456,7 @@ HALF_frexp(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(
 }
 
 NPY_NO_EXPORT void
-HALF_ldexp(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_ldexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const float in1 = npy_half_to_float(*(npy_half *)ip1);
@@ -2424,7 +2466,7 @@ HALF_ldexp(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(
 }
 
 NPY_NO_EXPORT void
-HALF_ldexp_long(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+HALF_ldexp_long(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /*
      * Additional loop to handle npy_long integer inputs (cf. #866, #1633).
@@ -2479,6 +2521,7 @@ HALF_ldexp_long(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UN
  * #ftype = npy_float, npy_double, npy_longdouble#
  * #c = f, , l#
  * #C = F, , L#
+ * #SIMD = 1, 1, 0#
  */
 
 /* similar to pairwise sum of real floats */
@@ -2554,6 +2597,7 @@ pairwise_sum_@TYPE@(@ftype@ *rr, @ftype@ * ri, char * a, npy_intp n,
     }
 }
 
+
 /**begin repeat1
  * arithmetic
  * #kind = add, subtract#
@@ -2561,7 +2605,7 @@ pairwise_sum_@TYPE@(@ftype@ *rr, @ftype@ * ri, char * a, npy_intp n,
  * #PW = 1, 0#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     if (IS_BINARY_REDUCE && @PW@) {
         npy_intp n = dimensions[0];
@@ -2588,7 +2632,7 @@ NPY_NO_EXPORT void
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2601,7 +2645,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2632,8 +2676,34 @@ NPY_NO_EXPORT void
     }
 }
 
+#if @SIMD@
 NPY_NO_EXPORT void
-@TYPE@_floor_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_add_avx512f(char **args, const npy_intp *dimensions, const npy_intp *steps, void *func)
+{
+    if (IS_BINARY_REDUCE) {
+        @TYPE@_add(args, dimensions, steps, func);
+    }
+    else if (!run_binary_avx512f_add_@TYPE@(args, dimensions, steps)) {
+        @TYPE@_add(args, dimensions, steps, func);
+    }
+}
+
+/**begin repeat1
+ * arithmetic
+ * #kind = subtract, multiply#
+ */
+NPY_NO_EXPORT void
+@TYPE@_@kind@_avx512f(char **args, const npy_intp *dimensions, const npy_intp *steps, void *func)
+{
+    if (!run_binary_avx512f_@kind@_@TYPE@(args, dimensions, steps)) {
+        @TYPE@_@kind@(args, dimensions, steps, func);
+    }
+}
+/**end repeat1**/
+#endif
+
+NPY_NO_EXPORT void
+@TYPE@_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2658,7 +2728,7 @@ NPY_NO_EXPORT void
  * #OP = CGT, CGE, CLT, CLE, CEQ, CNE#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2676,7 +2746,7 @@ NPY_NO_EXPORT void
    #OP2 = &&, ||#
 */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2689,7 +2759,7 @@ NPY_NO_EXPORT void
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_logical_xor(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_logical_xor(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2703,7 +2773,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_logical_not(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_logical_not(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2718,7 +2788,7 @@ NPY_NO_EXPORT void
  * #OP = ||, ||, &&#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2730,7 +2800,7 @@ NPY_NO_EXPORT void
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_square(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_square(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     UNARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2741,7 +2811,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_reciprocal(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@_reciprocal(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     UNARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2761,7 +2831,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data))
+@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data))
 {
     OUTPUT_LOOP {
         ((@ftype@ *)op1)[0] = 1;
@@ -2770,7 +2840,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_conjugate(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) {
+@TYPE@_conjugate(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) {
     UNARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
         const @ftype@ in1i = ((@ftype@ *)ip1)[1];
@@ -2780,7 +2850,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2789,8 +2859,23 @@ NPY_NO_EXPORT void
     }
 }
 
+#if @SIMD@
+/**begin repeat1
+ * arithmetic
+ * #kind = conjugate, square, absolute#
+ */
+NPY_NO_EXPORT void
+@TYPE@_@kind@_avx512f(char **args, const npy_intp *dimensions, const npy_intp *steps, void *func)
+{
+    if (!run_unary_avx512f_@kind@_@TYPE@(args, dimensions, steps)) {
+        @TYPE@_@kind@(args, dimensions, steps, func);
+    }
+}
+/**end repeat1**/
+#endif
+
 NPY_NO_EXPORT void
-@TYPE@__arg(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@__arg(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     UNARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2800,7 +2885,7 @@ NPY_NO_EXPORT void
 }
 
 NPY_NO_EXPORT void
-@TYPE@_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     /* fixme: sign of nan is currently 0 */
     UNARY_LOOP {
@@ -2818,7 +2903,7 @@ NPY_NO_EXPORT void
  * #OP = CGE, CLE#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2841,7 +2926,7 @@ NPY_NO_EXPORT void
  * #OP = CGE, CLE#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     BINARY_LOOP {
         const @ftype@ in1r = ((@ftype@ *)ip1)[0];
@@ -2889,7 +2974,7 @@ NPY_NO_EXPORT void
  * #as_bool = 1, 0#
  */
 NPY_NO_EXPORT void
-OBJECT@suffix@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func)) {
+OBJECT@suffix@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func)) {
     BINARY_LOOP {
         PyObject *ret_obj;
         PyObject *in1 = *(PyObject **)ip1;
@@ -2925,7 +3010,7 @@ OBJECT@suffix@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *
 /**end repeat**/
 
 NPY_NO_EXPORT void
-OBJECT_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+OBJECT_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     PyObject *zero = PyLong_FromLong(0);
 
index 7558de0bbdfc59d8337494087952e8eccff130ba..50a7ccfee89e26e3e248b6fe11ee1a906726cdad 100644 (file)
  *         logical_and, logical_or, absolute, logical_not#
  **/
 NPY_NO_EXPORT void
-BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+BOOL_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat**/
 
 NPY_NO_EXPORT void
-BOOL__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+BOOL__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 /**begin repeat
  * #kind = isnan, isinf, isfinite#
  **/
 NPY_NO_EXPORT void
-BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+BOOL_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat**/
 
 /*
@@ -64,32 +64,32 @@ BOOL_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED
 #define @S@@TYPE@_fmin @S@@TYPE@_minimum
 
 NPY_NO_EXPORT void
-@S@@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+@S@@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_positive(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**begin repeat2
  * #isa = , _avx2#
  */
 
 NPY_NO_EXPORT void
-@S@@TYPE@_square@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+@S@@TYPE@_square@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_reciprocal@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+@S@@TYPE@_reciprocal@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_conjugate@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_conjugate@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_negative@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_negative@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_logical_not@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_logical_not@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_invert@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_invert@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**begin repeat3
  * Arithmetic
@@ -98,7 +98,7 @@ NPY_NO_EXPORT void
  * #OP = +, -,*, &, |, ^, <<, >>#
  */
 NPY_NO_EXPORT void
-@S@@TYPE@_@kind@@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_@kind@@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**end repeat3**/
 
@@ -108,12 +108,12 @@ NPY_NO_EXPORT void
  * #OP =  ==, !=, >, >=, <, <=, &&, ||#
  */
 NPY_NO_EXPORT void
-@S@@TYPE@_@kind@@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_@kind@@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**end repeat3**/
 
 NPY_NO_EXPORT void
-@S@@TYPE@_logical_xor@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_logical_xor@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat2**/
 
 /**begin repeat2
@@ -121,41 +121,41 @@ NPY_NO_EXPORT void
  * #OP =  >, <#
  **/
 NPY_NO_EXPORT void
-@S@@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat2**/
 
 NPY_NO_EXPORT void
-@S@@TYPE@_power(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_power(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_fmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_fmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_gcd(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_gcd(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@S@@TYPE@_lcm(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_lcm(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**begin repeat2
  * #kind = isnan, isinf, isfinite#
  **/
 NPY_NO_EXPORT void
-@S@@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@S@@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat2**/
 
 /**end repeat1**/
@@ -172,7 +172,15 @@ NPY_NO_EXPORT void
  *  #TYPE = FLOAT, DOUBLE#
  */
 NPY_NO_EXPORT void
-@TYPE@_sqrt(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_sqrt(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
+
+/**begin repeat1
+ * #func = maximum, minimum#
+ */
+NPY_NO_EXPORT void
+@TYPE@_@func@_avx512f(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
+
+/**end repeat1**/
 
 /**begin repeat1
  * #isa = avx512f, fma#
@@ -182,24 +190,30 @@ NPY_NO_EXPORT void
  * #func = sqrt, absolute, square, reciprocal#
  */
 NPY_NO_EXPORT void
-@TYPE@_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_@func@_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**end repeat2**/
 /**end repeat1**/
 /**end repeat**/
 
+NPY_NO_EXPORT void
+DOUBLE_exp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
+
+NPY_NO_EXPORT void
+DOUBLE_exp_avx512f(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
+
 /**begin repeat
  *  #func = sin, cos, exp, log#
  */
 NPY_NO_EXPORT void
-FLOAT_@func@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+FLOAT_@func@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**begin repeat1
  * #isa = avx512f, fma#
  */
 
 NPY_NO_EXPORT void
-FLOAT_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+FLOAT_@func@_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**end repeat1**/
 /**end repeat**/
@@ -213,13 +227,13 @@ FLOAT_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY
 */
 
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_@func@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+@TYPE@_@func@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 /**begin repeat2
  * #isa = avx512f, fma#
  */
 NPY_NO_EXPORT NPY_GCC_OPT_3 void
-@TYPE@_@func@_@isa@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+@TYPE@_@func@_@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 /**end repeat2**/
 /**end repeat1**/
 /**end repeat**/
@@ -238,7 +252,7 @@ NPY_NO_EXPORT NPY_GCC_OPT_3 void
  * # OP = +, -, *, /#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 /**begin repeat1
@@ -247,21 +261,21 @@ NPY_NO_EXPORT void
  * #OP = ==, !=, <, <=, >, >=, &&, ||#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_logical_xor(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_logical_xor(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_logical_not(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_logical_not(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**begin repeat1
  * #kind = isnan, isinf, isfinite, signbit, copysign, nextafter, spacing#
  * #func = npy_isnan, npy_isinf, npy_isfinite, npy_signbit, npy_copysign, nextafter, spacing#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 /**begin repeat1
@@ -269,7 +283,7 @@ NPY_NO_EXPORT void
  * #OP =  >=, <=#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 /**begin repeat1
@@ -277,54 +291,53 @@ NPY_NO_EXPORT void
  * #OP =  >=, <=#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-@TYPE@_floor_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_square(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+@TYPE@_square(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 NPY_NO_EXPORT void
-@TYPE@_reciprocal(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
-
+@TYPE@_reciprocal(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 NPY_NO_EXPORT void
-@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 NPY_NO_EXPORT void
-@TYPE@_conjugate(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_conjugate(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_negative(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_negative(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_positive(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
-
+@TYPE@_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_modf(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_modf(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_frexp(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_frexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_ldexp(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_ldexp(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
+
 NPY_NO_EXPORT void
-@TYPE@_ldexp_long(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_ldexp_long(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 #define @TYPE@_true_divide @TYPE@_divide
 
@@ -349,33 +362,40 @@ NPY_NO_EXPORT void
  * #TYPE = FLOAT, DOUBLE, LONGDOUBLE#
  * #c = f, , l#
  * #C = F, , L#
+ * #IFSIMD = 1, 1, 0#
  */
 
 /**begin repeat1
+ * #isa = , _avx512f#
+ */
+
+/**begin repeat2
  * arithmetic
  * #kind = add, subtract#
  * #OP = +, -#
  */
+
 NPY_NO_EXPORT void
-C@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_@kind@@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
-/**end repeat1**/
+/**end repeat2**/
 
 NPY_NO_EXPORT void
-C@TYPE@_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_multiply@isa@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
+/**end repeat1**/
 
 NPY_NO_EXPORT void
-C@TYPE@_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-C@TYPE@_floor_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**begin repeat1
  * #kind= greater, greater_equal, less, less_equal, equal, not_equal#
  * #OP = CGT, CGE, CLT, CLE, CEQ, CNE#
  */
 NPY_NO_EXPORT void
-C@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 /**begin repeat1
@@ -384,50 +404,55 @@ C@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU
    #OP2 = &&, ||#
 */
 NPY_NO_EXPORT void
-C@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-C@TYPE@_logical_xor(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_logical_xor(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-C@TYPE@_logical_not(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_logical_not(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**begin repeat1
  * #kind = isnan, isinf, isfinite#
  * #func = npy_isnan, npy_isinf, npy_isfinite#
  * #OP = ||, ||, &&#
  **/
 NPY_NO_EXPORT void
-C@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 NPY_NO_EXPORT void
-C@TYPE@_square(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+C@TYPE@_reciprocal(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 NPY_NO_EXPORT void
-C@TYPE@_reciprocal(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+C@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
+
+/**begin repeat1
+ * #isa = , _avx512f#
+ */
 
 NPY_NO_EXPORT void
-C@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+C@TYPE@_conjugate@isa@(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-C@TYPE@_conjugate(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_absolute@isa@(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-C@TYPE@_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_square@isa@(char **args, const npy_intp *dimensions, const npy_intp *steps, void *NPY_UNUSED(data));
+/**end repeat1**/
 
 NPY_NO_EXPORT void
-C@TYPE@__arg(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@__arg(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-C@TYPE@_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**begin repeat1
  * #kind = maximum, minimum#
  * #OP = CGE, CLE#
  */
 NPY_NO_EXPORT void
-C@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 /**begin repeat1
@@ -435,9 +460,8 @@ C@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU
  * #OP = CGE, CLE#
  */
 NPY_NO_EXPORT void
-C@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+C@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
-
 #define C@TYPE@_true_divide C@TYPE@_divide
 
 /**end repeat**/
@@ -456,99 +480,99 @@ C@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNU
  */
 
 NPY_NO_EXPORT void
-TIMEDELTA_negative(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_negative(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_positive(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_positive(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_absolute(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_absolute(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /**begin repeat
  * #TYPE = DATETIME, TIMEDELTA#
  */
 
 NPY_NO_EXPORT void
-@TYPE@_isnat(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_isnat(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_isfinite(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_isfinite(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-@TYPE@_isinf(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_isinf(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 #define @TYPE@_isnan @TYPE@_isnat
 
 NPY_NO_EXPORT void
-@TYPE@__ones_like(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+@TYPE@__ones_like(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 /**begin repeat1
  * #kind = equal, not_equal, greater, greater_equal, less, less_equal#
  * #OP =  ==, !=, >, >=, <, <=#
  */
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 /**begin repeat1
  * #kind = maximum, minimum, fmin, fmax#
  **/
 NPY_NO_EXPORT void
-@TYPE@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 
 /**end repeat**/
 
 NPY_NO_EXPORT void
-DATETIME_Mm_M_add(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(data));
+DATETIME_Mm_M_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(data));
 
 NPY_NO_EXPORT void
-DATETIME_mM_M_add(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+DATETIME_mM_M_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_m_add(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_mm_m_add(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-DATETIME_Mm_M_subtract(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+DATETIME_Mm_M_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-DATETIME_MM_m_subtract(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+DATETIME_MM_m_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_m_subtract(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_mm_m_subtract(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_mq_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_mq_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_qm_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_qm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_md_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_md_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_dm_m_multiply(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_dm_m_multiply(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_mq_m_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_mq_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_md_m_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_md_m_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_d_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_mm_d_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_q_floor_divide(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_mm_q_floor_divide(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_m_remainder(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_mm_m_remainder(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-TIMEDELTA_mm_qm_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+TIMEDELTA_mm_qm_divmod(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 /* Special case equivalents to above functions */
 
@@ -573,15 +597,15 @@ TIMEDELTA_mm_qm_divmod(char **args, npy_intp *dimensions, npy_intp *steps, void
  * #suffix = , _OO_O#
  */
 NPY_NO_EXPORT void
-OBJECT@suffix@_@kind@(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+OBJECT@suffix@_@kind@(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat1**/
 /**end repeat**/
 
 NPY_NO_EXPORT void
-OBJECT_sign(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+OBJECT_sign(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 
 NPY_NO_EXPORT void
-PyUFunc_OOO_O(char **args, npy_intp *dimensions, npy_intp *steps, void *func);
+PyUFunc_OOO_O(char **args, npy_intp const *dimensions, npy_intp const *steps, void *func);
 
 /*
  *****************************************************************************
index c8f7c654dc17eb8c969dc774c63f47b4d652beae..5cbb6e94dde6d60d6a4dbeb4cd2a191f2b2c0bbc 100644 (file)
@@ -395,7 +395,7 @@ OBJECT_matmul_inner_noblas(void *_ip1, npy_intp is1_m, npy_intp is1_n,
 
 
 NPY_NO_EXPORT void
-@TYPE@_matmul(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func))
+@TYPE@_matmul(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func))
 {
     npy_intp dOuter = *dimensions++;
     npy_intp iOuter;
index a664b1b4e1fd35085c4a6fc9ac88e467f2d3bd65..18940e2f2c5f09b38527e7ac47e3e40b8d372562 100644 (file)
@@ -6,7 +6,7 @@
  *          BOOL, OBJECT#
  **/
 NPY_NO_EXPORT void
-@TYPE@_matmul(char **args, npy_intp *dimensions, npy_intp *steps, void *NPY_UNUSED(func));
+@TYPE@_matmul(char **args, npy_intp const *dimensions, npy_intp const *steps, void *NPY_UNUSED(func));
 /**end repeat**/
 
 
diff --git a/numpy/core/src/umath/npy_simd_data.h b/numpy/core/src/umath/npy_simd_data.h
new file mode 100644 (file)
index 0000000..36c8b6c
--- /dev/null
@@ -0,0 +1,137 @@
+#ifndef __NPY_SIMD_DATA_H_
+#define __NPY_SIMD_DATA_H_
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined  NPY_HAVE_SSE2_INTRINSICS
+/*
+ * Constants used in vector implementation of float64 exp(x)
+ */
+#define NPY_RINT_CVT_MAGIC 0x1.8p52
+#define NPY_INV_LN2_MUL_32 0x1.71547652b82fep+5
+#define NPY_TANG_NEG_L1 -0x1.62e42fefp-6
+#define NPY_TANG_NEG_L2 -0x1.473de6af278edp-39
+#define NPY_TANG_A1 0x1p-1
+#define NPY_TANG_A2 0x1.5555555548f7cp-3
+#define NPY_TANG_A3 0x1.5555555545d4ep-5
+#define NPY_TANG_A4 0x1.11115b7aa905ep-7
+#define NPY_TANG_A5 0x1.6c1728d739765p-10
+
+/* Lookup table for 2^(j/32) */
+static npy_uint64 EXP_Table_top[32] = {
+    0x3FF0000000000000,
+    0x3FF059B0D3158540,
+    0x3FF0B5586CF98900,
+    0x3FF11301D0125B40,
+    0x3FF172B83C7D5140,
+    0x3FF1D4873168B980,
+    0x3FF2387A6E756200,
+    0x3FF29E9DF51FDEC0,
+    0x3FF306FE0A31B700,
+    0x3FF371A7373AA9C0,
+    0x3FF3DEA64C123400,
+    0x3FF44E0860618900,
+    0x3FF4BFDAD5362A00,
+    0x3FF5342B569D4F80,
+    0x3FF5AB07DD485400,
+    0x3FF6247EB03A5580,
+    0x3FF6A09E667F3BC0,
+    0x3FF71F75E8EC5F40,
+    0x3FF7A11473EB0180,
+    0x3FF82589994CCE00,
+    0x3FF8ACE5422AA0C0,
+    0x3FF93737B0CDC5C0,
+    0x3FF9C49182A3F080,
+    0x3FFA5503B23E2540,
+    0x3FFAE89F995AD380,
+    0x3FFB7F76F2FB5E40,
+    0x3FFC199BDD855280,
+    0x3FFCB720DCEF9040,
+    0x3FFD5818DCFBA480,
+    0x3FFDFC97337B9B40,
+    0x3FFEA4AFA2A490C0,
+    0x3FFF50765B6E4540,
+};
+
+static npy_uint64 EXP_Table_tail[32] = {
+    0x0000000000000000,
+    0x3D0A1D73E2A475B4,
+    0x3CEEC5317256E308,
+    0x3CF0A4EBBF1AED93,
+    0x3D0D6E6FBE462876,
+    0x3D053C02DC0144C8,
+    0x3D0C3360FD6D8E0B,
+    0x3D009612E8AFAD12,
+    0x3CF52DE8D5A46306,
+    0x3CE54E28AA05E8A9,
+    0x3D011ADA0911F09F,
+    0x3D068189B7A04EF8,
+    0x3D038EA1CBD7F621,
+    0x3CBDF0A83C49D86A,
+    0x3D04AC64980A8C8F,
+    0x3CD2C7C3E81BF4B7,
+    0x3CE921165F626CDD,
+    0x3D09EE91B8797785,
+    0x3CDB5F54408FDB37,
+    0x3CF28ACF88AFAB35,
+    0x3CFB5BA7C55A192D,
+    0x3D027A280E1F92A0,
+    0x3CF01C7C46B071F3,
+    0x3CFC8B424491CAF8,
+    0x3D06AF439A68BB99,
+    0x3CDBAA9EC206AD4F,
+    0x3CFC2220CB12A092,
+    0x3D048A81E5E8F4A5,
+    0x3CDC976816BAD9B8,
+    0x3CFEB968CAC39ED3,
+    0x3CF9858F73A18F5E,
+    0x3C99D3E12DD8A18B,
+};
+#endif
+
+/*
+ * Constants used in vector implementation of exp(x)
+ */
+#define NPY_RINT_CVT_MAGICf 0x1.800000p+23f
+#define NPY_CODY_WAITE_LOGE_2_HIGHf -6.93145752e-1f
+#define NPY_CODY_WAITE_LOGE_2_LOWf -1.42860677e-6f
+#define NPY_COEFF_P0_EXPf 9.999999999980870924916e-01f
+#define NPY_COEFF_P1_EXPf 7.257664613233124478488e-01f
+#define NPY_COEFF_P2_EXPf 2.473615434895520810817e-01f
+#define NPY_COEFF_P3_EXPf 5.114512081637298353406e-02f
+#define NPY_COEFF_P4_EXPf 6.757896990527504603057e-03f
+#define NPY_COEFF_P5_EXPf 5.082762527590693718096e-04f
+#define NPY_COEFF_Q0_EXPf 1.000000000000000000000e+00f
+#define NPY_COEFF_Q1_EXPf -2.742335390411667452936e-01f
+#define NPY_COEFF_Q2_EXPf 2.159509375685829852307e-02f
+
+/*
+ * Constants used in vector implementation of log(x)
+ */
+#define NPY_COEFF_P0_LOGf 0.000000000000000000000e+00f
+#define NPY_COEFF_P1_LOGf 9.999999999999998702752e-01f
+#define NPY_COEFF_P2_LOGf 2.112677543073053063722e+00f
+#define NPY_COEFF_P3_LOGf 1.480000633576506585156e+00f
+#define NPY_COEFF_P4_LOGf 3.808837741388407920751e-01f
+#define NPY_COEFF_P5_LOGf 2.589979117907922693523e-02f
+#define NPY_COEFF_Q0_LOGf 1.000000000000000000000e+00f
+#define NPY_COEFF_Q1_LOGf 2.612677543073109236779e+00f
+#define NPY_COEFF_Q2_LOGf 2.453006071784736363091e+00f
+#define NPY_COEFF_Q3_LOGf 9.864942958519418960339e-01f
+#define NPY_COEFF_Q4_LOGf 1.546476374983906719538e-01f
+#define NPY_COEFF_Q5_LOGf 5.875095403124574342950e-03f
+/*
+ * Constants used in vector implementation of sinf/cosf(x)
+ */
+#define NPY_TWO_O_PIf 0x1.45f306p-1f
+#define NPY_CODY_WAITE_PI_O_2_HIGHf -0x1.921fb0p+00f
+#define NPY_CODY_WAITE_PI_O_2_MEDf -0x1.5110b4p-22f
+#define NPY_CODY_WAITE_PI_O_2_LOWf -0x1.846988p-48f
+#define NPY_COEFF_INVF0_COSINEf 0x1.000000p+00f
+#define NPY_COEFF_INVF2_COSINEf -0x1.000000p-01f
+#define NPY_COEFF_INVF4_COSINEf 0x1.55553cp-05f
+#define NPY_COEFF_INVF6_COSINEf -0x1.6c06dcp-10f
+#define NPY_COEFF_INVF8_COSINEf 0x1.98e616p-16f
+#define NPY_COEFF_INVF3_SINEf -0x1.555556p-03f
+#define NPY_COEFF_INVF5_SINEf 0x1.11119ap-07f
+#define NPY_COEFF_INVF7_SINEf -0x1.a06bbap-13f
+#define NPY_COEFF_INVF9_SINEf 0x1.7d3bbcp-19f
+
+#endif
index 43bed425cfdf25da27405591864b80fe51a63653..bf6e5a6985918dabc4a89426ec02d29cb13cc93f 100644 (file)
@@ -112,9 +112,16 @@ fail:
 static int
 normalize_signature_keyword(PyObject *normal_kwds)
 {
-    PyObject* obj = PyDict_GetItemString(normal_kwds, "sig");
+    PyObject *obj = _PyDict_GetItemStringWithError(normal_kwds, "sig");
+    if (obj == NULL && PyErr_Occurred()){
+        return -1;
+    }
     if (obj != NULL) {
-        if (PyDict_GetItemString(normal_kwds, "signature")) {
+        PyObject *sig = _PyDict_GetItemStringWithError(normal_kwds, "signature");
+        if (sig == NULL && PyErr_Occurred()) {
+            return -1;
+        }
+        if (sig) {
             PyErr_SetString(PyExc_TypeError,
                             "cannot specify both 'sig' and 'signature'");
             return -1;
@@ -165,11 +172,17 @@ normalize___call___args(PyUFuncObject *ufunc, PyObject *args,
 
     /* If we have more args than nin, they must be the output variables.*/
     if (nargs > nin) {
-        if(nkwds > 0 && PyDict_GetItemString(*normal_kwds, "out")) {
-            PyErr_Format(PyExc_TypeError,
-                         "argument given by name ('out') and position "
-                         "(%"NPY_INTP_FMT")", nin);
-            return -1;
+        if (nkwds > 0) {
+            PyObject *out_kwd = _PyDict_GetItemStringWithError(*normal_kwds, "out");
+            if (out_kwd == NULL && PyErr_Occurred()) {
+                return -1;
+            }
+            else if (out_kwd) {
+                PyErr_Format(PyExc_TypeError,
+                             "argument given by name ('out') and position "
+                             "(%"NPY_INTP_FMT")", nin);
+                return -1;
+            }
         }
         for (i = nin; i < nargs; i++) {
             not_all_none = (PyTuple_GET_ITEM(args, i) != Py_None);
@@ -204,11 +217,20 @@ normalize___call___args(PyUFuncObject *ufunc, PyObject *args,
         }
     }
     /* gufuncs accept either 'axes' or 'axis', but not both */
-    if (nkwds >= 2 && (PyDict_GetItemString(*normal_kwds, "axis") &&
-                       PyDict_GetItemString(*normal_kwds, "axes"))) {
-        PyErr_SetString(PyExc_TypeError,
-                        "cannot specify both 'axis' and 'axes'");
-        return -1;
+    if (nkwds >= 2) {
+        PyObject *axis_kwd = _PyDict_GetItemStringWithError(*normal_kwds, "axis");
+        if (axis_kwd == NULL && PyErr_Occurred()) {
+            return -1;
+        }
+        PyObject *axes_kwd = _PyDict_GetItemStringWithError(*normal_kwds, "axes");
+        if (axes_kwd == NULL && PyErr_Occurred()) {
+            return -1;
+        }
+        if (axis_kwd && axes_kwd) {
+            PyErr_SetString(PyExc_TypeError,
+                            "cannot specify both 'axis' and 'axes'");
+            return -1;
+        }
     }
     /* finally, ufuncs accept 'sig' or 'signature' normalize to 'signature' */
     return nkwds == 0 ? 0 : normalize_signature_keyword(*normal_kwds);
@@ -243,7 +265,11 @@ normalize_reduce_args(PyUFuncObject *ufunc, PyObject *args,
     }
 
     for (i = 1; i < nargs; i++) {
-        if (PyDict_GetItemString(*normal_kwds, kwlist[i])) {
+        PyObject *kwd = _PyDict_GetItemStringWithError(*normal_kwds, kwlist[i]);
+        if (kwd == NULL && PyErr_Occurred()) {
+            return -1;
+        }
+        else if (kwd) {
             PyErr_Format(PyExc_TypeError,
                          "argument given by name ('%s') and position "
                          "(%"NPY_INTP_FMT")", kwlist[i], i);
@@ -293,7 +319,11 @@ normalize_accumulate_args(PyUFuncObject *ufunc, PyObject *args,
     }
 
     for (i = 1; i < nargs; i++) {
-        if (PyDict_GetItemString(*normal_kwds, kwlist[i])) {
+        PyObject *kwd = _PyDict_GetItemStringWithError(*normal_kwds, kwlist[i]);
+        if (kwd == NULL && PyErr_Occurred()) {
+            return -1;
+        }
+        else if (kwd) {
             PyErr_Format(PyExc_TypeError,
                          "argument given by name ('%s') and position "
                          "(%"NPY_INTP_FMT")", kwlist[i], i);
@@ -341,7 +371,11 @@ normalize_reduceat_args(PyUFuncObject *ufunc, PyObject *args,
     }
 
     for (i = 2; i < nargs; i++) {
-        if (PyDict_GetItemString(*normal_kwds, kwlist[i])) {
+        PyObject *kwd = _PyDict_GetItemStringWithError(*normal_kwds, kwlist[i]);
+        if (kwd == NULL && PyErr_Occurred()) {
+            return -1;
+        }
+        else if (kwd) {
             PyErr_Format(PyExc_TypeError,
                          "argument given by name ('%s') and position "
                          "(%"NPY_INTP_FMT")", kwlist[i], i);
@@ -469,8 +503,11 @@ PyUFunc_CheckOverride(PyUFuncObject *ufunc, char *method,
 
         /* ensure out is always a tuple */
         normal_kwds = PyDict_Copy(kwds);
-        out = PyDict_GetItemString(normal_kwds, "out");
-        if (out != NULL) {
+        out = _PyDict_GetItemStringWithError(normal_kwds, "out");
+        if (out == NULL && PyErr_Occurred()) {
+            goto fail;
+        }
+        else if (out) {
             int nout = ufunc->nout;
 
             if (PyTuple_CheckExact(out)) {
index 4ce8d8ab7436216517b9e05cd5bab00a9687bff9..79adb0051fe82f26f56a1e1b54ce2c1c26a3be42 100644 (file)
@@ -18,6 +18,7 @@
 
 #include "npy_config.h"
 #include "npy_pycompat.h"
+#include "ctors.h"
 
 #include "numpy/ufuncobject.h"
 #include "lowlevel_strided_loops.h"
@@ -84,16 +85,17 @@ allocate_reduce_result(PyArrayObject *arr, const npy_bool *axis_flags,
  * The return value is a view into 'out'.
  */
 static PyArrayObject *
-conform_reduce_result(int ndim, const npy_bool *axis_flags,
+conform_reduce_result(PyArrayObject *in, const npy_bool *axis_flags,
                       PyArrayObject *out, int keepdims, const char *funcname,
                       int need_copy)
 {
-    npy_intp strides[NPY_MAXDIMS], shape[NPY_MAXDIMS];
-    npy_intp *strides_out = PyArray_STRIDES(out);
-    npy_intp *shape_out = PyArray_DIMS(out);
-    int idim, idim_out, ndim_out = PyArray_NDIM(out);
-    PyArray_Descr *dtype;
-    PyArrayObject_fields *ret;
+    /* unpack shape information */
+    int const ndim = PyArray_NDIM(in);
+    npy_intp const *shape_in = PyArray_DIMS(in);
+
+    int const ndim_out = PyArray_NDIM(out);
+    npy_intp const *strides_out = PyArray_STRIDES(out);
+    npy_intp const *shape_out = PyArray_DIMS(out);
 
     /*
      * If the 'keepdims' parameter is true, do a simpler validation and
@@ -108,7 +110,7 @@ conform_reduce_result(int ndim, const npy_bool *axis_flags,
             return NULL;
         }
 
-        for (idim = 0; idim < ndim; ++idim) {
+        for (int idim = 0; idim < ndim; ++idim) {
             if (axis_flags[idim]) {
                 if (shape_out[idim] != 1) {
                     PyErr_Format(PyExc_ValueError,
@@ -118,6 +120,16 @@ conform_reduce_result(int ndim, const npy_bool *axis_flags,
                     return NULL;
                 }
             }
+            else {
+                if (shape_out[idim] != shape_in[idim]) {
+                    PyErr_Format(PyExc_ValueError,
+                            "output parameter for reduction operation %s "
+                            "has a non-reduction dimension not equal to "
+                            "the input one.", funcname);
+                    return NULL;
+                }
+            }
+
         }
 
         Py_INCREF(out);
@@ -125,8 +137,9 @@ conform_reduce_result(int ndim, const npy_bool *axis_flags,
     }
 
     /* Construct the strides and shape */
-    idim_out = 0;
-    for (idim = 0; idim < ndim; ++idim) {
+    npy_intp strides[NPY_MAXDIMS], shape[NPY_MAXDIMS];
+    int idim_out = 0;
+    for (int idim = 0; idim < ndim; ++idim) {
         if (axis_flags[idim]) {
             strides[idim] = 0;
             shape[idim] = 1;
@@ -138,6 +151,13 @@ conform_reduce_result(int ndim, const npy_bool *axis_flags,
                         "does not have enough dimensions", funcname);
                 return NULL;
             }
+            if (shape_out[idim_out] != shape_in[idim]) {
+                PyErr_Format(PyExc_ValueError,
+                        "output parameter for reduction operation %s "
+                        "has a non-reduction dimension not equal to "
+                        "the input one.", funcname);
+                return NULL;
+            }
             strides[idim] = strides_out[idim_out];
             shape[idim] = shape_out[idim_out];
             ++idim_out;
@@ -152,31 +172,20 @@ conform_reduce_result(int ndim, const npy_bool *axis_flags,
     }
 
     /* Allocate the view */
-    dtype = PyArray_DESCR(out);
+    PyArray_Descr *dtype = PyArray_DESCR(out);
     Py_INCREF(dtype);
 
-    /* TODO: use PyArray_NewFromDescrAndBase here once multiarray and umath
-     *       are merged
-     */
-    ret = (PyArrayObject_fields *)PyArray_NewFromDescr(
+    PyArrayObject_fields *ret = (PyArrayObject_fields *)PyArray_NewFromDescrAndBase(
             &PyArray_Type, dtype,
             ndim, shape, strides, PyArray_DATA(out),
-            PyArray_FLAGS(out), NULL);
+            PyArray_FLAGS(out), NULL, (PyObject *)out);
     if (ret == NULL) {
         return NULL;
     }
 
-    Py_INCREF(out);
-    if (PyArray_SetBaseObject((PyArrayObject *)ret, (PyObject *)out) < 0) {
-        Py_DECREF(ret);
-        return NULL;
-    }
-
     if (need_copy) {
-        PyArrayObject *ret_copy;
-
-        ret_copy = (PyArrayObject *)PyArray_NewLikeArray(
-            (PyArrayObject *)ret, NPY_ANYORDER, NULL, 0);
+        PyArrayObject *ret_copy = (PyArrayObject *)PyArray_NewLikeArray(
+                (PyArrayObject *)ret, NPY_ANYORDER, NULL, 0);
         if (ret_copy == NULL) {
             Py_DECREF(ret);
             return NULL;
@@ -189,7 +198,6 @@ conform_reduce_result(int ndim, const npy_bool *axis_flags,
         }
 
         if (PyArray_SetWritebackIfCopyBase(ret_copy, (PyArrayObject *)ret) < 0) {
-            Py_DECREF(ret);
             Py_DECREF(ret_copy);
             return NULL;
         }
@@ -240,7 +248,7 @@ PyArray_CreateReduceResult(PyArrayObject *operand, PyArrayObject *out,
 
         /* Steal the dtype reference */
         Py_XDECREF(dtype);
-        result = conform_reduce_result(PyArray_NDIM(operand), axis_flags,
+        result = conform_reduce_result(operand, axis_flags,
                                        out, keepdims, funcname, need_copy);
     }
 
index dfaeabcbbdbdbcefbf7f3dca5d315ecd17e1bbfb..0c2183ed625e2e730813866fbd383e52acb7b136 100644 (file)
@@ -100,8 +100,8 @@ typedef int (PyArray_AssignReduceIdentityFunc)(PyArrayObject *result,
  */
 typedef int (PyArray_ReduceLoopFunc)(NpyIter *iter,
                                             char **dataptr,
-                                            npy_intp *strideptr,
-                                            npy_intp *countptr,
+                                            npy_intp const *strideptr,
+                                            npy_intp const *countptr,
                                             NpyIter_IterNextFunc *iternext,
                                             int needs_api,
                                             npy_intp skip_first_count,
index d5d8d659bbd2f45403301f82cd341e064c949da9..bb2915e09128cd5b94738fc14f8d43fb1a0a96f7 100644 (file)
@@ -744,56 +744,50 @@ _@name@_convert2_to_ctypes(PyObject *a, @type@ *arg1,
 /**end repeat**/
 
 
-#if defined(NPY_PY3K)
-#define CODEGEN_SKIP_divide_FLAG
-#endif
-
 /**begin repeat
  *
  * #name = (byte, ubyte, short, ushort, int, uint,
- *             long, ulong, longlong, ulonglong)*13,
+ *             long, ulong, longlong, ulonglong)*12,
  *         (half, float, double, longdouble,
- *             cfloat, cdouble, clongdouble)*6,
+ *             cfloat, cdouble, clongdouble)*5,
  *         (half, float, double, longdouble)*2#
  * #Name = (Byte, UByte, Short, UShort, Int, UInt,
- *             Long, ULong,LongLong,ULongLong)*13,
+ *             Long, ULong,LongLong,ULongLong)*12,
  *         (Half, Float, Double, LongDouble,
- *             CFloat, CDouble, CLongDouble)*6,
+ *             CFloat, CDouble, CLongDouble)*5,
  *         (Half, Float, Double, LongDouble)*2#
  * #type = (npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
- *             npy_long, npy_ulong, npy_longlong, npy_ulonglong)*13,
+ *             npy_long, npy_ulong, npy_longlong, npy_ulonglong)*12,
  *         (npy_half, npy_float, npy_double, npy_longdouble,
- *             npy_cfloat, npy_cdouble, npy_clongdouble)*6,
+ *             npy_cfloat, npy_cdouble, npy_clongdouble)*5,
  *         (npy_half, npy_float, npy_double, npy_longdouble)*2#
  *
- * #oper = add*10, subtract*10, multiply*10, divide*10, remainder*10,
+ * #oper = add*10, subtract*10, multiply*10, remainder*10,
  *         divmod*10, floor_divide*10, lshift*10, rshift*10, and*10,
  *         or*10, xor*10, true_divide*10,
- *         add*7, subtract*7, multiply*7, divide*7, floor_divide*7, true_divide*7,
+ *         add*7, subtract*7, multiply*7, floor_divide*7, true_divide*7,
  *         divmod*4, remainder*4#
  *
- * #fperr = 1*70,0*50,1*10,
- *          1*42,
+ * #fperr = 1*60,0*50,1*10,
+ *          1*35,
  *          1*8#
- * #twoout = 0*50,1*10,0*70,
- *           0*42,
+ * #twoout = 0*40,1*10,0*70,
+ *           0*35,
  *           1*4,0*4#
  * #otype = (npy_byte, npy_ubyte, npy_short, npy_ushort, npy_int, npy_uint,
- *             npy_long, npy_ulong, npy_longlong, npy_ulonglong)*12,
+ *             npy_long, npy_ulong, npy_longlong, npy_ulonglong)*11,
  *         npy_float*4, npy_double*6,
  *         (npy_half, npy_float, npy_double, npy_longdouble,
- *             npy_cfloat, npy_cdouble, npy_clongdouble)*6,
+ *             npy_cfloat, npy_cdouble, npy_clongdouble)*5,
  *         (npy_half, npy_float, npy_double, npy_longdouble)*2#
  * #OName = (Byte, UByte, Short, UShort, Int, UInt,
- *              Long, ULong, LongLong, ULongLong)*12,
+ *              Long, ULong, LongLong, ULongLong)*11,
  *          Float*4, Double*6,
  *          (Half, Float, Double, LongDouble,
- *              CFloat, CDouble, CLongDouble)*6,
+ *              CFloat, CDouble, CLongDouble)*5,
  *          (Half, Float, Double, LongDouble)*2#
  */
 
-#if !defined(CODEGEN_SKIP_@oper@_FLAG)
-
 static PyObject *
 @name@_@oper@(PyObject *a, PyObject *b)
 {
@@ -904,12 +898,9 @@ static PyObject *
 #endif
     return ret;
 }
-#endif
 
 /**end repeat**/
 
-#undef CODEGEN_SKIP_divide_FLAG
-
 #define _IS_ZERO(x) (x == 0)
 
 /**begin repeat
@@ -1300,12 +1291,6 @@ static PyObject *
 
 /**end repeat**/
 
-#if defined(NPY_PY3K)
-#define NONZERO_NAME(prefix) prefix##bool
-#else
-#define NONZERO_NAME(prefix) prefix##nonzero
-#endif
-
 #define _IS_NONZERO(x) (x != 0)
 /**begin repeat
  *
@@ -1321,7 +1306,7 @@ static PyObject *
  * #nonzero = _IS_NONZERO*10, !npy_half_iszero, _IS_NONZERO*6#
  */
 static int
-NONZERO_NAME(@name@_)(PyObject *a)
+@name@_bool(PyObject *a)
 {
     int ret;
     @type@ arg1;
@@ -1330,7 +1315,7 @@ NONZERO_NAME(@name@_)(PyObject *a)
         if (PyErr_Occurred()) {
             return -1;
         }
-        return PyGenericArrType_Type.tp_as_number->NONZERO_NAME(nb_)(a);
+        return PyGenericArrType_Type.tp_as_number->nb_bool(a);
     }
 
     /*
@@ -1410,15 +1395,6 @@ static PyObject *
         return NULL;
     }
 
-#ifndef NPY_PY3K
-    /* Invoke long.__int__ to try to downcast */
-    {
-        PyObject *before_downcast = long_result;
-        long_result = Py_TYPE(long_result)->tp_as_number->nb_int(long_result);
-        Py_DECREF(before_downcast);
-    }
-#endif
-
     return long_result;
 }
 /**end repeat**/
@@ -1451,63 +1427,6 @@ static NPY_INLINE PyObject *
 }
 /**end repeat**/
 
-
-#if !defined(NPY_PY3K)
-
-/**begin repeat
- *
- * #name = (byte, ubyte, short, ushort, int, uint,
- *             long, ulong, longlong, ulonglong,
- *             half, float, double, longdouble,
- *             cfloat, cdouble, clongdouble)#
- * #Name = (Byte, UByte, Short, UShort, Int, UInt,
- *             Long, ULong, LongLong, ULongLong,
- *             Half, Float, Double, LongDouble,
- *             CFloat, CDouble, CLongDouble)#
- * #cmplx = (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1)#
- * #to_ctype = (, , , , , , , , , , npy_half_to_double, , , , , , )#
- * #func = (PyLong_FromLongLong,  PyLong_FromUnsignedLongLong)*5,
- *         PyLong_FromDouble*3, npy_longdouble_to_PyLong,
- *         PyLong_FromDouble*2, npy_longdouble_to_PyLong#
- */
-static NPY_INLINE PyObject *
-@name@_long(PyObject *obj)
-{
-#if @cmplx@
-    if (emit_complexwarning() < 0) {
-        return NULL;
-    }
-    return @func@(@to_ctype@(PyArrayScalar_VAL(obj, @Name@).real));
-#else
-    return @func@(@to_ctype@(PyArrayScalar_VAL(obj, @Name@)));
-#endif
-}
-/**end repeat**/
-
-/**begin repeat
- *
- * #name = (byte, ubyte, short, ushort, int, uint,
- *             long, ulong, longlong, ulonglong,
- *             half, float, double, longdouble,
- *             cfloat, cdouble, clongdouble)*2#
- * #oper = oct*17,  hex*17#
- * #kind = (int*5,  long*5,  int*2,  long*2,  int,  long*2)*2#
- * #cap = (Int*5,  Long*5,  Int*2,  Long*2,  Int,  Long*2)*2#
- */
-static PyObject *
-@name@_@oper@(PyObject *obj)
-{
-    PyObject *pyint;
-    pyint = @name@_@kind@(obj);
-    if (pyint == NULL) {
-        return NULL;
-    }
-    return Py@cap@_Type.tp_as_number->nb_@oper@(pyint);
-}
-/**end repeat**/
-
-#endif
-
 /**begin repeat
  * #oper = le, ge, lt, gt, eq, ne#
  * #op = <=, >=, <, >, ==, !=#
@@ -1594,65 +1513,28 @@ static PyObject*
  *          cfloat, cdouble, clongdouble#
 **/
 static PyNumberMethods @name@_as_number = {
-    (binaryfunc)@name@_add,                     /*nb_add*/
-    (binaryfunc)@name@_subtract,                /*nb_subtract*/
-    (binaryfunc)@name@_multiply,                /*nb_multiply*/
-#if !defined(NPY_PY3K)
-    (binaryfunc)@name@_divide,                  /*nb_divide*/
-#endif
-    (binaryfunc)@name@_remainder,               /*nb_remainder*/
-    (binaryfunc)@name@_divmod,                  /*nb_divmod*/
-    (ternaryfunc)@name@_power,                  /*nb_power*/
-    (unaryfunc)@name@_negative,
-    (unaryfunc)@name@_positive,                 /*nb_pos*/
-    (unaryfunc)@name@_absolute,                 /*nb_abs*/
-#if defined(NPY_PY3K)
-    (inquiry)@name@_bool,                       /*nb_bool*/
-#else
-    (inquiry)@name@_nonzero,                    /*nb_nonzero*/
-#endif
-    (unaryfunc)@name@_invert,                   /*nb_invert*/
-    (binaryfunc)@name@_lshift,                  /*nb_lshift*/
-    (binaryfunc)@name@_rshift,                  /*nb_rshift*/
-    (binaryfunc)@name@_and,                     /*nb_and*/
-    (binaryfunc)@name@_xor,                     /*nb_xor*/
-    (binaryfunc)@name@_or,                      /*nb_or*/
-#if !defined(NPY_PY3K)
-    0,                                          /*nb_coerce*/
-#endif
-    (unaryfunc)@name@_int,                      /*nb_int*/
-#if defined(NPY_PY3K)
-    (unaryfunc)0,                               /*nb_reserved*/
-#else
-    (unaryfunc)@name@_long,                     /*nb_long*/
-#endif
-    (unaryfunc)@name@_float,                    /*nb_float*/
-#if !defined(NPY_PY3K)
-    (unaryfunc)@name@_oct,                      /*nb_oct*/
-    (unaryfunc)@name@_hex,                      /*nb_hex*/
-#endif
-    0,                                          /*inplace_add*/
-    0,                                          /*inplace_subtract*/
-    0,                                          /*inplace_multiply*/
-#if !defined(NPY_PY3K)
-    0,                                          /*inplace_divide*/
-#endif
-    0,                                          /*inplace_remainder*/
-    0,                                          /*inplace_power*/
-    0,                                          /*inplace_lshift*/
-    0,                                          /*inplace_rshift*/
-    0,                                          /*inplace_and*/
-    0,                                          /*inplace_xor*/
-    0,                                          /*inplace_or*/
-    (binaryfunc)@name@_floor_divide,            /*nb_floor_divide*/
-    (binaryfunc)@name@_true_divide,             /*nb_true_divide*/
-    0,                                          /*nb_inplace_floor_divide*/
-    0,                                          /*nb_inplace_true_divide*/
-    (unaryfunc)NULL,                            /*nb_index*/
-#if PY_VERSION_HEX >= 0x03050000
-    0,                                          /*nb_matrix_multiply*/
-    0,                                          /*nb_inplace_matrix_multiply*/
-#endif
+    .nb_add = (binaryfunc)@name@_add,
+    .nb_subtract = (binaryfunc)@name@_subtract,
+    .nb_multiply = (binaryfunc)@name@_multiply,
+    .nb_remainder = (binaryfunc)@name@_remainder,
+    .nb_divmod = (binaryfunc)@name@_divmod,
+    .nb_power = (ternaryfunc)@name@_power,
+    .nb_negative = (unaryfunc)@name@_negative,
+    .nb_positive = (unaryfunc)@name@_positive,
+    .nb_absolute = (unaryfunc)@name@_absolute,
+    .nb_bool = (inquiry)@name@_bool,
+    .nb_invert = (unaryfunc)@name@_invert,
+    .nb_lshift = (binaryfunc)@name@_lshift,
+    .nb_rshift = (binaryfunc)@name@_rshift,
+    .nb_and = (binaryfunc)@name@_and,
+    .nb_xor = (binaryfunc)@name@_xor,
+    .nb_or = (binaryfunc)@name@_or,
+    .nb_int = (unaryfunc)@name@_int,
+    .nb_float = (unaryfunc)@name@_float,
+    .nb_floor_divide = (binaryfunc)@name@_floor_divide,
+    .nb_true_divide = (binaryfunc)@name@_true_divide,
+    /* TODO: This struct/initialization should not be split between files */
+    .nb_index = (unaryfunc)NULL,  /* set in add_scalarmath below */
 };
 /**end repeat**/
 
index 74f52cc9d52997311aebd40a21ef0d683118b293..4f511cf0983f410d855cfedb348e06e3536b6479 100644 (file)
@@ -18,6 +18,7 @@
 #include "lowlevel_strided_loops.h"
 #include "numpy/npy_common.h"
 #include "numpy/npy_math.h"
+#include "npy_simd_data.h"
 #ifdef NPY_HAVE_SSE2_INTRINSICS
 #include <emmintrin.h>
 #if !defined(_MSC_VER) || _MSC_VER >= 1600
 
 #define VECTOR_SIZE_BYTES 16
 
-static NPY_INLINE npy_uintp
-abs_ptrdiff(char *a, char *b)
+/*
+ * MAX_STEP_SIZE is used to determine if we need to use SIMD version of the ufunc.
+ * Very large step size can be as slow as processing it using scalar. The
+ * value of 2097152 ( = 2MB) was chosen using 2 considerations:
+ * 1) Typical linux kernel page size is 4Kb, but sometimes it could also be 2MB
+ *    which is == 2097152 Bytes. For a step size as large as this, surely all
+ *    the loads/stores of gather/scatter instructions falls on 16 different pages
+ *    which one would think would slow down gather/scatter instructions.
+ * 2) It additionally satisfies MAX_STEP_SIZE*16/esize < NPY_MAX_INT32 which
+ *    allows us to use i32 version of gather/scatter (as opposed to the i64 version)
+ *    without problems (step larger than NPY_MAX_INT32*esize/16 would require use of
+ *    i64gather/scatter). esize = element size = 4/8 bytes for float/double.
+ */
+#define MAX_STEP_SIZE 2097152
+
+/*
+ * nomemoverlap - returns true if two strided arrays have an overlapping
+ * region in memory. ip_size/op_size = size of the arrays which can be negative
+ * indicating negative steps.
+ */
+static NPY_INLINE npy_bool
+nomemoverlap(char *ip,
+             npy_intp ip_size,
+             char *op,
+             npy_intp op_size)
 {
-    return (a > b) ? (a - b) : (b - a);
+    char *ip_start, *ip_end, *op_start, *op_end;
+    if (ip_size < 0) {
+        ip_start = ip + ip_size;
+        ip_end = ip;
+    }
+    else {
+        ip_start = ip;
+        ip_end = ip + ip_size;
+    }
+    if (op_size < 0) {
+        op_start = op + op_size;
+        op_end = op;
+    }
+    else {
+        op_start = op;
+        op_end = op + op_size;
+    }
+    return (ip_start > op_end) | (op_start > ip_end);
 }
 
+#define IS_BINARY_STRIDE_ONE(esize, vsize) \
+    ((steps[0] == esize) && \
+     (steps[1] == esize) && \
+     (steps[2] == esize) && \
+     (abs_ptrdiff(args[2], args[0]) >= vsize) && \
+     (abs_ptrdiff(args[2], args[1]) >= vsize))
+
 /*
  * stride is equal to element size and input and destination are equal or
  * don't overlap within one register. The check of the steps against
@@ -52,13 +100,34 @@ abs_ptrdiff(char *a, char *b)
       ((abs_ptrdiff(args[1], args[0]) == 0))))
 
 /*
- * output should be contiguous, can handle strided input data
+ * Avoid using SIMD for very large step sizes for several reasons:
+ * 1) Supporting large step sizes requires use of i64gather/scatter_ps instructions,
+ *    in which case we need two i64gather instructions and an additional vinsertf32x8
+ *    instruction to load a single zmm register (since one i64gather instruction
+ *    loads into a ymm register). This is not ideal for performance.
+ * 2) Gather and scatter instructions can be slow when the loads/stores
+ *    cross page boundaries.
+ *
+ * We instead rely on i32gather/scatter_ps instructions which use a 32-bit index
+ * element. The index needs to be < INT_MAX to avoid overflow. MAX_STEP_SIZE
+ * ensures this. The condition also requires that the input and output arrays
+ * should have no overlap in memory.
+ */
+#define IS_BINARY_SMALL_STEPS_AND_NOMEMOVERLAP \
+    ((abs(steps[0]) < MAX_STEP_SIZE)  && \
+     (abs(steps[1]) < MAX_STEP_SIZE)  && \
+     (abs(steps[2]) < MAX_STEP_SIZE)  && \
+     (nomemoverlap(args[0], steps[0] * dimensions[0], args[2], steps[2] * dimensions[0])) && \
+     (nomemoverlap(args[1], steps[1] * dimensions[0], args[2], steps[2] * dimensions[0])))
+
+/*
+ * 1) Output should be contiguous, can handle strided input data
+ * 2) Input step should be smaller than MAX_STEP_SIZE for performance
+ * 3) Input and output arrays should have no overlap in memory
  */
 #define IS_OUTPUT_BLOCKABLE_UNARY(esize, vsize) \
-    (steps[1] == (esize) && \
-     (npy_is_aligned(args[0], esize) && npy_is_aligned(args[1], esize)) && \
-     ((abs_ptrdiff(args[1], args[0]) >= (vsize)) || \
-      ((abs_ptrdiff(args[1], args[0]) == 0))))
+    (steps[1] == (esize) && abs(steps[0]) < MAX_STEP_SIZE && \
+     (nomemoverlap(args[1], steps[1] * dimensions[0], args[0], steps[0] * dimensions[0])))
 
 #define IS_BLOCKABLE_REDUCE(esize, vsize) \
     (steps[1] == (esize) && abs_ptrdiff(args[1], args[0]) >= (vsize) && \
@@ -123,12 +192,110 @@ abs_ptrdiff(char *a, char *b)
  * if it was run returns true and false if nothing was done
  */
 
+/*
+ *****************************************************************************
+ **                           CMPLX DISPATCHERS
+ *****************************************************************************
+ */
+
+/**begin repeat
+ * #TYPE = CFLOAT, CDOUBLE#
+ * #type= npy_float, npy_double#
+ * #esize = 8, 16#
+ */
+
+/**begin repeat1
+ *  #func = add, subtract, multiply#
+ */
+
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+static NPY_INLINE NPY_GCC_TARGET_AVX512F void
+AVX512F_@func@_@TYPE@(char **args, const npy_intp *dimensions, const npy_intp *steps);
+#endif
+
+static NPY_INLINE int
+run_binary_avx512f_@func@_@TYPE@(char **args, const npy_intp *dimensions, const npy_intp *steps)
+{
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+    if (IS_BINARY_STRIDE_ONE(@esize@, 64)) {
+        AVX512F_@func@_@TYPE@(args, dimensions, steps);
+        return 1;
+    }
+    else
+        return 0;
+#endif
+    return 0;
+}
+
+/**end repeat1**/
+
+/**begin repeat1
+ *  #func = square, absolute, conjugate#
+ *  #outsize = 1, 2, 1#
+ *  #max_stride = 2, 8, 8#
+ */
+
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+static NPY_INLINE NPY_GCC_TARGET_AVX512F void
+AVX512F_@func@_@TYPE@(@type@*, @type@*, const npy_intp n, const npy_intp stride);
+#endif
+
+static NPY_INLINE int
+run_unary_avx512f_@func@_@TYPE@(char **args, const npy_intp *dimensions, const npy_intp *steps)
+{
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+    if ((IS_OUTPUT_BLOCKABLE_UNARY((npy_uint)(@esize@/@outsize@), 64)) && (labs(steps[0]) < 2*@max_stride@*@esize@)) {
+        AVX512F_@func@_@TYPE@((@type@*)args[1], (@type@*)args[0], dimensions[0], steps[0]);
+        return 1;
+    }
+    else
+        return 0;
+#endif
+    return 0;
+}
+
+/**end repeat1**/
+/**end repeat**/
+
 /*
  *****************************************************************************
  **                           FLOAT DISPATCHERS
  *****************************************************************************
  */
 
+/**begin repeat
+ * #type = npy_float, npy_double, npy_longdouble#
+ * #TYPE = FLOAT, DOUBLE, LONGDOUBLE#
+ * #EXISTS = 1, 1, 0#
+ */
+
+/**begin repeat1
+ *  #func = maximum, minimum#
+ */
+
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS && @EXISTS@
+static NPY_INLINE NPY_GCC_TARGET_AVX512F void
+AVX512F_@func@_@TYPE@(char **args, npy_intp const *dimensions, npy_intp const *steps);
+#endif
+
+static NPY_INLINE int
+run_binary_avx512f_@func@_@TYPE@(char **args, npy_intp const *dimensions, npy_intp const *steps)
+{
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS && @EXISTS@
+    if (IS_BINARY_SMALL_STEPS_AND_NOMEMOVERLAP) {
+        AVX512F_@func@_@TYPE@(args, dimensions, steps);
+        return 1;
+    }
+    else
+        return 0;
+#endif
+    return 0;
+}
+
+
+/**end repeat1**/
+/**end repeat**/
+
 /**begin repeat
  * #ISA = FMA, AVX512F#
  * #isa = fma, avx512f#
@@ -153,7 +320,7 @@ static NPY_INLINE NPY_GCC_TARGET_@ISA@ void
 #endif
 
 static NPY_INLINE int
-run_unary_@isa@_@func@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps)
+run_unary_@isa@_@func@_@TYPE@(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
 #if defined @CHK@ && defined NPY_HAVE_SSE2_INTRINSICS
     if (IS_OUTPUT_BLOCKABLE_UNARY(sizeof(@type@), @REGISTER_SIZE@)) {
@@ -179,7 +346,7 @@ static NPY_INLINE void
 #endif
 
 static NPY_INLINE int
-run_unary_@isa@_@func@_FLOAT(char **args, npy_intp *dimensions, npy_intp *steps)
+run_unary_@isa@_@func@_FLOAT(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
 #if defined @CHK@ && defined NPY_HAVE_SSE2_INTRINSICS
     if (IS_OUTPUT_BLOCKABLE_UNARY(sizeof(npy_float), @REGISTER_SIZE@)) {
@@ -200,7 +367,7 @@ static NPY_INLINE void
 #endif
 
 static NPY_INLINE int
-run_unary_@isa@_sincos_FLOAT(char **args, npy_intp *dimensions, npy_intp *steps, NPY_TRIG_OP my_trig_op)
+run_unary_@isa@_sincos_FLOAT(char **args, npy_intp const *dimensions, npy_intp const *steps, NPY_TRIG_OP my_trig_op)
 {
 #if defined @CHK@ && defined NPY_HAVE_SSE2_INTRINSICS
     if (IS_OUTPUT_BLOCKABLE_UNARY(sizeof(npy_float), @REGISTER_SIZE@)) {
@@ -215,6 +382,25 @@ run_unary_@isa@_sincos_FLOAT(char **args, npy_intp *dimensions, npy_intp *steps,
 
 /**end repeat**/
 
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined  NPY_HAVE_SSE2_INTRINSICS
+static NPY_INLINE void
+AVX512F_exp_DOUBLE(npy_double *, npy_double *, const npy_intp n, const npy_intp stride);
+#endif
+static NPY_INLINE int
+run_unary_avx512f_exp_DOUBLE(char **args, npy_intp const *dimensions, npy_intp const *steps)
+{
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+#if !(defined(__clang__) && (__clang_major__ < 10 || (__clang_major__ == 10 && __clang_minor__ < 1)))
+    if (IS_OUTPUT_BLOCKABLE_UNARY(sizeof(npy_double), 64)) {
+        AVX512F_exp_DOUBLE((npy_double*)args[1], (npy_double*)args[0], dimensions[0], steps[0]);
+        return 1;
+    }
+    else
+        return 0;
+#endif
+#endif
+    return 0;
+}
 
 /**begin repeat
  * Float types
@@ -238,7 +424,7 @@ sse2_@func@_@TYPE@(@type@ *, @type@ *, const npy_intp n);
 #endif
 
 static NPY_INLINE int
-run_@name@_simd_@func@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps)
+run_@name@_simd_@func@_@TYPE@(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
 #if @vector@ && defined NPY_HAVE_SSE2_INTRINSICS
     if (@check@(sizeof(@type@), VECTOR_SIZE_BYTES)) {
@@ -272,7 +458,7 @@ sse2_binary_scalar2_@kind@_@TYPE@(@type@ * op, @type@ * ip1, @type@ * ip2,
 #endif
 
 static NPY_INLINE int
-run_binary_simd_@kind@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps)
+run_binary_simd_@kind@_@TYPE@(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
 #if @vector@ && defined NPY_HAVE_SSE2_INTRINSICS
     @type@ * ip1 = (@type@ *)args[0];
@@ -280,11 +466,11 @@ run_binary_simd_@kind@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps
     @type@ * op = (@type@ *)args[2];
     npy_intp n = dimensions[0];
 #if defined __AVX512F__
-    const npy_intp vector_size_bytes = 64;
+    const npy_uintp vector_size_bytes = 64;
 #elif defined __AVX2__
-    const npy_intp vector_size_bytes = 32;
+    const npy_uintp vector_size_bytes = 32;
 #else
-    const npy_intp vector_size_bytes = 32;
+    const npy_uintp vector_size_bytes = 32;
 #endif
     /* argument one scalar */
     if (IS_BLOCKABLE_BINARY_SCALAR1(sizeof(@type@), vector_size_bytes)) {
@@ -328,7 +514,7 @@ sse2_binary_scalar2_@kind@_@TYPE@(npy_bool * op, @type@ * ip1, @type@ * ip2,
 #endif
 
 static NPY_INLINE int
-run_binary_simd_@kind@_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps)
+run_binary_simd_@kind@_@TYPE@(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
 #if @vector@ && @simd@ && defined NPY_HAVE_SSE2_INTRINSICS
     @type@ * ip1 = (@type@ *)args[0];
@@ -367,7 +553,7 @@ sse2_@kind@_@TYPE@(npy_bool * op, @type@ * ip1, npy_intp n);
 #endif
 
 static NPY_INLINE int
-run_@kind@_simd_@TYPE@(char **args, npy_intp *dimensions, npy_intp *steps)
+run_@kind@_simd_@TYPE@(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
 #if @vector@ && defined NPY_HAVE_SSE2_INTRINSICS
     if (steps[0] == sizeof(@type@) && steps[1] == 1 &&
@@ -403,7 +589,7 @@ sse2_reduce_@kind@_BOOL(npy_bool * op, npy_bool * ip, npy_intp n);
 #endif
 
 static NPY_INLINE int
-run_binary_simd_@kind@_BOOL(char **args, npy_intp *dimensions, npy_intp *steps)
+run_binary_simd_@kind@_BOOL(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
 #if defined NPY_HAVE_SSE2_INTRINSICS
     if (sizeof(npy_bool) == 1 &&
@@ -418,7 +604,7 @@ run_binary_simd_@kind@_BOOL(char **args, npy_intp *dimensions, npy_intp *steps)
 
 
 static NPY_INLINE int
-run_reduce_simd_@kind@_BOOL(char **args, npy_intp *dimensions, npy_intp *steps)
+run_reduce_simd_@kind@_BOOL(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
 #if defined NPY_HAVE_SSE2_INTRINSICS
     if (sizeof(npy_bool) == 1 &&
@@ -443,7 +629,7 @@ sse2_@kind@_BOOL(npy_bool *, npy_bool *, const npy_intp n);
 #endif
 
 static NPY_INLINE int
-run_unary_simd_@kind@_BOOL(char **args, npy_intp *dimensions, npy_intp *steps)
+run_unary_simd_@kind@_BOOL(char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
 #if defined NPY_HAVE_SSE2_INTRINSICS
     if (sizeof(npy_bool) == 1 &&
@@ -1134,7 +1320,7 @@ sse2_@kind@_@TYPE@(@type@ * ip, @type@ * op, const npy_intp n)
         /* Order of operations important for MSVC 2015 */
         *op = (*op @OP@ ip[i] || npy_isnan(*op)) ? *op : ip[i];
     }
-    assert((npy_uintp)n < (stride) || npy_is_aligned(&ip[i], VECTOR_SIZE_BYTES));
+    assert(n < stride || npy_is_aligned(&ip[i], VECTOR_SIZE_BYTES));
     if (i + 3 * stride <= n) {
         /* load the first elements */
         @vtype@ c1 = @vpre@_load_@vsuf@((@type@*)&ip[i]);
@@ -1523,11 +1709,35 @@ avx512_scalef_ps(__m512 poly, __m512 quadrant)
 {
     return _mm512_scalef_ps(poly, quadrant);
 }
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F __m512d
+avx512_permute_x4var_pd(__m512d t0,
+                        __m512d t1,
+                        __m512d t2,
+                        __m512d t3,
+                        __m512i index)
+{
+
+    __mmask8 lut_mask = _mm512_cmp_epi64_mask(index, _mm512_set1_epi64(15),
+                                  _MM_CMPINT_GT);
+    __m512d res1 = _mm512_permutex2var_pd(t0, index, t1);
+    __m512d res2 = _mm512_permutex2var_pd(t2, index, t3);
+    return _mm512_mask_blend_pd(lut_mask, res1, res2);
+}
+
 /**begin repeat
  *  #vsub  = ps, pd#
+ *  #type= npy_float, npy_double#
  *  #epi_vsub  = epi32, epi64#
  *  #vtype = __m512, __m512d#
+ *  #mask = __mmask16, __mmask8#
  *  #and_const = 0x7fffffff, 0x7fffffffffffffffLL#
+ *  #neg_mask = 0x80000000, 0x8000000000000000#
+ *  #perm_ = 0xb1, 0x55#
+ *  #cmpx_img_mask = 0xAAAA, 0xAA#
+ *  #cmpx_re_mask = 0x5555, 0x55#
+ *  #INF = NPY_INFINITYF, NPY_INFINITY#
+ *  #NAN = NPY_NANF, NPY_NAN#
  */
 static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F @vtype@
 avx512_abs_@vsub@(@vtype@ x)
@@ -1565,6 +1775,96 @@ avx512_trunc_@vsub@(@vtype@ x)
 {
     return _mm512_roundscale_@vsub@(x, 0x0B);
 }
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F @vtype@
+avx512_hadd_@vsub@(const @vtype@ x)
+{
+    return _mm512_add_@vsub@(x, _mm512_permute_@vsub@(x, @perm_@));
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F @vtype@
+avx512_hsub_@vsub@(const @vtype@ x)
+{
+    return _mm512_sub_@vsub@(x, _mm512_permute_@vsub@(x, @perm_@));
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F @vtype@
+avx512_cabsolute_@vsub@(const @vtype@ x1,
+                        const @vtype@ x2,
+                        const __m512i re_indices,
+                        const __m512i im_indices)
+{
+    @vtype@ inf = _mm512_set1_@vsub@(@INF@);
+    @vtype@ nan = _mm512_set1_@vsub@(@NAN@);
+    @vtype@ x1_abs = avx512_abs_@vsub@(x1);
+    @vtype@ x2_abs = avx512_abs_@vsub@(x2);
+    @vtype@ re = _mm512_permutex2var_@vsub@(x1_abs, re_indices, x2_abs);
+    @vtype@ im = _mm512_permutex2var_@vsub@(x1_abs, im_indices , x2_abs);
+    /*
+     * If real or imag = INF, then convert it to inf + j*inf
+     * Handles: inf + j*nan, nan + j*inf
+     */
+    @mask@ re_infmask = _mm512_cmp_@vsub@_mask(re, inf, _CMP_EQ_OQ);
+    @mask@ im_infmask = _mm512_cmp_@vsub@_mask(im, inf, _CMP_EQ_OQ);
+    im = _mm512_mask_mov_@vsub@(im, re_infmask, inf);
+    re = _mm512_mask_mov_@vsub@(re, im_infmask, inf);
+
+    /*
+     * If real or imag = NAN, then convert it to nan + j*nan
+     * Handles: x + j*nan, nan + j*x
+     */
+    @mask@ re_nanmask = _mm512_cmp_@vsub@_mask(re, re, _CMP_NEQ_UQ);
+    @mask@ im_nanmask = _mm512_cmp_@vsub@_mask(im, im, _CMP_NEQ_UQ);
+    im = _mm512_mask_mov_@vsub@(im, re_nanmask, nan);
+    re = _mm512_mask_mov_@vsub@(re, im_nanmask, nan);
+
+    @vtype@ larger  = _mm512_max_@vsub@(re, im);
+    @vtype@ smaller = _mm512_min_@vsub@(im, re);
+
+    /*
+     * Calculate div_mask to prevent 0./0. and inf/inf operations in div
+     */
+    @mask@ zeromask = _mm512_cmp_@vsub@_mask(larger, _mm512_setzero_@vsub@(), _CMP_EQ_OQ);
+    @mask@ infmask = _mm512_cmp_@vsub@_mask(smaller, inf, _CMP_EQ_OQ);
+    @mask@ div_mask = _mm512_knot(_mm512_kor(zeromask, infmask));
+    @vtype@ ratio = _mm512_maskz_div_@vsub@(div_mask, smaller, larger);
+    @vtype@ hypot = _mm512_sqrt_@vsub@(_mm512_fmadd_@vsub@(
+                                        ratio, ratio, _mm512_set1_@vsub@(1.0f)));
+    return _mm512_mul_@vsub@(hypot, larger);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F @vtype@
+avx512_conjugate_@vsub@(const @vtype@ x)
+{
+    /*
+     * __mm512_mask_xor_ps/pd requires AVX512DQ. We cast it to __m512i and
+     * use the xor_epi32/64 uinstruction instead. Cast is a zero latency instruction
+     */
+    __m512i cast_x = _mm512_cast@vsub@_si512(x);
+    __m512i res = _mm512_mask_xor_@epi_vsub@(cast_x, @cmpx_img_mask@,
+                                        cast_x, _mm512_set1_@epi_vsub@(@neg_mask@));
+    return _mm512_castsi512_@vsub@(res);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F @vtype@
+avx512_cmul_@vsub@(@vtype@ x1, @vtype@ x2)
+{
+    // x1 = r1, i1
+    // x2 = r2, i2
+    @vtype@ x3  = _mm512_permute_@vsub@(x2, @perm_@);   // i2, r2
+    @vtype@ x12 = _mm512_mul_@vsub@(x1, x2);            // r1*r2, i1*i2
+    @vtype@ x13 = _mm512_mul_@vsub@(x1, x3);            // r1*i2, r2*i1
+    @vtype@ outreal = avx512_hsub_@vsub@(x12);          // r1*r2 - i1*i2, r1*r2 - i1*i2
+    @vtype@ outimg  = avx512_hadd_@vsub@(x13);          // r1*i2 + i1*r2, r1*i2 + i1*r2
+    return _mm512_mask_blend_@vsub@(@cmpx_img_mask@, outreal, outimg);
+}
+
+static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F @vtype@
+avx512_csquare_@vsub@(@vtype@ x)
+{
+    return avx512_cmul_@vsub@(x, x);
+}
+
 /**end repeat**/
 #endif
 
@@ -1671,6 +1971,101 @@ static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ @vtype@d
 #endif
 /**end repeat**/
 
+/**begin repeat
+ * #type = npy_float, npy_double#
+ * #TYPE = FLOAT, DOUBLE#
+ * #num_lanes = 16, 8#
+ * #vsuffix = ps, pd#
+ * #mask = __mmask16, __mmask8#
+ * #vtype = __m512, __m512d#
+ * #scale = 4, 8#
+ * #vindextype = __m512i, __m256i#
+ * #vindexsize = 512, 256#
+ * #vindexload = _mm512_loadu_si512, _mm256_loadu_si256#
+ */
+
+/**begin repeat1
+ *  #func = maximum, minimum#
+ *  #vectorf = max, min#
+ */
+
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+static NPY_INLINE NPY_GCC_TARGET_AVX512F void
+AVX512F_@func@_@TYPE@(char **args, npy_intp const *dimensions, npy_intp const *steps)
+{
+    const npy_intp stride_ip1 = steps[0]/(npy_intp)sizeof(@type@);
+    const npy_intp stride_ip2 = steps[1]/(npy_intp)sizeof(@type@);
+    const npy_intp stride_op = steps[2]/(npy_intp)sizeof(@type@);
+    const npy_intp array_size = dimensions[0];
+    npy_intp num_remaining_elements = array_size;
+    @type@* ip1 = (@type@*) args[0];
+    @type@* ip2 = (@type@*) args[1];
+    @type@* op  = (@type@*) args[2];
+
+    @mask@ load_mask = avx512_get_full_load_mask_@vsuffix@();
+
+    /*
+     * Note: while generally indices are npy_intp, we ensure that our maximum index
+     * will fit in an int32 as a precondition for this function via
+     * IS_BINARY_SMALL_STEPS_AND_NOMEMOVERLAP
+     */
+
+    npy_int32 index_ip1[@num_lanes@], index_ip2[@num_lanes@], index_op[@num_lanes@];
+    for (npy_int32 ii = 0; ii < @num_lanes@; ii++) {
+        index_ip1[ii] = ii*stride_ip1;
+        index_ip2[ii] = ii*stride_ip2;
+        index_op[ii] = ii*stride_op;
+    }
+    @vindextype@ vindex_ip1 = @vindexload@((@vindextype@*)&index_ip1[0]);
+    @vindextype@ vindex_ip2 = @vindexload@((@vindextype@*)&index_ip2[0]);
+    @vindextype@ vindex_op  = @vindexload@((@vindextype@*)&index_op[0]);
+    @vtype@ zeros_f = _mm512_setzero_@vsuffix@();
+
+    while (num_remaining_elements > 0) {
+        if (num_remaining_elements < @num_lanes@) {
+            load_mask = avx512_get_partial_load_mask_@vsuffix@(
+                                    num_remaining_elements, @num_lanes@);
+        }
+        @vtype@ x1, x2;
+        if (stride_ip1 == 1) {
+            x1 = avx512_masked_load_@vsuffix@(load_mask, ip1);
+        }
+        else {
+            x1 = avx512_masked_gather_@vsuffix@(zeros_f, ip1, vindex_ip1, load_mask);
+        }
+        if (stride_ip2 == 1) {
+            x2 = avx512_masked_load_@vsuffix@(load_mask, ip2);
+        }
+        else {
+            x2 = avx512_masked_gather_@vsuffix@(zeros_f, ip2, vindex_ip2, load_mask);
+        }
+
+        /*
+         * when only one of the argument is a nan, the maxps/maxpd instruction
+         * returns the second argument. The additional blend instruction fixes
+         * this issue to conform with NumPy behaviour.
+         */
+        @mask@ nan_mask = _mm512_cmp_@vsuffix@_mask(x1, x1, _CMP_NEQ_UQ);
+        @vtype@ out = _mm512_@vectorf@_@vsuffix@(x1, x2);
+        out = _mm512_mask_blend_@vsuffix@(nan_mask, out, x1);
+
+        if (stride_op == 1) {
+            _mm512_mask_storeu_@vsuffix@(op, load_mask, out);
+        }
+        else {
+            /* scatter! */
+            _mm512_mask_i32scatter_@vsuffix@(op, load_mask, vindex_op, out, @scale@);
+        }
+
+        ip1 += @num_lanes@*stride_ip1;
+        ip2 += @num_lanes@*stride_ip2;
+        op += @num_lanes@*stride_op;
+        num_remaining_elements -= @num_lanes@;
+    }
+}
+#endif
+/**end repeat**/
+/**end repeat1**/
 
 /**begin repeat
  * #ISA = FMA, AVX512F#
@@ -1699,16 +2094,23 @@ static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
                    const npy_intp array_size,
                    const npy_intp steps)
 {
-    const npy_intp stride = steps/sizeof(npy_float);
-    const npy_int num_lanes = @BYTES@/sizeof(npy_float);
+    const npy_intp stride = steps/(npy_intp)sizeof(npy_float);
+    const npy_int num_lanes = @BYTES@/(npy_intp)sizeof(npy_float);
     npy_intp num_remaining_elements = array_size;
     @vtype@ ones_f = _mm@vsize@_set1_ps(1.0f);
     @mask@ load_mask = @isa@_get_full_load_mask_ps();
 #if @replace_0_with_1@
     @mask@ inv_load_mask = @isa@_invert_mask_ps(load_mask);
 #endif
-    npy_int indexarr[16];
-    for (npy_int ii = 0; ii < 16; ii++) {
+
+    /*
+     * Note: while generally indices are npy_intp, we ensure that our maximum index
+     * will fit in an int32 as a precondition for this function via
+     * IS_OUTPUT_BLOCKABLE_UNARY
+     */
+
+    npy_int32 indexarr[16];
+    for (npy_int32 ii = 0; ii < 16; ii++) {
         indexarr[ii] = ii*stride;
     }
     @vtype@i vindex = _mm@vsize@_loadu_si@vsize@((@vtype@i*)&indexarr[0]);
@@ -1778,16 +2180,22 @@ static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
                     const npy_intp array_size,
                     const npy_intp steps)
 {
-    const npy_intp stride = steps/sizeof(npy_double);
-    const npy_int num_lanes = @BYTES@/sizeof(npy_double);
+    const npy_intp stride = steps/(npy_intp)sizeof(npy_double);
+    const npy_int num_lanes = @BYTES@/(npy_intp)sizeof(npy_double);
     npy_intp num_remaining_elements = array_size;
     @mask@ load_mask = @isa@_get_full_load_mask_pd();
 #if @replace_0_with_1@
     @mask@ inv_load_mask = @isa@_invert_mask_pd(load_mask);
 #endif
     @vtype@ ones_d = _mm@vsize@_set1_pd(1.0f);
-    npy_int indexarr[8];
-    for (npy_int ii = 0; ii < 8; ii++) {
+
+    /*
+     * Note: while generally indices are npy_intp, we ensure that our maximum index
+     * will fit in an int32 as a precondition for this function via
+     * IS_OUTPUT_BLOCKABLE_UNARY
+     */
+    npy_int32 indexarr[8];
+    for (npy_int32 ii = 0; ii < 8; ii++) {
         indexarr[ii] = ii*stride;
     }
     @vindextype@ vindex = @vindexload@((@vindextype@*)&indexarr[0]);
@@ -1856,7 +2264,7 @@ static NPY_INLINE NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
  * method: x* = x - y*PI/2, where y = rint(x*2/PI). x* \in [-PI/4, PI/4].
  * (3) Map cos(x) to (+/-)sine or (+/-)cosine of x* based on the quadrant k =
  * int(y).
- * (4) For elements outside that range, Cody-Waite reduction peforms poorly
+ * (4) For elements outside that range, Cody-Waite reduction performs poorly
  * leading to catastrophic cancellation. We compute cosine by calling glibc in
  * a scalar fashion.
  * (5) Vectorized implementation has a max ULP of 1.49 and performs at least
@@ -1874,8 +2282,8 @@ static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
                    const npy_intp steps,
                    NPY_TRIG_OP my_trig_op)
 {
-    const npy_intp stride = steps/sizeof(npy_float);
-    const npy_int num_lanes = @BYTES@/sizeof(npy_float);
+    const npy_intp stride = steps/(npy_intp)sizeof(npy_float);
+    const npy_int num_lanes = @BYTES@/(npy_intp)sizeof(npy_float);
     npy_float large_number = 71476.0625f;
     if (my_trig_op == npy_compute_sin) {
         large_number = 117435.992f;
@@ -1905,8 +2313,14 @@ static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
     @mask@ nan_mask, glibc_mask, sine_mask, negate_mask;
     @mask@ load_mask = @isa@_get_full_load_mask_ps();
     npy_intp num_remaining_elements = array_size;
-    npy_int indexarr[16];
-    for (npy_int ii = 0; ii < 16; ii++) {
+
+    /*
+     * Note: while generally indices are npy_intp, we ensure that our maximum index
+     * will fit in an int32 as a precondition for this function via
+     * IS_OUTPUT_BLOCKABLE_UNARY
+     */
+    npy_int32 indexarr[16];
+    for (npy_int32 ii = 0; ii < 16; ii++) {
         indexarr[ii] = ii*stride;
     }
     @vtype@i vindex = _mm@vsize@_loadu_si@vsize@((@vtype@i*)&indexarr[0]);
@@ -1975,17 +2389,17 @@ static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
 
         /* process elements using glibc for large elements */
         if (my_trig_op == npy_compute_cos) {
-            for (int ii = 0; iglibc_mask != 0; ii++) {
+            for (int ii = 0, jj = 0; iglibc_mask != 0; ii++, jj += stride) {
                 if (iglibc_mask & 0x01) {
-                    op[ii] = npy_cosf(ip[ii]);
+                    op[ii] = npy_cosf(ip[jj]);
                 }
                 iglibc_mask  = iglibc_mask >> 1;
             }
         }
         else {
-            for (int ii = 0; iglibc_mask != 0; ii++) {
+            for (int ii = 0, jj = 0; iglibc_mask != 0; ii++, jj += stride) {
                 if (iglibc_mask & 0x01) {
-                    op[ii] = npy_sinf(ip[ii]);
+                    op[ii] = npy_sinf(ip[jj]);
                 }
                 iglibc_mask  = iglibc_mask >> 1;
             }
@@ -2017,12 +2431,18 @@ static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
                 const npy_intp array_size,
                 const npy_intp steps)
 {
-    const npy_intp stride = steps/sizeof(npy_float);
-    const npy_int num_lanes = @BYTES@/sizeof(npy_float);
+    const npy_intp stride = steps/(npy_intp)sizeof(npy_float);
+    const npy_int num_lanes = @BYTES@/(npy_intp)sizeof(npy_float);
     npy_float xmax = 88.72283935546875f;
     npy_float xmin = -103.97208404541015625f;
-    npy_int indexarr[16];
-    for (npy_int ii = 0; ii < 16; ii++) {
+
+    /*
+     * Note: while generally indices are npy_intp, we ensure that our maximum index
+     * will fit in an int32 as a precondition for this function via
+     * IS_OUTPUT_BLOCKABLE_UNARY
+     */
+    npy_int32 indexarr[16];
+    for (npy_int32 ii = 0; ii < 16; ii++) {
         indexarr[ii] = ii*stride;
     }
 
@@ -2143,10 +2563,16 @@ static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
                 const npy_intp array_size,
                 const npy_intp steps)
 {
-    const npy_intp stride = steps/sizeof(npy_float);
-    const npy_int num_lanes = @BYTES@/sizeof(npy_float);
-    npy_int indexarr[16];
-    for (npy_int ii = 0; ii < 16; ii++) {
+    const npy_intp stride = steps/(npy_intp)sizeof(npy_float);
+    const npy_int num_lanes = @BYTES@/(npy_intp)sizeof(npy_float);
+
+    /*
+     * Note: while generally indices are npy_intp, we ensure that our maximum index
+     * will fit in an int32 as a precondition for this function via
+     * IS_OUTPUT_BLOCKABLE_UNARY
+     */
+    npy_int32 indexarr[16];
+    for (npy_int32 ii = 0; ii < 16; ii++) {
         indexarr[ii] = ii*stride;
     }
 
@@ -2258,6 +2684,335 @@ static NPY_GCC_OPT_3 NPY_GCC_TARGET_@ISA@ void
 #endif
 /**end repeat**/
 
+/*
+ * Vectorized implementation of exp double using AVX512
+ * Reference: Tang, P.T.P., "Table-driven implementation of the
+ *  exponential function in IEEE floating-point
+ *  arithmetic," ACM Transactions on Mathematical
+ *  Software, vol. 15, pp. 144-157, 1989.
+ * 1) if x > mTH_max or x is INF; return INF (overflow)
+ * 2) if x < mTH_min; return 0.0f (underflow)
+ * 3) if abs(x) < mTH_nearzero; return 1.0f + x
+ * 4) if x is Nan; return Nan
+ * 5) Range reduction:
+ *    x = (32m + j)ln2 / 32 + r; r in [-ln2/64, ln2/64]
+ * 6) exp(r) - 1 is approximated by a polynomial function p(r)
+ *    exp(x) = 2^m(2^(j/32) + 2^(j/32)p(r));
+ */
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS
+#if !(defined(__clang__) && (__clang_major__ < 10 || (__clang_major__ == 10 && __clang_minor__ < 1)))
+static NPY_GCC_OPT_3 NPY_GCC_TARGET_AVX512F void
+AVX512F_exp_DOUBLE(npy_double * op,
+                npy_double * ip,
+                const npy_intp array_size,
+                const npy_intp steps)
+{
+    npy_intp num_remaining_elements = array_size;
+    const npy_intp stride = steps / (npy_intp)sizeof(npy_double);
+    const npy_int num_lanes = 64 / (npy_intp)sizeof(npy_double);
+    npy_int32 indexarr[8];
+    for (npy_int32 ii = 0; ii < 8; ii++) {
+        indexarr[ii] = ii*stride;
+    }
+
+    __m512d InvLn2N = _mm512_set1_pd(NPY_INV_LN2_MUL_32);
+    __m512d mShift = _mm512_set1_pd(NPY_RINT_CVT_MAGIC);
+    __m512d mNegL1 = _mm512_set1_pd(NPY_TANG_NEG_L1);
+    __m512d mNegL2 = _mm512_set1_pd(NPY_TANG_NEG_L2);
+    __m512i mMod = _mm512_set1_epi64(0x1f);
+    __m512d mA1 = _mm512_set1_pd(NPY_TANG_A1);
+    __m512d mA2 = _mm512_set1_pd(NPY_TANG_A2);
+    __m512d mA3 = _mm512_set1_pd(NPY_TANG_A3);
+    __m512d mA4 = _mm512_set1_pd(NPY_TANG_A4);
+    __m512d mA5 = _mm512_set1_pd(NPY_TANG_A5);
+    __m512d mTH_nearzero = _mm512_set1_pd(0x1p-54);
+    __m512d mTH_max = _mm512_set1_pd(0x1.62e42fefa39efp+9);
+    __m512d mTH_min = _mm512_set1_pd(-0x1.74910d52d3053p+9);
+    __m512d mTH_inf = _mm512_set1_pd(NPY_INFINITY);
+    __m512d zeros_d = _mm512_set1_pd(0.0f);
+    __m512d ones_d = _mm512_set1_pd(1.0f);
+    __m256i vindex = _mm256_loadu_si256((__m256i*)&indexarr[0]);
+
+    __m512d mTable_top_0 = _mm512_loadu_pd(&(EXP_Table_top[8*0]));
+    __m512d mTable_top_1 = _mm512_loadu_pd(&(EXP_Table_top[8*1]));
+    __m512d mTable_top_2 = _mm512_loadu_pd(&(EXP_Table_top[8*2]));
+    __m512d mTable_top_3 = _mm512_loadu_pd(&(EXP_Table_top[8*3]));
+    __m512d mTable_tail_0 = _mm512_loadu_pd(&(EXP_Table_tail[8*0]));
+    __m512d mTable_tail_1 = _mm512_loadu_pd(&(EXP_Table_tail[8*1]));
+    __m512d mTable_tail_2 = _mm512_loadu_pd(&(EXP_Table_tail[8*2]));
+    __m512d mTable_tail_3 = _mm512_loadu_pd(&(EXP_Table_tail[8*3]));
+    
+    __mmask8 overflow_mask = avx512_get_partial_load_mask_pd(0, num_lanes);
+    __mmask8 load_mask = avx512_get_full_load_mask_pd();
+    __mmask8 xmin_mask, xmax_mask, inf_mask, nan_mask, nearzero_mask;
+
+    while (num_remaining_elements > 0) {
+        if (num_remaining_elements < num_lanes) {
+            load_mask = avx512_get_partial_load_mask_pd(num_remaining_elements,
+                                                      num_lanes);
+        }
+
+        __m512d x;
+        if (1 == stride) {
+            x = avx512_masked_load_pd(load_mask, ip);
+        }
+        else {
+            x = avx512_masked_gather_pd(zeros_d, ip, vindex, load_mask);
+        }
+
+        nan_mask = _mm512_cmp_pd_mask(x, x, _CMP_NEQ_UQ);
+        x = avx512_set_masked_lanes_pd(x, zeros_d, nan_mask);
+        xmax_mask = _mm512_cmp_pd_mask(x, mTH_max, _CMP_GT_OQ);
+        xmin_mask = _mm512_cmp_pd_mask(x, mTH_min, _CMP_LT_OQ);
+        inf_mask = _mm512_cmp_pd_mask(x, mTH_inf, _CMP_EQ_OQ);
+        __m512i x_abs = _mm512_and_epi64(_mm512_castpd_si512(x), 
+                                _mm512_set1_epi64(0x7FFFFFFFFFFFFFFF));
+        nearzero_mask = _mm512_cmp_pd_mask(_mm512_castsi512_pd(x_abs), 
+                                    mTH_nearzero, _CMP_LT_OQ);
+        nearzero_mask = _mm512_kxor(nearzero_mask, nan_mask);
+        overflow_mask = _mm512_kor(overflow_mask, 
+                                _mm512_kxor(xmax_mask, inf_mask));
+        x = avx512_set_masked_lanes_pd(x, zeros_d,
+                        _mm512_kor(_mm512_kor(nan_mask, xmin_mask),
+                            _mm512_kor(xmax_mask, nearzero_mask)));
+
+        /* z = x * 32/ln2 */
+        __m512d z = _mm512_mul_pd(x, InvLn2N);
+        
+        /* round to nearest */
+        __m512d kd = _mm512_add_pd(z, mShift);
+        __m512i ki = _mm512_castpd_si512(kd);
+        kd = _mm512_sub_pd(kd, mShift);
+
+        /* r = (x + kd*mNegL1) + kd*mNegL2 */
+        __m512d r1 = _mm512_fmadd_pd(kd, mNegL1, x);
+        __m512d r2 = _mm512_mul_pd(kd, mNegL2);
+        __m512d r = _mm512_add_pd(r1,r2);
+
+        /* Polynomial approximation for exp(r) - 1 */
+        __m512d q = _mm512_fmadd_pd(mA5, r, mA4);
+        q = _mm512_fmadd_pd(q, r, mA3);
+        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);;
+        p = _mm512_add_pd(r1, p);
+
+        /* Get 2^(j/32) from lookup table */
+        __m512i j = _mm512_and_epi64(ki, mMod);
+        __m512d top = avx512_permute_x4var_pd(mTable_top_0, mTable_top_1,
+                                  mTable_top_2, mTable_top_3, j);
+        __m512d tail = avx512_permute_x4var_pd(mTable_tail_0, mTable_tail_1,
+                                  mTable_tail_2, mTable_tail_3, j);
+
+        /* 
+         * s = top + tail;
+         * exp(x) = 2^m * (top + (tail + s * p)); 
+         */
+        __m512d s = _mm512_add_pd(top, tail);
+        __m512d res = _mm512_fmadd_pd(s, p, tail);
+        res = _mm512_add_pd(res, top);
+        res= _mm512_scalef_pd(res, _mm512_div_pd(kd, _mm512_set1_pd(32)));
+
+        /* return special cases */
+        res = avx512_set_masked_lanes_pd(res, _mm512_add_pd(x, ones_d), 
+                                        nearzero_mask);
+        res = avx512_set_masked_lanes_pd(res, _mm512_set1_pd(NPY_NAN), 
+                                        nan_mask);
+        res = avx512_set_masked_lanes_pd(res, mTH_inf, xmax_mask);
+        res = avx512_set_masked_lanes_pd(res, zeros_d, xmin_mask);
+
+        _mm512_mask_storeu_pd(op, load_mask, res);
+
+        ip += num_lanes * stride;
+        op += num_lanes;
+        num_remaining_elements -= num_lanes;
+    }
+    if (overflow_mask) {
+        npy_set_floatstatus_overflow();
+    }
+}
+#endif
+#endif
+
+/**begin repeat
+ * #TYPE = CFLOAT, CDOUBLE#
+ * #type = npy_float, npy_double#
+ * #num_lanes = 16, 8#
+ * #vsuffix = ps, pd#
+ * #epi_vsub  = epi32, epi64#
+ * #mask = __mmask16, __mmask8#
+ * #vtype = __m512, __m512d#
+ * #scale = 4, 8#
+ * #vindextype = __m512i, __m256i#
+ * #vindexload = _mm512_loadu_si512, _mm256_loadu_si256#
+ * #storemask = 0xFF, 0xF#
+ * #IS_FLOAT = 1, 0#
+ */
+
+/**begin repeat1
+ *  #func = add, subtract, multiply#
+ *  #vectorf = _mm512_add, _mm512_sub, avx512_cmul#
+ */
+
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+static NPY_GCC_OPT_3 NPY_INLINE NPY_GCC_TARGET_AVX512F void
+AVX512F_@func@_@TYPE@(char **args, const npy_intp *dimensions, const npy_intp *steps)
+{
+    const npy_intp array_size = dimensions[0];
+    npy_intp num_remaining_elements = 2*array_size;
+    @type@* ip1 = (@type@*) args[0];
+    @type@* ip2 = (@type@*) args[1];
+    @type@* op  = (@type@*) args[2];
+
+    @mask@ load_mask = avx512_get_full_load_mask_@vsuffix@();
+
+    while (num_remaining_elements > 0) {
+        if (num_remaining_elements < @num_lanes@) {
+            load_mask = avx512_get_partial_load_mask_@vsuffix@(
+                                    num_remaining_elements, @num_lanes@);
+        }
+        @vtype@ x1, x2;
+        x1 = avx512_masked_load_@vsuffix@(load_mask, ip1);
+        x2 = avx512_masked_load_@vsuffix@(load_mask, ip2);
+
+        @vtype@ out = @vectorf@_@vsuffix@(x1, x2);
+
+        _mm512_mask_storeu_@vsuffix@(op, load_mask, out);
+
+        ip1 += @num_lanes@;
+        ip2 += @num_lanes@;
+        op += @num_lanes@;
+        num_remaining_elements -= @num_lanes@;
+    }
+}
+#endif
+/**end repeat1**/
+
+/**begin repeat1
+ *  #func = square, conjugate#
+ *  #vectorf = avx512_csquare, avx512_conjugate#
+ */
+
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+static NPY_GCC_OPT_3 NPY_INLINE NPY_GCC_TARGET_AVX512F void
+AVX512F_@func@_@TYPE@(@type@ * op,
+                      @type@ * ip,
+                      const npy_intp array_size,
+                      const npy_intp steps)
+{
+    npy_intp num_remaining_elements = 2*array_size;
+    const npy_intp stride_ip1 = steps/(npy_intp)sizeof(@type@)/2;
+
+     /*
+      * Note: while generally indices are npy_intp, we ensure that our maximum index
+      * will fit in an int32 as a precondition for this function via max_stride
+      */
+    npy_int32 index_ip1[16];
+    for (npy_int32 ii = 0; ii < @num_lanes@; ii=ii+2) {
+        index_ip1[ii] = ii*stride_ip1;
+        index_ip1[ii+1] = ii*stride_ip1 + 1;
+    }
+    @vindextype@ vindex = @vindexload@((@vindextype@*)index_ip1);
+    @mask@ load_mask = avx512_get_full_load_mask_@vsuffix@();
+    @vtype@ zeros = _mm512_setzero_@vsuffix@();
+
+    while (num_remaining_elements > 0) {
+        if (num_remaining_elements < @num_lanes@) {
+            load_mask = avx512_get_partial_load_mask_@vsuffix@(
+                                    num_remaining_elements, @num_lanes@);
+        }
+        @vtype@ x1;
+        if (stride_ip1 == 1) {
+            x1 = avx512_masked_load_@vsuffix@(load_mask, ip);
+        }
+        else {
+            x1  = avx512_masked_gather_@vsuffix@(zeros, ip, vindex, load_mask);
+        }
+
+        @vtype@ out = @vectorf@_@vsuffix@(x1);
+
+        _mm512_mask_storeu_@vsuffix@(op, load_mask, out);
+        op += @num_lanes@;
+        ip += @num_lanes@*stride_ip1;
+        num_remaining_elements -= @num_lanes@;
+    }
+}
+#endif
+/**end repeat1**/
+
+#if defined HAVE_ATTRIBUTE_TARGET_AVX512F_WITH_INTRINSICS && defined NPY_HAVE_SSE2_INTRINSICS
+static NPY_GCC_OPT_3 NPY_INLINE NPY_GCC_TARGET_AVX512F void
+AVX512F_absolute_@TYPE@(@type@ * op,
+                        @type@ * ip,
+                        const npy_intp array_size,
+                        const npy_intp steps)
+{
+    npy_intp num_remaining_elements = 2*array_size;
+    const npy_intp stride_ip1 = steps/(npy_intp)sizeof(@type@)/2;
+
+    /*
+     * Note: while generally indices are npy_intp, we ensure that our maximum index
+     * will fit in an int32 as a precondition for this function via max_stride
+     */
+    npy_int32 index_ip[32];
+    for (npy_int32 ii = 0; ii < 2*@num_lanes@; ii=ii+2) {
+        index_ip[ii] = ii*stride_ip1;
+        index_ip[ii+1] = ii*stride_ip1 + 1;
+    }
+    @vindextype@ vindex1 = @vindexload@((@vindextype@*)index_ip);
+    @vindextype@ vindex2 = @vindexload@((@vindextype@*)(index_ip+@num_lanes@));
+
+    @mask@ load_mask1 = avx512_get_full_load_mask_@vsuffix@();
+    @mask@ load_mask2 = avx512_get_full_load_mask_@vsuffix@();
+    @mask@ store_mask = avx512_get_full_load_mask_@vsuffix@();
+    @vtype@ zeros = _mm512_setzero_@vsuffix@();
+
+#if @IS_FLOAT@
+    __m512i re_index = _mm512_set_epi32(30,28,26,24,22,20,18,16,14,12,10,8,6,4,2,0);
+    __m512i im_index  = _mm512_set_epi32(31,29,27,25,23,21,19,17,15,13,11,9,7,5,3,1);
+#else
+    __m512i re_index = _mm512_set_epi64(14,12,10,8,6,4,2,0);
+    __m512i im_index  = _mm512_set_epi64(15,13,11,9,7,5,3,1);
+#endif
+
+    while (num_remaining_elements > 0) {
+        if (num_remaining_elements < @num_lanes@) {
+            load_mask1 = avx512_get_partial_load_mask_@vsuffix@(
+                                    num_remaining_elements, @num_lanes@);
+            load_mask2 = 0x0000;
+            store_mask = avx512_get_partial_load_mask_@vsuffix@(
+                                    num_remaining_elements/2, @num_lanes@);
+        } else if (num_remaining_elements < 2*@num_lanes@) {
+            load_mask1 = avx512_get_full_load_mask_@vsuffix@();
+            load_mask2 = avx512_get_partial_load_mask_@vsuffix@(
+                                    num_remaining_elements - @num_lanes@, @num_lanes@);
+            store_mask = avx512_get_partial_load_mask_@vsuffix@(
+                                    num_remaining_elements/2, @num_lanes@);
+        }
+        @vtype@ x1, x2;
+        if (stride_ip1 == 1) {
+            x1 = avx512_masked_load_@vsuffix@(load_mask1, ip);
+            x2 = avx512_masked_load_@vsuffix@(load_mask2, ip+@num_lanes@);
+        }
+        else {
+            x1  = avx512_masked_gather_@vsuffix@(zeros, ip, vindex1, load_mask1);
+            x2  = avx512_masked_gather_@vsuffix@(zeros, ip, vindex2, load_mask2);
+        }
+
+        @vtype@ out = avx512_cabsolute_@vsuffix@(x1, x2, re_index, im_index);
+
+        _mm512_mask_storeu_@vsuffix@(op, store_mask, out);
+        op += @num_lanes@;
+        ip += 2*@num_lanes@*stride_ip1;
+        num_remaining_elements -= 2*@num_lanes@;
+    }
+    npy_clear_floatstatus_barrier((char*)op);
+}
+
+#endif
+/**end repeat**/
+
 /*
  *****************************************************************************
  **                           BOOL LOOPS
index 1dc5819773e06fdd0ee41cdfa4bf76512c320ea3..c57199c79bfd3c9052eece93993fe30b6d984dea 100644 (file)
@@ -324,7 +324,7 @@ _find_array_prepare(ufunc_full_args args,
 NPY_NO_EXPORT int
 set_matmul_flags(PyObject *d)
 {
-    PyObject *matmul = PyDict_GetItemString(d, "matmul");
+    PyObject *matmul = _PyDict_GetItemStringWithError(d, "matmul");
     if (matmul == NULL) {
         return -1;
     }
@@ -397,7 +397,7 @@ _ufunc_setup_flags(PyUFuncObject *ufunc, npy_uint32 op_in_flags,
  * A NULL is placed in output_wrap for outputs that
  * should just have PyArray_Return called.
  */
-static void
+static int
 _find_array_wrap(ufunc_full_args args, PyObject *kwds,
                 PyObject **output_wrap, int nin, int nout)
 {
@@ -409,9 +409,12 @@ _find_array_wrap(ufunc_full_args args, PyObject *kwds,
      * If a 'subok' parameter is passed and isn't True, don't wrap but put None
      * into slots with out arguments which means return the out argument
      */
-    if (kwds != NULL && (obj = PyDict_GetItem(kwds,
-                                              npy_um_str_subok)) != NULL) {
-        if (obj != Py_True) {
+    if (kwds != NULL) {
+        obj = PyDict_GetItemWithError(kwds, npy_um_str_subok);
+        if (obj == NULL && PyErr_Occurred()) {
+            return -1;
+        }
+        else if (obj != NULL && obj != Py_True) {
             /* skip search for wrap members */
             goto handle_out;
         }
@@ -450,7 +453,7 @@ handle_out:
     }
 
     Py_XDECREF(wrap);
-    return;
+    return 0;
 }
 
 
@@ -929,22 +932,9 @@ parse_ufunc_keywords(PyUFuncObject *ufunc, PyObject *kwds, PyObject **kwnames, .
             }
         }
         else {
-#if PY_VERSION_HEX >= 0x03000000
             PyErr_Format(PyExc_TypeError,
                          "'%S' is an invalid keyword to ufunc '%s'",
                          key, ufunc_get_name_cstr(ufunc));
-#else
-            char *str = PyString_AsString(key);
-            if (str == NULL) {
-                PyErr_Clear();
-                PyErr_SetString(PyExc_TypeError, "invalid keyword argument");
-            }
-            else {
-                PyErr_Format(PyExc_TypeError,
-                             "'%s' is an invalid keyword to ufunc '%s'",
-                             str, ufunc_get_name_cstr(ufunc));
-            }
-#endif
             return -1;
         }
     }
@@ -1044,7 +1034,7 @@ get_ufunc_arguments(PyUFuncObject *ufunc,
     int nin = ufunc->nin;
     int nout = ufunc->nout;
     int nop = ufunc->nargs;
-    PyObject *obj, *context;
+    PyObject *obj;
     PyArray_Descr *dtype = NULL;
     /*
      * Initialize output objects so caller knows when outputs and optional
@@ -1081,22 +1071,8 @@ get_ufunc_arguments(PyUFuncObject *ufunc,
             out_op[i] = (PyArrayObject *)PyArray_FromArray(obj_a, NULL, 0);
         }
         else {
-            if (!PyArray_IsScalar(obj, Generic)) {
-                /*
-                 * TODO: There should be a comment here explaining what
-                 *       context does.
-                 */
-                context = Py_BuildValue("OOi", ufunc, args, i);
-                if (context == NULL) {
-                    goto fail;
-                }
-            }
-            else {
-                context = NULL;
-            }
             out_op[i] = (PyArrayObject *)PyArray_FromAny(obj,
-                                    NULL, 0, 0, 0, context);
-            Py_XDECREF(context);
+                                    NULL, 0, 0, 0, NULL);
         }
 
         if (out_op[i] == NULL) {
@@ -1941,7 +1917,15 @@ make_full_arg_tuple(
     }
 
     /* Look for output keyword arguments */
-    out_kwd = kwds ? PyDict_GetItem(kwds, npy_um_str_out) : NULL;
+    if (kwds) {
+        out_kwd = PyDict_GetItemWithError(kwds, npy_um_str_out);
+        if (out_kwd == NULL && PyErr_Occurred()) {
+            goto fail;
+        }
+    }
+    else {
+        out_kwd = NULL;
+    }
 
     if (out_kwd != NULL) {
         assert(nargs == nin);
@@ -2942,7 +2926,7 @@ PyUFunc_GeneralizedFunction(PyUFuncObject *ufunc,
 
     /*
      * The first nop strides are for the inner loop (but only can
-     * copy them after removing the core axes
+     * copy them after removing the core axes)
      */
     memcpy(inner_strides, NpyIter_GetInnerStrideArray(iter),
                                     NPY_SIZEOF_INTP * nop);
@@ -3068,17 +3052,15 @@ fail:
     return retval;
 }
 
-/*UFUNC_API
- *
+/*
  * This generic function is called with the ufunc object, the arguments to it,
  * and an array of (pointers to) PyArrayObjects which are NULL.
  *
  * 'op' is an array of at least NPY_MAXARGS PyArrayObject *.
  */
-NPY_NO_EXPORT int
-PyUFunc_GenericFunction(PyUFuncObject *ufunc,
-                        PyObject *args, PyObject *kwds,
-                        PyArrayObject **op)
+static int
+PyUFunc_GenericFunction_int(PyUFuncObject *ufunc,
+        PyObject *args, PyObject *kwds, PyArrayObject **op)
 {
     int nin, nout;
     int i, nop;
@@ -3284,6 +3266,27 @@ fail:
     return retval;
 }
 
+
+/*UFUNC_API*/
+NPY_NO_EXPORT int
+PyUFunc_GenericFunction(PyUFuncObject *ufunc,
+        PyObject *args, PyObject *kwds, PyArrayObject **op)
+{
+    /* NumPy 1.19, 2020-01-24 */
+    if (DEPRECATE(
+            "PyUFunc_GenericFunction() C-API function is deprecated "
+            "and expected to be removed rapidly. If you are using it (i.e. see "
+            "this warning/error), please notify the NumPy developers. "
+            "As of now it is expected that any use case is served better by "
+            "the direct use of `PyObject_Call(ufunc, args, kwargs)`. "
+            "PyUFunc_GenericFunction function has slightly different "
+            "untested behaviour.") < 0) {
+        return -1;
+    }
+    return PyUFunc_GenericFunction_int(ufunc, args, kwds, op);
+}
+
+
 /*
  * Given the output type, finds the specified binary op.  The
  * ufunc must have nin==2 and nout==1.  The function may modify
@@ -3309,9 +3312,12 @@ get_binary_op_function(PyUFuncObject *ufunc, int *otype,
         if (key == NULL) {
             return -1;
         }
-        obj = PyDict_GetItem(ufunc->userloops, key);
+        obj = PyDict_GetItemWithError(ufunc->userloops, key);
         Py_DECREF(key);
-        if (obj != NULL) {
+        if (obj == NULL && PyErr_Occurred()) {
+            return -1;
+        }
+        else if (obj != NULL) {
             funcdata = (PyUFunc_Loop1d *)NpyCapsule_AsVoidPtr(obj);
             while (funcdata != NULL) {
                 int *types = funcdata->arg_types;
@@ -3437,8 +3443,8 @@ reduce_type_resolver(PyUFuncObject *ufunc, PyArrayObject *arr,
 }
 
 static int
-reduce_loop(NpyIter *iter, char **dataptrs, npy_intp *strides,
-            npy_intp *countptr, NpyIter_IterNextFunc *iternext,
+reduce_loop(NpyIter *iter, char **dataptrs, npy_intp const *strides,
+            npy_intp const *countptr, NpyIter_IterNextFunc *iternext,
             int needs_api, npy_intp skip_first_count, void *data)
 {
     PyArray_Descr *dtypes[3], **iter_dtypes;
@@ -3870,8 +3876,6 @@ PyUFunc_Accumulate(PyUFuncObject *ufunc, PyArrayObject *arr, PyArrayObject *out,
         stride_copy[1] = stride1;
         stride_copy[2] = stride0;
 
-        needs_api = NpyIter_IterationNeedsAPI(iter);
-
         NPY_BEGIN_THREADS_NDITER(iter);
 
         do {
@@ -4396,7 +4400,7 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
     PyObject *axes_in = NULL;
     PyArrayObject *mp = NULL, *wheremask = NULL, *ret = NULL;
     PyObject *op;
-    PyObject *obj_ind, *context;
+    PyObject *obj_ind;
     PyArrayObject *indices = NULL;
     PyArray_Descr *otype = NULL;
     PyArrayObject *out = NULL;
@@ -4435,8 +4439,11 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
     }
     /* if there is a tuple of 1 for `out` in kwds, unpack it */
     if (kwds != NULL) {
-        PyObject *out_obj = PyDict_GetItem(kwds, npy_um_str_out);
-        if (out_obj != NULL && PyTuple_CheckExact(out_obj)) {
+        PyObject *out_obj = PyDict_GetItemWithError(kwds, npy_um_str_out);
+        if (out_obj == NULL && PyErr_Occurred()){
+            return NULL;
+        }
+        else if (out_obj != NULL && PyTuple_CheckExact(out_obj)) {
             if (PyTuple_GET_SIZE(out_obj) != 1) {
                 PyErr_SetString(PyExc_ValueError,
                                 "The 'out' tuple must have exactly one entry");
@@ -4487,14 +4494,7 @@ PyUFunc_GenericReduction(PyUFuncObject *ufunc, PyObject *args,
         }
     }
     /* Ensure input is an array */
-    if (!PyArray_Check(op) && !PyArray_IsScalar(op, Generic)) {
-        context = Py_BuildValue("O(O)i", ufunc, op, 0);
-    }
-    else {
-        context = NULL;
-    }
-    mp = (PyArrayObject *)PyArray_FromAny(op, NULL, 0, 0, 0, context);
-    Py_XDECREF(context);
+    mp = (PyArrayObject *)PyArray_FromAny(op, NULL, 0, 0, 0, NULL);
     if (mp == NULL) {
         goto fail;
     }
@@ -4698,7 +4698,7 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
         return override;
     }
 
-    errval = PyUFunc_GenericFunction(ufunc, args, kwds, mps);
+    errval = PyUFunc_GenericFunction_int(ufunc, args, kwds, mps);
     if (errval < 0) {
         return NULL;
     }
@@ -4728,7 +4728,9 @@ ufunc_generic_call(PyUFuncObject *ufunc, PyObject *args, PyObject *kwds)
     if (make_full_arg_tuple(&full_args, ufunc->nin, ufunc->nout, args, kwds) < 0) {
         goto fail;
     }
-    _find_array_wrap(full_args, kwds, wraparr, ufunc->nin, ufunc->nout);
+    if (_find_array_wrap(full_args, kwds, wraparr, ufunc->nin, ufunc->nout) < 0) {
+        goto fail;
+    }
 
     /* wrap outputs */
     for (i = 0; i < ufunc->nout; i++) {
@@ -4790,8 +4792,11 @@ ufunc_geterr(PyObject *NPY_UNUSED(dummy), PyObject *args)
     if (thedict == NULL) {
         thedict = PyEval_GetBuiltins();
     }
-    res = PyDict_GetItem(thedict, npy_um_str_pyvals_name);
-    if (res != NULL) {
+    res = PyDict_GetItemWithError(thedict, npy_um_str_pyvals_name);
+    if (res == NULL && PyErr_Occurred()) {
+        return NULL;
+    }
+    else if (res != NULL) {
         Py_INCREF(res);
         return res;
     }
@@ -4987,6 +4992,16 @@ PyUFunc_FromFuncAndDataAndSignatureAndIdentity(PyUFuncGenericFunction *func, voi
 NPY_NO_EXPORT int
 PyUFunc_SetUsesArraysAsData(void **data, size_t i)
 {
+    /* NumPy 1.19, 2020-01-24 */
+    if (DEPRECATE(
+            "PyUFunc_SetUsesArraysAsData() C-API function is deprecated "
+            "and expected to be removed rapidly. If you are using it (i.e. see "
+            "this warning/error), please notify the NumPy developers. "
+            "It is currently assumed that this function is simply unused and "
+            "its removal will facilitate the implementation of better "
+            "approaches.") < 0) {
+        return -1;
+    }
     data[i] = (void*)PyUFunc_SetUsesArraysAsData;
     return 0;
 }
@@ -5068,21 +5083,12 @@ _free_loop1d_list(PyUFunc_Loop1d *data)
     }
 }
 
-#if PY_VERSION_HEX >= 0x03000000
 static void
 _loop1d_list_free(PyObject *ptr)
 {
     PyUFunc_Loop1d *data = (PyUFunc_Loop1d *)PyCapsule_GetPointer(ptr, NULL);
     _free_loop1d_list(data);
 }
-#else
-static void
-_loop1d_list_free(void *ptr)
-{
-    PyUFunc_Loop1d *data = (PyUFunc_Loop1d *)ptr;
-    _free_loop1d_list(data);
-}
-#endif
 
 
 /*
@@ -5145,8 +5151,11 @@ PyUFunc_RegisterLoopForDescr(PyUFuncObject *ufunc,
         function, arg_typenums, data);
 
     if (result == 0) {
-        cobj = PyDict_GetItem(ufunc->userloops, key);
-        if (cobj == NULL) {
+        cobj = PyDict_GetItemWithError(ufunc->userloops, key);
+        if (cobj == NULL && PyErr_Occurred()) {
+            result = -1;
+        }
+        else if (cobj == NULL) {
             PyErr_SetString(PyExc_KeyError,
                 "userloop for user dtype not found");
             result = -1;
@@ -5250,9 +5259,12 @@ PyUFunc_RegisterLoopForType(PyUFuncObject *ufunc,
     funcdata->nargs = 0;
 
     /* Get entry for this user-defined type*/
-    cobj = PyDict_GetItem(ufunc->userloops, key);
+    cobj = PyDict_GetItemWithError(ufunc->userloops, key);
+    if (cobj == NULL && PyErr_Occurred()) {
+        return 0;
+    }
     /* If it's not there, then make one and return. */
-    if (cobj == NULL) {
+    else if (cobj == NULL) {
         cobj = NpyCapsule_FromVoidPtr((void *)funcdata, _loop1d_list_free);
         if (cobj == NULL) {
             goto fail;
@@ -6056,63 +6068,17 @@ static PyGetSetDef ufunc_getset[] = {
  *****************************************************************************/
 
 NPY_NO_EXPORT PyTypeObject PyUFunc_Type = {
-#if defined(NPY_PY3K)
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(NULL)
-    0,                                          /* ob_size */
-#endif
-    "numpy.ufunc",                              /* tp_name */
-    sizeof(PyUFuncObject),                      /* tp_basicsize */
-    0,                                          /* tp_itemsize */
-    /* methods */
-    (destructor)ufunc_dealloc,                  /* tp_dealloc */
-    0,                                          /* tp_print */
-    0,                                          /* tp_getattr */
-    0,                                          /* tp_setattr */
-#if defined(NPY_PY3K)
-    0,                                          /* tp_reserved */
-#else
-    0,                                          /* tp_compare */
-#endif
-    (reprfunc)ufunc_repr,                       /* tp_repr */
-    0,                                          /* tp_as_number */
-    0,                                          /* tp_as_sequence */
-    0,                                          /* tp_as_mapping */
-    0,                                          /* tp_hash */
-    (ternaryfunc)ufunc_generic_call,            /* tp_call */
-    (reprfunc)ufunc_repr,                       /* tp_str */
-    0,                                          /* tp_getattro */
-    0,                                          /* tp_setattro */
-    0,                                          /* tp_as_buffer */
-    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,    /* tp_flags */
-    0,                                          /* tp_doc */
-    (traverseproc)ufunc_traverse,               /* tp_traverse */
-    0,                                          /* tp_clear */
-    0,                                          /* tp_richcompare */
-    0,                                          /* tp_weaklistoffset */
-    0,                                          /* tp_iter */
-    0,                                          /* tp_iternext */
-    ufunc_methods,                              /* tp_methods */
-    0,                                          /* tp_members */
-    ufunc_getset,                               /* tp_getset */
-    0,                                          /* tp_base */
-    0,                                          /* tp_dict */
-    0,                                          /* tp_descr_get */
-    0,                                          /* tp_descr_set */
-    0,                                          /* tp_dictoffset */
-    0,                                          /* tp_init */
-    0,                                          /* tp_alloc */
-    0,                                          /* tp_new */
-    0,                                          /* tp_free */
-    0,                                          /* tp_is_gc */
-    0,                                          /* tp_bases */
-    0,                                          /* tp_mro */
-    0,                                          /* tp_cache */
-    0,                                          /* tp_subclasses */
-    0,                                          /* tp_weaklist */
-    0,                                          /* tp_del */
-    0,                                          /* tp_version_tag */
+    .tp_name = "numpy.ufunc",
+    .tp_basicsize = sizeof(PyUFuncObject),
+    .tp_dealloc = (destructor)ufunc_dealloc,
+    .tp_repr = (reprfunc)ufunc_repr,
+    .tp_call = (ternaryfunc)ufunc_generic_call,
+    .tp_str = (reprfunc)ufunc_repr,
+    .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
+    .tp_traverse = (traverseproc)ufunc_traverse,
+    .tp_methods = ufunc_methods,
+    .tp_getset = ufunc_getset,
 };
 
 /* End of code for ufunc objects */
index f93d8229e5fb721c3f9006437e0df8b6f24cd3cc..ea20bb24f53072191f6e13565325cc6757b0857c 100644 (file)
@@ -51,25 +51,6 @@ npy_casting_to_py_object(NPY_CASTING casting)
 }
 
 
-static const char *
-npy_casting_to_string(NPY_CASTING casting)
-{
-    switch (casting) {
-        case NPY_NO_CASTING:
-            return "'no'";
-        case NPY_EQUIV_CASTING:
-            return "'equiv'";
-        case NPY_SAFE_CASTING:
-            return "'safe'";
-        case NPY_SAME_KIND_CASTING:
-            return "'same_kind'";
-        case NPY_UNSAFE_CASTING:
-            return "'unsafe'";
-        default:
-            return "<unknown>";
-    }
-}
-
 /**
  * Always returns -1 to indicate the exception was raised, for convenience
  */
@@ -1347,37 +1328,6 @@ PyUFunc_TrueDivisionTypeResolver(PyUFuncObject *ufunc,
     return PyUFunc_DivisionTypeResolver(ufunc, casting, operands,
                                         type_tup, out_dtypes);
 }
-/*
- * Function to check and report floor division warning when python2.x is
- * invoked with -3 switch
- * See PEP238 and #7949 for numpy
- * This function will not be hit for py3 or when __future__ imports division.
- * See generate_umath.py for reason
-*/
-NPY_NO_EXPORT int
-PyUFunc_MixedDivisionTypeResolver(PyUFuncObject *ufunc,
-                                  NPY_CASTING casting,
-                                  PyArrayObject **operands,
-                                  PyObject *type_tup,
-                                  PyArray_Descr **out_dtypes)
-{
- /* Deprecation checks needed only on python 2 */
-#if !defined(NPY_PY3K)
-    int type_num1, type_num2;
-
-    type_num1 = PyArray_DESCR(operands[0])->type_num;
-    type_num2 = PyArray_DESCR(operands[1])->type_num;
-
-    /* If both types are integer, warn the user, same as python does */
-    if (Py_DivisionWarningFlag &&
-            (PyTypeNum_ISINTEGER(type_num1) || PyTypeNum_ISBOOL(type_num1)) &&
-            (PyTypeNum_ISINTEGER(type_num2) || PyTypeNum_ISBOOL(type_num2))) {
-        PyErr_Warn(PyExc_DeprecationWarning, "numpy: classic int division");
-    }
-#endif
-    return PyUFunc_DivisionTypeResolver(ufunc, casting, operands,
-                                        type_tup, out_dtypes);
-}
 
 static int
 find_userloop(PyUFuncObject *ufunc,
@@ -1410,9 +1360,12 @@ find_userloop(PyUFuncObject *ufunc,
             if (key == NULL) {
                 return -1;
             }
-            obj = PyDict_GetItem(ufunc->userloops, key);
+            obj = PyDict_GetItemWithError(ufunc->userloops, key);
             Py_DECREF(key);
-            if (obj == NULL) {
+            if (obj == NULL && PyErr_Occurred()){
+                return -1;
+            }
+            else if (obj == NULL) {
                 continue;
             }
             for (funcdata = (PyUFunc_Loop1d *)NpyCapsule_AsVoidPtr(obj);
@@ -1815,9 +1768,12 @@ linear_search_userloop_type_resolver(PyUFuncObject *self,
             if (key == NULL) {
                 return -1;
             }
-            obj = PyDict_GetItem(self->userloops, key);
+            obj = PyDict_GetItemWithError(self->userloops, key);
             Py_DECREF(key);
-            if (obj == NULL) {
+            if (obj == NULL && PyErr_Occurred()){
+                return -1;
+            }
+            else if (obj == NULL) {
                 continue;
             }
             for (funcdata = (PyUFunc_Loop1d *)NpyCapsule_AsVoidPtr(obj);
@@ -1879,9 +1835,12 @@ type_tuple_userloop_type_resolver(PyUFuncObject *self,
             if (key == NULL) {
                 return -1;
             }
-            obj = PyDict_GetItem(self->userloops, key);
+            obj = PyDict_GetItemWithError(self->userloops, key);
             Py_DECREF(key);
-            if (obj == NULL) {
+            if (obj == NULL && PyErr_Occurred()){
+                return -1;
+            }
+            else if (obj == NULL) {
                 continue;
             }
 
index a4e670a8e56bfd651a66f65136288e79699762e7..1d6ad3358773c33bdb81bf9be3ac044f889b8a66 100644 (file)
@@ -71,13 +71,6 @@ PyUFunc_MultiplicationTypeResolver(PyUFuncObject *ufunc,
                                    PyObject *type_tup,
                                    PyArray_Descr **out_dtypes);
 
-NPY_NO_EXPORT int
-PyUFunc_MixedDivisionTypeResolver(PyUFuncObject *ufunc,
-                                  NPY_CASTING casting,
-                                  PyArrayObject **operands,
-                                  PyObject *type_tup,
-                                  PyArray_Descr **out_dtypes);
-
 NPY_NO_EXPORT int
 PyUFunc_TrueDivisionTypeResolver(PyUFuncObject *ufunc,
                                  NPY_CASTING casting,
index 6ec47437646d6a85d45d18571d8a056078f2283b..bad42d657dcd776be30930604a62d2c036161f41 100644 (file)
@@ -70,9 +70,7 @@ object_ufunc_loop_selector(PyUFuncObject *ufunc,
 }
 
 PyObject *
-ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUSED(kwds)) {
-    /* Keywords are ignored for now */
-
+ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *kwds) {
     PyObject *function, *pyname = NULL;
     int nin, nout, i, nargs;
     PyUFunc_PyFuncData *fdata;
@@ -81,14 +79,18 @@ ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUS
     Py_ssize_t fname_len = -1;
     void * ptr, **data;
     int offset[2];
+    PyObject *identity = NULL;  /* note: not the same semantics as Py_None */
+    static char *kwlist[] = {"", "nin", "nout", "identity", NULL};
 
-    if (!PyArg_ParseTuple(args, "Oii:frompyfunc", &function, &nin, &nout)) {
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "Oii|$O:frompyfunc", kwlist,
+                &function, &nin, &nout, &identity)) {
         return NULL;
     }
     if (!PyCallable_Check(function)) {
         PyErr_SetString(PyExc_TypeError, "function must be callable");
         return NULL;
     }
+
     nargs = nin + nout;
 
     pyname = PyObject_GetAttrString(function, "__name__");
@@ -146,10 +148,10 @@ ufunc_frompyfunc(PyObject *NPY_UNUSED(dummy), PyObject *args, PyObject *NPY_UNUS
     /* Do a better job someday */
     doc = "dynamic ufunc based on a python function";
 
-    self = (PyUFuncObject *)PyUFunc_FromFuncAndData(
+    self = (PyUFuncObject *)PyUFunc_FromFuncAndDataAndSignatureAndIdentity(
             (PyUFuncGenericFunction *)pyfunc_functions, data,
-            types, /* ntypes */ 1, nin, nout, PyUFunc_None,
-            str, doc, /* unused */ 0);
+            types, /* ntypes */ 1, nin, nout, identity ? PyUFunc_IdentityValue : PyUFunc_None,
+            str, doc, /* unused */ 0, NULL, identity);
 
     if (self == NULL) {
         PyArray_free(ptr);
@@ -174,7 +176,6 @@ add_newdoc_ufunc(PyObject *NPY_UNUSED(dummy), PyObject *args)
     PyObject *str, *tmp;
     char *docstr, *newdocstr;
 
-#if defined(NPY_PY3K)
     if (!PyArg_ParseTuple(args, "O!O!:_add_newdoc_ufunc", &PyUFunc_Type, &ufunc,
                                         &PyUnicode_Type, &str)) {
         return NULL;
@@ -184,20 +185,11 @@ add_newdoc_ufunc(PyObject *NPY_UNUSED(dummy), PyObject *args)
         return NULL;
     }
     docstr = PyBytes_AS_STRING(tmp);
-#else
-    if (!PyArg_ParseTuple(args, "O!O!:_add_newdoc_ufunc", &PyUFunc_Type, &ufunc,
-                                         &PyString_Type, &str)) {
-        return NULL;
-    }
-    docstr = PyString_AS_STRING(str);
-#endif
 
     if (NULL != ufunc->doc) {
         PyErr_SetString(PyExc_ValueError,
                 "Cannot change docstring of ufunc with non-NULL docstring");
-#if defined(NPY_PY3K)
         Py_DECREF(tmp);
-#endif
         return NULL;
     }
 
@@ -211,9 +203,7 @@ add_newdoc_ufunc(PyObject *NPY_UNUSED(dummy), PyObject *args)
     strcpy(newdocstr, docstr);
     ufunc->doc = newdocstr;
 
-#if defined(NPY_PY3K)
     Py_DECREF(tmp);
-#endif
     Py_RETURN_NONE;
 }
 
@@ -324,10 +314,8 @@ int initumath(PyObject *m)
     PyModule_AddObject(m, "NZERO", PyFloat_FromDouble(NPY_NZERO));
     PyModule_AddObject(m, "NAN", PyFloat_FromDouble(NPY_NAN));
 
-#if defined(NPY_PY3K)
     s = PyDict_GetItemString(d, "true_divide");
     PyDict_SetItemString(d, "divide", s);
-#endif
 
     s = PyDict_GetItemString(d, "conjugate");
     s2 = PyDict_GetItemString(d, "remainder");
index 52e4ff36d5ed125885c60f63d2ce618933838c9a..ce7b81f001b9537ca88130b39ea6d3d3f7cbabcb 100644 (file)
@@ -1,8 +1,6 @@
 """Provide class for testing in French locale
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import locale
 
@@ -45,7 +43,7 @@ def find_comma_decimal_point_locale():
     return old_locale, new_locale
 
 
-class CommaDecimalPointLocale(object):
+class CommaDecimalPointLocale:
     """Sets LC_NUMERIC to a locale with comma as decimal point.
 
     Classes derived from this class have setup and teardown methods that run
index 360ebcd6a42ef0e5c6f26a2a821f2a7db9ba2a95..2e75f044cb8c0fa87730a5df6f05cd9d40678bb4 100644 (file)
@@ -19,9 +19,7 @@ np.float32,0x80000001,0x3f800000,2
 np.float32,0x00000000,0x3f800000,2
 np.float32,0x80000000,0x3f800000,2
 np.float32,0x00800000,0x3f800000,2
-np.float32,0x7f7fffff,0x3f5a5f96,2
 np.float32,0x80800000,0x3f800000,2
-np.float32,0xff7fffff,0x3f5a5f96,2
 ## 1.00f + 0x00000001 ##
 np.float32,0x3f800000,0x3f0a5140,2
 np.float32,0x3f800001,0x3f0a513f,2
@@ -36,26 +34,6 @@ np.float32,0x41d92388,0xbed987c7,2
 np.float32,0x422dd66c,0x3f5dcab3,2
 np.float32,0xc28f5be6,0xbf5688d8,2
 np.float32,0x41ab2674,0xbf53aa3b,2
-np.float32,0xd0102756,0x3f45d12d,2
-np.float32,0xcf99405e,0xbe9cf281,2
-np.float32,0xcfd83a12,0x3eaae4ca,2
-np.float32,0x4fb54db0,0xbf7b2894,2
-np.float32,0xcfcca29d,0x3f752e4e,2
-np.float32,0xceec2ac0,0xbf745303,2
-np.float32,0xcfdca97f,0x3ef554a7,2
-np.float32,0xcfe92b0a,0x3f4618f2,2
-np.float32,0x5014b0eb,0x3ee933e6,2
-np.float32,0xcfa7ee96,0xbeedeeb2,2
-np.float32,0x754c09a0,0xbef298de,2
-np.float32,0x77a731fb,0x3f24599f,2
-np.float32,0x76de2494,0x3f79576c,2
-np.float32,0xf74920dc,0xbf4d196e,2
-np.float32,0x7707a312,0xbeb5cb8e,2
-np.float32,0x75bf9790,0xbf7fd7fe,2
-np.float32,0xf4ca7c40,0xbe15107d,2
-np.float32,0x77e91899,0xbe8a968b,2
-np.float32,0xf74c9820,0xbf7f9677,2
-np.float32,0x7785ca29,0xbe6ef93b,2
 np.float32,0x3f490fdb,0x3f3504f3,2
 np.float32,0xbf490fdb,0x3f3504f3,2
 np.float32,0x3fc90fdb,0xb33bbd2e,2
@@ -660,26 +638,6 @@ np.float32,0x4350ea79,0x3631dadb,2
 np.float32,0x42dbe957,0xbf800000,2
 np.float32,0x425be957,0xb505522a,2
 np.float32,0x435be957,0x3f800000,2
-np.float32,0x487fe5ab,0xba140185,2
-np.float32,0x497fe5ab,0x3f7fffd5,2
-np.float32,0x49ffe5ab,0x3f7fff55,2
-np.float32,0x49ffeb37,0x3b9382f5,2
-np.float32,0x497ff0c3,0x3b13049f,2
-np.float32,0x49fff0c3,0xbf7fff57,2
-np.float32,0x49fff64f,0xbb928618,2
-np.float32,0x497ffbdb,0xbf7fffd6,2
-np.float32,0x49fffbdb,0x3f7fff59,2
-np.float32,0x48fffbdb,0xba9207c6,2
-np.float32,0x4e736e56,0xbf800000,2
-np.float32,0x4d4da377,0xbf800000,2
-np.float32,0x4ece58c3,0xbf800000,2
-np.float32,0x4ee0db9c,0xbf800000,2
-np.float32,0x4dee7002,0x3f800000,2
-np.float32,0x4ee86afc,0x38857a23,2
-np.float32,0x4dca4f3f,0xbf800000,2
-np.float32,0x4ecb48af,0xb95d1e10,2
-np.float32,0x4e51e33f,0xbf800000,2
-np.float32,0x4ef5f421,0xbf800000,2
 np.float32,0x46027eb2,0x3e7d94c9,2
 np.float32,0x4477baed,0xbe7f1824,2
 np.float32,0x454b8024,0x3e7f5268,2
index 1b2cc9ce4b5f455399c03269ad018ca8ccda32ae..7c5ef3b334fbd8a63bb1a0e6ad72577f767dbaf6 100644 (file)
@@ -133,3 +133,280 @@ np.float32,0xc29b43d5,0x077ffffc,3
 np.float32,0xc1e61ff7,0x2ab504f5,3
 np.float32,0xc2867878,0x0effff15,3
 np.float32,0xc2a2324a,0x04fffff4,3
+#float64
+## near zero ##
+np.float64,0x8000000000000000,0x3ff0000000000000,1
+np.float64,0x8010000000000000,0x3ff0000000000000,1
+np.float64,0x8000000000000001,0x3ff0000000000000,1
+np.float64,0x8360000000000000,0x3ff0000000000000,1
+np.float64,0x9a70000000000000,0x3ff0000000000000,1
+np.float64,0xb9b0000000000000,0x3ff0000000000000,1
+np.float64,0xb810000000000000,0x3ff0000000000000,1
+np.float64,0xbc30000000000000,0x3ff0000000000000,1
+np.float64,0xb6a0000000000000,0x3ff0000000000000,1
+np.float64,0x0000000000000000,0x3ff0000000000000,1
+np.float64,0x0010000000000000,0x3ff0000000000000,1
+np.float64,0x0000000000000001,0x3ff0000000000000,1
+np.float64,0x0360000000000000,0x3ff0000000000000,1
+np.float64,0x1a70000000000000,0x3ff0000000000000,1
+np.float64,0x3c30000000000000,0x3ff0000000000000,1
+np.float64,0x36a0000000000000,0x3ff0000000000000,1
+np.float64,0x39b0000000000000,0x3ff0000000000000,1
+np.float64,0x3810000000000000,0x3ff0000000000000,1
+## underflow ##
+np.float64,0xc0c6276800000000,0x0000000000000000,1
+np.float64,0xc0c62d918ce2421d,0x0000000000000000,1
+np.float64,0xc0c62d918ce2421e,0x0000000000000000,1
+np.float64,0xc0c62d91a0000000,0x0000000000000000,1
+np.float64,0xc0c62d9180000000,0x0000000000000000,1
+np.float64,0xc0c62dea45ee3e06,0x0000000000000000,1
+np.float64,0xc0c62dea45ee3e07,0x0000000000000000,1
+np.float64,0xc0c62dea40000000,0x0000000000000000,1
+np.float64,0xc0c62dea60000000,0x0000000000000000,1
+np.float64,0xc0875f1120000000,0x0000000000000000,1
+np.float64,0xc0875f113c30b1c8,0x0000000000000000,1
+np.float64,0xc0875f1140000000,0x0000000000000000,1
+np.float64,0xc093480000000000,0x0000000000000000,1
+np.float64,0xffefffffffffffff,0x0000000000000000,1
+np.float64,0xc7efffffe0000000,0x0000000000000000,1
+## overflow ##
+np.float64,0x40862e52fefa39ef,0x7ff0000000000000,1
+np.float64,0x40872e42fefa39ef,0x7ff0000000000000,1
+## +/- INF, +/- NAN ##
+np.float64,0x7ff0000000000000,0x7ff0000000000000,1
+np.float64,0xfff0000000000000,0x0000000000000000,1
+np.float64,0x7ff8000000000000,0x7ff8000000000000,1
+np.float64,0xfff8000000000000,0xfff8000000000000,1
+## output denormal ##
+np.float64,0xc087438520000000,0x0000000000000001,1
+np.float64,0xc08743853f2f4461,0x0000000000000001,1
+np.float64,0xc08743853f2f4460,0x0000000000000001,1
+np.float64,0xc087438540000000,0x0000000000000001,1
+## between -745.13321910 and 709.78271289 ##
+np.float64,0xbff760cd14774bd9,0x3fcdb14ced00ceb6,1
+np.float64,0xbff760cd20000000,0x3fcdb14cd7993879,1
+np.float64,0xbff760cd00000000,0x3fcdb14d12fbd264,1
+np.float64,0xc07f1cf360000000,0x130c1b369af14fda,1
+np.float64,0xbeb0000000000000,0x3feffffe00001000,1
+np.float64,0xbd70000000000000,0x3fefffffffffe000,1
+np.float64,0xc084fd46e5c84952,0x0360000000000139,1
+np.float64,0xc084fd46e5c84953,0x035ffffffffffe71,1
+np.float64,0xc084fd46e0000000,0x0360000b9096d32c,1
+np.float64,0xc084fd4700000000,0x035fff9721d12104,1
+np.float64,0xc086232bc0000000,0x0010003af5e64635,1
+np.float64,0xc086232bdd7abcd2,0x001000000000007c,1
+np.float64,0xc086232bdd7abcd3,0x000ffffffffffe7c,1
+np.float64,0xc086232be0000000,0x000ffffaf57a6fc9,1
+np.float64,0xc086233920000000,0x000fe590e3b45eb0,1
+np.float64,0xc086233938000000,0x000fe56133493c57,1
+np.float64,0xc086233940000000,0x000fe5514deffbbc,1
+np.float64,0xc086234c98000000,0x000fbf1024c32ccb,1
+np.float64,0xc086234ca0000000,0x000fbf0065bae78d,1
+np.float64,0xc086234c80000000,0x000fbf3f623a7724,1
+np.float64,0xc086234ec0000000,0x000fbad237c846f9,1
+np.float64,0xc086234ec8000000,0x000fbac27cfdec97,1
+np.float64,0xc086234ee0000000,0x000fba934cfd3dc2,1
+np.float64,0xc086234ef0000000,0x000fba73d7f618d9,1
+np.float64,0xc086234f00000000,0x000fba54632dddc0,1
+np.float64,0xc0862356e0000000,0x000faae0945b761a,1
+np.float64,0xc0862356f0000000,0x000faac13eb9a310,1
+np.float64,0xc086235700000000,0x000faaa1e9567b0a,1
+np.float64,0xc086236020000000,0x000f98cd75c11ed7,1
+np.float64,0xc086236ca0000000,0x000f8081b4d93f89,1
+np.float64,0xc086236cb0000000,0x000f8062b3f4d6c5,1
+np.float64,0xc086236cc0000000,0x000f8043b34e6f8c,1
+np.float64,0xc086238d98000000,0x000f41220d9b0d2c,1
+np.float64,0xc086238da0000000,0x000f4112cc80a01f,1
+np.float64,0xc086238d80000000,0x000f414fd145db5b,1
+np.float64,0xc08624fd00000000,0x000cbfce8ea1e6c4,1
+np.float64,0xc086256080000000,0x000c250747fcd46e,1
+np.float64,0xc08626c480000000,0x000a34f4bd975193,1
+np.float64,0xbf50000000000000,0x3feff800ffeaac00,1
+np.float64,0xbe10000000000000,0x3fefffffff800000,1
+np.float64,0xbcd0000000000000,0x3feffffffffffff8,1
+np.float64,0xc055d589e0000000,0x38100004bf94f63e,1
+np.float64,0xc055d58a00000000,0x380ffff97f292ce8,1
+np.float64,0xbfd962d900000000,0x3fe585a4b00110e1,1
+np.float64,0x3ff4bed280000000,0x400d411e7a58a303,1
+np.float64,0x3fff0b3620000000,0x401bd7737ffffcf3,1
+np.float64,0x3ff0000000000000,0x4005bf0a8b145769,1
+np.float64,0x3eb0000000000000,0x3ff0000100000800,1
+np.float64,0x3d70000000000000,0x3ff0000000001000,1
+np.float64,0x40862e42e0000000,0x7fefff841808287f,1
+np.float64,0x40862e42fefa39ef,0x7fefffffffffff2a,1
+np.float64,0x40862e0000000000,0x7feef85a11e73f2d,1
+np.float64,0x4000000000000000,0x401d8e64b8d4ddae,1
+np.float64,0x4009242920000000,0x40372a52c383a488,1
+np.float64,0x4049000000000000,0x44719103e4080b45,1
+np.float64,0x4008000000000000,0x403415e5bf6fb106,1
+np.float64,0x3f50000000000000,0x3ff00400800aab55,1
+np.float64,0x3e10000000000000,0x3ff0000000400000,1
+np.float64,0x3cd0000000000000,0x3ff0000000000004,1
+np.float64,0x40562e40a0000000,0x47effed088821c3f,1
+np.float64,0x40562e42e0000000,0x47effff082e6c7ff,1
+np.float64,0x40562e4300000000,0x47f00000417184b8,1
+np.float64,0x3fe8000000000000,0x4000ef9db467dcf8,1
+np.float64,0x402b12e8d4f33589,0x412718f68c71a6fe,1
+np.float64,0x402b12e8d4f3358a,0x412718f68c71a70a,1
+np.float64,0x402b12e8c0000000,0x412718f59a7f472e,1
+np.float64,0x402b12e8e0000000,0x412718f70c0eac62,1
+##use 1th entry
+np.float64,0x40631659AE147CB4,0x4db3a95025a4890f,1
+np.float64,0xC061B87D2E85A4E2,0x332640c8e2de2c51,1
+np.float64,0x405A4A50BE243AF4,0x496a45e4b7f0339a,1
+np.float64,0xC0839898B98EC5C6,0x0764027828830df4,1
+#use 2th entry
+np.float64,0xC072428C44B6537C,0x2596ade838b96f3e,1
+np.float64,0xC053057C5E1AE9BF,0x3912c8fad18fdadf,1
+np.float64,0x407E89C78328BAA3,0x6bfe35d5b9a1a194,1
+np.float64,0x4083501B6DD87112,0x77a855503a38924e,1
+#use 3th entry
+np.float64,0x40832C6195F24540,0x7741e73c80e5eb2f,1
+np.float64,0xC083D4CD557C2EC9,0x06b61727c2d2508e,1
+np.float64,0x400C48F5F67C99BD,0x404128820f02b92e,1
+np.float64,0x4056E36D9B2DF26A,0x4830f52ff34a8242,1
+#use 4th entry
+np.float64,0x4080FF700D8CBD06,0x70fa70df9bc30f20,1
+np.float64,0x406C276D39E53328,0x543eb8e20a8f4741,1
+np.float64,0xC070D6159BBD8716,0x27a4a0548c904a75,1
+np.float64,0xC052EBCF8ED61F83,0x391c0e92368d15e4,1
+#use 5th entry
+np.float64,0xC061F892A8AC5FBE,0x32f807a89efd3869,1
+np.float64,0x4021D885D2DBA085,0x40bd4dc86d3e3270,1
+np.float64,0x40767AEEEE7D4FCF,0x605e22851ee2afb7,1
+np.float64,0xC0757C5D75D08C80,0x20f0751599b992a2,1
+#use 6th entry
+np.float64,0x405ACF7A284C4CE3,0x499a4e0b7a27027c,1
+np.float64,0xC085A6C9E80D7AF5,0x0175914009d62ec2,1
+np.float64,0xC07E4C02F86F1DAE,0x1439269b29a9231e,1
+np.float64,0x4080D80F9691CC87,0x7088a6cdafb041de,1
+#use 7th entry
+np.float64,0x407FDFD84FBA0AC1,0x6deb1ae6f9bc4767,1
+np.float64,0x40630C06A1A2213D,0x4dac7a9d51a838b7,1
+np.float64,0x40685FDB30BB8B4F,0x5183f5cc2cac9e79,1
+np.float64,0x408045A2208F77F4,0x6ee299e08e2aa2f0,1
+#use 8th entry
+np.float64,0xC08104E391F5078B,0x0ed397b7cbfbd230,1
+np.float64,0xC031501CAEFAE395,0x3e6040fd1ea35085,1
+np.float64,0xC079229124F6247C,0x1babf4f923306b1e,1
+np.float64,0x407FB65F44600435,0x6db03beaf2512b8a,1
+#use 9th entry
+np.float64,0xC07EDEE8E8E8A5AC,0x136536cec9cbef48,1
+np.float64,0x4072BB4086099A14,0x5af4d3c3008b56cc,1
+np.float64,0x4050442A2EC42CB4,0x45cd393bd8fad357,1
+np.float64,0xC06AC28FB3D419B4,0x2ca1b9d3437df85f,1
+#use 10th entry
+np.float64,0x40567FC6F0A68076,0x480c977fd5f3122e,1
+np.float64,0x40620A2F7EDA59BB,0x4cf278e96f4ce4d7,1
+np.float64,0xC085044707CD557C,0x034aad6c968a045a,1
+np.float64,0xC07374EA5AC516AA,0x23dd6afdc03e83d5,1
+#use 11th entry
+np.float64,0x4073CC95332619C1,0x5c804b1498bbaa54,1
+np.float64,0xC0799FEBBE257F31,0x1af6a954c43b87d2,1
+np.float64,0x408159F19EA424F6,0x7200858efcbfc84d,1
+np.float64,0x404A81F6F24C0792,0x44b664a07ce5bbfa,1
+#use 12th entry
+np.float64,0x40295FF1EFB9A741,0x4113c0e74c52d7b0,1
+np.float64,0x4073975F4CC411DA,0x5c32be40b4fec2c1,1
+np.float64,0x406E9DE52E82A77E,0x56049c9a3f1ae089,1
+np.float64,0x40748C2F52560ED9,0x5d93bc14fd4cd23b,1
+#use 13th entry
+np.float64,0x4062A553CDC4D04C,0x4d6266bfde301318,1
+np.float64,0xC079EC1D63598AB7,0x1a88cb184dab224c,1
+np.float64,0xC0725C1CB3167427,0x25725b46f8a081f6,1
+np.float64,0x407888771D9B45F9,0x6353b1ec6bd7ce80,1
+#use 14th entry
+np.float64,0xC082CBA03AA89807,0x09b383723831ce56,1
+np.float64,0xC083A8961BB67DD7,0x0735b118d5275552,1
+np.float64,0xC076BC6ECA12E7E3,0x1f2222679eaef615,1
+np.float64,0xC072752503AA1A5B,0x254eb832242c77e1,1
+#use 15th entry
+np.float64,0xC058800792125DEC,0x371882372a0b48d4,1
+np.float64,0x4082909FD863E81C,0x7580d5f386920142,1
+np.float64,0xC071616F8FB534F9,0x26dbe20ef64a412b,1
+np.float64,0x406D1AB571CAA747,0x54ee0d55cb38ac20,1
+#use 16th entry
+np.float64,0x406956428B7DAD09,0x52358682c271237f,1
+np.float64,0xC07EFC2D9D17B621,0x133b3e77c27a4d45,1
+np.float64,0xC08469BAC5BA3CCA,0x050863e5f42cc52f,1
+np.float64,0x407189D9626386A5,0x593cb1c0b3b5c1d3,1
+#use 17th entry
+np.float64,0x4077E652E3DEB8C6,0x6269a10dcbd3c752,1
+np.float64,0x407674C97DB06878,0x605485dcc2426ec2,1
+np.float64,0xC07CE9969CF4268D,0x16386cf8996669f2,1
+np.float64,0x40780EE32D5847C4,0x62a436bd1abe108d,1
+#use 18th entry
+np.float64,0x4076C3AA5E1E8DA1,0x60c62f56a5e72e24,1
+np.float64,0xC0730AFC7239B9BE,0x24758ead095cec1e,1
+np.float64,0xC085CC2B9C420DDB,0x0109cdaa2e5694c1,1
+np.float64,0x406D0765CB6D7AA4,0x54e06f8dd91bd945,1
+#use 19th entry
+np.float64,0xC082D011F3B495E7,0x09a6647661d279c2,1
+np.float64,0xC072826AF8F6AFBC,0x253acd3cd224507e,1
+np.float64,0x404EB9C4810CEA09,0x457933dbf07e8133,1
+np.float64,0x408284FBC97C58CE,0x755f6eb234aa4b98,1
+#use 20th entry
+np.float64,0x40856008CF6EDC63,0x7d9c0b3c03f4f73c,1
+np.float64,0xC077CB2E9F013B17,0x1d9b3d3a166a55db,1
+np.float64,0xC0479CA3C20AD057,0x3bad40e081555b99,1
+np.float64,0x40844CD31107332A,0x7a821d70aea478e2,1
+#use 21th entry
+np.float64,0xC07C8FCC0BFCC844,0x16ba1cc8c539d19b,1
+np.float64,0xC085C4E9A3ABA488,0x011ff675ba1a2217,1
+np.float64,0x4074D538B32966E5,0x5dfd9d78043c6ad9,1
+np.float64,0xC0630CA16902AD46,0x3231a446074cede6,1
+#use 22th entry
+np.float64,0xC06C826733D7D0B7,0x2b5f1078314d41e1,1
+np.float64,0xC0520DF55B2B907F,0x396c13a6ce8e833e,1
+np.float64,0xC080712072B0F437,0x107eae02d11d98ea,1
+np.float64,0x40528A6150E19EFB,0x469fdabda02228c5,1
+#use 23th entry
+np.float64,0xC07B1D74B6586451,0x18d1253883ae3b48,1
+np.float64,0x4045AFD7867DAEC0,0x43d7d634fc4c5d98,1
+np.float64,0xC07A08B91F9ED3E2,0x1a60973e6397fc37,1
+np.float64,0x407B3ECF0AE21C8C,0x673e03e9d98d7235,1
+#use 24th entry
+np.float64,0xC078AEB6F30CEABF,0x1c530b93ab54a1b3,1
+np.float64,0x4084495006A41672,0x7a775b6dc7e63064,1
+np.float64,0x40830B1C0EBF95DD,0x76e1e6eed77cfb89,1
+np.float64,0x407D93E8F33D8470,0x6a9adbc9e1e4f1e5,1
+#use 25th entry
+np.float64,0x4066B11A09EFD9E8,0x504dd528065c28a7,1
+np.float64,0x408545823723AEEB,0x7d504a9b1844f594,1
+np.float64,0xC068C711F2CA3362,0x2e104f3496ea118e,1
+np.float64,0x407F317FCC3CA873,0x6cf0732c9948ebf4,1
+#use 26th entry
+np.float64,0x407AFB3EBA2ED50F,0x66dc28a129c868d5,1
+np.float64,0xC075377037708ADE,0x21531a329f3d793e,1
+np.float64,0xC07C30066A1F3246,0x174448baa16ded2b,1
+np.float64,0xC06689A75DE2ABD3,0x2fad70662fae230b,1
+#use 27th entry
+np.float64,0x4081514E9FCCF1E0,0x71e673b9efd15f44,1
+np.float64,0xC0762C710AF68460,0x1ff1ed7d8947fe43,1
+np.float64,0xC0468102FF70D9C4,0x3be0c3a8ff3419a3,1
+np.float64,0xC07EA4CEEF02A83E,0x13b908f085102c61,1
+#use 28th entry
+np.float64,0xC06290B04AE823C4,0x328a83da3c2e3351,1
+np.float64,0xC0770EB1D1C395FB,0x1eab281c1f1db5fe,1
+np.float64,0xC06F5D4D838A5BAE,0x29500ea32fb474ea,1
+np.float64,0x40723B3133B54C5D,0x5a3c82c7c3a2b848,1
+#use 29th entry
+np.float64,0x4085E6454CE3B4AA,0x7f20319b9638d06a,1
+np.float64,0x408389F2A0585D4B,0x7850667c58aab3d0,1
+np.float64,0xC0382798F9C8AE69,0x3dc1c79fe8739d6d,1
+np.float64,0xC08299D827608418,0x0a4335f76cdbaeb5,1
+#use 30th entry
+np.float64,0xC06F3DED43301BF1,0x2965670ae46750a8,1
+np.float64,0xC070CAF6BDD577D9,0x27b4aa4ffdd29981,1
+np.float64,0x4078529AD4B2D9F2,0x6305c12755d5e0a6,1
+np.float64,0xC055B14E75A31B96,0x381c2eda6d111e5d,1
+#use 31th entry
+np.float64,0x407B13EE414FA931,0x6700772c7544564d,1
+np.float64,0x407EAFDE9DE3EC54,0x6c346a0e49724a3c,1
+np.float64,0xC08362F398B9530D,0x07ffeddbadf980cb,1
+np.float64,0x407E865CDD9EEB86,0x6bf866cac5e0d126,1
+#use 32th entry
+np.float64,0x407FB62DBC794C86,0x6db009f708ac62cb,1
+np.float64,0xC063D0BAA68CDDDE,0x31a3b2a51ce50430,1
+np.float64,0xC05E7706A2231394,0x34f24bead6fab5c9,1
+np.float64,0x4083E3A06FDE444E,0x79527b7a386d1937,1
index a562731953c910bc41be777d54033e48ab7ca5d7..64e78ae158a455b8455fde5769b53087a8ccc7df 100644 (file)
@@ -19,9 +19,7 @@ np.float32,0x80000001,0x80000001,2
 np.float32,0x00000000,0x00000000,2
 np.float32,0x80000000,0x80000000,2
 np.float32,0x00800000,0x00800000,2
-np.float32,0x7f7fffff,0xbf0599b3,2
 np.float32,0x80800000,0x80800000,2
-np.float32,0xff7fffff,0x3f0599b3,2
 ## 1.00f ##
 np.float32,0x3f800000,0x3f576aa4,2
 np.float32,0x3f800001,0x3f576aa6,2
@@ -36,26 +34,6 @@ np.float32,0x41d92388,0x3f67beef,2
 np.float32,0x422dd66c,0xbeffb0c1,2
 np.float32,0xc28f5be6,0xbf0bae79,2
 np.float32,0x41ab2674,0x3f0ffe2b,2
-np.float32,0xd0102756,0x3f227e8a,2
-np.float32,0xcf99405e,0x3f73ad00,2
-np.float32,0xcfd83a12,0xbf7151a7,2
-np.float32,0x4fb54db0,0xbe46354b,2
-np.float32,0xcfcca29d,0xbe9345e6,2
-np.float32,0xceec2ac0,0x3e98dc89,2
-np.float32,0xcfdca97f,0xbf60b2b4,2
-np.float32,0xcfe92b0a,0xbf222705,2
-np.float32,0x5014b0eb,0x3f63e75c,2
-np.float32,0xcfa7ee96,0x3f62ada4,2
-np.float32,0x754c09a0,0xbf617056,2
-np.float32,0x77a731fb,0x3f44472b,2
-np.float32,0x76de2494,0xbe680739,2
-np.float32,0xf74920dc,0xbf193338,2
-np.float32,0x7707a312,0xbf6f51b1,2
-np.float32,0x75bf9790,0xbd0f1a47,2
-np.float32,0xf4ca7c40,0xbf7d45e7,2
-np.float32,0x77e91899,0x3f767181,2
-np.float32,0xf74c9820,0xbd685b75,2
-np.float32,0x7785ca29,0x3f78ee61,2
 np.float32,0x3f490fdb,0x3f3504f3,2
 np.float32,0xbf490fdb,0xbf3504f3,2
 np.float32,0x3fc90fdb,0x3f800000,2
@@ -660,46 +638,21 @@ np.float32,0x4350ea79,0x3f800000,2
 np.float32,0x42dbe957,0x3585522a,2
 np.float32,0x425be957,0xbf800000,2
 np.float32,0x435be957,0xb605522a,2
-np.float32,0x487fe5ab,0xbf7ffffd,2
-np.float32,0x497fe5ab,0xbb14017d,2
-np.float32,0x49ffe5ab,0xbb940164,2
-np.float32,0x49ffeb37,0x3f7fff56,2
-np.float32,0x497ff0c3,0x3f7fffd6,2
-np.float32,0x49fff0c3,0x3b930487,2
-np.float32,0x49fff64f,0xbf7fff58,2
-np.float32,0x497ffbdb,0x3b1207c0,2
-np.float32,0x49fffbdb,0xbb9207a9,2
-np.float32,0x48fffbdb,0xbf7ffff6,2
-np.float32,0x4e736e56,0x397fa7f2,2
-np.float32,0x4d4da377,0xb57c64bc,2
-np.float32,0x4ece58c3,0xb80846c8,2
-np.float32,0x4ee0db9c,0x394c4786,2
-np.float32,0x4dee7002,0x381bce96,2
-np.float32,0x4ee86afc,0x3f800000,2
-np.float32,0x4dca4f3f,0xb8e25111,2
-np.float32,0x4ecb48af,0xbf800000,2
-np.float32,0x4e51e33f,0xb8a4fa6f,2
-np.float32,0x4ef5f421,0x387ca7df,2
 np.float32,0x476362a2,0xbd7ff911,2
 np.float32,0x464c99a4,0x3e7f4d41,2
 np.float32,0x4471f73d,0x3e7fe1b0,2
 np.float32,0x445a6752,0x3e7ef367,2
 np.float32,0x474fa400,0x3e7f9fcd,2
-np.float32,0x47c9e70e,0xbb4bba09,2
 np.float32,0x45c1e72f,0xbe7fc7af,2
 np.float32,0x4558c91d,0x3e7e9f31,2
 np.float32,0x43784f94,0xbdff6654,2
 np.float32,0x466e8500,0xbe7ea0a3,2
 np.float32,0x468e1c25,0x3e7e22fb,2
-np.float32,0x47d28adc,0xbe7d5e6b,2
 np.float32,0x44ea6cfc,0x3dff70c3,2
 np.float32,0x4605126c,0x3e7f89ef,2
 np.float32,0x4788b3c6,0xbb87d853,2
 np.float32,0x4531b042,0x3dffd163,2
-np.float32,0x47e46c29,0xbe7def2b,2
-np.float32,0x47c10e07,0xbdff63d4,2
 np.float32,0x43f1f71d,0x3dfff387,2
-np.float32,0x47c3e38c,0x3e7f0b2f,2
 np.float32,0x462c3fa5,0xbd7fe13d,2
 np.float32,0x441c5354,0xbdff76b4,2
 np.float32,0x44908b69,0x3e7dcf0d,2
index d9c61b0c611501d4b9fe2476add80305a0141e89..30e5748af86745d302740ee4fc023e44767eee36 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy.testing import assert_
 
 import numbers
@@ -7,7 +5,7 @@ import numbers
 import numpy as np
 from numpy.core.numerictypes import sctypes
 
-class TestABC(object):
+class TestABC:
     def test_abstract(self):
         assert_(issubclass(np.number, numbers.Number))
 
index 89fc2b0b90927445f2bde98fc187b167749dfebf..2600d409a74c4dd73514cc95733153e6535ed4c4 100644 (file)
@@ -1,8 +1,7 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 
 import numpy as np
+from numpy.core._rational_tests import rational
 import pytest
 from numpy.testing import (
      assert_, assert_equal, assert_array_equal, assert_raises, assert_warns,
@@ -41,57 +40,38 @@ def test_array_array():
         assert_equal(old_refcount, sys.getrefcount(np.float64))
 
     # test string
-    S2 = np.dtype((str, 2))
-    S3 = np.dtype((str, 3))
-    S5 = np.dtype((str, 5))
+    S2 = np.dtype((bytes, 2))
+    S3 = np.dtype((bytes, 3))
+    S5 = np.dtype((bytes, 5))
+    assert_equal(np.array(b"1.0", dtype=np.float64),
+                 np.ones((), dtype=np.float64))
+    assert_equal(np.array(b"1.0").dtype, S3)
+    assert_equal(np.array(b"1.0", dtype=bytes).dtype, S3)
+    assert_equal(np.array(b"1.0", dtype=S2), np.array(b"1."))
+    assert_equal(np.array(b"1", dtype=S5), np.ones((), dtype=S5))
+
+    # test string
+    U2 = np.dtype((str, 2))
+    U3 = np.dtype((str, 3))
+    U5 = np.dtype((str, 5))
     assert_equal(np.array("1.0", dtype=np.float64),
                  np.ones((), dtype=np.float64))
-    assert_equal(np.array("1.0").dtype, S3)
-    assert_equal(np.array("1.0", dtype=str).dtype, S3)
-    assert_equal(np.array("1.0", dtype=S2), np.array("1."))
-    assert_equal(np.array("1", dtype=S5), np.ones((), dtype=S5))
-
-    # test unicode
-    _unicode = globals().get("unicode")
-    if _unicode:
-        U2 = np.dtype((_unicode, 2))
-        U3 = np.dtype((_unicode, 3))
-        U5 = np.dtype((_unicode, 5))
-        assert_equal(np.array(_unicode("1.0"), dtype=np.float64),
-                     np.ones((), dtype=np.float64))
-        assert_equal(np.array(_unicode("1.0")).dtype, U3)
-        assert_equal(np.array(_unicode("1.0"), dtype=_unicode).dtype, U3)
-        assert_equal(np.array(_unicode("1.0"), dtype=U2),
-                     np.array(_unicode("1.")))
-        assert_equal(np.array(_unicode("1"), dtype=U5),
-                     np.ones((), dtype=U5))
+    assert_equal(np.array("1.0").dtype, U3)
+    assert_equal(np.array("1.0", dtype=str).dtype, U3)
+    assert_equal(np.array("1.0", dtype=U2), np.array(str("1.")))
+    assert_equal(np.array("1", dtype=U5), np.ones((), dtype=U5))
 
     builtins = getattr(__builtins__, '__dict__', __builtins__)
     assert_(hasattr(builtins, 'get'))
 
-    # test buffer
-    _buffer = builtins.get("buffer")
-    if _buffer and sys.version_info[:3] >= (2, 7, 5):
-        # This test fails for earlier versions of Python.
-        # Evidently a bug got fixed in 2.7.5.
-        dat = np.array(_buffer('1.0'), dtype=np.float64)
-        assert_equal(dat, [49.0, 46.0, 48.0])
-        assert_(dat.dtype.type is np.float64)
-
-        dat = np.array(_buffer(b'1.0'))
-        assert_equal(dat, [49, 46, 48])
-        assert_(dat.dtype.type is np.uint8)
-
-    # test memoryview, new version of buffer
-    _memoryview = builtins.get("memoryview")
-    if _memoryview:
-        dat = np.array(_memoryview(b'1.0'), dtype=np.float64)
-        assert_equal(dat, [49.0, 46.0, 48.0])
-        assert_(dat.dtype.type is np.float64)
-
-        dat = np.array(_memoryview(b'1.0'))
-        assert_equal(dat, [49, 46, 48])
-        assert_(dat.dtype.type is np.uint8)
+    # test memoryview
+    dat = np.array(memoryview(b'1.0'), dtype=np.float64)
+    assert_equal(dat, [49.0, 46.0, 48.0])
+    assert_(dat.dtype.type is np.float64)
+
+    dat = np.array(memoryview(b'1.0'))
+    assert_equal(dat, [49, 46, 48])
+    assert_(dat.dtype.type is np.uint8)
 
     # test array interface
     a = np.array(100.0, dtype=np.float64)
@@ -162,6 +142,16 @@ def test_array_array():
     assert_equal(np.array([(1.0,) * 10] * 10, dtype=np.float64),
                  np.ones((10, 10), dtype=np.float64))
 
+@pytest.mark.parametrize("array", [True, False])
+def test_array_impossible_casts(array):
+    # All builtin types can forst cast as least theoretically
+    # but user dtypes cannot necessarily.
+    rt = rational(1, 2)
+    if array:
+        rt = np.array(rt)
+    with assert_raises(ValueError):
+        np.array(rt, dtype="M8")
+
 
 def test_fastCopyAndTranspose():
     # 0D array
@@ -299,6 +289,34 @@ def test_array_astype_warning(t):
     a = np.array(10, dtype=np.complex_)
     assert_warns(np.ComplexWarning, a.astype, t)
 
+@pytest.mark.parametrize(["dtype", "out_dtype"],
+        [(np.bytes_, np.bool_),
+         (np.unicode, np.bool_),
+         (np.dtype("S10,S9"), np.dtype("?,?"))])
+def test_string_to_boolean_cast(dtype, out_dtype):
+    """
+    Currently, for `astype` strings are cast to booleans effectively by
+    calling `bool(int(string)`. This is not consistent (see gh-9875) and
+    will eventually be deprecated.
+    """
+    arr = np.array(["10", "10\0\0\0", "0\0\0", "0"], dtype=dtype)
+    expected = np.array([True, True, False, False], dtype=out_dtype)
+    assert_array_equal(arr.astype(out_dtype), expected)
+
+@pytest.mark.parametrize(["dtype", "out_dtype"],
+        [(np.bytes_, np.bool_),
+         (np.unicode, np.bool_),
+         (np.dtype("S10,S9"), np.dtype("?,?"))])
+def test_string_to_boolean_cast_errors(dtype, out_dtype):
+    """
+    These currently error out, since cast to integers fails, but should not
+    error out in the future.
+    """
+    for invalid in ["False", "True", "", "\0", "non-empty"]:
+        arr = np.array([invalid], dtype=dtype)
+        with assert_raises(ValueError):
+            arr.astype(out_dtype)
+
 def test_copyto_fromscalar():
     a = np.arange(6, dtype='f4').reshape(2, 3)
 
index 702e68e769f08a0c826734e9d9639b1145beaf35..e292174612c33c91b9338af567ab8333aef56276 100644 (file)
@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
-from __future__ import division, absolute_import, print_function
-
 import sys
 import gc
+from hypothesis import given
+from hypothesis.extra import numpy as hynp
 import pytest
 
 import numpy as np
@@ -12,7 +12,7 @@ from numpy.testing import (
     )
 import textwrap
 
-class TestArrayRepr(object):
+class TestArrayRepr:
     def test_nan_inf(self):
         x = np.array([np.nan, np.inf])
         assert_equal(repr(x), 'array([nan, inf])')
@@ -160,7 +160,7 @@ class TestArrayRepr(object):
         assert_equal(repr(arr_no_fields), 'array([(), (), (), ()], dtype=[])')
 
 
-class TestComplexArray(object):
+class TestComplexArray:
     def test_str(self):
         rvals = [0, 1, -1, np.inf, -np.inf, np.nan]
         cvals = [complex(rp, ip) for rp in rvals for ip in rvals]
@@ -207,7 +207,7 @@ class TestComplexArray(object):
         for res, val in zip(actual, wanted):
             assert_equal(res, val)
 
-class TestArray2String(object):
+class TestArray2String:
     def test_basic(self):
         """Basic test of array2string."""
         a = np.arange(3)
@@ -235,12 +235,8 @@ class TestArray2String(object):
                 return 'O'
 
         x = np.arange(3)
-        if sys.version_info[0] >= 3:
-            x_hex = "[0x0 0x1 0x2]"
-            x_oct = "[0o0 0o1 0o2]"
-        else:
-            x_hex = "[0x0L 0x1L 0x2L]"
-            x_oct = "[0L 01L 02L]"
+        x_hex = "[0x0 0x1 0x2]"
+        x_oct = "[0o0 0o1 0o2]"
         assert_(np.array2string(x, formatter={'all':_format_function}) ==
                 "[. o O]")
         assert_(np.array2string(x, formatter={'int_kind':_format_function}) ==
@@ -399,6 +395,18 @@ class TestArray2String(object):
             "[ 'xxxxx']"
         )
 
+    @given(hynp.from_dtype(np.dtype("U")))
+    def test_any_text(self, text):
+        # This test checks that, given any value that can be represented in an
+        # array of dtype("U") (i.e. unicode string), ...
+        a = np.array([text, text, text])
+        # casting a list of them to an array does not e.g. truncate the value
+        assert_equal(a[0], text)
+        # and that np.array2string puts a newline in the expected location
+        expected_repr = "[{0!r} {0!r}\n {0!r}]".format(text)
+        result = np.array2string(a, max_line_width=len(repr(text)) * 2 + 3)
+        assert_equal(result, expected_repr)
+
     @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
     def test_refcount(self):
         # make sure we do not hold references to the array due to a recursive
@@ -413,7 +421,7 @@ class TestArray2String(object):
         gc.enable()
         assert_(r1 == r2)
 
-class TestPrintOptions(object):
+class TestPrintOptions:
     """Test getting and setting global print options."""
 
     def setup(self):
@@ -467,16 +475,10 @@ class TestPrintOptions(object):
         assert_equal(repr(x), "array([0., 1., 2.])")
 
     def test_0d_arrays(self):
-        unicode = type(u'')
-
-        assert_equal(unicode(np.array(u'café', '<U4')), u'café')
+        assert_equal(str(np.array(u'café', '<U4')), u'café')
 
-        if sys.version_info[0] >= 3:
-            assert_equal(repr(np.array('café', '<U4')),
-                         "array('café', dtype='<U4')")
-        else:
-            assert_equal(repr(np.array(u'café', '<U4')),
-                         "array(u'caf\\xe9', dtype='<U4')")
+        assert_equal(repr(np.array('café', '<U4')),
+                     "array('café', dtype='<U4')")
         assert_equal(str(np.array('test', np.str_)), 'test')
 
         a = np.zeros(1, dtype=[('a', '<i4', (3,))])
@@ -709,7 +711,7 @@ class TestPrintOptions(object):
             array([10., 11., 12., 13., 14., 15., 16., 17., 18., 19., 20., 21., 22.],
                   dtype=float32)"""))
 
-        styp = '<U4' if sys.version_info[0] >= 3 else '|S4'
+        styp = '<U4'
         assert_equal(repr(np.ones(3, dtype=styp)),
             "array(['1', '1', '1'], dtype='{}')".format(styp))
         assert_equal(repr(np.ones(12, dtype=styp)), textwrap.dedent("""\
@@ -847,18 +849,14 @@ class TestPrintOptions(object):
         assert_raises(TypeError, np.set_printoptions, threshold=b'1')
 
 def test_unicode_object_array():
-    import sys
-    if sys.version_info[0] >= 3:
-        expected = "array(['é'], dtype=object)"
-    else:
-        expected = "array([u'\\xe9'], dtype=object)"
+    expected = "array(['é'], dtype=object)"
     x = np.array([u'\xe9'], dtype=object)
     assert_equal(repr(x), expected)
 
 
-class TestContextManager(object):
+class TestContextManager:
     def test_ctx_mgr(self):
-        # test that context manager actuall works
+        # test that context manager actually works
         with np.printoptions(precision=2):
             s = str(np.array([2.0]) / 3)
         assert_equal(s, '[0.67]')
diff --git a/numpy/core/tests/test_conversion_utils.py b/numpy/core/tests/test_conversion_utils.py
new file mode 100644 (file)
index 0000000..3c3f9e6
--- /dev/null
@@ -0,0 +1,156 @@
+"""
+Tests for numpy/core/src/multiarray/conversion_utils.c
+"""
+import re
+
+import pytest
+
+import numpy as np
+import numpy.core._multiarray_tests as mt
+
+
+class StringConverterTestCase:
+    allow_bytes = True
+    case_insensitive = True
+    exact_match = False
+
+    def _check_value_error(self, val):
+        pattern = r'\(got {}\)'.format(re.escape(repr(val)))
+        with pytest.raises(ValueError, match=pattern) as exc:
+            self.conv(val)
+
+    def _check(self, val, expected):
+        assert self.conv(val) == expected
+
+        if self.allow_bytes:
+            assert self.conv(val.encode('ascii')) == expected
+        else:
+            with pytest.raises(TypeError):
+                self.conv(val.encode('ascii'))
+
+        if len(val) != 1:
+            if self.exact_match:
+                self._check_value_error(val[:1])
+                self._check_value_error(val + '\0')
+            else:
+                assert self.conv(val[:1]) == expected
+
+        if self.case_insensitive:
+            if val != val.lower():
+                assert self.conv(val.lower()) == expected
+            if val != val.upper():
+                assert self.conv(val.upper()) == expected
+        else:
+            if val != val.lower():
+                self._check_value_error(val.lower())
+            if val != val.upper():
+                self._check_value_error(val.upper())
+
+    def test_wrong_type(self):
+        # common cases which apply to all the below
+        with pytest.raises(TypeError):
+            self.conv({})
+        with pytest.raises(TypeError):
+            self.conv([])
+
+    def test_wrong_value(self):
+        # nonsense strings
+        self._check_value_error('')
+        self._check_value_error('\N{greek small letter pi}')
+
+        if self.allow_bytes:
+            self._check_value_error(b'')
+            # bytes which can't be converted to strings via utf8
+            self._check_value_error(b"\xFF")
+        if self.exact_match:
+            self._check_value_error("there's no way this is supported")
+
+
+class TestByteorderConverter(StringConverterTestCase):
+    """ Tests of PyArray_ByteorderConverter """
+    conv = mt.run_byteorder_converter
+    def test_valid(self):
+        for s in ['big', '>']:
+            self._check(s, 'NPY_BIG')
+        for s in ['little', '<']:
+            self._check(s, 'NPY_LITTLE')
+        for s in ['native', '=']:
+            self._check(s, 'NPY_NATIVE')
+        for s in ['ignore', '|']:
+            self._check(s, 'NPY_IGNORE')
+        for s in ['swap']:
+            self._check(s, 'NPY_SWAP')
+
+
+class TestSortkindConverter(StringConverterTestCase):
+    """ Tests of PyArray_SortkindConverter """
+    conv = mt.run_sortkind_converter
+    def test_valid(self):
+        self._check('quick', 'NPY_QUICKSORT')
+        self._check('heap', 'NPY_HEAPSORT')
+        self._check('merge', 'NPY_STABLESORT')  # alias
+        self._check('stable', 'NPY_STABLESORT')
+
+
+class TestSelectkindConverter(StringConverterTestCase):
+    """ Tests of PyArray_SelectkindConverter """
+    conv = mt.run_selectkind_converter
+    case_insensitive = False
+    exact_match = True
+
+    def test_valid(self):
+        self._check('introselect', 'NPY_INTROSELECT')
+
+
+class TestSearchsideConverter(StringConverterTestCase):
+    """ Tests of PyArray_SearchsideConverter """
+    conv = mt.run_searchside_converter
+    def test_valid(self):
+        self._check('left', 'NPY_SEARCHLEFT')
+        self._check('right', 'NPY_SEARCHRIGHT')
+
+
+class TestOrderConverter(StringConverterTestCase):
+    """ Tests of PyArray_OrderConverter """
+    conv = mt.run_order_converter
+    def test_valid(self):
+        self._check('c', 'NPY_CORDER')
+        self._check('f', 'NPY_FORTRANORDER')
+        self._check('a', 'NPY_ANYORDER')
+        self._check('k', 'NPY_KEEPORDER')
+
+    def test_flatten_invalid_order(self):
+        # invalid after gh-14596
+        with pytest.raises(ValueError):
+            self.conv('Z')
+        for order in [False, True, 0, 8]:
+            with pytest.raises(TypeError):
+                self.conv(order)
+
+
+class TestClipmodeConverter(StringConverterTestCase):
+    """ Tests of PyArray_ClipmodeConverter """
+    conv = mt.run_clipmode_converter
+    def test_valid(self):
+        self._check('clip', 'NPY_CLIP')
+        self._check('wrap', 'NPY_WRAP')
+        self._check('raise', 'NPY_RAISE')
+
+        # integer values allowed here
+        assert self.conv(np.CLIP) == 'NPY_CLIP'
+        assert self.conv(np.WRAP) == 'NPY_WRAP'
+        assert self.conv(np.RAISE) == 'NPY_RAISE'
+
+
+class TestCastingConverter(StringConverterTestCase):
+    """ Tests of PyArray_CastingConverter """
+    conv = mt.run_casting_converter
+    case_insensitive = False
+    exact_match = True
+
+    def test_valid(self):
+        self._check("no", "NPY_NO_CASTING")
+        self._check("equiv", "NPY_EQUIV_CASTING")
+        self._check("safe", "NPY_SAFE_CASTING")
+        self._check("same_kind", "NPY_SAME_KIND_CASTING")
+        self._check("unsafe", "NPY_UNSAFE_CASTING")
diff --git a/numpy/core/tests/test_cpu_features.py b/numpy/core/tests/test_cpu_features.py
new file mode 100644 (file)
index 0000000..337b733
--- /dev/null
@@ -0,0 +1,127 @@
+import sys, platform, re, pytest
+
+from numpy.testing import assert_equal
+from numpy.core._multiarray_umath import __cpu_features__
+
+class AbstractTest(object):
+    features = []
+    features_groups = {}
+    features_map = {}
+    features_flags = set()
+
+    def load_flags(self):
+        # a hook
+        pass
+
+    def test_features(self):
+        self.load_flags()
+        for gname, features in self.features_groups.items():
+            test_features = [self.cpu_have(f) for f in features]
+            assert_equal(__cpu_features__.get(gname), all(test_features))
+
+        for feature_name in self.features:
+            cpu_have = self.cpu_have(feature_name)
+            npy_have = __cpu_features__.get(feature_name)
+            assert_equal(npy_have, cpu_have)
+
+    def cpu_have(self, feature_name):
+        map_names = self.features_map.get(feature_name, feature_name)
+        if isinstance(map_names, str):
+            return map_names in self.features_flags
+        for f in map_names:
+            if f in self.features_flags:
+                return True
+        return False
+
+    def load_flags_cpuinfo(self, magic_key):
+        self.features_flags = self.get_cpuinfo_item(magic_key)
+
+    def get_cpuinfo_item(self, magic_key):
+        values = set()
+        with open('/proc/cpuinfo') as fd:
+            for line in fd:
+                if not line.startswith(magic_key):
+                    continue
+                flags_value = [s.strip() for s in line.split(':', 1)]
+                if len(flags_value) == 2:
+                    values = values.union(flags_value[1].upper().split())
+        return values
+
+    def load_flags_auxv(self):
+        import subprocess
+        auxv = subprocess.check_output(['/bin/true'], env=dict(LD_SHOW_AUXV="1"))
+        for at in auxv.split(b'\n'):
+            if not at.startswith(b"AT_HWCAP"):
+                continue
+            hwcap_value = [s.strip() for s in at.split(b':', 1)]
+            if len(hwcap_value) == 2:
+                self.features_flags = self.features_flags.union(
+                    hwcap_value[1].upper().decode().split()
+                )
+
+is_linux = sys.platform.startswith('linux')
+machine  = platform.machine()
+is_x86   = re.match("^(amd64|x86|i386|i686)", machine, re.IGNORECASE)
+@pytest.mark.skipif(not is_linux or not is_x86, reason="Only for Linux and x86")
+class Test_X86_Features(AbstractTest):
+    features = [
+        "MMX", "SSE", "SSE2", "SSE3", "SSSE3", "SSE41", "POPCNT", "SSE42",
+        "AVX", "F16C", "XOP", "FMA4", "FMA3", "AVX2", "AVX512F", "AVX512CD",
+        "AVX512ER", "AVX512PF", "AVX5124FMAPS", "AVX5124VNNIW", "AVX512VPOPCNTDQ",
+        "AVX512VL", "AVX512BW", "AVX512DQ", "AVX512VNNI", "AVX512IFMA",
+        "AVX512VBMI", "AVX512VBMI2", "AVX512BITALG",
+    ]
+    features_groups = dict(
+        AVX512_KNL = ["AVX512F", "AVX512CD", "AVX512ER", "AVX512PF"],
+        AVX512_KNM = ["AVX512F", "AVX512CD", "AVX512ER", "AVX512PF", "AVX5124FMAPS",
+                      "AVX5124VNNIW", "AVX512VPOPCNTDQ"],
+        AVX512_SKX = ["AVX512F", "AVX512CD", "AVX512BW", "AVX512DQ", "AVX512VL"],
+        AVX512_CLX = ["AVX512F", "AVX512CD", "AVX512BW", "AVX512DQ", "AVX512VL", "AVX512VNNI"],
+        AVX512_CNL = ["AVX512F", "AVX512CD", "AVX512BW", "AVX512DQ", "AVX512VL", "AVX512IFMA",
+                      "AVX512VBMI"],
+        AVX512_ICL = ["AVX512F", "AVX512CD", "AVX512BW", "AVX512DQ", "AVX512VL", "AVX512IFMA",
+                      "AVX512VBMI", "AVX512VNNI", "AVX512VBMI2", "AVX512BITALG", "AVX512VPOPCNTDQ"],
+    )
+    features_map = dict(
+        SSE3="PNI", SSE41="SSE4_1", SSE42="SSE4_2", FMA3="FMA",
+        AVX512VNNI="AVX512_VNNI", AVX512BITALG="AVX512_BITALG", AVX512VBMI2="AVX512_VBMI2",
+        AVX5124FMAPS="AVX512_4FMAPS", AVX5124VNNIW="AVX512_4VNNIW", AVX512VPOPCNTDQ="AVX512_VPOPCNTDQ",
+    )
+    def load_flags(self):
+        self.load_flags_cpuinfo("flags")
+
+is_power = re.match("^(powerpc|ppc)64", machine, re.IGNORECASE)
+@pytest.mark.skipif(not is_linux or not is_power, reason="Only for Linux and Power")
+class Test_POWER_Features(AbstractTest):
+    features = ["VSX", "VSX2", "VSX3"]
+    features_map = dict(VSX2="ARCH_2_07", VSX3="ARCH_3_00")
+
+    def load_flags(self):
+        self.load_flags_auxv()
+
+is_arm = re.match("^(arm|aarch64)", machine, re.IGNORECASE)
+@pytest.mark.skipif(not is_linux or not is_arm, reason="Only for Linux and ARM")
+class Test_ARM_Features(AbstractTest):
+    features = [
+        "NEON", "ASIMD", "FPHP", "ASIMDHP", "ASIMDDP", "ASIMDFHM"
+    ]
+    features_groups = dict(
+        NEON_FP16  = ["NEON", "HALF"],
+        NEON_VFPV4 = ["NEON", "VFPV4"],
+    )
+    def load_flags(self):
+        self.load_flags_cpuinfo("Features")
+        arch = self.get_cpuinfo_item("CPU architecture")
+        # in case of mounting virtual filesystem of aarch64 kernel
+        is_rootfs_v8 = int('0'+next(iter(arch))) > 7 if arch else 0
+        if  re.match("^(aarch64|AARCH64)", machine) or is_rootfs_v8:
+            self.features_map = dict(
+                NEON="ASIMD", HALF="ASIMD", VFPV4="ASIMD"
+            )
+        else:
+            self.features_map = dict(
+                # ELF auxiliary vector and /proc/cpuinfo on Linux kernel(armv8 aarch32)
+                # doesn't provide information about ASIMD, so we assume that ASIMD is supported
+                # if the kernel reports any one of the following ARM8 features.
+                ASIMD=("AES", "SHA1", "SHA2", "PMULL", "CRC32")
+            )
index d38444ef7ea130e7835ebc05ea864d8bc69a8ff7..438d52f97f73f6491c8df89acd357f8d03d5c270 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 
 import numpy
 import numpy as np
@@ -24,7 +22,7 @@ except NameError:
     RecursionError = RuntimeError  # python < 3.5
 
 
-class TestDateTime(object):
+class TestDateTime:
     def test_datetime_dtype_creation(self):
         for unit in ['Y', 'M', 'W', 'D',
                      'h', 'm', 's', 'ms', 'us',
@@ -2368,7 +2366,7 @@ class TestDateTime(object):
         assert limit_via_str == limit
 
 
-class TestDateTimeData(object):
+class TestDateTimeData:
 
     def test_basic(self):
         a = np.array(['1980-03-23'], dtype=np.datetime64)
index 7b0e6f8a4bee5b1e1d8c26be94e5b659d5f4bd53..bbb94f7d38d6d4a3079276fe0ab9198c9fd8deca 100644 (file)
@@ -1,18 +1,15 @@
-from __future__ import division, absolute_import, print_function
-
-import sys
 
 import numpy as np
 from numpy.core.multiarray import _vec_string
 from numpy.testing import (
     assert_, assert_equal, assert_array_equal, assert_raises,
-    assert_raises_regex, suppress_warnings,
+    assert_raises_regex
     )
 
 kw_unicode_true = {'unicode': True}  # make 2to3 work properly
 kw_unicode_false = {'unicode': False}
 
-class TestBasic(object):
+class TestBasic:
     def test_from_object_array(self):
         A = np.array([['abc', 2],
                       ['long   ', '0123456789']], dtype='O')
@@ -83,7 +80,7 @@ class TestBasic(object):
         assert_equal(A.itemsize, 4)
         assert_(issubclass(A.dtype.type, np.unicode_))
 
-class TestVecString(object):
+class TestVecString:
     def test_non_existent_method(self):
 
         def fail():
@@ -122,19 +119,19 @@ class TestVecString(object):
     def test_invalid_result_type(self):
 
         def fail():
-            _vec_string(['a'], np.integer, 'strip')
+            _vec_string(['a'], np.int_, 'strip')
 
         assert_raises(TypeError, fail)
 
     def test_broadcast_error(self):
 
         def fail():
-            _vec_string([['abc', 'def']], np.integer, 'find', (['a', 'd', 'j'],))
+            _vec_string([['abc', 'def']], np.int_, 'find', (['a', 'd', 'j'],))
 
         assert_raises(ValueError, fail)
 
 
-class TestWhitespace(object):
+class TestWhitespace:
     def setup(self):
         self.A = np.array([['abc ', '123  '],
                            ['789 ', 'xyz ']]).view(np.chararray)
@@ -149,7 +146,7 @@ class TestWhitespace(object):
         assert_(not np.any(self.A < self.B))
         assert_(not np.any(self.A != self.B))
 
-class TestChar(object):
+class TestChar:
     def setup(self):
         self.A = np.array('abc1', dtype='c').view(np.chararray)
 
@@ -157,7 +154,7 @@ class TestChar(object):
         assert_equal(self.A.shape, (4,))
         assert_equal(self.A.upper()[:2].tobytes(), b'AB')
 
-class TestComparisons(object):
+class TestComparisons:
     def setup(self):
         self.A = np.array([['abc', '123'],
                            ['789', 'xyz']]).view(np.chararray)
@@ -198,7 +195,7 @@ class TestComparisonsMixed2(TestComparisons):
         self.A = np.array([['abc', '123'],
                            ['789', 'xyz']], np.unicode_).view(np.chararray)
 
-class TestInformation(object):
+class TestInformation:
     def setup(self):
         self.A = np.array([[' abc ', ''],
                            ['12345', 'MixedCase'],
@@ -304,7 +301,7 @@ class TestInformation(object):
         assert_raises(TypeError, fail)
 
 
-class TestMethods(object):
+class TestMethods:
     def setup(self):
         self.A = np.array([[' abc ', ''],
                            ['12345', 'MixedCase'],
@@ -343,15 +340,8 @@ class TestMethods(object):
         assert_array_equal(C, tgt)
 
     def test_decode(self):
-        if sys.version_info[0] >= 3:
-            A = np.char.array([b'\\u03a3'])
-            assert_(A.decode('unicode-escape')[0] == '\u03a3')
-        else:
-            with suppress_warnings() as sup:
-                if sys.py3kwarning:
-                    sup.filter(DeprecationWarning, "'hex_codec'")
-                A = np.char.array(['736563726574206d657373616765'])
-                assert_(A.decode('hex_codec')[0] == 'secret message')
+        A = np.char.array([b'\\u03a3'])
+        assert_(A.decode('unicode-escape')[0] == '\u03a3')
 
     def test_encode(self):
         B = self.B.encode('unicode_escape')
@@ -362,18 +352,12 @@ class TestMethods(object):
         assert_(T[2, 0] == b'123      345 \0')
 
     def test_join(self):
-        if sys.version_info[0] >= 3:
-            # NOTE: list(b'123') == [49, 50, 51]
-            #       so that b','.join(b'123') results to an error on Py3
-            A0 = self.A.decode('ascii')
-        else:
-            A0 = self.A
+        # NOTE: list(b'123') == [49, 50, 51]
+        #       so that b','.join(b'123') results to an error on Py3
+        A0 = self.A.decode('ascii')
 
         A = np.char.join([',', '#'], A0)
-        if sys.version_info[0] >= 3:
-            assert_(issubclass(A.dtype.type, np.unicode_))
-        else:
-            assert_(issubclass(A.dtype.type, np.string_))
+        assert_(issubclass(A.dtype.type, np.unicode_))
         tgt = np.array([[' ,a,b,c, ', ''],
                         ['1,2,3,4,5', 'M#i#x#e#d#C#a#s#e'],
                         ['1,2,3, ,\t, ,3,4,5, ,\x00, ', 'U#P#P#E#R']])
@@ -444,15 +428,6 @@ class TestMethods(object):
         assert_(issubclass(R.dtype.type, np.string_))
         assert_array_equal(R, tgt)
 
-        if sys.version_info[0] < 3:
-            # NOTE: b'abc'.replace(b'a', 'b') is not allowed on Py3
-            R = self.A.replace(b'a', u'\u03a3')
-            tgt = [[u' \u03a3bc ', ''],
-                   ['12345', u'MixedC\u03a3se'],
-                   ['123 \t 345 \x00', 'UPPER']]
-            assert_(issubclass(R.dtype.type, np.unicode_))
-            assert_array_equal(R, tgt)
-
     def test_rjust(self):
         assert_(issubclass(self.A.rjust(10).dtype.type, np.string_))
 
@@ -599,7 +574,7 @@ class TestMethods(object):
                 [False, False], [True, False], [False, False]])
 
 
-class TestOperations(object):
+class TestOperations:
     def setup(self):
         self.A = np.array([['abc', '123'],
                            ['789', 'xyz']]).view(np.chararray)
index 363ff26db32081af421a19e54716b3e0f5f913c1..82d24e0f7aca4f61158cddd2e181f04f2c56d9fc 100644 (file)
@@ -3,15 +3,12 @@ Tests related to deprecation warnings. Also a convenient place
 to document how deprecations should eventually be turned into errors.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import datetime
-import sys
 import operator
 import warnings
 import pytest
-import shutil
 import tempfile
+import re
 
 import numpy as np
 from numpy.testing import (
@@ -27,7 +24,7 @@ except ImportError:
     _has_pytz = False
 
 
-class _DeprecationTestCase(object):
+class _DeprecationTestCase:
     # Just as warning: warnings uses re.match, so the start of this message
     # must match.
     message = ''
@@ -137,7 +134,7 @@ class _VisibleDeprecationTestCase(_DeprecationTestCase):
     warning_cls = np.VisibleDeprecationWarning
 
 
-class TestNonTupleNDIndexDeprecation(object):
+class TestNonTupleNDIndexDeprecation:
     def test_basic(self):
         a = np.zeros((5, 5))
         with warnings.catch_warnings():
@@ -189,7 +186,7 @@ class TestComparisonDeprecations(_DeprecationTestCase):
         assert_warns(FutureWarning, lambda: a == [])
 
     def test_void_dtype_equality_failures(self):
-        class NotArray(object):
+        class NotArray:
             def __array__(self):
                 raise TypeError
 
@@ -229,15 +226,10 @@ class TestComparisonDeprecations(_DeprecationTestCase):
             struct = np.zeros(2, dtype="i4,i4")
             for arg2 in [struct, "a"]:
                 for f in [operator.lt, operator.le, operator.gt, operator.ge]:
-                    if sys.version_info[0] >= 3:
-                        # py3
-                        with warnings.catch_warnings() as l:
-                            warnings.filterwarnings("always")
-                            assert_raises(TypeError, f, arg1, arg2)
-                            assert_(not l)
-                    else:
-                        # py2
-                        assert_warns(DeprecationWarning, f, arg1, arg2)
+                    with warnings.catch_warnings() as l:
+                        warnings.filterwarnings("always")
+                        assert_raises(TypeError, f, arg1, arg2)
+                        assert_(not l)
 
 
 class TestDatetime64Timezone(_DeprecationTestCase):
@@ -334,15 +326,12 @@ class TestNumericStyleTypecodes(_DeprecationTestCase):
             'Int8', 'Int16', 'Int32', 'Int64', 'Object0', 'Timedelta64',
             'UInt8', 'UInt16', 'UInt32', 'UInt64', 'Void0'
             ]
-        if sys.version_info[0] < 3:
-            deprecated_types.extend(['Unicode0', 'String0'])
-
         for dt in deprecated_types:
             self.assert_deprecated(np.dtype, exceptions=(TypeError,),
                                    args=(dt,))
 
 
-class TestTestDeprecated(object):
+class TestTestDeprecated:
     def test_assert_deprecated(self):
         test_case_instance = _DeprecationTestCase()
         test_case_instance.setup()
@@ -357,28 +346,6 @@ class TestTestDeprecated(object):
         test_case_instance.teardown()
 
 
-class TestClassicIntDivision(_DeprecationTestCase):
-    """
-    See #7949. Deprecate the numeric-style dtypes with -3 flag in python 2
-    if used for division
-    List of data types: https://docs.scipy.org/doc/numpy/user/basics.types.html
-    """
-    def test_int_dtypes(self):
-        #scramble types and do some mix and match testing
-        deprecated_types = [
-           'bool_', 'int_', 'intc', 'uint8', 'int8', 'uint64', 'int32', 'uint16',
-           'intp', 'int64', 'uint32', 'int16'
-            ]
-        if sys.version_info[0] < 3 and sys.py3kwarning:
-            import operator as op
-            dt2 = 'bool_'
-            for dt1 in deprecated_types:
-                a = np.array([1,2,3], dtype=dt1)
-                b = np.array([1,2,3], dtype=dt2)
-                self.assert_deprecated(op.div, args=(a,b))
-                dt2 = dt1
-
-
 class TestNonNumericConjugate(_DeprecationTestCase):
     """
     Deprecate no-op behavior of ndarray.conjugate on non-numeric dtypes,
@@ -568,3 +535,86 @@ class TestNonZero(_DeprecationTestCase):
     def test_zerod(self):
         self.assert_deprecated(lambda: np.nonzero(np.array(0)))
         self.assert_deprecated(lambda: np.nonzero(np.array(1)))
+
+
+def test_deprecate_ragged_arrays():
+    # 2019-11-29 1.19.0
+    #
+    # NEP 34 deprecated automatic object dtype when creating ragged
+    # arrays. Also see the "ragged" tests in `test_multiarray`
+    #
+    # emits a VisibleDeprecationWarning
+    arg = [1, [2, 3]]
+    with assert_warns(np.VisibleDeprecationWarning):
+        np.array(arg)
+
+
+class TestToString(_DeprecationTestCase):
+    # 2020-03-06 1.19.0
+    message = re.escape("tostring() is deprecated. Use tobytes() instead.")
+
+    def test_tostring(self):
+        arr = np.array(list(b"test\xFF"), dtype=np.uint8)
+        self.assert_deprecated(arr.tostring)
+
+    def test_tostring_matches_tobytes(self):
+        arr = np.array(list(b"test\xFF"), dtype=np.uint8)
+        b = arr.tobytes()
+        with assert_warns(DeprecationWarning):
+            s = arr.tostring()
+        assert s == b
+
+
+class TestDTypeCoercion(_DeprecationTestCase):
+    # 2020-02-06 1.19.0
+    message = "Converting .* to a dtype .*is deprecated"
+    deprecated_types = [
+        # The builtin scalar super types:
+        np.generic, np.flexible, np.number,
+        np.inexact, np.floating, np.complexfloating,
+        np.integer, np.unsignedinteger, np.signedinteger,
+        # character is a deprecated S1 special case:
+        np.character,
+    ]
+
+    def test_dtype_coercion(self):
+        for scalar_type in self.deprecated_types:
+            self.assert_deprecated(np.dtype, args=(scalar_type,))
+
+    def test_array_construction(self):
+        for scalar_type in self.deprecated_types:
+            self.assert_deprecated(np.array, args=([], scalar_type,))
+
+    def test_not_deprecated(self):
+        # All specific types are not deprecated:
+        for group in np.sctypes.values():
+            for scalar_type in group:
+                self.assert_not_deprecated(np.dtype, args=(scalar_type,))
+
+        for scalar_type in [type, dict, list, tuple]:
+            # Typical python types are coerced to object currently:
+            self.assert_not_deprecated(np.dtype, args=(scalar_type,))
+
+
+class BuiltInRoundComplexDType(_DeprecationTestCase):
+    # 2020-03-31 1.19.0
+    deprecated_types = [np.csingle, np.cdouble, np.clongdouble]
+    not_deprecated_types = [
+        np.int8, np.int16, np.int32, np.int64,
+        np.uint8, np.uint16, np.uint32, np.uint64,
+        np.float16, np.float32, np.float64,
+    ]
+
+    def test_deprecated(self):
+        for scalar_type in self.deprecated_types:
+            scalar = scalar_type(0)
+            self.assert_deprecated(round, args=(scalar,))
+            self.assert_deprecated(round, args=(scalar, 0))
+            self.assert_deprecated(round, args=(scalar,), kwargs={'ndigits': 0})
+    
+    def test_not_deprecated(self):
+        for scalar_type in self.not_deprecated_types:
+            scalar = scalar_type(0)
+            self.assert_not_deprecated(round, args=(scalar,))
+            self.assert_not_deprecated(round, args=(scalar, 0))
+            self.assert_not_deprecated(round, args=(scalar,), kwargs={'ndigits': 0})
index e18e66c649bc4a3706f062aaa80658f251ec1590..c9a65cd9ccceddfd40925930e5efef328228a24a 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import operator
 import pytest
@@ -23,7 +21,7 @@ def assert_dtype_not_equal(a, b):
     assert_(hash(a) != hash(b),
             "two different types hash to the same value !")
 
-class TestBuiltin(object):
+class TestBuiltin:
     @pytest.mark.parametrize('t', [int, float, complex, np.int32, str, object,
                                    np.compat.unicode])
     def test_run(self, t):
@@ -138,15 +136,15 @@ class TestBuiltin(object):
                          'offsets':[0, 2]}, align=True)
 
     def test_field_order_equality(self):
-        x = np.dtype({'names': ['A', 'B'], 
-                      'formats': ['i4', 'f4'], 
+        x = np.dtype({'names': ['A', 'B'],
+                      'formats': ['i4', 'f4'],
                       'offsets': [0, 4]})
-        y = np.dtype({'names': ['B', 'A'], 
-                      'formats': ['f4', 'i4'], 
+        y = np.dtype({'names': ['B', 'A'],
+                      'formats': ['f4', 'i4'],
                       'offsets': [4, 0]})
         assert_equal(x == y, False)
 
-class TestRecord(object):
+class TestRecord:
     def test_equivalent_record(self):
         """Test whether equivalent record dtypes hash the same."""
         a = np.dtype([('yo', int)])
@@ -420,7 +418,7 @@ class TestRecord(object):
                 {'formats': ['i4', 'i4'], 'f0': ('i4', 0), 'f1':('i4', 4)})
 
     def test_fieldless_views(self):
-        a = np.zeros(2, dtype={'names':[], 'formats':[], 'offsets':[], 
+        a = np.zeros(2, dtype={'names':[], 'formats':[], 'offsets':[],
                                'itemsize':8})
         assert_raises(ValueError, a.view, np.dtype([]))
 
@@ -445,7 +443,7 @@ class TestRecord(object):
                      np.ones((1, 2), dtype=bool))
 
 
-class TestSubarray(object):
+class TestSubarray:
     def test_single_subarray(self):
         a = np.dtype((int, (2)))
         b = np.dtype((int, (2,)))
@@ -521,7 +519,7 @@ class TestSubarray(object):
         assert_(isinstance(dt['a'].shape, tuple))
         #
 
-        class IntLike(object):
+        class IntLike:
             def __index__(self):
                 return 3
 
@@ -711,7 +709,7 @@ class TestStructuredObjectRefcounting:
         assert after_repeat - after == count * 2 * 10
 
 
-class TestStructuredDtypeSparseFields(object):
+class TestStructuredDtypeSparseFields:
     """Tests subarray fields which contain sparse dtypes so that
     not all memory is used by the dtype work. Such dtype's should
     leave the underlying memory unchanged.
@@ -732,7 +730,7 @@ class TestStructuredDtypeSparseFields(object):
         assert_array_equal(arr["a"]["aa"], np.zeros((3, 2, 3)))
 
     def test_sparse_field_assignment_fancy(self):
-        # Fancy assignment goes to the copyswap function for comlex types:
+        # Fancy assignment goes to the copyswap function for complex types:
         arr = np.zeros(3, self.dtype)
         sparse_arr = arr.view(self.sparse_dtype)
 
@@ -741,7 +739,7 @@ class TestStructuredDtypeSparseFields(object):
         assert_array_equal(arr["a"]["aa"], np.zeros((3, 2, 3)))
 
 
-class TestMonsterType(object):
+class TestMonsterType:
     """Test deeply nested subtypes."""
 
     def test1(self):
@@ -759,7 +757,7 @@ class TestMonsterType(object):
             ('yi', np.dtype((a, (3, 2))))])
         assert_dtype_equal(c, d)
 
-class TestMetadata(object):
+class TestMetadata:
     def test_no_metadata(self):
         d = np.dtype(int)
         assert_(d.metadata is None)
@@ -781,7 +779,7 @@ class TestMetadata(object):
         d = np.dtype((np.void, np.dtype('i4,i4', metadata={'datum': 1})))
         assert_(d.metadata == {'datum': 1})
 
-class TestString(object):
+class TestString:
     def test_complex_dtype_str(self):
         dt = np.dtype([('top', [('tiles', ('>f4', (64, 64)), (1,)),
                                 ('rtile', '>f4', (64, 36))], (3,)),
@@ -902,11 +900,6 @@ class TestString(object):
         assert_equal(repr(dt), "dtype(('<i2', (1,)))")
         assert_equal(str(dt), "('<i2', (1,))")
 
-    @pytest.mark.skipif(sys.version_info[0] >= 3, reason="Python 2 only")
-    def test_dtype_str_with_long_in_shape(self):
-        # Pull request #376, should not error
-        np.dtype('(1L,)i4')
-
     def test_base_dtype_with_object_type(self):
         # Issue gh-2798, should not error.
         np.array(['a'], dtype="O").astype(("O", [("name", "O")]))
@@ -934,7 +927,7 @@ class TestString(object):
         assert_equal(dt.name, 'record16')
 
 
-class TestDtypeAttributeDeletion(object):
+class TestDtypeAttributeDeletion:
 
     def test_dtype_non_writable_attributes_deletion(self):
         dt = np.dtype(np.double)
@@ -952,7 +945,7 @@ class TestDtypeAttributeDeletion(object):
             assert_raises(AttributeError, delattr, dt, s)
 
 
-class TestDtypeAttributes(object):
+class TestDtypeAttributes:
     def test_descr_has_trailing_void(self):
         # see gh-6359
         dtype = np.dtype({
@@ -970,7 +963,7 @@ class TestDtypeAttributes(object):
         assert_equal(np.dtype(user_def_subcls).name, 'user_def_subcls')
 
 
-class TestPickling(object):
+class TestPickling:
 
     def check_pickling(self, dtype):
         for proto in range(pickle.HIGHEST_PROTOCOL + 1):
@@ -1054,7 +1047,7 @@ def test_invalid_dtype_string():
     assert_raises(TypeError, np.dtype, u'Fl\xfcgel')
 
 
-class TestFromDTypeAttribute(object):
+class TestFromDTypeAttribute:
     def test_simple(self):
         class dt:
             dtype = "f8"
@@ -1098,7 +1091,7 @@ class TestFromDTypeAttribute(object):
         with pytest.raises(RecursionError):
             np.dtype(dt(1))
 
-class TestFromCTypes(object):
+class TestFromCTypes:
 
     @staticmethod
     def check(ctype, dtype):
index 1b5b4cb262445b1cfbd4e41d51278ad6bfdaa469..da84735a0614548d6a2e58577d19727c6fda56a7 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import itertools
 
 import numpy as np
@@ -14,7 +12,7 @@ sizes = np.array([2, 3, 4, 5, 4, 3, 2, 6, 5, 4, 3])
 global_size_dict = dict(zip(chars, sizes))
 
 
-class TestEinsum(object):
+class TestEinsum:
     def test_einsum_errors(self):
         for do_opt in [True, False]:
             # Need enough arguments
@@ -29,7 +27,7 @@ class TestEinsum(object):
                           optimize=do_opt)
 
             # order parameter must be a valid order
-            assert_raises(TypeError, np.einsum, "", 0, order='W',
+            assert_raises(ValueError, np.einsum, "", 0, order='W',
                           optimize=do_opt)
 
             # casting parameter must be a valid casting
@@ -276,6 +274,13 @@ class TestEinsum(object):
             assert_equal(np.einsum(a, [0, 0], optimize=do_opt),
                          np.trace(a).astype(dtype))
 
+            # gh-15961: should accept numpy int64 type in subscript list
+            np_array = np.asarray([0, 0])
+            assert_equal(np.einsum(a, np_array, optimize=do_opt),
+                         np.trace(a).astype(dtype))
+            assert_equal(np.einsum(a, list(np_array), optimize=do_opt),
+                         np.trace(a).astype(dtype))
+
         # multiply(a, b)
         assert_equal(np.einsum("..., ...", 3, 4), 12)  # scalar case
         for n in range(1, 17):
@@ -607,6 +612,10 @@ class TestEinsum(object):
                      [[[1,  3], [3,  9], [5, 15], [7, 21]],
                      [[8, 16], [16, 32], [24, 48], [32, 64]]])
 
+        # Ensure explicitly setting out=None does not cause an error
+        # see issue gh-15776 and issue gh-15256
+        assert_equal(np.einsum('i,j', [1], [2], out=None), [[2]])
+
     def test_subscript_range(self):
         # Issue #7741, make sure that all letters of Latin alphabet (both uppercase & lowercase) can be used
         # when creating a subscript from arrays
@@ -868,7 +877,7 @@ class TestEinsum(object):
         self.optimize_compare('obk,ijk->ioj', operands=[g, g])
 
 
-class TestEinsumPath(object):
+class TestEinsumPath:
     def build_operands(self, string, size_dict=global_size_dict):
 
         # Builds views based off initial operands
index 0008c4cc8023dd2c6d479b9aaa1faff827cba452..184a373002fa1c39d5089bc102063912dfafda61 100644 (file)
@@ -1,14 +1,19 @@
-from __future__ import division, absolute_import, print_function
-
-import platform
 import pytest
+import sysconfig
 
 import numpy as np
 from numpy.testing import assert_, assert_raises
 
+# The floating point emulation on ARM EABI systems lacking a hardware FPU is
+# known to be buggy. This is an attempt to identify these hosts. It may not
+# catch all possible cases, but it catches the known cases of gh-413 and
+# gh-15562.
+hosttype = sysconfig.get_config_var('HOST_GNU_TYPE')
+arm_softfloat = False if hosttype is None else hosttype.endswith('gnueabi')
 
-class TestErrstate(object):
-    @pytest.mark.skipif(platform.machine() == "armv5tel", reason="See gh-413.")
+class TestErrstate:
+    @pytest.mark.skipif(arm_softfloat,
+                        reason='platform/cpu issue with FPU (gh-413,-15562)')
     def test_invalid(self):
         with np.errstate(all='raise', under='ignore'):
             a = -np.arange(3)
@@ -19,6 +24,8 @@ class TestErrstate(object):
             with assert_raises(FloatingPointError):
                 np.sqrt(a)
 
+    @pytest.mark.skipif(arm_softfloat,
+                        reason='platform/cpu issue with FPU (gh-15562)')
     def test_divide(self):
         with np.errstate(all='raise', under='ignore'):
             a = -np.arange(3)
@@ -28,6 +35,9 @@ class TestErrstate(object):
             # While this should fail!
             with assert_raises(FloatingPointError):
                 a // 0
+            # As should this, see gh-15562
+            with assert_raises(FloatingPointError):
+                a // a
 
     def test_errcall(self):
         def foo(*args):
index 7c454a603b60c7606f7d4611ca29bff6755231ce..3b64915f36a3c1874a7e8ee5cb0346c2fca39333 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import itertools
 import contextlib
 import operator
index c8a7cb6ce87db77c482662496cd859e90ad781ff..2197ef0cdc5c4343edba5e1d6b9c4d562730f129 100644 (file)
@@ -1,12 +1,9 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy import (
     logspace, linspace, geomspace, dtype, array, sctypes, arange, isnan,
     ndarray, sqrt, nextafter, stack
     )
 from numpy.testing import (
     assert_, assert_equal, assert_raises, assert_array_equal, assert_allclose,
-    suppress_warnings
     )
 
 
@@ -42,7 +39,7 @@ class PhysicalQuantity2(ndarray):
     __array_priority__ = 10
 
 
-class TestLogspace(object):
+class TestLogspace:
 
     def test_basic(self):
         y = logspace(0, 6)
@@ -92,7 +89,7 @@ class TestLogspace(object):
         assert_equal(ls, logspace(1.0, 7.0, 1))
 
 
-class TestGeomspace(object):
+class TestGeomspace:
 
     def test_basic(self):
         y = geomspace(1, 1e6)
@@ -222,7 +219,7 @@ class TestGeomspace(object):
         assert_raises(ValueError, geomspace, 0, 0)
 
 
-class TestLinspace(object):
+class TestLinspace:
 
     def test_basic(self):
         y = linspace(0, 10)
@@ -309,7 +306,7 @@ class TestLinspace(object):
         # Ensure that start/stop can be objects that implement
         # __array_interface__ and are convertible to numeric scalars
 
-        class Arrayish(object):
+        class Arrayish:
             """
             A generic object that supports the __array_interface__ and hence
             can in principle be converted to a numeric scalar, but is not
index 2f66481836509c53d62ff3e67659e1330dd49794..bcf8cf659b791e4fce2d7794a9281488bd2f2a22 100644 (file)
@@ -1,8 +1,6 @@
 """ Test functions for limits module.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.core import finfo, iinfo
 from numpy import half, single, double, longdouble
@@ -11,37 +9,37 @@ from numpy.core.getlimits import _discovered_machar, _float_ma
 
 ##################################################
 
-class TestPythonFloat(object):
+class TestPythonFloat:
     def test_singleton(self):
         ftype = finfo(float)
         ftype2 = finfo(float)
         assert_equal(id(ftype), id(ftype2))
 
-class TestHalf(object):
+class TestHalf:
     def test_singleton(self):
         ftype = finfo(half)
         ftype2 = finfo(half)
         assert_equal(id(ftype), id(ftype2))
 
-class TestSingle(object):
+class TestSingle:
     def test_singleton(self):
         ftype = finfo(single)
         ftype2 = finfo(single)
         assert_equal(id(ftype), id(ftype2))
 
-class TestDouble(object):
+class TestDouble:
     def test_singleton(self):
         ftype = finfo(double)
         ftype2 = finfo(double)
         assert_equal(id(ftype), id(ftype2))
 
-class TestLongdouble(object):
+class TestLongdouble:
     def test_singleton(self):
         ftype = finfo(longdouble)
         ftype2 = finfo(longdouble)
         assert_equal(id(ftype), id(ftype2))
 
-class TestFinfo(object):
+class TestFinfo:
     def test_basic(self):
         dts = list(zip(['f2', 'f4', 'f8', 'c8', 'c16'],
                        [np.float16, np.float32, np.float64, np.complex64,
@@ -54,7 +52,7 @@ class TestFinfo(object):
                              getattr(finfo(dt2), attr), attr)
         assert_raises(ValueError, finfo, 'i4')
 
-class TestIinfo(object):
+class TestIinfo:
     def test_basic(self):
         dts = list(zip(['i1', 'i2', 'i4', 'i8',
                    'u1', 'u2', 'u4', 'u8'],
@@ -71,7 +69,7 @@ class TestIinfo(object):
         for T in types:
             assert_equal(iinfo(T).max, T(-1))
 
-class TestRepr(object):
+class TestRepr:
     def test_iinfo_repr(self):
         expected = "iinfo(min=-32768, max=32767, dtype=int16)"
         assert_equal(repr(np.iinfo(np.int16)), expected)
index 1e1e6d7d9ab10268f24cce16c8f75a48845d6f8a..ae9827bc7e78eed4efa7ff3e0c91af6ce975f58f 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import platform
 import pytest
 
@@ -18,7 +16,7 @@ def assert_raises_fpe(strmatch, callable, *args, **kwargs):
         assert_(False,
                 "Did not raise floating point %s error" % strmatch)
 
-class TestHalf(object):
+class TestHalf:
     def setup(self):
         # An array of all possible float16 values
         self.all_f16 = np.arange(0x10000, dtype=uint16)
@@ -331,6 +329,7 @@ class TestHalf(object):
         # All non-negative finite #'s
         a = np.arange(0x7c00, dtype=uint16)
         hinf = np.array((np.inf,), dtype=float16)
+        hnan = np.array((np.nan,), dtype=float16)
         a_f16 = a.view(dtype=float16)
 
         assert_equal(np.spacing(a_f16[:-1]), a_f16[1:]-a_f16[:-1])
@@ -339,6 +338,21 @@ class TestHalf(object):
         assert_equal(np.nextafter(a_f16[0], -hinf), -a_f16[1])
         assert_equal(np.nextafter(a_f16[1:], -hinf), a_f16[:-1])
 
+        assert_equal(np.nextafter(hinf, a_f16), a_f16[-1])
+        assert_equal(np.nextafter(-hinf, a_f16), -a_f16[-1])
+
+        assert_equal(np.nextafter(hinf, hinf), hinf)
+        assert_equal(np.nextafter(hinf, -hinf), a_f16[-1])
+        assert_equal(np.nextafter(-hinf, hinf), -a_f16[-1])
+        assert_equal(np.nextafter(-hinf, -hinf), -hinf)
+
+        assert_equal(np.nextafter(a_f16, hnan), hnan[0])
+        assert_equal(np.nextafter(hnan, a_f16), hnan[0])
+
+        assert_equal(np.nextafter(hnan, hnan), hnan)
+        assert_equal(np.nextafter(hinf, hnan), hnan)
+        assert_equal(np.nextafter(hnan, hinf), hnan)
+
         # switch to negatives
         a |= 0x8000
 
@@ -349,6 +363,12 @@ class TestHalf(object):
         assert_equal(np.nextafter(a_f16[1:], hinf), a_f16[:-1])
         assert_equal(np.nextafter(a_f16[:-1], -hinf), a_f16[1:])
 
+        assert_equal(np.nextafter(hinf, a_f16), -a_f16[-1])
+        assert_equal(np.nextafter(-hinf, a_f16), a_f16[-1])
+
+        assert_equal(np.nextafter(a_f16, hnan), hnan[0])
+        assert_equal(np.nextafter(hnan, a_f16), hnan[0])
+
     def test_half_ufuncs(self):
         """Test the various ufuncs"""
 
@@ -489,9 +509,6 @@ class TestHalf(object):
             assert_raises_fpe('invalid', np.divide, float16(np.inf), float16(np.inf))
             assert_raises_fpe('invalid', np.spacing, float16(np.inf))
             assert_raises_fpe('invalid', np.spacing, float16(np.nan))
-            assert_raises_fpe('invalid', np.nextafter, float16(np.inf), float16(0))
-            assert_raises_fpe('invalid', np.nextafter, float16(-np.inf), float16(0))
-            assert_raises_fpe('invalid', np.nextafter, float16(0), float16(np.nan))
 
             # These should not raise
             float16(65472)+float16(32)
@@ -500,6 +517,10 @@ class TestHalf(object):
             np.spacing(float16(-65504))
             np.nextafter(float16(65504), float16(-np.inf))
             np.nextafter(float16(-65504), float16(np.inf))
+            np.nextafter(float16(np.inf), float16(0))
+            np.nextafter(float16(-np.inf), float16(0))
+            np.nextafter(float16(0), float16(np.nan))
+            np.nextafter(float16(np.nan), float16(0))
             float16(2**-14)/float16(2**10)
             float16(-2**-14)/float16(2**10)
             float16(2**-14+2**-23)/float16(2)
index 63b43c473c8ae582cce7796f011b3e3539f2d167..a0e9a8c55834a8c3f77e36d6a6847a19a46a4eed 100644 (file)
@@ -1,9 +1,10 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
-from numpy.testing import assert_raises
+from numpy.testing import (
+        assert_raises, assert_raises_regex,
+        )
+
 
-class TestIndexErrors(object):
+class TestIndexErrors:
     '''Tests to exercise indexerrors not covered by other tests.'''
 
     def test_arraytypes_fasttake(self):
@@ -112,6 +113,15 @@ class TestIndexErrors(object):
         assert_raises(IndexError, lambda: a[(1, [0, 1])])
         assert_raises(IndexError, lambda: assign(a, (1, [0, 1]), 1))
 
+    def test_mapping_error_message(self):
+        a = np.zeros((3, 5))
+        index = (1, 2, 3, 4, 5)
+        assert_raises_regex(
+                IndexError,
+                "too many indices for array: "
+                "array is 2-dimensional, but 5 were indexed",
+                lambda: a[index])
+
     def test_methods(self):
         "cases from methods.c"
 
index 70a5a246f39b4748a0924680b60e5001029422b9..4bb5cb11ac3c856d86ae37f47075fb76b6e53aa4 100644 (file)
@@ -1,21 +1,18 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import warnings
 import functools
 import operator
-import pytest
 
 import numpy as np
 from numpy.core._multiarray_tests import array_indexing
 from itertools import product
 from numpy.testing import (
     assert_, assert_equal, assert_raises, assert_array_equal, assert_warns,
-    HAS_REFCOUNT, suppress_warnings,
+    HAS_REFCOUNT,
     )
 
 
-class TestIndexing(object):
+class TestIndexing:
     def test_index_no_floats(self):
         a = np.array([[[5]]])
 
@@ -397,14 +394,14 @@ class TestIndexing(object):
     def test_scalar_return_type(self):
         # Full scalar indices should return scalars and object
         # arrays should not call PyArray_Return on their items
-        class Zero(object):
+        class Zero:
             # The most basic valid indexing
             def __index__(self):
                 return 0
 
         z = Zero()
 
-        class ArrayLike(object):
+        class ArrayLike:
             # Simple array, should behave like the array
             def __array__(self):
                 return np.array(0)
@@ -484,7 +481,7 @@ class TestIndexing(object):
         # on item getting, this should not be converted to an nd-index (tuple)
         # If this object happens to be a valid index otherwise, it should work
         # This object here is very dubious and probably bad though:
-        class SequenceLike(object):
+        class SequenceLike:
             def __index__(self):
                 return 0
 
@@ -527,7 +524,7 @@ class TestIndexing(object):
         arr[slices] = 10
         assert_array_equal(arr, 10.)
 
-class TestFieldIndexing(object):
+class TestFieldIndexing:
     def test_scalar_return_type(self):
         # Field access on an array should return an array, even if it
         # is 0-d.
@@ -536,7 +533,7 @@ class TestFieldIndexing(object):
         assert_(isinstance(a[['a']], np.ndarray))
 
 
-class TestBroadcastedAssignments(object):
+class TestBroadcastedAssignments:
     def assign(self, a, ind, val):
         a[ind] = val
         return a
@@ -587,7 +584,7 @@ class TestBroadcastedAssignments(object):
         assert_((a[::-1] == v).all())
 
 
-class TestSubclasses(object):
+class TestSubclasses:
     def test_basic(self):
         # Test that indexing in various ways produces SubClass instances,
         # and that the base is set up correctly: the original subclass
@@ -650,56 +647,8 @@ class TestSubclasses(object):
         assert_array_equal(new_s.finalize_status, new_s)
         assert_array_equal(new_s.old, s)
 
-    @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
-    def test_slice_decref_getsetslice(self):
-        # See gh-10066, a temporary slice object should be discarted.
-        # This test is only really interesting on Python 2 since
-        # it goes through `__set/getslice__` here and can probably be
-        # removed. Use 0:7 to make sure it is never None:7.
-        class KeepIndexObject(np.ndarray):
-            def __getitem__(self, indx):
-                self.indx = indx
-                if indx == slice(0, 7):
-                    raise ValueError
-
-            def __setitem__(self, indx, val):
-                self.indx = indx
-                if indx == slice(0, 4):
-                    raise ValueError
 
-        k = np.array([1]).view(KeepIndexObject)
-        k[0:5]
-        assert_equal(k.indx, slice(0, 5))
-        assert_equal(sys.getrefcount(k.indx), 2)
-        try:
-            k[0:7]
-            raise AssertionError
-        except ValueError:
-            # The exception holds a reference to the slice so clear on Py2
-            if hasattr(sys, 'exc_clear'):
-                with suppress_warnings() as sup:
-                    sup.filter(DeprecationWarning)
-                    sys.exc_clear()
-        assert_equal(k.indx, slice(0, 7))
-        assert_equal(sys.getrefcount(k.indx), 2)
-
-        k[0:3] = 6
-        assert_equal(k.indx, slice(0, 3))
-        assert_equal(sys.getrefcount(k.indx), 2)
-        try:
-            k[0:4] = 2
-            raise AssertionError
-        except ValueError:
-            # The exception holds a reference to the slice so clear on Py2
-            if hasattr(sys, 'exc_clear'):
-                with suppress_warnings() as sup:
-                    sup.filter(DeprecationWarning)
-                    sys.exc_clear()
-        assert_equal(k.indx, slice(0, 4))
-        assert_equal(sys.getrefcount(k.indx), 2)
-
-
-class TestFancyIndexingCast(object):
+class TestFancyIndexingCast:
     def test_boolean_index_cast_assign(self):
         # Setup the boolean index and float arrays.
         shape = (8, 63)
@@ -721,7 +670,7 @@ class TestFancyIndexingCast(object):
                      zero_array.__setitem__, bool_index, np.array([1j]))
         assert_equal(zero_array[0, 1], 0)
 
-class TestFancyIndexingEquivalence(object):
+class TestFancyIndexingEquivalence:
     def test_object_assign(self):
         # Check that the field and object special case using copyto is active.
         # The right hand side cannot be converted to an array here.
@@ -769,7 +718,7 @@ class TestFancyIndexingEquivalence(object):
         assert_array_equal(a, b[0])
 
 
-class TestMultiIndexingAutomated(object):
+class TestMultiIndexingAutomated:
     """
     These tests use code to mimic the C-Code indexing for selection.
 
@@ -1191,7 +1140,7 @@ class TestMultiIndexingAutomated(object):
         for index in self.complex_indices:
             self._check_single_index(a, index)
 
-class TestFloatNonIntegerArgument(object):
+class TestFloatNonIntegerArgument:
     """
     These test that ``TypeError`` is raised when you try to use
     non-integers as arguments to for indexing and slicing e.g. ``a[0.0:5]``
@@ -1246,7 +1195,7 @@ class TestFloatNonIntegerArgument(object):
         assert_raises(TypeError, np.min, d, (.2, 1.2))
 
 
-class TestBooleanIndexing(object):
+class TestBooleanIndexing:
     # Using a boolean as integer argument/indexing is an error.
     def test_bool_as_int_argument_errors(self):
         a = np.array([[[1]]])
@@ -1267,7 +1216,7 @@ class TestBooleanIndexing(object):
         assert_raises(IndexError, lambda: a[False, [0, 1], ...])
 
 
-class TestArrayToIndexDeprecation(object):
+class TestArrayToIndexDeprecation:
     """Creating an an index from array not 0-D is an error.
 
     """
@@ -1280,7 +1229,7 @@ class TestArrayToIndexDeprecation(object):
         assert_raises(TypeError, np.take, a, [0], a)
 
 
-class TestNonIntegerArrayLike(object):
+class TestNonIntegerArrayLike:
     """Tests that array_likes only valid if can safely cast to integer.
 
     For instance, lists give IndexError when they cannot be safely cast to
@@ -1297,7 +1246,7 @@ class TestNonIntegerArrayLike(object):
         a.__getitem__([])
 
 
-class TestMultipleEllipsisError(object):
+class TestMultipleEllipsisError:
     """An index can only have a single ellipsis.
 
     """
@@ -1308,7 +1257,7 @@ class TestMultipleEllipsisError(object):
         assert_raises(IndexError, a.__getitem__, ((Ellipsis,) * 3,))
 
 
-class TestCApiAccess(object):
+class TestCApiAccess:
     def test_getitem(self):
         subscript = functools.partial(array_indexing, 0)
 
diff --git a/numpy/core/tests/test_issue14735.py b/numpy/core/tests/test_issue14735.py
deleted file mode 100644 (file)
index 6105c8e..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-import pytest
-import warnings
-import numpy as np
-
-
-class Wrapper:
-    def __init__(self, array):
-        self.array = array
-
-    def __len__(self):
-        return len(self.array)
-
-    def __getitem__(self, item):
-        return type(self)(self.array[item])
-
-    def __getattr__(self, name):
-        if name.startswith("__array_"):
-            warnings.warn("object got converted", UserWarning, stacklevel=1)
-
-        return getattr(self.array, name)
-
-    def __repr__(self):
-        return "<Wrapper({self.array})>".format(self=self)
-
-@pytest.mark.filterwarnings("error")
-def test_getattr_warning():
-    array = Wrapper(np.arange(10))
-    with pytest.raises(UserWarning, match="object got converted"):
-        np.asarray(array)
index 9bd24686629b1c5807ace6cd982efd36baa4ef63..3c35245a3f43cb2fa9ae6fc6d85af4f140988ca5 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 
 import numpy as np
@@ -8,7 +6,7 @@ from numpy.testing import (
     )
 
 
-class TestTake(object):
+class TestTake:
     def test_simple(self):
         a = [[1, 2], [3, 4]]
         a_str = [[b'1', b'2'], [b'3', b'4']]
@@ -22,8 +20,9 @@ class TestTake(object):
                         'clip': {-1: 0, 4: 1}}
         # Currently all types but object, use the same function generation.
         # So it should not be necessary to test all. However test also a non
-        # refcounted struct on top of object.
-        types = int, object, np.dtype([('', 'i', 2)])
+        # refcounted struct on top of object, which has a size that hits the
+        # default (non-specialized) path.
+        types = int, object, np.dtype([('', 'i2', 3)])
         for t in types:
             # ta works, even if the array may be odd if buffer interface is used
             ta = np.array(a if np.issubdtype(t, np.number) else a_str, dtype=t)
index 0ba994860f8c127a0e03f0b18644953676b426b5..acef995f3f05a0c32733547a3be617b29ce2cfcc 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import warnings
 import pytest
 
@@ -135,7 +133,7 @@ def test_fromstring_missing():
                      np.array([1]))
 
 
-class TestFileBased(object):
+class TestFileBased:
 
     ldbl = 1 + LD_INFO.eps
     tgt = np.array([ldbl]*5)
index ab8800c09d30bd56e025719474d1d3558d834ea0..673f309f18c32866bd17ed4d92cc6c72b6301b81 100644 (file)
@@ -3,20 +3,18 @@ Test machar. Given recent changes to hardcode type data, we might want to get
 rid of both MachAr and this test at some point.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from numpy.core.machar import MachAr
 import numpy.core.numerictypes as ntypes
 from numpy import errstate, array
 
 
-class TestMachAr(object):
+class TestMachAr:
     def _run_machar_highprec(self):
         # Instantiate MachAr instance with high enough precision to cause
         # underflow
         try:
             hiprec = ntypes.float96
-            MachAr(lambda v:array([v], hiprec))
+            MachAr(lambda v: array(v, hiprec))
         except AttributeError:
             # Fixme, this needs to raise a 'skip' exception.
             "Skipping test: no ntypes.float96 available on this platform."
index 3c8e0e7220d2832d99b0832a88540abfb82729d6..675613de4b0303dbaca3a91c51c21aa8fdb2bb3c 100644 (file)
@@ -1,6 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
-import sys
 import itertools
 import pytest
 
@@ -8,14 +5,10 @@ import numpy as np
 from numpy.core._multiarray_tests import solve_diophantine, internal_overlap
 from numpy.core import _umath_tests
 from numpy.lib.stride_tricks import as_strided
-from numpy.compat import long
 from numpy.testing import (
     assert_, assert_raises, assert_equal, assert_array_equal
     )
 
-if sys.version_info[0] >= 3:
-    xrange = range
-
 
 ndims = 2
 size = 10
@@ -47,9 +40,7 @@ def _indices_for_axis():
     res = []
     for nelems in (0, 2, 3):
         ind = _indices_for_nelems(nelems)
-
-        # no itertools.product available in Py2.4
-        res.extend([(a, b) for a in ind for b in ind])  # all assignments of size "nelems"
+        res.extend(itertools.product(ind, ind))  # all assignments of size "nelems"
 
     return res
 
@@ -58,18 +49,7 @@ def _indices(ndims):
     """Returns ((axis0_src, axis0_dst), (axis1_src, axis1_dst), ... ) index pairs."""
 
     ind = _indices_for_axis()
-
-    # no itertools.product available in Py2.4
-
-    res = [[]]
-    for i in range(ndims):
-        newres = []
-        for elem in ind:
-            for others in res:
-                newres.append([elem] + others)
-        res = newres
-
-    return res
+    return itertools.product(ind, repeat=ndims)
 
 
 def _check_assignment(srcidx, dstidx):
@@ -140,11 +120,7 @@ def test_diophantine_fuzz():
                 # Check no solution exists (provided the problem is
                 # small enough so that brute force checking doesn't
                 # take too long)
-                try:
-                    ranges = tuple(xrange(0, a*ub+1, a) for a, ub in zip(A, U))
-                except OverflowError:
-                    # xrange on 32-bit Python 2 may overflow
-                    continue
+                ranges = tuple(range(0, a*ub+1, a) for a, ub in zip(A, U))
 
                 size = 1
                 for r in ranges:
@@ -410,7 +386,6 @@ def test_shares_memory_api():
     assert_equal(np.shares_memory(a, b), True)
     assert_equal(np.shares_memory(a, b, max_work=None), True)
     assert_raises(np.TooHardError, np.shares_memory, a, b, max_work=1)
-    assert_raises(np.TooHardError, np.shares_memory, a, b, max_work=long(1))
 
 
 def test_may_share_memory_bad_max_work():
@@ -477,7 +452,7 @@ def check_internal_overlap(a, manual_expected=None):
 
     # Brute-force check
     m = set()
-    ranges = tuple(xrange(n) for n in a.shape)
+    ranges = tuple(range(n) for n in a.shape)
     for v in itertools.product(*ranges):
         offset = sum(s*w for s, w in zip(a.strides, v))
         if offset in m:
@@ -564,7 +539,7 @@ def test_internal_overlap_fuzz():
 def test_non_ndarray_inputs():
     # Regression check for gh-5604
 
-    class MyArray(object):
+    class MyArray:
         def __init__(self, data):
             self.data = data
 
@@ -572,7 +547,7 @@ def test_non_ndarray_inputs():
         def __array_interface__(self):
             return self.data.__array_interface__
 
-    class MyArray2(object):
+    class MyArray2:
         def __init__(self, data):
             self.data = data
 
@@ -619,7 +594,7 @@ def assert_copy_equivalent(operation, args, out, **kwargs):
         assert_equal(got, expected)
 
 
-class TestUFunc(object):
+class TestUFunc:
     """
     Test ufunc call memory overlap handling
     """
@@ -748,6 +723,7 @@ class TestUFunc(object):
         a = np.arange(10000, dtype=np.int16)
         check(np.add, a, a[::-1], a)
 
+    @pytest.mark.slow
     def test_unary_gufunc_fuzz(self):
         shapes = [7, 13, 8, 21, 29, 32]
         gufunc = _umath_tests.euclidean_pdist
index d2ae564b24dae14c5e9e4b692cf6488479e06b00..feef80ce81e0ad76f7d6ed9bb5c2fbe3fe20e58d 100644 (file)
@@ -1,22 +1,20 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import os
 import shutil
 import mmap
 import pytest
+from pathlib import Path
 from tempfile import NamedTemporaryFile, TemporaryFile, mktemp, mkdtemp
 
 from numpy import (
     memmap, sum, average, product, ndarray, isscalar, add, subtract, multiply)
-from numpy.compat import Path
 
 from numpy import arange, allclose, asarray
 from numpy.testing import (
     assert_, assert_equal, assert_array_equal, suppress_warnings
     )
 
-class TestMemmap(object):
+class TestMemmap:
     def setup(self):
         self.tmpfp = NamedTemporaryFile(prefix='mmap')
         self.tempdir = mkdtemp()
@@ -76,7 +74,6 @@ class TestMemmap(object):
         del b
         del fp
 
-    @pytest.mark.skipif(Path is None, reason="No pathlib.Path")
     def test_path(self):
         tmpname = mktemp('', 'mmap', dir=self.tempdir)
         fp = memmap(Path(tmpname), dtype=self.dtype, mode='w+',
index 3df76bdb32979d21004527301b87e427dfb7b179..763b8fc5ab535cc4fcb10dda939c32b6370aad9a 100644 (file)
@@ -1,11 +1,4 @@
-from __future__ import division, absolute_import, print_function
-
-try:
-    # Accessing collections abstract classes from collections
-    # has been deprecated since Python 3.3
-    import collections.abc as collections_abc
-except ImportError:
-    import collections as collections_abc
+import collections.abc
 import tempfile
 import sys
 import shutil
@@ -23,22 +16,12 @@ from contextlib import contextmanager
 
 from numpy.compat import pickle
 
-try:
-    import pathlib
-except ImportError:
-    try:
-        import pathlib2 as pathlib
-    except ImportError:
-        pathlib = None
-
-if sys.version_info[0] >= 3:
-    import builtins
-else:
-    import __builtin__ as builtins
+import pathlib
+import builtins
 from decimal import Decimal
 
 import numpy as np
-from numpy.compat import strchar, unicode
+from numpy.compat import strchar
 import numpy.core._multiarray_tests as _multiarray_tests
 from numpy.testing import (
     assert_, assert_raises, assert_warns, assert_equal, assert_almost_equal,
@@ -53,15 +36,6 @@ from numpy.core.tests._locales import CommaDecimalPointLocale
 from datetime import timedelta, datetime
 
 
-if sys.version_info[:2] > (3, 2):
-    # In Python 3.3 the representation of empty shape, strides and sub-offsets
-    # is an empty tuple instead of None.
-    # https://docs.python.org/dev/whatsnew/3.3.html#api-changes
-    EMPTY = ()
-else:
-    EMPTY = None
-
-
 def _aligned_zeros(shape, dtype=float, order="C", align=None):
     """
     Allocate a new ndarray with aligned memory.
@@ -98,7 +72,7 @@ def _aligned_zeros(shape, dtype=float, order="C", align=None):
     return data
 
 
-class TestFlags(object):
+class TestFlags:
     def setup(self):
         self.a = np.arange(10)
 
@@ -172,7 +146,6 @@ class TestFlags(object):
         vals.setflags(write=True)
         assert_(vals.flags.writeable)
 
-    @pytest.mark.skipif(sys.version_info[0] < 3, reason="Python 2 always copies")
     @pytest.mark.skipif(IS_PYPY, reason="PyPy always copies")
     def test_writeable_pickle(self):
         import pickle
@@ -266,7 +239,7 @@ class TestFlags(object):
         assert_(a.flags.aligned)
 
 
-class TestHash(object):
+class TestHash:
     # see #3793
     def test_int(self):
         for st, ut, s in [(np.int8, np.uint8, 8),
@@ -288,7 +261,7 @@ class TestHash(object):
                              err_msg="%r: 2**%d - 1" % (ut, i))
 
 
-class TestAttributes(object):
+class TestAttributes:
     def setup(self):
         self.one = np.arange(10)
         self.two = np.arange(20).reshape(4, 5)
@@ -329,17 +302,8 @@ class TestAttributes(object):
 
         numpy_int = np.int_(0)
 
-        if sys.version_info[0] >= 3:
-            # On Py3k int_ should not inherit from int, because it's not
-            # fixed-width anymore
-            assert_equal(isinstance(numpy_int, int), False)
-        else:
-            # Otherwise, it should inherit from int...
-            assert_equal(isinstance(numpy_int, int), True)
-
-            # ... and fast-path checks on C-API level should also work
-            from numpy.core._multiarray_tests import test_int_subclass
-            assert_equal(test_int_subclass(numpy_int), True)
+        # int_ doesn't inherit from Python int, because it's not fixed-width
+        assert_(not isinstance(numpy_int, int))
 
     def test_stridesattr(self):
         x = self.one
@@ -392,6 +356,11 @@ class TestAttributes(object):
         a.strides = 1
         a[::2].strides = 2
 
+        # test 0d
+        arr_0d = np.array(0)
+        arr_0d.strides = ()
+        assert_raises(TypeError, set_strides, arr_0d, None)
+
     def test_fill(self):
         for t in "?bhilqpBHILQPfdgFDGO":
             x = np.empty((3, 2, 1), t)
@@ -421,7 +390,7 @@ class TestAttributes(object):
         assert_array_equal(x['b'], [-2, -2])
 
 
-class TestArrayConstruction(object):
+class TestArrayConstruction:
     def test_array(self):
         d = np.ones(6)
         r = np.array([d, d])
@@ -448,7 +417,7 @@ class TestArrayConstruction(object):
         assert_equal(r, np.ones((2, 6, 6)))
 
         d = np.ones((6, ))
-        r = np.array([[d, d + 1], d + 2])
+        r = np.array([[d, d + 1], d + 2], dtype=object)
         assert_equal(len(r), 2)
         assert_equal(r[0], [d, d + 1])
         assert_equal(r[1], d + 2)
@@ -499,7 +468,7 @@ class TestArrayConstruction(object):
         assert_(np.asfortranarray(d).flags.f_contiguous)
 
 
-class TestAssignment(object):
+class TestAssignment:
     def test_assignment_broadcasting(self):
         a = np.arange(6).reshape(2, 3)
 
@@ -565,7 +534,7 @@ class TestAssignment(object):
         u = np.array([u'done'])
         b = np.array([b'done'])
 
-        class bad_sequence(object):
+        class bad_sequence:
             def __getitem__(self): pass
             def __len__(self): raise RuntimeError
 
@@ -616,7 +585,7 @@ class TestAssignment(object):
         assert_equal(a[0], b"1.1234567890123457")
 
 
-class TestDtypedescr(object):
+class TestDtypedescr:
     def test_construction(self):
         d1 = np.dtype('i4')
         assert_equal(d1, np.dtype(np.int32))
@@ -638,7 +607,7 @@ class TestDtypedescr(object):
             "array([0, 0, 0, 0], dtype=(numpy.int32, [('a', '<i2'), ('b', '<i2')]))")
 
 
-class TestZeroRank(object):
+class TestZeroRank:
     def setup(self):
         self.d = np.array(0), np.array('x', object)
 
@@ -715,6 +684,12 @@ class TestZeroRank(object):
         y[()] = 6
         assert_equal(x[()], 6)
 
+        # strides and shape must be the same length
+        with pytest.raises(ValueError):
+            np.ndarray((2,), strides=())
+        with pytest.raises(ValueError):
+            np.ndarray((), strides=(2,))
+
     def test_output(self):
         x = np.array(2)
         assert_raises(ValueError, np.add, x, [1], x)
@@ -736,7 +711,7 @@ class TestZeroRank(object):
         assert_equal(xi.flags.f_contiguous, True)
 
 
-class TestScalarIndexing(object):
+class TestScalarIndexing:
     def setup(self):
         self.d = np.array([0, 1])[0]
 
@@ -832,12 +807,12 @@ class TestScalarIndexing(object):
         assert_equal(a, [0, 1, 0, 1, 2])
 
 
-class TestCreation(object):
+class TestCreation:
     """
     Test the np.array constructor
     """
     def test_from_attribute(self):
-        class x(object):
+        class x:
             def __array__(self, dtype=None):
                 pass
 
@@ -870,6 +845,13 @@ class TestCreation(object):
         assert_raises(ValueError, np.zeros, shape, dtype=np.int8)
         assert_raises(ValueError, np.ones, shape, dtype=np.int8)
 
+    @pytest.mark.skipif(np.dtype(np.intp).itemsize != 8,
+                        reason="malloc may not fail on 32 bit systems")
+    def test_malloc_fails(self):
+        # This test is guaranteed to fail due to a too large allocation
+        with assert_raises(np.core._exceptions._ArrayMemoryError):
+            np.empty(np.iinfo(np.intp).max, dtype=np.uint8)
+
     def test_zeros(self):
         types = np.typecodes['AllInteger'] + np.typecodes['AllFloat']
         for dt in types:
@@ -963,13 +945,6 @@ class TestCreation(object):
         assert_equal(np.array([[1j, 1j],[1, 1]]).dtype, complex)
         assert_equal(np.array([[1, 1, 1],[1, 1j, 1.], [1, 1, 1]]).dtype, complex)
 
-    @pytest.mark.skipif(sys.version_info[0] >= 3, reason="Not Python 2")
-    def test_sequence_long(self):
-        assert_equal(np.array([long(4), long(4)]).dtype, long)
-        assert_equal(np.array([long(4), 2**80]).dtype, object)
-        assert_equal(np.array([long(4), 2**80, long(4)]).dtype, object)
-        assert_equal(np.array([2**80, long(4)]).dtype, object)
-
     def test_non_sequence_sequence(self):
         """Should not segfault.
 
@@ -979,14 +954,14 @@ class TestCreation(object):
         of an error in the Fail case.
 
         """
-        class Fail(object):
+        class Fail:
             def __len__(self):
                 return 1
 
             def __getitem__(self, index):
                 raise ValueError()
 
-        class Map(object):
+        class Map:
             def __len__(self):
                 return 1
 
@@ -1020,11 +995,26 @@ class TestCreation(object):
             def __len__(self):
                 return 42
 
-        assert_raises(ValueError, np.array, C()) # segfault?
+        a = np.array(C()) # segfault?
+        assert_equal(len(a), 0)
+
+    def test_false_len_iterable(self):
+        # Special case where a bad __getitem__ makes us fall back on __iter__:
+        class C:
+            def __getitem__(self, x):
+                raise Exception
+            def __iter__(self):
+                return iter(())
+            def __len__(self):
+                return 2
+
+        a = np.empty(2)
+        with assert_raises(ValueError):
+            a[:] = C()  # Segfault!
 
     def test_failed_len_sequence(self):
         # gh-7393
-        class A(object):
+        class A:
             def __init__(self, data):
                 self._data = data
             def __getitem__(self, item):
@@ -1051,36 +1041,62 @@ class TestCreation(object):
             assert_raises(ValueError, np.ndarray, buffer=buf, strides=(0,),
                           shape=(max_bytes//itemsize + 1,), dtype=dtype)
 
-    def test_jagged_ndim_object(self):
-        # Lists of mismatching depths are treated as object arrays
-        a = np.array([[1], 2, 3])
-        assert_equal(a.shape, (3,))
-        assert_equal(a.dtype, object)
+    def _ragged_creation(self, seq):
+        # without dtype=object, the ragged object should raise
+        with assert_warns(np.VisibleDeprecationWarning):
+            a = np.array(seq)
+        b = np.array(seq, dtype=object)
+        assert_equal(a, b)
+        return b
 
-        a = np.array([1, [2], 3])
+    def test_ragged_ndim_object(self):
+        # Lists of mismatching depths are treated as object arrays
+        a = self._ragged_creation([[1], 2, 3])
         assert_equal(a.shape, (3,))
         assert_equal(a.dtype, object)
 
-        a = np.array([1, 2, [3]])
+        a = self._ragged_creation([1, [2], 3])
         assert_equal(a.shape, (3,))
         assert_equal(a.dtype, object)
 
-    def test_jagged_shape_object(self):
-        # The jagged dimension of a list is turned into an object array
-        a = np.array([[1, 1], [2], [3]])
+        a = self._ragged_creation([1, 2, [3]])
         assert_equal(a.shape, (3,))
         assert_equal(a.dtype, object)
 
-        a = np.array([[1], [2, 2], [3]])
+    def test_ragged_shape_object(self):
+        # The ragged dimension of a list is turned into an object array
+        a = self._ragged_creation([[1, 1], [2], [3]])
         assert_equal(a.shape, (3,))
         assert_equal(a.dtype, object)
 
-        a = np.array([[1], [2], [3, 3]])
+        a = self._ragged_creation([[1], [2, 2], [3]])
         assert_equal(a.shape, (3,))
         assert_equal(a.dtype, object)
 
-
-class TestStructured(object):
+        a = self._ragged_creation([[1], [2], [3, 3]])
+        assert a.shape == (3,)
+        assert a.dtype == object
+
+    def test_array_of_ragged_array(self):
+        outer = np.array([None, None])
+        outer[0] = outer[1] = np.array([1, 2, 3])
+        assert np.array(outer).shape == (2,)
+        assert np.array([outer]).shape == (1, 2)
+
+        outer_ragged = np.array([None, None])
+        outer_ragged[0] = np.array([1, 2, 3])
+        outer_ragged[1] = np.array([1, 2, 3, 4])
+        # should both of these emit deprecation warnings?
+        assert np.array(outer_ragged).shape == (2,)
+        assert np.array([outer_ragged]).shape == (1, 2,)
+
+    def test_deep_nonragged_object(self):
+        # None of these should raise, even though they are missing dtype=object
+        a = np.array([[[Decimal(1)]]])
+        a = np.array([1, Decimal(1)])
+        a = np.array([[1], [Decimal(1)]])
+
+class TestStructured:
     def test_subarray_field_access(self):
         a = np.zeros((3, 5), dtype=[('a', ('i4', (2, 2)))])
         a['a'] = np.arange(60).reshape(3, 5, 2, 2)
@@ -1368,7 +1384,7 @@ class TestStructured(object):
         a[['b','c']]  # no exception
 
 
-class TestBool(object):
+class TestBool:
     def test_test_interning(self):
         a0 = np.bool_(0)
         b0 = np.bool_(False)
@@ -1458,7 +1474,7 @@ class TestBool(object):
         self._test_cast_from_flexible(np.bytes_)
 
 
-class TestZeroSizeFlexible(object):
+class TestZeroSizeFlexible:
     @staticmethod
     def _zeros(shape, dtype=str):
         dtype = np.dtype(dtype)
@@ -1474,12 +1490,12 @@ class TestZeroSizeFlexible(object):
         assert_equal(zs.itemsize, 0)
         zs = self._zeros(10, np.void)
         assert_equal(zs.itemsize, 0)
-        zs = self._zeros(10, unicode)
+        zs = self._zeros(10, str)
         assert_equal(zs.itemsize, 0)
 
     def _test_sort_partition(self, name, kinds, **kwargs):
         # Previously, these would all hang
-        for dt in [bytes, np.void, unicode]:
+        for dt in [bytes, np.void, str]:
             zs = self._zeros(10, dt)
             sort_method = getattr(zs, name)
             sort_func = getattr(np, name)
@@ -1501,13 +1517,13 @@ class TestZeroSizeFlexible(object):
 
     def test_resize(self):
         # previously an error
-        for dt in [bytes, np.void, unicode]:
+        for dt in [bytes, np.void, str]:
             zs = self._zeros(10, dt)
             zs.resize(25)
             zs.resize((10, 10))
 
     def test_view(self):
-        for dt in [bytes, np.void, unicode]:
+        for dt in [bytes, np.void, str]:
             zs = self._zeros(10, dt)
 
             # viewing as itself should be allowed
@@ -1522,7 +1538,7 @@ class TestZeroSizeFlexible(object):
 
     def test_pickle(self):
         for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
-            for dt in [bytes, np.void, unicode]:
+            for dt in [bytes, np.void, str]:
                 zs = self._zeros(10, dt)
                 p = pickle.dumps(zs, protocol=proto)
                 zs2 = pickle.loads(p)
@@ -1545,7 +1561,7 @@ class TestZeroSizeFlexible(object):
         assert array_from_buffer[0] == -1, array_from_buffer[0]
 
 
-class TestMethods(object):
+class TestMethods:
 
     sort_kinds = ['quicksort', 'heapsort', 'stable']
 
@@ -1707,53 +1723,60 @@ class TestMethods(object):
         b = np.sort(a)
         assert_equal(b, a[::-1], msg)
 
-        # all c scalar sorts use the same code with different types
-        # so it suffices to run a quick check with one type. The number
-        # of sorted items must be greater than ~50 to check the actual
-        # algorithm because quick and merge sort fall over to insertion
-        # sort for small arrays.
-        # Test unsigned dtypes and nonnegative numbers
-        for dtype in [np.uint8, np.uint16, np.uint32, np.uint64, np.float16, np.float32, np.float64, np.longdouble]:
-            a = np.arange(101, dtype=dtype)
-            b = a[::-1].copy()
-            for kind in self.sort_kinds:
-                msg = "scalar sort, kind=%s, dtype=%s" % (kind, dtype)
-                c = a.copy()
-                c.sort(kind=kind)
-                assert_equal(c, a, msg)
-                c = b.copy()
-                c.sort(kind=kind)
-                assert_equal(c, a, msg)
-
-        # Test signed dtypes and negative numbers as well
-        for dtype in [np.int8, np.int16, np.int32, np.int64, np.float16, np.float32, np.float64, np.longdouble]:
-            a = np.arange(-50, 51, dtype=dtype)
-            b = a[::-1].copy()
-            for kind in self.sort_kinds:
-                msg = "scalar sort, kind=%s, dtype=%s" % (kind, dtype)
-                c = a.copy()
-                c.sort(kind=kind)
-                assert_equal(c, a, msg)
-                c = b.copy()
-                c.sort(kind=kind)
-                assert_equal(c, a, msg)
+    # all c scalar sorts use the same code with different types
+    # so it suffices to run a quick check with one type. The number
+    # of sorted items must be greater than ~50 to check the actual
+    # algorithm because quick and merge sort fall over to insertion
+    # sort for small arrays.
+
+    @pytest.mark.parametrize('dtype', [np.uint8, np.uint16, np.uint32, np.uint64,
+                                       np.float16, np.float32, np.float64,
+                                       np.longdouble])
+    def test_sort_unsigned(self, dtype):
+        a = np.arange(101, dtype=dtype)
+        b = a[::-1].copy()
+        for kind in self.sort_kinds:
+            msg = "scalar sort, kind=%s" % kind
+            c = a.copy()
+            c.sort(kind=kind)
+            assert_equal(c, a, msg)
+            c = b.copy()
+            c.sort(kind=kind)
+            assert_equal(c, a, msg)
 
-        # test complex sorts. These use the same code as the scalars
-        # but the compare function differs.
-        ai = a*1j + 1
-        bi = b*1j + 1
+    @pytest.mark.parametrize('dtype',
+                             [np.int8, np.int16, np.int32, np.int64, np.float16,
+                              np.float32, np.float64, np.longdouble])
+    def test_sort_signed(self, dtype):
+        a = np.arange(-50, 51, dtype=dtype)
+        b = a[::-1].copy()
         for kind in self.sort_kinds:
-            msg = "complex sort, real part == 1, kind=%s" % kind
-            c = ai.copy()
+            msg = "scalar sort, kind=%s" % (kind)
+            c = a.copy()
             c.sort(kind=kind)
-            assert_equal(c, ai, msg)
-            c = bi.copy()
+            assert_equal(c, a, msg)
+            c = b.copy()
             c.sort(kind=kind)
-            assert_equal(c, ai, msg)
-        ai = a + 1j
-        bi = b + 1j
+            assert_equal(c, a, msg)
+
+    @pytest.mark.parametrize('dtype', [np.float32, np.float64, np.longdouble])
+    @pytest.mark.parametrize('part', ['real', 'imag'])
+    def test_sort_complex(self, part, dtype):
+        # test complex sorts. These use the same code as the scalars
+        # but the compare function differs.
+        cdtype = {
+            np.single: np.csingle,
+            np.double: np.cdouble,
+            np.longdouble: np.clongdouble,
+        }[dtype]
+        a = np.arange(-50, 51, dtype=dtype)
+        b = a[::-1].copy()
+        ai = (a * (1+1j)).astype(cdtype)
+        bi = (b * (1+1j)).astype(cdtype)
+        setattr(ai, part, 1)
+        setattr(bi, part, 1)
         for kind in self.sort_kinds:
-            msg = "complex sort, imag part == 1, kind=%s" % kind
+            msg = "complex sort, %s part == 1, kind=%s" % (part, kind)
             c = ai.copy()
             c.sort(kind=kind)
             assert_equal(c, ai, msg)
@@ -1761,6 +1784,7 @@ class TestMethods(object):
             c.sort(kind=kind)
             assert_equal(c, ai, msg)
 
+    def test_sort_complex_byte_swapping(self):
         # test sorting of complex arrays requiring byte-swapping, gh-5441
         for endianness in '<>':
             for dt in np.typecodes['Complex']:
@@ -1770,25 +1794,13 @@ class TestMethods(object):
                 msg = 'byte-swapped complex sort, dtype={0}'.format(dt)
                 assert_equal(c, arr, msg)
 
-        # test string sorts.
-        s = 'aaaaaaaa'
-        a = np.array([s + chr(i) for i in range(101)])
-        b = a[::-1].copy()
-        for kind in self.sort_kinds:
-            msg = "string sort, kind=%s" % kind
-            c = a.copy()
-            c.sort(kind=kind)
-            assert_equal(c, a, msg)
-            c = b.copy()
-            c.sort(kind=kind)
-            assert_equal(c, a, msg)
-
-        # test unicode sorts.
-        s = 'aaaaaaaa'
-        a = np.array([s + chr(i) for i in range(101)], dtype=np.unicode_)
+    @pytest.mark.parametrize('dtype', [np.bytes_, np.unicode_])
+    def test_sort_string(self, dtype):
+        # np.array will perform the encoding to bytes for us in the bytes test
+        a = np.array(['aaaaaaaa' + chr(i) for i in range(101)], dtype=dtype)
         b = a[::-1].copy()
         for kind in self.sort_kinds:
-            msg = "unicode sort, kind=%s" % kind
+            msg = "kind=%s" % kind
             c = a.copy()
             c.sort(kind=kind)
             assert_equal(c, a, msg)
@@ -1796,12 +1808,13 @@ class TestMethods(object):
             c.sort(kind=kind)
             assert_equal(c, a, msg)
 
+    def test_sort_object(self):
         # test object array sorts.
         a = np.empty((101,), dtype=object)
         a[:] = list(range(101))
         b = a[::-1]
         for kind in ['q', 'h', 'm']:
-            msg = "object sort, kind=%s" % kind
+            msg = "kind=%s" % kind
             c = a.copy()
             c.sort(kind=kind)
             assert_equal(c, a, msg)
@@ -1809,24 +1822,13 @@ class TestMethods(object):
             c.sort(kind=kind)
             assert_equal(c, a, msg)
 
+    def test_sort_structured(self):
         # test record array sorts.
         dt = np.dtype([('f', float), ('i', int)])
         a = np.array([(i, i) for i in range(101)], dtype=dt)
         b = a[::-1]
         for kind in ['q', 'h', 'm']:
-            msg = "object sort, kind=%s" % kind
-            c = a.copy()
-            c.sort(kind=kind)
-            assert_equal(c, a, msg)
-            c = b.copy()
-            c.sort(kind=kind)
-            assert_equal(c, a, msg)
-
-        # test datetime64 sorts.
-        a = np.arange(0, 101, dtype='datetime64[D]')
-        b = a[::-1]
-        for kind in ['q', 'h', 'm']:
-            msg = "datetime64 sort, kind=%s" % kind
+            msg = "kind=%s" % kind
             c = a.copy()
             c.sort(kind=kind)
             assert_equal(c, a, msg)
@@ -1834,11 +1836,13 @@ class TestMethods(object):
             c.sort(kind=kind)
             assert_equal(c, a, msg)
 
-        # test timedelta64 sorts.
-        a = np.arange(0, 101, dtype='timedelta64[D]')
+    @pytest.mark.parametrize('dtype', ['datetime64[D]', 'timedelta64[D]'])
+    def test_sort_time(self, dtype):
+        # test datetime64 and timedelta64 sorts.
+        a = np.arange(0, 101, dtype=dtype)
         b = a[::-1]
         for kind in ['q', 'h', 'm']:
-            msg = "timedelta64 sort, kind=%s" % kind
+            msg = "kind=%s" % kind
             c = a.copy()
             c.sort(kind=kind)
             assert_equal(c, a, msg)
@@ -1846,6 +1850,7 @@ class TestMethods(object):
             c.sort(kind=kind)
             assert_equal(c, a, msg)
 
+    def test_sort_axis(self):
         # check axis handling. This should be the same for all type
         # specific sorts, so we only check it for one type and one kind
         a = np.array([[3, 2], [1, 0]])
@@ -1861,6 +1866,7 @@ class TestMethods(object):
         d.sort()
         assert_equal(d, c, "test sort with default axis")
 
+    def test_sort_size_0(self):
         # check axis handling for multidimensional empty arrays
         a = np.array([])
         a.shape = (3, 2, 1, 0)
@@ -1870,16 +1876,19 @@ class TestMethods(object):
         msg = 'test empty array sort with axis=None'
         assert_equal(np.sort(a, axis=None), a.ravel(), msg)
 
+    def test_sort_bad_ordering(self):
         # test generic class with bogus ordering,
         # should not segfault.
-        class Boom(object):
+        class Boom:
             def __lt__(self, other):
                 return True
 
-        a = np.array([Boom()]*100, dtype=object)
+        a = np.array([Boom()] * 100, dtype=object)
         for kind in self.sort_kinds:
-            msg = "bogus comparison object sort, kind=%s" % kind
+            msg = "kind=%s" % kind
+            c = a.copy()
             c.sort(kind=kind)
+            assert_equal(c, a, msg)
 
     def test_void_sort(self):
         # gh-8210 - previously segfaulted
@@ -1900,7 +1909,7 @@ class TestMethods(object):
         for kind in self.sort_kinds:
             assert_raises(TypeError, arr.sort, kind=kind)
         #gh-3879
-        class Raiser(object):
+        class Raiser:
             def raises_anything(*args, **kwargs):
                 raise TypeError("SOMETHING ERRORED")
             __eq__ = __ne__ = __lt__ = __gt__ = __ge__ = __le__ = raises_anything
@@ -2144,6 +2153,8 @@ class TestMethods(object):
         msg = "Test real searchsorted with nans, side='r'"
         b = a.searchsorted(a, side='r')
         assert_equal(b, np.arange(1, 4), msg)
+        # check keyword arguments
+        a.searchsorted(v=1)
         # check double complex
         a = np.zeros(9, dtype=np.complex128)
         a.real += [0, 0, 1, 1, 0, 1, np.nan, np.nan, np.nan]
@@ -2256,10 +2267,11 @@ class TestMethods(object):
         assert_equal([a.searchsorted(a[i], 'left') for i in ind], ind)
         assert_equal([a.searchsorted(a[i], 'right') for i in ind], ind + 1)
 
-    def test_searchsorted_with_sorter(self):
+    def test_searchsorted_with_invalid_sorter(self):
         a = np.array([5, 2, 1, 3, 4])
         s = np.argsort(a)
-        assert_raises(TypeError, np.searchsorted, a, 0, sorter=(1, (2, 3)))
+        assert_raises(TypeError, np.searchsorted, a, 0,
+                      sorter=np.array((1, (2, 3)), dtype=object))
         assert_raises(TypeError, np.searchsorted, a, 0, sorter=[1.1])
         assert_raises(ValueError, np.searchsorted, a, 0, sorter=[1, 2, 3, 4])
         assert_raises(ValueError, np.searchsorted, a, 0, sorter=[1, 2, 3, 4, 5, 6])
@@ -2269,6 +2281,7 @@ class TestMethods(object):
         assert_raises(ValueError, np.searchsorted, a, 0, sorter=[-1, 0, 1, 2, 3])
         assert_raises(ValueError, np.searchsorted, a, 0, sorter=[4, 0, -1, 2, 3])
 
+    def test_searchsorted_with_sorter(self):
         a = np.random.rand(300)
         s = a.argsort()
         b = np.sort(a)
@@ -2767,11 +2780,6 @@ class TestMethods(object):
         assert_equal(x1.flatten('F'), y1f)
         assert_equal(x1.flatten('F'), x1.T.flatten())
 
-    def test_flatten_invalid_order(self):
-        # invalid after gh-14596
-        for order in ['Z', 'c', False, True, 0, 8]:
-            x = np.array([[1, 2, 3], [4, 5, 6]], np.int32)
-            assert_raises(ValueError, x.flatten, {"order": order})
 
     @pytest.mark.parametrize('func', (np.dot, np.matmul))
     def test_arr_mult(self, func):
@@ -2942,7 +2950,7 @@ class TestMethods(object):
 
     def test_dot_matmul_inner_array_casting_fails(self):
 
-        class A(object):
+        class A:
             def __array__(self, *args, **kwargs):
                 raise NotImplementedError
 
@@ -3303,12 +3311,12 @@ class TestMethods(object):
         e = np.array(['1+1j'], 'U')
         assert_raises(TypeError, complex, e)
 
-class TestCequenceMethods(object):
+class TestCequenceMethods:
     def test_array_contains(self):
         assert_(4.0 in np.arange(16.).reshape(4,4))
         assert_(20.0 not in np.arange(16.).reshape(4,4))
 
-class TestBinop(object):
+class TestBinop:
     def test_inplace(self):
         # test refcount 1 inplace conversion
         assert_array_almost_equal(np.array([0.5]) * np.array([1.0, 2.0]),
@@ -3363,6 +3371,7 @@ class TestBinop(object):
             'and':      (np.bitwise_and, True, int),
             'xor':      (np.bitwise_xor, True, int),
             'or':       (np.bitwise_or, True, int),
+            'matmul':   (np.matmul, False, float),
             # 'ge':       (np.less_equal, False),
             # 'gt':       (np.less, False),
             # 'le':       (np.greater_equal, False),
@@ -3370,8 +3379,6 @@ class TestBinop(object):
             # 'eq':       (np.equal, False),
             # 'ne':       (np.not_equal, False),
         }
-        if sys.version_info >= (3, 5):
-            ops['matmul'] = (np.matmul, False, float)
 
         class Coerced(Exception):
             pass
@@ -3533,7 +3540,7 @@ class TestBinop(object):
 
     def test_ufunc_override_normalize_signature(self):
         # gh-5674
-        class SomeClass(object):
+        class SomeClass:
             def __array_ufunc__(self, ufunc, method, *inputs, **kw):
                 return kw
 
@@ -3551,7 +3558,7 @@ class TestBinop(object):
         # Check that index is set appropriately, also if only an output
         # is passed on (latter is another regression tests for github bug 4753)
         # This also checks implicitly that 'out' is always a tuple.
-        class CheckIndex(object):
+        class CheckIndex:
             def __array_ufunc__(self, ufunc, method, *inputs, **kw):
                 for i, a in enumerate(inputs):
                     if a is self:
@@ -3639,7 +3646,7 @@ class TestBinop(object):
 
     def test_pow_array_object_dtype(self):
         # test pow on arrays of object dtype
-        class SomeClass(object):
+        class SomeClass:
             def __init__(self, num=None):
                 self.num = num
 
@@ -3680,7 +3687,7 @@ class TestBinop(object):
             +tst
 
 
-class TestTemporaryElide(object):
+class TestTemporaryElide:
     # elision is only triggered on relatively large arrays
 
     def test_extension_incref_elide(self):
@@ -3782,7 +3789,7 @@ class TestTemporaryElide(object):
         assert_equal(a, 1)
 
 
-class TestCAPI(object):
+class TestCAPI:
     def test_IsPythonScalar(self):
         from numpy.core._multiarray_tests import IsPythonScalar
         assert_(IsPythonScalar(b'foobar'))
@@ -3792,30 +3799,28 @@ class TestCAPI(object):
         assert_(IsPythonScalar("a"))
 
 
-class TestSubscripting(object):
+class TestSubscripting:
     def test_test_zero_rank(self):
         x = np.array([1, 2, 3])
         assert_(isinstance(x[0], np.int_))
-        if sys.version_info[0] < 3:
-            assert_(isinstance(x[0], int))
         assert_(type(x[0, ...]) is np.ndarray)
 
 
-class TestPickling(object):
+class TestPickling:
     @pytest.mark.skipif(pickle.HIGHEST_PROTOCOL >= 5,
                         reason=('this tests the error messages when trying to'
                                 'protocol 5 although it is not available'))
     def test_correct_protocol5_error_message(self):
         array = np.arange(10)
 
-        if sys.version_info[:2] in ((3, 5), (3, 6), (3, 7)):
+        if sys.version_info[:2] in ((3, 6), (3, 7)):
             # For the specific case of python3.6 and 3.7, raise a clear import
             # error about the pickle5 backport when trying to use protocol=5
             # without the pickle5 package
             with pytest.raises(ImportError):
                 array.__reduce_ex__(5)
 
-        elif sys.version_info[:2] < (3, 5):
+        elif sys.version_info[:2] < (3, 6):
             # when calling __reduce_ex__ explicitly with protocol=5 on python
             # raise a ValueError saying that protocol 5 is not available for
             # this python version
@@ -3896,10 +3901,7 @@ class TestPickling(object):
                 assert ref() is None
 
     def _loads(self, obj):
-        if sys.version_info[0] >= 3:
-            return pickle.loads(obj, encoding='latin1')
-        else:
-            return pickle.loads(obj)
+        return pickle.loads(obj, encoding='latin1')
 
     # version 0 pickles, using protocol=2 to pickle
     # version 0 doesn't have a version field
@@ -3958,7 +3960,7 @@ class TestPickling(object):
         assert_equal(original.dtype, new.dtype)
 
 
-class TestFancyIndexing(object):
+class TestFancyIndexing:
     def test_list(self):
         x = np.ones((1, 1))
         x[:, [0]] = 2.0
@@ -4012,7 +4014,7 @@ class TestFancyIndexing(object):
         assert_array_equal(x, np.array([[1, 10, 3, 4], [5, 6, 7, 8]]))
 
 
-class TestStringCompare(object):
+class TestStringCompare:
     def test_string(self):
         g1 = np.array(["This", "is", "example"])
         g2 = np.array(["This", "was", "example"])
@@ -4044,7 +4046,7 @@ class TestStringCompare(object):
         assert_array_equal(g1 > g2,  [g1[i] > g2[i] for i in [0, 1, 2]])
 
 
-class TestArgmax(object):
+class TestArgmax:
 
     nan_arr = [
         ([0, 1, 2, 3, np.nan], 4),
@@ -4179,7 +4181,7 @@ class TestArgmax(object):
         assert_equal(a.argmax(), 1)
 
 
-class TestArgmin(object):
+class TestArgmin:
 
     nan_arr = [
         ([0, 1, 2, 3, np.nan], 4),
@@ -4328,7 +4330,7 @@ class TestArgmin(object):
         assert_equal(a.argmin(), 1)
 
 
-class TestMinMax(object):
+class TestMinMax:
 
     def test_scalar(self):
         assert_raises(np.AxisError, np.amax, 1, 1)
@@ -4354,14 +4356,14 @@ class TestMinMax(object):
             assert_equal(np.amax(a), a[3])
 
 
-class TestNewaxis(object):
+class TestNewaxis:
     def test_basic(self):
         sk = np.array([0, -0.1, 0.1])
         res = 250*sk[:, np.newaxis]
         assert_almost_equal(res.ravel(), 250*sk)
 
 
-class TestClip(object):
+class TestClip:
     def _check_range(self, x, cmin, cmax):
         assert_(np.all(x >= cmin))
         assert_(np.all(x <= cmax))
@@ -4439,7 +4441,7 @@ class TestClip(object):
         assert_array_equal(result, expected)
 
 
-class TestCompress(object):
+class TestCompress:
     def test_axis(self):
         tgt = [[5, 6, 7, 8, 9]]
         arr = np.arange(10).reshape(2, 5)
@@ -4462,14 +4464,13 @@ class TestCompress(object):
         assert_equal(out, 1)
 
 
-class TestPutmask(object):
+class TestPutmask:
     def tst_basic(self, x, T, mask, val):
         np.putmask(x, mask, val)
-        assert_equal(x[mask], T(val))
-        assert_equal(x.dtype, T)
+        assert_equal(x[mask], np.array(val, T))
 
     def test_ip_types(self):
-        unchecked_types = [bytes, unicode, np.void, object]
+        unchecked_types = [bytes, str, np.void]
 
         x = np.random.random(1000)*100
         mask = x < 40
@@ -4480,6 +4481,10 @@ class TestPutmask(object):
                     if T not in unchecked_types:
                         self.tst_basic(x.copy().astype(T), T, mask, val)
 
+            # Also test string of a length which uses an untypical length
+            dt = np.dtype("S3")
+            self.tst_basic(x.astype(dt), dt.type, mask, dt.type(val)[:3])
+
     def test_mask_size(self):
         assert_raises(ValueError, np.putmask, np.array([1, 2, 3]), [True], 5)
 
@@ -4513,13 +4518,13 @@ class TestPutmask(object):
         assert_equal(x, np.array([True, True, True, True]))
 
 
-class TestTake(object):
+class TestTake:
     def tst_basic(self, x):
         ind = list(range(x.shape[0]))
         assert_array_equal(x.take(ind, axis=0), x)
 
     def test_ip_types(self):
-        unchecked_types = [bytes, unicode, np.void, object]
+        unchecked_types = [bytes, str, np.void]
 
         x = np.random.random(24)*100
         x.shape = 2, 3, 4
@@ -4528,6 +4533,9 @@ class TestTake(object):
                 if T not in unchecked_types:
                     self.tst_basic(x.copy().astype(T))
 
+            # Also test string of a length which uses an untypical length
+            self.tst_basic(x.astype("S3"))
+
     def test_raise(self):
         x = np.random.random(24)*100
         x.shape = 2, 3, 4
@@ -4566,7 +4574,7 @@ class TestTake(object):
         y = np.take(x, [1, 2, 3], out=x[2:5], mode='wrap')
         assert_equal(y, np.array([1, 2, 3]))
 
-class TestLexsort(object):
+class TestLexsort:
     @pytest.mark.parametrize('dtype',[
         np.uint8, np.uint16, np.uint32, np.uint64,
         np.int8, np.int16, np.int32, np.int64,
@@ -4621,7 +4629,7 @@ class TestLexsort(object):
         x = np.linspace(0., 1., 42*3).reshape(42, 3)
         assert_raises(np.AxisError, np.lexsort, x, axis=2)
 
-class TestIO(object):
+class TestIO:
     """Test tofile, fromfile, tobytes, and fromstring"""
 
     def setup(self):
@@ -4662,25 +4670,23 @@ class TestIO(object):
         assert_array_equal(d, e)
 
     def test_empty_files_binary(self):
-        f = open(self.filename, 'w')
-        f.close()
+        with open(self.filename, 'w') as f:
+            pass
         y = np.fromfile(self.filename)
         assert_(y.size == 0, "Array not empty")
 
     def test_empty_files_text(self):
-        f = open(self.filename, 'w')
-        f.close()
+        with open(self.filename, 'wb') as f:
+            pass
         y = np.fromfile(self.filename, sep=" ")
         assert_(y.size == 0, "Array not empty")
 
     def test_roundtrip_file(self):
-        f = open(self.filename, 'wb')
-        self.x.tofile(f)
-        f.close()
+        with open(self.filename, 'wb') as f:
+            self.x.tofile(f)
         # NB. doesn't work with flush+seek, due to use of C stdio
-        f = open(self.filename, 'rb')
-        y = np.fromfile(f, dtype=self.dtype)
-        f.close()
+        with open(self.filename, 'rb') as f:
+            y = np.fromfile(f, dtype=self.dtype)
         assert_array_equal(y, self.x.flat)
 
     def test_roundtrip_filename(self):
@@ -4688,14 +4694,12 @@ class TestIO(object):
         y = np.fromfile(self.filename, dtype=self.dtype)
         assert_array_equal(y, self.x.flat)
 
-    @pytest.mark.skipif(pathlib is None, reason="pathlib not found")
     def test_roundtrip_pathlib(self):
         p = pathlib.Path(self.filename)
         self.x.tofile(p)
         y = np.fromfile(p, dtype=self.dtype)
         assert_array_equal(y, self.x.flat)
 
-    @pytest.mark.skipif(pathlib is None, reason="pathlib not found")
     def test_roundtrip_dump_pathlib(self):
         p = pathlib.Path(self.filename)
         self.x.dump(p)
@@ -4779,19 +4783,17 @@ class TestIO(object):
                  io.DEFAULT_BUFFER_SIZE*8]
 
         for size in sizes:
-            f = open(self.filename, 'wb')
-            f.seek(size-1)
-            f.write(b'\0')
-            f.close()
+            with open(self.filename, 'wb') as f:
+                f.seek(size-1)
+                f.write(b'\0')
 
             for mode in ['rb', 'r+b']:
                 err_msg = "%d %s" % (size, mode)
 
-                f = open(self.filename, mode)
-                f.read(2)
-                np.fromfile(f, dtype=np.float64, count=1)
-                pos = f.tell()
-                f.close()
+                with open(self.filename, mode) as f:
+                    f.read(2)
+                    np.fromfile(f, dtype=np.float64, count=1)
+                    pos = f.tell()
                 assert_equal(pos, 10, err_msg=err_msg)
 
     def test_file_position_after_tofile(self):
@@ -4803,22 +4805,20 @@ class TestIO(object):
         for size in sizes:
             err_msg = "%d" % (size,)
 
-            f = open(self.filename, 'wb')
-            f.seek(size-1)
-            f.write(b'\0')
-            f.seek(10)
-            f.write(b'12')
-            np.array([0], dtype=np.float64).tofile(f)
-            pos = f.tell()
-            f.close()
+            with open(self.filename, 'wb') as f:
+                f.seek(size-1)
+                f.write(b'\0')
+                f.seek(10)
+                f.write(b'12')
+                np.array([0], dtype=np.float64).tofile(f)
+                pos = f.tell()
             assert_equal(pos, 10 + 2 + 8, err_msg=err_msg)
 
-            f = open(self.filename, 'r+b')
-            f.read(2)
-            f.seek(0, 1)  # seek between read&write required by ANSI C
-            np.array([0], dtype=np.float64).tofile(f)
-            pos = f.tell()
-            f.close()
+            with open(self.filename, 'r+b') as f:
+                f.read(2)
+                f.seek(0, 1)  # seek between read&write required by ANSI C
+                np.array([0], dtype=np.float64).tofile(f)
+                pos = f.tell()
             assert_equal(pos, 10, err_msg=err_msg)
 
     def test_load_object_array_fromfile(self):
@@ -4871,9 +4871,8 @@ class TestIO(object):
             y = np.fromstring(s, **kw)
         assert_array_equal(y, value)
 
-        f = open(self.filename, 'wb')
-        f.write(s)
-        f.close()
+        with open(self.filename, 'wb') as f:
+            f.write(s)
         y = np.fromfile(self.filename, **kw)
         assert_array_equal(y, value)
 
@@ -4957,33 +4956,28 @@ class TestIO(object):
         # can't use _check_from because fromstring can't handle True/False
         v = np.array([True, False, True, False], dtype=np.bool_)
         s = b'1,0,-2.3,0'
-        f = open(self.filename, 'wb')
-        f.write(s)
-        f.close()
+        with open(self.filename, 'wb') as f:
+            f.write(s)
         y = np.fromfile(self.filename, sep=',', dtype=np.bool_)
         assert_(y.dtype == '?')
         assert_array_equal(y, v)
 
     def test_tofile_sep(self):
         x = np.array([1.51, 2, 3.51, 4], dtype=float)
-        f = open(self.filename, 'w')
-        x.tofile(f, sep=',')
-        f.close()
-        f = open(self.filename, 'r')
-        s = f.read()
-        f.close()
+        with open(self.filename, 'w') as f:
+            x.tofile(f, sep=',')
+        with open(self.filename, 'r') as f:
+            s = f.read()
         #assert_equal(s, '1.51,2.0,3.51,4.0')
         y = np.array([float(p) for p in s.split(',')])
         assert_array_equal(x,y)
 
     def test_tofile_format(self):
         x = np.array([1.51, 2, 3.51, 4], dtype=float)
-        f = open(self.filename, 'w')
-        x.tofile(f, sep=',', format='%.2f')
-        f.close()
-        f = open(self.filename, 'r')
-        s = f.read()
-        f.close()
+        with open(self.filename, 'w') as f:
+            x.tofile(f, sep=',', format='%.2f')
+        with open(self.filename, 'r') as f:
+            s = f.read()
         assert_equal(s, '1.51,2.00,3.51,4.00')
 
     def test_locale(self):
@@ -5011,7 +5005,7 @@ class TestIO(object):
             assert_array_equal(x, res)
 
 
-class TestFromBuffer(object):
+class TestFromBuffer:
     @pytest.mark.parametrize('byteorder', ['<', '>'])
     @pytest.mark.parametrize('dtype', [float, int, complex])
     def test_basic(self, byteorder, dtype):
@@ -5024,7 +5018,7 @@ class TestFromBuffer(object):
         assert_array_equal(np.frombuffer(b''), np.array([]))
 
 
-class TestFlat(object):
+class TestFlat:
     def setup(self):
         a0 = np.arange(20.0)
         a = a0.reshape(4, 5)
@@ -5096,7 +5090,7 @@ class TestFlat(object):
             assert_(abs(sys.getrefcount(indtype) - rc_indtype) < 50)
 
 
-class TestResize(object):
+class TestResize:
 
     @_no_tracing
     def test_basic(self):
@@ -5195,7 +5189,7 @@ class TestResize(object):
         del xref  # avoid pyflakes unused variable warning.
 
 
-class TestRecord(object):
+class TestRecord:
     def test_field_rename(self):
         dt = np.dtype([('f', float), ('i', int)])
         dt.names = ['p', 'q']
@@ -5208,7 +5202,6 @@ class TestRecord(object):
         # Error raised when multiple fields have the same name
         assert_raises(ValueError, test_dtype_init)
 
-    @pytest.mark.skipif(sys.version_info[0] < 3, reason="Not Python 3")
     def test_bytes_fields(self):
         # Bytes are not allowed in field names and not recognized in titles
         # on Py3
@@ -5224,7 +5217,6 @@ class TestRecord(object):
         y = x[0]
         assert_raises(IndexError, y.__getitem__, b'a')
 
-    @pytest.mark.skipif(sys.version_info[0] < 3, reason="Not Python 3")
     def test_multiple_field_name_unicode(self):
         def test_dtype_unicode():
             np.dtype([("\u20B9", "f8"), ("B", "f8"), ("\u20B9", "f8")])
@@ -5232,32 +5224,6 @@ class TestRecord(object):
         # Error raised when multiple fields have the same name(unicode included)
         assert_raises(ValueError, test_dtype_unicode)
 
-    @pytest.mark.skipif(sys.version_info[0] >= 3, reason="Not Python 2")
-    def test_unicode_field_titles(self):
-        # Unicode field titles are added to field dict on Py2
-        title = u'b'
-        dt = np.dtype([((title, 'a'), int)])
-        dt[title]
-        dt['a']
-        x = np.array([(1,), (2,), (3,)], dtype=dt)
-        x[title]
-        x['a']
-        y = x[0]
-        y[title]
-        y['a']
-
-    @pytest.mark.skipif(sys.version_info[0] >= 3, reason="Not Python 2")
-    def test_unicode_field_names(self):
-        # Unicode field names are converted to ascii on Python 2:
-        encodable_name = u'b'
-        assert_equal(np.dtype([(encodable_name, int)]).names[0], b'b')
-        assert_equal(np.dtype([(('a', encodable_name), int)]).names[0], b'b')
-
-        # But raises UnicodeEncodeError if it can't be encoded:
-        nonencodable_name = u'\uc3bc'
-        assert_raises(UnicodeEncodeError, np.dtype, [(nonencodable_name, int)])
-        assert_raises(UnicodeEncodeError, np.dtype, [(('a', nonencodable_name), int)])
-
     def test_fromarrays_unicode(self):
         # A single name string provided to fromarrays() is allowed to be unicode
         # on both Python 2 and 3:
@@ -5278,51 +5244,41 @@ class TestRecord(object):
         a = np.zeros((1,), dtype=[('f1', 'i4'),
                                   ('f2', 'i4'),
                                   ('f3', [('sf1', 'i4')])])
-        is_py3 = sys.version_info[0] >= 3
-        if is_py3:
-            funcs = (str,)
-            # byte string indexing fails gracefully
-            assert_raises(IndexError, a.__setitem__, b'f1', 1)
-            assert_raises(IndexError, a.__getitem__, b'f1')
-            assert_raises(IndexError, a['f1'].__setitem__, b'sf1', 1)
-            assert_raises(IndexError, a['f1'].__getitem__, b'sf1')
-        else:
-            funcs = (str, unicode)
-        for func in funcs:
-            b = a.copy()
-            fn1 = func('f1')
-            b[fn1] = 1
-            assert_equal(b[fn1], 1)
-            fnn = func('not at all')
-            assert_raises(ValueError, b.__setitem__, fnn, 1)
-            assert_raises(ValueError, b.__getitem__, fnn)
-            b[0][fn1] = 2
-            assert_equal(b[fn1], 2)
-            # Subfield
-            assert_raises(ValueError, b[0].__setitem__, fnn, 1)
-            assert_raises(ValueError, b[0].__getitem__, fnn)
-            # Subfield
-            fn3 = func('f3')
-            sfn1 = func('sf1')
-            b[fn3][sfn1] = 1
-            assert_equal(b[fn3][sfn1], 1)
-            assert_raises(ValueError, b[fn3].__setitem__, fnn, 1)
-            assert_raises(ValueError, b[fn3].__getitem__, fnn)
-            # multiple subfields
-            fn2 = func('f2')
-            b[fn2] = 3
-
-            assert_equal(b[['f1', 'f2']][0].tolist(), (2, 3))
-            assert_equal(b[['f2', 'f1']][0].tolist(), (3, 2))
-            assert_equal(b[['f1', 'f3']][0].tolist(), (2, (1,)))
+        # byte string indexing fails gracefully
+        assert_raises(IndexError, a.__setitem__, b'f1', 1)
+        assert_raises(IndexError, a.__getitem__, b'f1')
+        assert_raises(IndexError, a['f1'].__setitem__, b'sf1', 1)
+        assert_raises(IndexError, a['f1'].__getitem__, b'sf1')
+        b = a.copy()
+        fn1 = str('f1')
+        b[fn1] = 1
+        assert_equal(b[fn1], 1)
+        fnn = str('not at all')
+        assert_raises(ValueError, b.__setitem__, fnn, 1)
+        assert_raises(ValueError, b.__getitem__, fnn)
+        b[0][fn1] = 2
+        assert_equal(b[fn1], 2)
+        # Subfield
+        assert_raises(ValueError, b[0].__setitem__, fnn, 1)
+        assert_raises(ValueError, b[0].__getitem__, fnn)
+        # Subfield
+        fn3 = str('f3')
+        sfn1 = str('sf1')
+        b[fn3][sfn1] = 1
+        assert_equal(b[fn3][sfn1], 1)
+        assert_raises(ValueError, b[fn3].__setitem__, fnn, 1)
+        assert_raises(ValueError, b[fn3].__getitem__, fnn)
+        # multiple subfields
+        fn2 = str('f2')
+        b[fn2] = 3
+
+        assert_equal(b[['f1', 'f2']][0].tolist(), (2, 3))
+        assert_equal(b[['f2', 'f1']][0].tolist(), (3, 2))
+        assert_equal(b[['f1', 'f3']][0].tolist(), (2, (1,)))
 
         # non-ascii unicode field indexing is well behaved
-        if not is_py3:
-            pytest.skip('non ascii unicode field indexing skipped; '
-                        'raises segfault on python 2.x')
-        else:
-            assert_raises(ValueError, a.__setitem__, u'\u03e0', 1)
-            assert_raises(ValueError, a.__getitem__, u'\u03e0')
+        assert_raises(ValueError, a.__setitem__, u'\u03e0', 1)
+        assert_raises(ValueError, a.__getitem__, u'\u03e0')
 
     def test_record_hash(self):
         a = np.array([(1, 2), (1, 2)], dtype='i1,i2')
@@ -5357,7 +5313,7 @@ class TestRecord(object):
         v[:] = (4,5)
         assert_equal(a[0].item(), (4, 1, 5))
 
-class TestView(object):
+class TestView:
     def test_basic(self):
         x = np.array([(1, 2, 3, 4), (5, 6, 7, 8)],
                      dtype=[('r', np.int8), ('g', np.int8),
@@ -5382,7 +5338,7 @@ def _std(a, **args):
     return a.std(**args)
 
 
-class TestStats(object):
+class TestStats:
 
     funcs = [_mean, _var, _std]
 
@@ -5554,6 +5510,12 @@ class TestStats(object):
         # of float32.
         assert_(_mean(np.ones(100000, dtype='float16')) == 1)
 
+    def test_mean_axis_error(self):
+        # Ensure that AxisError is raised instead of IndexError when axis is
+        # out of bounds, see gh-15817.
+        with assert_raises(np.core._exceptions.AxisError):
+            np.arange(10).mean(axis=2)
+
     def test_var_values(self):
         for mat in [self.rmat, self.cmat, self.omat]:
             for axis in [0, 1, None]:
@@ -5563,6 +5525,45 @@ class TestStats(object):
                 res = _var(mat, axis=axis)
                 assert_almost_equal(res, tgt)
 
+    @pytest.mark.parametrize(('complex_dtype', 'ndec'), (
+        ('complex64', 6),
+        ('complex128', 7),
+        ('clongdouble', 7),
+    ))
+    def test_var_complex_values(self, complex_dtype, ndec):
+        # Test fast-paths for every builtin complex type
+        for axis in [0, 1, None]:
+            mat = self.cmat.copy().astype(complex_dtype)
+            msqr = _mean(mat * mat.conj(), axis=axis)
+            mean = _mean(mat, axis=axis)
+            tgt = msqr - mean * mean.conjugate()
+            res = _var(mat, axis=axis)
+            assert_almost_equal(res, tgt, decimal=ndec)
+
+    def test_var_dimensions(self):
+        # _var paths for complex number introduce additions on views that
+        # increase dimensions. Ensure this generalizes to higher dims
+        mat = np.stack([self.cmat]*3)
+        for axis in [0, 1, 2, -1, None]:
+            msqr = _mean(mat * mat.conj(), axis=axis)
+            mean = _mean(mat, axis=axis)
+            tgt = msqr - mean * mean.conjugate()
+            res = _var(mat, axis=axis)
+            assert_almost_equal(res, tgt)
+
+    def test_var_complex_byteorder(self):
+        # Test that var fast-path does not cause failures for complex arrays
+        # with non-native byteorder
+        cmat = self.cmat.copy().astype('complex128')
+        cmat_swapped = cmat.astype(cmat.dtype.newbyteorder())
+        assert_almost_equal(cmat.var(), cmat_swapped.var())
+
+    def test_var_axis_error(self):
+        # Ensure that AxisError is raised instead of IndexError when axis is
+        # out of bounds, see gh-15817.
+        with assert_raises(np.core._exceptions.AxisError):
+            np.arange(10).var(axis=2)
+
     def test_std_values(self):
         for mat in [self.rmat, self.cmat, self.omat]:
             for axis in [0, 1, None]:
@@ -5589,7 +5590,7 @@ class TestStats(object):
         res = dat.var(1)
         assert_(res.info == dat.info)
 
-class TestVdot(object):
+class TestVdot:
     def test_basic(self):
         dt_numeric = np.typecodes['AllFloat'] + np.typecodes['AllInteger']
         dt_complex = np.typecodes['Complex']
@@ -5649,7 +5650,7 @@ class TestVdot(object):
                          np.vdot(a.flatten(), b.flatten()))
 
 
-class TestDot(object):
+class TestDot:
     def setup(self):
         np.random.seed(128)
         self.A = np.random.rand(4, 2)
@@ -5751,7 +5752,7 @@ class TestDot(object):
             assert_almost_equal(res, tgt, decimal=self.N)
 
     def test_vecobject(self):
-        class Vec(object):
+        class Vec:
             def __init__(self, sequence=None):
                 if sequence is None:
                     sequence = []
@@ -5920,7 +5921,7 @@ class TestDot(object):
             assert_dot_close(A_f_12, X_f_2, desired)
 
 
-class MatmulCommon(object):
+class MatmulCommon:
     """Common tests for '@' operator and numpy.matmul.
 
     """
@@ -6295,59 +6296,55 @@ class TestMatmul(MatmulCommon):
         assert not np.any(c)
 
 
-if sys.version_info[:2] >= (3, 5):
-    class TestMatmulOperator(MatmulCommon):
-        import operator
-        matmul = operator.matmul
+class TestMatmulOperator(MatmulCommon):
+    import operator
+    matmul = operator.matmul
 
-        def test_array_priority_override(self):
+    def test_array_priority_override(self):
 
-            class A(object):
-                __array_priority__ = 1000
+        class A:
+            __array_priority__ = 1000
 
-                def __matmul__(self, other):
-                    return "A"
+            def __matmul__(self, other):
+                return "A"
 
-                def __rmatmul__(self, other):
-                    return "A"
+            def __rmatmul__(self, other):
+                return "A"
 
-            a = A()
-            b = np.ones(2)
-            assert_equal(self.matmul(a, b), "A")
-            assert_equal(self.matmul(b, a), "A")
+        a = A()
+        b = np.ones(2)
+        assert_equal(self.matmul(a, b), "A")
+        assert_equal(self.matmul(b, a), "A")
 
-        def test_matmul_raises(self):
-            assert_raises(TypeError, self.matmul, np.int8(5), np.int8(5))
-            assert_raises(TypeError, self.matmul, np.void(b'abc'), np.void(b'abc'))
-            assert_raises(ValueError, self.matmul, np.arange(10), np.void(b'abc'))
+    def test_matmul_raises(self):
+        assert_raises(TypeError, self.matmul, np.int8(5), np.int8(5))
+        assert_raises(TypeError, self.matmul, np.void(b'abc'), np.void(b'abc'))
+        assert_raises(ValueError, self.matmul, np.arange(10), np.void(b'abc'))
+
+def test_matmul_inplace():
+    # It would be nice to support in-place matmul eventually, but for now
+    # we don't have a working implementation, so better just to error out
+    # and nudge people to writing "a = a @ b".
+    a = np.eye(3)
+    b = np.eye(3)
+    assert_raises(TypeError, a.__imatmul__, b)
+    import operator
+    assert_raises(TypeError, operator.imatmul, a, b)
+    assert_raises(TypeError, exec, "a @= b", globals(), locals())
+
+def test_matmul_axes():
+    a = np.arange(3*4*5).reshape(3, 4, 5)
+    c = np.matmul(a, a, axes=[(-2, -1), (-1, -2), (1, 2)])
+    assert c.shape == (3, 4, 4)
+    d = np.matmul(a, a, axes=[(-2, -1), (-1, -2), (0, 1)])
+    assert d.shape == (4, 4, 3)
+    e = np.swapaxes(d, 0, 2)
+    assert_array_equal(e, c)
+    f = np.matmul(a, np.arange(3), axes=[(1, 0), (0), (0)])
+    assert f.shape == (4, 5)
 
-    def test_matmul_inplace():
-        # It would be nice to support in-place matmul eventually, but for now
-        # we don't have a working implementation, so better just to error out
-        # and nudge people to writing "a = a @ b".
-        a = np.eye(3)
-        b = np.eye(3)
-        assert_raises(TypeError, a.__imatmul__, b)
-        import operator
-        assert_raises(TypeError, operator.imatmul, a, b)
-        # we avoid writing the token `exec` so as not to crash python 2's
-        # parser
-        exec_ = getattr(builtins, "exec")
-        assert_raises(TypeError, exec_, "a @= b", globals(), locals())
-
-    def test_matmul_axes():
-        a = np.arange(3*4*5).reshape(3, 4, 5)
-        c = np.matmul(a, a, axes=[(-2, -1), (-1, -2), (1, 2)])
-        assert c.shape == (3, 4, 4)
-        d = np.matmul(a, a, axes=[(-2, -1), (-1, -2), (0, 1)])
-        assert d.shape == (4, 4, 3)
-        e = np.swapaxes(d, 0, 2)
-        assert_array_equal(e, c)
-        f = np.matmul(a, np.arange(3), axes=[(1, 0), (0), (0)])
-        assert f.shape == (4, 5)
-
-
-class TestInner(object):
+
+class TestInner:
 
     def test_inner_type_mismatch(self):
         c = 1.
@@ -6425,7 +6422,7 @@ class TestInner(object):
             assert_equal(np.inner(b, a).transpose(2,3,0,1), desired)
 
 
-class TestAlen(object):
+class TestAlen:
     def test_basic(self):
         with pytest.warns(DeprecationWarning):
             m = np.array([1, 2, 3])
@@ -6445,7 +6442,7 @@ class TestAlen(object):
             assert_equal(np.alen(5), 1)
 
 
-class TestChoose(object):
+class TestChoose:
     def setup(self):
         self.x = 2*np.ones((3,), dtype=int)
         self.y = 3*np.ones((3,), dtype=int)
@@ -6465,8 +6462,17 @@ class TestChoose(object):
         A = np.choose(self.ind, (self.x, self.y2))
         assert_equal(A, [[2, 2, 3], [2, 2, 3]])
 
+    @pytest.mark.parametrize("ops",
+        [(1000, np.array([1], dtype=np.uint8)),
+         (-1, np.array([1], dtype=np.uint8)),
+         (1., np.float32(3)),
+         (1., np.array([3], dtype=np.float32))],)
+    def test_output_dtype(self, ops):
+        expected_dt = np.result_type(*ops)
+        assert(np.choose([0], ops).dtype == expected_dt)
+
 
-class TestRepeat(object):
+class TestRepeat:
     def setup(self):
         self.m = np.array([1, 2, 3, 4, 5, 6])
         self.m_rect = self.m.reshape((2, 3))
@@ -6508,7 +6514,7 @@ NEIGH_MODE = {'zero': 0, 'one': 1, 'constant': 2, 'circular': 3, 'mirror': 4}
 
 
 @pytest.mark.parametrize('dt', [float, Decimal], ids=['float', 'object'])
-class TestNeighborhoodIter(object):
+class TestNeighborhoodIter:
     # Simple, 2d tests
     def test_simple2d(self, dt):
         # Test zero and one padding for simple data type
@@ -6587,7 +6593,7 @@ class TestNeighborhoodIter(object):
 
 
 # Test stacking neighborhood iterators
-class TestStackedNeighborhoodIter(object):
+class TestStackedNeighborhoodIter:
     # Simple, 1d test: stacking 2 constant-padded neigh iterators
     def test_simple_const(self):
         dt = np.float64
@@ -6737,7 +6743,7 @@ class TestStackedNeighborhoodIter(object):
                 x, [1, 1], NEIGH_MODE['zero'], [-1, 2], NEIGH_MODE['circular'])
         assert_array_equal(l, r)
 
-class TestWarnings(object):
+class TestWarnings:
 
     def test_complex_warning(self):
         x = np.array([1, 2])
@@ -6749,7 +6755,7 @@ class TestWarnings(object):
             assert_equal(x, [1, 2])
 
 
-class TestMinScalarType(object):
+class TestMinScalarType:
 
     def test_usigned_shortshort(self):
         dt = np.min_scalar_type(2**8-1)
@@ -6780,7 +6786,7 @@ class TestMinScalarType(object):
 from numpy.core._internal import _dtype_from_pep3118
 
 
-class TestPEP3118Dtype(object):
+class TestPEP3118Dtype:
     def _check(self, spec, wanted):
         dt = np.dtype(wanted)
         actual = _dtype_from_pep3118(spec)
@@ -6887,7 +6893,7 @@ class TestPEP3118Dtype(object):
         self._check('i:f0:', [('f0', 'i')])
 
 
-class TestNewBufferProtocol(object):
+class TestNewBufferProtocol:
     """ Test PEP3118 buffers """
 
     def _check_roundtrip(self, obj):
@@ -7037,7 +7043,7 @@ class TestNewBufferProtocol(object):
         assert_equal(y.shape, (5,))
         assert_equal(y.ndim, 1)
         assert_equal(y.strides, (4,))
-        assert_equal(y.suboffsets, EMPTY)
+        assert_equal(y.suboffsets, ())
         assert_equal(y.itemsize, 4)
 
     def test_export_simple_nd(self):
@@ -7047,7 +7053,7 @@ class TestNewBufferProtocol(object):
         assert_equal(y.shape, (2, 2))
         assert_equal(y.ndim, 2)
         assert_equal(y.strides, (16, 8))
-        assert_equal(y.suboffsets, EMPTY)
+        assert_equal(y.suboffsets, ())
         assert_equal(y.itemsize, 8)
 
     def test_export_discontiguous(self):
@@ -7057,7 +7063,7 @@ class TestNewBufferProtocol(object):
         assert_equal(y.shape, (3, 3))
         assert_equal(y.ndim, 2)
         assert_equal(y.strides, (36, 4))
-        assert_equal(y.suboffsets, EMPTY)
+        assert_equal(y.suboffsets, ())
         assert_equal(y.itemsize, 4)
 
     def test_export_record(self):
@@ -7090,7 +7096,7 @@ class TestNewBufferProtocol(object):
         y = memoryview(x)
         assert_equal(y.shape, (1,))
         assert_equal(y.ndim, 1)
-        assert_equal(y.suboffsets, EMPTY)
+        assert_equal(y.suboffsets, ())
 
         sz = sum([np.dtype(b).itemsize for a, b in dt])
         if np.dtype('l').itemsize == 4:
@@ -7106,10 +7112,10 @@ class TestNewBufferProtocol(object):
         x = np.array(([[1, 2], [3, 4]],), dtype=[('a', ('i', (2, 2)))])
         y = memoryview(x)
         assert_equal(y.format, 'T{(2,2)i:a:}')
-        assert_equal(y.shape, EMPTY)
+        assert_equal(y.shape, ())
         assert_equal(y.ndim, 0)
-        assert_equal(y.strides, EMPTY)
-        assert_equal(y.suboffsets, EMPTY)
+        assert_equal(y.strides, ())
+        assert_equal(y.suboffsets, ())
         assert_equal(y.itemsize, 16)
 
     def test_export_endian(self):
@@ -7212,7 +7218,7 @@ class TestNewBufferProtocol(object):
         a = np.empty((1,) * 32)
         self._check_roundtrip(a)
 
-    @pytest.mark.skipif(sys.version_info < (2, 7, 7), reason="See gh-11115")
+    @pytest.mark.slow
     def test_error_too_many_dims(self):
         def make_ctype(shape, scalar_type):
             t = scalar_type
@@ -7253,12 +7259,11 @@ class TestNewBufferProtocol(object):
             np.array(t())
 
         exc = cm.exception
-        if sys.version_info.major > 2:
-            with assert_raises_regex(
-                NotImplementedError,
-                r"Unrepresentable .* 'u' \(UCS-2 strings\)"
-            ):
-                raise exc.__cause__
+        with assert_raises_regex(
+            NotImplementedError,
+            r"Unrepresentable .* 'u' \(UCS-2 strings\)"
+        ):
+            raise exc.__cause__
 
     def test_ctypes_integer_via_memoryview(self):
         # gh-11150, due to bpo-10746
@@ -7284,7 +7289,7 @@ class TestNewBufferProtocol(object):
         assert_equal(arr['a'], 3)
 
 
-class TestArrayAttributeDeletion(object):
+class TestArrayAttributeDeletion:
 
     def test_multiarray_writable_attributes_deletion(self):
         # ticket #2046, should not seqfault, raise AttributeError
@@ -7319,7 +7324,7 @@ class TestArrayAttributeDeletion(object):
 
 
 class TestArrayInterface():
-    class Foo(object):
+    class Foo:
         def __init__(self, value):
             self.value = value
             self.iface = {'typestr': 'f8'}
@@ -7364,7 +7369,7 @@ class TestArrayInterface():
             assert_equal(pre_cnt, post_cnt)
 
 def test_interface_no_shape():
-    class ArrayLike(object):
+    class ArrayLike:
         array = np.array(1)
         __array_interface__ = array.__array_interface__
     assert_equal(np.array(ArrayLike()), 1)
@@ -7386,7 +7391,7 @@ def test_array_interface_empty_shape():
     interface1 = dict(arr.__array_interface__)
     interface1['shape'] = ()
 
-    class DummyArray1(object):
+    class DummyArray1:
         __array_interface__ = interface1
 
     # NOTE: Because Py2 str/Py3 bytes supports the buffer interface, setting
@@ -7396,7 +7401,7 @@ def test_array_interface_empty_shape():
     interface2 = dict(interface1)
     interface2['data'] = arr[0].tobytes()
 
-    class DummyArray2(object):
+    class DummyArray2:
         __array_interface__ = interface2
 
     arr1 = np.asarray(DummyArray1())
@@ -7413,7 +7418,7 @@ def test_array_interface_offset():
     interface['offset'] = 4
 
 
-    class DummyArray(object):
+    class DummyArray:
         __array_interface__ = interface
 
     arr1 = np.asarray(DummyArray())
@@ -7435,7 +7440,7 @@ def test_scalar_element_deletion():
     assert_raises(ValueError, a[0].__delitem__, 'x')
 
 
-class TestMemEventHook(object):
+class TestMemEventHook:
     def test_mem_seteventhook(self):
         # The actual tests are within the C code in
         # multiarray/_multiarray_tests.c.src
@@ -7447,7 +7452,7 @@ class TestMemEventHook(object):
         break_cycles()
         _multiarray_tests.test_pydatamem_seteventhook_end()
 
-class TestMapIter(object):
+class TestMapIter:
     def test_mapiter(self):
         # The actual tests are within the C code in
         # multiarray/_multiarray_tests.c.src
@@ -7469,7 +7474,7 @@ class TestMapIter(object):
         assert_equal(b, [100.1,  51.,   6.,   3.,   4.,   5.])
 
 
-class TestAsCArray(object):
+class TestAsCArray:
     def test_1darray(self):
         array = np.arange(24, dtype=np.double)
         from_c = _multiarray_tests.test_as_c_array(array, 3)
@@ -7486,7 +7491,7 @@ class TestAsCArray(object):
         assert_equal(array[1, 2, 3], from_c)
 
 
-class TestConversion(object):
+class TestConversion:
     def test_array_scalar_relational_operation(self):
         # All integer
         for dt1 in np.typecodes['AllInteger']:
@@ -7534,10 +7539,9 @@ class TestConversion(object):
         assert_equal(bool(np.array([[42]])), True)
         assert_raises(ValueError, bool, np.array([1, 2]))
 
-        class NotConvertible(object):
+        class NotConvertible:
             def __bool__(self):
                 raise NotImplementedError
-            __nonzero__ = __bool__  # python 2
 
         assert_raises(NotImplementedError, bool, np.array(NotConvertible()))
         assert_raises(NotImplementedError, bool, np.array([NotConvertible()]))
@@ -7555,8 +7559,8 @@ class TestConversion(object):
         # gh-9972 means that these aren't always the same
         int_funcs = (int, lambda x: x.__int__())
         for int_func in int_funcs:
+            assert_equal(int_func(np.array(0)), 0)
             assert_equal(int_func(np.array([1])), 1)
-            assert_equal(int_func(np.array([0])), 0)
             assert_equal(int_func(np.array([[42]])), 42)
             assert_raises(TypeError, int_func, np.array([1, 2]))
 
@@ -7571,7 +7575,7 @@ class TestConversion(object):
             assert_equal(3, int_func(np.array(HasTrunc())))
             assert_equal(3, int_func(np.array([HasTrunc()])))
 
-            class NotConvertible(object):
+            class NotConvertible:
                 def __int__(self):
                     raise NotImplementedError
             assert_raises(NotImplementedError,
@@ -7580,7 +7584,7 @@ class TestConversion(object):
                 int_func, np.array([NotConvertible()]))
 
 
-class TestWhere(object):
+class TestWhere:
     def test_basic(self):
         dts = [bool, np.int16, np.int32, np.int64, np.double, np.complex128,
                np.longdouble, np.clongdouble]
@@ -7747,7 +7751,7 @@ class TestWhere(object):
 
 if not IS_PYPY:
     # sys.getsizeof() is not valid on PyPy
-    class TestSizeOf(object):
+    class TestSizeOf:
 
         def test_empty_array(self):
             x = np.array([])
@@ -7794,7 +7798,7 @@ if not IS_PYPY:
             assert_raises(TypeError, d.__sizeof__, "a")
 
 
-class TestHashing(object):
+class TestHashing:
 
     def test_arrays_not_hashable(self):
         x = np.ones(3)
@@ -7802,10 +7806,10 @@ class TestHashing(object):
 
     def test_collections_hashable(self):
         x = np.array([])
-        assert_(not isinstance(x, collections_abc.Hashable))
+        assert_(not isinstance(x, collections.abc.Hashable))
 
 
-class TestArrayPriority(object):
+class TestArrayPriority:
     # This will go away when __array_priority__ is settled, meanwhile
     # it serves to check unintended changes.
     op = operator
@@ -7815,11 +7819,6 @@ class TestArrayPriority(object):
         op.ge, op.lt, op.le, op.ne, op.eq
         ]
 
-    # See #7949. Don't use "/" operator With -3 switch, since python reports it
-    # as a DeprecationWarning
-    if sys.version_info[0] < 3 and not sys.py3kwarning:
-        binary_ops.append(op.div)
-
     class Foo(np.ndarray):
         __array_priority__ = 100.
 
@@ -7832,7 +7831,7 @@ class TestArrayPriority(object):
         def __new__(cls, *args, **kwargs):
             return np.array(*args, **kwargs).view(cls)
 
-    class Other(object):
+    class Other:
         __array_priority__ = 1000.
 
         def _all(self, other):
@@ -7891,7 +7890,7 @@ class TestArrayPriority(object):
             assert_(isinstance(f(b, a), self.Other), msg)
 
 
-class TestBytestringArrayNonzero(object):
+class TestBytestringArrayNonzero:
 
     def test_empty_bstring_array_is_falsey(self):
         assert_(not np.array([''], dtype=str))
@@ -7912,7 +7911,35 @@ class TestBytestringArrayNonzero(object):
         assert_(a)
 
 
-class TestUnicodeArrayNonzero(object):
+class TestUnicodeEncoding:
+    """
+    Tests for encoding related bugs, such as UCS2 vs UCS4, round-tripping
+    issues, etc
+    """
+    def test_round_trip(self):
+        """ Tests that GETITEM, SETITEM, and PyArray_Scalar roundtrip """
+        # gh-15363
+        arr = np.zeros(shape=(), dtype="U1")
+        for i in range(1, sys.maxunicode + 1):
+            expected = chr(i)
+            arr[()] = expected
+            assert arr[()] == expected
+            assert arr.item() == expected
+
+    def test_assign_scalar(self):
+        # gh-3258
+        l = np.array(['aa', 'bb'])
+        l[:] = np.unicode_('cc')
+        assert_equal(l, ['cc', 'cc'])
+
+    def test_fill_scalar(self):
+        # gh-7227
+        l = np.array(['aa', 'bb'])
+        l.fill(np.unicode_('cc'))
+        assert_equal(l, ['cc', 'cc'])
+
+
+class TestUnicodeArrayNonzero:
 
     def test_empty_ustring_array_is_falsey(self):
         assert_(not np.array([''], dtype=np.unicode_))
@@ -7933,7 +7960,7 @@ class TestUnicodeArrayNonzero(object):
         assert_(a)
 
 
-class TestFormat(object):
+class TestFormat:
 
     def test_0d(self):
         a = np.array(np.pi)
@@ -7947,18 +7974,11 @@ class TestFormat(object):
     def test_1d_format(self):
         # until gh-5543, ensure that the behaviour matches what it used to be
         a = np.array([np.pi])
-        if sys.version_info[:2] >= (3, 4):
-            assert_raises(TypeError, '{:30}'.format, a)
-        else:
-            with suppress_warnings() as sup:
-                sup.filter(PendingDeprecationWarning)
-                res = '{:30}'.format(a)
-                dst = object.__format__(a, '30')
-                assert_equal(res, dst)
+        assert_raises(TypeError, '{:30}'.format, a)
 
 from numpy.testing import IS_PYPY
 
-class TestCTypes(object):
+class TestCTypes:
 
     def test_ctypes_is_available(self):
         test_arr = np.array([[1, 2, 3], [4, 5, 6]])
@@ -8050,7 +8070,7 @@ class TestCTypes(object):
         assert_(arr_ref() is None, "unknowable whether ctypes pointer holds a reference")
 
 
-class TestWritebackIfCopy(object):
+class TestWritebackIfCopy:
     # all these tests use the WRITEBACKIFCOPY mechanism
     def test_argmax_with_out(self):
         mat = np.eye(5)
@@ -8163,7 +8183,7 @@ class TestWritebackIfCopy(object):
         assert_equal(arr, orig)
 
 
-class TestArange(object):
+class TestArange:
     def test_infinite(self):
         assert_raises_regex(
             ValueError, "size exceeded",
@@ -8185,7 +8205,7 @@ class TestArange(object):
         assert_raises(ZeroDivisionError, np.arange, 0.0, 0.0, 0.0)
 
 
-class TestArrayFinalize(object):
+class TestArrayFinalize:
     """ Tests __array_finalize__ """
 
     def test_receives_base(self):
@@ -8205,7 +8225,7 @@ class TestArrayFinalize(object):
                 raise Exception(self)
 
         # a plain object can't be weakref'd
-        class Dummy(object): pass
+        class Dummy: pass
 
         # get a weak reference to an object within an array
         obj_arr = np.array(Dummy())
@@ -8214,9 +8234,6 @@ class TestArrayFinalize(object):
         # get an array that crashed in __array_finalize__
         with assert_raises(Exception) as e:
             obj_arr.view(RaisesInFinalize)
-        if sys.version_info.major == 2:
-            # prevent an extra reference being kept
-            sys.exc_clear()
 
         obj_subarray = e.exception.args[0]
         del e
@@ -8245,7 +8262,7 @@ def test_equal_override():
     # gh-9153: ndarray.__eq__ uses special logic for structured arrays, which
     # did not respect overrides with __array_priority__ or __array_ufunc__.
     # The PR fixed this for __array_priority__ and __array_ufunc__ = None.
-    class MyAlwaysEqual(object):
+    class MyAlwaysEqual:
         def __eq__(self, other):
             return "eq"
 
@@ -8308,7 +8325,7 @@ def test_npymath_real():
                 assert_allclose(got, expected)
 
 def test_uintalignment_and_alignment():
-    # alignment code needs to satisfy these requrements:
+    # alignment code needs to satisfy these requirements:
     #  1. numpy structs match C struct layout
     #  2. ufuncs/casting is safe wrt to aligned access
     #  3. copy code is safe wrt to "uint alidned" access
@@ -8343,7 +8360,7 @@ def test_uintalignment_and_alignment():
     dst = np.zeros((2,2), dtype='c8')
     dst[:,1] = src[:,1]  # assert in lowlevel_strided_loops fails?
 
-class TestAlignment(object):
+class TestAlignment:
     # adapted from scipy._lib.tests.test__util.test__aligned_zeros
     # Checks that unusual memory alignments don't trip up numpy.
     # In particular, check RELAXED_STRIDES don't trip alignment assertions in
index daec9ce6df67ae2b42b6679d9d50f8b0d63402e4..c106c528dd21e881ef30a3910f4d9d8accf0c107 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import pytest
 
@@ -2188,7 +2186,7 @@ def test_iter_no_broadcast():
                   [['readonly'], ['readonly'], ['readonly', 'no_broadcast']])
 
 
-class TestIterNested(object):
+class TestIterNested:
 
     def test_basic(self):
         # Test nested iteration basic usage
@@ -2690,7 +2688,15 @@ def test_0d_iter():
     i = nditer(np.arange(5), ['multi_index'], [['readonly']], op_axes=[()])
     assert_equal(i.ndim, 0)
     assert_equal(len(i), 1)
-    # note that itershape=(), still behaves like None due to the conversions
+
+    i = nditer(np.arange(5), ['multi_index'], [['readonly']],
+               op_axes=[()], itershape=())
+    assert_equal(i.ndim, 0)
+    assert_equal(len(i), 1)
+
+    # passing an itershape alone is not enough, the op_axes are also needed
+    with assert_raises(ValueError):
+        nditer(np.arange(5), ['multi_index'], [['readonly']], itershape=())
 
     # Test a more complex buffered casting case (same as another test above)
     sdt = [('a', 'f4'), ('b', 'i8'), ('c', 'c8', (2, 3)), ('d', 'O')]
index ffebdf64870c967f250bb9fce3468da23cee6c1b..acd442e2fbb6cb947c0cb405595b89f026b33498 100644 (file)
@@ -1,10 +1,9 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import warnings
 import itertools
 import platform
 import pytest
+import math
 from decimal import Decimal
 
 import numpy as np
@@ -13,11 +12,14 @@ from numpy.random import rand, randint, randn
 from numpy.testing import (
     assert_, assert_equal, assert_raises, assert_raises_regex,
     assert_array_equal, assert_almost_equal, assert_array_almost_equal,
-    assert_warns, HAS_REFCOUNT
+    assert_warns, assert_array_max_ulp, HAS_REFCOUNT
     )
 
+from hypothesis import assume, given, strategies as st
+from hypothesis.extra import numpy as hynp
+
 
-class TestResize(object):
+class TestResize:
     def test_copies(self):
         A = np.array([[1, 2], [3, 4]])
         Ar1 = np.array([[1, 2, 3, 4], [1, 2, 3, 4]])
@@ -49,7 +51,7 @@ class TestResize(object):
         assert_equal(A.dtype, Ar.dtype)
 
 
-class TestNonarrayArgs(object):
+class TestNonarrayArgs:
     # check that non-array arguments to functions wrap them in arrays
     def test_choose(self):
         choices = [[0, 1, 2],
@@ -138,6 +140,51 @@ class TestNonarrayArgs(object):
         arr = [1.56, 72.54, 6.35, 3.25]
         tgt = [1.6, 72.5, 6.4, 3.2]
         assert_equal(np.around(arr, decimals=1), tgt)
+        s = np.float64(1.)
+        assert_(isinstance(s.round(), np.float64))
+        assert_equal(s.round(), 1.)
+
+    @pytest.mark.parametrize('dtype', [
+        np.int8, np.int16, np.int32, np.int64,
+        np.uint8, np.uint16, np.uint32, np.uint64,
+        np.float16, np.float32, np.float64,
+    ])
+    def test_dunder_round(self, dtype):
+        s = dtype(1)
+        assert_(isinstance(round(s), int))
+        assert_(isinstance(round(s, None), int))
+        assert_(isinstance(round(s, ndigits=None), int))
+        assert_equal(round(s), 1)
+        assert_equal(round(s, None), 1)
+        assert_equal(round(s, ndigits=None), 1)
+
+    @pytest.mark.parametrize('val, ndigits', [
+        pytest.param(2**31 - 1, -1,
+            marks=pytest.mark.xfail(reason="Out of range of int32")
+        ),
+        (2**31 - 1, 1-math.ceil(math.log10(2**31 - 1))),
+        (2**31 - 1, -math.ceil(math.log10(2**31 - 1)))
+    ])
+    def test_dunder_round_edgecases(self, val, ndigits):
+        assert_equal(round(val, ndigits), round(np.int32(val), ndigits))
+
+    def test_dunder_round_accuracy(self):
+        f = np.float64(5.1 * 10**73)
+        assert_(isinstance(round(f, -73), np.float64))
+        assert_array_max_ulp(round(f, -73), 5.0 * 10**73)
+        assert_(isinstance(round(f, ndigits=-73), np.float64))
+        assert_array_max_ulp(round(f, ndigits=-73), 5.0 * 10**73)
+
+        i = np.int64(501)
+        assert_(isinstance(round(i, -2), np.int64))
+        assert_array_max_ulp(round(i, -2), 500)
+        assert_(isinstance(round(i, ndigits=-2), np.int64))
+        assert_array_max_ulp(round(i, ndigits=-2), 500)
+
+    @pytest.mark.xfail(raises=AssertionError, reason="gh-15896")
+    def test_round_py_consistency(self):
+        f = 5.1 * 10**73
+        assert_equal(round(np.float64(f), -73), round(f, -73))
 
     def test_searchsorted(self):
         arr = [-8, -5, -1, 3, 6, 10]
@@ -220,7 +267,7 @@ class TestNonarrayArgs(object):
         B[0] = 1j
         assert_almost_equal(np.var(B), 0.25)
 
-class TestIsscalar(object):
+class TestIsscalar:
     def test_isscalar(self):
         assert_(np.isscalar(3.1))
         assert_(np.isscalar(np.int16(12345)))
@@ -236,7 +283,7 @@ class TestIsscalar(object):
         assert_(np.isscalar(Number()))
 
 
-class TestBoolScalar(object):
+class TestBoolScalar:
     def test_logical(self):
         f = np.False_
         t = np.True_
@@ -269,7 +316,7 @@ class TestBoolScalar(object):
         assert_((f ^ f) is f)
 
 
-class TestBoolArray(object):
+class TestBoolArray:
     def setup(self):
         # offset for simd tests
         self.t = np.array([True] * 41, dtype=bool)[1::]
@@ -356,7 +403,7 @@ class TestBoolArray(object):
         assert_array_equal(self.im ^ False, self.im)
 
 
-class TestBoolCmp(object):
+class TestBoolCmp:
     def setup(self):
         self.f = np.ones(256, dtype=np.float32)
         self.ef = np.ones(self.f.size, dtype=bool)
@@ -456,7 +503,7 @@ class TestBoolCmp(object):
             assert_array_equal(np.signbit(self.signd[i:]), self.ed[i:])
 
 
-class TestSeterr(object):
+class TestSeterr:
     def test_default(self):
         err = np.geterr()
         assert_equal(err,
@@ -537,7 +584,7 @@ class TestSeterr(object):
             np.seterrobj(olderrobj)
 
 
-class TestFloatExceptions(object):
+class TestFloatExceptions:
     def assert_raises_fpe(self, fpeerr, flop, x, y):
         ftype = type(x)
         try:
@@ -633,7 +680,7 @@ class TestFloatExceptions(object):
                 assert_("underflow" in str(w[-1].message))
 
 
-class TestTypes(object):
+class TestTypes:
     def check_promotion_cases(self, promote_func):
         # tests that the scalars get coerced correctly.
         b = np.bool_(0)
@@ -954,10 +1001,9 @@ class NIterError(Exception):
     pass
 
 
-class TestFromiter(object):
+class TestFromiter:
     def makegen(self):
-        for x in range(24):
-            yield x**2
+        return (x**2 for x in range(24))
 
     def test_types(self):
         ai32 = np.fromiter(self.makegen(), np.int32)
@@ -1005,7 +1051,7 @@ class TestFromiter(object):
                           self.load_data(count, eindex), dtype=int, count=count)
 
 
-class TestNonzero(object):
+class TestNonzero:
     def test_nonzero_trivial(self):
         assert_equal(np.count_nonzero(np.array([])), 0)
         assert_equal(np.count_nonzero(np.array([], dtype='?')), 0)
@@ -1201,6 +1247,17 @@ class TestNonzero(object):
         a = np.array([[0, 0, 1], [1, 0, 1]])
         assert_equal(np.count_nonzero(a, axis=()), a.astype(bool))
 
+    def test_countnonzero_keepdims(self):
+        a = np.array([[0, 0, 1, 0],
+                      [0, 3, 5, 0],
+                      [7, 9, 2, 0]])
+        assert_equal(np.count_nonzero(a, axis=0, keepdims=True),
+                     [[1, 2, 3, 0]])
+        assert_equal(np.count_nonzero(a, axis=1, keepdims=True),
+                     [[1], [2], [3]])
+        assert_equal(np.count_nonzero(a, keepdims=True),
+                     [[6]])
+
     def test_array_method(self):
         # Tests that the array method
         # call to nonzero works
@@ -1211,14 +1268,12 @@ class TestNonzero(object):
 
     def test_nonzero_invalid_object(self):
         # gh-9295
-        a = np.array([np.array([1, 2]), 3])
+        a = np.array([np.array([1, 2]), 3], dtype=object)
         assert_raises(ValueError, np.nonzero, a)
 
         class BoolErrors:
             def __bool__(self):
                 raise ValueError("Not allowed")
-            def __nonzero__(self):
-                raise ValueError("Not allowed")
 
         assert_raises(ValueError, np.nonzero, np.array([BoolErrors()]))
 
@@ -1288,7 +1343,7 @@ class TestNonzero(object):
         assert_raises(ValueError, np.nonzero, a)
 
 
-class TestIndex(object):
+class TestIndex:
     def test_boolean(self):
         a = rand(3, 5, 8)
         V = rand(5, 8)
@@ -1305,7 +1360,7 @@ class TestIndex(object):
         assert_equal(c.dtype, np.dtype('int32'))
 
 
-class TestBinaryRepr(object):
+class TestBinaryRepr:
     def test_zero(self):
         assert_equal(np.binary_repr(0), '0')
 
@@ -1347,7 +1402,7 @@ class TestBinaryRepr(object):
                      '11' + '0'*62)
 
 
-class TestBaseRepr(object):
+class TestBaseRepr:
     def test_base3(self):
         assert_equal(np.base_repr(3**5, 3), '100000')
 
@@ -1369,7 +1424,7 @@ class TestBaseRepr(object):
             np.base_repr(1, 37)
 
 
-class TestArrayComparisons(object):
+class TestArrayComparisons:
     def test_array_equal(self):
         res = np.array_equal(np.array([1, 2]), np.array([1, 2]))
         assert_(res)
@@ -1391,6 +1446,36 @@ class TestArrayComparisons(object):
         assert_(res)
         assert_(type(res) is bool)
 
+    def test_array_equal_equal_nan(self):
+        # Test array_equal with equal_nan kwarg
+        a1 = np.array([1, 2, np.nan])
+        a2 = np.array([1, np.nan, 2])
+        a3 = np.array([1, 2, np.inf])
+
+        # equal_nan=False by default
+        assert_(not np.array_equal(a1, a1))
+        assert_(np.array_equal(a1, a1, equal_nan=True))
+        assert_(not np.array_equal(a1, a2, equal_nan=True))
+        # nan's not conflated with inf's
+        assert_(not np.array_equal(a1, a3, equal_nan=True))
+        # 0-D arrays
+        a = np.array(np.nan)
+        assert_(not np.array_equal(a, a))
+        assert_(np.array_equal(a, a, equal_nan=True))
+        # Non-float dtype - equal_nan should have no effect
+        a = np.array([1, 2, 3], dtype=int)
+        assert_(np.array_equal(a, a))
+        assert_(np.array_equal(a, a, equal_nan=True))
+        # Multi-dimensional array
+        a = np.array([[0, 1], [np.nan, 1]])
+        assert_(not np.array_equal(a, a))
+        assert_(np.array_equal(a, a, equal_nan=True))
+        # Complex values
+        a, b = [np.array([1 + 1j])]*2
+        a.real, b.imag = np.nan, np.nan
+        assert_(not np.array_equal(a, b, equal_nan=False))
+        assert_(np.array_equal(a, b, equal_nan=True))
+
     def test_none_compares_elementwise(self):
         a = np.array([None, 1, None], dtype=object)
         assert_equal(a == None, [True, False, True])
@@ -1448,7 +1533,7 @@ def assert_array_strict_equal(x, y):
     assert_(x.dtype.isnative == y.dtype.isnative)
 
 
-class TestClip(object):
+class TestClip:
     def setup(self):
         self.nr = 5
         self.nc = 3
@@ -1884,7 +1969,7 @@ class TestClip(object):
         assert_array_strict_equal(ac, act)
 
     def test_clip_with_out_transposed(self):
-        # Test that the out argument works when tranposed
+        # Test that the out argument works when transposed
         a = np.arange(16).reshape(4, 4)
         out = np.empty_like(a).T
         a.clip(4, 10, out=out)
@@ -1993,20 +2078,22 @@ class TestClip(object):
         actual = np.clip(arr, amin, amax)
         assert_equal(actual, exp)
 
-    @pytest.mark.xfail(reason="no scalar nan propagation yet")
+    @pytest.mark.xfail(reason="no scalar nan propagation yet",
+                       raises=AssertionError,
+                       strict=True)
     @pytest.mark.parametrize("arr, amin, amax", [
         # problematic scalar nan case from hypothesis
         (np.zeros(10, dtype=np.int64),
          np.array(np.nan),
          np.zeros(10, dtype=np.int32)),
     ])
+    @pytest.mark.filterwarnings("ignore::DeprecationWarning")
     def test_clip_scalar_nan_propagation(self, arr, amin, amax):
         # enforcement of scalar nan propagation for comparisons
         # called through clip()
-        expected = np.minimum(np.maximum(a, amin), amax)
-        with assert_warns(DeprecationWarning):
-            actual = np.clip(arr, amin, amax)
-            assert_equal(actual, expected)
+        expected = np.minimum(np.maximum(arr, amin), amax)
+        actual = np.clip(arr, amin, amax)
+        assert_equal(actual, expected)
 
     @pytest.mark.xfail(reason="propagation doesn't match spec")
     @pytest.mark.parametrize("arr, amin, amax", [
@@ -2014,15 +2101,78 @@ class TestClip(object):
          np.timedelta64('NaT'),
          np.zeros(10, dtype=np.int32)),
     ])
+    @pytest.mark.filterwarnings("ignore::DeprecationWarning")
     def test_NaT_propagation(self, arr, amin, amax):
         # NOTE: the expected function spec doesn't
         # propagate NaT, but clip() now does
-        expected = np.minimum(np.maximum(a, amin), amax)
+        expected = np.minimum(np.maximum(arr, amin), amax)
         actual = np.clip(arr, amin, amax)
         assert_equal(actual, expected)
 
+    @given(data=st.data(), shape=hynp.array_shapes())
+    def test_clip_property(self, data, shape):
+        """A property-based test using Hypothesis.
+
+        This aims for maximum generality: it could in principle generate *any*
+        valid inputs to np.clip, and in practice generates much more varied
+        inputs than human testers come up with.
 
-class TestAllclose(object):
+        Because many of the inputs have tricky dependencies - compatible dtypes
+        and mutually-broadcastable shapes - we use `st.data()` strategy draw
+        values *inside* the test function, from strategies we construct based
+        on previous values.  An alternative would be to define a custom strategy
+        with `@st.composite`, but until we have duplicated code inline is fine.
+
+        That accounts for most of the function; the actual test is just three
+        lines to calculate and compare actual vs expected results!
+        """
+        # Our base array and bounds should not need to be of the same type as
+        # long as they are all compatible - so we allow any int or float type.
+        dtype_strategy = hynp.integer_dtypes() | hynp.floating_dtypes()
+
+        # The following line is a total hack to disable the varied-dtypes
+        # component of this test, because result != expected if dtypes can vary.
+        dtype_strategy = st.just(data.draw(dtype_strategy))
+
+        # Generate an arbitrary array of the chosen shape and dtype
+        # This is the value that we clip.
+        arr = data.draw(hynp.arrays(dtype=dtype_strategy, shape=shape))
+
+        # Generate shapes for the bounds which can be broadcast with each other
+        # and with the base shape.  Below, we might decide to use scalar bounds,
+        # but it's clearer to generate these shapes unconditionally in advance.
+        in_shapes, result_shape = data.draw(
+            hynp.mutually_broadcastable_shapes(
+                num_shapes=2,
+                base_shape=shape,
+                # Commenting out the min_dims line allows zero-dimensional arrays,
+                # and zero-dimensional arrays containing NaN make the test fail.
+                min_dims=1  
+                            
+            )
+        )
+        amin = data.draw(
+            dtype_strategy.flatmap(hynp.from_dtype)
+            | hynp.arrays(dtype=dtype_strategy, shape=in_shapes[0])
+        )
+        amax = data.draw(
+            dtype_strategy.flatmap(hynp.from_dtype)
+            | hynp.arrays(dtype=dtype_strategy, shape=in_shapes[1])
+        )
+        # If we allow either bound to be a scalar `nan`, the test will fail -
+        # so we just "assume" that away (if it is, this raises a special
+        # exception and Hypothesis will try again with different inputs)
+        assume(not np.isscalar(amin) or not np.isnan(amin))
+        assume(not np.isscalar(amax) or not np.isnan(amax))
+
+        # Then calculate our result and expected result and check that they're
+        # equal!  See gh-12519 for discussion deciding on this property.
+        result = np.clip(arr, amin, amax)
+        expected = np.minimum(amax, np.maximum(arr, amin))
+        assert_array_equal(result, expected)
+
+
+class TestAllclose:
     rtol = 1e-5
     atol = 1e-8
 
@@ -2107,7 +2257,7 @@ class TestAllclose(object):
         assert_(type(np.allclose(a, a)) is bool)
 
 
-class TestIsclose(object):
+class TestIsclose:
     rtol = 1e-5
     atol = 1e-8
 
@@ -2245,7 +2395,7 @@ class TestIsclose(object):
         assert_(type(np.isclose(0, np.inf)) is np.bool_)
 
 
-class TestStdVar(object):
+class TestStdVar:
     def setup(self):
         self.A = np.array([1, -1, 1, -1])
         self.real_var = 1
@@ -2284,7 +2434,7 @@ class TestStdVar(object):
         assert_array_equal(r, out)
 
 
-class TestStdVarComplex(object):
+class TestStdVarComplex:
     def test_basic(self):
         A = np.array([1, 1.j, -1, -1.j])
         real_var = 1
@@ -2296,7 +2446,7 @@ class TestStdVarComplex(object):
         assert_equal(np.std(1j), 0)
 
 
-class TestCreationFuncs(object):
+class TestCreationFuncs:
     # Test ones, zeros, empty and full.
 
     def setup(self):
@@ -2367,7 +2517,7 @@ class TestCreationFuncs(object):
         assert_(sys.getrefcount(dim) == beg)
 
 
-class TestLikeFuncs(object):
+class TestLikeFuncs:
     '''Test ones_like, zeros_like, empty_like and full_like'''
 
     def setup(self):
@@ -2394,7 +2544,7 @@ class TestLikeFuncs(object):
                 (np.arange(24).reshape(2, 3, 4).swapaxes(0, 1), None),
                 (np.arange(24).reshape(4, 3, 2).swapaxes(0, 1), '?'),
                      ]
-        self.shapes = [(5,), (5,6,), (5,6,7,)]
+        self.shapes = [(), (5,), (5,6,), (5,6,7,)]
 
     def compare_array_value(self, dz, value, fill_value):
         if value is not None:
@@ -2517,7 +2667,7 @@ class TestLikeFuncs(object):
         self.check_like_function(np.full_like, np.inf, True)
 
 
-class TestCorrelate(object):
+class TestCorrelate:
     def _setup(self, dt):
         self.x = np.array([1, 2, 3, 4, 5], dtype=dt)
         self.xs = np.arange(1, 20)[::3]
@@ -2573,7 +2723,7 @@ class TestCorrelate(object):
         with pytest.raises(ValueError):
             np.correlate(np.ones(1000), np.array([]), mode='full')
 
-class TestConvolve(object):
+class TestConvolve:
     def test_object(self):
         d = [1.] * 100
         k = [1.] * 3
@@ -2587,7 +2737,7 @@ class TestConvolve(object):
         assert_array_equal(k, np.ones(3))
 
 
-class TestArgwhere(object):
+class TestArgwhere:
 
     @pytest.mark.parametrize('nd', [0, 1, 2])
     def test_nd(self, nd):
@@ -2624,7 +2774,7 @@ class TestArgwhere(object):
         assert_equal(np.argwhere([4, 0, 2, 1, 3]), [[0], [2], [3], [4]])
 
 
-class TestStringFunction(object):
+class TestStringFunction:
 
     def test_set_string_function(self):
         a = np.array([1])
@@ -2639,7 +2789,7 @@ class TestStringFunction(object):
         assert_equal(str(a), "[1]")
 
 
-class TestRoll(object):
+class TestRoll:
     def test_roll1d(self):
         x = np.arange(10)
         xr = np.roll(x, 2)
@@ -2697,7 +2847,7 @@ class TestRoll(object):
         assert_equal(np.roll(x, 1), np.array([]))
 
 
-class TestRollaxis(object):
+class TestRollaxis:
 
     # expected shape indexed by (axis, start) for array of
     # shape (1, 2, 3, 4)
@@ -2759,7 +2909,7 @@ class TestRollaxis(object):
             assert_(not res.flags['OWNDATA'])
 
 
-class TestMoveaxis(object):
+class TestMoveaxis:
     def test_move_to_end(self):
         x = np.random.randn(5, 6, 7)
         for source, expected in [(0, (6, 7, 5)),
@@ -2833,7 +2983,7 @@ class TestMoveaxis(object):
         assert_(isinstance(result, np.ndarray))
 
 
-class TestCross(object):
+class TestCross:
     def test_2x2(self):
         u = [1, 2]
         v = [3, 4]
@@ -2922,7 +3072,7 @@ def test_outer_out_param():
     assert_equal(np.outer(arr2, arr3, out2), out2)
 
 
-class TestIndices(object):
+class TestIndices:
 
     def test_simple(self):
         [x, y] = np.indices((4, 3))
@@ -2963,7 +3113,7 @@ class TestIndices(object):
             assert_(arr.dtype == dtype)
 
 
-class TestRequire(object):
+class TestRequire:
     flag_names = ['C', 'C_CONTIGUOUS', 'CONTIGUOUS',
                   'F', 'F_CONTIGUOUS', 'FORTRAN',
                   'A', 'ALIGNED',
@@ -3037,7 +3187,7 @@ class TestRequire(object):
             self.set_and_check_flag(flag, None, a)
 
 
-class TestBroadcast(object):
+class TestBroadcast:
     def test_broadcast_in_args(self):
         # gh-5881
         arrs = [np.empty((6, 7)), np.empty((5, 6, 1)), np.empty((7,)),
@@ -3088,7 +3238,7 @@ class TestBroadcast(object):
 
         assert_raises(ValueError, np.broadcast, 1, **{'x': 1})
 
-class TestKeepdims(object):
+class TestKeepdims:
 
     class sub_array(np.ndarray):
         def sum(self, axis=None, dtype=None, out=None):
@@ -3100,7 +3250,7 @@ class TestKeepdims(object):
         assert_raises(TypeError, np.sum, x, keepdims=True)
 
 
-class TestTensordot(object):
+class TestTensordot:
 
     def test_zero_dimension(self):
         # Test resolution to issue #5663
index 387740e357070af1bdc7308f16054d635eb57f5d..9cb00342dd0c7a9dadd8819f09c32bc0e618bf06 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import itertools
 
@@ -100,7 +98,7 @@ def normalize_descr(descr):
 #    Creation tests
 ############################################################
 
-class CreateZeros(object):
+class CreateZeros:
     """Check the creation of heterogeneous arrays zero-valued"""
 
     def test_zeros0D(self):
@@ -143,7 +141,7 @@ class TestCreateZerosNested(CreateZeros):
     _descr = Ndescr
 
 
-class CreateValues(object):
+class CreateValues:
     """Check the creation of heterogeneous arrays with values"""
 
     def test_tuple(self):
@@ -203,7 +201,7 @@ class TestCreateValuesNestedMultiple(CreateValues):
 #    Reading tests
 ############################################################
 
-class ReadValuesPlain(object):
+class ReadValuesPlain:
     """Check the reading of values in heterogeneous arrays (plain)"""
 
     def test_access_fields(self):
@@ -235,7 +233,7 @@ class TestReadValuesPlainMultiple(ReadValuesPlain):
     multiple_rows = 1
     _buffer = PbufferT
 
-class ReadValuesNested(object):
+class ReadValuesNested:
     """Check the reading of values in heterogeneous arrays (nested)"""
 
     def test_access_top_fields(self):
@@ -308,10 +306,7 @@ class ReadValuesNested(object):
         h = np.array(self._buffer, dtype=self._descr)
         assert_(h.dtype['Info']['value'].name == 'complex128')
         assert_(h.dtype['Info']['y2'].name == 'float64')
-        if sys.version_info[0] >= 3:
-            assert_(h.dtype['info']['Name'].name == 'str256')
-        else:
-            assert_(h.dtype['info']['Name'].name == 'unicode256')
+        assert_(h.dtype['info']['Name'].name == 'str256')
         assert_(h.dtype['info']['Value'].name == 'complex128')
 
     def test_nested2_descriptor(self):
@@ -333,14 +328,14 @@ class TestReadValuesNestedMultiple(ReadValuesNested):
     multiple_rows = True
     _buffer = NbufferT
 
-class TestEmptyField(object):
+class TestEmptyField:
     def test_assign(self):
         a = np.arange(10, dtype=np.float32)
         a.dtype = [("int",   "<0i4"), ("float", "<2f4")]
         assert_(a['int'].shape == (5, 0))
         assert_(a['float'].shape == (5, 2))
 
-class TestCommonType(object):
+class TestCommonType:
     def test_scalar_loses1(self):
         res = np.find_common_type(['f4', 'f4', 'i2'], ['f8'])
         assert_(res == 'f4')
@@ -361,7 +356,7 @@ class TestCommonType(object):
         res = np.find_common_type(['u8', 'i8', 'i8'], ['f8'])
         assert_(res == 'f8')
 
-class TestMultipleFields(object):
+class TestMultipleFields:
     def setup(self):
         self.ary = np.array([(1, 2, 3, 4), (5, 6, 7, 8)], dtype='i4,f4,i2,c8')
 
@@ -376,7 +371,7 @@ class TestMultipleFields(object):
         assert_(res == [(1, 3), (5, 7)])
 
 
-class TestIsSubDType(object):
+class TestIsSubDType:
     # scalar types can be promoted into dtypes
     wrappers = [np.dtype, lambda x: x]
 
@@ -406,19 +401,48 @@ class TestIsSubDType(object):
             assert_(not np.issubdtype(w1(np.float32), w2(np.float64)))
             assert_(not np.issubdtype(w1(np.float64), w2(np.float32)))
 
-
-class TestSctypeDict(object):
+    def test_nondtype_nonscalartype(self):
+        # See gh-14619 and gh-9505 which introduced the deprecation to fix
+        # this. These tests are directly taken from gh-9505
+        assert not np.issubdtype(np.float32, 'float64')
+        assert not np.issubdtype(np.float32, 'f8')
+        assert not np.issubdtype(np.int32, str)
+        assert not np.issubdtype(np.int32, 'int64')
+        assert not np.issubdtype(np.str_, 'void')
+        # for the following the correct spellings are
+        # np.integer, np.floating, or np.complexfloating respectively:
+        assert not np.issubdtype(np.int8, int)  # np.int8 is never np.int_
+        assert not np.issubdtype(np.float32, float)
+        assert not np.issubdtype(np.complex64, complex)
+        assert not np.issubdtype(np.float32, "float")
+        assert not np.issubdtype(np.float64, "f")
+
+        # Test the same for the correct first datatype and abstract one
+        # in the case of int, float, complex:
+        assert np.issubdtype(np.float64, 'float64')
+        assert np.issubdtype(np.float64, 'f8')
+        assert np.issubdtype(np.str_, str)
+        assert np.issubdtype(np.int64, 'int64')
+        assert np.issubdtype(np.void, 'void')
+        assert np.issubdtype(np.int8, np.integer)
+        assert np.issubdtype(np.float32, np.floating)
+        assert np.issubdtype(np.complex64, np.complexfloating)
+        assert np.issubdtype(np.float64, "float")
+        assert np.issubdtype(np.float32, "f")
+
+
+class TestSctypeDict:
     def test_longdouble(self):
         assert_(np.sctypeDict['f8'] is not np.longdouble)
         assert_(np.sctypeDict['c16'] is not np.clongdouble)
 
 
-class TestBitName(object):
+class TestBitName:
     def test_abstract(self):
         assert_raises(ValueError, np.core.numerictypes.bitname, np.floating)
 
 
-class TestMaximumSctype(object):
+class TestMaximumSctype:
 
     # note that parametrizing with sctype['int'] and similar would skip types
     # with the same size (gh-11923)
@@ -444,7 +468,7 @@ class TestMaximumSctype(object):
         assert_equal(np.maximum_sctype(t), t)
 
 
-class Test_sctype2char(object):
+class Test_sctype2char:
     # This function is old enough that we're really just documenting the quirks
     # at this point.
 
@@ -491,8 +515,9 @@ def test_issctype(rep, expected):
 
 @pytest.mark.skipif(sys.flags.optimize > 1,
                     reason="no docstrings present to inspect when PYTHONOPTIMIZE/Py_OptimizeFlag > 1")
-@pytest.mark.xfail(IS_PYPY, reason="PyPy does not modify tp_doc")
-class TestDocStrings(object):
+@pytest.mark.xfail(IS_PYPY,
+                   reason="PyPy cannot modify tp_doc after PyType_Ready")
+class TestDocStrings:
     def test_platform_dependent_aliases(self):
         if np.int64 is np.int_:
             assert_('int64' in np.int_.__doc__)
index 63b0e4539e9e0b30f18723ce4ad374967055c965..7e73d8c03264068eb84ada656be41a88364e2c9a 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import inspect
 import sys
 from unittest import mock
@@ -36,7 +34,7 @@ def dispatched_two_arg(array1, array2):
     return 'original'
 
 
-class TestGetImplementingArgs(object):
+class TestGetImplementingArgs:
 
     def test_ndarray(self):
         array = np.array(1)
@@ -77,7 +75,7 @@ class TestGetImplementingArgs(object):
 
     def test_ndarray_and_duck_array(self):
 
-        class Other(object):
+        class Other:
             __array_function__ = _return_not_implemented
 
         array = np.array(1)
@@ -94,7 +92,7 @@ class TestGetImplementingArgs(object):
         class OverrideSub(np.ndarray):
             __array_function__ = _return_not_implemented
 
-        class Other(object):
+        class Other:
             __array_function__ = _return_not_implemented
 
         array = np.array(1)
@@ -108,7 +106,7 @@ class TestGetImplementingArgs(object):
 
     def test_many_duck_arrays(self):
 
-        class A(object):
+        class A:
             __array_function__ = _return_not_implemented
 
         class B(A):
@@ -117,7 +115,7 @@ class TestGetImplementingArgs(object):
         class C(A):
             __array_function__ = _return_not_implemented
 
-        class D(object):
+        class D:
             __array_function__ = _return_not_implemented
 
         a = A()
@@ -147,12 +145,12 @@ class TestGetImplementingArgs(object):
             _get_implementing_args(relevant_args)
 
 
-class TestNDArrayArrayFunction(object):
+class TestNDArrayArrayFunction:
 
     @requires_array_function
     def test_method(self):
 
-        class Other(object):
+        class Other:
             __array_function__ = _return_not_implemented
 
         class NoOverrideSub(np.ndarray):
@@ -209,7 +207,7 @@ class TestNDArrayArrayFunction(object):
 
 
 @requires_array_function
-class TestArrayFunctionDispatch(object):
+class TestArrayFunctionDispatch:
 
     def test_pickle(self):
         for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
@@ -224,7 +222,7 @@ class TestArrayFunctionDispatch(object):
 
     def test_interface(self):
 
-        class MyArray(object):
+        class MyArray:
             def __array_function__(self, func, types, args, kwargs):
                 return (self, func, types, args, kwargs)
 
@@ -239,7 +237,7 @@ class TestArrayFunctionDispatch(object):
 
     def test_not_implemented(self):
 
-        class MyArray(object):
+        class MyArray:
             def __array_function__(self, func, types, args, kwargs):
                 return NotImplemented
 
@@ -249,7 +247,7 @@ class TestArrayFunctionDispatch(object):
 
 
 @requires_array_function
-class TestVerifyMatchingSignatures(object):
+class TestVerifyMatchingSignatures:
 
     def test_verify_matching_signatures(self):
 
@@ -283,7 +281,7 @@ def _new_duck_type_and_implements():
     """Create a duck array type and implements functions."""
     HANDLED_FUNCTIONS = {}
 
-    class MyArray(object):
+    class MyArray:
         def __array_function__(self, func, types, args, kwargs):
             if func not in HANDLED_FUNCTIONS:
                 return NotImplemented
@@ -302,7 +300,7 @@ def _new_duck_type_and_implements():
 
 
 @requires_array_function
-class TestArrayFunctionImplementation(object):
+class TestArrayFunctionImplementation:
 
     def test_one_arg(self):
         MyArray, implements = _new_duck_type_and_implements()
@@ -355,7 +353,7 @@ class TestArrayFunctionImplementation(object):
             func(MyArray())
 
 
-class TestNDArrayMethods(object):
+class TestNDArrayMethods:
 
     def test_repr(self):
         # gh-12162: should still be defined even if __array_function__ doesn't
@@ -370,7 +368,7 @@ class TestNDArrayMethods(object):
         assert_equal(str(array), '1')
 
 
-class TestNumPyFunctions(object):
+class TestNumPyFunctions:
 
     def test_set_module(self):
         assert_equal(np.sum.__module__, 'numpy')
index c5c091e13ac84356ff52a0d4bb35b6115611b15e..89a8b48bfdee058299aacb6a58e38151455cd05d 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 
 import pytest
@@ -9,10 +7,7 @@ from numpy.testing import assert_, assert_equal
 from numpy.core.tests._locales import CommaDecimalPointLocale
 
 
-if sys.version_info[0] >= 3:
-    from io import StringIO
-else:
-    from StringIO import StringIO
+from io import StringIO
 
 _REF = {np.inf: 'inf', -np.inf: '-inf', np.nan: 'nan'}
 
diff --git a/numpy/core/tests/test_protocols.py b/numpy/core/tests/test_protocols.py
new file mode 100644 (file)
index 0000000..55a2bcf
--- /dev/null
@@ -0,0 +1,44 @@
+import pytest
+import warnings
+import numpy as np
+
+
+@pytest.mark.filterwarnings("error")
+def test_getattr_warning():
+    # issue gh-14735: make sure we clear only getattr errors, and let warnings
+    # through
+    class Wrapper:
+        def __init__(self, array):
+            self.array = array
+
+        def __len__(self):
+            return len(self.array)
+
+        def __getitem__(self, item):
+            return type(self)(self.array[item])
+
+        def __getattr__(self, name):
+            if name.startswith("__array_"):
+                warnings.warn("object got converted", UserWarning, stacklevel=1)
+
+            return getattr(self.array, name)
+
+        def __repr__(self):
+            return "<Wrapper({self.array})>".format(self=self)
+
+    array = Wrapper(np.arange(10))
+    with pytest.raises(UserWarning, match="object got converted"):
+        np.asarray(array)
+
+
+def test_array_called():
+    class Wrapper:
+        val = '0' * 100
+        def __array__(self, result=None):
+            return np.array([self.val], dtype=object)
+
+
+    wrapped = Wrapper()
+    arr = np.array(wrapped, dtype=str)
+    assert arr.dtype == 'U100'
+    assert arr[0] == Wrapper.val
index c1b794145d1974648cfa9f0f6c0aad0ae629e713..4350a3407c797495075547d7ea61756958bac9e6 100644 (file)
@@ -1,37 +1,25 @@
-from __future__ import division, absolute_import, print_function
-
-import sys
-try:
-    # Accessing collections abstract classes from collections
-    # has been deprecated since Python 3.3
-    import collections.abc as collections_abc
-except ImportError:
-    import collections as collections_abc
+import collections.abc
 import textwrap
 from os import path
+from pathlib import Path
 import pytest
 
 import numpy as np
-from numpy.compat import Path
 from numpy.testing import (
     assert_, assert_equal, assert_array_equal, assert_array_almost_equal,
-    assert_raises, temppath
+    assert_raises, temppath,
     )
 from numpy.compat import pickle
 
 
-class TestFromrecords(object):
+class TestFromrecords:
     def test_fromrecords(self):
         r = np.rec.fromrecords([[456, 'dbe', 1.2], [2, 'de', 1.3]],
                             names='col1,col2,col3')
         assert_equal(r[0].item(), (456, 'dbe', 1.2))
         assert_equal(r['col1'].dtype.kind, 'i')
-        if sys.version_info[0] >= 3:
-            assert_equal(r['col2'].dtype.kind, 'U')
-            assert_equal(r['col2'].dtype.itemsize, 12)
-        else:
-            assert_equal(r['col2'].dtype.kind, 'S')
-            assert_equal(r['col2'].dtype.itemsize, 3)
+        assert_equal(r['col2'].dtype.kind, 'U')
+        assert_equal(r['col2'].dtype.itemsize, 12)
         assert_equal(r['col3'].dtype.kind, 'f')
 
     def test_fromrecords_0len(self):
@@ -258,7 +246,7 @@ class TestFromrecords(object):
         assert_array_equal(ra['shape'], [['A', 'B', 'C']])
         ra.field = 5
         assert_array_equal(ra['field'], [[5, 5, 5]])
-        assert_(isinstance(ra.field, collections_abc.Callable))
+        assert_(isinstance(ra.field, collections.abc.Callable))
 
     def test_fromrecords_with_explicit_dtype(self):
         a = np.rec.fromrecords([(1, 'a'), (2, 'bbb')],
@@ -325,8 +313,7 @@ class TestFromrecords(object):
         assert_equal(rec['f1'], [b'', b'', b''])
 
 
-@pytest.mark.skipif(Path is None, reason="No pathlib.Path")
-class TestPathUsage(object):
+class TestPathUsage:
     # Test that pathlib.Path can be used
     def test_tofile_fromfile(self):
         with temppath(suffix='.bin') as path:
@@ -342,7 +329,7 @@ class TestPathUsage(object):
             assert_array_equal(x, a)
 
 
-class TestRecord(object):
+class TestRecord:
     def setup(self):
         self.data = np.rec.fromrecords([(1, 2, 3), (4, 5, 6)],
                             dtype=[("col1", "<i4"),
@@ -416,6 +403,22 @@ class TestRecord(object):
             assert_(pa.flags.writeable)
             assert_(pa.flags.aligned)
 
+    def test_pickle_void(self):
+        # issue gh-13593
+        dt = np.dtype([('obj', 'O'), ('int', 'i')])
+        a = np.empty(1, dtype=dt)
+        data = (bytearray(b'eman'),)
+        a['obj'] = data
+        a['int'] = 42
+        ctor, args = a[0].__reduce__()
+        # check the constructor is what we expect before interpreting the arguments
+        assert ctor is np.core.multiarray.scalar
+        dtype, obj = args
+        # make sure we did not pickle the address
+        assert not isinstance(obj, bytes)
+
+        assert_raises(TypeError, ctor, dtype, 13)
+
     def test_objview_record(self):
         # https://github.com/numpy/numpy/issues/2599
         dt = np.dtype([('foo', 'i8'), ('bar', 'O')])
index f2d3d788dd3832344745a1290f81900dda8b1eaf..96a6d810fb7d039a66ed8dfe55c9a48db923dacd 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import copy
 import sys
 import gc
@@ -17,14 +15,14 @@ from numpy.testing import (
         _assert_valid_refcount, HAS_REFCOUNT,
         )
 from numpy.testing._private.utils import _no_tracing
-from numpy.compat import asbytes, asunicode, long, pickle
+from numpy.compat import asbytes, asunicode, pickle
 
 try:
     RecursionError
 except NameError:
     RecursionError = RuntimeError  # python < 3.5
 
-class TestRegression(object):
+class TestRegression:
     def test_invalid_round(self):
         # Ticket #3
         v = 4.7599999999999998
@@ -38,11 +36,10 @@ class TestRegression(object):
         # Ticket #16
         a = np.transpose(np.array([[2, 9], [7, 0], [3, 8]]))
         for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
-            f = BytesIO()
-            pickle.dump(a, f, protocol=proto)
-            f.seek(0)
-            b = pickle.load(f)
-            f.close()
+            with BytesIO() as f:
+                pickle.dump(a, f, protocol=proto)
+                f.seek(0)
+                b = pickle.load(f)
             assert_array_equal(a, b)
 
     def test_typeNA(self):
@@ -96,11 +93,10 @@ class TestRegression(object):
         # Ticket #50
         ca = np.char.array(np.arange(1000, 1010), itemsize=4)
         for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
-            f = BytesIO()
-            pickle.dump(ca, f, protocol=proto)
-            f.seek(0)
-            ca = np.load(f, allow_pickle=True)
-            f.close()
+            with BytesIO() as f:
+                pickle.dump(ca, f, protocol=proto)
+                f.seek(0)
+                ca = np.load(f, allow_pickle=True)
 
     def test_noncontiguous_fill(self):
         # Ticket #58.
@@ -360,11 +356,10 @@ class TestRegression(object):
         # Implemented in r2840
         dt = np.dtype([('x', int), ('y', np.object_), ('z', 'O')])
         for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
-            f = BytesIO()
-            pickle.dump(dt, f, protocol=proto)
-            f.seek(0)
-            dt_ = pickle.load(f)
-            f.close()
+            with BytesIO() as f:
+                pickle.dump(dt, f, protocol=proto)
+                f.seek(0)
+                dt_ = pickle.load(f)
             assert_equal(dt, dt_)
 
     def test_mem_array_creation_invalid_specification(self):
@@ -428,7 +423,7 @@ class TestRegression(object):
 
     def test_lexsort_invalid_sequence(self):
         # Issue gh-4123
-        class BuggySequence(object):
+        class BuggySequence:
             def __len__(self):
                 return 4
 
@@ -457,6 +452,11 @@ class TestRegression(object):
         xs.strides = (16, 16)
         assert np.lexsort((xs,), axis=0).shape[0] == 2
 
+    def test_lexsort_invalid_axis(self):
+        assert_raises(np.AxisError, np.lexsort, (np.arange(1),), axis=2)
+        assert_raises(np.AxisError, np.lexsort, (np.array([]),), axis=1)
+        assert_raises(np.AxisError, np.lexsort, (np.array(1),), axis=10)
+
     def test_lexsort_zerolen_element(self):
         dt = np.dtype([])  # a void dtype with no fields
         xs = np.empty(4, dt)
@@ -489,15 +489,13 @@ class TestRegression(object):
              b"bI00\nS'O\\x81\\xb7Z\\xaa:\\xabY'\np22\ntp23\nb."),
         ]
 
-        if sys.version_info[:2] >= (3, 4):
-            # encoding='bytes' was added in Py3.4
-            for original, data in test_data:
-                result = pickle.loads(data, encoding='bytes')
-                assert_equal(result, original)
+        for original, data in test_data:
+            result = pickle.loads(data, encoding='bytes')
+            assert_equal(result, original)
 
-                if isinstance(result, np.ndarray) and result.dtype.names is not None:
-                    for name in result.dtype.names:
-                        assert_(isinstance(name, str))
+            if isinstance(result, np.ndarray) and result.dtype.names is not None:
+                for name in result.dtype.names:
+                    assert_(isinstance(name, str))
 
     def test_pickle_dtype(self):
         # Ticket #251
@@ -1041,7 +1039,7 @@ class TestRegression(object):
 
     def test_mem_custom_float_to_array(self):
         # Ticket 702
-        class MyFloat(object):
+        class MyFloat:
             def __float__(self):
                 return 1.0
 
@@ -1050,7 +1048,7 @@ class TestRegression(object):
 
     def test_object_array_refcount_self_assign(self):
         # Ticket #711
-        class VictimObject(object):
+        class VictimObject:
             deleted = False
 
             def __del__(self):
@@ -1108,14 +1106,8 @@ class TestRegression(object):
         # The dtype is float64, but the isbuiltin attribute is 0.
         data_dir = path.join(path.dirname(__file__), 'data')
         filename = path.join(data_dir, "astype_copy.pkl")
-        if sys.version_info[0] >= 3:
-            f = open(filename, 'rb')
+        with open(filename, 'rb') as f:
             xp = pickle.load(f, encoding='latin1')
-            f.close()
-        else:
-            f = open(filename)
-            xp = pickle.load(f)
-            f.close()
         xpd = xp.astype(np.float64)
         assert_((xp.__array_interface__['data'][0] !=
                 xpd.__array_interface__['data'][0]))
@@ -1232,10 +1224,7 @@ class TestRegression(object):
             msg = 'unicode offset: %d chars' % i
             t = np.dtype([('a', 'S%d' % i), ('b', 'U2')])
             x = np.array([(b'a', u'b')], dtype=t)
-            if sys.version_info[0] >= 3:
-                assert_equal(str(x), "[(b'a', 'b')]", err_msg=msg)
-            else:
-                assert_equal(str(x), "[('a', u'b')]", err_msg=msg)
+            assert_equal(str(x), "[(b'a', 'b')]", err_msg=msg)
 
     def test_sign_for_complex_nan(self):
         # Ticket 794.
@@ -1367,13 +1356,13 @@ class TestRegression(object):
     def test_array_from_sequence_scalar_array(self):
         # Ticket #1078: segfaults when creating an array with a sequence of
         # 0d arrays.
-        a = np.array((np.ones(2), np.array(2)))
+        a = np.array((np.ones(2), np.array(2)), dtype=object)
         assert_equal(a.shape, (2,))
         assert_equal(a.dtype, np.dtype(object))
         assert_equal(a[0], np.ones(2))
         assert_equal(a[1], np.array(2))
 
-        a = np.array(((1,), np.array(1)))
+        a = np.array(((1,), np.array(1)), dtype=object)
         assert_equal(a.shape, (2,))
         assert_equal(a.dtype, np.dtype(object))
         assert_equal(a[0], (1,))
@@ -1381,7 +1370,7 @@ class TestRegression(object):
 
     def test_array_from_sequence_scalar_array2(self):
         # Ticket #1081: weird array with strange input...
-        t = np.array([np.array([]), np.array(0, object)])
+        t = np.array([np.array([]), np.array(0, object)], dtype=object)
         assert_equal(t.shape, (2,))
         assert_equal(t.dtype, np.dtype(object))
 
@@ -1424,6 +1413,13 @@ class TestRegression(object):
                      dtype='U')
         assert_raises(UnicodeEncodeError, np.array, a, 'S4')
 
+    def test_unicode_to_string_cast_error(self):
+        # gh-15790
+        a = np.array([u'\x80'] * 129, dtype='U3')
+        assert_raises(UnicodeEncodeError, np.array, a, 'S')
+        b = a.reshape(3, 43)[:-1, :-1]
+        assert_raises(UnicodeEncodeError, np.array, b, 'S')
+
     def test_mixed_string_unicode_array_creation(self):
         a = np.array(['1234', u'123'])
         assert_(a.itemsize == 16)
@@ -1513,14 +1509,11 @@ class TestRegression(object):
             min //= -1
 
         with np.errstate(divide="ignore"):
-            for t in (np.int8, np.int16, np.int32, np.int64, int, np.compat.long):
+            for t in (np.int8, np.int16, np.int32, np.int64, int):
                 test_type(t)
 
     def test_buffer_hashlib(self):
-        try:
-            from hashlib import md5
-        except ImportError:
-            from md5 import new as md5
+        from hashlib import md5
 
         x = np.array([1, 2, 3], dtype=np.dtype('<i4'))
         assert_equal(md5(x).hexdigest(), '2a1dd1e1e59d0a384c26951e316cd7e6')
@@ -1815,13 +1808,7 @@ class TestRegression(object):
         a = np.array(0, dtype=object)
         a[()] = a
         assert_raises(RecursionError, int, a)
-        assert_raises(RecursionError, long, a)
         assert_raises(RecursionError, float, a)
-        if sys.version_info.major == 2:
-            # in python 3, this falls back on operator.index, which fails on
-            # on dtype=object
-            assert_raises(RecursionError, oct, a)
-            assert_raises(RecursionError, hex, a)
         a[()] = None
 
     def test_object_array_circular_reference(self):
@@ -1846,13 +1833,7 @@ class TestRegression(object):
         b = np.array(0, dtype=object)
         a[()] = b
         assert_equal(int(a), int(0))
-        assert_equal(long(a), long(0))
         assert_equal(float(a), float(0))
-        if sys.version_info.major == 2:
-            # in python 3, this falls back on operator.index, which fails on
-            # on dtype=object
-            assert_equal(oct(a), oct(0))
-            assert_equal(hex(a), hex(0))
 
     def test_object_array_self_copy(self):
         # An object array being copied into itself DECREF'ed before INCREF'ing
@@ -1956,13 +1937,12 @@ class TestRegression(object):
         assert_equal(s[0], "\x01")
 
     def test_pickle_bytes_overwrite(self):
-        if sys.version_info[0] >= 3:
-            for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
-                data = np.array([1], dtype='b')
-                data = pickle.loads(pickle.dumps(data, protocol=proto))
-                data[0] = 0xdd
-                bytestring = "\x01  ".encode('ascii')
-                assert_equal(bytestring[0:1], '\x01'.encode('ascii'))
+        for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
+            data = np.array([1], dtype='b')
+            data = pickle.loads(pickle.dumps(data, protocol=proto))
+            data[0] = 0xdd
+            bytestring = "\x01  ".encode('ascii')
+            assert_equal(bytestring[0:1], '\x01'.encode('ascii'))
 
     def test_pickle_py2_array_latin1_hack(self):
         # Check that unpickling hacks in Py3 that support
@@ -1973,12 +1953,11 @@ class TestRegression(object):
                 b"tp2\nS'b'\np3\ntp4\nRp5\n(I1\n(I1\ntp6\ncnumpy\ndtype\np7\n(S'i1'\np8\n"
                 b"I0\nI1\ntp9\nRp10\n(I3\nS'|'\np11\nNNNI-1\nI-1\nI0\ntp12\nbI00\nS'\\x81'\n"
                 b"p13\ntp14\nb.")
-        if sys.version_info[0] >= 3:
-            # This should work:
-            result = pickle.loads(data, encoding='latin1')
-            assert_array_equal(result, np.array([129], dtype='b'))
-            # Should not segfault:
-            assert_raises(Exception, pickle.loads, data, encoding='koi8-r')
+        # This should work:
+        result = pickle.loads(data, encoding='latin1')
+        assert_array_equal(result, np.array([129], dtype='b'))
+        # Should not segfault:
+        assert_raises(Exception, pickle.loads, data, encoding='koi8-r')
 
     def test_pickle_py2_scalar_latin1_hack(self):
         # Check that scalar unpickling hack in Py3 that supports
@@ -2005,25 +1984,24 @@ class TestRegression(object):
               b"tp8\nRp9\n."),
              'different'),
         ]
-        if sys.version_info[0] >= 3:
-            for original, data, koi8r_validity in datas:
-                result = pickle.loads(data, encoding='latin1')
-                assert_equal(result, original)
-
-                # Decoding under non-latin1 encoding (e.g.) KOI8-R can
-                # produce bad results, but should not segfault.
-                if koi8r_validity == 'different':
-                    # Unicode code points happen to lie within latin1,
-                    # but are different in koi8-r, resulting to silent
-                    # bogus results
-                    result = pickle.loads(data, encoding='koi8-r')
-                    assert_(result != original)
-                elif koi8r_validity == 'invalid':
-                    # Unicode code points outside latin1, so results
-                    # to an encoding exception
-                    assert_raises(ValueError, pickle.loads, data, encoding='koi8-r')
-                else:
-                    raise ValueError(koi8r_validity)
+        for original, data, koi8r_validity in datas:
+            result = pickle.loads(data, encoding='latin1')
+            assert_equal(result, original)
+
+            # Decoding under non-latin1 encoding (e.g.) KOI8-R can
+            # produce bad results, but should not segfault.
+            if koi8r_validity == 'different':
+                # Unicode code points happen to lie within latin1,
+                # but are different in koi8-r, resulting to silent
+                # bogus results
+                result = pickle.loads(data, encoding='koi8-r')
+                assert_(result != original)
+            elif koi8r_validity == 'invalid':
+                # Unicode code points outside latin1, so results
+                # to an encoding exception
+                assert_raises(ValueError, pickle.loads, data, encoding='koi8-r')
+            else:
+                raise ValueError(koi8r_validity)
 
     def test_structured_type_to_object(self):
         a_rec = np.array([(0, 1), (3, 2)], dtype='i4,i8')
@@ -2057,6 +2035,7 @@ class TestRegression(object):
         a[...] = [[1, 2]]
         assert_equal(a, [[1, 2], [1, 2]])
 
+    @pytest.mark.slow_pypy
     def test_memoryleak(self):
         # Ticket #1917 - ensure that array data doesn't leak
         for i in range(1000):
@@ -2096,10 +2075,7 @@ class TestRegression(object):
         # Ticket #2081. Python compiled with two byte unicode
         # can lead to truncation if itemsize is not properly
         # adjusted for NumPy's four byte unicode.
-        if sys.version_info[0] >= 3:
-            a = np.array(['abcd'])
-        else:
-            a = np.array([u'abcd'])
+        a = np.array(['abcd'])
         assert_equal(a.dtype.itemsize, 16)
 
     def test_unique_stable(self):
@@ -2233,7 +2209,7 @@ class TestRegression(object):
         import operator as op
 
         # dummy class where __array__ throws exception
-        class Foo(object):
+        class Foo:
             __array_priority__ = 1002
 
             def __array__(self, *args, **kwargs):
@@ -2242,12 +2218,7 @@ class TestRegression(object):
         rhs = Foo()
         lhs = np.array(1)
         for f in [op.lt, op.le, op.gt, op.ge]:
-            if sys.version_info[0] >= 3:
-                assert_raises(TypeError, f, lhs, rhs)
-            elif not sys.py3kwarning:
-                # With -3 switch in python 2, DeprecationWarning is raised
-                # which we are not interested in
-                f(lhs, rhs)
+            assert_raises(TypeError, f, lhs, rhs)
         assert_(not op.eq(lhs, rhs))
         assert_(op.ne(lhs, rhs))
 
@@ -2290,9 +2261,10 @@ class TestRegression(object):
             x[0], x[-1] = x[-1], x[0]
 
         uf = np.frompyfunc(f, 1, 0)
-        a = np.array([[1, 2, 3], [4, 5], [6, 7, 8, 9]])
+        a = np.array([[1, 2, 3], [4, 5], [6, 7, 8, 9]], dtype=object)
         assert_equal(uf(a), ())
-        assert_array_equal(a, [[3, 2, 1], [5, 4], [9, 7, 8, 6]])
+        expected = np.array([[3, 2, 1], [5, 4], [9, 7, 8, 6]], dtype=object)
+        assert_array_equal(a, expected)
 
     @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
     def test_leak_in_structured_dtype_comparison(self):
@@ -2467,8 +2439,11 @@ class TestRegression(object):
         x = np.array([1, 2, 4, 7, 0], dtype=np.int16)
         res = np.ediff1d(x, to_begin=-99, to_end=np.array([88, 99]))
         assert_equal(res, [-99,   1,   2,   3,  -7,  88,  99])
-        assert_raises(ValueError, np.ediff1d, x, to_begin=(1<<20))
-        assert_raises(ValueError, np.ediff1d, x, to_end=(1<<20))
+
+        # The use of safe casting means, that 1<<20 is cast unsafely, an
+        # error may be better, but currently there is no mechanism for it.
+        res = np.ediff1d(x, to_begin=(1<<20), to_end=(1<<20))
+        assert_equal(res, [0,   1,   2,   3,  -7,  0])
 
     def test_pickle_datetime64_array(self):
         # gh-12745 (would fail with pickle5 installed)
@@ -2479,11 +2454,32 @@ class TestRegression(object):
             assert_equal(pickle.loads(dumped), arr)
 
     def test_bad_array_interface(self):
-        class T(object):
+        class T:
             __array_interface__ = {}
 
         np.array([T()])
 
+    def test_2d__array__shape(self):
+        class T(object):
+            def __array__(self):
+                return np.ndarray(shape=(0,0))
+
+            # Make sure __array__ is used instead of Sequence methods.
+            def __iter__(self):
+                return iter([])
+
+            def __getitem__(self, idx):
+                raise AssertionError("__getitem__ was called")
+
+            def __len__(self):
+                return 0
+
+
+        t = T()
+        # gh-13659, would raise in broadcasting [x=t for x in result]
+        arr = np.array([t])
+        assert arr.shape == (1, 0, 0)
+
     @pytest.mark.skipif(sys.maxsize < 2 ** 31 + 1, reason='overflows 32-bit python')
     @pytest.mark.skipif(sys.platform == 'win32' and sys.version_info[:2] < (3, 8),
                         reason='overflows on windows, fixed in bpo-16865')
index b21bc9dad07db4c0a858285b48aa26ae9341dfd0..7645a08534fe98c4767dec01595d225e6012953e 100644 (file)
@@ -1,18 +1,14 @@
 """
 Test the scalar constructors, which also do type-coercion
 """
-from __future__ import division, absolute_import, print_function
-
-import sys
-import platform
 import pytest
 
 import numpy as np
 from numpy.testing import (
-    assert_equal, assert_almost_equal, assert_raises, assert_warns,
+    assert_equal, assert_almost_equal, assert_warns,
     )
 
-class TestFromString(object):
+class TestFromString:
     def test_floating(self):
         # Ticket #640, floats from string
         fsingle = np.single('1.234')
@@ -42,21 +38,41 @@ class TestFromString(object):
         flongdouble = assert_warns(RuntimeWarning, np.longdouble, '-1e10000')
         assert_equal(flongdouble, -np.inf)
 
-    @pytest.mark.skipif((sys.version_info[0] >= 3)
-                        or (sys.platform == "win32"
-                            and platform.architecture()[0] == "64bit"),
-                        reason="numpy.intp('0xff', 16) not supported on Py3 "
-                               "or 64 bit Windows")
-    def test_intp(self):
-        # Ticket #99
-        i_width = np.int_(0).nbytes*2 - 1
-        np.intp('0x' + 'f'*i_width, 16)
-        assert_raises(OverflowError, np.intp, '0x' + 'f'*(i_width+1), 16)
-        assert_raises(ValueError, np.intp, '0x1', 32)
-        assert_equal(255, np.intp('0xFF', 16))
+
+class TestExtraArgs:
+    def test_superclass(self):
+        # try both positional and keyword arguments
+        s = np.str_(b'\\x61', encoding='unicode-escape')
+        assert s == 'a'
+        s = np.str_(b'\\x61', 'unicode-escape')
+        assert s == 'a'
+
+        # previously this would return '\\xx'
+        with pytest.raises(UnicodeDecodeError):
+            np.str_(b'\\xx', encoding='unicode-escape')
+        with pytest.raises(UnicodeDecodeError):
+            np.str_(b'\\xx', 'unicode-escape')
+
+        # superclass fails, but numpy succeeds
+        assert np.bytes_(-2) == b'-2'
+
+    def test_datetime(self):
+        dt = np.datetime64('2000-01', ('M', 2))
+        assert np.datetime_data(dt) == ('M', 2)
+
+        with pytest.raises(TypeError):
+            np.datetime64('2000', garbage=True)
+
+    def test_bool(self):
+        with pytest.raises(TypeError):
+            np.bool(False, garbage=True)
+
+    def test_void(self):
+        with pytest.raises(TypeError):
+            np.void(b'test', garbage=True)
 
 
-class TestFromInt(object):
+class TestFromInt:
     def test_intp(self):
         # Ticket #99
         assert_equal(1024, np.intp(1024))
index 93434dd1bf64c4db4b647b975a8eadb95b473386..4f5fd298887db41781666fcc687cb1d5aaa341bd 100644 (file)
@@ -1,22 +1,16 @@
 """
 Test the scalar constructors, which also do type-coercion
 """
-from __future__ import division, absolute_import, print_function
-
-import os
 import fractions
 import platform
 
 import pytest
 import numpy as np
 
-from numpy.testing import (
-    run_module_suite,
-    assert_equal, assert_almost_equal, assert_raises, assert_warns,
-    dec
-)
+from numpy.testing import assert_equal, assert_raises
+
 
-class TestAsIntegerRatio(object):
+class TestAsIntegerRatio:
     # derived in part from the cpython test "test_floatasratio"
 
     @pytest.mark.parametrize("ftype", [
index 3ded7eecdbce5a3b0bb8d91f47809bd2c0a492eb..b1c1bbbb12ff0eb9f213979d149eb466932e370d 100644 (file)
@@ -1,7 +1,6 @@
 """
 Test scalar buffer interface adheres to PEP 3118
 """
-import sys
 import numpy as np
 import pytest
 
@@ -31,9 +30,7 @@ scalars_and_codes = [
 scalars_only, codes_only = zip(*scalars_and_codes)
 
 
-@pytest.mark.skipif(sys.version_info.major < 3,
-                    reason="Python 2 scalars lack a buffer interface")
-class TestScalarPEP3118(object):
+class TestScalarPEP3118:
 
     @pytest.mark.parametrize('scalar', scalars_only, ids=codes_only)
     def test_scalar_match_array(self, scalar):
@@ -79,27 +76,44 @@ class TestScalarPEP3118(object):
         assert_equal(mv_x.itemsize, mv_a.itemsize)
         assert_equal(mv_x.format, mv_a.format)
 
+    def _as_dict(self, m):
+        return dict(strides=m.strides, shape=m.shape, itemsize=m.itemsize,
+                    ndim=m.ndim, format=m.format)
+
     def test_datetime_memoryview(self):
         # gh-11656
         # Values verified with v1.13.3, shape is not () as in test_scalar_dim
-        def as_dict(m):
-            return dict(strides=m.strides, shape=m.shape, itemsize=m.itemsize,
-                        ndim=m.ndim, format=m.format)
 
         dt1 = np.datetime64('2016-01-01')
         dt2 = np.datetime64('2017-01-01')
-        expected = {'strides': (1,), 'itemsize': 1, 'ndim': 1,
-                    'shape': (8,), 'format': 'B'}
+        expected = dict(strides=(1,), itemsize=1, ndim=1, shape=(8,),
+                        format='B')
         v = memoryview(dt1)
-        res = as_dict(v) 
-        assert_equal(res, expected)
+        assert self._as_dict(v) == expected
 
         v = memoryview(dt2 - dt1)
-        res = as_dict(v)
-        assert_equal(res, expected)
+        assert self._as_dict(v) == expected
 
         dt = np.dtype([('a', 'uint16'), ('b', 'M8[s]')])
         a = np.empty(1, dt)
         # Fails to create a PEP 3118 valid buffer
         assert_raises((ValueError, BufferError), memoryview, a[0])
 
+    @pytest.mark.parametrize('s', [
+        pytest.param("\x32\x32", id="ascii"),
+        pytest.param("\uFE0F\uFE0F", id="basic multilingual"),
+        pytest.param("\U0001f4bb\U0001f4bb", id="non-BMP"),
+    ])
+    def test_str_ucs4(self, s):
+        s = np.str_(s)  # only our subclass implements the buffer protocol
+
+        # all the same, characters always encode as ucs4
+        expected = dict(strides=(), itemsize=8, ndim=0, shape=(), format='2w')
+
+        v = memoryview(s)
+        assert self._as_dict(v) == expected
+
+        # integers of the paltform-appropriate endianness
+        code_points = np.frombuffer(v, dtype='i4')
+
+        assert_equal(code_points, [ord(c) for c in s])
index 6a5c4fde9da56c3a5be50cfe7d331b22bb7c6107..74829986c215b732c6c4958ae08c014ce387ad6b 100644 (file)
@@ -2,13 +2,13 @@
 """ Test printing of scalar types.
 
 """
-from __future__ import division, absolute_import, print_function
+import pytest
 
 import numpy as np
 from numpy.testing import assert_
 
 
-class A(object):
+class A:
     pass
 class B(A, np.float64):
     pass
@@ -23,7 +23,15 @@ class B0(np.float64, A):
 class C0(B0):
     pass
 
-class TestInherit(object):
+class HasNew:
+    def __new__(cls, *args, **kwargs):
+        return cls, args, kwargs
+
+class B1(np.float64, HasNew):
+    pass
+
+
+class TestInherit:
     def test_init(self):
         x = B(1.0)
         assert_(str(x) == '1.0')
@@ -38,8 +46,17 @@ class TestInherit(object):
         y = C0(2.0)
         assert_(str(y) == '2.0')
 
+    def test_gh_15395(self):
+        # HasNew is the second base, so `np.float64` should have priority
+        x = B1(1.0)
+        assert_(str(x) == '1.0')
+
+        # previously caused RecursionError!?
+        with pytest.raises(TypeError):
+            B1(1.0, 2.0)
+
 
-class TestCharacter(object):
+class TestCharacter:
     def test_char_radd(self):
         # GH issue 9620, reached gentype_add and raise TypeError
         np_s = np.string_('abc')
index c84380cd9ca00fd957ffdd5bf1dd2378790ffd6f..c7f44cf5097a8c647a251cd879f8d41e55865548 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import warnings
 import itertools
@@ -25,7 +23,7 @@ complex_floating_types = np.complexfloating.__subclasses__()
 
 # This compares scalarmath against ufuncs.
 
-class TestTypes(object):
+class TestTypes:
     def test_types(self):
         for atype in types:
             a = atype(1)
@@ -64,7 +62,7 @@ class TestTypes(object):
             np.add(1, 1)
 
 
-class TestBaseMath(object):
+class TestBaseMath:
     def test_blocked(self):
         # test alignments offsets for simd instructions
         # alignments for vz + 2 * (vs - 1) + 1
@@ -86,7 +84,7 @@ class TestBaseMath(object):
                 assert_almost_equal(np.square(inp2),
                                     np.multiply(inp2, inp2),  err_msg=msg)
                 # skip true divide for ints
-                if dt != np.int32 or (sys.version_info.major < 3 and not sys.py3kwarning):
+                if dt != np.int32:
                     assert_almost_equal(np.reciprocal(inp2),
                                         np.divide(1, inp2),  err_msg=msg)
 
@@ -110,7 +108,7 @@ class TestBaseMath(object):
         np.add(d, np.ones_like(d))
 
 
-class TestPower(object):
+class TestPower:
     def test_small_types(self):
         for t in [np.int8, np.int16, np.float16]:
             a = t(3)
@@ -202,7 +200,7 @@ def _signs(dt):
         return (+1, -1)
 
 
-class TestModulus(object):
+class TestModulus:
 
     def test_modulus_basic(self):
         dt = np.typecodes['AllInteger'] + np.typecodes['Float']
@@ -304,7 +302,7 @@ class TestModulus(object):
             a //= b
 
 
-class TestComplexDivision(object):
+class TestComplexDivision:
     def test_zero_division(self):
         with np.errstate(all="ignore"):
             for t in [np.complex64, np.complex128]:
@@ -376,7 +374,7 @@ class TestComplexDivision(object):
                     assert_equal(result.imag, ex[1])
 
 
-class TestConversion(object):
+class TestConversion:
     def test_int_from_long(self):
         l = [1e6, 1e12, 1e18, -1e6, -1e12, -1e18]
         li = [10**6, 10**12, 10**18, -10**6, -10**12, -10**18]
@@ -512,7 +510,7 @@ class TestConversion(object):
         assert_(np.equal(np.datetime64('NaT'), None))
 
 
-#class TestRepr(object):
+#class TestRepr:
 #    def test_repr(self):
 #        for t in types:
 #            val = t(1197346475.0137341)
@@ -521,7 +519,7 @@ class TestConversion(object):
 #            assert_equal( val, val2 )
 
 
-class TestRepr(object):
+class TestRepr:
     def _test_type_repr(self, t):
         finfo = np.finfo(t)
         last_fraction_bit_idx = finfo.nexp + finfo.nmant
@@ -556,7 +554,7 @@ class TestRepr(object):
 
 if not IS_PYPY:
     # sys.getsizeof() is not valid on PyPy
-    class TestSizeOf(object):
+    class TestSizeOf:
 
         def test_equal_nbytes(self):
             for type in types:
@@ -568,7 +566,7 @@ if not IS_PYPY:
             assert_raises(TypeError, d.__sizeof__, "a")
 
 
-class TestMultiply(object):
+class TestMultiply:
     def test_seq_repeat(self):
         # Test that basic sequences get repeated when multiplied with
         # numpy integers. And errors are raised when multiplied with others.
@@ -605,7 +603,7 @@ class TestMultiply(object):
         # Test that an array-like which does not know how to be multiplied
         # does not attempt sequence repeat (raise TypeError).
         # See also gh-7428.
-        class ArrayLike(object):
+        class ArrayLike:
             def __init__(self, arr):
                 self.arr = arr
             def __array__(self):
@@ -619,7 +617,7 @@ class TestMultiply(object):
             assert_array_equal(np.int_(3) * arr_like, np.full(3, 3))
 
 
-class TestNegative(object):
+class TestNegative:
     def test_exceptions(self):
         a = np.ones((), dtype=np.bool_)[()]
         assert_raises(TypeError, operator.neg, a)
@@ -633,7 +631,7 @@ class TestNegative(object):
                 assert_equal(operator.neg(a) + a, 0)
 
 
-class TestSubtract(object):
+class TestSubtract:
     def test_exceptions(self):
         a = np.ones((), dtype=np.bool_)[()]
         assert_raises(TypeError, operator.sub, a, a)
@@ -647,7 +645,7 @@ class TestSubtract(object):
                 assert_equal(operator.sub(a, a), 0)
 
 
-class TestAbs(object):
+class TestAbs:
     def _test_abs_func(self, absfunc):
         for tp in floating_types + complex_floating_types:
             x = tp(-1.5)
@@ -676,7 +674,7 @@ class TestAbs(object):
         self._test_abs_func(np.abs)
 
 
-class TestBitShifts(object):
+class TestBitShifts:
 
     @pytest.mark.parametrize('type_code', np.typecodes['AllInteger'])
     @pytest.mark.parametrize('op',
index 86b0ca1990c341d4ec994ba83ce78a0cc313f2ae..6502ec4c148664d80e80da4960d0f4e3479e864b 100644 (file)
@@ -2,17 +2,16 @@
 """ Test printing of scalar types.
 
 """
-from __future__ import division, absolute_import, print_function
-
-import code, sys
+import code
 import platform
 import pytest
+import sys
 
 from tempfile import TemporaryFile
 import numpy as np
-from numpy.testing import assert_, assert_equal, suppress_warnings
+from numpy.testing import assert_, assert_equal
 
-class TestRealScalars(object):
+class TestRealScalars:
     def test_str(self):
         svals = [0.0, -0.0, 1, -1, np.inf, -np.inf, np.nan]
         styps = [np.float16, np.float32, np.float64, np.longdouble]
@@ -32,12 +31,12 @@ class TestRealScalars(object):
 
     def test_scalar_cutoffs(self):
         # test that both the str and repr of np.float64 behaves
-        # like python floats in python3. Note that in python2
-        # the str has truncated digits, but we do not do this
+        # like python floats in python3.
         def check(v):
-            # we compare str to repr, to avoid python2 truncation behavior
+            assert_equal(str(np.float64(v)), str(v))
             assert_equal(str(np.float64(v)), repr(v))
             assert_equal(repr(np.float64(v)), repr(v))
+            assert_equal(repr(np.float64(v)), str(v))
 
         # check we use the same number of significant digits
         check(1.12345678901234567890)
@@ -84,10 +83,7 @@ class TestRealScalars(object):
             orig_stdout, orig_stderr = sys.stdout, sys.stderr
             sys.stdout, sys.stderr = fo, fe
 
-            # py2 code.interact sends irrelevant internal DeprecationWarnings
-            with suppress_warnings() as sup:
-                sup.filter(DeprecationWarning)
-                code.interact(local={'np': np}, readfunc=input_func, banner='')
+            code.interact(local={'np': np}, readfunc=input_func, banner='')
 
             sys.stdout, sys.stderr = orig_stdout, orig_stderr
 
index 53d272fc5c0dafe6331feed9f5fececea91ae032..546ecf001452cf22dd926d0bcd3a767952d42c25 100644 (file)
@@ -1,7 +1,4 @@
-from __future__ import division, absolute_import, print_function
-
 import pytest
-import sys
 import numpy as np
 from numpy.core import (
     array, arange, atleast_1d, atleast_2d, atleast_3d, block, vstack, hstack,
@@ -14,9 +11,8 @@ from numpy.testing import (
     assert_raises_regex, assert_warns
     )
 
-from numpy.compat import long
 
-class TestAtleast1d(object):
+class TestAtleast1d:
     def test_0D_array(self):
         a = array(1)
         b = array(2)
@@ -52,12 +48,11 @@ class TestAtleast1d(object):
         """
         assert_(atleast_1d(3).shape == (1,))
         assert_(atleast_1d(3j).shape == (1,))
-        assert_(atleast_1d(long(3)).shape == (1,))
         assert_(atleast_1d(3.0).shape == (1,))
         assert_(atleast_1d([[2, 3], [4, 5]]).shape == (2, 2))
 
 
-class TestAtleast2d(object):
+class TestAtleast2d:
     def test_0D_array(self):
         a = array(1)
         b = array(2)
@@ -96,7 +91,7 @@ class TestAtleast2d(object):
         assert_(atleast_2d([[[3, 1], [4, 5]], [[3, 5], [1, 2]]]).shape == (2, 2, 2))
 
 
-class TestAtleast3d(object):
+class TestAtleast3d:
     def test_0D_array(self):
         a = array(1)
         b = array(2)
@@ -128,7 +123,7 @@ class TestAtleast3d(object):
         assert_array_equal(res, desired)
 
 
-class TestHstack(object):
+class TestHstack:
     def test_non_iterable(self):
         assert_raises(TypeError, hstack, 1)
 
@@ -159,13 +154,11 @@ class TestHstack(object):
     def test_generator(self):
         with assert_warns(FutureWarning):
             hstack((np.arange(3) for _ in range(2)))
-        if sys.version_info.major > 2:
-            # map returns a list on Python 2
-            with assert_warns(FutureWarning):
-                hstack(map(lambda x: x, np.ones((3, 2))))
+        with assert_warns(FutureWarning):
+            hstack(map(lambda x: x, np.ones((3, 2))))
 
 
-class TestVstack(object):
+class TestVstack:
     def test_non_iterable(self):
         assert_raises(TypeError, vstack, 1)
 
@@ -205,7 +198,7 @@ class TestVstack(object):
             vstack((np.arange(3) for _ in range(2)))
 
 
-class TestConcatenate(object):
+class TestConcatenate:
     def test_returns_copy(self):
         a = np.eye(3)
         b = np.concatenate([a])
@@ -409,7 +402,7 @@ def test_stack():
     assert_array_equal(result, np.array([0, 1, 2]))
 
 
-class TestBlock(object):
+class TestBlock:
     @pytest.fixture(params=['block', 'force_concatenate', 'force_slicing'])
     def block(self, request):
         # blocking small arrays and large arrays go through different paths.
@@ -707,7 +700,7 @@ class TestBlock(object):
 
 
 def test_block_dispatcher():
-    class ArrayLike(object):
+    class ArrayLike:
         pass
     a = ArrayLike()
     b = ArrayLike()
index 526925eceeaec24796d0a5edf641639b748258ab..abdaeeb93e2cd5799c9baed72461ef6f4d42e691 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import warnings
 import itertools
 
@@ -18,7 +16,12 @@ from numpy.testing import (
 from numpy.compat import pickle
 
 
-class TestUfuncKwargs(object):
+UNARY_UFUNCS = [obj for obj in np.core.umath.__dict__.values()
+                    if isinstance(obj, np.ufunc)]
+UNARY_OBJECT_UFUNCS = [uf for uf in UNARY_UFUNCS if "O->O" in uf.types]
+
+
+class TestUfuncKwargs:
     def test_kwarg_exact(self):
         assert_raises(TypeError, np.add, 1, 2, castingx='safe')
         assert_raises(TypeError, np.add, 1, 2, dtypex=int)
@@ -44,7 +47,7 @@ class TestUfuncKwargs(object):
         assert_raises(TypeError, np.add, 1, 2, extobj=[4096], parrot=True)
 
 
-class TestUfuncGenericLoops(object):
+class TestUfuncGenericLoops:
     """Test generic loops.
 
     The loops to be tested are:
@@ -113,7 +116,7 @@ class TestUfuncGenericLoops(object):
         assert_equal(ys.dtype, output_dtype)
 
     # class to use in testing object method loops
-    class foo(object):
+    class foo:
         def conjugate(self):
             return np.bool_(1)
 
@@ -124,7 +127,7 @@ class TestUfuncGenericLoops(object):
         x = np.ones(10, dtype=object)
         assert_(np.all(np.abs(x) == 1))
 
-    def test_unary_PyUFunc_O_O_method(self, foo=foo):
+    def test_unary_PyUFunc_O_O_method_simple(self, foo=foo):
         x = np.full(10, foo(), dtype=object)
         assert_(np.all(np.conjugate(x) == True))
 
@@ -140,8 +143,41 @@ class TestUfuncGenericLoops(object):
         x = np.full((10, 2, 3), foo(), dtype=object)
         assert_(np.all(np.logical_xor(x, x)))
 
+    def test_python_complex_conjugate(self):
+        # The conjugate ufunc should fall back to calling the method:
+        arr = np.array([1+2j, 3-4j], dtype="O")
+        assert isinstance(arr[0], complex)
+        res = np.conjugate(arr)
+        assert res.dtype == np.dtype("O")
+        assert_array_equal(res, np.array([1-2j, 3+4j], dtype="O"))
+
+    @pytest.mark.parametrize("ufunc", UNARY_OBJECT_UFUNCS)
+    def test_unary_PyUFunc_O_O_method_full(self, ufunc):
+        """Compare the result of the object loop with non-object one"""
+        val = np.float64(np.pi/4)
+
+        class MyFloat(np.float64):
+            def __getattr__(self, attr):
+                try:
+                    return super().__getattr__(attr)
+                except AttributeError:
+                    return lambda: getattr(np.core.umath, attr)(val)
+
+        num_arr = np.array([val], dtype=np.float64)
+        obj_arr = np.array([MyFloat(val)], dtype="O")
+
+        with np.errstate(all="raise"):
+            try:
+                res_num = ufunc(num_arr)
+            except Exception as exc:
+                with assert_raises(type(exc)):
+                    ufunc(obj_arr)
+            else:
+                res_obj = ufunc(obj_arr)
+                assert_array_equal(res_num.astype("O"), res_obj)
+
 
-class TestUfunc(object):
+class TestUfunc:
     def test_pickle(self):
         for proto in range(2, pickle.HIGHEST_PROTOCOL + 1):
             assert_(pickle.loads(pickle.dumps(np.sin,
@@ -1085,7 +1121,7 @@ class TestUfunc(object):
         assert_equal(np.logical_and.reduce(a), None)
 
     def test_object_comparison(self):
-        class HasComparisons(object):
+        class HasComparisons:
             def __eq__(self, other):
                 return '=='
 
@@ -1124,14 +1160,18 @@ class TestUfunc(object):
         # Twice reproduced also for tuples:
         np.add.accumulate(arr, out=arr)
         np.add.accumulate(arr, out=arr)
-        assert_array_equal(arr, np.array([[1]*i for i in [1, 3, 6, 10]]))
+        assert_array_equal(arr,
+                           np.array([[1]*i for i in [1, 3, 6, 10]], dtype=object),
+                          )
 
         # And the same if the axis argument is used
         arr = np.ones((2, 4), dtype=object)
         arr[0, :] = [[2] for i in range(4)]
         np.add.accumulate(arr, out=arr, axis=-1)
         np.add.accumulate(arr, out=arr, axis=-1)
-        assert_array_equal(arr[0, :], np.array([[2]*i for i in [1, 3, 6, 10]]))
+        assert_array_equal(arr[0, :],
+                           np.array([[2]*i for i in [1, 3, 6, 10]], dtype=object),
+                          )
 
     def test_object_array_reduceat_inplace(self):
         # Checks that in-place reduceats work, see also gh-7465
@@ -1554,7 +1594,7 @@ class TestUfunc(object):
 
     def test_custom_array_like(self):
 
-        class MyThing(object):
+        class MyThing:
             __array_priority__ = 1000
 
             rmul_count = 0
@@ -1775,7 +1815,7 @@ class TestUfunc(object):
         assert_raises(TypeError, f, d, 0, keepdims="invalid", dtype="invalid",
                      out=None)
 
-        # invalid keyord
+        # invalid keyword
         assert_raises(TypeError, f, d, axis=0, dtype=None, invalid=0)
         assert_raises(TypeError, f, d, invalid=0)
         assert_raises(TypeError, f, d, 0, keepdims=True, invalid="invalid",
@@ -1850,6 +1890,23 @@ class TestUfunc(object):
         assert_equal(y_base[1,:], y_base_copy[1,:])
         assert_equal(y_base[3,:], y_base_copy[3,:])
 
+    @pytest.mark.parametrize('output_shape',
+                             [(), (1,), (1, 1), (1, 3), (4, 3)])
+    @pytest.mark.parametrize('f_reduce', [np.add.reduce, np.minimum.reduce])
+    def test_reduce_wrong_dimension_output(self, f_reduce, output_shape):
+        # Test that we're not incorrectly broadcasting dimensions.
+        # See gh-15144 (failed for np.add.reduce previously).
+        a = np.arange(12.).reshape(4, 3)
+        out = np.empty(output_shape, a.dtype)
+        assert_raises(ValueError, f_reduce, a, axis=0, out=out)
+        if output_shape != (1, 3):
+            assert_raises(ValueError, f_reduce, a, axis=0, out=out,
+                          keepdims=True)
+        else:
+            check = f_reduce(a, axis=0, out=out, keepdims=True)
+            assert_(check is out)
+            assert_array_equal(check, f_reduce(a, axis=0, keepdims=True))
+
     def test_no_doc_string(self):
         # gh-9337
         assert_('\n' not in umt.inner1d_no_doc.__doc__)
@@ -1946,3 +2003,21 @@ def test_ufunc_noncontiguous(ufunc):
                 assert_allclose(res_c, res_n, atol=tol, rtol=tol)
             else:
                 assert_equal(c_ar, n_ar)
+
+
+@pytest.mark.parametrize('ufunc', [np.sign, np.equal])
+def test_ufunc_warn_with_nan(ufunc):
+    # issue gh-15127
+    # test that calling certain ufuncs with a non-standard `nan` value does not
+    # emit a warning
+    # `b` holds a 64 bit signaling nan: the most significant bit of the
+    # significand is zero.
+    b = np.array([0x7ff0000000000001], 'i8').view('f8')
+    assert np.isnan(b)
+    if ufunc.nin == 1:
+        ufunc(b)
+    elif ufunc.nin == 2:
+        ufunc(b, b.copy())
+    else:
+        raise ValueError('ufunc with more than 2 inputs')
+
index e892e81d23c6cdc86998ddff69c858f01793e391..7caa4c7f933f982f8036e15f481f927754bab02d 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import platform
 import warnings
 import fnmatch
@@ -23,7 +21,28 @@ def on_powerpc():
            platform.machine().startswith('ppc')
 
 
-class _FilterInvalids(object):
+def bad_arcsinh():
+    """The blacklisted trig functions are not accurate on aarch64 for
+    complex256. Rather than dig through the actual problem skip the
+    test. This should be fixed when we can move past glibc2.17
+    which is the version in manylinux2014
+    """
+    x = 1.78e-10
+    v1 = np.arcsinh(np.float128(x))
+    v2 = np.arcsinh(np.complex256(x)).real
+    # The eps for float128 is 1-e33, so this is way bigger
+    return abs((v1 / v2) - 1.0) > 1e-23
+
+if platform.machine() == 'aarch64' and bad_arcsinh():
+    skip_longcomplex_msg = ('Trig functions of np.longcomplex values known to be '
+                            'inaccurate on aarch64 for some compilation '
+                            'configurations, should be fixed by building on a '
+                            'platform using glibc>2.17')
+else:
+    skip_longcomplex_msg = ''
+
+
+class _FilterInvalids:
     def setup(self):
         self.olderr = np.seterr(invalid='ignore')
 
@@ -31,7 +50,7 @@ class _FilterInvalids(object):
         np.seterr(**self.olderr)
 
 
-class TestConstants(object):
+class TestConstants:
     def test_pi(self):
         assert_allclose(ncu.pi, 3.141592653589793, 1e-15)
 
@@ -42,7 +61,7 @@ class TestConstants(object):
         assert_allclose(ncu.euler_gamma, 0.5772156649015329, 1e-15)
 
 
-class TestOut(object):
+class TestOut:
     def test_out_subok(self):
         for subok in (True, False):
             a = np.array(0.5)
@@ -168,7 +187,7 @@ class TestOut(object):
                 r1, r2 = np.frexp(d, out=o1, subok=subok)
 
 
-class TestComparisons(object):
+class TestComparisons:
     def test_ignore_object_identity_in_equal(self):
         # Check comparing identical objects whose comparison
         # is not a simple boolean, e.g., arrays that are compared elementwise.
@@ -176,7 +195,7 @@ class TestComparisons(object):
         assert_raises(ValueError, np.equal, a, a)
 
         # Check error raised when comparing identical non-comparable objects.
-        class FunkyType(object):
+        class FunkyType:
             def __eq__(self, other):
                 raise TypeError("I won't compare")
 
@@ -194,7 +213,7 @@ class TestComparisons(object):
         assert_raises(ValueError, np.not_equal, a, a)
 
         # Check error raised when comparing identical non-comparable objects.
-        class FunkyType(object):
+        class FunkyType:
             def __ne__(self, other):
                 raise TypeError("I won't compare")
 
@@ -206,7 +225,7 @@ class TestComparisons(object):
         assert_equal(np.not_equal(a, a), [True])
 
 
-class TestAdd(object):
+class TestAdd:
     def test_reduce_alignment(self):
         # gh-9876
         # make sure arrays with weird strides work with the optimizations in
@@ -217,7 +236,7 @@ class TestAdd(object):
         assert_equal(a['b'].sum(), 0)
 
 
-class TestDivision(object):
+class TestDivision:
     def test_division_int(self):
         # int division should follow Python
         x = np.array([5, 10, 90, 100, -5, -10, -90, -100, -120])
@@ -284,7 +303,7 @@ def _signs(dt):
         return (+1, -1)
 
 
-class TestRemainder(object):
+class TestRemainder:
 
     def test_remainder_basic(self):
         dt = np.typecodes['AllInteger'] + np.typecodes['Float']
@@ -375,7 +394,7 @@ class TestRemainder(object):
                 assert_(np.isnan(rem), 'dt: %s, rem: %s' % (dt, rem))
 
 
-class TestCbrt(object):
+class TestCbrt:
     def test_cbrt_scalar(self):
         assert_almost_equal((np.cbrt(np.float32(-2.5)**3)), -2.5)
 
@@ -388,7 +407,7 @@ class TestCbrt(object):
         assert_equal(np.cbrt(-np.inf), -np.inf)
 
 
-class TestPower(object):
+class TestPower:
     def test_power_float(self):
         x = np.array([1., 2., 3.])
         assert_equal(x**0, [1., 1., 1.])
@@ -527,7 +546,7 @@ class TestPower(object):
             assert_raises(ValueError, np.power, one, minusone)
 
 
-class TestFloat_power(object):
+class TestFloat_power:
     def test_type_conversion(self):
         arg_type = '?bhilBHILefdgFDG'
         res_type = 'ddddddddddddgDDG'
@@ -538,7 +557,7 @@ class TestFloat_power(object):
             assert_(res.dtype.name == np.dtype(dtout).name, msg)
 
 
-class TestLog2(object):
+class TestLog2:
     def test_log2_values(self):
         x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
         y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@@ -569,7 +588,7 @@ class TestLog2(object):
             assert_(w[2].category is RuntimeWarning)
 
 
-class TestExp2(object):
+class TestExp2:
     def test_exp2_values(self):
         x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
         y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@@ -620,8 +639,14 @@ class TestLogAddExp2(_FilterInvalids):
         assert_(np.isnan(np.logaddexp2(0, np.nan)))
         assert_(np.isnan(np.logaddexp2(np.nan, np.nan)))
 
+    def test_reduce(self):
+        assert_equal(np.logaddexp2.identity, -np.inf)
+        assert_equal(np.logaddexp2.reduce([]), -np.inf)
+        assert_equal(np.logaddexp2.reduce([-np.inf]), -np.inf)
+        assert_equal(np.logaddexp2.reduce([-np.inf, 0]), 0)
 
-class TestLog(object):
+
+class TestLog:
     def test_log_values(self):
         x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
         y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@@ -632,7 +657,7 @@ class TestLog(object):
             assert_almost_equal(np.log(xf), yf)
 
 
-class TestExp(object):
+class TestExp:
     def test_exp_values(self):
         x = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]
         y = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
@@ -642,7 +667,17 @@ class TestExp(object):
             yf = np.array(y, dtype=dt)*log2_
             assert_almost_equal(np.exp(yf), xf)
 
-class TestSpecialFloats(object):
+    def test_exp_strides(self):
+        np.random.seed(42)
+        strides = np.array([-4,-3,-2,-1,1,2,3,4])
+        sizes = np.arange(2,100)
+        for ii in sizes:
+            x_f64 = np.float64(np.random.uniform(low=0.01, high=709.1,size=ii))
+            y_true = np.exp(x_f64)
+            for jj in strides:
+                assert_array_almost_equal_nulp(np.exp(x_f64[::jj]), y_true[::jj], nulp=2)
+
+class TestSpecialFloats:
     def test_exp_values(self):
         x = [np.nan,  np.nan, np.inf, 0.]
         y = [np.nan, -np.nan, np.inf, -np.inf]
@@ -654,6 +689,8 @@ class TestSpecialFloats(object):
         with np.errstate(over='raise'):
             assert_raises(FloatingPointError, np.exp, np.float32(100.))
             assert_raises(FloatingPointError, np.exp, np.float32(1E19))
+            assert_raises(FloatingPointError, np.exp, np.float64(800.))
+            assert_raises(FloatingPointError, np.exp, np.float64(1E19))
 
     def test_log_values(self):
         with np.errstate(all='ignore'):
@@ -744,7 +781,7 @@ avx_ufuncs = {'sqrt'        :[1,  0.,   100.],
               'ceil'        :[0, -100., 100.],
               'trunc'       :[0, -100., 100.]}
 
-class TestAVXUfuncs(object):
+class TestAVXUfuncs:
     def test_avx_based_ufunc(self):
         strides = np.array([-4,-3,-2,-1,1,2,3,4])
         np.random.seed(42)
@@ -776,7 +813,7 @@ class TestAVXUfuncs(object):
                         assert_equal(myfunc(x_f64[::jj]), y_true64[::jj])
                         assert_equal(myfunc(x_f32[::jj]), y_true32[::jj])
 
-class TestAVXFloat32Transcendental(object):
+class TestAVXFloat32Transcendental:
     def test_exp_float32(self):
         np.random.seed(42)
         x_f32 = np.float32(np.random.uniform(low=0.0,high=88.1,size=1000000))
@@ -807,15 +844,17 @@ class TestAVXFloat32Transcendental(object):
         sizes = np.arange(2,100)
         for ii in sizes:
             x_f32 = np.float32(np.random.uniform(low=0.01,high=88.1,size=ii))
+            x_f32_large = x_f32.copy()
+            x_f32_large[3:-1:4] = 120000.0
             exp_true = np.exp(x_f32)
             log_true = np.log(x_f32)
-            sin_true = np.sin(x_f32)
-            cos_true = np.cos(x_f32)
+            sin_true = np.sin(x_f32_large)
+            cos_true = np.cos(x_f32_large)
             for jj in strides:
                 assert_array_almost_equal_nulp(np.exp(x_f32[::jj]), exp_true[::jj], nulp=2)
                 assert_array_almost_equal_nulp(np.log(x_f32[::jj]), log_true[::jj], nulp=2)
-                assert_array_almost_equal_nulp(np.sin(x_f32[::jj]), sin_true[::jj], nulp=2)
-                assert_array_almost_equal_nulp(np.cos(x_f32[::jj]), cos_true[::jj], nulp=2)
+                assert_array_almost_equal_nulp(np.sin(x_f32_large[::jj]), sin_true[::jj], nulp=2)
+                assert_array_almost_equal_nulp(np.cos(x_f32_large[::jj]), cos_true[::jj], nulp=2)
 
 class TestLogAddExp(_FilterInvalids):
     def test_logaddexp_values(self):
@@ -862,7 +901,7 @@ class TestLogAddExp(_FilterInvalids):
         assert_equal(np.logaddexp.reduce([]), -np.inf)
 
 
-class TestLog1p(object):
+class TestLog1p:
     def test_log1p(self):
         assert_almost_equal(ncu.log1p(0.2), ncu.log(1.2))
         assert_almost_equal(ncu.log1p(1e-6), ncu.log(1+1e-6))
@@ -876,7 +915,7 @@ class TestLog1p(object):
             assert_equal(ncu.log1p(-np.inf), np.nan)
 
 
-class TestExpm1(object):
+class TestExpm1:
     def test_expm1(self):
         assert_almost_equal(ncu.expm1(0.2), ncu.exp(0.2)-1)
         assert_almost_equal(ncu.expm1(1e-6), ncu.exp(1e-6)-1)
@@ -888,8 +927,14 @@ class TestExpm1(object):
         assert_equal(ncu.expm1(np.inf), np.inf)
         assert_equal(ncu.expm1(-np.inf), -1.)
 
+    def test_complex(self):
+        x = np.asarray(1e-12)
+        assert_allclose(x, ncu.expm1(x))
+        x = x.astype(np.complex128)
+        assert_allclose(x, ncu.expm1(x))
 
-class TestHypot(object):
+
+class TestHypot:
     def test_simple(self):
         assert_almost_equal(ncu.hypot(1, 1), ncu.sqrt(2))
         assert_almost_equal(ncu.hypot(0, 0), 0)
@@ -913,7 +958,7 @@ def assert_hypot_isinf(x, y):
                 "hypot(%s, %s) is %s, not inf" % (x, y, ncu.hypot(x, y)))
 
 
-class TestHypotSpecialValues(object):
+class TestHypotSpecialValues:
     def test_nan_outputs(self):
         assert_hypot_isnan(np.nan, np.nan)
         assert_hypot_isnan(np.nan, 1)
@@ -950,7 +995,7 @@ def assert_arctan2_isnzero(x, y):
     assert_((ncu.arctan2(x, y) == 0 and np.signbit(ncu.arctan2(x, y))), "arctan(%s, %s) is %s, not -0" % (x, y, ncu.arctan2(x, y)))
 
 
-class TestArctan2SpecialValues(object):
+class TestArctan2SpecialValues:
     def test_one_one(self):
         # atan2(1, 1) returns pi/4.
         assert_almost_equal(ncu.arctan2(1, 1), 0.25 * np.pi)
@@ -1019,7 +1064,7 @@ class TestArctan2SpecialValues(object):
         assert_arctan2_isnan(np.nan, np.nan)
 
 
-class TestLdexp(object):
+class TestLdexp:
     def _check_ldexp(self, tp):
         assert_almost_equal(ncu.ldexp(np.array(2., np.float32),
                                       np.array(3, tp)), 16.)
@@ -1104,6 +1149,19 @@ class TestMaximum(_FilterInvalids):
         arg2 = arg1 + 1
         assert_equal(np.maximum(arg1, arg2), arg2)
 
+    def test_strided_array(self):
+        arr1 = np.array([-4.0, 1.0, 10.0,  0.0, np.nan, -np.nan, np.inf, -np.inf])
+        arr2 = np.array([-2.0,-1.0, np.nan, 1.0, 0.0,    np.nan, 1.0,    -3.0])
+        maxtrue  = np.array([-2.0, 1.0, np.nan, 1.0, np.nan, np.nan, np.inf, -3.0])
+        out = np.ones(8)
+        out_maxtrue = np.array([-2.0, 1.0, 1.0, 10.0, 1.0, 1.0, np.nan, 1.0])
+        assert_equal(np.maximum(arr1,arr2), maxtrue)
+        assert_equal(np.maximum(arr1[::2],arr2[::2]), maxtrue[::2])
+        assert_equal(np.maximum(arr1[:4:], arr2[::2]), np.array([-2.0, np.nan, 10.0, 1.0]))
+        assert_equal(np.maximum(arr1[::3], arr2[:3:]), np.array([-2.0, 0.0, np.nan]))
+        assert_equal(np.maximum(arr1[:6:2], arr2[::3], out=out[::3]), np.array([-2.0, 10., np.nan]))
+        assert_equal(out, out_maxtrue)
+
 
 class TestMinimum(_FilterInvalids):
     def test_reduce(self):
@@ -1162,6 +1220,18 @@ class TestMinimum(_FilterInvalids):
         arg2 = arg1 + 1
         assert_equal(np.minimum(arg1, arg2), arg1)
 
+    def test_strided_array(self):
+        arr1 = np.array([-4.0, 1.0, 10.0,  0.0, np.nan, -np.nan, np.inf, -np.inf])
+        arr2 = np.array([-2.0,-1.0, np.nan, 1.0, 0.0,    np.nan, 1.0,    -3.0])
+        mintrue  = np.array([-4.0, -1.0, np.nan, 0.0, np.nan, np.nan, 1.0, -np.inf])
+        out = np.ones(8)
+        out_mintrue = np.array([-4.0, 1.0, 1.0, 1.0, 1.0, 1.0, np.nan, 1.0])
+        assert_equal(np.minimum(arr1,arr2), mintrue)
+        assert_equal(np.minimum(arr1[::2],arr2[::2]), mintrue[::2])
+        assert_equal(np.minimum(arr1[:4:], arr2[::2]), np.array([-4.0, np.nan, 0.0, 0.0]))
+        assert_equal(np.minimum(arr1[::3], arr2[:3:]), np.array([-4.0, -1.0, np.nan]))
+        assert_equal(np.minimum(arr1[:6:2], arr2[::3], out=out[::3]), np.array([-4.0, 1.0, np.nan]))
+        assert_equal(out, out_mintrue)
 
 class TestFmax(_FilterInvalids):
     def test_reduce(self):
@@ -1247,7 +1317,7 @@ class TestFmin(_FilterInvalids):
             assert_equal(np.fmin(arg1, arg2), out)
 
 
-class TestBool(object):
+class TestBool:
     def test_exceptions(self):
         a = np.ones(1, dtype=np.bool_)
         assert_raises(TypeError, np.negative, a)
@@ -1310,7 +1380,7 @@ class TestBool(object):
             assert_equal(np.logical_xor.reduce(arr), arr.sum() % 2 == 1)
 
 
-class TestBitwiseUFuncs(object):
+class TestBitwiseUFuncs:
 
     bitwise_types = [np.dtype(c) for c in '?' + 'bBhHiIlLqQ' + 'O']
 
@@ -1394,7 +1464,7 @@ class TestBitwiseUFuncs(object):
             assert_(type(f.reduce(btype)) is bool, msg)
 
 
-class TestInt(object):
+class TestInt:
     def test_logical_not(self):
         x = np.ones(10, dtype=np.int16)
         o = np.ones(10 * 2, dtype=bool)
@@ -1405,24 +1475,24 @@ class TestInt(object):
         assert_array_equal(o, tgt)
 
 
-class TestFloatingPoint(object):
+class TestFloatingPoint:
     def test_floating_point(self):
         assert_equal(ncu.FLOATING_POINT_SUPPORT, 1)
 
 
-class TestDegrees(object):
+class TestDegrees:
     def test_degrees(self):
         assert_almost_equal(ncu.degrees(np.pi), 180.0)
         assert_almost_equal(ncu.degrees(-0.5*np.pi), -90.0)
 
 
-class TestRadians(object):
+class TestRadians:
     def test_radians(self):
         assert_almost_equal(ncu.radians(180.0), np.pi)
         assert_almost_equal(ncu.radians(-90.0), -0.5*np.pi)
 
 
-class TestHeavside(object):
+class TestHeavside:
     def test_heaviside(self):
         x = np.array([[-30.0, -0.1, 0.0, 0.2], [7.5, np.nan, np.inf, -np.inf]])
         expectedhalf = np.array([[0.0, 0.0, 0.5, 1.0], [1.0, np.nan, 1.0, 0.0]])
@@ -1444,7 +1514,7 @@ class TestHeavside(object):
         assert_equal(h, expected1.astype(np.float32))
 
 
-class TestSign(object):
+class TestSign:
     def test_sign(self):
         a = np.array([np.inf, -np.inf, np.nan, 0.0, 3.0, -3.0])
         out = np.zeros(a.shape)
@@ -1475,7 +1545,7 @@ class TestSign(object):
 
         assert_raises(TypeError, test_nan)
 
-class TestMinMax(object):
+class TestMinMax:
     def test_minmax_blocked(self):
         # simd tests on max/min, test all alignments, slow but important
         # for 2 * vz + 2 * (vs - 1) + 1 (unrolled once)
@@ -1518,7 +1588,7 @@ class TestMinMax(object):
         assert_equal(a, np.nan)
 
 
-class TestAbsoluteNegative(object):
+class TestAbsoluteNegative:
     def test_abs_neg_blocked(self):
         # simd tests on abs, test all alignments for vz + 2 * (vs - 1) + 1
         for dt, sz in [(np.float32, 11), (np.float64, 5)]:
@@ -1560,7 +1630,7 @@ class TestAbsoluteNegative(object):
         np.abs(np.ones_like(d), out=d)
 
 
-class TestPositive(object):
+class TestPositive:
     def test_valid(self):
         valid_dtypes = [int, float, complex, object]
         for dtype in valid_dtypes:
@@ -1579,10 +1649,10 @@ class TestPositive(object):
             np.positive(np.array(['bar'], dtype=object))
 
 
-class TestSpecialMethods(object):
+class TestSpecialMethods:
     def test_wrap(self):
 
-        class with_wrap(object):
+        class with_wrap:
             def __array__(self):
                 return np.zeros(1)
 
@@ -1620,7 +1690,7 @@ class TestSpecialMethods(object):
             @property
             def args(self):
                 # We need to ensure these are fetched at the same time, before
-                # any other ufuncs are calld by the assertions
+                # any other ufuncs are called by the assertions
                 return (self._prepare_args, self._wrap_args)
             def __repr__(self):
                 return "a"  # for short test output
@@ -1686,7 +1756,7 @@ class TestSpecialMethods(object):
 
     def test_old_wrap(self):
 
-        class with_wrap(object):
+        class with_wrap:
             def __array__(self):
                 return np.zeros(1)
 
@@ -1701,7 +1771,7 @@ class TestSpecialMethods(object):
 
     def test_priority(self):
 
-        class A(object):
+        class A:
             def __array__(self):
                 return np.zeros(1)
 
@@ -1744,7 +1814,7 @@ class TestSpecialMethods(object):
 
     def test_failing_wrap(self):
 
-        class A(object):
+        class A:
             def __array__(self):
                 return np.zeros(2)
 
@@ -1776,7 +1846,7 @@ class TestSpecialMethods(object):
     def test_none_wrap(self):
         # Tests that issue #8507 is resolved. Previously, this would segfault
 
-        class A(object):
+        class A:
             def __array__(self):
                 return np.zeros(1)
 
@@ -1788,7 +1858,7 @@ class TestSpecialMethods(object):
 
     def test_default_prepare(self):
 
-        class with_wrap(object):
+        class with_wrap:
             __array_priority__ = 10
 
             def __array__(self):
@@ -1834,7 +1904,7 @@ class TestSpecialMethods(object):
 
     def test_failing_prepare(self):
 
-        class A(object):
+        class A:
             def __array__(self):
                 return np.zeros(1)
 
@@ -1844,36 +1914,18 @@ class TestSpecialMethods(object):
         a = A()
         assert_raises(RuntimeError, ncu.maximum, a, a)
 
-    def test_array_with_context(self):
+    def test_array_too_many_args(self):
 
         class A(object):
-            def __array__(self, dtype=None, context=None):
-                func, args, i = context
-                self.func = func
-                self.args = args
-                self.i = i
-                return np.zeros(1)
-
-        class B(object):
-            def __array__(self, dtype=None):
-                return np.zeros(1, dtype)
-
-        class C(object):
-            def __array__(self):
+            def __array__(self, dtype, context):
                 return np.zeros(1)
 
         a = A()
-        ncu.maximum(np.zeros(1), a)
-        assert_(a.func is ncu.maximum)
-        assert_equal(a.args[0], 0)
-        assert_(a.args[1] is a)
-        assert_(a.i == 1)
-        assert_equal(ncu.maximum(a, B()), 0)
-        assert_equal(ncu.maximum(a, C()), 0)
+        assert_raises_regex(TypeError, '2 required positional', np.sum, a)
 
     def test_ufunc_override(self):
         # check override works even with instance with high priority.
-        class A(object):
+        class A:
             def __array_ufunc__(self, func, method, *inputs, **kwargs):
                 return self, func, method, inputs, kwargs
 
@@ -1910,7 +1962,7 @@ class TestSpecialMethods(object):
         three_mul_ufunc = np.frompyfunc(tres_mul, 3, 1)
         four_mul_ufunc = np.frompyfunc(quatro_mul, 4, 1)
 
-        class A(object):
+        class A:
             def __array_ufunc__(self, func, method, *inputs, **kwargs):
                 return "A"
 
@@ -1918,11 +1970,11 @@ class TestSpecialMethods(object):
             def __array_ufunc__(self, func, method, *inputs, **kwargs):
                 return "ASub"
 
-        class B(object):
+        class B:
             def __array_ufunc__(self, func, method, *inputs, **kwargs):
                 return "B"
 
-        class C(object):
+        class C:
             def __init__(self):
                 self.count = 0
 
@@ -2034,7 +2086,7 @@ class TestSpecialMethods(object):
 
     def test_ufunc_override_methods(self):
 
-        class A(object):
+        class A:
             def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
                 return self, ufunc, method, inputs, kwargs
 
@@ -2203,11 +2255,11 @@ class TestSpecialMethods(object):
 
     def test_ufunc_override_out(self):
 
-        class A(object):
+        class A:
             def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
                 return kwargs
 
-        class B(object):
+        class B:
             def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
                 return kwargs
 
@@ -2259,7 +2311,7 @@ class TestSpecialMethods(object):
 
     def test_ufunc_override_exception(self):
 
-        class A(object):
+        class A:
             def __array_ufunc__(self, *a, **kwargs):
                 raise ValueError("oops")
 
@@ -2270,7 +2322,7 @@ class TestSpecialMethods(object):
 
     def test_ufunc_override_not_implemented(self):
 
-        class A(object):
+        class A:
             def __array_ufunc__(self, *args, **kwargs):
                 return NotImplemented
 
@@ -2287,7 +2339,7 @@ class TestSpecialMethods(object):
 
     def test_ufunc_override_disabled(self):
 
-        class OptOut(object):
+        class OptOut:
             __array_ufunc__ = None
 
         opt_out = OptOut()
@@ -2304,7 +2356,7 @@ class TestSpecialMethods(object):
         # opt-outs still hold even when other arguments have pathological
         # __array_ufunc__ implementations
 
-        class GreedyArray(object):
+        class GreedyArray:
             def __array_ufunc__(self, *args, **kwargs):
                 return self
 
@@ -2318,7 +2370,7 @@ class TestSpecialMethods(object):
     def test_gufunc_override(self):
         # gufunc are just ufunc instances, but follow a different path,
         # so check __array_ufunc__ overrides them properly.
-        class A(object):
+        class A:
             def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
                 return self, ufunc, method, inputs, kwargs
 
@@ -2349,7 +2401,7 @@ class TestSpecialMethods(object):
         # NOTE: this class is given as an example in doc/subclassing.py;
         # if you make any changes here, do update it there too.
         class A(np.ndarray):
-            def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
+            def __array_ufunc__(self, ufunc, method, *inputs, out=None, **kwargs):
                 args = []
                 in_no = []
                 for i, input_ in enumerate(inputs):
@@ -2359,7 +2411,7 @@ class TestSpecialMethods(object):
                     else:
                         args.append(input_)
 
-                outputs = kwargs.pop('out', None)
+                outputs = out
                 out_no = []
                 if outputs:
                     out_args = []
@@ -2400,7 +2452,7 @@ class TestSpecialMethods(object):
 
                 return results[0] if len(results) == 1 else results
 
-        class B(object):
+        class B:
             def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
                 if any(isinstance(input_, A) for input_ in inputs):
                     return "A!"
@@ -2519,14 +2571,14 @@ class TestSpecialMethods(object):
         assert_(a.info, {'inputs': [0, 2]})
 
 
-class TestChoose(object):
+class TestChoose:
     def test_mixed(self):
         c = np.array([True, True])
         a = np.array([True, True])
         assert_equal(np.choose(c, (a, 1)), np.array([1, 1]))
 
 
-class TestRationalFunctions(object):
+class TestRationalFunctions:
     def test_lcm(self):
         self._test_lcm_inner(np.int16)
         self._test_lcm_inner(np.uint16)
@@ -2625,7 +2677,7 @@ class TestRationalFunctions(object):
         assert_equal(np.gcd(2**100, 3**100), 1)
 
 
-class TestRoundingFunctions(object):
+class TestRoundingFunctions:
 
     def test_object_direct(self):
         """ test direct implementation of these magic methods """
@@ -2661,7 +2713,7 @@ class TestRoundingFunctions(object):
         assert_equal(np.trunc(f), -1)
 
 
-class TestComplexFunctions(object):
+class TestComplexFunctions:
     funcs = [np.arcsin,  np.arccos,  np.arctan, np.arcsinh, np.arccosh,
              np.arctanh, np.sin,     np.cos,    np.tan,     np.exp,
              np.exp2,    np.log,     np.sqrt,   np.log10,   np.log2,
@@ -2800,6 +2852,8 @@ class TestComplexFunctions(object):
             # are accurate down to a few epsilons. (Eg. on Linux 64-bit)
             # So, give more leeway for long complex tests here:
             # Can use 2.1 for > Ubuntu LTS Trusty (2014), glibc = 2.19.
+            if skip_longcomplex_msg:
+                pytest.skip(skip_longcomplex_msg)
             check(x_series, 50.0*eps)
         else:
             check(x_series, 2.1*eps)
@@ -2844,7 +2898,7 @@ class TestComplexFunctions(object):
             check(func, pts, 1+1j)
 
 
-class TestAttributes(object):
+class TestAttributes:
     def test_attributes(self):
         add = ncu.add
         assert_equal(add.__name__, 'add')
@@ -2863,7 +2917,7 @@ class TestAttributes(object):
             "frexp(x[, out1, out2], / [, out=(None, None)], *, where=True"))
 
 
-class TestSubclass(object):
+class TestSubclass:
 
     def test_subclass_op(self):
 
@@ -2876,6 +2930,32 @@ class TestSubclass(object):
         a = simple((3, 4))
         assert_equal(a+a, a)
 
+
+class TestFrompyfunc(object):
+
+    def test_identity(self):
+        def mul(a, b):
+            return a * b
+
+        # with identity=value
+        mul_ufunc = np.frompyfunc(mul, nin=2, nout=1, identity=1)
+        assert_equal(mul_ufunc.reduce([2, 3, 4]), 24)
+        assert_equal(mul_ufunc.reduce(np.ones((2, 2)), axis=(0, 1)), 1)
+        assert_equal(mul_ufunc.reduce([]), 1)
+
+        # with identity=None (reorderable)
+        mul_ufunc = np.frompyfunc(mul, nin=2, nout=1, identity=None)
+        assert_equal(mul_ufunc.reduce([2, 3, 4]), 24)
+        assert_equal(mul_ufunc.reduce(np.ones((2, 2)), axis=(0, 1)), 1)
+        assert_raises(ValueError, lambda: mul_ufunc.reduce([]))
+
+        # with no identity (not reorderable)
+        mul_ufunc = np.frompyfunc(mul, nin=2, nout=1)
+        assert_equal(mul_ufunc.reduce([2, 3, 4]), 24)
+        assert_raises(ValueError, lambda: mul_ufunc.reduce(np.ones((2, 2)), axis=(0, 1)))
+        assert_raises(ValueError, lambda: mul_ufunc.reduce([]))
+
+
 def _check_branch_cut(f, x0, dx, re_sign=1, im_sign=-1, sig_zero_ok=False,
                       dtype=complex):
     """
@@ -3120,6 +3200,14 @@ def test_rint_big_int():
     # Rint should not change the value
     assert_equal(val, np.rint(val))
 
+@pytest.mark.parametrize('ftype', [np.float32, np.float64])
+def test_memoverlap_accumulate(ftype):
+    # Reproduces bug https://github.com/numpy/numpy/issues/15597
+    arr = np.array([0.61, 0.60, 0.77, 0.41, 0.19], dtype=ftype)
+    out_max = np.array([0.61, 0.61, 0.77, 0.77, 0.77], dtype=ftype)
+    out_min = np.array([0.61, 0.60, 0.60, 0.41, 0.19], dtype=ftype)
+    assert_equal(np.maximum.accumulate(arr), out_max)
+    assert_equal(np.minimum.accumulate(arr), out_min)
 
 def test_signaling_nan_exceptions():
     with assert_no_warnings():
index fec18078696b007b791bce427e5ac4938e3e29ee..33080edbb4c373b6e7e5d76c05502ca0e4f4c906 100644 (file)
@@ -3,23 +3,28 @@ import platform
 from os import path
 import sys
 import pytest
-from ctypes import *
+from ctypes import c_longlong, c_double, c_float, c_int, cast, pointer, POINTER
 from numpy.testing import assert_array_max_ulp
+from numpy.core._multiarray_umath import __cpu_features__
 
-runtest = sys.platform.startswith('linux') and (platform.machine() == 'x86_64')
+IS_AVX = __cpu_features__.get('AVX512F', False) or \
+        (__cpu_features__.get('FMA3', False) and __cpu_features__.get('AVX2', False))
+runtest = sys.platform.startswith('linux') and IS_AVX
 platform_skip = pytest.mark.skipif(not runtest,
-                                   reason="""
-                                   stick to x86_64 and linux platforms.
-                                   test seems to fail on some of ARM and power
-                                   architectures.
-                                   """)
+                                   reason="avoid testing inconsistent platform "
+                                   "library implementations")
 
 # convert string to hex function taken from:
 # https://stackoverflow.com/questions/1592158/convert-hex-to-float #
-def convert(s):
+def convert(s, datatype="np.float32"):
     i = int(s, 16)                   # convert from hex to a Python int
-    cp = pointer(c_int(i))           # make this into a c integer
-    fp = cast(cp, POINTER(c_float))  # cast the int pointer to a float pointer
+    if (datatype == "np.float64"):
+        cp = pointer(c_longlong(i))           # make this into a c long long integer
+        fp = cast(cp, POINTER(c_double))  # cast the int pointer to a double pointer
+    else:
+        cp = pointer(c_int(i))           # make this into a c integer
+        fp = cast(cp, POINTER(c_float))  # cast the int pointer to a float pointer
+
     return fp.contents.value         # dereference the pointer, get the float
 
 str_to_float = np.vectorize(convert)
@@ -28,8 +33,8 @@ files = ['umath-validation-set-exp',
          'umath-validation-set-sin',
          'umath-validation-set-cos']
 
-class TestAccuracy(object):
-    @pytest.mark.xfail(reason="Fails for MacPython/numpy-wheels builds")
+class TestAccuracy:
+    @platform_skip
     def test_validate_transcendentals(self):
         with np.errstate(all='ignore'):
             for filename in files:
@@ -37,18 +42,18 @@ class TestAccuracy(object):
                 filepath = path.join(data_dir, filename)
                 with open(filepath) as fid:
                     file_without_comments = (r for r in fid if not r[0] in ('$', '#'))
-                data = np.genfromtxt(file_without_comments,
-                                     dtype=('|S39','|S39','|S39',int),
-                                     names=('type','input','output','ulperr'),
-                                     delimiter=',',
-                                     skip_header=1)
-                npfunc = getattr(np, filename.split('-')[3])
-                for datatype in np.unique(data['type']):
-                    data_subset = data[data['type'] == datatype]
-                    inval  = np.array(str_to_float(data_subset['input'].astype(str)), dtype=eval(datatype))
-                    outval = np.array(str_to_float(data_subset['output'].astype(str)), dtype=eval(datatype))
-                    perm = np.random.permutation(len(inval))
-                    inval = inval[perm]
-                    outval = outval[perm]
-                    maxulperr = data_subset['ulperr'].max()
-                    assert_array_max_ulp(npfunc(inval), outval, maxulperr)
+                    data = np.genfromtxt(file_without_comments,
+                                         dtype=('|S39','|S39','|S39',int),
+                                         names=('type','input','output','ulperr'),
+                                         delimiter=',',
+                                         skip_header=1)
+                    npfunc = getattr(np, filename.split('-')[3])
+                    for datatype in np.unique(data['type']):
+                        data_subset = data[data['type'] == datatype]
+                        inval  = np.array(str_to_float(data_subset['input'].astype(str), data_subset['type'].astype(str)), dtype=eval(datatype))
+                        outval = np.array(str_to_float(data_subset['output'].astype(str), data_subset['type'].astype(str)), dtype=eval(datatype))
+                        perm = np.random.permutation(len(inval))
+                        inval = inval[perm]
+                        outval = outval[perm]
+                        maxulperr = data_subset['ulperr'].max()
+                        assert_array_max_ulp(npfunc(inval), outval, maxulperr)
index 1f5b4077f68f135d44f92a7441455be54cf4fe48..a21158420410510fb79fc3a8f8efe7f8965755ca 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import platform
 import pytest
@@ -8,7 +6,7 @@ import numpy as np
 # import the c-extension module directly since _arg is not exported via umath
 import numpy.core._multiarray_umath as ncu
 from numpy.testing import (
-    assert_raises, assert_equal, assert_array_equal, assert_almost_equal
+    assert_raises, assert_equal, assert_array_equal, assert_almost_equal, assert_array_max_ulp
     )
 
 # TODO: branch cuts (use Pauli code)
@@ -31,7 +29,7 @@ platform_skip = pytest.mark.skipif(xfail_complex_tests,
 
 
 
-class TestCexp(object):
+class TestCexp:
     def test_simple(self):
         check = check_complex_value
         f = np.exp
@@ -131,7 +129,7 @@ class TestCexp(object):
 
         check(f, np.nan, 0, np.nan, 0)
 
-class TestClog(object):
+class TestClog:
     def test_simple(self):
         x = np.array([1+0j, 1+2j])
         y_r = np.log(np.abs(x)) + 1j * np.angle(x)
@@ -276,7 +274,7 @@ class TestClog(object):
                 assert_almost_equal(np.log(xa[i].conj()), ya[i].conj())
 
 
-class TestCsqrt(object):
+class TestCsqrt:
 
     def test_simple(self):
         # sqrt(1)
@@ -356,7 +354,7 @@ class TestCsqrt(object):
         # XXX: check for conj(csqrt(z)) == csqrt(conj(z)) (need to fix branch
         # cuts first)
 
-class TestCpow(object):
+class TestCpow:
     def setup(self):
         self.olderr = np.seterr(invalid='ignore')
 
@@ -396,7 +394,7 @@ class TestCpow(object):
         for i in lx:
             assert_almost_equal(n_r[i], p_r[i], err_msg='Loop %d\n' % i)
 
-class TestCabs(object):
+class TestCabs:
     def setup(self):
         self.olderr = np.seterr(invalid='ignore')
 
@@ -458,7 +456,7 @@ class TestCabs(object):
             ref = g(x[i], y[i])
             check_real_value(f, x[i], y[i], ref)
 
-class TestCarg(object):
+class TestCarg:
     def test_simple(self):
         check_real_value(ncu._arg, 1, 0, 0, False)
         check_real_value(ncu._arg, 0, 1, 0.5*np.pi, False)
@@ -542,3 +540,40 @@ def check_complex_value(f, x1, y1, x2, y2, exact=True):
             assert_equal(f(z1), z2)
         else:
             assert_almost_equal(f(z1), z2)
+
+class TestSpecialComplexAVX(object):
+    @pytest.mark.parametrize("stride", [-4,-2,-1,1,2,4])
+    @pytest.mark.parametrize("astype", [np.complex64, np.complex128])
+    def test_array(self, stride, astype):
+        arr = np.array([np.complex(np.nan , np.nan),
+                        np.complex(np.nan , np.inf),
+                        np.complex(np.inf , np.nan),
+                        np.complex(np.inf , np.inf),
+                        np.complex(0.     , np.inf),
+                        np.complex(np.inf , 0.),
+                        np.complex(0.     , 0.),
+                        np.complex(0.     , np.nan),
+                        np.complex(np.nan , 0.)], dtype=astype)
+        abs_true = np.array([np.nan, np.inf, np.inf, np.inf, np.inf, np.inf, 0., np.nan, np.nan], dtype=arr.real.dtype)
+        sq_true = np.array([np.complex(np.nan,  np.nan),
+                            np.complex(np.nan,  np.nan),
+                            np.complex(np.nan,  np.nan),
+                            np.complex(np.nan,  np.inf),
+                            np.complex(-np.inf, np.nan),
+                            np.complex(np.inf,  np.nan),
+                            np.complex(0.,     0.),
+                            np.complex(np.nan, np.nan),
+                            np.complex(np.nan, np.nan)], dtype=astype)
+        assert_equal(np.abs(arr[::stride]), abs_true[::stride])
+        with np.errstate(invalid='ignore'):
+            assert_equal(np.square(arr[::stride]), sq_true[::stride])
+
+class TestComplexAbsoluteAVX(object):
+    @pytest.mark.parametrize("arraysize", [1,2,3,4,5,6,7,8,9,10,11,13,15,17,18,19])
+    @pytest.mark.parametrize("stride", [-4,-3,-2,-1,1,2,3,4])
+    @pytest.mark.parametrize("astype", [np.complex64, np.complex128])
+    # test to ensure masking and strides work as intended in the AVX implementation
+    def test_array(self, arraysize, stride, astype):
+        arr = np.ones(arraysize, dtype=astype)
+        abs_true = np.ones(arraysize, dtype=arr.real.dtype)
+        assert_equal(np.abs(arr[::stride]), abs_true[::stride])
index 2ffd8801b7ea2bd97dcd5976920c3bb8d70ad521..8e0dd47cb077b8d9db3a457dc6cbb0c204b0a759 100644 (file)
@@ -1,45 +1,24 @@
-from __future__ import division, absolute_import, print_function
-
-import sys
-
 import numpy as np
-from numpy.compat import unicode
 from numpy.testing import assert_, assert_equal, assert_array_equal
 
-# Guess the UCS length for this python interpreter
-if sys.version_info[:2] >= (3, 3):
-    # Python 3.3 uses a flexible string representation
-    ucs4 = False
-
-    def buffer_length(arr):
-        if isinstance(arr, unicode):
-            arr = str(arr)
-            if not arr:
-                charmax = 0
-            else:
-                charmax = max([ord(c) for c in arr])
-            if charmax < 256:
-                size = 1
-            elif charmax < 65536:
-                size = 2
-            else:
-                size = 4
-            return size * len(arr)
-        v = memoryview(arr)
-        if v.shape is None:
-            return len(v) * v.itemsize
+def buffer_length(arr):
+    if isinstance(arr, str):
+        if not arr:
+            charmax = 0
+        else:
+            charmax = max([ord(c) for c in arr])
+        if charmax < 256:
+            size = 1
+        elif charmax < 65536:
+            size = 2
         else:
-            return np.prod(v.shape) * v.itemsize
-else:
-    if len(buffer(u'u')) == 4:
-        ucs4 = True
+            size = 4
+        return size * len(arr)
+    v = memoryview(arr)
+    if v.shape is None:
+        return len(v) * v.itemsize
     else:
-        ucs4 = False
-
-    def buffer_length(arr):
-        if isinstance(arr, np.ndarray):
-            return len(arr.data)
-        return len(buffer(arr))
+        return np.prod(v.shape) * v.itemsize
 
 # In both cases below we need to make sure that the byte swapped value (as
 # UCS4) is still a valid unicode:
@@ -54,12 +33,8 @@ def test_string_cast():
     uni_arr1 = str_arr.astype('>U')
     uni_arr2 = str_arr.astype('<U')
 
-    if sys.version_info[0] < 3:
-        assert_array_equal(str_arr, uni_arr1)
-        assert_array_equal(str_arr, uni_arr2)
-    else:
-        assert_(str_arr != uni_arr1)
-        assert_(str_arr != uni_arr2)
+    assert_(str_arr != uni_arr1)
+    assert_(str_arr != uni_arr2)
     assert_array_equal(uni_arr1, uni_arr2)
 
 
@@ -67,7 +42,7 @@ def test_string_cast():
 #    Creation tests
 ############################################################
 
-class CreateZeros(object):
+class CreateZeros:
     """Check the creation of zero-valued arrays"""
 
     def content_check(self, ua, ua_scalar, nbytes):
@@ -81,10 +56,7 @@ class CreateZeros(object):
         # Encode to ascii and double check
         assert_(ua_scalar.encode('ascii') == b'')
         # Check buffer lengths for scalars
-        if ucs4:
-            assert_(buffer_length(ua_scalar) == 0)
-        else:
-            assert_(buffer_length(ua_scalar) == 0)
+        assert_(buffer_length(ua_scalar) == 0)
 
     def test_zeros0D(self):
         # Check creation of 0-dimensional objects
@@ -119,7 +91,7 @@ class TestCreateZeros_1009(CreateZeros):
     ulen = 1009
 
 
-class CreateValues(object):
+class CreateValues:
     """Check the creation of unicode arrays with values"""
 
     def content_check(self, ua, ua_scalar, nbytes):
@@ -134,17 +106,14 @@ class CreateValues(object):
         assert_(ua_scalar.encode('utf-8') ==
                         (self.ucs_value*self.ulen).encode('utf-8'))
         # Check buffer lengths for scalars
-        if ucs4:
-            assert_(buffer_length(ua_scalar) == 4*self.ulen)
+        if self.ucs_value == ucs4_value:
+            # In UCS2, the \U0010FFFF will be represented using a
+            # surrogate *pair*
+            assert_(buffer_length(ua_scalar) == 2*2*self.ulen)
         else:
-            if self.ucs_value == ucs4_value:
-                # In UCS2, the \U0010FFFF will be represented using a
-                # surrogate *pair*
-                assert_(buffer_length(ua_scalar) == 2*2*self.ulen)
-            else:
-                # In UCS2, the \uFFFF will be represented using a
-                # regular 2-byte word
-                assert_(buffer_length(ua_scalar) == 2*self.ulen)
+            # In UCS2, the \uFFFF will be represented using a
+            # regular 2-byte word
+            assert_(buffer_length(ua_scalar) == 2*self.ulen)
 
     def test_values0D(self):
         # Check creation of 0-dimensional objects with values
@@ -204,7 +173,7 @@ class TestCreateValues_1009_UCS4(CreateValues):
 #    Assignment tests
 ############################################################
 
-class AssignValues(object):
+class AssignValues:
     """Check the assignment of unicode arrays with values"""
 
     def content_check(self, ua, ua_scalar, nbytes):
@@ -219,17 +188,14 @@ class AssignValues(object):
         assert_(ua_scalar.encode('utf-8') ==
                         (self.ucs_value*self.ulen).encode('utf-8'))
         # Check buffer lengths for scalars
-        if ucs4:
-            assert_(buffer_length(ua_scalar) == 4*self.ulen)
+        if self.ucs_value == ucs4_value:
+            # In UCS2, the \U0010FFFF will be represented using a
+            # surrogate *pair*
+            assert_(buffer_length(ua_scalar) == 2*2*self.ulen)
         else:
-            if self.ucs_value == ucs4_value:
-                # In UCS2, the \U0010FFFF will be represented using a
-                # surrogate *pair*
-                assert_(buffer_length(ua_scalar) == 2*2*self.ulen)
-            else:
-                # In UCS2, the \uFFFF will be represented using a
-                # regular 2-byte word
-                assert_(buffer_length(ua_scalar) == 2*self.ulen)
+            # In UCS2, the \uFFFF will be represented using a
+            # regular 2-byte word
+            assert_(buffer_length(ua_scalar) == 2*self.ulen)
 
     def test_values0D(self):
         # Check assignment of 0-dimensional objects with values
@@ -294,7 +260,7 @@ class TestAssignValues_1009_UCS4(AssignValues):
 #    Byteorder tests
 ############################################################
 
-class ByteorderValues(object):
+class ByteorderValues:
     """Check the byteorder of unicode arrays in round-trip conversions"""
 
     def test_values0D(self):
index f3b26ab72be507327f2e249f86e5cf0975728f20..6a5474ffed1433978428021f8cec1be0ab0222fb 100644 (file)
@@ -7,10 +7,11 @@ by importing from the extension module.
 """
 
 from . import _multiarray_umath
-from numpy.core._multiarray_umath import *
-from numpy.core._multiarray_umath import (
-    _UFUNC_API, _add_newdoc_ufunc, _ones_like
-    )
+from ._multiarray_umath import *  # noqa: F403
+# These imports are needed for backward compatibility,
+# do not change them. issue gh-11862
+# _ones_like is semi-public, on purpose not added to __all__
+from ._multiarray_umath import _UFUNC_API, _add_newdoc_ufunc, _ones_like
 
 __all__ = [
     '_UFUNC_API', 'ERR_CALL', 'ERR_DEFAULT', 'ERR_IGNORE', 'ERR_LOG',
index 28e325b984cb45ffc8629359ad88f780a326b330..90ab17e6744a751c4d60e9b86e150cdbc3f6ff2e 100644 (file)
@@ -2,8 +2,6 @@
 Shim for _umath_tests to allow a deprecation period for the new name.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import warnings
 
 # 2018-04-04, numpy 1.15.0
index 58f3ef9d3f08397ea57a9ddde125e4e1bdced9bb..ec3cdc33d5c15a148621236525f0b11a46412f6a 100644 (file)
@@ -49,8 +49,6 @@ Then, we're ready to call ``foo_func``:
 >>> _lib.foo_func(out, len(out))                #doctest: +SKIP
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['load_library', 'ndpointer', 'ctypes_load_library',
            'c_intp', 'as_ctypes', 'as_array']
 
index 8dbb63b28e4a1b50fc64a42354d85188a641bb52..79974d1c220a147159873079b5350f29739206bc 100644 (file)
@@ -19,8 +19,6 @@ LAPACK, and for setting include paths and similar build options, please see
 
 """
 
-from __future__ import division, absolute_import, print_function
-
 # Must import local ccompiler ASAP in order to get
 # customized CCompiler.spawn effective.
 from . import ccompiler
index 6438790234b763d8ff20be2f92b9e62767d2b73b..9ea083774d6466ceb3a0aa0bfb8fbb078aaee279 100644 (file)
@@ -1,22 +1,23 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import re
 import sys
-import types
 import shlex
 import time
 import subprocess
 from copy import copy
 from distutils import ccompiler
-from distutils.ccompiler import *
-from distutils.errors import DistutilsExecError, DistutilsModuleError, \
-                             DistutilsPlatformError, CompileError
+from distutils.ccompiler import (
+    compiler_class, gen_lib_options, get_default_compiler, new_compiler,
+    CCompiler
+)
+from distutils.errors import (
+    DistutilsExecError, DistutilsModuleError, DistutilsPlatformError,
+    CompileError, UnknownFileError
+)
 from distutils.sysconfig import customize_compiler
 from distutils.version import LooseVersion
 
 from numpy.distutils import log
-from numpy.distutils.compat import get_exception
 from numpy.distutils.exec_command import (
     filepath_from_subprocess_output, forward_bytes_to_stdout
 )
@@ -85,11 +86,8 @@ def _needs_build(obj, cc_args, extra_postargs, pp_opts):
 
 
 def replace_method(klass, method_name, func):
-    if sys.version_info[0] < 3:
-        m = types.MethodType(func, None, klass)
-    else:
-        # Py3k does not have unbound method anymore, MethodType does not work
-        m = lambda self, *args, **kw: func(self, *args, **kw)
+    # Py3k does not have unbound method anymore, MethodType does not work
+    m = lambda self, *args, **kw: func(self, *args, **kw)
     setattr(klass, method_name, m)
 
 
@@ -277,12 +275,8 @@ def CCompiler_compile(self, sources, output_dir=None, macros=None,
 
     if not sources:
         return []
-    # FIXME:RELATIVE_IMPORT
-    if sys.version_info[0] < 3:
-        from .fcompiler import FCompiler, is_f_file, has_f90_header
-    else:
-        from numpy.distutils.fcompiler import (FCompiler, is_f_file,
-                                               has_f90_header)
+    from numpy.distutils.fcompiler import (FCompiler, is_f_file,
+                                           has_f90_header)
     if isinstance(self, FCompiler):
         display = []
         for fc in ['f77', 'f90', 'fix']:
@@ -751,15 +745,15 @@ def new_compiler (plat=None,
     module_name = "numpy.distutils." + module_name
     try:
         __import__ (module_name)
-    except ImportError:
-        msg = str(get_exception())
+    except ImportError as e:
+        msg = str(e)
         log.info('%s in numpy.distutils; trying from distutils',
                  str(msg))
         module_name = module_name[6:]
         try:
             __import__(module_name)
-        except ImportError:
-            msg = str(get_exception())
+        except ImportError as e:
+            msg = str(e)
             raise DistutilsModuleError("can't compile C/C++ code: unable to load module '%s'" % \
                   module_name)
     try:
index 76a2600723deff95ac43ee57c4b1e201bbc908e4..3ba501de03b6d17da62f03b7cf66f07232679533 100644 (file)
@@ -4,8 +4,6 @@ Package containing implementation of all the standard Distutils
 commands.
 
 """
-from __future__ import division, absolute_import, print_function
-
 def test_na_writable_attributes_deletion():
     a = np.NA(2)
     attr =  ['payload', 'dtype']
index 9c98b84d8822d4df470d4b39b3f08e2d0dee2352..8f6436004a0a0934c4ef8fadbe86b432f8c17679 100644 (file)
@@ -1,8 +1,6 @@
 """This module implements additional tests ala autoconf which can be useful.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import textwrap
 
 # We put them here since they could be easily reused outside numpy.distutils
@@ -71,7 +69,10 @@ def check_gcc_function_attribute(cmd, attribute, name):
         #pragma GCC diagnostic error "-Wattributes"
         #pragma clang diagnostic error "-Wattributes"
 
-        int %s %s(void*);
+        int %s %s(void* unused)
+        {
+            return 0;
+        }
 
         int
         main()
index 3e52a503b172141f6d28799841e6df4332b59db8..682e7a8eb8e2b8cdd922fe77ed13992c5a7a1252 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 if 'setuptools' in sys.modules:
index 5a9da1217c2bdf448a482dbcd1eb388664930ded..a156a7c6ed5f1d73525211176872a7ec3b0cf62c 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 from distutils.command.build import build as old_build
index 13edf07177984f298ca9454643d7528aab3c5668..f6a84e3516cc99c55b36a90da6c8727188c7d437 100644 (file)
@@ -1,7 +1,5 @@
 """ Modified version of build_clib that handles fortran source files.
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 from glob import glob
 import shutil
@@ -11,9 +9,10 @@ from distutils.errors import DistutilsSetupError, DistutilsError, \
 
 from numpy.distutils import log
 from distutils.dep_util import newer_group
-from numpy.distutils.misc_util import filter_sources, has_f_sources,\
-     has_cxx_sources, all_strings, get_lib_source_files, is_sequence, \
-     get_numpy_include_dirs
+from numpy.distutils.misc_util import (
+    filter_sources, get_lib_source_files, get_numpy_include_dirs,
+    has_cxx_sources, has_f_sources, is_sequence
+)
 
 # Fix Python distutils bug sf #1718574:
 _l = old_build_clib.user_options
@@ -50,8 +49,8 @@ class build_clib(old_build_clib):
         if self.parallel:
             try:
                 self.parallel = int(self.parallel)
-            except ValueError:
-                raise ValueError("--parallel/-j argument must be an integer")
+            except ValueError as e:
+                raise ValueError("--parallel/-j argument must be an integer") from e
         old_build_clib.finalize_options(self)
         self.set_undefined_options('build',
                                         ('parallel', 'parallel'),
index 52e2a5931303bfc2035bee7dc056187f772d28d9..d53285c92b0574ee0231a5ad7a1b91dc005151f0 100644 (file)
@@ -1,8 +1,6 @@
 """ Modified version of build_ext that handles fortran source files.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 import subprocess
 from glob import glob
@@ -15,11 +13,11 @@ from distutils.file_util import copy_file
 
 from numpy.distutils import log
 from numpy.distutils.exec_command import filepath_from_subprocess_output
-from numpy.distutils.system_info import combine_paths, system_info
-from numpy.distutils.misc_util import filter_sources, has_f_sources, \
-    has_cxx_sources, get_ext_source_files, \
-    get_numpy_include_dirs, is_sequence, get_build_architecture, \
-    msvc_version
+from numpy.distutils.system_info import combine_paths
+from numpy.distutils.misc_util import (
+    filter_sources, get_ext_source_files, get_numpy_include_dirs,
+    has_cxx_sources, has_f_sources, is_sequence
+)
 from numpy.distutils.command.config_compiler import show_fortran_compilers
 
 
@@ -54,8 +52,8 @@ class build_ext (old_build_ext):
         if self.parallel:
             try:
                 self.parallel = int(self.parallel)
-            except ValueError:
-                raise ValueError("--parallel/-j argument must be an integer")
+            except ValueError as e:
+                raise ValueError("--parallel/-j argument must be an integer") from e
 
         # Ensure that self.include_dirs and self.distribution.include_dirs
         # refer to the same list object. finalize_options will modify
index 54dcde43508396bf2c1ccd7887f7716ffe3cdb6d..d30dc5bf42d806e03b055627b7f813f4b772d2f5 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from distutils.command.build_py import build_py as old_build_py
 from numpy.distutils.misc_util import is_string
 
index c8b25fc719b593ca63dcf31d7693c0de6dcea3df..d5cadb2745fefccf2efe646afa986452461e48a0 100644 (file)
@@ -1,8 +1,6 @@
 """ Modified version of build_scripts that handles building scripts from functions.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from distutils.command.build_scripts import build_scripts as old_build_scripts
 from numpy.distutils import log
 from numpy.distutils.misc_util import is_string
index 3e0522c5f82bc236298878d78694fbc3dcfaef77..303d6197cbd3ed734752d87bf9d2331d7168f6a7 100644 (file)
@@ -1,7 +1,5 @@
 """ Build swig and f2py sources.
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 import re
 import sys
index b9f2fa76e26020f6b4aff61958c27b546d82224b..e54a5444995b66ee007c6ca97244fcb9f53c3ce5 100644 (file)
@@ -2,13 +2,12 @@
 # try_compile call. try_run works but is untested for most of Fortran
 # compilers (they must define linker_exe first).
 # Pearu Peterson
-from __future__ import division, absolute_import, print_function
-
-import os, signal
-import warnings
-import sys
+import os
+import signal
 import subprocess
+import sys
 import textwrap
+import warnings
 
 from distutils.command.config import config as old_config
 from distutils.command.config import LANG_EXT
@@ -24,7 +23,6 @@ from numpy.distutils.command.autodist import (check_gcc_function_attribute,
                                               check_inline,
                                               check_restrict,
                                               check_compiler_gcc4)
-from numpy.distutils.compat import get_exception
 
 LANG_EXT['f77'] = '.f'
 LANG_EXT['f90'] = '.f90'
@@ -52,8 +50,7 @@ class config(old_config):
             if not self.compiler.initialized:
                 try:
                     self.compiler.initialize()
-                except IOError:
-                    e = get_exception()
+                except IOError as e:
                     msg = textwrap.dedent("""\
                         Could not initialize compiler instance: do you have Visual Studio
                         installed?  If you are trying to build with MinGW, please use "python setup.py
@@ -96,8 +93,8 @@ class config(old_config):
             self.compiler = self.fcompiler
         try:
             ret = mth(*((self,)+args))
-        except (DistutilsExecError, CompileError):
-            str(get_exception())
+        except (DistutilsExecError, CompileError) as e:
+            str(e)
             self.compiler = save_compiler
             raise CompileError
         self.compiler = save_compiler
@@ -495,7 +492,7 @@ class config(old_config):
         self._clean()
         return exitcode, output
 
-class GrabStdout(object):
+class GrabStdout:
 
     def __init__(self):
         self.sys_stdout = sys.stdout
index bf170063ede89da46b50e9925c4f55d3cb2d9a9b..44265bfcce8916ddd3e07130576b4b30ba74695d 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from distutils.core import Command
 from numpy.distutils import log
 
index 1410ab2a00fd401fea48d25315a95a2d7fb9e488..af24baf2e7e1e7ff715788cb5acfcbefaafebd48 100644 (file)
@@ -3,8 +3,6 @@ generated files (from build_src or build_scripts) are properly converted to real
 files with filenames.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from setuptools.command.develop import develop as old_develop
 
 class develop(old_develop):
index 18673ece7d196c47fab3983df7a2f5f45f8f0c64..14c62b4d1b905ec71d8ab97dfdb3f18638d707f1 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 
 from setuptools.command.egg_info import egg_info as _egg_info
index c74ae94468a0d94085b2d5e107cb566c8dcaf2bd..2eff2d1450473c28774758f2ad29081586c1ef99 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 if 'setuptools' in sys.modules:
     import setuptools.command.install as old_install_mod
index 6a73f7e3308ff0aa6b9f6454bfa43673fdd0e9b1..aa2e5594c3c2e87434f7db1e0ffb7b8aa12f7fce 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 from distutils.core import Command
 from distutils.ccompiler import new_compiler
index 996cf7e4017a68dc4983c816ddbbbd8ad01b22e3..0a2e68ae192ae95422ae47136054d394bb45d2f0 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 have_setuptools = ('setuptools' in sys.modules)
 
index f3f58aa2876fdb358e83d0e72ded83e045911430..bb4ad563b2a5398039e7e569408545c3e1d2fa4e 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 from distutils.command.install_headers import install_headers as old_install_headers
 
index bfaab1c8ffa18333e41db6a9d976ce6971f5d26d..e34193883dea739b09792a86bfc3d4c03b42cb5a 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 if 'setuptools' in sys.modules:
     from setuptools.command.sdist import sdist as old_sdist
diff --git a/numpy/distutils/compat.py b/numpy/distutils/compat.py
deleted file mode 100644 (file)
index 9a81cd3..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-"""Small modules to cope with python 2 vs 3 incompatibilities inside
-numpy.distutils
-
-"""
-from __future__ import division, absolute_import, print_function
-
-import sys
-
-def get_exception():
-    return sys.exc_info()[1]
index 3bcb7b8845ecce1da7251f8eed70454b964f4be0..d08015fdf39f5aeaa625da418624b32cee72122c 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 takes templated file .xxx.src and produces .xxx file  where .xxx is
 .i or .c or .h, using the following template rules
@@ -78,8 +78,6 @@ Example:
         3, 3, jim
 
 """
-from __future__ import division, absolute_import, print_function
-
 
 __all__ = ['process_str', 'process_file']
 
@@ -87,8 +85,6 @@ import os
 import sys
 import re
 
-from numpy.distutils.compat import get_exception
-
 # names for replacement that are already global.
 global_names = {}
 
@@ -240,8 +236,7 @@ def parse_string(astr, env, level, line) :
             code.append(replace_re.sub(replace, pref))
             try :
                 envlist = parse_loop_header(head)
-            except ValueError:
-                e = get_exception()
+            except ValueError as e:
                 msg = "line %d: %s" % (newline, e)
                 raise ValueError(msg)
             for newenv in envlist :
@@ -289,8 +284,7 @@ def process_file(source):
     sourcefile = os.path.normcase(source).replace("\\", "\\\\")
     try:
         code = process_str(''.join(lines))
-    except ValueError:
-        e = get_exception()
+    except ValueError as e:
         raise ValueError('In "%s" loop at %s' % (sourcefile, e))
     return '#line 1 "%s"\n%s' % (sourcefile, code)
 
@@ -327,8 +321,7 @@ def main():
     allstr = fid.read()
     try:
         writestr = process_str(allstr)
-    except ValueError:
-        e = get_exception()
+    except ValueError as e:
         raise ValueError("In %s loop at %s" % (file, e))
 
     outfile.write(writestr)
index 70cc37caa32b2dfe0f5f86a8e7f29f22fbf51380..d5551f3490d155f0c253ff530fede5a89e2483b8 100644 (file)
@@ -1,7 +1,5 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
-from distutils.core import *
+from distutils.core import Distribution
 
 if 'setuptools' in sys.modules:
     have_setuptools = True
@@ -27,7 +25,7 @@ from numpy.distutils.command import config, config_compiler, \
      build, build_py, build_ext, build_clib, build_src, build_scripts, \
      sdist, install_data, install_headers, install, bdist_rpm, \
      install_clib
-from numpy.distutils.misc_util import get_data_files, is_sequence, is_string
+from numpy.distutils.misc_util import is_sequence, is_string
 
 numpy_cmdclass = {'build':            build.build,
                   'build_src':        build_src.build_src,
index bc9728335018be3c0285b1bbc2fb026fc48c5af9..51ce3c1291b44592f76047ecaa0d5651090b898b 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 cpuinfo
 
@@ -12,28 +12,22 @@ NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['cpu']
 
-import sys, re, types
 import os
-
-if sys.version_info[0] >= 3:
-    from subprocess import getstatusoutput
-else:
-    from commands import getstatusoutput
-
-import warnings
 import platform
+import re
+import sys
+import types
+import warnings
+
+from subprocess import getstatusoutput
 
-from numpy.distutils.compat import get_exception
 
 def getoutput(cmd, successful_status=(0,), stacklevel=1):
     try:
         status, output = getstatusoutput(cmd)
-    except EnvironmentError:
-        e = get_exception()
+    except EnvironmentError as e:
         warnings.warn(str(e), UserWarning, stacklevel=stacklevel)
         return False, ""
     if os.WIFEXITED(status) and os.WEXITSTATUS(status) in successful_status:
@@ -67,7 +61,7 @@ def key_value_from_command(cmd, sep, successful_status=(0,),
             d[l[0]] = l[1]
     return d
 
-class CPUInfoBase(object):
+class CPUInfoBase:
     """Holds CPU information and provides methods for requiring
     the availability of various CPU features.
     """
@@ -115,8 +109,7 @@ class LinuxCPUInfo(CPUInfoBase):
             info[0]['uname_m'] = output.strip()
         try:
             fo = open('/proc/cpuinfo')
-        except EnvironmentError:
-            e = get_exception()
+        except EnvironmentError as e:
             warnings.warn(str(e), UserWarning, stacklevel=2)
         else:
             for line in fo:
@@ -490,10 +483,7 @@ class Win32CPUInfo(CPUInfoBase):
         info = []
         try:
             #XXX: Bad style to use so long `try:...except:...`. Fix it!
-            if sys.version_info[0] >= 3:
-                import winreg
-            else:
-                import _winreg as winreg
+            import winreg
 
             prgx = re.compile(r"family\s+(?P<FML>\d+)\s+model\s+(?P<MDL>\d+)"
                               r"\s+stepping\s+(?P<STP>\d+)", re.IGNORECASE)
@@ -523,8 +513,8 @@ class Win32CPUInfo(CPUInfoBase):
                                     info[-1]["Family"]=int(srch.group("FML"))
                                     info[-1]["Model"]=int(srch.group("MDL"))
                                     info[-1]["Stepping"]=int(srch.group("STP"))
-        except Exception:
-            print(sys.exc_info()[1], '(ignoring)')
+        except Exception as e:
+            print(e, '(ignoring)')
         self.__class__.info = info
 
     def _not_impl(self): pass
index 712f22666b391e322b1844191845e291cf18506f..fb10d247069bc9a195a39697d590b0948b066d52 100644 (file)
@@ -49,8 +49,6 @@ Known bugs:
   because the messages are lost at some point.
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['exec_command', 'find_executable']
 
 import os
@@ -76,10 +74,6 @@ def filepath_from_subprocess_output(output):
     # Another historical oddity
     if output[-1:] == '\n':
         output = output[:-1]
-    # stdio uses bytes in python 2, so to avoid issues, we simply
-    # remove all non-ascii characters
-    if sys.version_info < (3, 0):
-        output = output.encode('ascii', errors='replace')
     return output
 
 
@@ -91,10 +85,7 @@ def forward_bytes_to_stdout(val):
     The assumption is that the subprocess call already returned bytes in
     a suitable encoding.
     """
-    if sys.version_info.major < 3:
-        # python 2 has binary output anyway
-        sys.stdout.write(val)
-    elif hasattr(sys.stdout, 'buffer'):
+    if hasattr(sys.stdout, 'buffer'):
         # use the underlying binary output if there is one
         sys.stdout.buffer.write(val)
     elif hasattr(sys.stdout, 'encoding'):
@@ -307,11 +298,6 @@ def _exec_command(command, use_shell=None, use_tee = None, **env):
     if text[-1:] == '\n':
         text = text[:-1]
 
-    # stdio uses bytes in python 2, so to avoid issues, we simply
-    # remove all non-ascii characters
-    if sys.version_info < (3, 0):
-        text = text.encode('ascii', errors='replace')
-
     if use_tee and text:
         print(text)
     return proc.returncode, text
index 872bd5362f2e7e45dedb07bd0cf19ff73d96f478..67114ef2e3f7e0def150cee0b6bae332685e7801 100644 (file)
@@ -6,15 +6,9 @@ modules in setup scripts.
 Overridden to support f2py.
 
 """
-from __future__ import division, absolute_import, print_function
-
-import sys
 import re
 from distutils.extension import Extension as old_Extension
 
-if sys.version_info[0] >= 3:
-    basestring = str
-
 
 cxx_ext_re = re.compile(r'.*[.](cpp|cxx|cc)\Z', re.I).match
 fortran_pyf_ext_re = re.compile(r'.*[.](f90|f95|f77|for|ftn|f|pyf)\Z', re.I).match
@@ -76,7 +70,7 @@ class Extension(old_Extension):
         self.swig_opts = swig_opts or []
         # swig_opts is assumed to be a list. Here we handle the case where it
         # is specified as a string instead.
-        if isinstance(self.swig_opts, basestring):
+        if isinstance(self.swig_opts, str):
             import warnings
             msg = "swig_opts is specified as a string instead of a list"
             warnings.warn(msg, SyntaxWarning, stacklevel=2)
index 3723470f32f47127b6061bdfacd3fa503396e9ab..1c3069363f84e2150f277a24369f3e3872ad0037 100644 (file)
@@ -13,15 +13,12 @@ should be a list.
 But note that FCompiler.executables is actually a dictionary of commands.
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['FCompiler', 'new_fcompiler', 'show_fcompilers',
            'dummy_fortran_file']
 
 import os
 import sys
 import re
-import types
 
 from numpy.compat import open_latin1
 
@@ -36,7 +33,6 @@ from numpy.distutils import log
 from numpy.distutils.misc_util import is_string, all_strings, is_sequence, \
     make_temp_file, get_shared_lib_extension
 from numpy.distutils.exec_command import find_executable
-from numpy.distutils.compat import get_exception
 from numpy.distutils import _shell_utils
 
 from .environment import EnvironmentConfig
@@ -614,8 +610,8 @@ class FCompiler(CCompiler):
                               src)
         try:
             self.spawn(command, display=display)
-        except DistutilsExecError:
-            msg = str(get_exception())
+        except DistutilsExecError as e:
+            msg = str(e)
             raise CompileError(msg)
 
     def module_options(self, module_dirs, module_build_dir):
@@ -682,8 +678,8 @@ class FCompiler(CCompiler):
             command = linker + ld_args
             try:
                 self.spawn(command)
-            except DistutilsExecError:
-                msg = str(get_exception())
+            except DistutilsExecError as e:
+                msg = str(e)
                 raise LinkError(msg)
         else:
             log.debug("skipping %s (up-to-date)", output_filename)
@@ -931,8 +927,7 @@ def show_fcompilers(dist=None):
             c = new_fcompiler(compiler=compiler, verbose=dist.verbose)
             c.customize(dist)
             v = c.get_version()
-        except (DistutilsModuleError, CompilerNotFound):
-            e = get_exception()
+        except (DistutilsModuleError, CompilerNotFound) as e:
             log.debug("show_fcompilers: %s not found" % (compiler,))
             log.debug(repr(e))
 
index d14fee0e18e3aa8b85987abff2b4404e220c5b84..efe3a4cb55e94f7b6ca55fdac0d1c29ca3102871 100644 (file)
@@ -5,8 +5,6 @@
 # Notes:
 # - when using -g77 then use -DUNDERSCORE_G77 to compile f2py
 #   generated extension modules (works for f2py v2.45.241_1936 and up)
-from __future__ import division, absolute_import, print_function
-
 import os
 
 from numpy.distutils.cpuinfo import cpu
index 671b3a55f2909e2c1983a5662b6c77931c23ddd8..6ce590c7c8215ccec42f0021b20b55269950ec5a 100644 (file)
@@ -1,12 +1,9 @@
 
 #http://www.compaq.com/fortran/docs/
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 
 from numpy.distutils.fcompiler import FCompiler
-from numpy.distutils.compat import get_exception
 from distutils.errors import DistutilsPlatformError
 
 compilers = ['CompaqFCompiler']
@@ -82,19 +79,16 @@ class CompaqVisualFCompiler(FCompiler):
             ar_exe = m.lib
         except DistutilsPlatformError:
             pass
-        except AttributeError:
-            msg = get_exception()
+        except AttributeError as e:
             if '_MSVCCompiler__root' in str(msg):
                 print('Ignoring "%s" (I think it is msvccompiler.py bug)' % (msg))
             else:
                 raise
-        except IOError:
-            e = get_exception()
+        except IOError as e:
             if not "vcvarsall.bat" in str(e):
                 print("Unexpected IOError in", __file__)
                 raise e
-        except ValueError:
-            e = get_exception()
+        except ValueError as e:
             if not "'path'" in str(e):
                 print("Unexpected ValueError in", __file__)
                 raise e
index bb362d48336422b24123876f59d2b9cd8844721e..21a5be00389ee1dda1790324325ae76002072d65 100644 (file)
@@ -1,12 +1,9 @@
-from __future__ import division, absolute_import, print_function
-
 import os
-import warnings
 from distutils.dist import Distribution
 
 __metaclass__ = type
 
-class EnvironmentConfig(object):
+class EnvironmentConfig:
     def __init__(self, distutils_section='ALL', **kw):
         self._distutils_section = distutils_section
         self._conf_keys = kw
index e7c659b332c2a603d0775d43daea517f877a44ee..e109a972a8729ba886f86b16530b2ed315dcce8b 100644 (file)
@@ -1,6 +1,4 @@
 # http://g95.sourceforge.net/
-from __future__ import division, absolute_import, print_function
-
 from numpy.distutils.fcompiler import FCompiler
 
 compilers = ['G95FCompiler']
index 965c67041082b1ff0fdfcaca613c8c315186c1cd..23d905393b598106b89c2abb7ff6d5c28bc268cd 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import re
 import os
 import sys
@@ -12,8 +10,7 @@ import subprocess
 from subprocess import Popen, PIPE, STDOUT
 from numpy.distutils.exec_command import filepath_from_subprocess_output
 from numpy.distutils.fcompiler import FCompiler
-from numpy.distutils.compat import get_exception
-from numpy.distutils.system_info import system_info
+from distutils.version import LooseVersion
 
 compilers = ['GnuFCompiler', 'Gnu95FCompiler']
 
@@ -126,26 +123,17 @@ class GnuFCompiler(FCompiler):
             # error checking.
             if not target:
                 # If MACOSX_DEPLOYMENT_TARGET is not set in the environment,
-                # we try to get it first from the Python Makefile and then we
-                # fall back to setting it to 10.3 to maximize the set of
-                # versions we can work with.  This is a reasonable default
+                # we try to get it first from sysconfig and then
+                # fall back to setting it to 10.9 This is a reasonable default
                 # even when using the official Python dist and those derived
                 # from it.
-                import distutils.sysconfig as sc
-                g = {}
-                try:
-                    get_makefile_filename = sc.get_makefile_filename
-                except AttributeError:
-                    pass  # i.e. PyPy
-                else:
-                    filename = get_makefile_filename()
-                    sc.parse_makefile(filename, g)
-                target = g.get('MACOSX_DEPLOYMENT_TARGET', '10.3')
-                os.environ['MACOSX_DEPLOYMENT_TARGET'] = target
-                if target == '10.3':
-                    s = 'Env. variable MACOSX_DEPLOYMENT_TARGET set to 10.3'
+                import sysconfig
+                target = sysconfig.get_config_var('MACOSX_DEPLOYMENT_TARGET')
+                if not target:
+                    target = '10.9'
+                    s = f'Env. variable MACOSX_DEPLOYMENT_TARGET set to {target}'
                     warnings.warn(s, stacklevel=2)
-
+                os.environ['MACOSX_DEPLOYMENT_TARGET'] = target
             opt.extend(['-undefined', 'dynamic_lookup', '-bundle'])
         else:
             opt.append("-shared")
@@ -286,7 +274,7 @@ class Gnu95FCompiler(GnuFCompiler):
         if not v or v[0] != 'gfortran':
             return None
         v = v[1]
-        if v >= '4.':
+        if LooseVersion(v) >= "4":
             # gcc-4 series releases do not support -mno-cygwin option
             pass
         else:
@@ -415,8 +403,7 @@ class Gnu95FCompiler(GnuFCompiler):
                         break
                     h.update(block)
         text = base64.b32encode(h.digest())
-        if sys.version_info[0] >= 3:
-            text = text.decode('ascii')
+        text = text.decode('ascii')
         return text.rstrip('=')
 
     def _link_wrapper_lib(self, objects, output_dir, extra_dll_dir,
@@ -560,5 +547,5 @@ if __name__ == '__main__':
     print(customized_fcompiler('gnu').get_version())
     try:
         print(customized_fcompiler('g95').get_version())
-    except Exception:
-        print(get_exception())
+    except Exception as e:
+        print(e)
index 51bad548a124f3f9fe9e3ff26605bff43d40316b..09e6483bf5adb89fee267a153c82ef76ccb1e12a 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy.distutils.fcompiler import FCompiler
 
 compilers = ['HPUXFCompiler']
index 70d2132e1491b27a7cd3832975d0ec608d55b45c..4a83682e5165b5f5469ba4572a415da68f542f4a 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import re
 import sys
index 51f6812743a28a47232e5d2f0cd4590328c4833a..c7b3c2340df605f08810b77a3c09086f1723277f 100644 (file)
@@ -1,6 +1,4 @@
 # http://developer.intel.com/software/products/compilers/flin/
-from __future__ import division, absolute_import, print_function
-
 import sys
 
 from numpy.distutils.ccompiler import simple_version_match
@@ -61,7 +59,7 @@ class IntelFCompiler(BaseIntelFCompiler):
     def get_flags_opt(self):  # Scipy test failures with -O2
         v = self.get_version()
         mpopt = 'openmp' if v and v < '15' else 'qopenmp'
-        return ['-fp-model strict -O1 -{}'.format(mpopt)]
+        return ['-fp-model', 'strict', '-O1', '-{}'.format(mpopt)]
 
     def get_flags_arch(self):
         return []
@@ -127,10 +125,10 @@ class IntelEM64TFCompiler(IntelFCompiler):
     def get_flags_opt(self):  # Scipy test failures with -O2
         v = self.get_version()
         mpopt = 'openmp' if v and v < '15' else 'qopenmp'
-        return ['-fp-model strict -O1 -{}'.format(mpopt)]
+        return ['-fp-model', 'strict', '-O1', '-{}'.format(mpopt)]
 
     def get_flags_arch(self):
-        return ['']
+        return []
 
 # Is there no difference in the version string between the above compilers
 # and the Visual compilers?
@@ -212,7 +210,7 @@ class IntelEM64VisualFCompiler(IntelVisualFCompiler):
     version_match = simple_version_match(start=r'Intel\(R\).*?64,')
 
     def get_flags_arch(self):
-        return ['']
+        return []
 
 
 if __name__ == '__main__':
index 1beb662f4e93666ebbb79c92117432c30919589f..e925838268b82d9c26d94e811717cdc58e269a12 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 
 from numpy.distutils.fcompiler import FCompiler
index da337b24a3ffcbc8815e27879828d59b8e71c369..a0973804571b1404400e0749533a001d0833f905 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy.distutils.cpuinfo import cpu
 from numpy.distutils.fcompiler import FCompiler
 
index cb71d548cd2d4cb5ec7a1d90abebc34df16138e3..908e724e65363bf90605fa48805a15e8f9a29f94 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import re
 from numpy.distutils.fcompiler import FCompiler
index bdeea1560e91ab91ef002ae950a6f103c14b9e48..ef411fffc7cb7e1d8fac4872eb31292b9fc5d7bb 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy.distutils.fcompiler import FCompiler
 from numpy.distutils import customized_fcompiler
 
index 5de86f63aee637ac1df38e0869b126bcd096814d..0768cb12e87a54aa7fc0d10a04d97953eaa8aa41 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy.distutils.fcompiler import FCompiler
 
 compilers = ['PathScaleFCompiler']
index 9c51947fd80335e4a33cbbcf82d4193f885f2629..eb628cb63d8e0858186a1c80890cdbbcf18bf4d8 100644 (file)
@@ -1,9 +1,7 @@
 # http://www.pgroup.com
-from __future__ import division, absolute_import, print_function
-
 import sys
 
-from numpy.distutils.fcompiler import FCompiler, dummy_fortran_file
+from numpy.distutils.fcompiler import FCompiler
 from sys import platform
 from os.path import join, dirname, normpath
 
@@ -64,72 +62,60 @@ class PGroupFCompiler(FCompiler):
         return '-R%s' % dir
 
 
-if sys.version_info >= (3, 5):
-    import functools
-
-    class PGroupFlangCompiler(FCompiler):
-        compiler_type = 'flang'
-        description = 'Portland Group Fortran LLVM Compiler'
-        version_pattern = r'\s*(flang|clang) version (?P<version>[\d.-]+).*'
-
-        ar_exe = 'lib.exe'
-        possible_executables = ['flang']
-
-        executables = {
-            'version_cmd': ["<F77>", "--version"],
-            'compiler_f77': ["flang"],
-            'compiler_fix': ["flang"],
-            'compiler_f90': ["flang"],
-            'linker_so': [None],
-            'archiver': [ar_exe, "/verbose", "/OUT:"],
-            'ranlib': None
-        }
+import functools
 
-        library_switch = '/OUT:'  # No space after /OUT:!
-        module_dir_switch = '-module '  # Don't remove ending space!
+class PGroupFlangCompiler(FCompiler):
+    compiler_type = 'flang'
+    description = 'Portland Group Fortran LLVM Compiler'
+    version_pattern = r'\s*(flang|clang) version (?P<version>[\d.-]+).*'
 
-        def get_libraries(self):
-            opt = FCompiler.get_libraries(self)
-            opt.extend(['flang', 'flangrti', 'ompstub'])
-            return opt
+    ar_exe = 'lib.exe'
+    possible_executables = ['flang']
 
-        @functools.lru_cache(maxsize=128)
-        def get_library_dirs(self):
-            """List of compiler library directories."""
-            opt = FCompiler.get_library_dirs(self)
-            flang_dir = dirname(self.executables['compiler_f77'][0])
-            opt.append(normpath(join(flang_dir, '..', 'lib')))
+    executables = {
+        'version_cmd': ["<F77>", "--version"],
+        'compiler_f77': ["flang"],
+        'compiler_fix': ["flang"],
+        'compiler_f90': ["flang"],
+        'linker_so': [None],
+        'archiver': [ar_exe, "/verbose", "/OUT:"],
+        'ranlib': None
+    }
 
-            return opt
+    library_switch = '/OUT:'  # No space after /OUT:!
+    module_dir_switch = '-module '  # Don't remove ending space!
 
-        def get_flags(self):
-            return []
+    def get_libraries(self):
+        opt = FCompiler.get_libraries(self)
+        opt.extend(['flang', 'flangrti', 'ompstub'])
+        return opt
 
-        def get_flags_free(self):
-            return []
+    @functools.lru_cache(maxsize=128)
+    def get_library_dirs(self):
+        """List of compiler library directories."""
+        opt = FCompiler.get_library_dirs(self)
+        flang_dir = dirname(self.executables['compiler_f77'][0])
+        opt.append(normpath(join(flang_dir, '..', 'lib')))
 
-        def get_flags_debug(self):
-            return ['-g']
+        return opt
 
-        def get_flags_opt(self):
-            return ['-O3']
+    def get_flags(self):
+        return []
 
-        def get_flags_arch(self):
-            return []
+    def get_flags_free(self):
+        return []
 
-        def runtime_library_dir_option(self, dir):
-            raise NotImplementedError
+    def get_flags_debug(self):
+        return ['-g']
 
-else:
-    from numpy.distutils.fcompiler import CompilerNotFound
+    def get_flags_opt(self):
+        return ['-O3']
 
-    # No point in supporting on older Pythons because not ABI compatible
-    class PGroupFlangCompiler(FCompiler):
-        compiler_type = 'flang'
-        description = 'Portland Group Fortran LLVM Compiler'
+    def get_flags_arch(self):
+        return []
 
-        def get_version(self):
-            raise CompilerNotFound('Flang unsupported on Python < 3.5')
+    def runtime_library_dir_option(self, dir):
+        raise NotImplementedError
 
 
 if __name__ == '__main__':
index 561ea854f9826a23cb4004d94e6d233c8c22262e..d039f0b25705afc915da5266958f0d0ba1145763 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy.distutils.ccompiler import simple_version_match
 from numpy.distutils.fcompiler import FCompiler
 
index adc1591bde91ce69b83d7b9d3acb4d4252f267dd..92a1647ba43708084ce85e0b986cb9d71329b842 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 
 from numpy.distutils.fcompiler.gnu import GnuFCompiler
index c5c1163c63c4575da51788d5bca617275596066b..070b7d8b885575733724d7a0acc776f0bd9cf25b 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 process_file(filename)
@@ -45,8 +45,6 @@ process_file(filename)
   <ctypereal=float,double,\\0,\\1>
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['process_str', 'process_file']
 
 import os
index 3386775ee56ab03fe476c08653d99a19d532e47a..0388ad57751848887191127698f40a5c45e4445f 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import platform
 
 from distutils.unixccompiler import UnixCCompiler
index 34b1eceaff2321965ee4f4587e6ee89c5b8234eb..820ed71f5808a1345070a6452404c2745591cb0b 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import re
 import sys
 import subprocess
index fe8fd1b0fe6a6fa858073a4ea12c9fdeab388e7f..686e5ebd937fff16d5aa7f154d5c823ed17d9e0a 100644 (file)
@@ -1,9 +1,10 @@
 """ Functions for converting from DOS to UNIX line endings
 
 """
-from __future__ import division, absolute_import, print_function
+import os
+import re
+import sys
 
-import sys, re, os
 
 def dos2unix(file):
     "Replace CRLF with LF in argument files.  Print names of changed files."
index ff7de86b1147d0096152f2a54a57c7d9140b91e1..a8113b9c6e1a9b37b763dc24420bd780caa40bb1 100644 (file)
@@ -1,17 +1,11 @@
-# Colored log, requires Python 2.3 or up.
-from __future__ import division, absolute_import, print_function
-
+# Colored log
 import sys
-from distutils.log import *
+from distutils.log import *  # noqa: F403
 from distutils.log import Log as old_Log
 from distutils.log import _global_log
 
-if sys.version_info[0] < 3:
-    from .misc_util import (red_text, default_text, cyan_text, green_text,
-            is_sequence, is_string)
-else:
-    from numpy.distutils.misc_util import (red_text, default_text, cyan_text,
-            green_text, is_sequence, is_string)
+from numpy.distutils.misc_util import (red_text, default_text, cyan_text,
+        green_text, is_sequence, is_string)
 
 
 def _fix_args(args,flag=1):
index a56cc8f8cf97e1fd88de39b6db9527c6ae6aedb5..7cb6fadcca4a3165c8b74f7e25e122ea3623a8e6 100644 (file)
@@ -7,8 +7,6 @@ Support code for building Python extensions on Windows.
     # 3. Force windows to use g77
 
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 import subprocess
@@ -16,12 +14,8 @@ import re
 import textwrap
 
 # Overwrite certain distutils.ccompiler functions:
-import numpy.distutils.ccompiler
-
-if sys.version_info[0] < 3:
-    from . import log
-else:
-    from numpy.distutils import log
+import numpy.distutils.ccompiler  # noqa: F401
+from numpy.distutils import log
 # NT stuff
 # 1. Make sure libpython<version>.a exists for gcc.  If not, build it.
 # 2. Force windows to use gcc (we're struggling with MSVC and g77 support)
@@ -32,8 +26,7 @@ import distutils.cygwinccompiler
 from distutils.version import StrictVersion
 from distutils.unixccompiler import UnixCCompiler
 from distutils.msvccompiler import get_build_version as get_build_msvc_version
-from distutils.errors import (DistutilsExecError, CompileError,
-                              UnknownFileError)
+from distutils.errors import UnknownFileError
 from numpy.distutils.misc_util import (msvc_runtime_library,
                                        msvc_runtime_version,
                                        msvc_runtime_major,
index bb1699eade21cd781aaf99ba54069255d08d9c9a..9f9e9f1ac44a12a1f866d12b39c3e84ad05df039 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import re
 import sys
@@ -34,8 +32,6 @@ def clean_up_temporary_directory():
 
 atexit.register(clean_up_temporary_directory)
 
-from numpy.distutils.compat import get_exception
-from numpy.compat import basestring
 from numpy.compat import npy_load_module
 
 __all__ = ['Configuration', 'get_numpy_include_dirs', 'default_config_dict',
@@ -51,7 +47,7 @@ __all__ = ['Configuration', 'get_numpy_include_dirs', 'default_config_dict',
            'quote_args', 'get_build_architecture', 'get_info', 'get_pkg_info',
            'get_num_build_jobs']
 
-class InstallableLib(object):
+class InstallableLib:
     """
     Container to hold information on an installable library.
 
@@ -168,7 +164,6 @@ def get_path_from_frame(frame, parent_path=None):
             # we're probably running setup.py as execfile("setup.py")
             # (likely we're building an egg)
             d = os.path.abspath('.')
-            # hmm, should we use sys.argv[0] like in __builtin__ case?
 
     if parent_path is not None:
         d = rel_path(d, parent_path)
@@ -453,7 +448,7 @@ def _get_f90_modules(source):
     return modules
 
 def is_string(s):
-    return isinstance(s, basestring)
+    return isinstance(s, str)
 
 def all_strings(lst):
     """Return True if all items in lst are string objects. """
@@ -728,7 +723,7 @@ def get_frame(level=0):
 
 ######################
 
-class Configuration(object):
+class Configuration:
 
     _list_keys = ['packages', 'ext_modules', 'data_files', 'include_dirs',
                   'libraries', 'headers', 'scripts', 'py_modules',
@@ -926,18 +921,8 @@ class Configuration(object):
             else:
                 pn = dot_join(*([parent_name] + subpackage_name.split('.')[:-1]))
                 args = (pn,)
-                def fix_args_py2(args):
-                    if setup_module.configuration.__code__.co_argcount > 1:
-                        args = args + (self.top_path,)
-                    return args
-                def fix_args_py3(args):
-                    if setup_module.configuration.__code__.co_argcount > 1:
-                        args = args + (self.top_path,)
-                    return args
-                if sys.version_info[0] < 3:
-                    args = fix_args_py2(args)
-                else:
-                    args = fix_args_py3(args)
+                if setup_module.configuration.__code__.co_argcount > 1:
+                    args = args + (self.top_path,)
                 config = setup_module.configuration(*args)
             if config.name!=dot_join(parent_name, subpackage_name):
                 self.warn('Subpackage %r configuration returned as %r' % \
@@ -1971,9 +1956,8 @@ class Configuration(object):
                 try:
                     version_module = npy_load_module('_'.join(n.split('.')),
                                                      fn, info)
-                except ImportError:
-                    msg = get_exception()
-                    self.warn(str(msg))
+                except ImportError as e:
+                    self.warn(str(e))
                     version_module = None
                 if version_module is None:
                     continue
@@ -2245,10 +2229,7 @@ def get_info(pkgname, dirs=None):
     return info
 
 def is_bootstrapping():
-    if sys.version_info[0] >= 3:
-        import builtins
-    else:
-        import __builtin__ as builtins
+    import builtins
 
     try:
         builtins.__NUMPY_SETUP__
@@ -2344,6 +2325,43 @@ def generate_config_py(target):
                 return g.get(name, g.get(name + "_info", {}))
 
             def show():
+                """
+                Show libraries in the system on which NumPy was built.
+
+                Print information about various resources (libraries, library
+                directories, include directories, etc.) in the system on which
+                NumPy was built.
+
+                See Also
+                --------
+                get_include : Returns the directory containing NumPy C
+                              header files.
+
+                Notes
+                -----
+                Classes specifying the information to be printed are defined
+                in the `numpy.distutils.system_info` module.
+
+                Information may include:
+
+                * ``language``: language used to write the libraries (mostly
+                  C or f77)
+                * ``libraries``: names of libraries found in the system
+                * ``library_dirs``: directories containing the libraries
+                * ``include_dirs``: directories containing library header files
+                * ``src_dirs``: directories containing library source files
+                * ``define_macros``: preprocessor macros used by
+                  ``distutils.setup``
+
+                Examples
+                --------
+                >>> np.show_config()
+                blas_opt_info:
+                    language = c
+                    define_macros = [('HAVE_CBLAS', None)]
+                    libraries = ['openblas', 'openblas']
+                    library_dirs = ['/usr/local/lib']
+                """
                 for name,info_dict in globals().items():
                     if name[0] == "_" or type(info_dict) is not type({}): continue
                     print(name + ":")
index e9cc334a5ec468360275384e18ba682596938b0d..68239495d6c72b70257e51d7ec3ddb35611940a2 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 from distutils.msvc9compiler import MSVCCompiler as _MSVCCompiler
 
index 0cb4bf9794bea861b62c870272d4927a07a94f4f..681a254b87ee68639882845ad98024a584c04d15 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 from distutils.msvccompiler import MSVCCompiler as _MSVCCompiler
 
index 48584b4c41c77d2fd52873b6722330197afa3657..951ce5fb8c125892a8e127a6f8358b2415b7df90 100644 (file)
@@ -1,13 +1,8 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import re
 import os
 
-if sys.version_info[0] < 3:
-    from ConfigParser import RawConfigParser
-else:
-    from configparser import RawConfigParser
+from configparser import RawConfigParser
 
 __all__ = ['FormatError', 'PkgNotFound', 'LibraryInfo', 'VariableSet',
         'read_config', 'parse_flags']
@@ -78,7 +73,7 @@ def parse_flags(line):
 def _escape_backslash(val):
     return val.replace('\\', '\\\\')
 
-class LibraryInfo(object):
+class LibraryInfo:
     """
     Object containing build information about a library.
 
@@ -150,7 +145,7 @@ class LibraryInfo(object):
 
         return "\n".join(m)
 
-class VariableSet(object):
+class VariableSet:
     """
     Container object for the variables defined in a config file.
 
@@ -380,7 +375,6 @@ def read_config(pkgname, dirs=None):
 # pkg-config simple emulator - useful for debugging, and maybe later to query
 # the system
 if __name__ == '__main__':
-    import sys
     from optparse import OptionParser
     import glob
 
index 6ae19d16b18f3f641a8c7f5c76a51e1bf1e2d944..ea8182659cb1af718879de305798b62c23bf3346 100644 (file)
@@ -1,6 +1,4 @@
 # XXX: Handle setuptools ?
-from __future__ import division, absolute_import, print_function
-
 from distutils.core import Distribution
 
 # This class is used because we add new files (sconscripts, and so on) with the
index fc9872db34da859e85f7bd52945d627bf37ff0f6..48051810ee218fb037cc15ccec05293e5ae9bb6b 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from distutils.unixccompiler import UnixCCompiler
 
 class PathScaleCCompiler(UnixCCompiler):
index 82a53bd08dbe339443bd337e12006ad2a6cf7d9d..88cd1a16083beb8269bff52a73af9481b0bc5ab7 100644 (file)
@@ -1,12 +1,10 @@
-#!/usr/bin/env python
-from __future__ import division, print_function
-
+#!/usr/bin/env python3
 def configuration(parent_package='',top_path=None):
     from numpy.distutils.misc_util import Configuration
     config = Configuration('distutils', parent_package, top_path)
     config.add_subpackage('command')
     config.add_subpackage('fcompiler')
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
     config.add_data_files('site.cfg')
     config.add_data_files('mingw/gfortran_vs2003_hack.c')
     config.make_config_py()
index fc7018af3490bc162f42c4ecab151f968d63ee79..3a6a7b29da971d67f8bf5655337ccb34b1236da2 100644 (file)
@@ -1,59 +1,8 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 This file defines a set of system_info classes for getting
 information about various resources (libraries, library directories,
-include directories, etc.) in the system. Currently, the following
-classes are available:
-
-  atlas_info
-  atlas_threads_info
-  atlas_blas_info
-  atlas_blas_threads_info
-  lapack_atlas_info
-  lapack_atlas_threads_info
-  atlas_3_10_info
-  atlas_3_10_threads_info
-  atlas_3_10_blas_info,
-  atlas_3_10_blas_threads_info,
-  lapack_atlas_3_10_info
-  lapack_atlas_3_10_threads_info
-  flame_info
-  blas_info
-  lapack_info
-  openblas_info
-  openblas64__info
-  openblas_ilp64_info
-  blis_info
-  blas_opt_info       # usage recommended
-  lapack_opt_info     # usage recommended
-  blas_ilp64_opt_info    # usage recommended (general ILP64 BLAS)
-  lapack_ilp64_opt_info  # usage recommended (general ILP64 LAPACK)
-  blas_ilp64_plain_opt_info    # usage recommended (general ILP64 BLAS, no symbol suffix)
-  lapack_ilp64_plain_opt_info  # usage recommended (general ILP64 LAPACK, no symbol suffix)
-  blas64__opt_info    # usage recommended (general ILP64 BLAS, 64_ symbol suffix)
-  lapack64__opt_info  # usage recommended (general ILP64 LAPACK, 64_ symbol suffix)
-  fftw_info,dfftw_info,sfftw_info
-  fftw_threads_info,dfftw_threads_info,sfftw_threads_info
-  djbfft_info
-  x11_info
-  lapack_src_info
-  blas_src_info
-  numpy_info
-  numarray_info
-  numpy_info
-  boost_python_info
-  agg2_info
-  wx_info
-  gdk_pixbuf_xlib_2_info
-  gdk_pixbuf_2_info
-  gdk_x11_2_info
-  gtkp_x11_2_info
-  gtkp_2_info
-  xft_info
-  freetype2_info
-  umfpack_info
-
-Usage:
+include directories, etc.) in the system. Usage:
     info_dict = get_info(<name>)
   where <name> is a string 'atlas','x11','fftw','lapack','blas',
   'lapack_src', 'blas_src', etc. For a complete list of allowed names,
@@ -81,19 +30,94 @@ The file 'site.cfg' is looked for in
 
 The first one found is used to get system configuration options The
 format is that used by ConfigParser (i.e., Windows .INI style). The
-section ALL has options that are the default for each section. The
-available sections are fftw, atlas, and x11. Appropriate defaults are
-used if nothing is specified.
+section ALL is not intended for general use.
+
+Appropriate defaults are used if nothing is specified.
 
 The order of finding the locations of resources is the following:
  1. environment variable
  2. section in site.cfg
- 3. ALL section in site.cfg
+ 3. DEFAULT section in site.cfg
+ 4. System default search paths (see ``default_*`` variables below).
 Only the first complete match is returned.
 
+Currently, the following classes are available, along with their section names:
+
+    Numeric_info:Numeric
+    _numpy_info:Numeric
+    _pkg_config_info:None
+    accelerate_info:accelerate
+    agg2_info:agg2
+    amd_info:amd
+    atlas_3_10_blas_info:atlas
+    atlas_3_10_blas_threads_info:atlas
+    atlas_3_10_info:atlas
+    atlas_3_10_threads_info:atlas
+    atlas_blas_info:atlas
+    atlas_blas_threads_info:atlas
+    atlas_info:atlas
+    atlas_threads_info:atlas
+    blas64__opt_info:ALL               # usage recommended (general ILP64 BLAS, 64_ symbol suffix)
+    blas_ilp64_opt_info:ALL            # usage recommended (general ILP64 BLAS)
+    blas_ilp64_plain_opt_info:ALL      # usage recommended (general ILP64 BLAS, no symbol suffix)
+    blas_info:blas
+    blas_mkl_info:mkl
+    blas_opt_info:ALL                  # usage recommended
+    blas_src_info:blas_src
+    blis_info:blis
+    boost_python_info:boost_python
+    dfftw_info:fftw
+    dfftw_threads_info:fftw
+    djbfft_info:djbfft
+    f2py_info:ALL
+    fft_opt_info:ALL
+    fftw2_info:fftw
+    fftw3_info:fftw3
+    fftw_info:fftw
+    fftw_threads_info:fftw
+    flame_info:flame
+    freetype2_info:freetype2
+    gdk_2_info:gdk_2
+    gdk_info:gdk
+    gdk_pixbuf_2_info:gdk_pixbuf_2
+    gdk_pixbuf_xlib_2_info:gdk_pixbuf_xlib_2
+    gdk_x11_2_info:gdk_x11_2
+    gtkp_2_info:gtkp_2
+    gtkp_x11_2_info:gtkp_x11_2
+    lapack64__opt_info:ALL             # usage recommended (general ILP64 LAPACK, 64_ symbol suffix)
+    lapack_atlas_3_10_info:atlas
+    lapack_atlas_3_10_threads_info:atlas
+    lapack_atlas_info:atlas
+    lapack_atlas_threads_info:atlas
+    lapack_ilp64_opt_info:ALL          # usage recommended (general ILP64 LAPACK)
+    lapack_ilp64_plain_opt_info:ALL    # usage recommended (general ILP64 LAPACK, no symbol suffix)
+    lapack_info:lapack
+    lapack_mkl_info:mkl
+    lapack_opt_info:ALL                # usage recommended
+    lapack_src_info:lapack_src
+    mkl_info:mkl
+    numarray_info:numarray
+    numerix_info:numerix
+    numpy_info:numpy
+    openblas64__info:openblas64_
+    openblas64__lapack_info:openblas64_
+    openblas_clapack_info:openblas
+    openblas_ilp64_info:openblas_ilp64
+    openblas_ilp64_lapack_info:openblas_ilp64
+    openblas_info:openblas
+    openblas_lapack_info:openblas
+    sfftw_info:fftw
+    sfftw_threads_info:fftw
+    system_info:ALL
+    umfpack_info:umfpack
+    wx_info:wx
+    x11_info:x11
+    xft_info:xft
+
 Example:
 ----------
-[ALL]
+[DEFAULT]
+# default section
 library_dirs = /usr/lib:/usr/local/lib:/opt/lib
 include_dirs = /usr/include:/usr/local/include:/opt/include
 src_dirs = /usr/local/src:/opt/src
@@ -128,8 +152,6 @@ this distribution for specifics.
 NO WARRANTY IS EXPRESSED OR IMPLIED.  USE AT YOUR OWN RISK.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import os
 import re
@@ -140,12 +162,8 @@ import textwrap
 
 from glob import glob
 from functools import reduce
-if sys.version_info[0] < 3:
-    from ConfigParser import NoOptionError
-    from ConfigParser import RawConfigParser as ConfigParser
-else:
-    from configparser import NoOptionError
-    from configparser import RawConfigParser as ConfigParser
+from configparser import NoOptionError
+from configparser import RawConfigParser as ConfigParser
 # It seems that some people are importing ConfigParser from here so is
 # good to keep its class name. Use of RawConfigParser is needed in
 # order to be able to load path names with percent in them, like
@@ -159,11 +177,10 @@ from distutils.util import get_platform
 
 from numpy.distutils.exec_command import (
     find_executable, filepath_from_subprocess_output,
-    get_pythonexe)
+    )
 from numpy.distutils.misc_util import (is_sequence, is_string,
                                        get_shared_lib_extension)
 from numpy.distutils.command.config import config as cmd_config
-from numpy.distutils.compat import get_exception
 from numpy.distutils import customized_ccompiler as _customized_ccompiler
 from numpy.distutils import _shell_utils
 import distutils.ccompiler
@@ -267,32 +284,29 @@ if sys.platform == 'win32':
         default_include_dirs.extend(
             os.path.join(library_root, d) for d in _include_dirs)
 
-    if sys.version_info >= (3, 3):
-        # VCpkg is the de-facto package manager on windows for C/C++
-        # libraries. If it is on the PATH, then we append its paths here.
-        # We also don't re-implement shutil.which for Python 2.7 because
-        # vcpkg doesn't support MSVC 2008.
-        vcpkg = shutil.which('vcpkg')
-        if vcpkg:
-            vcpkg_dir = os.path.dirname(vcpkg)
-            if platform.architecture() == '32bit':
-                specifier = 'x86'
-            else:
-                specifier = 'x64'
-
-            vcpkg_installed = os.path.join(vcpkg_dir, 'installed')
-            for vcpkg_root in [
-                os.path.join(vcpkg_installed, specifier + '-windows'),
-                os.path.join(vcpkg_installed, specifier + '-windows-static'),
-            ]:
-                add_system_root(vcpkg_root)
-
-        # Conda is another popular package manager that provides libraries
-        conda = shutil.which('conda')
-        if conda:
-            conda_dir = os.path.dirname(conda)
-            add_system_root(os.path.join(conda_dir, '..', 'Library'))
-            add_system_root(os.path.join(conda_dir, 'Library'))
+    # VCpkg is the de-facto package manager on windows for C/C++
+    # libraries. If it is on the PATH, then we append its paths here.
+    vcpkg = shutil.which('vcpkg')
+    if vcpkg:
+        vcpkg_dir = os.path.dirname(vcpkg)
+        if platform.architecture() == '32bit':
+            specifier = 'x86'
+        else:
+            specifier = 'x64'
+
+        vcpkg_installed = os.path.join(vcpkg_dir, 'installed')
+        for vcpkg_root in [
+            os.path.join(vcpkg_installed, specifier + '-windows'),
+            os.path.join(vcpkg_installed, specifier + '-windows-static'),
+        ]:
+            add_system_root(vcpkg_root)
+
+    # Conda is another popular package manager that provides libraries
+    conda = shutil.which('conda')
+    if conda:
+        conda_dir = os.path.dirname(conda)
+        add_system_root(os.path.join(conda_dir, '..', 'Library'))
+        add_system_root(os.path.join(conda_dir, 'Library'))
 
 else:
     default_lib_dirs = libpaths(['/usr/local/lib', '/opt/lib', '/usr/lib',
@@ -582,14 +596,18 @@ class UmfpackNotFoundError(NotFoundError):
     the UMFPACK environment variable."""
 
 
-class system_info(object):
+class system_info:
 
     """ get_info() is the only public method. Don't use others.
     """
-    section = 'ALL'
     dir_env_var = None
-    search_static_first = 0  # XXX: disabled by default, may disappear in
-                            # future unless it is proved to be useful.
+    # XXX: search_static_first is disabled by default, may disappear in
+    # future unless it is proved to be useful.
+    search_static_first = 0
+    # The base-class section name is a random word "ALL" and is not really
+    # intended for general use. It cannot be None nor can it be DEFAULT as
+    # these break the ConfigParser. See gh-15338
+    section = 'ALL'
     saved_results = {}
 
     notfounderror = NotFoundError
@@ -717,7 +735,7 @@ class system_info(object):
         return info
 
     def get_info(self, notfound_action=0):
-        """ Return a dictonary with items that are compatible
+        """ Return a dictionary with items that are compatible
             with numpy.distutils.setup keyword arguments.
         """
         flag = 0
@@ -2148,8 +2166,6 @@ class openblas_info(blas_info):
             extra_args = info['extra_link_args']
         except Exception:
             extra_args = []
-        if sys.version_info < (3, 5) and sys.version_info > (3, 0) and c.compiler_type == "msvc":
-            extra_args.append("/MANIFEST")
         try:
             with open(src, 'wt') as f:
                 f.write(s)
@@ -2541,18 +2557,18 @@ class numerix_info(system_info):
             try:
                 import numpy  # noqa: F401
                 which = "numpy", "defaulted"
-            except ImportError:
-                msg1 = str(get_exception())
+            except ImportError as e:
+                msg1 = str(e)
                 try:
                     import Numeric  # noqa: F401
                     which = "numeric", "defaulted"
-                except ImportError:
-                    msg2 = str(get_exception())
+                except ImportError as e:
+                    msg2 = str(e)
                     try:
                         import numarray  # noqa: F401
                         which = "numarray", "defaulted"
-                    except ImportError:
-                        msg3 = str(get_exception())
+                    except ImportError as e:
+                        msg3 = str(e)
                         log.info(msg1)
                         log.info(msg2)
                         log.info(msg3)
index 37912f5ba9d88686934a6f4ac41aff24a7e72d16..d6eb7d1c3f27eeedd29ab97081a3672220f7f6dd 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 from tempfile import TemporaryFile
@@ -10,12 +8,9 @@ from numpy.testing import tempdir, assert_, assert_warns
 
 # In python 3 stdout, stderr are text (unicode compliant) devices, so to
 # emulate them import StringIO from the io module.
-if sys.version_info[0] >= 3:
-    from io import StringIO
-else:
-    from StringIO import StringIO
+from io import StringIO
 
-class redirect_stdout(object):
+class redirect_stdout:
     """Context manager to redirect stdout for exec_command test."""
     def __init__(self, stdout=None):
         self._stdout = stdout or sys.stdout
@@ -30,7 +25,7 @@ class redirect_stdout(object):
         # note: closing sys.stdout won't close it.
         self._stdout.close()
 
-class redirect_stderr(object):
+class redirect_stderr:
     """Context manager to redirect stderr for exec_command test."""
     def __init__(self, stderr=None):
         self._stderr = stderr or sys.stderr
@@ -45,7 +40,7 @@ class redirect_stderr(object):
         # note: closing sys.stderr won't close it.
         self._stderr.close()
 
-class emulate_nonposix(object):
+class emulate_nonposix:
     """Context manager to emulate os.name != 'posix' """
     def __init__(self, osname='non-posix'):
         self._new_name = osname
@@ -98,7 +93,7 @@ def test_exec_command_stderr():
                         exec_command.exec_command("cd '.'")
 
 
-class TestExecCommand(object):
+class TestExecCommand:
     def setup(self):
         self.pyexe = get_pythonexe()
 
@@ -191,9 +186,8 @@ class TestExecCommand(object):
         with tempdir() as tmpdir:
             fn = "file"
             tmpfile = os.path.join(tmpdir, fn)
-            f = open(tmpfile, 'w')
-            f.write('Hello')
-            f.close()
+            with open(tmpfile, 'w') as f:
+                f.write('Hello')
 
             s, o = exec_command.exec_command(
                  '"%s" -c "f = open(\'%s\', \'r\'); f.close()"' %
index 6d245fbd4b697a1fa8d79b1c3ca23fcccc525bb6..dd97f1e72afcba2ab379e5ff4dfce15341686534 100644 (file)
@@ -1,8 +1,4 @@
-from __future__ import division, absolute_import, print_function
-
-import pytest
-
-from numpy.testing import assert_, suppress_warnings
+from numpy.testing import assert_
 import numpy.distutils.fcompiler
 
 customizable_flags = [
index 49208aaced349f338a495ba42f223a5e885a7f12..0817ae58c2140e912eaf3d61e040050016dede54 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy.testing import assert_
 
 import numpy.distutils.fcompiler
@@ -30,7 +28,7 @@ gfortran_version_strings = [
     ('GNU Fortran (crosstool-NG 8a21ab48) 7.2.0', '7.2.0')
 ]
 
-class TestG77Versions(object):
+class TestG77Versions:
     def test_g77_version(self):
         fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu')
         for vs, version in g77_version_strings:
@@ -43,7 +41,7 @@ class TestG77Versions(object):
             v = fc.version_match(vs)
             assert_(v is None, (vs, v))
 
-class TestGFortranVersions(object):
+class TestGFortranVersions:
     def test_gfortran_version(self):
         fc = numpy.distutils.fcompiler.new_fcompiler(compiler='gnu95')
         for vs, version in gfortran_version_strings:
index 5e014bada34f60497bfbe97ef20a1ddc6437530b..45c9cdac1910def6b5a50a60b4ab5c8e0092af18 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy.distutils.fcompiler
 from numpy.testing import assert_
 
@@ -16,7 +14,7 @@ intel_64bit_version_strings = [
      "running on Intel(R) 64, Version 11.1", '11.1')
 ]
 
-class TestIntelFCompilerVersions(object):
+class TestIntelFCompilerVersions:
     def test_32bit_version(self):
         fc = numpy.distutils.fcompiler.new_fcompiler(compiler='intel')
         for vs, version in intel_32bit_version_strings:
@@ -24,7 +22,7 @@ class TestIntelFCompilerVersions(object):
             assert_(v == version)
 
 
-class TestIntelEM64TFCompilerVersions(object):
+class TestIntelEM64TFCompilerVersions:
     def test_64bit_version(self):
         fc = numpy.distutils.fcompiler.new_fcompiler(compiler='intelem')
         for vs, version in intel_64bit_version_strings:
index 1c936056a89b2a1ca97aa8b595d45247cab842da..2e04f5266dc1e9c5a15f130af5f9c596f8bd7ef9 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from numpy.testing import assert_
 import numpy.distutils.fcompiler
 
@@ -16,7 +14,7 @@ nag_version_strings = [('nagfor', 'NAG Fortran Compiler Release '
                         '431,435,437,446,459-460,463,472,494,496,503,508,'
                         '511,517,529,555,557,565)', '5.1')]
 
-class TestNagFCompilerVersions(object):
+class TestNagFCompilerVersions:
     def test_version_match(self):
         for comp, vs, version in nag_version_strings:
             fc = numpy.distutils.fcompiler.new_fcompiler(compiler=comp)
index 3e239cf48cba83212a0252608d82a67864806e87..605c80483b77fd4efa6f48ab8fd1bc6abd12e5a4 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from os.path import join, sep, dirname
 
 from numpy.distutils.misc_util import (
@@ -11,7 +9,7 @@ from numpy.testing import (
 
 ajoin = lambda *paths: join(*((sep,)+paths))
 
-class TestAppendpath(object):
+class TestAppendpath:
 
     def test_1(self):
         assert_equal(appendpath('prefix', 'name'), join('prefix', 'name'))
@@ -35,7 +33,7 @@ class TestAppendpath(object):
         assert_equal(appendpath('/prefix/sub/sub2', '/prefix/sub/sup/name'),
                      ajoin('prefix', 'sub', 'sub2', 'sup', 'name'))
 
-class TestMinrelpath(object):
+class TestMinrelpath:
 
     def test_1(self):
         n = lambda path: path.replace('/', sep)
@@ -49,7 +47,7 @@ class TestMinrelpath(object):
         assert_equal(minrelpath(n('.././..')), n('../..'))
         assert_equal(minrelpath(n('aa/bb/.././../dd')), n('dd'))
 
-class TestGpaths(object):
+class TestGpaths:
 
     def test_gpaths(self):
         local_path = minrelpath(join(dirname(__file__), '..'))
@@ -58,7 +56,7 @@ class TestGpaths(object):
         f = gpaths('system_info.py', local_path)
         assert_(join(local_path, 'system_info.py') == f[0], repr(f))
 
-class TestSharedExtension(object):
+class TestSharedExtension:
 
     def test_get_shared_lib_extension(self):
         import sys
index 537e16e90d2a5f6b90412286dbf8a98a87a574fd..b287ebe2e83209fdcf5add161a7af8d988b9d086 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 
 from numpy.distutils.npy_pkg_config import read_config, parse_flags
@@ -36,7 +34,7 @@ libs = -L${libdir}
 simple_variable_d = {'cflags': '-I/foo/bar/include', 'libflags': '-L/foo/bar/lib',
         'version': '0.1', 'name': 'foo'}
 
-class TestLibraryInfo(object):
+class TestLibraryInfo:
     def test_simple(self):
         with temppath('foo.ini') as path:
             with open(path,  'w') as f:
@@ -63,7 +61,7 @@ class TestLibraryInfo(object):
         out.vars['prefix'] = '/Users/david'
         assert_(out.cflags() == '-I/Users/david/include')
 
-class TestParseFlags(object):
+class TestParseFlags:
     def test_simple_cflags(self):
         d = parse_flags("-I/usr/include")
         assert_(d['include_dirs'] == ['/usr/include'])
index a0344244fe9c9092c91ab5078fd3adc802e085a9..32bd283e56b600029da5f0399ffeea37084025ea 100644 (file)
@@ -1,8 +1,5 @@
-from __future__ import division, absolute_import, print_function
-
 import pytest
 import subprocess
-import os
 import json
 import sys
 
index 3c7638960c7cebcb498e28b7e0db7b5a4459dc97..0768ffdde55ad999fb9d9632861c106e2c84bbf0 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, print_function
-
 import os
 import shutil
 import pytest
@@ -9,7 +7,7 @@ from distutils.errors import DistutilsError
 
 from numpy.testing import assert_, assert_equal, assert_raises
 from numpy.distutils import ccompiler, customized_ccompiler
-from numpy.distutils.system_info import system_info, ConfigParser
+from numpy.distutils.system_info import system_info, ConfigParser, mkl_info
 from numpy.distutils.system_info import AliasedOptionError
 from numpy.distutils.system_info import default_lib_dirs, default_include_dirs
 from numpy.distutils import _shell_utils
@@ -130,7 +128,7 @@ class DuplicateOptionInfo(_system_info):
     section = 'duplicate_options'
 
 
-class TestSystemInfoReading(object):
+class TestSystemInfoReading:
 
     def setup(self):
         """ Create the libraries """
@@ -255,3 +253,35 @@ class TestSystemInfoReading(object):
             assert_(os.path.isfile(self._src2.replace('.c', '.o')))
         finally:
             os.chdir(previousDir)
+
+    def test_overrides(self):
+        previousDir = os.getcwd()
+        cfg = os.path.join(self._dir1, 'site.cfg')
+        shutil.copy(self._sitecfg, cfg)
+        try:
+            os.chdir(self._dir1)
+            # Check that the '[ALL]' section does not override
+            # missing values from other sections
+            info = mkl_info()
+            lib_dirs = info.cp['ALL']['library_dirs'].split(os.pathsep)
+            assert info.get_lib_dirs() != lib_dirs
+
+            # But if we copy the values to a '[mkl]' section the value
+            # is correct
+            with open(cfg, 'r') as fid:
+                mkl = fid.read().replace('ALL', 'mkl')
+            with open(cfg, 'w') as fid:
+                fid.write(mkl)
+            info = mkl_info()
+            assert info.get_lib_dirs() == lib_dirs
+
+            # Also, the values will be taken from a section named '[DEFAULT]'
+            with open(cfg, 'r') as fid:
+                dflt = fid.read().replace('mkl', 'DEFAULT')
+            with open(cfg, 'w') as fid:
+                fid.write(dflt)
+            info = mkl_info()
+            assert info.get_lib_dirs() == lib_dirs
+        finally:
+            os.chdir(previousDir)
+        
index 11b2cce529af56d81809db9dcb11941bece4cde3..5f36c439f48bdbc9eb0468870165917d3390b572 100644 (file)
@@ -2,20 +2,13 @@
 unixccompiler - can handle very long argument lists for ar.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 
-from distutils.errors import DistutilsExecError, CompileError
-from distutils.unixccompiler import *
+from distutils.errors import CompileError, DistutilsExecError, LibError
+from distutils.unixccompiler import UnixCCompiler
 from numpy.distutils.ccompiler import replace_method
-from numpy.distutils.compat import get_exception
 from numpy.distutils.misc_util import _commandline_dep_string
-
-if sys.version_info[0] < 3:
-    from . import log
-else:
-    from numpy.distutils import log
+from numpy.distutils import log
 
 # Note that UnixCCompiler._compile appeared in Python 2.3
 def UnixCCompiler__compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts):
@@ -56,8 +49,8 @@ def UnixCCompiler__compile(self, obj, src, ext, cc_args, extra_postargs, pp_opts
     try:
         self.spawn(self.compiler_so + cc_args + [src, '-o', obj] + deps +
                    extra_postargs, display = display)
-    except DistutilsExecError:
-        msg = str(get_exception())
+    except DistutilsExecError as e:
+        msg = str(e)
         raise CompileError(msg)
 
     # add commandline flags to dependency file
@@ -128,8 +121,8 @@ def UnixCCompiler_create_static_lib(self, objects, output_libname,
             try:
                 self.spawn(self.ranlib + [output_filename],
                            display = display)
-            except DistutilsExecError:
-                msg = str(get_exception())
+            except DistutilsExecError as e:
+                msg = str(e)
                 raise LibError(msg)
     else:
         log.debug("skipping %s (up-to-date)", output_filename)
index b6f1fa71c54a1cdc3df88e30c5ae49f5ffb36fb6..8a944fecd865487e489ecefb90700f5eed38cd44 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 
 ref_dir = os.path.join(os.path.dirname(__file__))
index c05f347a1f46a96b5621b6355e219d9ee14fa05a..635c1b1b8e65c1af468fe62c841677c587446622 100644 (file)
@@ -339,4 +339,3 @@ be useful to test your code with the value
 ``1 + np.finfo(np.longdouble).eps``.
 
 """
-from __future__ import division, absolute_import, print_function
index cb548a0d064c01752c9a470c68ddf10d9c32708c..63975e6a9367f22bbc67409ebf7070ed0c523aec 100644 (file)
@@ -178,4 +178,3 @@ making it a two-dimensional ``4x1`` array.  Combining the ``4x1`` array
 with ``b``, which has shape ``(3,)``, yields a ``4x3`` array.
 
 """
-from __future__ import division, absolute_import, print_function
index 7a749c8d55134e344c1f0c7dc70ff32865611da4..fe94619779719d9bc624b0f58b7835b0ccf20467 100644 (file)
@@ -153,4 +153,3 @@ can be achieved with the ndarray astype method:
 False
 
 """
-from __future__ import division, absolute_import, print_function
index 72793e44dcc8572b6c0357062e7d3bcbbb0e4ce5..2c629ad33da8d62a66f647d829021e42bcd45b80 100644 (file)
@@ -13,9 +13,8 @@ NumPy includes several constants:
 #
 # Note: the docstring is autogenerated.
 #
-from __future__ import division, absolute_import, print_function
-
-import textwrap, re
+import re
+import textwrap
 
 # Maintain same format as in numpy.add_newdocs
 constants = []
index 9ebe938be0006657b9322b121a5080a49b896e51..067f8bb336ad03f37bfacfe4c68cd35409075247 100644 (file)
@@ -141,4 +141,3 @@ random values, and some utility functions to generate special matrices (e.g.
 diagonal).
 
 """
-from __future__ import division, absolute_import, print_function
index c9029941b52af3f35b77a4207b62ac2f97682620..ba76a43ae56349d109bbed93dd883be20808ae81 100644 (file)
@@ -58,7 +58,7 @@ numpy.ndarray
 
 How can we pass our custom array type through this function? Numpy allows a
 class to indicate that it would like to handle computations in a custom-defined
-way through the interaces ``__array_ufunc__`` and ``__array_function__``. Let's
+way through the interfaces ``__array_ufunc__`` and ``__array_function__``. Let's
 take one at a time, starting with ``_array_ufunc__``. This method covers
 :ref:`ufuncs`, a class of functions that includes, for example,
 :func:`numpy.multiply` and :func:`numpy.sin`.
index 7d1c9a1d5d15e6cc350ddac81609ba6fb2035d3b..16a3b92417cbf14b84706e10f5697e31fa62b58a 100644 (file)
@@ -159,7 +159,7 @@ Glossary
 
    field
        In a :term:`structured data type`, each sub-type is called a `field`.
-       The `field` has a name (a string), a type (any valid dtype, and
+       The `field` has a name (a string), a type (any valid dtype), and
        an optional `title`. See :ref:`arrays.dtypes`
 
    Fortran order
@@ -182,7 +182,7 @@ Glossary
    instance
        A class definition gives the blueprint for constructing an object::
 
-         >>> class House(object):
+         >>> class House:
          ...     wall_colour = 'white'
 
        Yet, we have to *build* a house before it exists::
@@ -336,7 +336,7 @@ Glossary
        Often seen in method signatures, ``self`` refers to the instance
        of the associated class.  For example:
 
-         >>> class Paintbrush(object):
+         >>> class Paintbrush:
          ...     color = 'blue'
          ...
          ...     def paint(self):
@@ -473,4 +473,3 @@ Glossary
        and f2py (which wraps Fortran).
 
 """
-from __future__ import division, absolute_import, print_function
index 67601566824130270524d83e9c2695e178d8d8e1..c7dda279055304ee0710b41205ee6eb457fc8bf9 100644 (file)
@@ -285,14 +285,23 @@ Combining index arrays with slices
 
 Index arrays may be combined with slices. For example: ::
 
- >>> y[np.array([0,2,4]),1:3]
+ >>> y[np.array([0, 2, 4]), 1:3]
  array([[ 1,  2],
         [15, 16],
         [29, 30]])
 
-In effect, the slice is converted to an index array
-np.array([[1,2]]) (shape (1,2)) that is broadcast with the index array
-to produce a resultant array of shape (3,2).
+In effect, the slice and index array operation are independent.
+The slice operation extracts columns with index 1 and 2,
+(i.e. the 2nd and 3rd columns),
+followed by the index array operation which extracts rows with 
+index 0, 2 and 4 (i.e the first, third and fifth rows).
+
+This is equivalent to::
+
+ >>> y[:, 1:3][np.array([0, 2, 4]), :]
+ array([[ 1,  2],
+        [15, 16],
+        [29, 30]])
 
 Likewise, slicing can be combined with broadcasted boolean indices: ::
 
@@ -372,8 +381,7 @@ exceptions (assigning complex to floats or ints): ::
  >>> x[1]
  1
  >>> x[1] = 1.2j
- <type 'exceptions.TypeError'>: can't convert complex to long; use
- long(abs(z))
+ TypeError: can't convert complex to int
 
 
 Unlike some of the references (such as array and mask indices)
@@ -446,4 +454,3 @@ converted to an array as a list would be. As an example: ::
  40
 
 """
-from __future__ import division, absolute_import, print_function
index a14fee7c2fff230858c1ef54d789faad1aa83987..6718f1108dc44f15803bada0a223df3dc0b51830 100644 (file)
@@ -160,4 +160,3 @@ when accessing elements of an array. Granted, it goes against the grain, but
 it is more in line with Python semantics and the natural order of the data.
 
 """
-from __future__ import division, absolute_import, print_function
index a76abe164f33d47f97809942f55686c84eaf103d..fc1c4cd0122a0dba16ab4c094d8e71ab133ad2f5 100644 (file)
@@ -224,4 +224,3 @@ Interfacing to C++:
  5) SIP (used mainly in PyQT)
 
 """
-from __future__ import division, absolute_import, print_function
index 1343d2adc1f963546db3bc06c3ba32737517e8e8..359d4f7f48d40e75bc0249bdefc0dfeabe2859d4 100644 (file)
@@ -341,7 +341,7 @@ structured datatype has just a single field::
  >>> nostruct[:] = twofield
  Traceback (most recent call last):
  ...
- TypeError: Cannot cast scalar from dtype([('A', '<i4'), ('B', '<i4')]) to dtype('int32') according to the rule 'unsafe'
+ TypeError: Cannot cast array data from dtype([('A', '<i4'), ('B', '<i4')]) to dtype('int32') according to the rule 'unsafe'
 
 Assignment from other Structured Arrays
 ```````````````````````````````````````
@@ -644,4 +644,3 @@ attribute takes precedence. Such fields will be inaccessible by attribute but
 will still be accessible by index.
 
 """
-from __future__ import division, absolute_import, print_function
index d0685328e29fd50dd5ed6f7aa858d4d4401e293d..7dc10e1c80ce91e2e6513d128f3ed17891ffbd41 100644 (file)
@@ -72,7 +72,7 @@ class, that points to the data in the original.
 There are other points in the use of ndarrays where we need such views,
 such as copying arrays (``c_arr.copy()``), creating ufunc output arrays
 (see also :ref:`array-wrap`), and reducing methods (like
-``c_arr.mean()``.
+``c_arr.mean()``).
 
 Relationship of view casting and new-from-template
 --------------------------------------------------
@@ -114,7 +114,7 @@ For example, consider the following Python code:
 
 .. testcode::
 
-  class C(object):
+  class C:
       def __new__(cls, *args):
           print('Cls in __new__:', cls)
           print('Args in __new__:', args)
@@ -454,7 +454,7 @@ following.
     input numpy as np
 
     class A(np.ndarray):
-        def __array_ufunc__(self, ufunc, method, *inputs, **kwargs):
+        def __array_ufunc__(self, ufunc, method, *inputs, out=None, **kwargs):
             args = []
             in_no = []
             for i, input_ in enumerate(inputs):
@@ -464,7 +464,7 @@ following.
                 else:
                     args.append(input_)
 
-            outputs = kwargs.pop('out', None)
+            outputs = out
             out_no = []
             if outputs:
                 out_args = []
@@ -750,4 +750,3 @@ This object is now compatible with ``np.sum`` again because any extraneous argum
 ``**unused_kwargs`` parameter.
 
 """
-from __future__ import division, absolute_import, print_function
index df2c455ec21f4e995cc0091bd21b00e2d9708c77..eecc15083d534e43c65e5adb95c8826e3b3a2b51 100644 (file)
@@ -135,4 +135,3 @@ results in an error. There are two alternatives:
     a convenient way to apply these operators.
 
 """
-from __future__ import division, absolute_import, print_function
index 651e845bbd5cef33f640842f2338e9c2cc46e5db..92afec52df90e7ef44c5abb82f08d83b2c132d04 100644 (file)
@@ -10,8 +10,6 @@ NumPy.
 .. _Scipy : https://www.scipy.org
 
 """
-from __future__ import division, absolute_import, print_function
-
 # This module should be used for functions both in numpy and scipy if
 #  you want to use the numpy version if available but the scipy version
 #  otherwise.
index 42e3632fdf3e489c0dbe734a1256c2eb9183abe0..949bac0ffb66e7b8daa369b5755433d0e4e52e83 100644 (file)
@@ -1,17 +1,13 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """Fortran to Python Interface Generator.
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['run_main', 'compile', 'f2py_testing']
 
 import sys
 import subprocess
 import os
 
-import numpy as np
-
 from . import f2py2e
 from . import f2py_testing
 from . import diagnose
@@ -89,7 +85,7 @@ def compile(source,
 
         args = ['-c', '-m', modulename, f.name]
 
-        if isinstance(extra_args, np.compat.basestring):
+        if isinstance(extra_args, str):
             is_posix = (os.name == 'posix')
             extra_args = shlex.split(extra_args, posix=is_posix)
 
index 708f7f3624adde4b8993f7de3571091640fd13f3..c6115070e4cc9943d5e2d368342f98491a6e0291 100644 (file)
@@ -1,6 +1,4 @@
 # See http://cens.ioc.ee/projects/f2py2e/
-from __future__ import division, print_function
-
 from numpy.f2py.f2py2e import main
 
 main()
index 49a2199bf38b0bccdf49300718fb9eaf2bd2fe87..104c2e1a899efa384fba6b286ca23752f1d856c7 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 major = 2
 
 try:
index 404bdbd2d62aeba47699a51d04023323a0af935b..80b150655eb0009f0608ad6f4d9ab4e4e67b1600 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 Auxiliary functions for f2py2e.
@@ -14,8 +14,6 @@ $Date: 2005/07/24 19:01:55 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 import pprint
 import sys
 import types
@@ -552,7 +550,7 @@ class F2PYError(Exception):
     pass
 
 
-class throw_error(object):
+class throw_error:
 
     def __init__(self, mess):
         self.mess = mess
index ce79f680f2a84dc635a679acd27a084e78ae528b..fabbfc4c24ac7608d173a90e547fc81fa25b25d7 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 Copyright 1999,2000 Pearu Peterson all rights reserved,
@@ -11,8 +11,6 @@ $Date: 2005/05/06 10:57:33 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 __version__ = "$Revision: 1.60 $"[10:-1]
 
 from . import __version__
@@ -21,11 +19,10 @@ f2py_version = __version__.version
 import copy
 import re
 import os
-import sys
 from .crackfortran import markoutercomma
 from . import cb_rules
 
-# The eviroment provided by auxfuncs.py is needed for some calls to eval.
+# The environment provided by auxfuncs.py is needed for some calls to eval.
 # As the needed functions cannot be determined by static inspection of the
 # code, it is safest to use import * pending a major refactoring of f2py.
 from .auxfuncs import *
@@ -79,7 +76,7 @@ c2capi_map = {'double': 'NPY_DOUBLE',
               'complex_long_double': 'NPY_CDOUBLE',   # forced casting
               'string': 'NPY_STRING'}
 
-# These new maps aren't used anyhere yet, but should be by default
+# These new maps aren't used anywhere yet, but should be by default
 #  unless building numeric or numarray extensions.
 if using_newcore:
     c2capi_map = {'double': 'NPY_DOUBLE',
@@ -149,11 +146,7 @@ c2buildvalue_map = {'double': 'd',
                     'complex_float': 'N',
                     'complex_double': 'N',
                     'complex_long_double': 'N',
-                    'string': 'z'}
-
-if sys.version_info[0] >= 3:
-    # Bytes, not Unicode strings
-    c2buildvalue_map['string'] = 'y'
+                    'string': 'y'}
 
 if using_newcore:
     # c2buildvalue_map=???
@@ -325,7 +318,6 @@ def getstrlength(var):
 
 
 def getarrdims(a, var, verbose=0):
-    global depargs
     ret = {}
     if isstring(var) and not isarray(var):
         ret['dims'] = getstrlength(var)
@@ -521,7 +513,6 @@ def sign2map(a, var):
     varrfromat
     intent
     """
-    global lcb_map, cb_map
     out_a = a
     if isintent_out(var):
         for k in var['intent']:
index 183d7c2f920b703a482afd5ecc846afbd327ba0c..87887c152750b09e7d24faa16ff18c6cd5ad4937 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 Build call-back mechanism for f2py2e.
@@ -13,8 +13,6 @@ $Date: 2005/07/20 11:27:58 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 from . import __version__
 from .auxfuncs import (
     applyrules, debugcapi, dictappend, errmess, getargs, hasnote, isarray,
@@ -438,7 +436,6 @@ cb_map = {}
 
 
 def buildcallbacks(m):
-    global cb_map
     cb_map[m['name']] = []
     for bi in m['body']:
         if bi['block'] == 'interface':
@@ -450,7 +447,6 @@ def buildcallbacks(m):
 
 
 def buildcallback(rout, um):
-    global cb_map
     from . import capi_maps
 
     outmess('\tConstructing call-back function "cb_%s_in_%s"\n' %
index ccb7b3a329f7f05db8351e9a719f049aa68fff10..f1ac214d43fe79fcde743cc59e4b490d827c1b2b 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 C declarations, CPP macros, and C functions for f2py2e.
@@ -14,8 +14,6 @@ $Date: 2005/05/06 11:42:34 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import copy
 
@@ -542,7 +540,7 @@ cppmacros[
     'ARRSIZE'] = '#define ARRSIZE(dims,rank) (_PyArray_multiply_list(dims,rank))'
 cppmacros['OLDPYNUM'] = """\
 #ifdef OLDPYNUM
-#error You need to install NumPy version 13 or higher. See https://scipy.org/install.html
+#error You need to install NumPy version 0.13 or higher. See https://scipy.org/install.html
 #endif
 """
 ################# C functions ###############
@@ -646,7 +644,6 @@ fprintf(stderr,\"string_from_pyobj(str='%s',len=%d,inistr='%s',obj=%p)\\n\",(cha
         tmp = obj;
         Py_INCREF(tmp);
     }
-#if PY_VERSION_HEX >= 0x03000000
     else if (PyUnicode_Check(obj)) {
         tmp = PyUnicode_AsASCIIString(obj);
     }
@@ -661,11 +658,6 @@ fprintf(stderr,\"string_from_pyobj(str='%s',len=%d,inistr='%s',obj=%p)\\n\",(cha
             tmp = NULL;
         }
     }
-#else
-    else {
-        tmp = PyObject_Str(obj);
-    }
-#endif
     if (tmp == NULL) goto capi_fail;
     if (*len == -1)
         *len = PyString_GET_SIZE(tmp);
@@ -1041,6 +1033,8 @@ cfuncs[
     'try_pyarr_from_complex_double'] = 'static int try_pyarr_from_complex_double(PyObject* obj,complex_double* v) {\n    TRYCOMPLEXPYARRAYTEMPLATE(double,\'D\');\n}\n'
 
 needs['create_cb_arglist'] = ['CFUNCSMESS', 'PRINTPYOBJERR', 'MINMAX']
+
+# create the list of arguments to be used when calling back to python
 cfuncs['create_cb_arglist'] = """\
 static int create_cb_arglist(PyObject* fun,PyTupleObject* xa,const int maxnofargs,const int nofoptargs,int *nofargs,PyTupleObject **args,const char *errmess) {
     PyObject *tmp = NULL;
@@ -1066,6 +1060,10 @@ static int create_cb_arglist(PyObject* fun,PyTupleObject* xa,const int maxnofarg
                 tmp_fun = fun; /* built-in function */
                 Py_INCREF(tmp_fun);
                 tot = maxnofargs;
+                if (PyCFunction_Check(fun)) {
+                    /* In case the function has a co_argcount (like on PyPy) */
+                    di = 0;
+                }
                 if (xa != NULL)
                     tot += PyTuple_Size((PyObject *)xa);
             }
@@ -1094,13 +1092,8 @@ if (tmp_fun==NULL) {
 fprintf(stderr,\"Call-back argument must be function|instance|instance.__call__|f2py-function but got %s.\\n\",(fun==NULL?\"NULL\":Py_TYPE(fun)->tp_name));
 goto capi_fail;
 }
-#if PY_VERSION_HEX >= 0x03000000
     if (PyObject_HasAttrString(tmp_fun,\"__code__\")) {
         if (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"__code__\"),\"co_argcount\")) {
-#else
-    if (PyObject_HasAttrString(tmp_fun,\"func_code\")) {
-        if (PyObject_HasAttrString(tmp = PyObject_GetAttrString(tmp_fun,\"func_code\"),\"co_argcount\")) {
-#endif
             PyObject *tmp_argcount = PyObject_GetAttrString(tmp,\"co_argcount\");
             Py_DECREF(tmp);
             if (tmp_argcount == NULL) {
@@ -1111,13 +1104,8 @@ goto capi_fail;
         }
     }
     /* Get the number of optional arguments */
-#if PY_VERSION_HEX >= 0x03000000
     if (PyObject_HasAttrString(tmp_fun,\"__defaults__\")) {
         if (PyTuple_Check(tmp = PyObject_GetAttrString(tmp_fun,\"__defaults__\")))
-#else
-    if (PyObject_HasAttrString(tmp_fun,\"func_defaults\")) {
-        if (PyTuple_Check(tmp = PyObject_GetAttrString(tmp_fun,\"func_defaults\")))
-#endif
             opt = PyTuple_Size(tmp);
         Py_XDECREF(tmp);
     }
@@ -1174,7 +1162,7 @@ def buildcfuncs():
 ############ Auxiliary functions for sorting needs ###################
 
 def append_needs(need, flag=1):
-    global outneeds, needs
+    # This function modifies the contents of the global `outneeds` dict.
     if isinstance(need, list):
         for n in need:
             append_needs(n, flag)
@@ -1241,7 +1229,7 @@ def append_needs(need, flag=1):
 
 
 def get_needs():
-    global outneeds, needs
+    # This function modifies the contents of the global `outneeds` dict.
     res = {}
     for n in outneeds.keys():
         out = []
index f61d8810a1810cac51d54a52dcf37f0766c0202a..90483e55be831b0c4f25e0c84059b9c215b832e1 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 Build common block mechanism for f2py2e.
@@ -13,8 +13,6 @@ $Date: 2005/05/06 10:57:33 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 __version__ = "$Revision: 1.19 $"[10:-1]
 
 from . import __version__
index 2aaf5d7c6c12e962c7e89e99692724f4d4bba178..3d2f97a5626e0be57d5d347bb45e6e110658b974 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 crackfortran --- read fortran (77,90) code and extract declaration information.
 
@@ -138,8 +138,6 @@ TODO:
     The above may be solved by creating appropriate preprocessor program, for example.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import string
 import fileinput
@@ -150,7 +148,7 @@ import platform
 
 from . import __version__
 
-# The eviroment provided by auxfuncs.py is needed for some calls to eval.
+# The environment provided by auxfuncs.py is needed for some calls to eval.
 # As the needed functions cannot be determined by static inspection of the
 # code, it is safest to use import * pending a major refactoring of f2py.
 from .auxfuncs import *
@@ -558,7 +556,8 @@ groupbegins90 = groupbegins77 + \
     r'|module(?!\s*procedure)|python\s*module|interface|type(?!\s*\()'
 beginpattern90 = re.compile(
     beforethisafter % ('', groupbegins90, groupbegins90, '.*'), re.I), 'begin'
-groupends = r'end|endprogram|endblockdata|endmodule|endpythonmodule|endinterface'
+groupends = (r'end|endprogram|endblockdata|endmodule|endpythonmodule|'
+             r'endinterface|endsubroutine|endfunction')
 endpattern = re.compile(
     beforethisafter % ('', groupends, groupends, r'[\w\s]*'), re.I), 'end'
 # endifs='end\s*(if|do|where|select|while|forall)'
@@ -580,8 +579,8 @@ publicpattern = re.compile(
     beforethisafter % ('', 'public', 'public', '.*'), re.I), 'public'
 privatepattern = re.compile(
     beforethisafter % ('', 'private', 'private', '.*'), re.I), 'private'
-intrisicpattern = re.compile(
-    beforethisafter % ('', 'intrisic', 'intrisic', '.*'), re.I), 'intrisic'
+intrinsicpattern = re.compile(
+    beforethisafter % ('', 'intrinsic', 'intrinsic', '.*'), re.I), 'intrinsic'
 intentpattern = re.compile(beforethisafter % (
     '', 'intent|depend|note|check', 'intent|depend|note|check', r'\s*\(.*?\).*'), re.I), 'intent'
 parameterpattern = re.compile(
@@ -706,7 +705,7 @@ def crackline(line, reset=0):
     for pat in [dimensionpattern, externalpattern, intentpattern, optionalpattern,
                 requiredpattern,
                 parameterpattern, datapattern, publicpattern, privatepattern,
-                intrisicpattern,
+                intrinsicpattern,
                 endifpattern, endpattern,
                 formatpattern,
                 beginpattern, functionpattern, subroutinepattern,
@@ -1098,7 +1097,7 @@ def analyzeline(m, case, line):
         last_name = updatevars(typespec, selector, attr, edecl)
         if last_name is not None:
             previous_context = ('variable', last_name, groupcounter)
-    elif case in ['dimension', 'intent', 'optional', 'required', 'external', 'public', 'private', 'intrisic']:
+    elif case in ['dimension', 'intent', 'optional', 'required', 'external', 'public', 'private', 'intrinsic']:
         edecl = groupcache[groupcounter]['vars']
         ll = m.group('after').strip()
         i = ll.find('::')
@@ -1158,7 +1157,7 @@ def analyzeline(m, case, line):
                     else:
                         errmess('analyzeline: intent(callback) %s is already'
                                 ' in argument list' % (k))
-            if case in ['optional', 'required', 'public', 'external', 'private', 'intrisic']:
+            if case in ['optional', 'required', 'public', 'external', 'private', 'intrinsic']:
                 ap = case
             if 'attrspec' in edecl[k]:
                 edecl[k]['attrspec'].append(ap)
@@ -1750,10 +1749,12 @@ def setattrspec(decl, attr, force=0):
         decl['attrspec'].append(attr)
     elif attr == 'automatic' and 'static' not in decl['attrspec']:
         decl['attrspec'].append(attr)
-    elif attr == 'public' and 'private' not in decl['attrspec']:
-        decl['attrspec'].append(attr)
-    elif attr == 'private' and 'public' not in decl['attrspec']:
-        decl['attrspec'].append(attr)
+    elif attr == 'public':
+        if 'private' not in decl['attrspec']:
+            decl['attrspec'].append(attr)
+    elif attr == 'private':
+        if 'public' not in decl['attrspec']:
+            decl['attrspec'].append(attr)
     else:
         decl['attrspec'].append(attr)
     return decl
@@ -3114,11 +3115,12 @@ def true_intent_list(var):
     ret = []
     for intent in lst:
         try:
-            c = eval('isintent_%s(var)' % intent)
-        except NameError:
-            c = 0
-        if c:
-            ret.append(intent)
+            f = globals()['isintent_%s' % intent]
+        except KeyError:
+            pass
+        else:
+            if f(var):
+                ret.append(intent)
     return ret
 
 
index 0241fed12ffebd6604a8cb1bbc6ead7c42c06c99..21ee399f035f3042134c162511659e50c2a90e93 100644 (file)
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
+#!/usr/bin/env python3
 import os
 import sys
 import tempfile
index d03eff9e31b2fd689abd724d2b9ae1d43017f1f6..71a049e410f6e8c90a1cccbce17246961611cf98 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 f2py2e - Fortran to Python C/API generator. 2nd Edition.
@@ -14,8 +14,6 @@ $Date: 2005/05/06 08:31:19 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import os
 import pprint
@@ -171,7 +169,7 @@ Extra options (only effective with -c):
 
 Version:     %s
 numpy Version: %s
-Requires:    Python 2.3 or higher.
+Requires:    Python 3.5 or higher.
 License:     NumPy license (see LICENSE.txt in the NumPy source code)
 Copyright 1999 - 2011 Pearu Peterson all rights reserved.
 http://cens.ioc.ee/projects/f2py2e/""" % (f2py_version, numpy_version)
index f5d5fa63d03f0d5d99b285b7d0081f76d31ad4a2..1f109e67a5e21f7cd88acf06dcc887da0abf59c7 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import re
 
index 85eae80479285e0ac1f3509d709997ff7ce7c261..122fa89394b7ae7f8b1fe1d5e52b763b0439ce0c 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 Build F90 module support for f2py2e.
@@ -13,8 +13,6 @@ $Date: 2005/02/03 19:30:23 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 __version__ = "$Revision: 1.27 $"[10:-1]
 
 f2py_version = 'See `f2py -v`'
@@ -25,7 +23,7 @@ from . import capi_maps
 from . import func2subr
 from .crackfortran import undo_rmbadname, undo_rmbadname1
 
-# The eviroment provided by auxfuncs.py is needed for some calls to eval.
+# The environment provided by auxfuncs.py is needed for some calls to eval.
 # As the needed functions cannot be determined by static inspection of the
 # code, it is safest to use import * pending a major refactoring of f2py.
 from .auxfuncs import *
@@ -87,7 +85,6 @@ fgetdims2_sa = """\
 
 
 def buildhooks(pymod):
-    global fgetdims1, fgetdims2
     from . import rules
     ret = {'f90modhooks': [], 'initf90modhooks': [], 'body': [],
            'need': ['F_FUNC', 'arrayobject.h'],
@@ -180,7 +177,7 @@ def buildhooks(pymod):
                      (m['name'], undo_rmbadname1(n)))
                 fadd('integer flag\n')
                 fhooks[0] = fhooks[0] + fgetdims1
-                dms = eval('range(1,%s+1)' % (dm['rank']))
+                dms = range(1, int(dm['rank']) + 1)
                 fadd(' allocate(d(%s))\n' %
                      (','.join(['s(%s)' % i for i in dms])))
                 fhooks[0] = fhooks[0] + use_fgetdims2
index 6010d5a231af4c4fc6ddc64fc48eeb51e4c81d1c..e9976f43cf41646081e75a5d5feec357e7221caf 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 Rules for building C/API module with f2py2e.
@@ -13,8 +13,6 @@ $Date: 2004/11/26 11:13:06 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 __version__ = "$Revision: 1.16 $"[10:-1]
 
 f2py_version = 'See `f2py -v`'
index f2f713bde251c892a9e0d6d6a7428e7869253e11..ecfc71ae3a64153b0c46e79ef1fa669eee604a7d 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 Rules for building C/API module with f2py2e.
@@ -50,8 +50,6 @@ $Date: 2005/08/30 08:58:42 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 __version__ = "$Revision: 1.129 $"[10:-1]
 
 from . import __version__
@@ -180,7 +178,6 @@ static PyMethodDef f2py_module_methods[] = {
 \t{NULL,NULL}
 };
 
-#if PY_VERSION_HEX >= 0x03000000
 static struct PyModuleDef moduledef = {
 \tPyModuleDef_HEAD_INIT,
 \t"#modulename#",
@@ -192,35 +189,20 @@ static struct PyModuleDef moduledef = {
 \tNULL,
 \tNULL
 };
-#endif
 
-#if PY_VERSION_HEX >= 0x03000000
-#define RETVAL m
 PyMODINIT_FUNC PyInit_#modulename#(void) {
-#else
-#define RETVAL
-PyMODINIT_FUNC init#modulename#(void) {
-#endif
 \tint i;
 \tPyObject *m,*d, *s, *tmp;
-#if PY_VERSION_HEX >= 0x03000000
 \tm = #modulename#_module = PyModule_Create(&moduledef);
-#else
-\tm = #modulename#_module = Py_InitModule(\"#modulename#\", f2py_module_methods);
-#endif
-\tPy_TYPE(&PyFortran_Type) = &PyType_Type;
+\tPy_SET_TYPE(&PyFortran_Type, &PyType_Type);
 \timport_array();
 \tif (PyErr_Occurred())
-\t\t{PyErr_SetString(PyExc_ImportError, \"can't initialize module #modulename# (failed to import numpy)\"); return RETVAL;}
+\t\t{PyErr_SetString(PyExc_ImportError, \"can't initialize module #modulename# (failed to import numpy)\"); return m;}
 \td = PyModule_GetDict(m);
 \ts = PyString_FromString(\"$R""" + """evision: $\");
 \tPyDict_SetItemString(d, \"__version__\", s);
 \tPy_DECREF(s);
-#if PY_VERSION_HEX >= 0x03000000
 \ts = PyUnicode_FromString(
-#else
-\ts = PyString_FromString(
-#endif
 \t\t\"This module '#modulename#' is auto-generated with f2py (version:#f2py_version#).\\nFunctions:\\n\"\n#docs#\".\");
 \tPyDict_SetItemString(d, \"__doc__\", s);
 \tPy_DECREF(s);
@@ -245,7 +227,7 @@ PyMODINIT_FUNC init#modulename#(void) {
 \tif (! PyErr_Occurred())
 \t\ton_exit(f2py_report_on_exit,(void*)\"#modulename#\");
 #endif
-\treturn RETVAL;
+\treturn m;
 }
 #ifdef __cplusplus
 }
@@ -294,7 +276,7 @@ static PyObject *#apiname#(const PyObject *capi_self,
 f2py_start_clock();
 #endif
 \tif (!PyArg_ParseTupleAndKeywords(capi_args,capi_keywds,\\
-\t\t\"#argformat##keyformat##xaformat#:#pyname#\",\\
+\t\t\"#argformat#|#keyformat##xaformat#:#pyname#\",\\
 \t\tcapi_kwlist#args_capi##keys_capi##keys_xa#))\n\t\treturn NULL;
 #frompyobj#
 /*end of frompyobj*/
@@ -448,11 +430,7 @@ rout_rules = [
       tmp = F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL);
       PyObject_SetAttrString(o,"_cpointer", tmp);
       Py_DECREF(tmp);
-#if PY_VERSION_HEX >= 0x03000000
       s = PyUnicode_FromString("#name#");
-#else
-      s = PyString_FromString("#name#");
-#endif
       PyObject_SetAttrString(o,"__name__", s);
       Py_DECREF(s);
     }
@@ -490,11 +468,7 @@ rout_rules = [
       tmp = F2PyCapsule_FromVoidPtr((void*)#F_FUNC#(#name_lower#,#NAME#),NULL);
       PyObject_SetAttrString(o,"_cpointer", tmp);
       Py_DECREF(tmp);
-#if PY_VERSION_HEX >= 0x03000000
       s = PyUnicode_FromString("#name#");
-#else
-      s = PyString_FromString("#name#");
-#endif
       PyObject_SetAttrString(o,"__name__", s);
       Py_DECREF(s);
     }
@@ -1064,8 +1038,10 @@ if (#varname#_capi==Py_None) {
                        '\tcapi_#varname#_tmp = array_from_pyobj(#atype#,#varname#_Dims,#varname#_Rank,capi_#varname#_intent,#varname#_capi);'},
                       """\
 \tif (capi_#varname#_tmp == NULL) {
-\t\tif (!PyErr_Occurred())
-\t\t\tPyErr_SetString(#modulename#_error,\"failed in converting #nth# `#varname#\' of #pyname# to C/Fortran array\" );
+\t\tPyObject *exc, *val, *tb;
+\t\tPyErr_Fetch(&exc, &val, &tb);
+\t\tPyErr_SetString(exc ? exc : #modulename#_error,\"failed in converting #nth# `#varname#\' of #pyname# to C/Fortran array\" );
+\t\tnpy_PyErr_ChainExceptionsCause(exc, val, tb);
 \t} else {
 \t\t#varname# = (#ctype# *)(PyArray_DATA(capi_#varname#_tmp));
 """,
@@ -1081,8 +1057,10 @@ if (#varname#_capi==Py_None) {
 \t\t\twhile ((_i = nextforcomb()))
 \t\t\t\t#varname#[capi_i++] = #init#; /* fortran way */
 \t\t} else {
-\t\t\tif (!PyErr_Occurred())
-\t\t\t\tPyErr_SetString(#modulename#_error,\"Initialization of #nth# #varname# failed (initforcomb).\");
+\t\t\tPyObject *exc, *val, *tb;
+\t\t\tPyErr_Fetch(&exc, &val, &tb);
+\t\t\tPyErr_SetString(exc ? exc : #modulename#_error,\"Initialization of #nth# #varname# failed (initforcomb).\");
+\t\t\tnpy_PyErr_ChainExceptionsCause(exc, val, tb);
 \t\t\tf2py_success = 0;
 \t\t}
 \t}
@@ -1179,7 +1157,6 @@ def buildmodule(m, um):
     """
     Return
     """
-    global f2py_version, options
     outmess('\tBuilding module "%s"...\n' % (m['name']))
     ret = {}
     mod_rules = defmod_rules[:]
@@ -1467,16 +1444,6 @@ def buildapi(rout):
                 ['\\begin{description}'] + rd[k][1:] +\
                 ['\\end{description}']
 
-    # Workaround for Python 2.6, 2.6.1 bug: https://bugs.python.org/issue4720
-    if rd['keyformat'] or rd['xaformat']:
-        argformat = rd['argformat']
-        if isinstance(argformat, list):
-            argformat.append('|')
-        else:
-            assert isinstance(argformat, str), repr(
-                (argformat, type(argformat)))
-            rd['argformat'] += '|'
-
     ar = applyrules(routine_rules, rd)
     if ismoduleroutine(rout):
         outmess('\t\t\t  %s\n' % (ar['docshort']))
index a8c1401aaa9fa765a373c3ce277266a5bf5ce923..80b47e527aabd1bd571f1083f96307ff9ae6d6d9 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 setup.py for installing F2PY
 
@@ -16,8 +16,6 @@ $Date: 2005/01/30 17:22:14 $
 Pearu Peterson
 
 """
-from __future__ import division, print_function
-
 from numpy.distutils.core import setup
 from numpy.distutils.misc_util import Configuration
 
@@ -27,7 +25,8 @@ from __version__ import version
 
 def configuration(parent_package='', top_path=None):
     config = Configuration('f2py', parent_package, top_path)
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
+    config.add_data_dir('tests/src')
     config.add_data_files(
         'src/fortranobject.c',
         'src/fortranobject.h')
index 8aa55555d2a57e34c5249a337770b4c1ef29da35..b3a04bcf0ef114ef8850842bdc823d8255013956 100644 (file)
@@ -115,14 +115,6 @@ fortran_dealloc(PyFortranObject *fp) {
 }
 
 
-#if PY_VERSION_HEX >= 0x03000000
-#else
-static PyMethodDef fortran_methods[] = {
-    {NULL,          NULL}           /* sentinel */
-};
-#endif
-
-
 /* Returns number of bytes consumed from buf, or -1 on error. */
 static Py_ssize_t
 format_def(char *buf, Py_ssize_t size, FortranDataDef def)
@@ -242,11 +234,7 @@ fortran_doc(FortranDataDef def)
     size--;
 
     /* p now points one beyond the last character of the string in buf */
-#if PY_VERSION_HEX >= 0x03000000
     s = PyUnicode_FromStringAndSize(buf, p - buf);
-#else
-    s = PyString_FromStringAndSize(buf, p - buf);
-#endif
 
     PyMem_Free(buf);
     return s;
@@ -272,8 +260,11 @@ static PyObject *
 fortran_getattr(PyFortranObject *fp, char *name) {
     int i,j,k,flag;
     if (fp->dict != NULL) {
-        PyObject *v = PyDict_GetItemString(fp->dict, name);
-        if (v != NULL) {
+        PyObject *v = _PyDict_GetItemStringWithError(fp->dict, name);
+        if (v == NULL && PyErr_Occurred()) {
+            return NULL;
+        }
+        else if (v != NULL) {
             Py_INCREF(v);
             return v;
         }
@@ -306,7 +297,6 @@ fortran_getattr(PyFortranObject *fp, char *name) {
         return fp->dict;
     }
     if (strcmp(name,"__doc__")==0) {
-#if PY_VERSION_HEX >= 0x03000000
         PyObject *s = PyUnicode_FromString(""), *s2, *s3;
         for (i=0;i<fp->len;i++) {
             s2 = fortran_doc(fp->defs[i]);
@@ -315,11 +305,6 @@ fortran_getattr(PyFortranObject *fp, char *name) {
             Py_DECREF(s);
             s = s3;
         }
-#else
-        PyObject *s = PyString_FromString("");
-        for (i=0;i<fp->len;i++)
-            PyString_ConcatAndDel(&s,fortran_doc(fp->defs[i]));
-#endif
         if (PyDict_SetItemString(fp->dict, name, s))
             return NULL;
         return s;
@@ -330,17 +315,11 @@ fortran_getattr(PyFortranObject *fp, char *name) {
             return NULL;
         return cobj;
     }
-#if PY_VERSION_HEX >= 0x03000000
-    if (1) {
-        PyObject *str, *ret;
-        str = PyUnicode_FromString(name);
-        ret = PyObject_GenericGetAttr((PyObject *)fp, str);
-        Py_DECREF(str);
-        return ret;
-    }
-#else
-    return Py_FindMethod(fortran_methods, (PyObject *)fp, name);
-#endif
+    PyObject *str, *ret;
+    str = PyUnicode_FromString(name);
+    ret = PyObject_GenericGetAttr((PyObject *)fp, str);
+    Py_DECREF(str);
+    return ret;
 }
 
 static int
@@ -434,48 +413,26 @@ fortran_repr(PyFortranObject *fp)
     PyObject *name = NULL, *repr = NULL;
     name = PyObject_GetAttrString((PyObject *)fp, "__name__");
     PyErr_Clear();
-#if PY_VERSION_HEX >= 0x03000000
     if (name != NULL && PyUnicode_Check(name)) {
         repr = PyUnicode_FromFormat("<fortran %U>", name);
     }
     else {
         repr = PyUnicode_FromString("<fortran object>");
     }
-#else
-    if (name != NULL && PyString_Check(name)) {
-        repr = PyString_FromFormat("<fortran %s>", PyString_AsString(name));
-    }
-    else {
-        repr = PyString_FromString("<fortran object>");
-    }
-#endif
     Py_XDECREF(name);
     return repr;
 }
 
 
 PyTypeObject PyFortran_Type = {
-#if PY_VERSION_HEX >= 0x03000000
     PyVarObject_HEAD_INIT(NULL, 0)
-#else
-    PyObject_HEAD_INIT(0)
-    0,                            /*ob_size*/
-#endif
-    "fortran",                    /*tp_name*/
-    sizeof(PyFortranObject),      /*tp_basicsize*/
-    0,                            /*tp_itemsize*/
-    /* methods */
-    (destructor)fortran_dealloc,  /*tp_dealloc*/
-    0,                            /*tp_print*/
-    (getattrfunc)fortran_getattr, /*tp_getattr*/
-    (setattrfunc)fortran_setattr, /*tp_setattr*/
-    0,                            /*tp_compare/tp_reserved*/
-    (reprfunc)fortran_repr,       /*tp_repr*/
-    0,                            /*tp_as_number*/
-    0,                            /*tp_as_sequence*/
-    0,                            /*tp_as_mapping*/
-    0,                            /*tp_hash*/
-    (ternaryfunc)fortran_call,    /*tp_call*/
+    .tp_name ="fortran",
+    .tp_basicsize = sizeof(PyFortranObject),
+    .tp_dealloc = (destructor)fortran_dealloc,
+    .tp_getattr = (getattrfunc)fortran_getattr,
+    .tp_setattr = (setattrfunc)fortran_setattr,
+    .tp_repr = (reprfunc)fortran_repr,
+    .tp_call = (ternaryfunc)fortran_call,
 };
 
 /************************* f2py_report_atexit *******************************/
@@ -626,7 +583,7 @@ count_negative_dimensions(const int rank,
 }
 
 #ifdef DEBUG_COPY_ND_ARRAY
-void dump_dims(int rank, npy_intp* dims) {
+void dump_dims(int rank, npy_intp const* dims) {
     int i;
     printf("[");
     for(i=0;i<rank;++i) {
@@ -839,9 +796,10 @@ PyArrayObject* array_from_pyobj(const int type_num,
     if ((intent & F2PY_INTENT_INOUT) ||
             (intent & F2PY_INTENT_INPLACE) ||
             (intent & F2PY_INTENT_CACHE)) {
-        PyErr_SetString(PyExc_TypeError,
-                        "failed to initialize intent(inout|inplace|cache) "
-                        "array, input not an array");
+        PyErr_Format(PyExc_TypeError,
+                     "failed to initialize intent(inout|inplace|cache) "
+                     "array, input '%s' object is not an array",
+                     Py_TYPE(obj)->tp_name);
         return NULL;
     }
 
@@ -1052,8 +1010,6 @@ int copy_ND_array(const PyArrayObject *arr, PyArrayObject *out)
 /* Compatibility functions for Python >= 3.0 */
 /*********************************************/
 
-#if PY_VERSION_HEX >= 0x03000000
-
 PyObject *
 F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *))
 {
@@ -1080,29 +1036,6 @@ F2PyCapsule_Check(PyObject *ptr)
     return PyCapsule_CheckExact(ptr);
 }
 
-#else
-
-PyObject *
-F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(void *))
-{
-    return PyCObject_FromVoidPtr(ptr, dtor);
-}
-
-void *
-F2PyCapsule_AsVoidPtr(PyObject *ptr)
-{
-    return PyCObject_AsVoidPtr(ptr);
-}
-
-int
-F2PyCapsule_Check(PyObject *ptr)
-{
-    return PyCObject_Check(ptr);
-}
-
-#endif
-
-
 #ifdef __cplusplus
 }
 #endif
index 5d0dcf67633769333ec5be6f9679f43a661460de..5c382ab7b71ced3ea10527a70b5c2f9fd3331f53 100644 (file)
@@ -11,30 +11,7 @@ extern "C" {
 #endif
 #define PY_ARRAY_UNIQUE_SYMBOL _npy_f2py_ARRAY_API
 #include "numpy/arrayobject.h"
-
-/*
- * Python 3 support macros
- */
-#if PY_VERSION_HEX >= 0x03000000
-#define PyString_Check PyBytes_Check
-#define PyString_GET_SIZE PyBytes_GET_SIZE
-#define PyString_AS_STRING PyBytes_AS_STRING
-#define PyString_FromString PyBytes_FromString
-#define PyUString_FromStringAndSize PyUnicode_FromStringAndSize
-#define PyString_ConcatAndDel PyBytes_ConcatAndDel
-#define PyString_AsString PyBytes_AsString
-
-#define PyInt_Check PyLong_Check
-#define PyInt_FromLong PyLong_FromLong
-#define PyInt_AS_LONG PyLong_AsLong
-#define PyInt_AsLong PyLong_AsLong
-
-#define PyNumber_Int PyNumber_Long
-
-#else
-
-#define PyUString_FromStringAndSize PyString_FromStringAndSize
-#endif
+#include "numpy/npy_3kcompat.h"
 
 
 #ifdef F2PY_REPORT_ATEXIT
@@ -105,20 +82,10 @@ typedef struct {
   extern PyObject * PyFortranObject_New(FortranDataDef* defs, f2py_void_func init);
   extern PyObject * PyFortranObject_NewAsAttr(FortranDataDef* defs);
 
-#if PY_VERSION_HEX >= 0x03000000
-
 PyObject * F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(PyObject *));
 void * F2PyCapsule_AsVoidPtr(PyObject *obj);
 int F2PyCapsule_Check(PyObject *ptr);
 
-#else
-
-PyObject * F2PyCapsule_FromVoidPtr(void *ptr, void (*dtor)(void *));
-void * F2PyCapsule_AsVoidPtr(PyObject *ptr);
-int F2PyCapsule_Check(PyObject *ptr);
-
-#endif
-
 #define ISCONTIGUOUS(m) (PyArray_FLAGS(m) & NPY_ARRAY_C_CONTIGUOUS)
 #define F2PY_INTENT_IN 1
 #define F2PY_INTENT_INOUT 2
index 978db4e6902ad7ef3384c09a2365b99c84c97e18..0db33e71448f7855092f8e988fbd167730a27e19 100644 (file)
@@ -129,7 +129,6 @@ static PyMethodDef f2py_module_methods[] = {
   {NULL,NULL}
 };
 
-#if PY_VERSION_HEX >= 0x03000000
 static struct PyModuleDef moduledef = {
     PyModuleDef_HEAD_INIT,
     "test_array_from_pyobj_ext",
@@ -141,22 +140,11 @@ static struct PyModuleDef moduledef = {
     NULL,
     NULL
 };
-#endif
 
-#if PY_VERSION_HEX >= 0x03000000
-#define RETVAL m
 PyMODINIT_FUNC PyInit_test_array_from_pyobj_ext(void) {
-#else
-#define RETVAL
-PyMODINIT_FUNC inittest_array_from_pyobj_ext(void) {
-#endif
   PyObject *m,*d, *s;
-#if PY_VERSION_HEX >= 0x03000000
   m = wrap_module = PyModule_Create(&moduledef);
-#else
-  m = wrap_module = Py_InitModule("test_array_from_pyobj_ext", f2py_module_methods);
-#endif
-  Py_TYPE(&PyFortran_Type) = &PyType_Type;
+  Py_SET_TYPE(&PyFortran_Type, &PyType_Type);
   import_array();
   if (PyErr_Occurred())
     Py_FatalError("can't initialize module wrap (failed to import numpy)");
@@ -238,7 +226,7 @@ PyMODINIT_FUNC inittest_array_from_pyobj_ext(void) {
   on_exit(f2py_report_on_exit,(void*)"array_from_pyobj.wrap.call");
 #endif
 
-  return RETVAL;
+  return m;
 }
 #ifdef __cplusplus
 }
index a80090185d0f5c6f00282ed88709126546a76784..b719f2495ed47b31a9f8a12f3302f25646a392ef 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 import copy
@@ -57,7 +55,7 @@ def flags2names(flags):
     return info
 
 
-class Intent(object):
+class Intent:
 
     def __init__(self, intent_list=[]):
         self.intent_list = intent_list[:]
@@ -131,7 +129,7 @@ if ((intp().dtype.itemsize != 4 or clongdouble().dtype.alignment <= 8) and
     _cast_dict['CDOUBLE'] = _cast_dict['DOUBLE'] + ['CFLOAT', 'CDOUBLE']
 
 
-class Type(object):
+class Type:
     _type_cache = {}
 
     def __new__(cls, name):
@@ -192,7 +190,7 @@ class Type(object):
         return types
 
 
-class Array(object):
+class Array:
 
     def __init__(self, typ, dims, intent, obj):
         self.type = typ
@@ -293,7 +291,7 @@ class Array(object):
         return obj_attr[0] == self.arr_attr[0]
 
 
-class TestIntent(object):
+class TestIntent:
 
     def test_in_out(self):
         assert_equal(str(intent.in_.out), 'intent(in,out)')
@@ -304,7 +302,7 @@ class TestIntent(object):
         assert_(not intent.in_.is_intent('c'))
 
 
-class TestSharedMemory(object):
+class TestSharedMemory:
     num2seq = [1, 2]
     num23seq = [[1, 2, 3], [4, 5, 6]]
 
index e5695a61c11a4e6a4cdff6661babbbdbcc74fc27..dfc252660c5949d941be271df43512f6ad7ed561 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import pytest
 import tempfile
index 4f1678980f8b29c77a7df07b4effe7040aa388fa..e431f5ba6c97deb73db85afbe51bc4e703e0cd1d 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import pytest
 from . import util
@@ -18,7 +16,8 @@ class TestBlockDocString(util.F2PyTest):
 
     @pytest.mark.skipif(sys.platform=='win32',
                         reason='Fails with MinGW64 Gfortran (Issue #9673)')
-    @pytest.mark.xfail(IS_PYPY, reason="PyPy does not modify tp_doc")
+    @pytest.mark.xfail(IS_PYPY,
+                       reason="PyPy cannot modify tp_doc after PyType_Ready")
     def test_block_docstring(self):
         expected = "'i'-array(2,3)\n"
         assert_equal(self.module.block.__doc__, expected)
index 21c29ba5f8a89f584b8d3740255b3f3758d0b9ff..4e29ab9fcd905a4045a86debaacd39beddce8b9c 100644 (file)
@@ -1,12 +1,10 @@
-from __future__ import division, absolute_import, print_function
-
 import math
 import textwrap
 import sys
 import pytest
 
 import numpy as np
-from numpy.testing import assert_, assert_equal
+from numpy.testing import assert_, assert_equal, IS_PYPY
 from . import util
 
 
@@ -61,12 +59,12 @@ cf2py  intent(out) a
        end
     """
 
-    @pytest.mark.slow
     @pytest.mark.parametrize('name', 't,t2'.split(','))
     def test_all(self, name):
         self.check_function(name)
 
-    @pytest.mark.slow
+    @pytest.mark.xfail(IS_PYPY,
+                       reason="PyPy cannot modify tp_doc after PyType_Ready")
     def test_docstring(self):
         expected = textwrap.dedent("""\
         a = t(fun,[fun_extra_args])
@@ -118,7 +116,7 @@ cf2py  intent(out) a
         r = t(self.module.func0._cpointer)
         assert_(r == 11, repr(r))
 
-        class A(object):
+        class A:
 
             def __call__(self):
                 return 7
index dcb01b0ec736ab28111256544dc8bf07e8ef33a3..e4bf3550476123de91e5890a0c7b281aa87bb27b 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 import pytest
index 40ea7997f7d7120160f692e15ea00d531eeebfd2..f76fd644807c487f953926e800227e75889258ba 100644 (file)
@@ -1,8 +1,6 @@
 """See https://github.com/numpy/numpy/pull/11937.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import os
 import uuid
@@ -16,8 +14,6 @@ from . import util
 
 
 def setup_module():
-    if sys.platform == 'win32' and sys.version_info[0] < 3:
-        pytest.skip('Fails with MinGW64 Gfortran (Issue #9673)')
     if not util.has_c_compiler():
         pytest.skip("Needs C compiler")
     if not util.has_f77_compiler():
diff --git a/numpy/f2py/tests/test_crackfortran.py b/numpy/f2py/tests/test_crackfortran.py
new file mode 100644 (file)
index 0000000..7358040
--- /dev/null
@@ -0,0 +1,88 @@
+import numpy as np
+from numpy.testing import assert_array_equal
+from . import util
+from numpy.f2py import crackfortran
+import tempfile
+import textwrap
+
+
+class TestNoSpace(util.F2PyTest):
+    # issue gh-15035: add handling for endsubroutine, endfunction with no space
+    # between "end" and the block name
+    code = """
+        subroutine subb(k)
+          real(8), intent(inout) :: k(:)
+          k=k+1
+        endsubroutine
+
+        subroutine subc(w,k)
+          real(8), intent(in) :: w(:)
+          real(8), intent(out) :: k(size(w))
+          k=w+1
+        endsubroutine
+
+        function t0(value)
+          character value
+          character t0
+          t0 = value
+        endfunction
+    """
+
+    def test_module(self):
+        k = np.array([1, 2, 3], dtype=np.float64)
+        w = np.array([1, 2, 3], dtype=np.float64)
+        self.module.subb(k)
+        assert_array_equal(k, w + 1)
+        self.module.subc([w, k])
+        assert_array_equal(k, w + 1)
+        assert self.module.t0(23) == b'2'
+
+class TestPublicPrivate():
+    def test_defaultPrivate(self, tmp_path):
+        f_path = tmp_path / "mod.f90"
+        with f_path.open('w') as ff:
+            ff.write(textwrap.dedent("""\
+            module foo
+              private
+              integer :: a
+              public :: setA
+              integer :: b
+            contains
+              subroutine setA(v)
+                integer, intent(in) :: v
+                a = v
+              end subroutine setA
+            end module foo
+            """))
+        mod = crackfortran.crackfortran([str(f_path)])
+        assert len(mod) == 1
+        mod = mod[0]
+        assert 'private' in mod['vars']['a']['attrspec']
+        assert 'public' not in mod['vars']['a']['attrspec']
+        assert 'private' in mod['vars']['b']['attrspec']
+        assert 'public' not in mod['vars']['b']['attrspec']
+        assert 'private' not in mod['vars']['seta']['attrspec']
+        assert 'public' in mod['vars']['seta']['attrspec']
+
+    def test_defaultPublic(self, tmp_path):
+        f_path = tmp_path / "mod.f90"
+        with f_path.open('w') as ff:
+            ff.write(textwrap.dedent("""\
+            module foo
+              public
+              integer, private :: a
+              public :: setA
+            contains
+              subroutine setA(v)
+                integer, intent(in) :: v
+                a = v
+              end subroutine setA
+            end module foo
+            """))
+        mod = crackfortran.crackfortran([str(f_path)])
+        assert len(mod) == 1
+        mod = mod[0]
+        assert 'private' in mod['vars']['a']['attrspec']
+        assert 'public' not in mod['vars']['a']['attrspec']
+        assert 'private' not in mod['vars']['seta']['attrspec']
+        assert 'public' in mod['vars']['seta']['attrspec']
index 1f7762a805f28ea3b08a280abfb8a7f434aba5d7..a7e2b28ed37c9cabb8dd2c8bd485466ae2552226 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import pytest
 
index 0337538ff1ef17f717f60510d03b8a6fa01de9e7..04266ca5b19078dd26306d052f88e76415975868 100644 (file)
@@ -1,10 +1,8 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import textwrap
 import pytest
 
-from numpy.testing import assert_, assert_equal
+from numpy.testing import assert_, assert_equal, IS_PYPY
 from . import util
 
 
@@ -17,13 +15,13 @@ class TestMixed(util.F2PyTest):
                _path('src', 'mixed', 'foo_fixed.f90'),
                _path('src', 'mixed', 'foo_free.f90')]
 
-    @pytest.mark.slow
     def test_all(self):
         assert_(self.module.bar11() == 11)
         assert_(self.module.foo_fixed.bar12() == 12)
         assert_(self.module.foo_free.bar13() == 13)
 
-    @pytest.mark.slow
+    @pytest.mark.xfail(IS_PYPY,
+                       reason="PyPy cannot modify tp_doc after PyType_Ready")
     def test_docstring(self):
         expected = textwrap.dedent("""\
         a = bar11()
index 6a378687ad78049df9e3059f9c4cea61db8cbdac..b6182716987b12ea9d3c982e5fc93ead2a5e1dc3 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import pytest
 
index c9a1c36f50cb8d018d7aa1043ee118ce35f4c84f..20c77666c59aaff5b21e17722ba35805270f1fb9 100644 (file)
@@ -1,10 +1,7 @@
 """See https://github.com/numpy/numpy/pull/10676.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
-from importlib import import_module
 import pytest
 
 from numpy.testing import assert_equal
index 3adae635d9acc71247d7d17cc2bba80b609ca4d6..67e00f1f78205bca797d056776e548a298da05b8 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import pytest
 
index fc3a58d36b8a70e11f256fa2e529061efd46c73e..429e69bb4a24ae6c5c4e3ce77172927f0b6372f8 100644 (file)
@@ -1,16 +1,15 @@
-from __future__ import division, absolute_import, print_function
-
 import pytest
 
 from numpy import array
 from numpy.testing import assert_
 from . import util
+import platform
+IS_S390X = platform.machine() == 's390x'
 
 
 class TestReturnCharacter(util.F2PyTest):
 
-    def check_function(self, t):
-        tname = t.__doc__.split()[0]
+    def check_function(self, t, tname):
         if tname in ['t0', 't1', 's0', 's1']:
             assert_(t(23) == b'2')
             r = t('ab')
@@ -81,10 +80,10 @@ cf2py    intent(out) ts
        end
     """
 
-    @pytest.mark.slow
+    @pytest.mark.xfail(IS_S390X, reason="calback returns ' '")
     @pytest.mark.parametrize('name', 't0,t1,t5,s0,s1,s5,ss'.split(','))
     def test_all(self, name):
-        self.check_function(getattr(self.module, name))
+        self.check_function(getattr(self.module, name), name)
 
 
 class TestF90ReturnCharacter(TestReturnCharacter):
@@ -140,7 +139,7 @@ module f90_return_char
 end module f90_return_char
     """
 
-    @pytest.mark.slow
+    @pytest.mark.xfail(IS_S390X, reason="calback returns ' '")
     @pytest.mark.parametrize('name', 't0,t1,t5,ts,s0,s1,s5,ss'.split(','))
     def test_all(self, name):
-        self.check_function(getattr(self.module.f90_return_char, name))
+        self.check_function(getattr(self.module.f90_return_char, name), name)
index 43c884dfb0d5e8ed483773b1225be72be590f37d..3d2e2b94f27ac302bd337645a6e8b70fa92c5fc5 100644 (file)
@@ -1,24 +1,20 @@
-from __future__ import division, absolute_import, print_function
-
 import pytest
 
 from numpy import array
-from numpy.compat import long
 from numpy.testing import assert_, assert_raises
 from . import util
 
 
 class TestReturnComplex(util.F2PyTest):
 
-    def check_function(self, t):
-        tname = t.__doc__.split()[0]
+    def check_function(self, t, tname):
         if tname in ['t0', 't8', 's0', 's8']:
             err = 1e-5
         else:
             err = 0.0
         assert_(abs(t(234j) - 234.0j) <= err)
         assert_(abs(t(234.6) - 234.6) <= err)
-        assert_(abs(t(long(234)) - 234.0) <= err)
+        assert_(abs(t(234) - 234.0) <= err)
         assert_(abs(t(234.6 + 3j) - (234.6 + 3j)) <= err)
         #assert_( abs(t('234')-234.)<=err)
         #assert_( abs(t('234.6')-234.6)<=err)
@@ -104,10 +100,9 @@ cf2py    intent(out) td
        end
     """
 
-    @pytest.mark.slow
     @pytest.mark.parametrize('name', 't0,t8,t16,td,s0,s8,s16,sd'.split(','))
     def test_all(self, name):
-        self.check_function(getattr(self.module, name))
+        self.check_function(getattr(self.module, name), name)
 
 
 class TestF90ReturnComplex(TestReturnComplex):
@@ -163,7 +158,6 @@ module f90_return_complex
 end module f90_return_complex
     """
 
-    @pytest.mark.slow
     @pytest.mark.parametrize('name', 't0,t8,t16,td,s0,s8,s16,sd'.split(','))
     def test_all(self, name):
-        self.check_function(getattr(self.module.f90_return_complex, name))
+        self.check_function(getattr(self.module.f90_return_complex, name), name)
index 22f4acfdf6d1d265e94324916d20f1b355b8cbc3..0a8121dc14b83b0914ed395ce03b952b4c11608e 100644 (file)
@@ -1,19 +1,15 @@
-from __future__ import division, absolute_import, print_function
-
 import pytest
 
 from numpy import array
-from numpy.compat import long
 from numpy.testing import assert_, assert_raises
 from . import util
 
 
 class TestReturnInteger(util.F2PyTest):
 
-    def check_function(self, t):
+    def check_function(self, t, tname):
         assert_(t(123) == 123, repr(t(123)))
         assert_(t(123.6) == 123)
-        assert_(t(long(123)) == 123)
         assert_(t('123') == 123)
         assert_(t(-123) == -123)
         assert_(t([123]) == 123)
@@ -38,7 +34,7 @@ class TestReturnInteger(util.F2PyTest):
         assert_raises(Exception, t, t)
         assert_raises(Exception, t, {})
 
-        if t.__doc__.split()[0] in ['t8', 's8']:
+        if tname in ['t8', 's8']:
             assert_raises(OverflowError, t, 100000000000000000000000)
             assert_raises(OverflowError, t, 10000000011111111111111.23)
 
@@ -103,11 +99,10 @@ cf2py    intent(out) t8
        end
     """
 
-    @pytest.mark.slow
     @pytest.mark.parametrize('name',
                              't0,t1,t2,t4,t8,s0,s1,s2,s4,s8'.split(','))
     def test_all(self, name):
-        self.check_function(getattr(self.module, name))
+        self.check_function(getattr(self.module, name), name)
 
 
 class TestF90ReturnInteger(TestReturnInteger):
@@ -174,8 +169,7 @@ module f90_return_integer
 end module f90_return_integer
     """
 
-    @pytest.mark.slow
     @pytest.mark.parametrize('name',
                              't0,t1,t2,t4,t8,s0,s1,s2,s4,s8'.split(','))
     def test_all(self, name):
-        self.check_function(getattr(self.module.f90_return_integer, name))
+        self.check_function(getattr(self.module.f90_return_integer, name), name)
index 96f215a914fda85ab900c91b75f307c4f5208117..9db939c7e066d9956d0450ccb8b729cd307a34a4 100644 (file)
@@ -1,9 +1,6 @@
-from __future__ import division, absolute_import, print_function
-
 import pytest
 
 from numpy import array
-from numpy.compat import long
 from numpy.testing import assert_, assert_raises
 from . import util
 
@@ -20,7 +17,6 @@ class TestReturnLogical(util.F2PyTest):
         assert_(t(1j) == 1)
         assert_(t(234) == 1)
         assert_(t(234.6) == 1)
-        assert_(t(long(234)) == 1)
         assert_(t(234.6 + 3j) == 1)
         assert_(t('234') == 1)
         assert_(t('aaa') == 1)
index 315cfe49b9b507c621a771d4222c5bce1843c595..8e5022a8ec97fa8b2d83c155af8834cf27e7f5ae 100644 (file)
@@ -1,24 +1,20 @@
-from __future__ import division, absolute_import, print_function
-
 import platform
 import pytest
 
 from numpy import array
-from numpy.compat import long
 from numpy.testing import assert_, assert_raises
 from . import util
 
 
 class TestReturnReal(util.F2PyTest):
 
-    def check_function(self, t):
-        if t.__doc__.split()[0] in ['t0', 't4', 's0', 's4']:
+    def check_function(self, t, tname):
+        if tname in ['t0', 't4', 's0', 's4']:
             err = 1e-5
         else:
             err = 0.0
         assert_(abs(t(234) - 234.0) <= err)
         assert_(abs(t(234.6) - 234.6) <= err)
-        assert_(abs(t(long(234)) - 234.0) <= err)
         assert_(abs(t('234') - 234) <= err)
         assert_(abs(t('234.6') - 234.6) <= err)
         assert_(abs(t(-234) + 234) <= err)
@@ -34,7 +30,7 @@ class TestReturnReal(util.F2PyTest):
         assert_(abs(t(array([234], 'B')) - 234.) <= err)
         assert_(abs(t(array([234], 'f')) - 234.) <= err)
         assert_(abs(t(array([234], 'd')) - 234.) <= err)
-        if t.__doc__.split()[0] in ['t0', 't4', 's0', 's4']:
+        if tname in ['t0', 't4', 's0', 's4']:
             assert_(t(1e200) == t(1e300))  # inf
 
         #assert_raises(ValueError, t, array([234], 'S1'))
@@ -90,10 +86,9 @@ end interface
 end python module c_ext_return_real
     """
 
-    @pytest.mark.slow
     @pytest.mark.parametrize('name', 't4,t8,s4,s8'.split(','))
     def test_all(self, name):
-        self.check_function(getattr(self.module, name))
+        self.check_function(getattr(self.module, name), name)
 
 
 class TestF77ReturnReal(TestReturnReal):
@@ -145,10 +140,9 @@ cf2py    intent(out) td
        end
     """
 
-    @pytest.mark.slow
     @pytest.mark.parametrize('name', 't0,t4,t8,td,s0,s4,s8,sd'.split(','))
     def test_all(self, name):
-        self.check_function(getattr(self.module, name))
+        self.check_function(getattr(self.module, name), name)
 
 
 class TestF90ReturnReal(TestReturnReal):
@@ -204,7 +198,6 @@ module f90_return_real
 end module f90_return_real
     """
 
-    @pytest.mark.slow
     @pytest.mark.parametrize('name', 't0,t4,t8,td,s0,s4,s8,sd'.split(','))
     def test_all(self, name):
-        self.check_function(getattr(self.module.f90_return_real, name))
+        self.check_function(getattr(self.module.f90_return_real, name), name)
index bcd18c893fc2f36f78363f7e1a61153772f60a33..d8b4bf22212273b6d1505b3d8c0a0ce98cf23d2e 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import platform
 import pytest
 
index e2af6180489b31a8b765c7ed457f4cd6ee23186a..b609fa77f711ef453493535758d037e01cfdf79e 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import pytest
 
index 0493c99cf1dd112b1d7a38e904d352cdad1a3e06..e3ec96af9ff41743d222ddd15e3d082d997bdd6c 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import pytest
 
index bf005df882ae669016246424a296c21f024c7d58..c5b06697d3302fd8380636cd491947b09af1e2fe 100644 (file)
@@ -5,8 +5,6 @@ Utility functions for
 - detecting if compilers are present
 
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 import subprocess
@@ -21,10 +19,7 @@ from numpy.compat import asbytes, asstr
 from numpy.testing import temppath
 from importlib import import_module
 
-try:
-    from hashlib import md5
-except ImportError:
-    from md5 import new as md5  # noqa: F401
+from hashlib import md5
 
 #
 # Maintaining a temporary module directory
@@ -284,9 +279,8 @@ def build_module_distutils(source_files, config_code, module_name, **kw):
 
     script = os.path.join(d, get_temp_module_name() + '.py')
     dst_sources.append(script)
-    f = open(script, 'wb')
-    f.write(asbytes(code))
-    f.close()
+    with open(script, 'wb') as f:
+        f.write(asbytes(code))
 
     # Build
     cwd = os.getcwd()
@@ -315,7 +309,7 @@ def build_module_distutils(source_files, config_code, module_name, **kw):
 #
 
 
-class F2PyTest(object):
+class F2PyTest:
     code = None
     sources = None
     options = []
index 6f44f16345bd3551516509beda25cc51c386a614..f1b71e83c252a31a9921d1eb984c539dd3a16971 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 
 Build 'use others module data' mechanism for f2py2e.
@@ -15,8 +15,6 @@ $Date: 2000/09/10 12:35:43 $
 Pearu Peterson
 
 """
-from __future__ import division, absolute_import, print_function
-
 __version__ = "$Revision: 1.3 $"[10:-1]
 
 f2py_version = 'See `f2py -v`'
index 37b3f0da6543c50df19c2c8a7636beddd60782bc..36cfe81b38eba9b2a6307dbb5a59dc7e3e8fec45 100644 (file)
@@ -191,8 +191,6 @@ For examples, see the various functions.
 
 """
 
-from __future__ import division, absolute_import, print_function
-
 from ._pocketfft import *
 from .helper import *
 
index d75b9983c64bca3f4dd9ff6e00faa264a7cb8806..764116a840abb815ab993c6fdbaf1417e7fbf961 100644 (file)
  *  \author Martin Reinecke
  */
 
+#define NPY_NO_DEPRECATED_API NPY_API_VERSION
+
+#include "Python.h"
+#include "numpy/arrayobject.h"
+
 #include <math.h>
 #include <string.h>
 #include <stdlib.h>
@@ -2184,11 +2189,6 @@ WARN_UNUSED_RESULT static int rfft_forward(rfft_plan plan, double c[], double fc
     return rfftblue_forward(plan->blueplan,c,fct);
   }
 
-#define NPY_NO_DEPRECATED_API NPY_API_VERSION
-
-#include "Python.h"
-#include "numpy/arrayobject.h"
-
 static PyObject *
 execute_complex(PyObject *a1, int is_forward, double fct)
 {
@@ -2359,7 +2359,6 @@ static struct PyMethodDef methods[] = {
     {NULL, NULL, 0, NULL}          /* sentinel */
 };
 
-#if PY_MAJOR_VERSION >= 3
 static struct PyModuleDef moduledef = {
         PyModuleDef_HEAD_INIT,
         "_pocketfft_internal",
@@ -2371,30 +2370,14 @@ static struct PyModuleDef moduledef = {
         NULL,
         NULL
 };
-#endif
 
 /* Initialization function for the module */
-#if PY_MAJOR_VERSION >= 3
-#define RETVAL(x) x
 PyMODINIT_FUNC PyInit__pocketfft_internal(void)
-#else
-#define RETVAL(x)
-PyMODINIT_FUNC
-init_pocketfft_internal(void)
-#endif
 {
     PyObject *m;
-#if PY_MAJOR_VERSION >= 3
     m = PyModule_Create(&moduledef);
-#else
-    static const char module_documentation[] = "";
-
-    m = Py_InitModule4("_pocketfft_internal", methods,
-            module_documentation,
-            (PyObject*)NULL,PYTHON_API_VERSION);
-#endif
     if (m == NULL) {
-        return RETVAL(NULL);
+        return NULL;
     }
 
     /* Import the array object */
@@ -2402,5 +2385,5 @@ init_pocketfft_internal(void)
 
     /* XXXX Add constants here */
 
-    return RETVAL(m);
+    return m;
 }
index 50720cda4d233d99263916b30535940400f1fc35..e9f554fe783bac7db0ed377497af22359c3874c7 100644 (file)
@@ -27,8 +27,6 @@ n = n-dimensional transform
 behavior.)
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['fft', 'ifft', 'rfft', 'irfft', 'hfft', 'ihfft', 'rfftn',
            'irfftn', 'rfft2', 'irfft2', 'fft2', 'ifft2', 'fftn', 'ifftn']
 
@@ -61,12 +59,11 @@ def _raw_fft(a, n, axis, is_real, is_forward, inv_norm):
 
     if a.shape[axis] != n:
         s = list(a.shape)
+        index = [slice(None)]*len(s)
         if s[axis] > n:
-            index = [slice(None)]*len(s)
             index[axis] = slice(0, n)
             a = a[tuple(index)]
         else:
-            index = [slice(None)]*len(s)
             index[axis] = slice(0, s[axis])
             s[axis] = n
             z = zeros(s, a.dtype.char)
@@ -527,8 +524,8 @@ def hfft(a, n=None, axis=-1, norm=None):
     domain and is real in the frequency domain. So here it's `hfft` for
     which you must supply the length of the result if it is to be odd.
 
-    * even: ``ihfft(hfft(a, 2*len(a) - 2) == a``, within roundoff error,
-    * odd: ``ihfft(hfft(a, 2*len(a) - 1) == a``, within roundoff error.
+    * even: ``ihfft(hfft(a, 2*len(a) - 2)) == a``, within roundoff error,
+    * odd: ``ihfft(hfft(a, 2*len(a) - 1)) == a``, within roundoff error.
 
     The correct interpretation of the hermitian input depends on the length of
     the original data, as given by `n`. This is because each input shape could
@@ -607,8 +604,8 @@ def ihfft(a, n=None, axis=-1, norm=None):
     domain and is real in the frequency domain. So here it's `hfft` for
     which you must supply the length of the result if it is to be odd:
 
-    * even: ``ihfft(hfft(a, 2*len(a) - 2) == a``, within roundoff error,
-    * odd: ``ihfft(hfft(a, 2*len(a) - 1) == a``, within roundoff error.
+    * even: ``ihfft(hfft(a, 2*len(a) - 2)) == a``, within roundoff error,
+    * odd: ``ihfft(hfft(a, 2*len(a) - 1)) == a``, within roundoff error.
 
     Examples
     --------
index a920a4ac08d8944022695ae4a902c4f4ba3cde1a..3dacd9ee1a92354b024be8ab548b1732d4ec8977 100644 (file)
@@ -2,8 +2,6 @@
 Discrete Fourier Transforms - helper.py
 
 """
-from __future__ import division, absolute_import, print_function
-
 from numpy.compat import integer_types
 from numpy.core import integer, empty, arange, asarray, roll
 from numpy.core.overrides import array_function_dispatch, set_module
index 8c3a315577b5e2c9fa4dec1bbc7d451b750fcdbf..9ed824e4f8abb406c9279becd88d0ad93ff9f847 100644 (file)
@@ -1,15 +1,17 @@
-from __future__ import division, print_function
-
+import sys
 
 def configuration(parent_package='',top_path=None):
     from numpy.distutils.misc_util import Configuration
     config = Configuration('fft', parent_package, top_path)
 
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
 
+    # AIX needs to be told to use large file support - at all times
+    defs = [('_LARGE_FILES', None)] if sys.platform[:3] == "aix" else []
     # Configure pocketfft_internal
     config.add_extension('_pocketfft_internal',
-                         sources=['_pocketfft.c']
+                         sources=['_pocketfft.c'],
+                         define_macros=defs,
                          )
 
     return config
index 6613c8002306553e3eebec959df7ae7036108bdd..68f5990aff9e8cb19086b775a180eff71a6629a7 100644 (file)
@@ -3,13 +3,12 @@
 Copied from fftpack.helper by Pearu Peterson, October 2005
 
 """
-from __future__ import division, absolute_import, print_function
 import numpy as np
-from numpy.testing import assert_array_almost_equal, assert_equal
+from numpy.testing import assert_array_almost_equal
 from numpy import fft, pi
 
 
-class TestFFTShift(object):
+class TestFFTShift:
 
     def test_definition(self):
         x = [0, 1, 2, 3, 4, -4, -3, -2, -1]
@@ -135,7 +134,7 @@ class TestFFTShift(object):
                                               original_ifftshift(inp, axes_keyword))
 
 
-class TestFFTFreq(object):
+class TestFFTFreq:
 
     def test_definition(self):
         x = [0, 1, 2, 3, 4, -4, -3, -2, -1]
@@ -146,7 +145,7 @@ class TestFFTFreq(object):
         assert_array_almost_equal(10*pi*fft.fftfreq(10, pi), x)
 
 
-class TestRFFTFreq(object):
+class TestRFFTFreq:
 
     def test_definition(self):
         x = [0, 1, 2, 3, 4]
@@ -157,7 +156,7 @@ class TestRFFTFreq(object):
         assert_array_almost_equal(10*pi*fft.rfftfreq(10, pi), x)
 
 
-class TestIRFFTN(object):
+class TestIRFFTN:
 
     def test_not_last_axis_success(self):
         ar, ai = np.random.random((2, 16, 8, 32))
index 453e964fa753dc12ae1c9e41430489785f8244cc..7c3db04856fe076366dac2ca4f294341ab23dd57 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 import pytest
 from numpy.random import random
@@ -7,11 +5,7 @@ from numpy.testing import (
         assert_array_equal, assert_raises, assert_allclose
         )
 import threading
-import sys
-if sys.version_info[0] >= 3:
-    import queue
-else:
-    import Queue as queue
+import queue
 
 
 def fft1(x):
@@ -21,13 +15,13 @@ def fft1(x):
     return np.sum(x*np.exp(phase), axis=1)
 
 
-class TestFFTShift(object):
+class TestFFTShift:
 
     def test_fft_n(self):
         assert_raises(ValueError, np.fft.fft, [1, 2, 3], 0)
 
 
-class TestFFT1D(object):
+class TestFFT1D:
 
     def test_identity(self):
         maxlen = 512
@@ -222,7 +216,7 @@ def test_fft_with_order(dtype, order, fft):
         raise ValueError()
 
 
-class TestFFTThreadSafe(object):
+class TestFFTThreadSafe:
     threads = 16
     input_shape = (800, 200)
 
index 2db12d9a4d0b0c0839817a2da15539ac1ac75c51..cb0de0d155db69654719b0a8f8aa3fbdff13ac5a 100644 (file)
@@ -11,8 +11,6 @@ Most contains basic functions that are used by several submodules and are
 useful to have in the main name-space.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import math
 
 from numpy.version import version as __version__
index 0d71375c28c3fdb48086acddddfebc486e6a813d..f5d0cc21727cb6115fc8a4980699bd9c0b1341e2 100644 (file)
@@ -34,11 +34,7 @@ Example::
     >>> fp.close() # doctest: +SKIP
 
 """
-from __future__ import division, absolute_import, print_function
-
 import os
-import sys
-import warnings
 import shutil
 import io
 from contextlib import closing
@@ -72,76 +68,12 @@ def _check_mode(mode, encoding, newline):
             raise ValueError("Argument 'newline' not supported in binary mode")
 
 
-def _python2_bz2open(fn, mode, encoding, newline):
-    """Wrapper to open bz2 in text mode.
-
-    Parameters
-    ----------
-    fn : str
-        File name
-    mode : {'r', 'w'}
-        File mode. Note that bz2 Text files are not supported.
-    encoding : str
-        Ignored, text bz2 files not supported in Python2.
-    newline : str
-        Ignored, text bz2 files not supported in Python2.
-    """
-    import bz2
-
-    _check_mode(mode, encoding, newline)
-
-    if "t" in mode:
-        # BZ2File is missing necessary functions for TextIOWrapper
-        warnings.warn("Assuming latin1 encoding for bz2 text file in Python2",
-                      RuntimeWarning, stacklevel=5)
-        mode = mode.replace("t", "")
-    return bz2.BZ2File(fn, mode)
-
-def _python2_gzipopen(fn, mode, encoding, newline):
-    """ Wrapper to open gzip in text mode.
-
-    Parameters
-    ----------
-    fn : str, bytes, file
-        File path or opened file.
-    mode : str
-        File mode. The actual files are opened as binary, but will decoded
-        using the specified `encoding` and `newline`.
-    encoding : str
-        Encoding to be used when reading/writing as text.
-    newline : str
-        Newline to be used when reading/writing as text.
-
-    """
-    import gzip
-    # gzip is lacking read1 needed for TextIOWrapper
-    class GzipWrap(gzip.GzipFile):
-        def read1(self, n):
-            return self.read(n)
-
-    _check_mode(mode, encoding, newline)
-
-    gz_mode = mode.replace("t", "")
-
-    if isinstance(fn, (str, bytes)):
-        binary_file = GzipWrap(fn, gz_mode)
-    elif hasattr(fn, "read") or hasattr(fn, "write"):
-        binary_file = GzipWrap(None, gz_mode, fileobj=fn)
-    else:
-        raise TypeError("filename must be a str or bytes object, or a file")
-
-    if "t" in mode:
-        return io.TextIOWrapper(binary_file, encoding, newline=newline)
-    else:
-        return binary_file
-
-
 # Using a class instead of a module-level dictionary
 # to reduce the initial 'import numpy' overhead by
 # deferring the import of lzma, bz2 and gzip until needed
 
 # TODO: .zip support, .tar support?
-class _FileOpeners(object):
+class _FileOpeners:
     """
     Container for different methods to open (un-)compressed files.
 
@@ -176,19 +108,13 @@ class _FileOpeners(object):
 
         try:
             import bz2
-            if sys.version_info[0] >= 3:
-                self._file_openers[".bz2"] = bz2.open
-            else:
-                self._file_openers[".bz2"] = _python2_bz2open
+            self._file_openers[".bz2"] = bz2.open
         except ImportError:
             pass
 
         try:
             import gzip
-            if sys.version_info[0] >= 3:
-                self._file_openers[".gz"] = gzip.open
-            else:
-                self._file_openers[".gz"] = _python2_gzipopen
+            self._file_openers[".gz"] = gzip.open
         except ImportError:
             pass
 
@@ -270,7 +196,7 @@ def open(path, mode='r', destpath=os.curdir, encoding=None, newline=None):
 
 
 @set_module('numpy')
-class DataSource(object):
+class DataSource:
     """
     DataSource(destpath='.')
 
@@ -377,10 +303,7 @@ class DataSource(object):
         """Test if path is a net location.  Tests the scheme and netloc."""
 
         # We do this here to reduce the 'import numpy' initial import time.
-        if sys.version_info[0] >= 3:
-            from urllib.parse import urlparse
-        else:
-            from urlparse import urlparse
+        from urllib.parse import urlparse
 
         # BUG : URLs require a scheme string ('http://') to be used.
         #       www.google.com will fail.
@@ -397,14 +320,10 @@ class DataSource(object):
         Creates a copy of the file in the datasource cache.
 
         """
-        # We import these here because importing urllib2 is slow and
+        # We import these here because importing urllib is slow and
         # a significant fraction of numpy's total import time.
-        if sys.version_info[0] >= 3:
-            from urllib.request import urlopen
-            from urllib.error import URLError
-        else:
-            from urllib2 import urlopen
-            from urllib2 import URLError
+        from urllib.request import urlopen
+        from urllib.error import URLError
 
         upath = self.abspath(path)
 
@@ -479,10 +398,7 @@ class DataSource(object):
 
         """
         # We do this here to reduce the 'import numpy' initial import time.
-        if sys.version_info[0] >= 3:
-            from urllib.parse import urlparse
-        else:
-            from urlparse import urlparse
+        from urllib.parse import urlparse
 
         # TODO:  This should be more robust.  Handles case where path includes
         #        the destpath, but not other sub-paths. Failing case:
@@ -549,14 +465,10 @@ class DataSource(object):
         if os.path.exists(path):
             return True
 
-        # We import this here because importing urllib2 is slow and
+        # We import this here because importing urllib is slow and
         # a significant fraction of numpy's total import time.
-        if sys.version_info[0] >= 3:
-            from urllib.request import urlopen
-            from urllib.error import URLError
-        else:
-            from urllib2 import urlopen
-            from urllib2 import URLError
+        from urllib.request import urlopen
+        from urllib.error import URLError
 
         # Test cached url
         upath = self.abspath(path)
index c392929fd8793720d8255cee144915ae0ea27d95..84aff5e5d75bc0e4744e7a95248b20db32811954 100644 (file)
@@ -1,20 +1,11 @@
 """A collection of functions designed to help I/O with ascii files.
 
 """
-from __future__ import division, absolute_import, print_function
-
 __docformat__ = "restructuredtext en"
 
-import sys
 import numpy as np
 import numpy.core.numeric as nx
-from numpy.compat import asbytes, asunicode, bytes, basestring
-
-if sys.version_info[0] >= 3:
-    from builtins import bool, int, float, complex, object, str
-    unicode = str
-else:
-    from __builtin__ import bool, int, float, complex, object, unicode, str
+from numpy.compat import asbytes, asunicode, bytes
 
 
 def _decode_line(line, encoding=None):
@@ -65,40 +56,6 @@ def _is_bytes_like(obj):
     return True
 
 
-def _to_filehandle(fname, flag='r', return_opened=False):
-    """
-    Returns the filehandle corresponding to a string or a file.
-    If the string ends in '.gz', the file is automatically unzipped.
-
-    Parameters
-    ----------
-    fname : string, filehandle
-        Name of the file whose filehandle must be returned.
-    flag : string, optional
-        Flag indicating the status of the file ('r' for read, 'w' for write).
-    return_opened : boolean, optional
-        Whether to return the opening status of the file.
-    """
-    if _is_string_like(fname):
-        if fname.endswith('.gz'):
-            import gzip
-            fhd = gzip.open(fname, flag)
-        elif fname.endswith('.bz2'):
-            import bz2
-            fhd = bz2.BZ2File(fname)
-        else:
-            fhd = file(fname, flag)
-        opened = True
-    elif hasattr(fname, 'seek'):
-        fhd = fname
-        opened = False
-    else:
-        raise ValueError('fname must be a string or file handle')
-    if return_opened:
-        return fhd, opened
-    return fhd
-
-
 def has_nested_fields(ndtype):
     """
     Returns whether one or several fields of a dtype are nested.
@@ -173,7 +130,7 @@ def flatten_dtype(ndtype, flatten_base=False):
         return types
 
 
-class LineSplitter(object):
+class LineSplitter:
     """
     Object to split a string at a given delimiter or at given places.
 
@@ -208,16 +165,16 @@ class LineSplitter(object):
 
         """
         return lambda input: [_.strip() for _ in method(input)]
-    #
 
-    def __init__(self, delimiter=None, comments='#', autostrip=True, encoding=None):
+    def __init__(self, delimiter=None, comments='#', autostrip=True,
+                 encoding=None):
         delimiter = _decode_line(delimiter)
         comments = _decode_line(comments)
 
         self.comments = comments
 
         # Delimiter is a character
-        if (delimiter is None) or isinstance(delimiter, basestring):
+        if (delimiter is None) or isinstance(delimiter, str):
             delimiter = delimiter or None
             _handyman = self._delimited_splitter
         # Delimiter is a list of field widths
@@ -237,7 +194,6 @@ class LineSplitter(object):
         else:
             self._handyman = _handyman
         self.encoding = encoding
-    #
 
     def _delimited_splitter(self, line):
         """Chop off comments, strip, and split at delimiter. """
@@ -247,7 +203,6 @@ class LineSplitter(object):
         if not line:
             return []
         return line.split(self.delimiter)
-    #
 
     def _fixedwidth_splitter(self, line):
         if self.comments is not None:
@@ -258,7 +213,6 @@ class LineSplitter(object):
         fixed = self.delimiter
         slices = [slice(i, i + fixed) for i in range(0, len(line), fixed)]
         return [line[s] for s in slices]
-    #
 
     def _variablewidth_splitter(self, line):
         if self.comments is not None:
@@ -267,13 +221,12 @@ class LineSplitter(object):
             return []
         slices = self.delimiter
         return [line[s] for s in slices]
-    #
 
     def __call__(self, line):
         return self._handyman(_decode_line(line, self.encoding))
 
 
-class NameValidator(object):
+class NameValidator:
     """
     Object to validate a list of strings to use as field names.
 
@@ -324,10 +277,9 @@ class NameValidator(object):
     ('EXCL', 'FIELD2', 'NO_Q', 'WITH_SPACE', 'CASE')
 
     """
-    #
+
     defaultexcludelist = ['return', 'file', 'print']
     defaultdeletechars = set(r"""~!@#$%^&*()-=+~\|]}[{';: /?.>,<""")
-    #
 
     def __init__(self, excludelist=None, deletechars=None,
                  case_sensitive=None, replace_space='_'):
@@ -353,7 +305,7 @@ class NameValidator(object):
         else:
             msg = 'unrecognized case_sensitive value %s.' % case_sensitive
             raise ValueError(msg)
-        #
+
         self.replace_space = replace_space
 
     def validate(self, names, defaultfmt="f%i", nbfields=None):
@@ -387,7 +339,7 @@ class NameValidator(object):
             if (nbfields is None):
                 return None
             names = []
-        if isinstance(names, basestring):
+        if isinstance(names, str):
             names = [names, ]
         if nbfields is not None:
             nbnames = len(names)
@@ -404,7 +356,7 @@ class NameValidator(object):
         validatednames = []
         seen = dict()
         nbempty = 0
-        #
+
         for item in names:
             item = case_converter(item).strip()
             if replace_space:
@@ -425,7 +377,6 @@ class NameValidator(object):
                 validatednames.append(item)
             seen[item] = cnt + 1
         return tuple(validatednames)
-    #
 
     def __call__(self, names, defaultfmt="f%i", nbfields=None):
         return self.validate(names, defaultfmt=defaultfmt, nbfields=nbfields)
@@ -496,7 +447,7 @@ class ConversionWarning(UserWarning):
     pass
 
 
-class StringConverter(object):
+class StringConverter:
     """
     Factory class for function transforming a string into another object
     (int, float).
@@ -544,70 +495,70 @@ class StringConverter(object):
         upgrade or not. Default is False.
 
     """
-    #
     _mapper = [(nx.bool_, str2bool, False),
-               (nx.integer, int, -1)]
+               (nx.int_, int, -1),]
 
     # On 32-bit systems, we need to make sure that we explicitly include
-    # nx.int64 since ns.integer is nx.int32.
-    if nx.dtype(nx.integer).itemsize < nx.dtype(nx.int64).itemsize:
+    # nx.int64 since ns.int_ is nx.int32.
+    if nx.dtype(nx.int_).itemsize < nx.dtype(nx.int64).itemsize:
         _mapper.append((nx.int64, int, -1))
 
-    _mapper.extend([(nx.floating, float, nx.nan),
-                    (nx.complexfloating, complex, nx.nan + 0j),
+    _mapper.extend([(nx.float64, float, nx.nan),
+                    (nx.complex128, complex, nx.nan + 0j),
                     (nx.longdouble, nx.longdouble, nx.nan),
                     (nx.unicode_, asunicode, '???'),
-                    (nx.string_, asbytes, '???')])
-
-    (_defaulttype, _defaultfunc, _defaultfill) = zip(*_mapper)
+                    (nx.string_, asbytes, '???'),
+                    # If a non-default dtype is passed, fall back to generic
+                    # ones (should only be used for the converter)
+                    (nx.integer, int, -1),
+                    (nx.floating, float, nx.nan),
+                    (nx.complexfloating, complex, nx.nan + 0j),])
 
     @classmethod
     def _getdtype(cls, val):
         """Returns the dtype of the input variable."""
         return np.array(val).dtype
-    #
 
     @classmethod
     def _getsubdtype(cls, val):
         """Returns the type of the dtype of the input variable."""
         return np.array(val).dtype.type
-    #
-    # This is a bit annoying. We want to return the "general" type in most
-    # cases (ie. "string" rather than "S10"), but we want to return the
-    # specific type for datetime64 (ie. "datetime64[us]" rather than
-    # "datetime64").
 
     @classmethod
     def _dtypeortype(cls, dtype):
         """Returns dtype for datetime64 and type of dtype otherwise."""
+
+        # This is a bit annoying. We want to return the "general" type in most
+        # cases (ie. "string" rather than "S10"), but we want to return the
+        # specific type for datetime64 (ie. "datetime64[us]" rather than
+        # "datetime64").
         if dtype.type == np.datetime64:
             return dtype
         return dtype.type
-    #
 
     @classmethod
     def upgrade_mapper(cls, func, default=None):
         """
-    Upgrade the mapper of a StringConverter by adding a new function and
-    its corresponding default.
+        Upgrade the mapper of a StringConverter by adding a new function and
+        its corresponding default.
 
-    The input function (or sequence of functions) and its associated
-    default value (if any) is inserted in penultimate position of the
-    mapper.  The corresponding type is estimated from the dtype of the
-    default value.
+        The input function (or sequence of functions) and its associated
+        default value (if any) is inserted in penultimate position of the
+        mapper.  The corresponding type is estimated from the dtype of the
+        default value.
 
-    Parameters
-    ----------
-    func : var
-        Function, or sequence of functions
-
-    Examples
-    --------
-    >>> import dateutil.parser
-    >>> import datetime
-    >>> dateparser = dateutil.parser.parse
-    >>> defaultdate = datetime.date(2000, 1, 1)
-    >>> StringConverter.upgrade_mapper(dateparser, default=defaultdate)
+        Parameters
+        ----------
+        func : var
+            Function, or sequence of functions
+
+        Examples
+        --------
+        >>> import dateutil.parser
+        >>> import datetime
+        >>> dateparser = dateutil.parser.parse
+        >>> defaultdate = datetime.date(2000, 1, 1)
+        >>> StringConverter.upgrade_mapper(dateparser, default=defaultdate)
         """
         # Func is a single functions
         if hasattr(func, '__call__'):
@@ -623,9 +574,22 @@ class StringConverter(object):
             else:
                 default = list(default)
                 default.append([None] * (len(func) - len(default)))
-            for (fct, dft) in zip(func, default):
+            for fct, dft in zip(func, default):
                 cls._mapper.insert(-1, (cls._getsubdtype(dft), fct, dft))
-    #
+
+    @classmethod
+    def _find_map_entry(cls, dtype):
+        # if a converter for the specific dtype is available use that
+        for i, (deftype, func, default_def) in enumerate(cls._mapper):
+            if dtype.type == deftype:
+                return i, (deftype, func, default_def)
+
+        # otherwise find an inexact match
+        for i, (deftype, func, default_def) in enumerate(cls._mapper):
+            if np.issubdtype(dtype.type, deftype):
+                return i, (deftype, func, default_def)
+
+        raise LookupError
 
     def __init__(self, dtype_or_func=None, default=None, missing_values=None,
                  locked=False):
@@ -658,36 +622,26 @@ class StringConverter(object):
                     except ValueError:
                         default = None
                 dtype = self._getdtype(default)
-            # Set the status according to the dtype
-            _status = -1
-            for (i, (deftype, func, default_def)) in enumerate(self._mapper):
-                if np.issubdtype(dtype.type, deftype):
-                    _status = i
-                    if default is None:
-                        self.default = default_def
-                    else:
-                        self.default = default
-                    break
-            # if a converter for the specific dtype is available use that
-            last_func = func
-            for (i, (deftype, func, default_def)) in enumerate(self._mapper):
-                if dtype.type == deftype:
-                    _status = i
-                    last_func = func
-                    if default is None:
-                        self.default = default_def
-                    else:
-                        self.default = default
-                    break
-            func = last_func
-            if _status == -1:
-                # We never found a match in the _mapper...
-                _status = 0
+
+            # find the best match in our mapper
+            try:
+                self._status, (_, func, default_def) = self._find_map_entry(dtype)
+            except LookupError:
+                # no match
                 self.default = default
-            self._status = _status
+                _, func, _ = self._mapper[-1]
+                self._status = 0
+            else:
+                # use the found default only if we did not already have one
+                if default is None:
+                    self.default = default_def
+                else:
+                    self.default = default
+
             # If the input was a dtype, set the function to the last we saw
             if self.func is None:
                 self.func = func
+
             # If the status is 1 (int), change the function to
             # something more robust.
             if self.func == self._mapper[1][1]:
@@ -701,22 +655,20 @@ class StringConverter(object):
         if missing_values is None:
             self.missing_values = {''}
         else:
-            if isinstance(missing_values, basestring):
+            if isinstance(missing_values, str):
                 missing_values = missing_values.split(",")
             self.missing_values = set(list(missing_values) + [''])
-        #
+
         self._callingfunction = self._strict_call
         self.type = self._dtypeortype(dtype)
         self._checked = False
         self._initial_default = default
-    #
 
     def _loose_call(self, value):
         try:
             return self.func(value)
         except ValueError:
             return self.default
-    #
 
     def _strict_call(self, value):
         try:
@@ -742,11 +694,29 @@ class StringConverter(object):
                     self._checked = False
                 return self.default
             raise ValueError("Cannot convert string '%s'" % value)
-    #
 
     def __call__(self, value):
         return self._callingfunction(value)
-    #
+
+    def _do_upgrade(self):
+        # Raise an exception if we locked the converter...
+        if self._locked:
+            errmsg = "Converter is locked and cannot be upgraded"
+            raise ConverterLockError(errmsg)
+        _statusmax = len(self._mapper)
+        # Complains if we try to upgrade by the maximum
+        _status = self._status
+        if _status == _statusmax:
+            errmsg = "Could not find a valid conversion function"
+            raise ConverterError(errmsg)
+        elif _status < _statusmax - 1:
+            _status += 1
+        self.type, self.func, default = self._mapper[_status]
+        self._status = _status
+        if self._initial_default is not None:
+            self.default = self._initial_default
+        else:
+            self.default = default
 
     def upgrade(self, value):
         """
@@ -773,24 +743,7 @@ class StringConverter(object):
         try:
             return self._strict_call(value)
         except ValueError:
-            # Raise an exception if we locked the converter...
-            if self._locked:
-                errmsg = "Converter is locked and cannot be upgraded"
-                raise ConverterLockError(errmsg)
-            _statusmax = len(self._mapper)
-            # Complains if we try to upgrade by the maximum
-            _status = self._status
-            if _status == _statusmax:
-                errmsg = "Could not find a valid conversion function"
-                raise ConverterError(errmsg)
-            elif _status < _statusmax - 1:
-                _status += 1
-            (self.type, self.func, default) = self._mapper[_status]
-            self._status = _status
-            if self._initial_default is not None:
-                self.default = self._initial_default
-            else:
-                self.default = default
+            self._do_upgrade()
             return self.upgrade(value)
 
     def iterupgrade(self, value):
@@ -802,25 +755,7 @@ class StringConverter(object):
             for _m in value:
                 _strict_call(_m)
         except ValueError:
-            # Raise an exception if we locked the converter...
-            if self._locked:
-                errmsg = "Converter is locked and cannot be upgraded"
-                raise ConverterLockError(errmsg)
-            _statusmax = len(self._mapper)
-            # Complains if we try to upgrade by the maximum
-            _status = self._status
-            if _status == _statusmax:
-                raise ConverterError(
-                    "Could not find a valid conversion function"
-                    )
-            elif _status < _statusmax - 1:
-                _status += 1
-            (self.type, self.func, default) = self._mapper[_status]
-            if self._initial_default is not None:
-                self.default = self._initial_default
-            else:
-                self.default = default
-            self._status = _status
+            self._do_upgrade()
             self.iterupgrade(value)
 
     def update(self, func, default=None, testing_value=None,
@@ -876,7 +811,7 @@ class StringConverter(object):
         else:
             if not np.iterable(missing_values):
                 missing_values = [missing_values]
-            if not all(isinstance(v, basestring) for v in missing_values):
+            if not all(isinstance(v, str) for v in missing_values):
                 raise TypeError("missing_values must be strings or unicode")
             self.missing_values.update(missing_values)
 
@@ -926,7 +861,7 @@ def easy_dtype(ndtype, names=None, defaultfmt="f%i", **validationargs):
         nbfields = len(ndtype)
         if names is None:
             names = [''] * len(ndtype)
-        elif isinstance(names, basestring):
+        elif isinstance(names, str):
             names = names.split(",")
         names = validate(names, nbfields=nbfields, defaultfmt=defaultfmt)
         ndtype = np.dtype(dict(formats=ndtype, names=names))
@@ -934,7 +869,7 @@ def easy_dtype(ndtype, names=None, defaultfmt="f%i", **validationargs):
         # Explicit names
         if names is not None:
             validate = NameValidator(**validationargs)
-            if isinstance(names, basestring):
+            if isinstance(names, str):
                 names = names.split(",")
             # Simple dtype: repeat to match the nb of names
             if ndtype.names is None:
@@ -949,9 +884,10 @@ def easy_dtype(ndtype, names=None, defaultfmt="f%i", **validationargs):
         elif ndtype.names is not None:
             validate = NameValidator(**validationargs)
             # Default initial names : should we change the format ?
-            if ((ndtype.names == tuple("f%i" % i for i in range(len(ndtype.names)))) and
-                    (defaultfmt != "f%i")):
-                ndtype.names = validate([''] * len(ndtype.names), defaultfmt=defaultfmt)
+            numbered_names = tuple("f%i" % i for i in range(len(ndtype.names)))
+            if ((ndtype.names == numbered_names) and (defaultfmt != "f%i")):
+                ndtype.names = validate([''] * len(ndtype.names),
+                                        defaultfmt=defaultfmt)
             # Explicit initial names : just validate
             else:
                 ndtype.names = validate(ndtype.names, defaultfmt=defaultfmt)
index 8aa999fc9251dda7345efb733feb675dde29a88b..d4098acb5aeaa51e456914ba9c479d93131746f7 100644 (file)
@@ -5,12 +5,8 @@ The LooseVersion and StrictVersion classes that distutils provides don't
 work; they don't recognize anything like alpha/beta/rc/dev versions.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import re
 
-from numpy.compat import basestring
-
 
 __all__ = ['NumpyVersion']
 
@@ -116,10 +112,10 @@ class NumpyVersion():
         return vercmp
 
     def _compare(self, other):
-        if not isinstance(other, (basestring, NumpyVersion)):
+        if not isinstance(other, (str, NumpyVersion)):
             raise ValueError("Invalid object to compare with NumpyVersion.")
 
-        if isinstance(other, basestring):
+        if isinstance(other, str):
             other = NumpyVersion(other)
 
         vercmp = self._compare_version(other)
index 33e64708d5453ea7831ab81bdd0f4655431581ed..7569e765164d9be3cf5c2408db09def39fa17143 100644 (file)
@@ -3,8 +3,6 @@ The arraypad module contains a group of functions to pad values onto the edges
 of an n-dimensional array.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.core.overrides import array_function_dispatch
 from numpy.lib.index_tricks import ndindex
@@ -234,7 +232,7 @@ def _get_linear_ramps(padded, axis, width_pair, end_value_pair):
 
 def _get_stats(padded, axis, width_pair, length_pair, stat_func):
     """
-    Calculate statistic for the empty-padded array in given dimnsion.
+    Calculate statistic for the empty-padded array in given dimension.
 
     Parameters
     ----------
@@ -273,7 +271,7 @@ def _get_stats(padded, axis, width_pair, length_pair, stat_func):
 
     if (left_length == 0 or right_length == 0) \
             and stat_func in {np.amax, np.amin}:
-        # amax and amin can't operate on an emtpy array,
+        # amax and amin can't operate on an empty array,
         # raise a more descriptive warning here instead of the default one
         raise ValueError("stat_length of 0 yields no value for padding")
 
index 2309f7e4217a20fa240f17616faa1bc8b75121e3..22687b9415f68e2073a9f200b6060c36f06563b0 100644 (file)
@@ -25,8 +25,6 @@ To do: Optionally return indices analogously to unique for all functions.
 :Author: Robert Cimrman
 
 """
-from __future__ import division, absolute_import, print_function
-
 import functools
 
 import numpy as np
@@ -94,8 +92,7 @@ def ediff1d(ary, to_end=None, to_begin=None):
     # force a 1d array
     ary = np.asanyarray(ary).ravel()
 
-    # enforce propagation of the dtype of input
-    # ary to returned result
+    # enforce that the dtype of `ary` is used for the output
     dtype_req = ary.dtype
 
     # fast track default case
@@ -105,22 +102,23 @@ def ediff1d(ary, to_end=None, to_begin=None):
     if to_begin is None:
         l_begin = 0
     else:
-        _to_begin = np.asanyarray(to_begin, dtype=dtype_req)
-        if not np.all(_to_begin == to_begin):
-            raise ValueError("cannot convert 'to_begin' to array with dtype "
-                            "'%r' as required for input ary" % dtype_req)
-        to_begin = _to_begin.ravel()
+        to_begin = np.asanyarray(to_begin)
+        if not np.can_cast(to_begin, dtype_req, casting="same_kind"):
+            raise TypeError("dtype of `to_end` must be compatible "
+                            "with input `ary` under the `same_kind` rule.")
+
+        to_begin = to_begin.ravel()
         l_begin = len(to_begin)
 
     if to_end is None:
         l_end = 0
     else:
-        _to_end = np.asanyarray(to_end, dtype=dtype_req)
-        # check that casting has not overflowed
-        if not np.all(_to_end == to_end):
-            raise ValueError("cannot convert 'to_end' to array with dtype "
-                             "'%r' as required for input ary" % dtype_req)
-        to_end = _to_end.ravel()
+        to_end = np.asanyarray(to_end)
+        if not np.can_cast(to_end, dtype_req, casting="same_kind"):
+            raise TypeError("dtype of `to_end` must be compatible "
+                            "with input `ary` under the `same_kind` rule.")
+
+        to_end = to_end.ravel()
         l_end = len(to_end)
 
     # do the calculation in place and copy to_begin and to_end
@@ -253,9 +251,9 @@ def unique(ar, return_index=False, return_inverse=False,
     >>> u
     array([1, 2, 3, 4, 6])
     >>> indices
-    array([0, 1, 4, ..., 1, 2, 1])
+    array([0, 1, 4, 3, 1, 2, 1])
     >>> u[indices]
-    array([1, 2, 6, ..., 2, 3, 2])
+    array([1, 2, 6, 4, 2, 3, 2])
 
     """
     ar = np.asanyarray(ar)
@@ -272,20 +270,33 @@ def unique(ar, return_index=False, return_inverse=False,
 
     # Must reshape to a contiguous 2D array for this to work...
     orig_shape, orig_dtype = ar.shape, ar.dtype
-    ar = ar.reshape(orig_shape[0], -1)
+    ar = ar.reshape(orig_shape[0], np.prod(orig_shape[1:], dtype=np.intp))
     ar = np.ascontiguousarray(ar)
     dtype = [('f{i}'.format(i=i), ar.dtype) for i in range(ar.shape[1])]
 
+    # At this point, `ar` has shape `(n, m)`, and `dtype` is a structured
+    # data type with `m` fields where each field has the data type of `ar`.
+    # In the following, we create the array `consolidated`, which has
+    # shape `(n,)` with data type `dtype`.
     try:
-        consolidated = ar.view(dtype)
+        if ar.shape[1] > 0:
+            consolidated = ar.view(dtype)
+        else:
+            # If ar.shape[1] == 0, then dtype will be `np.dtype([])`, which is
+            # a data type with itemsize 0, and the call `ar.view(dtype)` will
+            # fail.  Instead, we'll use `np.empty` to explicitly create the
+            # array with shape `(len(ar),)`.  Because `dtype` in this case has
+            # itemsize 0, the total size of the result is still 0 bytes.
+            consolidated = np.empty(len(ar), dtype=dtype)
     except TypeError:
         # There's no good way to do this for object arrays, etc...
         msg = 'The axis argument to unique is not supported for dtype {dt}'
         raise TypeError(msg.format(dt=ar.dtype))
 
     def reshape_uniq(uniq):
+        n = len(uniq)
         uniq = uniq.view(orig_dtype)
-        uniq = uniq.reshape(-1, *orig_shape[1:])
+        uniq = uniq.reshape(n, *orig_shape[1:])
         uniq = np.moveaxis(uniq, 0, axis)
         return uniq
 
@@ -785,4 +796,3 @@ def setdiff1d(ar1, ar2, assume_unique=False):
         ar1 = unique(ar1)
         ar2 = unique(ar2)
     return ar1[in1d(ar1, ar2, assume_unique=True, invert=True)]
-
index c166685825ed59386e3e523dd2652baf1400956d..b9ea21f8e49f60461416962fc6e2a2ca625c04cd 100644 (file)
@@ -7,17 +7,13 @@ an array object, and when iterated it will return sub-arrays with at most
 a user-specified number of elements.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from operator import mul
 from functools import reduce
 
-from numpy.compat import long
-
 __all__ = ['Arrayterator']
 
 
-class Arrayterator(object):
+class Arrayterator:
     """
     Buffered iterator for big arrays.
 
@@ -110,7 +106,7 @@ class Arrayterator(object):
             if slice_ is Ellipsis:
                 fixed.extend([slice(None)] * (dims-length+1))
                 length = len(fixed)
-            elif isinstance(slice_, (int, long)):
+            elif isinstance(slice_, int):
                 fixed.append(slice(slice_, slice_+1, 1))
             else:
                 fixed.append(slice_)
@@ -163,8 +159,7 @@ class Arrayterator(object):
 
         """
         for block in self:
-            for value in block.flat:
-                yield value
+            yield from block.flat
 
     @property
     def shape(self):
index a011e52a9eb0a1c41abb2acc04385c4a2d067516..709a79dc0280f66005f2a26d7eeddee38e9ed08a 100644 (file)
@@ -10,8 +10,6 @@ or arrays (or other sequences).
 Functions support the :class:`decimal.Decimal` type unless
 otherwise stated.
 """
-from __future__ import division, absolute_import, print_function
-
 import warnings
 from decimal import Decimal
 import functools
@@ -468,7 +466,7 @@ def _rbl(rate, per, pmt, pv, when):
     This function is here to simply have a different name for the 'fv'
     function to not interfere with the 'fv' keyword argument within the 'ipmt'
     function.  It is the 'remaining balance on loan' which might be useful as
-    it's own function, but is easily calculated with the 'fv' function.
+    its own function, but is easily calculated with the 'fv' function.
     """
     return fv(rate, (per - 1), pmt, pv, when)
 
index 20e2e9c729ab704af9d2fe8bdeb27e5002c5e181..2afa4ac1036b45d67a8824ce218b41b9e3ff655c 100644 (file)
@@ -161,15 +161,12 @@ alternatives, is described in the `"npy-format" NEP
 evolved with time and this document is more current.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy
-import sys
 import io
 import warnings
 from numpy.lib.utils import safe_eval
 from numpy.compat import (
-    isfileobj, long, os_fspath, pickle
+    isfileobj, os_fspath, pickle
     )
 
 
@@ -215,10 +212,7 @@ def magic(major, minor):
         raise ValueError("major version must be 0 <= major < 256")
     if minor < 0 or minor > 255:
         raise ValueError("minor version must be 0 <= minor < 256")
-    if sys.version_info[0] < 3:
-        return MAGIC_PREFIX + chr(major) + chr(minor)
-    else:
-        return MAGIC_PREFIX + bytes([major, minor])
+    return MAGIC_PREFIX + bytes([major, minor])
 
 def read_magic(fp):
     """ Read the magic string to get the version of the file format.
@@ -236,10 +230,7 @@ def read_magic(fp):
     if magic_str[:-2] != MAGIC_PREFIX:
         msg = "the magic string is not correct; expected %r, got %r"
         raise ValueError(msg % (MAGIC_PREFIX, magic_str[:-2]))
-    if sys.version_info[0] < 3:
-        major, minor = map(ord, magic_str[-2:])
-    else:
-        major, minor = magic_str[-2:]
+    major, minor = magic_str[-2:]
     return major, minor
 
 def _has_metadata(dt):
@@ -304,7 +295,11 @@ def descr_to_dtype(descr):
         # subtype, will always have a shape descr[1]
         dt = descr_to_dtype(descr[0])
         return numpy.dtype((dt, descr[1]))
-    fields = []
+
+    titles = []
+    names = []
+    formats = []
+    offsets = []
     offset = 0
     for field in descr:
         if len(field) == 2:
@@ -318,14 +313,13 @@ def descr_to_dtype(descr):
         # Once support for blank names is removed, only "if name == ''" needed)
         is_pad = (name == '' and dt.type is numpy.void and dt.names is None)
         if not is_pad:
-            fields.append((name, dt, offset))
-
+            title, name = name if isinstance(name, tuple) else (None, name)
+            titles.append(title)
+            names.append(name)
+            formats.append(dt)
+            offsets.append(offset)
         offset += dt.itemsize
 
-    names, formats, offsets = zip(*fields)
-    # names may be (title, names) tuples
-    nametups = (n  if isinstance(n, tuple) else (None, n) for n in names)
-    titles, names = zip(*nametups)
     return numpy.dtype({'names': names, 'formats': formats, 'titles': titles,
                         'offsets': offsets, 'itemsize': offset})
 
@@ -544,16 +538,11 @@ def _filter_header(s):
 
     """
     import tokenize
-    if sys.version_info[0] >= 3:
-        from io import StringIO
-    else:
-        from StringIO import StringIO
+    from io import StringIO
 
     tokens = []
     last_token_was_number = False
-    # adding newline as python 2.7.5 workaround
-    string = s + "\n"
-    for token in tokenize.generate_tokens(StringIO(string).readline):
+    for token in tokenize.generate_tokens(StringIO(s).readline):
         token_type = token[0]
         token_string = token[1]
         if (last_token_was_number and
@@ -563,8 +552,7 @@ def _filter_header(s):
         else:
             tokens.append(token)
         last_token_was_number = (token_type == tokenize.NUMBER)
-    # removing newline (see above) as python 2.7.5 workaround
-    return tokenize.untokenize(tokens)[:-1]
+    return tokenize.untokenize(tokens)
 
 
 def _read_array_header(fp, version):
@@ -606,7 +594,7 @@ def _read_array_header(fp, version):
 
     # Sanity-check the values.
     if (not isinstance(d['shape'], tuple) or
-            not numpy.all([isinstance(x, (int, long)) for x in d['shape']])):
+            not numpy.all([isinstance(x, int) for x in d['shape']])):
         msg = "shape is not valid: {!r}"
         raise ValueError(msg.format(d['shape']))
     if not isinstance(d['fortran_order'], bool):
@@ -614,7 +602,7 @@ def _read_array_header(fp, version):
         raise ValueError(msg.format(d['fortran_order']))
     try:
         dtype = descr_to_dtype(d['descr'])
-    except TypeError as e:
+    except TypeError:
         msg = "descr is not a valid dtype descriptor: {!r}"
         raise ValueError(msg.format(d['descr']))
 
@@ -743,12 +731,10 @@ def read_array(fp, allow_pickle=False, pickle_kwargs=None):
         try:
             array = pickle.load(fp, **pickle_kwargs)
         except UnicodeError as err:
-            if sys.version_info[0] >= 3:
-                # Friendlier error message
-                raise UnicodeError("Unpickling a python object failed: %r\n"
-                                   "You may need to pass the encoding= option "
-                                   "to numpy.load" % (err,))
-            raise
+            # Friendlier error message
+            raise UnicodeError("Unpickling a python object failed: %r\n"
+                               "You may need to pass the encoding= option "
+                               "to numpy.load" % (err,))
     else:
         if isfileobj(fp):
             # We can use the fast fromfile() function.
index df06d10cc8d9eefd34abb44a1663e8b963ff564f..dea01d12d90665a3c7409af91355254b19fcacad 100644 (file)
@@ -1,11 +1,4 @@
-from __future__ import division, absolute_import, print_function
-
-try:
-    # Accessing collections abstract classes from collections
-    # has been deprecated since Python 3.3
-    import collections.abc as collections_abc
-except ImportError:
-    import collections as collections_abc
+import collections.abc
 import functools
 import re
 import sys
@@ -13,10 +6,10 @@ import warnings
 
 import numpy as np
 import numpy.core.numeric as _nx
-from numpy.core import atleast_1d, transpose
+from numpy.core import transpose
 from numpy.core.numeric import (
     ones, zeros, arange, concatenate, array, asarray, asanyarray, empty,
-    empty_like, ndarray, around, floor, ceil, take, dot, where, intp,
+    ndarray, around, floor, ceil, take, dot, where, intp,
     integer, isscalar, absolute
     )
 from numpy.core.umath import (
@@ -36,23 +29,17 @@ from numpy.core.multiarray import (
     interp as compiled_interp, interp_complex as compiled_interp_complex
     )
 from numpy.core.umath import _add_newdoc_ufunc as add_newdoc_ufunc
-from numpy.compat import long
 
-if sys.version_info[0] < 3:
-    # Force range to be a generator, for np.delete's usage.
-    range = xrange
-    import __builtin__ as builtins
-else:
-    import builtins
+import builtins
+
+# needed in this module for compatibility
+from numpy.lib.histograms import histogram, histogramdd
 
 
 array_function_dispatch = functools.partial(
     overrides.array_function_dispatch, module='numpy')
 
 
-# needed in this module for compatibility
-from numpy.lib.histograms import histogram, histogramdd
-
 __all__ = [
     'select', 'piecewise', 'trim_zeros', 'copy', 'iterable', 'percentile',
     'diff', 'gradient', 'angle', 'unwrap', 'sort_complex', 'disp', 'flip',
@@ -70,7 +57,7 @@ def _rot90_dispatcher(m, k=None, axes=None):
 
 
 @array_function_dispatch(_rot90_dispatcher)
-def rot90(m, k=1, axes=(0,1)):
+def rot90(m, k=1, axes=(0, 1)):
     """
     Rotate an array by 90 degrees in the plane specified by axes.
 
@@ -150,7 +137,7 @@ def rot90(m, k=1, axes=(0,1)):
                                                 axes_list[axes[0]])
 
     if k == 1:
-        return transpose(flip(m,axes[1]), axes_list)
+        return transpose(flip(m, axes[1]), axes_list)
     else:
         # k == 3
         return flip(transpose(m, axes_list), axes[1])
@@ -504,8 +491,7 @@ def _piecewise_dispatcher(x, condlist, funclist, *args, **kw):
     yield x
     # support the undocumented behavior of allowing scalars
     if np.iterable(condlist):
-        for c in condlist:
-            yield c
+        yield from condlist
 
 
 @array_function_dispatch(_piecewise_dispatcher)
@@ -620,7 +606,7 @@ def piecewise(x, condlist, funclist, *args, **kw):
     y = zeros(x.shape, x.dtype)
     for k in range(n):
         item = funclist[k]
-        if not isinstance(item, collections_abc.Callable):
+        if not isinstance(item, collections.abc.Callable):
             y[condlist[k]] = item
         else:
             vals = x[condlist[k]]
@@ -631,10 +617,8 @@ def piecewise(x, condlist, funclist, *args, **kw):
 
 
 def _select_dispatcher(condlist, choicelist, default=None):
-    for c in condlist:
-        yield c
-    for c in choicelist:
-        yield c
+    yield from condlist
+    yield from choicelist
 
 
 @array_function_dispatch(_select_dispatcher)
@@ -723,12 +707,12 @@ def select(condlist, choicelist, default=0):
     return result
 
 
-def _copy_dispatcher(a, order=None):
+def _copy_dispatcher(a, order=None, subok=None):
     return (a,)
 
 
 @array_function_dispatch(_copy_dispatcher)
-def copy(a, order='K'):
+def copy(a, order='K', subok=False):
     """
     Return an array copy of the given object.
 
@@ -743,12 +727,21 @@ def copy(a, order='K'):
         as possible. (Note that this function and :meth:`ndarray.copy` are very
         similar, but have different default values for their order=
         arguments.)
+    subok : bool, optional
+        If True, then sub-classes will be passed-through, otherwise the
+        returned array will be forced to be a base-class array (defaults to False).
+
+        .. versionadded:: 1.19.0
 
     Returns
     -------
     arr : ndarray
         Array interpretation of `a`.
 
+    See Also
+    --------
+    ndarray.copy : Preferred method for creating an array copy
+
     Notes
     -----
     This is equivalent to:
@@ -771,20 +764,43 @@ def copy(a, order='K'):
     >>> x[0] == z[0]
     False
 
+    Note that np.copy is a shallow copy and will not copy object
+    elements within arrays. This is mainly important for arrays
+    containing Python objects. The new array will contain the
+    same object which may lead to surprises if that object can
+    be modified (is mutable):
+
+    >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object)
+    >>> b = np.copy(a)
+    >>> b[2][0] = 10
+    >>> a
+    array([1, 'm', list([10, 3, 4])], dtype=object)
+
+    To ensure all elements within an ``object`` array are copied,
+    use `copy.deepcopy`:
+
+    >>> import copy
+    >>> a = np.array([1, 'm', [2, 3, 4]], dtype=object)
+    >>> c = copy.deepcopy(a)
+    >>> c[2][0] = 10
+    >>> c
+    array([1, 'm', list([10, 3, 4])], dtype=object)
+    >>> a
+    array([1, 'm', list([2, 3, 4])], dtype=object)
+
     """
-    return array(a, order=order, copy=True)
+    return array(a, order=order, subok=subok, copy=True)
 
 # Basic operations
 
 
-def _gradient_dispatcher(f, *varargs, **kwargs):
+def _gradient_dispatcher(f, *varargs, axis=None, edge_order=None):
     yield f
-    for v in varargs:
-        yield v
+    yield from varargs
 
 
 @array_function_dispatch(_gradient_dispatcher)
-def gradient(f, *varargs, **kwargs):
+def gradient(f, *varargs, axis=None, edge_order=1):
     """
     Return the gradient of an N-dimensional array.
 
@@ -961,11 +977,10 @@ def gradient(f, *varargs, **kwargs):
     f = np.asanyarray(f)
     N = f.ndim  # number of dimensions
 
-    axes = kwargs.pop('axis', None)
-    if axes is None:
+    if axis is None:
         axes = tuple(range(N))
     else:
-        axes = _nx.normalize_axis_tuple(axes, N)
+        axes = _nx.normalize_axis_tuple(axis, N)
 
     len_axes = len(axes)
     n = len(varargs)
@@ -1000,10 +1015,6 @@ def gradient(f, *varargs, **kwargs):
     else:
         raise TypeError("invalid number of arguments")
 
-    edge_order = kwargs.pop('edge_order', 1)
-    if kwargs:
-        raise TypeError('"{}" are not valid keyword arguments.'.format(
-                                                  '", "'.join(kwargs.keys())))
     if edge_order > 2:
         raise ValueError("'edge_order' greater than 2 not supported")
 
@@ -1442,6 +1453,11 @@ def angle(z, deg=False):
     arctan2
     absolute
 
+    Notes
+    -----
+    Although the angle of the complex number 0 is undefined, ``numpy.angle(0)``
+    returns the value 0.
+
     Examples
     --------
     >>> np.angle([1.0, 1.0j, 1+1j])               # in radians
@@ -1621,6 +1637,7 @@ def trim_zeros(filt, trim='fb'):
                 last = last - 1
     return filt[first:last]
 
+
 def _extract_dispatcher(condition, arr):
     return (condition, arr)
 
@@ -1876,7 +1893,7 @@ def _create_arrays(broadcast_shape, dim_sizes, list_of_core_dims, dtypes):
 
 
 @set_module('numpy')
-class vectorize(object):
+class vectorize:
     """
     vectorize(pyfunc, otypes=None, doc=None, excluded=None, cache=False,
               signature=None)
@@ -2033,7 +2050,7 @@ class vectorize(object):
         self.pyfunc = pyfunc
         self.cache = cache
         self.signature = signature
-        self._ufunc = None    # Caching to improve default performance
+        self._ufunc = {}    # Caching to improve default performance
 
         if doc is None:
             self.__doc__ = pyfunc.__doc__
@@ -2098,14 +2115,22 @@ class vectorize(object):
 
         if self.otypes is not None:
             otypes = self.otypes
-            nout = len(otypes)
 
-            # Note logic here: We only *use* self._ufunc if func is self.pyfunc
-            # even though we set self._ufunc regardless.
-            if func is self.pyfunc and self._ufunc is not None:
-                ufunc = self._ufunc
+            # self._ufunc is a dictionary whose keys are the number of
+            # arguments (i.e. len(args)) and whose values are ufuncs created
+            # by frompyfunc. len(args) can be different for different calls if
+            # self.pyfunc has parameters with default values.  We only use the
+            # cache when func is self.pyfunc, which occurs when the call uses
+            # only positional arguments and no arguments are excluded.
+
+            nin = len(args)
+            nout = len(self.otypes)
+            if func is not self.pyfunc or nin not in self._ufunc:
+                ufunc = frompyfunc(func, nin, nout)
             else:
-                ufunc = self._ufunc = frompyfunc(func, len(args), nout)
+                ufunc = None  # We'll get it from self._ufunc
+            if func is self.pyfunc:
+                ufunc = self._ufunc.setdefault(nin, ufunc)
         else:
             # Get number of outputs and output types by calling the function on
             # the first entries of args.  We also cache the result to prevent
@@ -2956,6 +2981,7 @@ def hamming(M):
     n = arange(0, M)
     return 0.54 - 0.46*cos(2.0*pi*n/(M-1))
 
+
 ## Code from cephes for i0
 
 _i0A = [
@@ -3498,6 +3524,7 @@ def median(a, axis=None, out=None, overwrite_input=False, keepdims=False):
     else:
         return r
 
+
 def _median(a, axis=None, out=None, overwrite_input=False):
     # can't be reasonably be implemented in terms of percentile as we have to
     # call mean to not break astropy
@@ -3716,7 +3743,7 @@ def quantile(a, q, axis=None, out=None,
              overwrite_input=False, interpolation='linear', keepdims=False):
     """
     Compute the q-th quantile of the data along the specified axis.
-    
+
     .. versionadded:: 1.15.0
 
     Parameters
@@ -3887,8 +3914,8 @@ def _quantile_ureduce_func(a, q, axis=None, out=None, overwrite_input=False,
             "interpolation can only be 'linear', 'lower' 'higher', "
             "'midpoint', or 'nearest'")
 
-    n = np.array(False, dtype=bool) # check for nan's flag
-    if indices.dtype == intp:  # take the points along axis
+    n = np.array(False, dtype=bool)  # check for nan's flag
+    if np.issubdtype(indices.dtype, np.integer):  # take the points along axis
         # Check if the array contains any nan's
         if np.issubdtype(a.dtype, np.inexact):
             indices = concatenate((indices, [-1]))
@@ -3907,7 +3934,6 @@ def _quantile_ureduce_func(a, q, axis=None, out=None, overwrite_input=False,
             indices = indices[0]
         r = take(ap, indices, axis=axis, out=out)
 
-
     else:  # weight the points above and below the indices
         indices_below = floor(indices).astype(intp)
         indices_above = indices_below + 1
@@ -4068,13 +4094,13 @@ def trapz(y, x=None, dx=1.0, axis=-1):
     return ret
 
 
-def _meshgrid_dispatcher(*xi, **kwargs):
+def _meshgrid_dispatcher(*xi, copy=None, sparse=None, indexing=None):
     return xi
 
 
 # Based on scitools meshgrid
 @array_function_dispatch(_meshgrid_dispatcher)
-def meshgrid(*xi, **kwargs):
+def meshgrid(*xi, copy=True, sparse=False, indexing='xy'):
     """
     Return coordinate matrices from coordinate vectors.
 
@@ -4180,14 +4206,6 @@ def meshgrid(*xi, **kwargs):
     """
     ndim = len(xi)
 
-    copy_ = kwargs.pop('copy', True)
-    sparse = kwargs.pop('sparse', False)
-    indexing = kwargs.pop('indexing', 'xy')
-
-    if kwargs:
-        raise TypeError("meshgrid() got an unexpected keyword argument '%s'"
-                        % (list(kwargs)[0],))
-
     if indexing not in ['xy', 'ij']:
         raise ValueError(
             "Valid values for `indexing` are 'xy' and 'ij'.")
@@ -4205,7 +4223,7 @@ def meshgrid(*xi, **kwargs):
         # Return the full N-D matrix (not only the 1-D vector)
         output = np.broadcast_arrays(*output, subok=True)
 
-    if copy_:
+    if copy:
         output = [x.copy() for x in output]
 
     return output
@@ -4225,12 +4243,17 @@ def delete(arr, obj, axis=None):
     Parameters
     ----------
     arr : array_like
-      Input array.
+        Input array.
     obj : slice, int or array of ints
-      Indicate indices of sub-arrays to remove along the specified axis.
+        Indicate indices of sub-arrays to remove along the specified axis.
+
+        .. versionchanged:: 1.19.0
+            Boolean indices are now treated as a mask of elements to remove,
+            rather than being cast to the integers 0 and 1.
+
     axis : int, optional
-      The axis along which to delete the subarray defined by `obj`.
-      If `axis` is None, `obj` is applied to the flattened array.
+        The axis along which to delete the subarray defined by `obj`.
+        If `axis` is None, `obj` is applied to the flattened array.
 
     Returns
     -------
@@ -4288,20 +4311,11 @@ def delete(arr, obj, axis=None):
     if axis is None:
         if ndim != 1:
             arr = arr.ravel()
+        # needed for np.matrix, which is still not 1d after being ravelled
         ndim = arr.ndim
-        axis = -1
-
-    if ndim == 0:
-        # 2013-09-24, 1.9
-        warnings.warn(
-            "in the future the special handling of scalars will be removed "
-            "from delete and raise an error", DeprecationWarning, stacklevel=3)
-        if wrap:
-            return wrap(arr)
-        else:
-            return arr.copy(order=arrorder)
-
-    axis = normalize_axis_index(axis, ndim)
+        axis = ndim - 1
+    else:
+        axis = normalize_axis_index(axis, ndim)
 
     slobj = [slice(None)]*ndim
     N = arr.shape[axis]
@@ -4357,18 +4371,8 @@ def delete(arr, obj, axis=None):
         else:
             return new
 
-    _obj = obj
-    obj = np.asarray(obj)
-    # After removing the special handling of booleans and out of
-    # bounds values, the conversion to the array can be removed.
-    if obj.dtype == bool:
-        warnings.warn("in the future insert will treat boolean arrays and "
-                      "array-likes as boolean index instead of casting it "
-                      "to integer", FutureWarning, stacklevel=3)
-        obj = obj.astype(intp)
-    if isinstance(_obj, (int, long, integer)):
+    if isinstance(obj, (int, integer)) and not isinstance(obj, bool):
         # optimization for a single value
-        obj = obj.item()
         if (obj < -N or obj >= N):
             raise IndexError(
                 "index %i is out of bounds for axis %i with "
@@ -4384,35 +4388,23 @@ def delete(arr, obj, axis=None):
         slobj2[axis] = slice(obj+1, None)
         new[tuple(slobj)] = arr[tuple(slobj2)]
     else:
+        _obj = obj
+        obj = np.asarray(obj)
         if obj.size == 0 and not isinstance(_obj, np.ndarray):
             obj = obj.astype(intp)
-        if not np.can_cast(obj, intp, 'same_kind'):
-            # obj.size = 1 special case always failed and would just
-            # give superfluous warnings.
-            # 2013-09-24, 1.9
-            warnings.warn(
-                "using a non-integer array as obj in delete will result in an "
-                "error in the future", DeprecationWarning, stacklevel=3)
-            obj = obj.astype(intp)
-        keep = ones(N, dtype=bool)
 
-        # Test if there are out of bound indices, this is deprecated
-        inside_bounds = (obj < N) & (obj >= -N)
-        if not inside_bounds.all():
-            # 2013-09-24, 1.9
-            warnings.warn(
-                "in the future out of bounds indices will raise an error "
-                "instead of being ignored by `numpy.delete`.",
-                DeprecationWarning, stacklevel=3)
-            obj = obj[inside_bounds]
-        positive_indices = obj >= 0
-        if not positive_indices.all():
-            warnings.warn(
-                "in the future negative indices will not be ignored by "
-                "`numpy.delete`.", FutureWarning, stacklevel=3)
-            obj = obj[positive_indices]
+        if obj.dtype == bool:
+            if obj.shape != (N,):
+                raise ValueError('boolean array argument obj to delete '
+                                 'must be one dimensional and match the axis '
+                                 'length of {}'.format(N))
+
+            # optimization, the other branch is slower
+            keep = ~obj
+        else:
+            keep = ones(N, dtype=bool)
+            keep[obj,] = False
 
-        keep[obj, ] = False
         slobj[axis] = keep
         new = arr[tuple(slobj)]
 
@@ -4528,19 +4520,9 @@ def insert(arr, obj, values, axis=None):
     if axis is None:
         if ndim != 1:
             arr = arr.ravel()
+        # needed for np.matrix, which is still not 1d after being ravelled
         ndim = arr.ndim
         axis = ndim - 1
-    elif ndim == 0:
-        # 2013-09-24, 1.9
-        warnings.warn(
-            "in the future the special handling of scalars will be removed "
-            "from insert and raise an error", DeprecationWarning, stacklevel=3)
-        arr = arr.copy(order=arrorder)
-        arr[...] = values
-        if wrap:
-            return wrap(arr)
-        else:
-            return arr
     else:
         axis = normalize_axis_index(axis, ndim)
     slobj = [slice(None)]*ndim
@@ -4549,12 +4531,13 @@ def insert(arr, obj, values, axis=None):
 
     if isinstance(obj, slice):
         # turn it into a range object
-        indices = arange(*obj.indices(N), **{'dtype': intp})
+        indices = arange(*obj.indices(N), dtype=intp)
     else:
         # need to copy obj, because indices will be changed in-place
         indices = np.array(obj)
         if indices.dtype == bool:
             # See also delete
+            # 2012-10-11, NumPy 1.8
             warnings.warn(
                 "in the future insert will treat boolean arrays and "
                 "array-likes as a boolean index instead of casting it to "
@@ -4604,13 +4587,6 @@ def insert(arr, obj, values, axis=None):
         # Can safely cast the empty list to intp
         indices = indices.astype(intp)
 
-    if not np.can_cast(indices, intp, 'same_kind'):
-        # 2013-09-24, 1.9
-        warnings.warn(
-            "using a non-integer array as obj in insert will result in an "
-            "error in the future", DeprecationWarning, stacklevel=3)
-        indices = indices.astype(intp)
-
     indices[indices < 0] += N
 
     numnew = len(indices)
@@ -4681,7 +4657,9 @@ def append(arr, values, axis=None):
     >>> np.append([[1, 2, 3], [4, 5, 6]], [7, 8, 9], axis=0)
     Traceback (most recent call last):
         ...
-    ValueError: all the input arrays must have same number of dimensions
+    ValueError: all the input arrays must have same number of dimensions, but
+    the array at index 0 has 2 dimension(s) and the array at index 1 has 1
+    dimension(s)
 
     """
     arr = asanyarray(arr)
index 03c365ab6e3c8c9461578f1d18ce52729d055341..1a9b41ceda6b6d1b99811a53f008f305522c2b31 100644 (file)
@@ -1,15 +1,12 @@
 """
 Histogram-related functions
 """
-from __future__ import division, absolute_import, print_function
-
 import contextlib
 import functools
 import operator
 import warnings
 
 import numpy as np
-from numpy.compat.py3k import basestring
 from numpy.core import overrides
 
 __all__ = ['histogram', 'histogramdd', 'histogram_bin_edges']
@@ -210,7 +207,7 @@ def _hist_bin_fd(x, range):
     than the standard deviation, so it is less accurate, especially for
     long tailed distributions.
 
-    If the IQR is 0, this function returns 1 for the number of bins.
+    If the IQR is 0, this function returns 0 for the bin width.
     Binwidth is inversely proportional to the cube root of data size
     (asymptotically optimal).
 
@@ -232,21 +229,21 @@ def _hist_bin_fd(x, range):
 def _hist_bin_auto(x, range):
     """
     Histogram bin estimator that uses the minimum width of the
-    Freedman-Diaconis and Sturges estimators if the FD bandwidth is non zero
-    and the Sturges estimator if the FD bandwidth is 0.
+    Freedman-Diaconis and Sturges estimators if the FD bin width is non-zero.
+    If the bin width from the FD estimator is 0, the Sturges estimator is used.
 
     The FD estimator is usually the most robust method, but its width
     estimate tends to be too large for small `x` and bad for data with limited
     variance. The Sturges estimator is quite good for small (<1000) datasets
-    and is the default in the R language. This method gives good off the shelf
+    and is the default in the R language. This method gives good off-the-shelf
     behaviour.
 
     .. versionchanged:: 1.15.0
     If there is limited variance the IQR can be 0, which results in the
     FD bin width being 0 too. This is not a valid bin width, so
     ``np.histogram_bin_edges`` chooses 1 bin instead, which may not be optimal.
-    If the IQR is 0, it's unlikely any variance based estimators will be of
-    use, so we revert to the sturges estimator, which only uses the size of the
+    If the IQR is 0, it's unlikely any variance-based estimators will be of
+    use, so we revert to the Sturges estimator, which only uses the size of the
     dataset in its calculation.
 
     Parameters
@@ -385,7 +382,7 @@ def _get_bin_edges(a, bins, range, weights):
     n_equal_bins = None
     bin_edges = None
 
-    if isinstance(bins, basestring):
+    if isinstance(bins, str):
         bin_name = bins
         # if `bins` is a string for an automatic method,
         # this will replace it with the number of bins calculated
@@ -420,9 +417,9 @@ def _get_bin_edges(a, bins, range, weights):
     elif np.ndim(bins) == 0:
         try:
             n_equal_bins = operator.index(bins)
-        except TypeError:
+        except TypeError as e:
             raise TypeError(
-                '`bins` must be an integer, a string, or an array')
+                '`bins` must be an integer, a string, or an array') from e
         if n_equal_bins < 1:
             raise ValueError('`bins` must be positive, when an integer')
 
@@ -956,9 +953,9 @@ def histogramdd(sample, bins=10, range=None, normed=None, weights=None,
         Note the unusual interpretation of sample when an array_like:
 
         * When an array, each row is a coordinate in a D-dimensional space -
-          such as ``histogramgramdd(np.array([p1, p2, p3]))``.
+          such as ``histogramdd(np.array([p1, p2, p3]))``.
         * When an array_like, each element is the list of values for single
-          coordinate - such as ``histogramgramdd((X, Y, Z))``.
+          coordinate - such as ``histogramdd((X, Y, Z))``.
 
         The first form should be preferred.
 
@@ -1050,7 +1047,15 @@ def histogramdd(sample, bins=10, range=None, normed=None, weights=None,
                 raise ValueError(
                     '`bins[{}]` must be positive, when an integer'.format(i))
             smin, smax = _get_outer_edges(sample[:,i], range[i])
-            edges[i] = np.linspace(smin, smax, bins[i] + 1)
+            try:
+                n = operator.index(bins[i])
+            
+            except TypeError as e:
+                raise TypeError(
+                       "`bins[{}]` must be an integer, when a scalar".format(i)
+                ) from e
+                
+            edges[i] = np.linspace(smin, smax, n + 1)    
         elif np.ndim(bins[i]) == 1:
             edges[i] = np.asarray(bins[i])
             if np.any(edges[i][:-1] > edges[i][1:]):
index 04384854c74cadf736484955c64cf76e7e7bc2bd..d145477c3b60af3f60a4c183715ad307aa286720 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import functools
 import sys
 import math
@@ -107,7 +105,7 @@ def ix_(*args):
         out.append(new)
     return tuple(out)
 
-class nd_grid(object):
+class nd_grid:
     """
     Construct a multi-dimensional "meshgrid".
 
@@ -299,7 +297,7 @@ class OGridClass(nd_grid):
 ogrid = OGridClass()
 
 
-class AxisConcatenator(object):
+class AxisConcatenator:
     """
     Translates slice objects to concatenation along an axis.
 
@@ -370,8 +368,10 @@ class AxisConcatenator(object):
                         if len(vec) == 3:
                             trans1d = int(vec[2])
                         continue
-                    except Exception:
-                        raise ValueError("unknown special directive")
+                    except Exception as e:
+                        raise ValueError(
+                            "unknown special directive {!r}".format(item)
+                        ) from e
                 try:
                     axis = int(item)
                     continue
@@ -552,7 +552,7 @@ c_ = CClass()
 
 
 @set_module('numpy')
-class ndenumerate(object):
+class ndenumerate:
     """
     Multidimensional index iterator.
 
@@ -599,11 +599,9 @@ class ndenumerate(object):
     def __iter__(self):
         return self
 
-    next = __next__
-
 
 @set_module('numpy')
-class ndindex(object):
+class ndindex:
     """
     An N-dimensional iterator object to index arrays.
 
@@ -667,8 +665,6 @@ class ndindex(object):
         next(self._it)
         return self._it.multi_index
 
-    next = __next__
-
 
 # You can do all this with slice() plus a few special objects,
 # but there's a lot to remember. This version is simpler because
@@ -681,7 +677,7 @@ class ndindex(object):
 #
 #
 
-class IndexExpression(object):
+class IndexExpression:
     """
     A nicer way to build up index tuples for arrays.
 
index f974a7724e4d246dc0318010071f8edcb148d262..50157069cdf54ad1f1f8401376309d2356124c7a 100644 (file)
@@ -1,8 +1,4 @@
 """Mixin classes for custom array types that don't inherit from ndarray."""
-from __future__ import division, absolute_import, print_function
-
-import sys
-
 from numpy.core import umath as um
 
 
@@ -60,7 +56,7 @@ def _unary_method(ufunc, name):
     return func
 
 
-class NDArrayOperatorsMixin(object):
+class NDArrayOperatorsMixin:
     """Mixin defining all operator special methods using __array_ufunc__.
 
     This class implements the special methods for almost all of Python's
@@ -154,9 +150,7 @@ class NDArrayOperatorsMixin(object):
     __mul__, __rmul__, __imul__ = _numeric_methods(um.multiply, 'mul')
     __matmul__, __rmatmul__, __imatmul__ = _numeric_methods(
         um.matmul, 'matmul')
-    if sys.version_info.major < 3:
-        # Python 3 uses only __truediv__ and __floordiv__
-        __div__, __rdiv__, __idiv__ = _numeric_methods(um.divide, 'div')
+    # Python 3 does not use __div__, __rdiv__, or __idiv__
     __truediv__, __rtruediv__, __itruediv__ = _numeric_methods(
         um.true_divide, 'truediv')
     __floordiv__, __rfloordiv__, __ifloordiv__ = _numeric_methods(
index 8e2a34e707d1362ef65921955071962a909b10c1..00355043257db61e0a32b5d2a8d69375c1450131 100644 (file)
@@ -20,8 +20,6 @@ Functions
 - `nanpercentile` -- qth percentile of non-NaN values
 
 """
-from __future__ import division, absolute_import, print_function
-
 import functools
 import warnings
 import numpy as np
index 3e54ff10c2538d495a80fa9e9a0bd496f0a63988..f5a5484339df877cc56c5f562c8f2ed9dd0abefb 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import os
 import re
@@ -9,6 +7,7 @@ import warnings
 import weakref
 import contextlib
 from operator import itemgetter, index as opindex
+from collections.abc import Mapping
 
 import numpy as np
 from . import format
@@ -24,16 +23,10 @@ from ._iotools import (
     )
 
 from numpy.compat import (
-    asbytes, asstr, asunicode, bytes, basestring, os_fspath, os_PathLike,
+    asbytes, asstr, asunicode, bytes, os_fspath, os_PathLike,
     pickle, contextlib_nullcontext
     )
 
-if sys.version_info[0] >= 3:
-    from collections.abc import Mapping
-else:
-    from future_builtins import map
-    from collections import Mapping
-
 
 @set_module('numpy')
 def loads(*args, **kwargs):
@@ -55,7 +48,7 @@ array_function_dispatch = functools.partial(
     overrides.array_function_dispatch, module='numpy')
 
 
-class BagObj(object):
+class BagObj:
     """
     BagObj(obj)
 
@@ -69,7 +62,7 @@ class BagObj(object):
     Examples
     --------
     >>> from numpy.lib.npyio import BagObj as BO
-    >>> class BagDemo(object):
+    >>> class BagDemo:
     ...     def __getitem__(self, key): # An instance of BagObj(BagDemo)
     ...                                 # will call this method when any
     ...                                 # attribute look-up is required
@@ -266,26 +259,25 @@ class NpzFile(Mapping):
             raise KeyError("%s is not a file in the archive" % key)
 
 
-    if sys.version_info.major == 3:
-        # deprecate the python 2 dict apis that we supported by accident in
-        # python 3. We forgot to implement itervalues() at all in earlier
-        # versions of numpy, so no need to deprecated it here.
+    # deprecate the python 2 dict apis that we supported by accident in
+    # python 3. We forgot to implement itervalues() at all in earlier
+    # versions of numpy, so no need to deprecated it here.
 
-        def iteritems(self):
-            # Numpy 1.15, 2018-02-20
-            warnings.warn(
-                "NpzFile.iteritems is deprecated in python 3, to match the "
-                "removal of dict.itertems. Use .items() instead.",
-                DeprecationWarning, stacklevel=2)
-            return self.items()
+    def iteritems(self):
+        # Numpy 1.15, 2018-02-20
+        warnings.warn(
+            "NpzFile.iteritems is deprecated in python 3, to match the "
+            "removal of dict.itertems. Use .items() instead.",
+            DeprecationWarning, stacklevel=2)
+        return self.items()
 
-        def iterkeys(self):
-            # Numpy 1.15, 2018-02-20
-            warnings.warn(
-                "NpzFile.iterkeys is deprecated in python 3, to match the "
-                "removal of dict.iterkeys. Use .keys() instead.",
-                DeprecationWarning, stacklevel=2)
-            return self.keys()
+    def iterkeys(self):
+        # Numpy 1.15, 2018-02-20
+        warnings.warn(
+            "NpzFile.iterkeys is deprecated in python 3, to match the "
+            "removal of dict.iterkeys. Use .keys() instead.",
+            DeprecationWarning, stacklevel=2)
+        return self.keys()
 
 
 @set_module('numpy')
@@ -414,21 +406,16 @@ def load(file, mmap_mode=None, allow_pickle=False, fix_imports=True,
         # result can similarly silently corrupt numerical data.
         raise ValueError("encoding must be 'ASCII', 'latin1', or 'bytes'")
 
-    if sys.version_info[0] >= 3:
-        pickle_kwargs = dict(encoding=encoding, fix_imports=fix_imports)
-    else:
-        # Nothing to do on Python 2
-        pickle_kwargs = {}
+    pickle_kwargs = dict(encoding=encoding, fix_imports=fix_imports)
 
-    # TODO: Use contextlib.ExitStack once we drop Python 2
-    if hasattr(file, 'read'):
-        fid = file
-        own_fid = False
-    else:
-        fid = open(os_fspath(file), "rb")
-        own_fid = True
+    with contextlib.ExitStack() as stack:
+        if hasattr(file, 'read'):
+            fid = file
+            own_fid = False
+        else:
+            fid = stack.enter_context(open(os_fspath(file), "rb"))
+            own_fid = True
 
-    try:
         # Code to distinguish from NumPy binary files and pickles.
         _ZIP_PREFIX = b'PK\x03\x04'
         _ZIP_SUFFIX = b'PK\x05\x06' # empty zip files start with this
@@ -439,10 +426,10 @@ def load(file, mmap_mode=None, allow_pickle=False, fix_imports=True,
         fid.seek(-min(N, len(magic)), 1)  # back-up
         if magic.startswith(_ZIP_PREFIX) or magic.startswith(_ZIP_SUFFIX):
             # zip-file (assume .npz)
-            # Transfer file ownership to NpzFile
+            # Potentially transfer file ownership to NpzFile
+            stack.pop_all()
             ret = NpzFile(fid, own_fid=own_fid, allow_pickle=allow_pickle,
                           pickle_kwargs=pickle_kwargs)
-            own_fid = False
             return ret
         elif magic == format.MAGIC_PREFIX:
             # .npy file
@@ -461,9 +448,6 @@ def load(file, mmap_mode=None, allow_pickle=False, fix_imports=True,
             except Exception:
                 raise IOError(
                     "Failed to interpret file %s as a pickle" % repr(file))
-    finally:
-        if own_fid:
-            fid.close()
 
 
 def _save_dispatcher(file, arr, allow_pickle=None, fix_imports=None):
@@ -531,36 +515,23 @@ def save(file, arr, allow_pickle=True, fix_imports=True):
     >>> print(a, b)
     # [1 2] [1 3]
     """
-    own_fid = False
     if hasattr(file, 'write'):
-        fid = file
+        file_ctx = contextlib_nullcontext(file)
     else:
         file = os_fspath(file)
         if not file.endswith('.npy'):
             file = file + '.npy'
-        fid = open(file, "wb")
-        own_fid = True
+        file_ctx = open(file, "wb")
 
-    if sys.version_info[0] >= 3:
-        pickle_kwargs = dict(fix_imports=fix_imports)
-    else:
-        # Nothing to do on Python 2
-        pickle_kwargs = None
-
-    try:
+    with file_ctx as fid:
         arr = np.asanyarray(arr)
         format.write_array(fid, arr, allow_pickle=allow_pickle,
-                           pickle_kwargs=pickle_kwargs)
-    finally:
-        if own_fid:
-            fid.close()
+                           pickle_kwargs=dict(fix_imports=fix_imports))
 
 
 def _savez_dispatcher(file, *args, **kwds):
-    for a in args:
-        yield a
-    for v in kwds.values():
-        yield v
+    yield from args
+    yield from kwds.values()
 
 
 @array_function_dispatch(_savez_dispatcher)
@@ -646,10 +617,8 @@ def savez(file, *args, **kwds):
 
 
 def _savez_compressed_dispatcher(file, *args, **kwds):
-    for a in args:
-        yield a
-    for v in kwds.values():
-        yield v
+    yield from args
+    yield from kwds.values()
 
 
 @array_function_dispatch(_savez_compressed_dispatcher)
@@ -693,7 +662,7 @@ def savez_compressed(file, *args, **kwds):
     The ``.npz`` file format is a zipped archive of files named after the
     variables they contain.  The archive is compressed with
     ``zipfile.ZIP_DEFLATED`` and each file in the archive contains one variable
-    in ``.npy`` format. For a description of the ``.npy`` format, see 
+    in ``.npy`` format. For a description of the ``.npy`` format, see
     :py:mod:`numpy.lib.format`.
 
 
@@ -823,7 +792,7 @@ _loadtxt_chunksize = 50000
 def loadtxt(fname, dtype=float, comments='#', delimiter=None,
             converters=None, skiprows=0, usecols=None, unpack=False,
             ndmin=0, encoding='bytes', max_rows=None):
-    """
+    r"""
     Load data from a text file.
 
     Each row in the text file must have the same number of values.
@@ -915,28 +884,39 @@ def loadtxt(fname, dtype=float, comments='#', delimiter=None,
     Examples
     --------
     >>> from io import StringIO   # StringIO behaves like a file object
-    >>> c = StringIO(u"0 1\\n2 3")
+    >>> c = StringIO("0 1\n2 3")
     >>> np.loadtxt(c)
     array([[0., 1.],
            [2., 3.]])
 
-    >>> d = StringIO(u"M 21 72\\nF 35 58")
+    >>> d = StringIO("M 21 72\nF 35 58")
     >>> np.loadtxt(d, dtype={'names': ('gender', 'age', 'weight'),
     ...                      'formats': ('S1', 'i4', 'f4')})
     array([(b'M', 21, 72.), (b'F', 35, 58.)],
           dtype=[('gender', 'S1'), ('age', '<i4'), ('weight', '<f4')])
 
-    >>> c = StringIO(u"1,0,2\\n3,0,4")
+    >>> c = StringIO("1,0,2\n3,0,4")
     >>> x, y = np.loadtxt(c, delimiter=',', usecols=(0, 2), unpack=True)
     >>> x
     array([1., 3.])
     >>> y
     array([2., 4.])
 
+    This example shows how `converters` can be used to convert a field
+    with a trailing minus sign into a negative number.
+
+    >>> s = StringIO('10.01 31.25-\n19.22 64.31\n17.57- 63.94')
+    >>> def conv(fld):
+    ...     return -float(fld[:-1]) if fld.endswith(b'-') else float(fld)
+    ...
+    >>> np.loadtxt(s, converters={0: conv, 1: conv})
+    array([[ 10.01, -31.25],
+           [ 19.22,  64.31],
+           [-17.57,  63.94]])
     """
     # Type conversions for Py3 convenience
     if comments is not None:
-        if isinstance(comments, (basestring, bytes)):
+        if isinstance(comments, (str, bytes)):
             comments = [comments]
         comments = [_decode_line(x) for x in comments]
         # Compile regex for comments beforehand
@@ -1336,8 +1316,8 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='',
         fmt = asstr(fmt)
     delimiter = asstr(delimiter)
 
-    class WriteWrap(object):
-        """Convert to unicode in py2 or to bytes on bytestream inputs.
+    class WriteWrap:
+        """Convert to bytes on bytestream inputs.
 
         """
         def __init__(self, fh, encoding):
@@ -1377,9 +1357,6 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='',
         open(fname, 'wt').close()
         fh = np.lib._datasource.open(fname, 'wt', encoding=encoding)
         own_fh = True
-        # need to convert str to unicode for text io output
-        if sys.version_info[0] == 2:
-            fh = WriteWrap(fh, encoding or 'latin1')
     elif hasattr(fname, 'write'):
         # wrap to handle byte output streams
         fh = WriteWrap(fname, encoding or 'latin1')
@@ -1412,7 +1389,7 @@ def savetxt(fname, X, fmt='%.18e', delimiter=' ', newline='\n', header='',
             if len(fmt) != ncol:
                 raise AttributeError('fmt has wrong shape.  %s' % str(fmt))
             format = asstr(delimiter).join(map(asstr, fmt))
-        elif isinstance(fmt, basestring):
+        elif isinstance(fmt, str):
             n_fmt_chars = fmt.count('%')
             error = ValueError('fmt has wrong number of %% formats:  %s' % fmt)
             if n_fmt_chars == 1:
@@ -1678,7 +1655,7 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
     -----
     * When spaces are used as delimiters, or when no delimiter has been given
       as input, there should not be any missing data between two fields.
-    * When the variables are named (either by a flexible dtype or with `names`,
+    * When the variables are named (either by a flexible dtype or with `names`),
       there must not be any header in the file (else a ValueError
       exception is raised).
     * Individual values are not stripped of spaces by default.
@@ -1768,7 +1745,7 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
     try:
         if isinstance(fname, os_PathLike):
             fname = os_fspath(fname)
-        if isinstance(fname, basestring):
+        if isinstance(fname, str):
             fid = np.lib._datasource.open(fname, 'rt', encoding=encoding)
             fid_ctx = contextlib.closing(fid)
         else:
@@ -1910,7 +1887,7 @@ def genfromtxt(fname, dtype=float, comments='#', delimiter=None,
                 if value not in entry:
                     entry.append(value)
         # We have a string : apply it to all entries
-        elif isinstance(user_missing_values, basestring):
+        elif isinstance(user_missing_values, str):
             user_value = user_missing_values.split(",")
             for entry in missing_values:
                 entry.extend(user_value)
index 3d07a0de430be20b29708b6ad2b336108ab8fb1f..5a0fa5431ef3c2cabb0618429cf64cfa5293dac4 100644 (file)
@@ -2,8 +2,6 @@
 Functions to operate on polynomials.
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['poly', 'roots', 'polyint', 'polyder', 'polyadd',
            'polysub', 'polymul', 'polydiv', 'polyval', 'poly1d',
            'polyfit', 'RankWarning']
@@ -1007,7 +1005,7 @@ def _raise_power(astr, wrap=70):
 
 
 @set_module('numpy')
-class poly1d(object):
+class poly1d:
     """
     A one-dimensional polynomial class.
 
index 927161ddb01bd11e5708b18f3fdcf0084fd163da..a11d5f2c74910da5b358a3c81c6e792796bb0db0 100644 (file)
@@ -5,9 +5,6 @@ Most of these functions were initially implemented by John Hunter for
 matplotlib.  They have been rewritten and extended for convenience.
 
 """
-from __future__ import division, absolute_import, print_function
-
-import sys
 import itertools
 import numpy as np
 import numpy.ma as ma
@@ -16,12 +13,8 @@ from numpy.ma import MaskedArray
 from numpy.ma.mrecords import MaskedRecords
 from numpy.core.overrides import array_function_dispatch
 from numpy.lib._iotools import _is_string_like
-from numpy.compat import basestring
 from numpy.testing import suppress_warnings
 
-if sys.version_info[0] < 3:
-    from future_builtins import zip
-
 _check_fill_value = np.ma.core._check_fill_value
 
 
@@ -292,8 +285,7 @@ def _izip_fields_flat(iterable):
     """
     for element in iterable:
         if isinstance(element, np.void):
-            for f in _izip_fields_flat(tuple(element)):
-                yield f
+            yield from _izip_fields_flat(tuple(element))
         else:
             yield element
 
@@ -305,12 +297,11 @@ def _izip_fields(iterable):
     """
     for element in iterable:
         if (hasattr(element, '__iter__') and
-                not isinstance(element, basestring)):
-            for f in _izip_fields(element):
-                yield f
+                not isinstance(element, str)):
+            yield from _izip_fields(element)
         elif isinstance(element, np.void) and len(tuple(element)) == 1:
-            for f in _izip_fields(element):
-                yield f
+            # this statement is the same from the previous expression
+            yield from _izip_fields(element)
         else:
             yield element
 
@@ -335,12 +326,7 @@ def _izip_records(seqarrays, fill_value=None, flatten=True):
     else:
         zipfunc = _izip_fields
 
-    if sys.version_info[0] >= 3:
-        zip_longest = itertools.zip_longest
-    else:
-        zip_longest = itertools.izip_longest
-
-    for tup in zip_longest(*seqarrays, fillvalue=fill_value):
+    for tup in itertools.zip_longest(*seqarrays, fillvalue=fill_value):
         yield tuple(zipfunc(tup))
 
 
@@ -438,7 +424,7 @@ def merge_arrays(seqarrays, fill_value=-1, flatten=False,
         if seqdtype.names is None:
             seqdtype = np.dtype([('', seqdtype)])
         if not flatten or _zip_dtype((seqarrays,), flatten=True) == seqdtype:
-            # Minimal processing needed: just make sure everythng's a-ok
+            # Minimal processing needed: just make sure everything's a-ok
             seqarrays = seqarrays.ravel()
             # Find what type of array we must return
             if usemask:
@@ -669,8 +655,7 @@ def rename_fields(base, namemapper):
 def _append_fields_dispatcher(base, names, data, dtypes=None,
                               fill_value=None, usemask=None, asrecarray=None):
     yield base
-    for d in data:
-        yield d
+    yield from data
 
 
 @array_function_dispatch(_append_fields_dispatcher)
@@ -709,7 +694,7 @@ def append_fields(base, names, data, dtypes=None,
         if len(names) != len(data):
             msg = "The number of arrays does not match the number of names"
             raise ValueError(msg)
-    elif isinstance(names, basestring):
+    elif isinstance(names, str):
         names = [names, ]
         data = [data, ]
     #
@@ -746,8 +731,7 @@ def append_fields(base, names, data, dtypes=None,
 
 def _rec_append_fields_dispatcher(base, names, data, dtypes=None):
     yield base
-    for d in data:
-        yield d
+    yield from data
 
 
 @array_function_dispatch(_rec_append_fields_dispatcher)
@@ -1466,7 +1450,7 @@ def join_by(key, r1, r2, jointype='inner', r1postfix='1', r2postfix='2',
                 "'outer' or 'leftouter' (got '%s' instead)" % jointype
                 )
     # If we have a single key, put it in a tuple
-    if isinstance(key, basestring):
+    if isinstance(key, str):
         key = (key,)
 
     # Check the keys
index 5ac790ce9f511076989d9fd39d17308380cebb00..555a3d5a844e304243d025eac081ba76e4915f31 100644 (file)
@@ -15,8 +15,6 @@ Similarly, `sqrt`, other base logarithms, `power` and trig functions are
 correctly handled.  See their respective docstrings for specific examples.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy.core.numeric as nx
 import numpy.core.numerictypes as nt
 from numpy.core.numeric import asarray, any
index d342410b8a85856eb59aced352fbf4caa40f5932..b3f441f38d3b671caea52c99a61cf6f9d8ad5fb8 100644 (file)
@@ -1,10 +1,9 @@
-from __future__ import division, print_function
-
 def configuration(parent_package='',top_path=None):
     from numpy.distutils.misc_util import Configuration
 
     config = Configuration('lib', parent_package, top_path)
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
+    config.add_data_dir('tests/data')
     return config
 
 if __name__ == '__main__':
index dbb61c2251f86320a56f563a01d9b71572d043cc..78703555eb2f784f318868b0d57abc1b14a52562 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import functools
 
 import numpy.core.numeric as _nx
@@ -271,8 +269,8 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs):
     """
     Apply a function to 1-D slices along the given axis.
 
-    Execute `func1d(a, *args)` where `func1d` operates on 1-D arrays and `a`
-    is a 1-D slice of `arr` along `axis`.
+    Execute `func1d(a, *args, **kwargs)` where `func1d` operates on 1-D arrays
+    and `a` is a 1-D slice of `arr` along `axis`.
 
     This is equivalent to (but faster than) the following use of `ndindex` and
     `s_`, which sets each of ``ii``, ``jj``, and ``kk`` to a tuple of indices::
@@ -374,8 +372,10 @@ def apply_along_axis(func1d, axis, arr, *args, **kwargs):
     # invoke the function on the first item
     try:
         ind0 = next(inds)
-    except StopIteration:
-        raise ValueError('Cannot apply_along_axis when any iteration dimensions are 0')
+    except StopIteration as e:
+        raise ValueError(
+            'Cannot apply_along_axis when any iteration dimensions are 0'
+        ) from None
     res = asanyarray(func1d(inarr_view[ind0], *args, **kwargs))
 
     # build a buffer for storing evaluations of func1d.
@@ -688,10 +688,12 @@ def dstack(tup):
 
     See Also
     --------
-    stack : Join a sequence of arrays along a new axis.
-    vstack : Stack along first axis.
-    hstack : Stack along second axis.
     concatenate : Join a sequence of arrays along an existing axis.
+    stack : Join a sequence of arrays along a new axis.
+    block : Assemble an nd-array from nested lists of blocks.
+    vstack : Stack arrays in sequence vertically (row wise).
+    hstack : Stack arrays in sequence horizontally (column wise).
+    column_stack : Stack 1-D arrays as columns into a 2-D array.
     dsplit : Split array along third axis.
 
     Examples
index 8aafd094b02c4ba445245d252c38dc82f88e3cf5..502235bdfbcd58152dbf6be834c4a0137c035a01 100644 (file)
@@ -5,15 +5,13 @@ An explanation of strides can be found in the "ndarray.rst" file in the
 NumPy reference guide.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.core.overrides import array_function_dispatch
 
 __all__ = ['broadcast_to', 'broadcast_arrays']
 
 
-class DummyArray(object):
+class DummyArray:
     """Dummy object that just exists to hang __array_interface__ dictionaries
     and possibly keep alive a reference to a base array.
     """
@@ -199,12 +197,12 @@ def _broadcast_shape(*args):
     return b.shape
 
 
-def _broadcast_arrays_dispatcher(*args, **kwargs):
+def _broadcast_arrays_dispatcher(*args, subok=None):
     return args
 
 
 @array_function_dispatch(_broadcast_arrays_dispatcher, module='numpy')
-def broadcast_arrays(*args, **kwargs):
+def broadcast_arrays(*args, subok=False):
     """
     Broadcast any number of arrays against each other.
 
@@ -255,10 +253,6 @@ def broadcast_arrays(*args, **kwargs):
     # return np.nditer(args, flags=['multi_index', 'zerosize_ok'],
     #                  order='C').itviews
 
-    subok = kwargs.pop('subok', False)
-    if kwargs:
-        raise TypeError('broadcast_arrays() got an unexpected keyword '
-                        'argument {!r}'.format(list(kwargs.keys())[0]))
     args = [np.array(_m, copy=False, subok=subok) for _m in args]
 
     shape = _broadcast_shape(*args)
index 8eac16b589a0030d6dc285d5f1df676ca4614d2b..1ed7815d9c0c5b2816c2e5bf5c9e6cad0945b6a5 100644 (file)
@@ -1,24 +1,14 @@
-from __future__ import division, absolute_import, print_function
-
 import os
-import sys
 import pytest
 from tempfile import mkdtemp, mkstemp, NamedTemporaryFile
 from shutil import rmtree
 
 import numpy.lib._datasource as datasource
-from numpy.testing import (
-    assert_, assert_equal, assert_raises, assert_warns
-    )
+from numpy.testing import assert_, assert_equal, assert_raises
 
-if sys.version_info[0] >= 3:
-    import urllib.request as urllib_request
-    from urllib.parse import urlparse
-    from urllib.error import URLError
-else:
-    import urllib2 as urllib_request
-    from urlparse import urlparse
-    from urllib2 import URLError
+import urllib.request as urllib_request
+from urllib.parse import urlparse
+from urllib.error import URLError
 
 
 def urlopen_stub(url, data=None):
@@ -96,7 +86,7 @@ def invalid_httpfile():
     return http_fakefile
 
 
-class TestDataSourceOpen(object):
+class TestDataSourceOpen:
     def setup(self):
         self.tmpdir = mkdtemp()
         self.ds = datasource.DataSource(self.tmpdir)
@@ -164,26 +154,8 @@ class TestDataSourceOpen(object):
         fp.close()
         assert_equal(magic_line, result)
 
-    @pytest.mark.skipif(sys.version_info[0] >= 3, reason="Python 2 only")
-    def test_Bz2File_text_mode_warning(self):
-        try:
-            import bz2
-        except ImportError:
-            # We don't have the bz2 capabilities to test.
-            pytest.skip()
-        # Test datasource's internal file_opener for BZip2 files.
-        filepath = os.path.join(self.tmpdir, 'foobar.txt.bz2')
-        fp = bz2.BZ2File(filepath, 'w')
-        fp.write(magic_line)
-        fp.close()
-        with assert_warns(RuntimeWarning):
-            fp = self.ds.open(filepath, 'rt')
-            result = fp.readline()
-            fp.close()
-        assert_equal(magic_line, result)
-
 
-class TestDataSourceExists(object):
+class TestDataSourceExists:
     def setup(self):
         self.tmpdir = mkdtemp()
         self.ds = datasource.DataSource(self.tmpdir)
@@ -213,7 +185,7 @@ class TestDataSourceExists(object):
         assert_equal(self.ds.exists(tmpfile), False)
 
 
-class TestDataSourceAbspath(object):
+class TestDataSourceAbspath:
     def setup(self):
         self.tmpdir = os.path.abspath(mkdtemp())
         self.ds = datasource.DataSource(self.tmpdir)
@@ -278,7 +250,7 @@ class TestDataSourceAbspath(object):
             os.sep = orig_os_sep
 
 
-class TestRepositoryAbspath(object):
+class TestRepositoryAbspath:
     def setup(self):
         self.tmpdir = os.path.abspath(mkdtemp())
         self.repos = datasource.Repository(valid_baseurl(), self.tmpdir)
@@ -311,7 +283,7 @@ class TestRepositoryAbspath(object):
             os.sep = orig_os_sep
 
 
-class TestRepositoryExists(object):
+class TestRepositoryExists:
     def setup(self):
         self.tmpdir = mkdtemp()
         self.repos = datasource.Repository(valid_baseurl(), self.tmpdir)
@@ -344,7 +316,7 @@ class TestRepositoryExists(object):
         assert_(self.repos.exists(tmpfile))
 
 
-class TestOpenFunc(object):
+class TestOpenFunc:
     def setup(self):
         self.tmpdir = mkdtemp()
 
index 15cd3ad9d8d9ecaeed863020b6e4954b4b7865d7..6964c11280e64a5b216aff1bb8aa9ea6d4a14b3c 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import time
 from datetime import date
 
@@ -11,10 +9,9 @@ from numpy.lib._iotools import (
     LineSplitter, NameValidator, StringConverter,
     has_nested_fields, easy_dtype, flatten_dtype
     )
-from numpy.compat import unicode
 
 
-class TestLineSplitter(object):
+class TestLineSplitter:
     "Tests the LineSplitter class."
 
     def test_no_delimiter(self):
@@ -83,7 +80,7 @@ class TestLineSplitter(object):
 # -----------------------------------------------------------------------------
 
 
-class TestNameValidator(object):
+class TestNameValidator:
 
     def test_case_sensitivity(self):
         "Test case sensitivity"
@@ -141,7 +138,7 @@ def _bytes_to_date(s):
     return date(*time.strptime(s, "%Y-%m-%d")[:3])
 
 
-class TestStringConverter(object):
+class TestStringConverter:
     "Test StringConverter"
 
     def test_creation(self):
@@ -181,10 +178,10 @@ class TestStringConverter(object):
         # note that the longdouble type has been skipped, so the
         # _status increases by 2. Everything should succeed with
         # unicode conversion (5).
-        for s in ['a', u'a', b'a']:
+        for s in ['a', b'a']:
             res = converter.upgrade(s)
-            assert_(type(res) is unicode)
-            assert_equal(res, u'a')
+            assert_(type(res) is str)
+            assert_equal(res, 'a')
             assert_equal(converter._status, 5 + status_offset)
 
     def test_missing(self):
@@ -266,7 +263,7 @@ class TestStringConverter(object):
         assert_(converter(val) == 9223372043271415339)
 
 
-class TestMiscFunctions(object):
+class TestMiscFunctions:
 
     def test_has_nested_dtype(self):
         "Test has_nested_dtype"
index 8e66a0c0323f0cd16aea1707e6954846d3d4e146..1825046316a9705f77e2790bc131354f5ecf71b8 100644 (file)
@@ -1,8 +1,6 @@
 """Tests for the NumpyVersion class.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from numpy.testing import assert_, assert_raises
 from numpy.lib import NumpyVersion
 
index 65593dd299225e261949d8eb03babbca86814215..75db5928b288760a6b0b07ef219697a915384924 100644 (file)
@@ -1,8 +1,6 @@
 """Tests for the array padding functions.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import pytest
 
 import numpy as np
@@ -31,7 +29,7 @@ _all_modes = {
 }
 
 
-class TestAsPairs(object):
+class TestAsPairs:
     def test_single_value(self):
         """Test casting for a single value."""
         expected = np.array([[3, 3]] * 10)
@@ -114,7 +112,7 @@ class TestAsPairs(object):
             _as_pairs(np.ones((2, 3)), 3)
 
 
-class TestConditionalShortcuts(object):
+class TestConditionalShortcuts:
     @pytest.mark.parametrize("mode", _all_modes.keys())
     def test_zero_padding_shortcuts(self, mode):
         test = np.arange(120).reshape(4, 5, 6)
@@ -136,7 +134,7 @@ class TestConditionalShortcuts(object):
                            np.pad(test, pad_amt, mode=mode, stat_length=30))
 
 
-class TestStatistic(object):
+class TestStatistic:
     def test_check_mean_stat_length(self):
         a = np.arange(100).astype('f')
         a = np.pad(a, ((25, 20), ), 'mean', stat_length=((2, 3), ))
@@ -498,7 +496,7 @@ class TestStatistic(object):
             np.pad([1., 2.], 1, mode, stat_length=(1, 0))
 
 
-class TestConstant(object):
+class TestConstant:
     def test_check_constant(self):
         a = np.arange(100)
         a = np.pad(a, (25, 20), 'constant', constant_values=(10, 20))
@@ -677,7 +675,7 @@ class TestConstant(object):
         assert result.shape == (3, 4, 4)
 
 
-class TestLinearRamp(object):
+class TestLinearRamp:
     def test_check_simple(self):
         a = np.arange(100).astype('f')
         a = np.pad(a, (25, 20), 'linear_ramp', end_values=(4, 5))
@@ -762,7 +760,7 @@ class TestLinearRamp(object):
         assert_equal(result, expected)
 
 
-class TestReflect(object):
+class TestReflect:
     def test_check_simple(self):
         a = np.arange(100)
         a = np.pad(a, (25, 20), 'reflect')
@@ -872,7 +870,7 @@ class TestReflect(object):
         assert_array_equal(a, b)
 
 
-class TestEmptyArray(object):
+class TestEmptyArray:
     """Check how padding behaves on arrays with an empty dimension."""
 
     @pytest.mark.parametrize(
@@ -896,7 +894,7 @@ class TestEmptyArray(object):
         assert result.shape == (8, 0, 4)
 
 
-class TestSymmetric(object):
+class TestSymmetric:
     def test_check_simple(self):
         a = np.arange(100)
         a = np.pad(a, (25, 20), 'symmetric')
@@ -1030,7 +1028,7 @@ class TestSymmetric(object):
         assert_array_equal(a, b)
 
 
-class TestWrap(object):
+class TestWrap:
     def test_check_simple(self):
         a = np.arange(100)
         a = np.pad(a, (25, 20), 'wrap')
@@ -1144,7 +1142,7 @@ class TestWrap(object):
         assert_array_equal(np.r_[a, a, a, a][:-3], b)
 
 
-class TestEdge(object):
+class TestEdge:
     def test_check_simple(self):
         a = np.arange(12)
         a = np.reshape(a, (4, 3))
@@ -1183,7 +1181,7 @@ class TestEdge(object):
         assert_array_equal(padded, expected)
 
 
-class TestEmpty(object):
+class TestEmpty:
     def test_simple(self):
         arr = np.arange(24).reshape(4, 6)
         result = np.pad(arr, [(2, 3), (3, 1)], mode="empty")
@@ -1231,7 +1229,7 @@ def test_object_input(mode):
     assert_array_equal(np.pad(a, pad_amt, mode=mode), b)
 
 
-class TestPadWidth(object):
+class TestPadWidth:
     @pytest.mark.parametrize("pad_width", [
         (4, 5, 6, 7),
         ((1,), (2,), (3,)),
@@ -1262,24 +1260,29 @@ class TestPadWidth(object):
         with pytest.raises(ValueError, match=match):
             np.pad(arr, pad_width, mode)
 
-    @pytest.mark.parametrize("pad_width", [
-        "3",
-        "word",
-        None,
-        object(),
-        3.4,
-        ((2, 3, 4), (3, 2)),  # dtype=object (tuple)
-        complex(1, -1),
-        ((-2.1, 3), (3, 2)),
+    @pytest.mark.parametrize("pad_width, dtype", [
+        ("3", None),
+        ("word", None),
+        (None, None),
+        (object(), None),
+        (3.4, None),
+        (((2, 3, 4), (3, 2)), object),
+        (complex(1, -1), None),
+        (((-2.1, 3), (3, 2)), None),
     ])
     @pytest.mark.parametrize("mode", _all_modes.keys())
-    def test_bad_type(self, pad_width, mode):
+    def test_bad_type(self, pad_width, dtype, mode):
         arr = np.arange(30).reshape((6, 5))
         match = "`pad_width` must be of integral type."
-        with pytest.raises(TypeError, match=match):
-            np.pad(arr, pad_width, mode)
-        with pytest.raises(TypeError, match=match):
-            np.pad(arr, np.array(pad_width), mode)
+        if dtype is not None:
+            # avoid DeprecationWarning when not specifying dtype
+            with pytest.raises(TypeError, match=match):
+                np.pad(arr, np.array(pad_width, dtype=dtype), mode)
+        else:
+            with pytest.raises(TypeError, match=match):
+                np.pad(arr, pad_width, mode)
+            with pytest.raises(TypeError, match=match):
+                np.pad(arr, np.array(pad_width), mode)
 
     def test_pad_width_as_ndarray(self):
         a = np.arange(12)
index fd21a7f76288360f53e32e0ba91a0fc3c631bd71..81ba789e30d68a5199e3d122bea27452a028bd5e 100644 (file)
@@ -1,8 +1,6 @@
 """Test functions for 1D array set operations.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 
 from numpy.testing import (assert_array_equal, assert_equal,
@@ -13,8 +11,7 @@ from numpy.lib.arraysetops import (
 import pytest
 
 
-
-class TestSetOps(object):
+class TestSetOps:
 
     def test_intersect1d(self):
         # unique inputs
@@ -36,7 +33,7 @@ class TestSetOps(object):
 
     def test_intersect1d_array_like(self):
         # See gh-11772
-        class Test(object):
+        class Test:
             def __array__(self):
                 return np.arange(3)
 
@@ -120,12 +117,13 @@ class TestSetOps(object):
         assert_array_equal([-1, 0], ediff1d(zero_elem, to_begin=-1, to_end=0))
         assert_array_equal([], ediff1d(one_elem))
         assert_array_equal([1], ediff1d(two_elem))
-        assert_array_equal([7,1,9], ediff1d(two_elem, to_begin=7, to_end=9))
-        assert_array_equal([5,6,1,7,8], ediff1d(two_elem, to_begin=[5,6], to_end=[7,8]))
-        assert_array_equal([1,9], ediff1d(two_elem, to_end=9))
-        assert_array_equal([1,7,8], ediff1d(two_elem, to_end=[7,8]))
-        assert_array_equal([7,1], ediff1d(two_elem, to_begin=7))
-        assert_array_equal([5,6,1], ediff1d(two_elem, to_begin=[5,6]))
+        assert_array_equal([7, 1, 9], ediff1d(two_elem, to_begin=7, to_end=9))
+        assert_array_equal([5, 6, 1, 7, 8],
+                           ediff1d(two_elem, to_begin=[5, 6], to_end=[7, 8]))
+        assert_array_equal([1, 9], ediff1d(two_elem, to_end=9))
+        assert_array_equal([1, 7, 8], ediff1d(two_elem, to_end=[7, 8]))
+        assert_array_equal([7, 1], ediff1d(two_elem, to_begin=7))
+        assert_array_equal([5, 6, 1], ediff1d(two_elem, to_begin=[5, 6]))
 
     @pytest.mark.parametrize("ary, prepend, append", [
         # should fail because trying to cast
@@ -135,9 +133,9 @@ class TestSetOps(object):
          None,
          np.nan),
         # should fail because attempting
-        # to downcast to smaller int type:
-        (np.array([1, 2, 3], dtype=np.int16),
-         np.array([5, 1<<20, 2], dtype=np.int32),
+        # to downcast to int type:
+        (np.array([1, 2, 3], dtype=np.int64),
+         np.array([5, 7, 2], dtype=np.float32),
          None),
         # should fail because attempting to cast
         # two special floating point values
@@ -152,29 +150,33 @@ class TestSetOps(object):
         # specifically, raise an appropriate
         # Exception when attempting to append or
         # prepend with an incompatible type
-        msg = 'cannot convert'
-        with assert_raises_regex(ValueError, msg):
+        msg = 'must be compatible'
+        with assert_raises_regex(TypeError, msg):
             ediff1d(ary=ary,
                     to_end=append,
                     to_begin=prepend)
 
-    @pytest.mark.parametrize("ary,"
-                             "prepend,"
-                             "append,"
-                             "expected", [
-        (np.array([1, 2, 3], dtype=np.int16),
-         0,
-         None,
-         np.array([0, 1, 1], dtype=np.int16)),
-        (np.array([1, 2, 3], dtype=np.int32),
-         0,
-         0,
-         np.array([0, 1, 1, 0], dtype=np.int32)),
-        (np.array([1, 2, 3], dtype=np.int64),
-         3,
-         -9,
-         np.array([3, 1, 1, -9], dtype=np.int64)),
-         ])
+    @pytest.mark.parametrize(
+        "ary,prepend,append,expected",
+        [
+         (np.array([1, 2, 3], dtype=np.int16),
+          2**16,  # will be cast to int16 under same kind rule.
+          2**16 + 4,
+          np.array([0, 1, 1, 4], dtype=np.int16)),
+         (np.array([1, 2, 3], dtype=np.float32),
+          np.array([5], dtype=np.float64),
+          None,
+          np.array([5, 1, 1], dtype=np.float32)),
+         (np.array([1, 2, 3], dtype=np.int32),
+          0,
+          0,
+          np.array([0, 1, 1, 0], dtype=np.int32)),
+         (np.array([1, 2, 3], dtype=np.int64),
+          3,
+          -9,
+          np.array([3, 1, 1, -9], dtype=np.int64)),
+        ]
+    )
     def test_ediff1d_scalar_handling(self,
                                      ary,
                                      prepend,
@@ -187,7 +189,7 @@ class TestSetOps(object):
                             to_end=append,
                             to_begin=prepend)
         assert_equal(actual, expected)
-
+        assert actual.dtype == expected.dtype
 
     def test_isin(self):
         # the tests for in1d cover most of isin's behavior
@@ -197,33 +199,34 @@ class TestSetOps(object):
             b = np.asarray(b).flatten().tolist()
             return a in b
         isin_slow = np.vectorize(_isin_slow, otypes=[bool], excluded={1})
+
         def assert_isin_equal(a, b):
             x = isin(a, b)
             y = isin_slow(a, b)
             assert_array_equal(x, y)
 
-        #multidimensional arrays in both arguments
+        # multidimensional arrays in both arguments
         a = np.arange(24).reshape([2, 3, 4])
         b = np.array([[10, 20, 30], [0, 1, 3], [11, 22, 33]])
         assert_isin_equal(a, b)
 
-        #array-likes as both arguments
+        # array-likes as both arguments
         c = [(9, 8), (7, 6)]
         d = (9, 7)
         assert_isin_equal(c, d)
 
-        #zero-d array:
+        # zero-d array:
         f = np.array(3)
         assert_isin_equal(f, b)
         assert_isin_equal(a, f)
         assert_isin_equal(f, f)
 
-        #scalar:
+        # scalar:
         assert_isin_equal(5, b)
         assert_isin_equal(a, 6)
         assert_isin_equal(5, 6)
 
-        #empty array-like:
+        # empty array-like:
         x = []
         assert_isin_equal(x, b)
         assert_isin_equal(a, x)
@@ -410,7 +413,7 @@ class TestSetOps(object):
         assert_array_equal(c1, c2)
 
 
-class TestUnique(object):
+class TestUnique:
 
     def test_unique_1d(self):
 
@@ -517,7 +520,8 @@ class TestUnique(object):
         a = []
         a1_idx = np.unique(a, return_index=True)[1]
         a2_inv = np.unique(a, return_inverse=True)[1]
-        a3_idx, a3_inv = np.unique(a, return_index=True, return_inverse=True)[1:]
+        a3_idx, a3_inv = np.unique(a, return_index=True,
+                                   return_inverse=True)[1:]
         assert_equal(a1_idx.dtype, np.intp)
         assert_equal(a2_inv.dtype, np.intp)
         assert_equal(a3_idx.dtype, np.intp)
@@ -560,9 +564,52 @@ class TestUnique(object):
         result = np.array([[-0.0, 0.0]])
         assert_array_equal(unique(data, axis=0), result, msg)
 
+    @pytest.mark.parametrize("axis", [0, -1])
+    def test_unique_1d_with_axis(self, axis):
+        x = np.array([4, 3, 2, 3, 2, 1, 2, 2])
+        uniq = unique(x, axis=axis)
+        assert_array_equal(uniq, [1, 2, 3, 4])
+
+    def test_unique_axis_zeros(self):
+        # issue 15559
+        single_zero = np.empty(shape=(2, 0), dtype=np.int8)
+        uniq, idx, inv, cnt = unique(single_zero, axis=0, return_index=True,
+                                     return_inverse=True, return_counts=True)
+
+        # there's 1 element of shape (0,) along axis 0
+        assert_equal(uniq.dtype, single_zero.dtype)
+        assert_array_equal(uniq, np.empty(shape=(1, 0)))
+        assert_array_equal(idx, np.array([0]))
+        assert_array_equal(inv, np.array([0, 0]))
+        assert_array_equal(cnt, np.array([2]))
+
+        # there's 0 elements of shape (2,) along axis 1
+        uniq, idx, inv, cnt = unique(single_zero, axis=1, return_index=True,
+                                     return_inverse=True, return_counts=True)
+
+        assert_equal(uniq.dtype, single_zero.dtype)
+        assert_array_equal(uniq, np.empty(shape=(2, 0)))
+        assert_array_equal(idx, np.array([]))
+        assert_array_equal(inv, np.array([]))
+        assert_array_equal(cnt, np.array([]))
+
+        # test a "complicated" shape
+        shape = (0, 2, 0, 3, 0, 4, 0)
+        multiple_zeros = np.empty(shape=shape)
+        for axis in range(len(shape)):
+            expected_shape = list(shape)
+            if shape[axis] == 0:
+                expected_shape[axis] = 0
+            else:
+                expected_shape[axis] = 1
+
+            assert_array_equal(unique(multiple_zeros, axis=axis),
+                               np.empty(shape=expected_shape))
+
     def test_unique_masked(self):
         # issue 8664
-        x = np.array([64, 0, 1, 2, 3, 63, 63, 0, 0, 0, 1, 2, 0, 63, 0], dtype='uint8')
+        x = np.array([64, 0, 1, 2, 3, 63, 63, 0, 0, 0, 1, 2, 0, 63, 0],
+                     dtype='uint8')
         y = np.ma.masked_equal(x, 0)
 
         v = np.unique(y)
@@ -577,7 +624,7 @@ class TestUnique(object):
         # as unsigned byte strings.  See gh-10495.
         fmt = "sort order incorrect for integer type '%s'"
         for dt in 'bhilq':
-            a = np.array([[-1],[0]], dt)
+            a = np.array([[-1], [0]], dt)
             b = np.unique(a, axis=0)
             assert_array_equal(a, b, fmt % dt)
 
index 2ce4456a5b5c0210668409fdb3dd1a0a53fd5e8c..c00ed13d7f3076d53ec080a46fe7e13ff7dfb5a2 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from operator import mul
 from functools import reduce
 
index cb67f7c0f621c54564675067895343c9bc74f0ca..26e79bc0618ab632011a87712a94b06b08e39851 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import warnings
 from decimal import Decimal
 
@@ -18,7 +16,7 @@ def filter_deprecation(func):
     return newfunc
 
 
-class TestFinancial(object):
+class TestFinancial:
     @filter_deprecation
     def test_npv_irr_congruence(self):
         # IRR is defined as the rate required for the present value of a
index 0592e0b125924f217902cdcd281031511e33d73f..2dbaeb8cbdbb635aa1880f190a01679baa538633 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 # doctest
 r''' Test the .npy file format.
 
@@ -537,8 +535,10 @@ dt4 = np.dtype({'names': ['a', '', 'b'], 'formats': ['i4']*3})
 # titles
 dt5 = np.dtype({'names': ['a', 'b'], 'formats': ['i4', 'i4'],
                 'offsets': [1, 6], 'titles': ['aa', 'bb']})
+# empty
+dt6 = np.dtype({'names': [], 'formats': [], 'itemsize': 8})
 
-@pytest.mark.parametrize("dt", [dt1, dt2, dt3, dt4, dt5])
+@pytest.mark.parametrize("dt", [dt1, dt2, dt3, dt4, dt5, dt6])
 def test_load_padded_dtype(dt):
     arr = np.zeros(3, dt)
     for i in range(3):
@@ -550,10 +550,7 @@ def test_load_padded_dtype(dt):
 
 
 def test_python2_python3_interoperability():
-    if sys.version_info[0] >= 3:
-        fname = 'win64python2.npy'
-    else:
-        fname = 'python3.npy'
+    fname = 'win64python2.npy'
     path = os.path.join(os.path.dirname(__file__), 'data', fname)
     data = np.load(path)
     assert_array_equal(data, np.ones(2))
@@ -563,13 +560,7 @@ def test_pickle_python2_python3():
     # Python 2 and Python 3 and vice versa
     data_dir = os.path.join(os.path.dirname(__file__), 'data')
 
-    if sys.version_info[0] >= 3:
-        xrange = range
-    else:
-        import __builtin__
-        xrange = __builtin__.xrange
-
-    expected = np.array([None, xrange, u'\u512a\u826f',
+    expected = np.array([None, range, u'\u512a\u826f',
                          b'\xe4\xb8\x8d\xe8\x89\xaf'],
                         dtype=object)
 
@@ -585,34 +576,30 @@ def test_pickle_python2_python3():
             else:
                 data = data_f
 
-            if sys.version_info[0] >= 3:
-                if encoding == 'latin1' and fname.startswith('py2'):
-                    assert_(isinstance(data[3], str))
-                    assert_array_equal(data[:-1], expected[:-1])
-                    # mojibake occurs
-                    assert_array_equal(data[-1].encode(encoding), expected[-1])
-                else:
-                    assert_(isinstance(data[3], bytes))
-                    assert_array_equal(data, expected)
+            if encoding == 'latin1' and fname.startswith('py2'):
+                assert_(isinstance(data[3], str))
+                assert_array_equal(data[:-1], expected[:-1])
+                # mojibake occurs
+                assert_array_equal(data[-1].encode(encoding), expected[-1])
             else:
+                assert_(isinstance(data[3], bytes))
                 assert_array_equal(data, expected)
 
-        if sys.version_info[0] >= 3:
-            if fname.startswith('py2'):
-                if fname.endswith('.npz'):
-                    data = np.load(path, allow_pickle=True)
-                    assert_raises(UnicodeError, data.__getitem__, 'x')
-                    data.close()
-                    data = np.load(path, allow_pickle=True, fix_imports=False,
-                                   encoding='latin1')
-                    assert_raises(ImportError, data.__getitem__, 'x')
-                    data.close()
-                else:
-                    assert_raises(UnicodeError, np.load, path,
-                                  allow_pickle=True)
-                    assert_raises(ImportError, np.load, path,
-                                  allow_pickle=True, fix_imports=False,
-                                  encoding='latin1')
+        if fname.startswith('py2'):
+            if fname.endswith('.npz'):
+                data = np.load(path, allow_pickle=True)
+                assert_raises(UnicodeError, data.__getitem__, 'x')
+                data.close()
+                data = np.load(path, allow_pickle=True, fix_imports=False,
+                               encoding='latin1')
+                assert_raises(ImportError, data.__getitem__, 'x')
+                data.close()
+            else:
+                assert_raises(UnicodeError, np.load, path,
+                              allow_pickle=True)
+                assert_raises(ImportError, np.load, path,
+                              allow_pickle=True, fix_imports=False,
+                              encoding='latin1')
 
 
 def test_pickle_disallow():
index d5d62a8d12d3a96a16ca21b5a79369356b9620ce..b26da29c624598b81ca734774931b87d85214419 100644 (file)
@@ -1,11 +1,9 @@
-from __future__ import division, absolute_import, print_function
-
 import operator
 import warnings
 import sys
 import decimal
-import types
 from fractions import Fraction
+import math
 import pytest
 
 import numpy as np
@@ -24,9 +22,6 @@ from numpy.lib import (
     select, setxor1d, sinc, trapz, trim_zeros, unwrap, unique, vectorize
     )
 
-from numpy.compat import long
-
-PY2 = sys.version_info[0] == 2
 
 def get_mat(n):
     data = np.arange(n)
@@ -45,7 +40,7 @@ def _make_complex(real, imag):
     return ret
 
 
-class TestRot90(object):
+class TestRot90:
     def test_basic(self):
         assert_raises(ValueError, rot90, np.ones(4))
         assert_raises(ValueError, rot90, np.ones((2,2,2)), axes=(0,1,2))
@@ -113,7 +108,7 @@ class TestRot90(object):
                          rot90(a_rot90_20, k=k-1, axes=(2, 0)))
 
 
-class TestFlip(object):
+class TestFlip:
 
     def test_axes(self):
         assert_raises(np.AxisError, np.flip, np.ones(4), axis=1)
@@ -216,7 +211,7 @@ class TestFlip(object):
         assert_equal(np.flip(a, axis=(1, 2)), c)
 
 
-class TestAny(object):
+class TestAny:
 
     def test_basic(self):
         y1 = [0, 0, 1, 0]
@@ -233,7 +228,7 @@ class TestAny(object):
         assert_array_equal(np.sometrue(y1, axis=1), [0, 1, 1])
 
 
-class TestAll(object):
+class TestAll:
 
     def test_basic(self):
         y1 = [0, 1, 1, 0]
@@ -251,7 +246,7 @@ class TestAll(object):
         assert_array_equal(np.alltrue(y1, axis=1), [0, 0, 1])
 
 
-class TestCopy(object):
+class TestCopy:
 
     def test_basic(self):
         a = np.array([[1, 2], [3, 4]])
@@ -278,8 +273,15 @@ class TestCopy(object):
         assert_(not a_fort_copy.flags.c_contiguous)
         assert_(a_fort_copy.flags.f_contiguous)
 
+    def test_subok(self):
+        mx = ma.ones(5)
+        assert_(not ma.isMaskedArray(np.copy(mx, subok=False)))
+        assert_(ma.isMaskedArray(np.copy(mx, subok=True)))
+        # Default behavior
+        assert_(not ma.isMaskedArray(np.copy(mx)))
 
-class TestAverage(object):
+
+class TestAverage:
 
     def test_basic(self):
         y1 = np.array([1, 2, 3])
@@ -380,7 +382,7 @@ class TestAverage(object):
         w /= w.sum()
         assert_almost_equal(a.mean(0), average(a, weights=w))
 
-class TestSelect(object):
+class TestSelect:
     choices = [np.array([1, 2, 3]),
                np.array([4, 5, 6]),
                np.array([7, 8, 9])]
@@ -442,7 +444,7 @@ class TestSelect(object):
         select(conditions, choices)
 
 
-class TestInsert(object):
+class TestInsert:
 
     def test_basic(self):
         a = [1, 2, 3]
@@ -507,12 +509,11 @@ class TestInsert(object):
                      insert(a, 1, a[:, 2, :], axis=1))
 
     def test_0d(self):
-        # This is an error in the future
         a = np.array(1)
-        with warnings.catch_warnings(record=True) as w:
-            warnings.filterwarnings('always', '', DeprecationWarning)
-            assert_equal(insert(a, [], 2, axis=0), np.array(2))
-            assert_(w[0].category is DeprecationWarning)
+        with pytest.raises(np.AxisError):
+            insert(a, [], 2, axis=0)
+        with pytest.raises(TypeError):
+            insert(a, [], 2, axis="nonsense")
 
     def test_subclass(self):
         class SubClass(np.ndarray):
@@ -542,8 +543,14 @@ class TestInsert(object):
         b = np.insert(a, [0, 2], val)
         assert_array_equal(b[[0, 3]], np.array(val, dtype=b.dtype))
 
+    def test_index_floats(self):
+        with pytest.raises(IndexError):
+            np.insert([0, 1, 2], np.array([1.0, 2.0]), [10, 20])
+        with pytest.raises(IndexError):
+            np.insert([0, 1, 2], np.array([], dtype=float), [])
 
-class TestAmax(object):
+
+class TestAmax:
 
     def test_basic(self):
         a = [3, 4, 5, 10, -3, -5, 6.0]
@@ -555,7 +562,7 @@ class TestAmax(object):
         assert_equal(np.amax(b, axis=1), [9.0, 10.0, 8.0])
 
 
-class TestAmin(object):
+class TestAmin:
 
     def test_basic(self):
         a = [3, 4, 5, 10, -3, -5, 6.0]
@@ -567,7 +574,7 @@ class TestAmin(object):
         assert_equal(np.amin(b, axis=1), [3.0, 4.0, 2.0])
 
 
-class TestPtp(object):
+class TestPtp:
 
     def test_basic(self):
         a = np.array([3, 4, 5, 10, -3, -5, 6.0])
@@ -582,7 +589,7 @@ class TestPtp(object):
         assert_equal(b.ptp(axis=(0,1), keepdims=True), [[8.0]])
 
 
-class TestCumsum(object):
+class TestCumsum:
 
     def test_basic(self):
         ba = [1, 2, 10, 11, 6, 5, 4]
@@ -605,7 +612,7 @@ class TestCumsum(object):
             assert_array_equal(np.cumsum(a2, axis=1), tgt)
 
 
-class TestProd(object):
+class TestProd:
 
     def test_basic(self):
         ba = [1, 2, 10, 11, 6, 5, 4]
@@ -625,7 +632,7 @@ class TestProd(object):
                                    np.array([24, 1890, 600], ctype))
 
 
-class TestCumprod(object):
+class TestCumprod:
 
     def test_basic(self):
         ba = [1, 2, 10, 11, 6, 5, 4]
@@ -652,7 +659,7 @@ class TestCumprod(object):
                                              [10, 30, 120, 600]], ctype))
 
 
-class TestDiff(object):
+class TestDiff:
 
     def test_basic(self):
         x = [1, 4, 6, 7, 12]
@@ -792,7 +799,7 @@ class TestDiff(object):
         assert_raises(np.AxisError, diff, x, append=0, axis=3)
 
 
-class TestDelete(object):
+class TestDelete:
 
     def setup(self):
         self.a = np.arange(5)
@@ -802,10 +809,6 @@ class TestDelete(object):
         a_del = delete(self.a, indices)
         nd_a_del = delete(self.nd_a, indices, axis=1)
         msg = 'Delete failed for obj: %r' % indices
-        # NOTE: The cast should be removed after warning phase for bools
-        if not isinstance(indices, (slice, int, long, np.integer)):
-            indices = np.asarray(indices, dtype=np.intp)
-            indices = indices[(indices >= 0) & (indices < 5)]
         assert_array_equal(setxor1d(a_del, self.a[indices, ]), self.a,
                            err_msg=msg)
         xor = setxor1d(nd_a_del[0,:, 0], self.nd_a[0, indices, 0])
@@ -821,19 +824,25 @@ class TestDelete(object):
                     self._check_inverse_of_slicing(s)
 
     def test_fancy(self):
-        # Deprecation/FutureWarning tests should be kept after change.
         self._check_inverse_of_slicing(np.array([[0, 1], [2, 1]]))
-        with warnings.catch_warnings():
-            warnings.filterwarnings('error', category=DeprecationWarning)
-            assert_raises(DeprecationWarning, delete, self.a, [100])
-            assert_raises(DeprecationWarning, delete, self.a, [-100])
-        with warnings.catch_warnings(record=True) as w:
-            warnings.filterwarnings('always', category=FutureWarning)
-            self._check_inverse_of_slicing([0, -1, 2, 2])
-            obj = np.array([True, False, False], dtype=bool)
-            self._check_inverse_of_slicing(obj)
-            assert_(w[0].category is FutureWarning)
-            assert_(w[1].category is FutureWarning)
+        with pytest.raises(IndexError):
+            delete(self.a, [100])
+        with pytest.raises(IndexError):
+            delete(self.a, [-100])
+
+        self._check_inverse_of_slicing([0, -1, 2, 2])
+
+        self._check_inverse_of_slicing([True, False, False, True, False])
+
+        # not legal, indexing with these would change the dimension
+        with pytest.raises(ValueError):
+            delete(self.a, True)
+        with pytest.raises(ValueError):
+            delete(self.a, False)
+
+        # not enough items
+        with pytest.raises(ValueError):
+            delete(self.a, [False]*4)
 
     def test_single(self):
         self._check_inverse_of_slicing(0)
@@ -841,10 +850,10 @@ class TestDelete(object):
 
     def test_0d(self):
         a = np.array(1)
-        with warnings.catch_warnings(record=True) as w:
-            warnings.filterwarnings('always', '', DeprecationWarning)
-            assert_equal(delete(a, [], axis=0), a)
-            assert_(w[0].category is DeprecationWarning)
+        with pytest.raises(np.AxisError):
+            delete(a, [], axis=0)
+        with pytest.raises(TypeError):
+            delete(a, [], axis="nonsense")
 
     def test_subclass(self):
         class SubClass(np.ndarray):
@@ -866,8 +875,14 @@ class TestDelete(object):
         assert_equal(m.flags.c_contiguous, k.flags.c_contiguous)
         assert_equal(m.flags.f_contiguous, k.flags.f_contiguous)
 
+    def test_index_floats(self):
+        with pytest.raises(IndexError):
+            np.delete([0, 1, 2], np.array([1.0, 2.0]))
+        with pytest.raises(IndexError):
+            np.delete([0, 1, 2], np.array([], dtype=float))
 
-class TestGradient(object):
+
+class TestGradient:
 
     def test_basic(self):
         v = [[1, 1], [3, 4]]
@@ -1119,7 +1134,7 @@ class TestGradient(object):
         assert_array_equal(dfdx, [0.5, 0.5])
 
 
-class TestAngle(object):
+class TestAngle:
 
     def test_basic(self):
         x = [1 + 3j, np.sqrt(2) / 2.0 + 1j * np.sqrt(2) / 2,
@@ -1145,7 +1160,7 @@ class TestAngle(object):
         assert_equal(actual, expected)
 
 
-class TestTrimZeros(object):
+class TestTrimZeros:
 
     """
     Only testing for integer splits.
@@ -1168,7 +1183,7 @@ class TestTrimZeros(object):
         assert_array_equal(res, np.array([1, 0, 2, 3, 0, 4]))
 
 
-class TestExtins(object):
+class TestExtins:
 
     def test_basic(self):
         a = np.array([1, 3, 2, 1, 2, 3, 3])
@@ -1207,7 +1222,17 @@ class TestExtins(object):
         assert_array_equal(a, ac)
 
 
-class TestVectorize(object):
+# _foo1 and _foo2 are used in some tests in TestVectorize.
+
+def _foo1(x, y=1.0):
+    return y*math.floor(x)
+
+
+def _foo2(x, y=1.0, z=0.0):
+    return y*math.floor(x) + z
+
+
+class TestVectorize:
 
     def test_simple(self):
         def addsubtract(a, b):
@@ -1238,7 +1263,6 @@ class TestVectorize(object):
         assert_array_equal(y, x)
 
     def test_ufunc(self):
-        import math
         f = vectorize(math.cos)
         args = np.array([0, 0.5 * np.pi, np.pi, 1.5 * np.pi, 2 * np.pi])
         r1 = f(args)
@@ -1259,6 +1283,63 @@ class TestVectorize(object):
         r2 = np.array([3, 4, 5])
         assert_array_equal(r1, r2)
 
+    def test_keywords_with_otypes_order1(self):
+        # gh-1620: The second call of f would crash with
+        # `ValueError: invalid number of arguments`.
+        f = vectorize(_foo1, otypes=[float])
+        # We're testing the caching of ufuncs by vectorize, so the order
+        # of these function calls is an important part of the test.
+        r1 = f(np.arange(3.0), 1.0)
+        r2 = f(np.arange(3.0))
+        assert_array_equal(r1, r2)
+
+    def test_keywords_with_otypes_order2(self):
+        # gh-1620: The second call of f would crash with
+        # `ValueError: non-broadcastable output operand with shape ()
+        # doesn't match the broadcast shape (3,)`.
+        f = vectorize(_foo1, otypes=[float])
+        # We're testing the caching of ufuncs by vectorize, so the order
+        # of these function calls is an important part of the test.
+        r1 = f(np.arange(3.0))
+        r2 = f(np.arange(3.0), 1.0)
+        assert_array_equal(r1, r2)
+
+    def test_keywords_with_otypes_order3(self):
+        # gh-1620: The third call of f would crash with
+        # `ValueError: invalid number of arguments`.
+        f = vectorize(_foo1, otypes=[float])
+        # We're testing the caching of ufuncs by vectorize, so the order
+        # of these function calls is an important part of the test.
+        r1 = f(np.arange(3.0))
+        r2 = f(np.arange(3.0), y=1.0)
+        r3 = f(np.arange(3.0))
+        assert_array_equal(r1, r2)
+        assert_array_equal(r1, r3)
+
+    def test_keywords_with_otypes_several_kwd_args1(self):
+        # gh-1620 Make sure different uses of keyword arguments
+        # don't break the vectorized function.
+        f = vectorize(_foo2, otypes=[float])
+        # We're testing the caching of ufuncs by vectorize, so the order
+        # of these function calls is an important part of the test.
+        r1 = f(10.4, z=100)
+        r2 = f(10.4, y=-1)
+        r3 = f(10.4)
+        assert_equal(r1, _foo2(10.4, z=100))
+        assert_equal(r2, _foo2(10.4, y=-1))
+        assert_equal(r3, _foo2(10.4))
+
+    def test_keywords_with_otypes_several_kwd_args2(self):
+        # gh-1620 Make sure different uses of keyword arguments
+        # don't break the vectorized function.
+        f = vectorize(_foo2, otypes=[float])
+        # We're testing the caching of ufuncs by vectorize, so the order
+        # of these function calls is an important part of the test.
+        r1 = f(z=100, x=10.4, y=-1)
+        r2 = f(1, 2, 3)
+        assert_equal(r1, _foo2(z=100, x=10.4, y=-1))
+        assert_equal(r2, _foo2(1, 2, 3))
+
     def test_keywords_no_func_code(self):
         # This needs to test a function that has keywords but
         # no func_code attribute, since otherwise vectorize will
@@ -1539,8 +1620,8 @@ class TestVectorize(object):
             f(x)
 
 
-class TestLeaks(object):
-    class A(object):
+class TestLeaks:
+    class A:
         iters = 20
 
         def bound(self, *args):
@@ -1571,18 +1652,15 @@ class TestLeaks(object):
                 a.f = np.frompyfunc(getattr(a, name), 1, 1)
                 out = a.f(np.arange(10))
             a = None
-            if PY2:
-                assert_equal(sys.getrefcount(A_func), refcount)
-            else:
-                # A.func is part of a reference cycle if incr is non-zero
-                assert_equal(sys.getrefcount(A_func), refcount + incr)
+            # A.func is part of a reference cycle if incr is non-zero
+            assert_equal(sys.getrefcount(A_func), refcount + incr)
             for i in range(5):
                 gc.collect()
             assert_equal(sys.getrefcount(A_func), refcount)
         finally:
             gc.enable()
 
-class TestDigitize(object):
+class TestDigitize:
 
     def test_forward(self):
         x = np.arange(-6, 5)
@@ -1667,7 +1745,7 @@ class TestDigitize(object):
         assert_equal(np.digitize(x, [x + 1, x - 1]), 1)
 
 
-class TestUnwrap(object):
+class TestUnwrap:
 
     def test_simple(self):
         # check that unwrap removes jumps greater that 2*pi
@@ -1676,7 +1754,7 @@ class TestUnwrap(object):
         assert_(np.all(diff(unwrap(rand(10) * 100)) < np.pi))
 
 
-class TestFilterwindows(object):
+class TestFilterwindows:
 
     def test_hanning(self):
         # check symmetry
@@ -1707,7 +1785,7 @@ class TestFilterwindows(object):
         assert_almost_equal(np.sum(w, axis=0), 3.7800, 4)
 
 
-class TestTrapz(object):
+class TestTrapz:
 
     def test_simple(self):
         x = np.arange(-10, 10, .1)
@@ -1769,7 +1847,7 @@ class TestTrapz(object):
         assert_almost_equal(trapz(y, xm), r)
 
 
-class TestSinc(object):
+class TestSinc:
 
     def test_simple(self):
         assert_(sinc(0) == 1)
@@ -1786,7 +1864,7 @@ class TestSinc(object):
         assert_array_equal(y1, y3)
 
 
-class TestUnique(object):
+class TestUnique:
 
     def test_simple(self):
         x = np.array([4, 3, 2, 1, 1, 2, 3, 4, 0])
@@ -1798,7 +1876,7 @@ class TestUnique(object):
         assert_(np.all(unique(x) == [1 + 1j, 1 + 10j, 5 + 6j, 10]))
 
 
-class TestCheckFinite(object):
+class TestCheckFinite:
 
     def test_simple(self):
         a = [1, 2, 3]
@@ -1815,7 +1893,7 @@ class TestCheckFinite(object):
         assert_(a.dtype == np.float64)
 
 
-class TestCorrCoef(object):
+class TestCorrCoef:
     A = np.array(
         [[0.15391142, 0.18045767, 0.14197213],
          [0.70461506, 0.96474128, 0.27906989],
@@ -1900,14 +1978,14 @@ class TestCorrCoef(object):
         assert_(np.all(np.abs(c) <= 1.0))
 
 
-class TestCov(object):
+class TestCov:
     x1 = np.array([[0, 2], [1, 1], [2, 0]]).T
     res1 = np.array([[1., -1.], [-1., 1.]])
     x2 = np.array([0.0, 1.0, 2.0], ndmin=2)
     frequencies = np.array([1, 4, 1])
     x2_repeats = np.array([[0.0], [1.0], [1.0], [1.0], [1.0], [2.0]]).T
     res2 = np.array([[0.4, -0.4], [-0.4, 0.4]])
-    unit_frequencies = np.ones(3, dtype=np.integer)
+    unit_frequencies = np.ones(3, dtype=np.int_)
     weights = np.array([1.0, 4.0, 1.0])
     res3 = np.array([[2. / 3., -2. / 3.], [-2. / 3., 2. / 3.]])
     unit_weights = np.ones(3)
@@ -1960,11 +2038,11 @@ class TestCov(object):
                         self.res1)
         nonint = self.frequencies + 0.5
         assert_raises(TypeError, cov, self.x1, fweights=nonint)
-        f = np.ones((2, 3), dtype=np.integer)
+        f = np.ones((2, 3), dtype=np.int_)
         assert_raises(RuntimeError, cov, self.x1, fweights=f)
-        f = np.ones(2, dtype=np.integer)
+        f = np.ones(2, dtype=np.int_)
         assert_raises(RuntimeError, cov, self.x1, fweights=f)
-        f = -1 * np.ones(3, dtype=np.integer)
+        f = -1 * np.ones(3, dtype=np.int_)
         assert_raises(ValueError, cov, self.x1, fweights=f)
 
     def test_aweights(self):
@@ -2000,7 +2078,7 @@ class TestCov(object):
                         self.res1)
 
 
-class Test_I0(object):
+class Test_I0:
 
     def test_simple(self):
         assert_almost_equal(
@@ -2046,7 +2124,7 @@ class Test_I0(object):
         assert_array_equal(exp, res)
 
 
-class TestKaiser(object):
+class TestKaiser:
 
     def test_simple(self):
         assert_(np.isfinite(kaiser(1, 1.0)))
@@ -2065,7 +2143,7 @@ class TestKaiser(object):
         kaiser(3, 4)
 
 
-class TestMsort(object):
+class TestMsort:
 
     def test_simple(self):
         A = np.array([[0.44567325, 0.79115165, 0.54900530],
@@ -2078,7 +2156,7 @@ class TestMsort(object):
                       [0.64864341, 0.79115165, 0.96098397]]))
 
 
-class TestMeshgrid(object):
+class TestMeshgrid:
 
     def test_simple(self):
         [X, Y] = meshgrid([1, 2, 3], [4, 5, 6, 7])
@@ -2167,7 +2245,7 @@ class TestMeshgrid(object):
         assert_equal(x[1, :], X)
 
 
-class TestPiecewise(object):
+class TestPiecewise:
 
     def test_simple(self):
         # Condition is single bool list
@@ -2259,7 +2337,7 @@ class TestPiecewise(object):
                                         [3., 3., 1.]]))
 
 
-class TestBincount(object):
+class TestBincount:
 
     def test_simple(self):
         y = np.bincount(np.arange(4))
@@ -2345,8 +2423,17 @@ class TestBincount(object):
         assert_equal(sys.getrefcount(np.dtype(np.intp)), intp_refcount)
         assert_equal(sys.getrefcount(np.dtype(np.double)), double_refcount)
 
+    @pytest.mark.parametrize("vals", [[[2, 2]], 2])
+    def test_error_not_1d(self, vals):
+        # Test that values has to be 1-D (both as array and nested list)
+        vals_arr = np.asarray(vals)
+        with assert_raises(ValueError):
+            np.bincount(vals_arr)
+        with assert_raises(ValueError):
+            np.bincount(vals)
+
 
-class TestInterp(object):
+class TestInterp:
 
     def test_exceptions(self):
         assert_raises(ValueError, interp, 0, [], [])
@@ -2545,7 +2632,7 @@ def compare_results(res, desired):
         assert_array_equal(res[i], desired[i])
 
 
-class TestPercentile(object):
+class TestPercentile:
 
     def test_basic(self):
         x = np.arange(8) * 0.5
@@ -2966,7 +3053,7 @@ class TestPercentile(object):
             a, [0.3, 0.6], (0, 2), interpolation='nearest'), b)
 
 
-class TestQuantile(object):
+class TestQuantile:
     # most of this is already tested by TestPercentile
 
     def test_basic(self):
@@ -2975,6 +3062,16 @@ class TestQuantile(object):
         assert_equal(np.quantile(x, 1), 3.5)
         assert_equal(np.quantile(x, 0.5), 1.75)
 
+    def test_correct_quantile_value(self):
+        a = np.array([True])
+        tf_quant = np.quantile(True, False)
+        assert_equal(tf_quant, a[0])
+        assert_equal(type(tf_quant), a.dtype)
+        a = np.array([False, True, True])
+        quant_res = np.quantile(a, a)
+        assert_array_equal(quant_res, a)
+        assert_equal(a.dtype, quant_res.dtype)
+
     def test_fraction(self):
         # fractional input, integral quantile
         x = [Fraction(i, 2) for i in range(8)]
@@ -3008,7 +3105,7 @@ class TestQuantile(object):
         assert_array_equal(p, p0)
 
 
-class TestMedian(object):
+class TestMedian:
 
     def test_basic(self):
         a0 = np.array(1)
@@ -3247,7 +3344,7 @@ class TestMedian(object):
                      (1, 1, 7, 1))
 
 
-class TestAdd_newdoc_ufunc(object):
+class TestAdd_newdoc_ufunc:
 
     def test_ufunc_arg(self):
         assert_raises(TypeError, add_newdoc_ufunc, 2, "blah")
@@ -3257,7 +3354,7 @@ class TestAdd_newdoc_ufunc(object):
         assert_raises(TypeError, add_newdoc_ufunc, np.add, 3)
 
 
-class TestAdd_newdoc(object):
+class TestAdd_newdoc:
 
     @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO")
     @pytest.mark.xfail(IS_PYPY, reason="PyPy does not modify tp_doc")
@@ -3268,7 +3365,7 @@ class TestAdd_newdoc(object):
         assert_(len(np.core.ufunc.identity.__doc__) > 300)
         assert_(len(np.lib.index_tricks.mgrid.__doc__) > 300)
 
-class TestSortComplex(object):
+class TestSortComplex:
 
     @pytest.mark.parametrize("type_in, type_out", [
         ('l', 'D'),
index dbf189f3e5e141f28a6a7f51e133edaf6565d48b..fc16b73967932c07da57bfa22caa06ea8ae36921 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 
 from numpy.lib.histograms import histogram, histogramdd, histogram_bin_edges
@@ -11,7 +9,7 @@ from numpy.testing import (
 import pytest
 
 
-class TestHistogram(object):
+class TestHistogram:
 
     def setup(self):
         pass
@@ -83,7 +81,7 @@ class TestHistogram(object):
         a, b = histogram(v, bins, density=False)
         assert_array_equal(a, [1, 2, 3, 4])
 
-        # Variale bin widths are especially useful to deal with
+        # Variable bin widths are especially useful to deal with
         # infinities.
         v = np.arange(10)
         bins = [0, 1, 3, 6, np.inf]
@@ -424,7 +422,7 @@ class TestHistogram(object):
         assert_array_equal(edges, e)
 
 
-class TestHistogramOptimBinNums(object):
+class TestHistogramOptimBinNums:
     """
     Provide test coverage when using provided estimators for optimal number of
     bins
@@ -612,7 +610,7 @@ class TestHistogramOptimBinNums(object):
                           estimator, weights=[1, 2, 3])
 
 
-class TestHistogramdd(object):
+class TestHistogramdd:
 
     def test_simple(self):
         x = np.array([[-.5, .5, 1.5], [-.5, 1.5, 2.5], [-.5, 2.5, .5],
index dbe445c2c37d3302e3e8e83d93ecb4c72a5f46ac..905165a99b890b980c64f694a0ff1caebb09c24d 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import pytest
 
 import numpy as np
@@ -14,7 +12,7 @@ from numpy.lib.index_tricks import (
     )
 
 
-class TestRavelUnravelIndex(object):
+class TestRavelUnravelIndex:
     def test_basic(self):
         assert_equal(np.unravel_index(2, (2, 2)), (1, 0))
 
@@ -194,7 +192,7 @@ class TestRavelUnravelIndex(object):
         with assert_raises(ValueError):
             np.unravel_index([1], (2, 1, 0))
 
-class TestGrid(object):
+class TestGrid:
     def test_basic(self):
         a = mgrid[-1:1:10j]
         b = mgrid[-1:1:0.1]
@@ -252,7 +250,7 @@ class TestGrid(object):
         assert_equal(grid_small.size, expected[1])
 
 
-class TestConcatenator(object):
+class TestConcatenator:
     def test_1d(self):
         assert_array_equal(r_[1, 2, 3, 4, 5, 6], np.array([1, 2, 3, 4, 5, 6]))
         b = np.ones(5)
@@ -290,14 +288,14 @@ class TestConcatenator(object):
         assert_equal(r_[np.array(0), [1, 2, 3]], [0, 1, 2, 3])
 
 
-class TestNdenumerate(object):
+class TestNdenumerate:
     def test_basic(self):
         a = np.array([[1, 2], [3, 4]])
         assert_equal(list(ndenumerate(a)),
                      [((0, 0), 1), ((0, 1), 2), ((1, 0), 3), ((1, 1), 4)])
 
 
-class TestIndexExpression(object):
+class TestIndexExpression:
     def test_regression_1(self):
         # ticket #1196
         a = np.arange(2)
@@ -311,7 +309,7 @@ class TestIndexExpression(object):
         assert_equal(a[:, :3, [1, 2]], a[s_[:, :3, [1, 2]]])
 
 
-class TestIx_(object):
+class TestIx_:
     def test_regression_1(self):
         # Test empty untyped inputs create outputs of indexing type, gh-5804
         a, = np.ix_(range(0))
@@ -358,7 +356,7 @@ def test_c_():
     assert_equal(a, [[1, 2, 3, 0, 0, 4, 5, 6]])
 
 
-class TestFillDiagonal(object):
+class TestFillDiagonal:
     def test_basic(self):
         a = np.zeros((3, 3), int)
         fill_diagonal(a, 5)
@@ -457,7 +455,7 @@ def test_diag_indices():
         )
 
 
-class TestDiagIndicesFrom(object):
+class TestDiagIndicesFrom:
 
     def test_diag_indices_from(self):
         x = np.random.random((4, 4))
index a095e250af052a582f070d087a10d0afde552f86..9abde3e11f6b491204dc3461bcd3ca44bd19cbf5 100644 (file)
@@ -1,6 +1,5 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
+import gc
 import gzip
 import os
 import threading
@@ -9,15 +8,17 @@ import warnings
 import io
 import re
 import pytest
+from pathlib import Path
 from tempfile import NamedTemporaryFile
 from io import BytesIO, StringIO
 from datetime import datetime
 import locale
+from multiprocessing import Process
 
 import numpy as np
 import numpy.ma as ma
 from numpy.lib._iotools import ConverterError, ConversionWarning
-from numpy.compat import asbytes, bytes, Path
+from numpy.compat import asbytes, bytes
 from numpy.ma.testutils import assert_equal
 from numpy.testing import (
     assert_warns, assert_, assert_raises_regex, assert_raises,
@@ -46,7 +47,6 @@ class TextIO(BytesIO):
         BytesIO.writelines(self, [asbytes(s) for s in lines])
 
 
-MAJVER, MINVER = sys.version_info[:2]
 IS_64BIT = sys.maxsize > 2**32
 try:
     import bz2
@@ -71,7 +71,7 @@ def strptime(s, fmt=None):
     return datetime(*time.strptime(s, fmt)[:3])
 
 
-class RoundtripTest(object):
+class RoundtripTest:
     def roundtrip(self, save_func, *args, **kwargs):
         """
         save_func : callable
@@ -278,8 +278,7 @@ class TestSavezLoad(RoundtripTest):
                 fp.seek(0)
                 assert_(not fp.closed)
 
-    #FIXME: Is this still true?
-    @pytest.mark.skipif(IS_PYPY, reason="Missing context manager on PyPy")
+    @pytest.mark.slow_pypy
     def test_closing_fid(self):
         # Test that issue #1517 (too many opened files) remains closed
         # It might be a "weak" test since failed to get triggered on
@@ -292,17 +291,18 @@ class TestSavezLoad(RoundtripTest):
             # numpy npz file returned by np.load when their reference count
             # goes to zero.  Python 3 running in debug mode raises a
             # ResourceWarning when file closing is left to the garbage
-            # collector, so we catch the warnings.  Because ResourceWarning
-            # is unknown in Python < 3.x, we take the easy way out and
-            # catch all warnings.
+            # collector, so we catch the warnings.
             with suppress_warnings() as sup:
-                sup.filter(Warning)  # TODO: specify exact message
+                sup.filter(ResourceWarning)  # TODO: specify exact message
                 for i in range(1, 1025):
                     try:
                         np.load(tmp)["data"]
                     except Exception as e:
                         msg = "Failed to load data from a file: %s" % e
                         raise AssertionError(msg)
+                    finally:
+                        if IS_PYPY:
+                            gc.collect()
 
     def test_closing_zipfile_after_load(self):
         # Check that zipfile owns file and can close it.  This needs to
@@ -318,7 +318,7 @@ class TestSavezLoad(RoundtripTest):
             assert_(fp.closed)
 
 
-class TestSaveTxt(object):
+class TestSaveTxt:
     def test_array(self):
         a = np.array([[1, 2], [3, 4]], float)
         fmt = "%.18e"
@@ -365,7 +365,6 @@ class TestSaveTxt(object):
         c.seek(0)
         assert_equal(c.readlines(), [b'1 3\n', b'4 6\n'])
 
-    @pytest.mark.skipif(Path is None, reason="No pathlib.Path")
     def test_multifield_view(self):
         a = np.ones(1, dtype=[('x', 'i4'), ('y', 'i4'), ('z', 'f4')])
         v = a[['x', 'z']]
@@ -530,12 +529,10 @@ class TestSaveTxt(object):
         a = np.array([utf8], dtype=np.unicode_)
         # our gz wrapper support encoding
         suffixes = ['', '.gz']
-        # stdlib 2 versions do not support encoding
-        if MAJVER > 2:
-            if HAS_BZ2:
-                suffixes.append('.bz2')
-            if HAS_LZMA:
-                suffixes.extend(['.xz', '.lzma'])
+        if HAS_BZ2:
+            suffixes.append('.bz2')
+        if HAS_LZMA:
+            suffixes.extend(['.xz', '.lzma'])
         with tempdir() as tmpdir:
             for suffix in suffixes:
                 np.savetxt(os.path.join(tmpdir, 'test.csv' + suffix), a,
@@ -573,18 +570,23 @@ class TestSaveTxt(object):
         else:
             assert_equal(s.read(), b"%f\n" % 1.)
 
-    @pytest.mark.skipif(sys.platform=='win32',
-                        reason="large files cause problems")
+    @pytest.mark.skipif(sys.platform=='win32', reason="files>4GB may not work")
     @pytest.mark.slow
     @requires_memory(free_bytes=7e9)
     def test_large_zip(self):
-        # The test takes at least 6GB of memory, writes a file larger than 4GB
-        test_data = np.asarray([np.random.rand(np.random.randint(50,100),4)
-                               for i in range(800000)])
-        with tempdir() as tmpdir:
-            np.savez(os.path.join(tmpdir, 'test.npz'), test_data=test_data)
-
-class LoadTxtBase(object):
+        def check_large_zip():
+            # The test takes at least 6GB of memory, writes a file larger than 4GB
+            test_data = np.asarray([np.random.rand(np.random.randint(50,100),4)
+                                   for i in range(800000)], dtype=object)
+            with tempdir() as tmpdir:
+                np.savez(os.path.join(tmpdir, 'test.npz'), test_data=test_data)
+        # run in a subprocess to ensure memory is released on PyPy, see gh-15775
+        p = Process(target=check_large_zip)
+        p.start()
+        p.join()
+        assert p.exitcode == 0
+
+class LoadTxtBase:
     def check_compressed(self, fopen, suffixes):
         # Test that we can load data from a compressed file
         wanted = np.arange(6).reshape((2, 3))
@@ -601,18 +603,14 @@ class LoadTxtBase(object):
                         res = self.loadfunc(f)
                     assert_array_equal(res, wanted)
 
-    # Python2 .open does not support encoding
-    @pytest.mark.skipif(MAJVER == 2, reason="Needs Python version >= 3")
     def test_compressed_gzip(self):
         self.check_compressed(gzip.open, ('.gz',))
 
     @pytest.mark.skipif(not HAS_BZ2, reason="Needs bz2")
-    @pytest.mark.skipif(MAJVER == 2, reason="Needs Python version >= 3")
     def test_compressed_bz2(self):
         self.check_compressed(bz2.open, ('.bz2',))
 
     @pytest.mark.skipif(not HAS_LZMA, reason="Needs lzma")
-    @pytest.mark.skipif(MAJVER == 2, reason="Needs Python version >= 3")
     def test_compressed_lzma(self):
         self.check_compressed(lzma.open, ('.xz', '.lzma'))
 
@@ -826,7 +824,7 @@ class TestLoadTxt(LoadTxtBase):
             assert_array_equal(x, a[:, 1])
 
         # Testing with some crazy custom integer type
-        class CrazyInt(object):
+        class CrazyInt:
             def __index__(self):
                 return 1
 
@@ -1158,7 +1156,7 @@ class TestLoadTxt(LoadTxtBase):
         a = np.array([[1, 2, 3, 5], [4, 5, 7, 8], [2, 1, 4, 5]], int)
         assert_array_equal(x, a)
 
-class Testfromregex(object):
+class Testfromregex:
     def test_record(self):
         c = TextIO()
         c.write('1.312 foo\n1.534 bar\n4.444 qux')
@@ -2341,15 +2339,14 @@ M   33  21.99
 
         assert_(test.dtype['f0'] == float)
         assert_(test.dtype['f1'] == np.int64)
-        assert_(test.dtype['f2'] == np.integer)
+        assert_(test.dtype['f2'] == np.int_)
 
         assert_allclose(test['f0'], 73786976294838206464.)
         assert_equal(test['f1'], 17179869184)
         assert_equal(test['f2'], 1024)
 
 
-@pytest.mark.skipif(Path is None, reason="No pathlib.Path")
-class TestPathUsage(object):
+class TestPathUsage:
     # Test that pathlib.Path can be used
     def test_loadtxt(self):
         with temppath(suffix='.txt') as path:
@@ -2482,7 +2479,7 @@ def test_gzip_load():
 
 # These next two classes encode the minimal API needed to save()/load() arrays.
 # The `test_ducktyping` ensures they work correctly
-class JustWriter(object):
+class JustWriter:
     def __init__(self, base):
         self.base = base
 
@@ -2492,7 +2489,7 @@ class JustWriter(object):
     def flush(self):
         return self.base.flush()
 
-class JustReader(object):
+class JustReader:
     def __init__(self, base):
         self.base = base
 
index 3dd5346b695cc1a24895cc4a3e632266a1f6df8d..632058763b7d9e826122af6834bb72d4bd970434 100644 (file)
@@ -1,16 +1,10 @@
-from __future__ import division, absolute_import, print_function
-
 import numbers
 import operator
-import sys
 
 import numpy as np
 from numpy.testing import assert_, assert_equal, assert_raises
 
 
-PY2 = sys.version_info.major < 3
-
-
 # NOTE: This class should be kept as an exact copy of the example from the
 # docstring for NDArrayOperatorsMixin.
 
@@ -86,7 +80,6 @@ _ALL_BINARY_OPERATORS = [
     operator.mul,
     operator.truediv,
     operator.floordiv,
-    # TODO: test div on Python 2, only
     operator.mod,
     divmod,
     pow,
@@ -98,7 +91,7 @@ _ALL_BINARY_OPERATORS = [
 ]
 
 
-class TestNDArrayOperatorsMixin(object):
+class TestNDArrayOperatorsMixin:
 
     def test_array_like_add(self):
 
@@ -128,7 +121,7 @@ class TestNDArrayOperatorsMixin(object):
 
     def test_opt_out(self):
 
-        class OptOut(object):
+        class OptOut:
             """Object that opts out of __array_ufunc__."""
             __array_ufunc__ = None
 
@@ -204,11 +197,10 @@ class TestNDArrayOperatorsMixin(object):
         array_like = ArrayLike(array)
         expected = ArrayLike(np.float64(5))
         _assert_equal_type_and_value(expected, np.matmul(array_like, array))
-        if not PY2:
-            _assert_equal_type_and_value(
-                expected, operator.matmul(array_like, array))
-            _assert_equal_type_and_value(
-                expected, operator.matmul(array, array_like))
+        _assert_equal_type_and_value(
+            expected, operator.matmul(array_like, array))
+        _assert_equal_type_and_value(
+            expected, operator.matmul(array, array_like))
 
     def test_ufunc_at(self):
         array = ArrayLike(np.array([1, 2, 3, 4]))
index da2d0cc52b6be8a9a18e9c9ad9e3b522d94de13d..db563e30c021219c779cbc8bcd374aa0151eb866 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import warnings
 import pytest
 
@@ -37,7 +35,7 @@ _ndat_zeros = np.array([[0.6244, 0.0, 0.2692, 0.0116, 0.0, 0.1170],
                         [0.1610, 0.0, 0.0, 0.1859, 0.3146, 0.0]])
 
 
-class TestNanFunctions_MinMax(object):
+class TestNanFunctions_MinMax:
 
     nanfuncs = [np.nanmin, np.nanmax]
     stdfuncs = [np.min, np.max]
@@ -171,7 +169,7 @@ class TestNanFunctions_MinMax(object):
             assert_(issubclass(w[0].category, RuntimeWarning))
 
 
-class TestNanFunctions_ArgminArgmax(object):
+class TestNanFunctions_ArgminArgmax:
 
     nanfuncs = [np.nanargmin, np.nanargmax]
 
@@ -233,7 +231,7 @@ class TestNanFunctions_ArgminArgmax(object):
             assert_(res.shape == ())
 
 
-class TestNanFunctions_IntTypes(object):
+class TestNanFunctions_IntTypes:
 
     int_types = (np.int8, np.int16, np.int32, np.int64, np.uint8,
                  np.uint16, np.uint32, np.uint64)
@@ -308,7 +306,7 @@ class TestNanFunctions_IntTypes(object):
             assert_equal(np.nanstd(mat, ddof=1), tgt)
 
 
-class SharedNanFunctionsTestsMixin(object):
+class SharedNanFunctionsTestsMixin:
     def test_mutation(self):
         # Check that passed array is not modified.
         ndat = _ndat.copy()
@@ -590,7 +588,7 @@ class TestNanFunctions_MeanVarStd(SharedNanFunctionsTestsMixin):
                     assert_(len(w) == 0)
 
 
-class TestNanFunctions_Median(object):
+class TestNanFunctions_Median:
 
     def test_mutation(self):
         # Check that passed array is not modified.
@@ -754,7 +752,7 @@ class TestNanFunctions_Median(object):
                                      ([np.nan] * i) + [-inf] * j)
 
 
-class TestNanFunctions_Percentile(object):
+class TestNanFunctions_Percentile:
 
     def test_mutation(self):
         # Check that passed array is not modified.
@@ -893,7 +891,7 @@ class TestNanFunctions_Percentile(object):
         assert_equal(np.nanpercentile(megamat, perc, axis=(1, 2)).shape, (2, 3, 6))
 
 
-class TestNanFunctions_Quantile(object):
+class TestNanFunctions_Quantile:
     # most of this is already tested by TestPercentile
 
     def test_regression(self):
index 95a465c36a6a74c1fe50b19269d629ad4553e14c..5b07f41c62609255951edcbc56bc818137497e0e 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.testing import assert_array_equal, assert_equal, assert_raises
 import pytest
index 89759bd839499d00dcad0b1f14ac62a6b0820ac2..cd0b90dc48b6af52e43853306ceabf4da121ad4b 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.testing import (
     assert_, assert_equal, assert_array_equal, assert_almost_equal,
@@ -7,7 +5,7 @@ from numpy.testing import (
     )
 
 
-class TestPolynomial(object):
+class TestPolynomial:
     def test_poly1d_str_and_repr(self):
         p = np.poly1d([1., 2, 3])
         assert_equal(repr(p), 'poly1d([1., 2., 3.])')
index fa5f4dec23a9fad8eaf20a22e19ae4fda982370e..2f3c14df31f0fff85f59231622814484a2b23571 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import pytest
 
 import numpy as np
@@ -19,7 +17,7 @@ zip_descr = np.lib.recfunctions._zip_descr
 zip_dtype = np.lib.recfunctions._zip_dtype
 
 
-class TestRecFunctions(object):
+class TestRecFunctions:
     # Misc tests
 
     def setup(self):
@@ -348,7 +346,7 @@ class TestRecFunctions(object):
         assert_equal(b[()], 3)
 
 
-class TestRecursiveFillFields(object):
+class TestRecursiveFillFields:
     # Test recursive_fill_fields.
     def test_simple_flexible(self):
         # Test recursive_fill_fields on flexible-array
@@ -371,7 +369,7 @@ class TestRecursiveFillFields(object):
         assert_equal(test, control)
 
 
-class TestMergeArrays(object):
+class TestMergeArrays:
     # Test merge_arrays
 
     def setup(self):
@@ -504,7 +502,7 @@ class TestMergeArrays(object):
         assert_equal(test, control)
 
 
-class TestAppendFields(object):
+class TestAppendFields:
     # Test append_fields
 
     def setup(self):
@@ -558,7 +556,7 @@ class TestAppendFields(object):
         assert_equal(test, control)
 
 
-class TestStackArrays(object):
+class TestStackArrays:
     # Test stack_arrays
     def setup(self):
         x = np.array([1, 2, ])
@@ -729,7 +727,7 @@ class TestStackArrays(object):
         assert_equal(res.mask, expected.mask)
 
 
-class TestJoinBy(object):
+class TestJoinBy:
     def setup(self):
         self.a = np.array(list(zip(np.arange(10), np.arange(50, 60),
                                    np.arange(100, 110))),
@@ -772,7 +770,6 @@ class TestJoinBy(object):
 
     def test_join_subdtype(self):
         # tests the bug in https://stackoverflow.com/q/44769632/102441
-        from numpy.lib import recfunctions as rfn
         foo = np.array([(1,)],
                        dtype=[('key', int)])
         bar = np.array([(1, np.array([1,2,3]))],
@@ -895,7 +892,7 @@ class TestJoinBy(object):
         assert_equal(res.dtype, expected_dtype)
 
 
-class TestJoinBy2(object):
+class TestJoinBy2:
     @classmethod
     def setup(cls):
         cls.a = np.array(list(zip(np.arange(10), np.arange(50, 60),
@@ -960,7 +957,7 @@ class TestJoinBy2(object):
         assert_equal(test.dtype, control.dtype)
         assert_equal(test, control)
 
-class TestAppendFieldsObj(object):
+class TestAppendFieldsObj:
     """
     Test append_fields with arrays containing objects
     """
index 4cd812f5dc10690b272351883cb2d0cbaf2a47db..55df2a6752c2629a12dc96ae4a0d267a9e228cf4 100644 (file)
@@ -1,17 +1,13 @@
-from __future__ import division, absolute_import, print_function
-
 import os
-import sys
 
 import numpy as np
 from numpy.testing import (
     assert_, assert_equal, assert_array_equal, assert_array_almost_equal,
     assert_raises, _assert_valid_refcount,
     )
-from numpy.compat import unicode
 
 
-class TestRegression(object):
+class TestRegression:
     def test_poly1d(self):
         # Ticket #28
         assert_equal(np.poly1d([1]) - np.poly1d([1, 0]),
@@ -183,7 +179,7 @@ class TestRegression(object):
         # related to ticket #1405.
         include_dirs = [np.get_include()]
         for path in include_dirs:
-            assert_(isinstance(path, (str, unicode)))
+            assert_(isinstance(path, str))
             assert_(path != '')
 
     def test_polyder_return_type(self):
@@ -208,10 +204,7 @@ class TestRegression(object):
 
     def test_loadtxt_fields_subarrays(self):
         # For ticket #1936
-        if sys.version_info[0] >= 3:
-            from io import StringIO
-        else:
-            from StringIO import StringIO
+        from io import StringIO
 
         dt = [("a", 'u1', 2), ("b", 'u1', 2)]
         x = np.loadtxt(StringIO("0 1 2 3"), dtype=dt)
index be1604a754ab74eccc93ed1cf3f93c5c6c7dd2e8..fb7ba78749ebc3877386816a15e795e822e9af4a 100644 (file)
@@ -1,7 +1,4 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
-import warnings
 import functools
 import sys
 import pytest
@@ -30,7 +27,7 @@ def _add_keepdims(func):
     return wrapped
 
 
-class TestTakeAlongAxis(object):
+class TestTakeAlongAxis:
     def test_argequivalent(self):
         """ Test it translates from arg<func> to <func> """
         from numpy.random import rand
@@ -82,7 +79,7 @@ class TestTakeAlongAxis(object):
         assert_equal(actual.shape, (3, 2, 5))
 
 
-class TestPutAlongAxis(object):
+class TestPutAlongAxis:
     def test_replace_max(self):
         a_base = np.array([[10, 30, 20], [60, 40, 50]])
 
@@ -107,7 +104,7 @@ class TestPutAlongAxis(object):
         assert_equal(take_along_axis(a, ai, axis=1), 20)
 
 
-class TestApplyAlongAxis(object):
+class TestApplyAlongAxis:
     def test_simple(self):
         a = np.ones((20, 10), 'd')
         assert_array_equal(
@@ -273,14 +270,14 @@ class TestApplyAlongAxis(object):
             assert_equal(type(actual[i]), type(expected[i]))
 
 
-class TestApplyOverAxes(object):
+class TestApplyOverAxes:
     def test_simple(self):
         a = np.arange(24).reshape(2, 3, 4)
         aoa_a = apply_over_axes(np.sum, a, [0, 2])
         assert_array_equal(aoa_a, np.array([[[60], [92], [124]]]))
 
 
-class TestExpandDims(object):
+class TestExpandDims:
     def test_functionality(self):
         s = (2, 3, 4, 5)
         a = np.empty(s)
@@ -320,7 +317,7 @@ class TestExpandDims(object):
         assert_equal(expanded.mask.shape, (2, 1, 5))
 
 
-class TestArraySplit(object):
+class TestArraySplit:
     def test_integer_0_split(self):
         a = np.arange(10)
         assert_raises(ValueError, array_split, a, 0)
@@ -454,7 +451,7 @@ class TestArraySplit(object):
         compare_results(res, desired)
 
 
-class TestSplit(object):
+class TestSplit:
     # The split function is essentially the same as array_split,
     # except that it test if splitting will result in an
     # equal split.  Only test for this case.
@@ -470,7 +467,7 @@ class TestSplit(object):
         assert_raises(ValueError, split, a, 3)
 
 
-class TestColumnStack(object):
+class TestColumnStack:
     def test_non_iterable(self):
         assert_raises(TypeError, column_stack, 1)
 
@@ -499,7 +496,7 @@ class TestColumnStack(object):
             column_stack((np.arange(3) for _ in range(2)))
 
 
-class TestDstack(object):
+class TestDstack:
     def test_non_iterable(self):
         assert_raises(TypeError, dstack, 1)
 
@@ -538,7 +535,7 @@ class TestDstack(object):
 
 # array_split has more comprehensive test of splitting.
 # only do simple test on hsplit, vsplit, and dsplit
-class TestHsplit(object):
+class TestHsplit:
     """Only testing for integer splits.
 
     """
@@ -567,7 +564,7 @@ class TestHsplit(object):
         compare_results(res, desired)
 
 
-class TestVsplit(object):
+class TestVsplit:
     """Only testing for integer splits.
 
     """
@@ -594,7 +591,7 @@ class TestVsplit(object):
         compare_results(res, desired)
 
 
-class TestDsplit(object):
+class TestDsplit:
     # Only testing for integer splits.
     def test_non_iterable(self):
         assert_raises(ValueError, dsplit, 1, 1)
@@ -627,7 +624,7 @@ class TestDsplit(object):
         compare_results(res, desired)
 
 
-class TestSqueeze(object):
+class TestSqueeze:
     def test_basic(self):
         from numpy.random import rand
 
@@ -646,7 +643,7 @@ class TestSqueeze(object):
         assert_equal(type(res), np.ndarray)
 
 
-class TestKron(object):
+class TestKron:
     def test_return_type(self):
         class myarray(np.ndarray):
             __array_priority__ = 0.0
@@ -659,7 +656,7 @@ class TestKron(object):
         assert_equal(type(kron(ma, a)), myarray)
 
 
-class TestTile(object):
+class TestTile:
     def test_basic(self):
         a = np.array([0, 1, 2])
         b = [[1, 2], [3, 4]]
@@ -699,7 +696,7 @@ class TestTile(object):
                 assert_equal(large, klarge)
 
 
-class TestMayShareMemory(object):
+class TestMayShareMemory:
     def test_basic(self):
         d = np.ones((50, 60))
         d2 = np.ones((30, 60, 6))
index 85fcceedc1e3729a41923faa6bf6762b993415ff..9d95eb9d0321cf2161f2d8d81dbca848fd470e71 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.core._rational_tests import rational
 from numpy.testing import (
@@ -65,8 +63,7 @@ def test_broadcast_kwargs():
     x = np.arange(10)
     y = np.arange(10)
 
-    with assert_raises_regex(TypeError,
-                             r'broadcast_arrays\(\) got an unexpected keyword*'):
+    with assert_raises_regex(TypeError, 'got an unexpected keyword'):
         broadcast_arrays(x, y, dtype='float64')
 
 
@@ -356,14 +353,12 @@ def as_strided_writeable():
 
 class VerySimpleSubClass(np.ndarray):
     def __new__(cls, *args, **kwargs):
-        kwargs['subok'] = True
-        return np.array(*args, **kwargs).view(cls)
+        return np.array(*args, subok=True, **kwargs).view(cls)
 
 
 class SimpleSubClass(VerySimpleSubClass):
     def __new__(cls, *args, **kwargs):
-        kwargs['subok'] = True
-        self = np.array(*args, **kwargs).view(cls)
+        self = np.array(*args, subok=True, **kwargs).view(cls)
         self.info = 'simple'
         return self
 
index bb844e4bd6a6d2d6b917703ac7ed2487f332171c..cce683bfeda3e990e94aee7ffde1f8fcfa9051d0 100644 (file)
@@ -1,8 +1,6 @@
 """Test functions for matrix module
 
 """
-from __future__ import division, absolute_import, print_function
-
 from numpy.testing import (
     assert_equal, assert_array_equal, assert_array_max_ulp,
     assert_array_almost_equal, assert_raises, assert_
@@ -26,7 +24,7 @@ def get_mat(n):
     return data
 
 
-class TestEye(object):
+class TestEye:
     def test_basic(self):
         assert_equal(eye(4),
                      array([[1, 0, 0, 0],
@@ -108,7 +106,7 @@ class TestEye(object):
         assert mat_f.flags.f_contiguous
 
 
-class TestDiag(object):
+class TestDiag:
     def test_vector(self):
         vals = (100 * arange(5)).astype('l')
         b = zeros((5, 5))
@@ -155,7 +153,7 @@ class TestDiag(object):
         assert_raises(ValueError, diag, [[[1]]])
 
 
-class TestFliplr(object):
+class TestFliplr:
     def test_basic(self):
         assert_raises(ValueError, fliplr, ones(4))
         a = get_mat(4)
@@ -168,7 +166,7 @@ class TestFliplr(object):
         assert_equal(fliplr(a), b)
 
 
-class TestFlipud(object):
+class TestFlipud:
     def test_basic(self):
         a = get_mat(4)
         b = a[::-1, :]
@@ -180,7 +178,7 @@ class TestFlipud(object):
         assert_equal(flipud(a), b)
 
 
-class TestHistogram2d(object):
+class TestHistogram2d:
     def test_simple(self):
         x = array(
             [0.41702200, 0.72032449, 1.1437481e-4, 0.302332573, 0.146755891])
@@ -298,7 +296,7 @@ class TestHistogram2d(object):
         assert_(r, ((ShouldDispatch,), (xy, xy), dict(weights=s_d)))
 
 
-class TestTri(object):
+class TestTri:
     def test_dtype(self):
         out = array([[1, 0, 0],
                      [1, 1, 0],
@@ -436,7 +434,7 @@ def test_tril_indices():
                               [-10, -10, -10, -10, -10]]))
 
 
-class TestTriuIndices(object):
+class TestTriuIndices:
     def test_triu_indices(self):
         iu1 = triu_indices(4)
         iu2 = triu_indices(4, k=2)
@@ -486,21 +484,21 @@ class TestTriuIndices(object):
                                   [16, 17, 18, -1, -1]]))
 
 
-class TestTrilIndicesFrom(object):
+class TestTrilIndicesFrom:
     def test_exceptions(self):
         assert_raises(ValueError, tril_indices_from, np.ones((2,)))
         assert_raises(ValueError, tril_indices_from, np.ones((2, 2, 2)))
         # assert_raises(ValueError, tril_indices_from, np.ones((2, 3)))
 
 
-class TestTriuIndicesFrom(object):
+class TestTriuIndicesFrom:
     def test_exceptions(self):
         assert_raises(ValueError, triu_indices_from, np.ones((2,)))
         assert_raises(ValueError, triu_indices_from, np.ones((2, 2, 2)))
         # assert_raises(ValueError, triu_indices_from, np.ones((2, 3)))
 
 
-class TestVander(object):
+class TestVander:
     def test_basic(self):
         c = np.array([0, 1, -2, 3])
         v = vander(c)
index b3f114b929686e042f6a4077775943e4f2177e62..3f4ca630960e401b80f406a1fffb2d24a20d80f8 100644 (file)
@@ -1,7 +1,4 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
-from numpy.compat import long
 from numpy.testing import (
     assert_, assert_equal, assert_array_equal, assert_raises
     )
@@ -15,7 +12,7 @@ def assert_all(x):
     assert_(np.all(x), x)
 
 
-class TestCommonType(object):
+class TestCommonType:
     def test_basic(self):
         ai32 = np.array([[1, 2], [3, 4]], dtype=np.int32)
         af16 = np.array([[1, 2], [3, 4]], dtype=np.float16)
@@ -31,7 +28,7 @@ class TestCommonType(object):
         assert_(common_type(acd) == np.cdouble)
 
 
-class TestMintypecode(object):
+class TestMintypecode:
 
     def test_default_1(self):
         for itype in '1bcsuwil':
@@ -81,18 +78,17 @@ class TestMintypecode(object):
         assert_equal(mintypecode('idD'), 'D')
 
 
-class TestIsscalar(object):
+class TestIsscalar:
 
     def test_basic(self):
         assert_(np.isscalar(3))
         assert_(not np.isscalar([3]))
         assert_(not np.isscalar((3,)))
         assert_(np.isscalar(3j))
-        assert_(np.isscalar(long(10)))
         assert_(np.isscalar(4.0))
 
 
-class TestReal(object):
+class TestReal:
 
     def test_real(self):
         y = np.random.rand(10,)
@@ -123,7 +119,7 @@ class TestReal(object):
         assert_(not isinstance(out, np.ndarray))
 
 
-class TestImag(object):
+class TestImag:
 
     def test_real(self):
         y = np.random.rand(10,)
@@ -154,7 +150,7 @@ class TestImag(object):
         assert_(not isinstance(out, np.ndarray))
 
 
-class TestIscomplex(object):
+class TestIscomplex:
 
     def test_fail(self):
         z = np.array([-1, 0, 1])
@@ -167,7 +163,7 @@ class TestIscomplex(object):
         assert_array_equal(res, [1, 0, 0])
 
 
-class TestIsreal(object):
+class TestIsreal:
 
     def test_pass(self):
         z = np.array([-1, 0, 1j])
@@ -180,7 +176,7 @@ class TestIsreal(object):
         assert_array_equal(res, [0, 1, 1])
 
 
-class TestIscomplexobj(object):
+class TestIscomplexobj:
 
     def test_basic(self):
         z = np.array([-1, 0, 1])
@@ -209,7 +205,7 @@ class TestIscomplexobj(object):
         # (pandas.core.dtypes)
         class PdComplex(np.complex128):
             pass
-        class PdDtype(object):
+        class PdDtype:
             name = 'category'
             names = None
             type = PdComplex
@@ -233,7 +229,7 @@ class TestIscomplexobj(object):
         assert_(iscomplexobj(a))
 
 
-class TestIsrealobj(object):
+class TestIsrealobj:
     def test_basic(self):
         z = np.array([-1, 0, 1])
         assert_(isrealobj(z))
@@ -241,7 +237,7 @@ class TestIsrealobj(object):
         assert_(not isrealobj(z))
 
 
-class TestIsnan(object):
+class TestIsnan:
 
     def test_goodvalues(self):
         z = np.array((-1., 0., 1.))
@@ -271,7 +267,7 @@ class TestIsnan(object):
             assert_all(np.isnan(np.array(0+0j)/0.) == 1)
 
 
-class TestIsfinite(object):
+class TestIsfinite:
     # Fixme, wrong place, isfinite now ufunc
 
     def test_goodvalues(self):
@@ -302,7 +298,7 @@ class TestIsfinite(object):
             assert_all(np.isfinite(np.array(1+1j)/0.) == 0)
 
 
-class TestIsinf(object):
+class TestIsinf:
     # Fixme, wrong place, isinf now ufunc
 
     def test_goodvalues(self):
@@ -331,7 +327,7 @@ class TestIsinf(object):
             assert_all(np.isinf(np.array((0.,))/0.) == 0)
 
 
-class TestIsposinf(object):
+class TestIsposinf:
 
     def test_generic(self):
         with np.errstate(divide='ignore', invalid='ignore'):
@@ -341,7 +337,7 @@ class TestIsposinf(object):
         assert_(vals[2] == 1)
 
 
-class TestIsneginf(object):
+class TestIsneginf:
 
     def test_generic(self):
         with np.errstate(divide='ignore', invalid='ignore'):
@@ -351,7 +347,7 @@ class TestIsneginf(object):
         assert_(vals[2] == 0)
 
 
-class TestNanToNum(object):
+class TestNanToNum:
 
     def test_generic(self):
         with np.errstate(divide='ignore', invalid='ignore'):
@@ -456,7 +452,7 @@ class TestNanToNum(object):
         assert_equal(type(vals), np.ndarray)
 
 
-class TestRealIfClose(object):
+class TestRealIfClose:
 
     def test_basic(self):
         a = np.random.rand(10)
@@ -469,7 +465,7 @@ class TestRealIfClose(object):
         assert_all(isrealobj(b))
 
 
-class TestArrayConversion(object):
+class TestArrayConversion:
 
     def test_asfarray(self):
         a = asfarray(np.array([1, 2, 3]))
index 64280616f2bc3057082aff6dfbdfbfcbb840bad1..c280b696921a558fb07894f647a951b71e5ee2e5 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 import numpy.core as nx
 import numpy.lib.ufunclike as ufl
@@ -8,7 +6,7 @@ from numpy.testing import (
 )
 
 
-class TestUfunclike(object):
+class TestUfunclike:
 
     def test_isposinf(self):
         a = nx.array([nx.inf, -nx.inf, nx.nan, 0.0, 3.0, -3.0])
index 9673a05fa12daf20d0eb672bd8c4fb33fa0d73a6..261cfef5d680224b22208024e5d1308030010f60 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import inspect
 import sys
 import pytest
@@ -9,10 +7,7 @@ from numpy.testing import assert_, assert_equal, assert_raises_regex
 from numpy.lib import deprecate
 import numpy.lib.utils as utils
 
-if sys.version_info[0] >= 3:
-    from io import StringIO
-else:
-    from StringIO import StringIO
+from io import StringIO
 
 
 @pytest.mark.skipif(sys.flags.optimize == 2, reason="Python running -OO")
@@ -54,7 +49,7 @@ def old_func5(self, x):
         Bizarre indentation.
     """
     return x
-new_func5 = deprecate(old_func5)
+new_func5 = deprecate(old_func5, message="This function is\ndeprecated.")
 
 
 def old_func6(self, x):
@@ -79,10 +74,20 @@ def test_deprecate_fn():
 
 
 @pytest.mark.skipif(sys.flags.optimize == 2, reason="-OO discards docstrings")
-def test_deprecate_help_indentation():
-    _compare_docs(old_func4, new_func4)
-    _compare_docs(old_func5, new_func5)
-    _compare_docs(old_func6, new_func6)
+@pytest.mark.parametrize('old_func, new_func', [
+    (old_func4, new_func4),
+    (old_func5, new_func5),
+    (old_func6, new_func6),
+])
+def test_deprecate_help_indentation(old_func, new_func):
+    _compare_docs(old_func, new_func)
+    # Ensure we don't mess up the indentation
+    for knd, func in (('old', old_func), ('new', new_func)):
+        for li, line in enumerate(func.__doc__.split('\n')):
+            if li == 0:
+                assert line.startswith('    ') or not line.startswith(' '), knd
+            elif line:
+                assert line.startswith('    '), knd
 
 
 def _compare_docs(old_func, new_func):
@@ -102,7 +107,7 @@ def test_safe_eval_nameconstant():
     utils.safe_eval('None')
 
 
-class TestByteBounds(object):
+class TestByteBounds:
 
     def test_byte_bounds(self):
         # pointer difference matches size * itemsize
index f453921885c24b5d2cfa7cffadd41ab6be4aa29d..320a24856bc194ee5a3020d6da2ec33c019bc758 100644 (file)
@@ -1,18 +1,16 @@
 """ Basic functions for manipulating 2d arrays
 
 """
-from __future__ import division, absolute_import, print_function
-
 import functools
 
 from numpy.core.numeric import (
-    absolute, asanyarray, arange, zeros, greater_equal, multiply, ones,
+    asanyarray, arange, zeros, greater_equal, multiply, ones,
     asarray, where, int8, int16, int32, int64, empty, promote_types, diagonal,
     nonzero
     )
 from numpy.core.overrides import set_module
 from numpy.core import overrides
-from numpy.core import iinfo, transpose
+from numpy.core import iinfo
 
 
 __all__ = [
index 9771172352c91058fa30787f9269ac61ff9d6995..2a2982ab348e15963f62d88c1d5d2005a20f70a0 100644 (file)
@@ -1,7 +1,6 @@
 """Automatically adapted for numpy Sep 19, 2005 by convertcode.py
 
 """
-from __future__ import division, absolute_import, print_function
 import functools
 import warnings
 
@@ -493,7 +492,8 @@ def _real_if_close_dispatcher(a, tol=None):
 @array_function_dispatch(_real_if_close_dispatcher)
 def real_if_close(a, tol=100):
     """
-    If complex input returns a real array if complex parts are close to zero.
+    If input is complex with all imaginary parts close to zero, return 
+    real parts.
 
     "Close to zero" is defined as `tol` * (machine epsilon of the type for
     `a`).
@@ -528,10 +528,10 @@ def real_if_close(a, tol=100):
     >>> np.finfo(float).eps
     2.2204460492503131e-16 # may vary
 
-    >>> np.real_if_close([2.1 + 4e-14j], tol=1000)
-    array([2.1])
-    >>> np.real_if_close([2.1 + 4e-13j], tol=1000)
-    array([2.1+4.e-13j])
+    >>> np.real_if_close([2.1 + 4e-14j, 5.2 + 3e-15j], tol=1000)
+    array([2.1, 5.2])
+    >>> np.real_if_close([2.1 + 4e-13j, 5.2 + 3e-15j], tol=1000)
+    array([2.1+4.e-13j, 5.2 + 3e-15j])
 
     """
     a = asanyarray(a)
index 96fd5b319a00c2fe5c865cf8a5084ebe945ed369..1f26a18459f0d5d97368553df52cbebae32c10c0 100644 (file)
@@ -3,8 +3,6 @@ Module of functions that are like ufuncs in acting on arrays and optionally
 storing results in an output array.
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['fix', 'isneginf', 'isposinf']
 
 import numpy.core.numeric as nx
@@ -85,13 +83,20 @@ def fix(x, out=None):
     ----------
     x : array_like
         An array of floats to be rounded
-    y : ndarray, optional
-        Output array
+    out : ndarray, optional
+        A location into which the result is stored. If provided, it must have
+        a shape that the input broadcasts to. If not provided or None, a
+        freshly-allocated array is returned.
 
     Returns
     -------
     out : ndarray of floats
-        The array of rounded numbers
+        A float array with the same dimensions as the input.
+        If second argument is not supplied then a float array is returned
+        with the rounded values.
+
+        If a second argument is supplied the result is stored there.
+        The return value `out` is then a reference to that array.
 
     See Also
     --------
@@ -129,8 +134,10 @@ def isposinf(x, out=None):
     ----------
     x : array_like
         The input array.
-    y : array_like, optional
-        A boolean array with the same shape as `x` to store the result.
+    out : array_like, optional
+        A location into which the result is stored. If provided, it must have a
+        shape that the input broadcasts to. If not provided or None, a
+        freshly-allocated boolean array is returned.
 
     Returns
     -------
@@ -181,9 +188,9 @@ def isposinf(x, out=None):
     is_inf = nx.isinf(x)
     try:
         signbit = ~nx.signbit(x)
-    except TypeError:
+    except TypeError as e:
         raise TypeError('This operation is not supported for complex values '
-                        'because it would be ambiguous.')
+                        'because it would be ambiguous.') from e
     else:
         return nx.logical_and(is_inf, signbit, out)
 
@@ -199,8 +206,9 @@ def isneginf(x, out=None):
     x : array_like
         The input array.
     out : array_like, optional
-        A boolean array with the same shape and type as `x` to store the
-        result.
+        A location into which the result is stored. If provided, it must have a
+        shape that the input broadcasts to. If not provided or None, a
+        freshly-allocated boolean array is returned.
 
     Returns
     -------
@@ -251,8 +259,8 @@ def isneginf(x, out=None):
     is_inf = nx.isinf(x)
     try:
         signbit = nx.signbit(x)
-    except TypeError:
+    except TypeError as e:
         raise TypeError('This operation is not supported for complex values '
-                        'because it would be ambiguous.')
+                        'because it would be ambiguous.') from e
     else:
         return nx.logical_and(is_inf, signbit, out)
index f1510a7b11c95fbd07153d10cd2774edccc5c150..0e96b477ef7456e5ce575b17698323b7ff479dcd 100644 (file)
@@ -5,18 +5,15 @@ Try to inherit from the ndarray instead of using this class as this is not
 complete.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from numpy.core import (
     array, asarray, absolute, add, subtract, multiply, divide,
     remainder, power, left_shift, right_shift, bitwise_and, bitwise_or,
     bitwise_xor, invert, less, less_equal, not_equal, equal, greater,
     greater_equal, shape, reshape, arange, sin, sqrt, transpose
 )
-from numpy.compat import long
 
 
-class container(object):
+class container:
     """
     container(data, dtype=None, copy=True)
 
@@ -198,9 +195,6 @@ class container(object):
     def __int__(self):
         return self._scalarfunc(int)
 
-    def __long__(self):
-        return self._scalarfunc(long)
-
     def __hex__(self):
         return self._scalarfunc(hex)
 
@@ -233,6 +227,10 @@ class container(object):
         ""
         return self.array.tostring()
 
+    def tobytes(self):
+        ""
+        return self.array.tobytes()
+
     def byteswap(self):
         ""
         return self._rc(self.array.byteswap())
index 3c71d2a7c8be54aad86f3d2a5b7c444fd6cc5869..ba8616aa3c204784f0e8ceba205e27919fda7212 100644 (file)
@@ -1,7 +1,6 @@
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
+import textwrap
 import types
 import re
 import warnings
@@ -55,7 +54,7 @@ def _set_function_name(func, name):
     return func
 
 
-class _Deprecate(object):
+class _Deprecate:
     """
     Decorator class to deprecate old functions.
 
@@ -119,6 +118,7 @@ class _Deprecate(object):
                         break
                     skip += len(line) + 1
                 doc = doc[skip:]
+            depdoc = textwrap.indent(depdoc, ' ' * indent)
             doc = '\n\n'.join([depdoc, doc])
         newfunc.__doc__ = doc
         try:
@@ -607,41 +607,6 @@ def info(object=None, maxwidth=76, output=sys.stdout, toplevel='numpy'):
                             )
                 print("  %s  --  %s" % (meth, methstr), file=output)
 
-    elif (sys.version_info[0] < 3
-            and isinstance(object, types.InstanceType)):
-        # check for __call__ method
-        # types.InstanceType is the type of the instances of oldstyle classes
-        print("Instance of class: ", object.__class__.__name__, file=output)
-        print(file=output)
-        if hasattr(object, '__call__'):
-            arguments = formatargspec(
-                    *getargspec(object.__call__.__func__)
-                    )
-            arglist = arguments.split(', ')
-            if len(arglist) > 1:
-                arglist[1] = "("+arglist[1]
-                arguments = ", ".join(arglist[1:])
-            else:
-                arguments = "()"
-
-            if hasattr(object, 'name'):
-                name = "%s" % object.name
-            else:
-                name = "<name>"
-            if len(name+arguments) > maxwidth:
-                argstr = _split_line(name, arguments, maxwidth)
-            else:
-                argstr = name + arguments
-
-            print(" " + argstr + "\n", file=output)
-            doc = inspect.getdoc(object.__call__)
-            if doc is not None:
-                print(inspect.getdoc(object.__call__), file=output)
-            print(inspect.getdoc(object), file=output)
-
-        else:
-            print(inspect.getdoc(object), file=output)
-
     elif inspect.ismethod(object):
         name = object.__name__
         arguments = formatargspec(
@@ -869,15 +834,10 @@ def _lookfor_generate_cache(module, import_modules, regenerate):
         or newly generated.
 
     """
-    global _lookfor_caches
     # Local import to speed up numpy's import time.
     import inspect
 
-    if sys.version_info[0] >= 3:
-        # In Python3 stderr, stdout are text files.
-        from io import StringIO
-    else:
-        from StringIO import StringIO
+    from io import StringIO
 
     if module is None:
         module = "numpy"
index 55560815d00535f5fa8203e4a68881038fb11690..3a53ac6ecac61690cb28e3499011dfc7b118ca0c 100644 (file)
@@ -69,8 +69,6 @@ Exceptions
    LinAlgError
 
 """
-from __future__ import division, absolute_import, print_function
-
 # To get sub-modules
 from .linalg import *
 
index 1343d25f8a94649f83352e856cff0182a987df56..ed738ab86d75c8c6eceea0cf735c781e57d6921d 100644 (file)
@@ -18,9 +18,9 @@ and is unlikely to ever be ported to python 3.
 The routines that ``lapack_litemodule.c`` wraps are listed in
 ``wrapped_routines``, along with a few exceptions that aren't picked up
 properly. Assuming that you have an unpacked LAPACK source tree in
-``~/LAPACK``, you generate the new routines in a directory ``new-lite/`` with::
+``~/LAPACK``, you generate the new routines in this directory with::
 
-$ python2 ./make_lite.py wrapped_routines ~/LAPACK new-lite/
+$ python ./make_lite.py wrapped_routines ~/LAPACK
 
 This will grab the right routines, with dependencies, put them into the
 appropriate ``f2c_*.f`` files, run ``f2c`` over them, then do some scrubbing
index 4345861131f837e429f9eaf70cb7689585aa2cc0..f3e7d25d2eab38bb2e9e0e5eea3b5dfe467efe32 100644 (file)
@@ -1,17 +1,12 @@
-#!/usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
-import sys, os
+#!/usr/bin/env python3
+import os
 import re
+import sys
+from io import StringIO
+
 from plex import Scanner, Str, Lexicon, Opt, Bol, State, AnyChar, TEXT, IGNORE
 from plex.traditional import re as Re
 
-PY2 = sys.version_info < (3, 0)
-
-if PY2:
-    from io import BytesIO as UStringIO
-else:
-    from io import StringIO as UStringIO
 
 class MyScanner(Scanner):
     def __init__(self, info, name='<default>'):
@@ -27,8 +22,8 @@ def sep_seq(sequence, sep):
     return pat
 
 def runScanner(data, scanner_class, lexicon=None):
-    info = UStringIO(data)
-    outfo = UStringIO()
+    info = StringIO(data)
+    outfo = StringIO()
     if lexicon is not None:
         scanner = scanner_class(lexicon, info)
     else:
@@ -106,7 +101,7 @@ def cleanSource(source):
     source = re.sub(r'\n\n\n\n+', r'\n\n\n', source)
     return source
 
-class LineQueue(object):
+class LineQueue:
     def __init__(self):
         object.__init__(self)
         self._queue = []
@@ -195,7 +190,7 @@ def cleanComments(source):
             return SourceLines
 
     state = SourceLines
-    for line in UStringIO(source):
+    for line in StringIO(source):
         state = state(line)
     comments.flushTo(lines)
     return lines.getValue()
@@ -223,7 +218,7 @@ def removeHeader(source):
         return OutOfHeader
 
     state = LookingForHeader
-    for line in UStringIO(source):
+    for line in StringIO(source):
         state = state(line)
     return lines.getValue()
 
@@ -232,7 +227,7 @@ def removeSubroutinePrototypes(source):
         r'/[*] Subroutine [*]/^\s*(?:(?:inline|static)\s+){0,2}(?!else|typedef|return)\w+\s+\*?\s*(\w+)\s*\([^0]+\)\s*;?'
     )
     lines = LineQueue()
-    for line in UStringIO(source):
+    for line in StringIO(source):
         if not expression.match(line):
             lines.add(line)
 
@@ -254,7 +249,7 @@ def removeBuiltinFunctions(source):
             return InBuiltInFunctions
 
     state = LookingForBuiltinFunctions
-    for line in UStringIO(source):
+    for line in StringIO(source):
         state = state(line)
     return lines.getValue()
 
index 1114bef3b1c34ddb78fcdff597c64a89ec0bc207..9a1e9cec1d2b398ea322dfc1f53b6daadbfcfd53 100644 (file)
@@ -567,7 +567,7 @@ if( (abi = b->i) < 0.f)
        abi = - abi;
 if( abr <= abi )
        {
-         /*Let IEEE Infinties handle this ;( */
+         /*Let IEEE Infinities handle this ;( */
          /*if(abi == 0)
                sig_die("complex division by zero", 1);*/
        ratio = b->r / b->i ;
@@ -603,7 +603,7 @@ if( (abi = b->i) < 0.)
        abi = - abi;
 if( abr <= abi )
        {
-         /*Let IEEE Infinties handle this ;( */
+         /*Let IEEE Infinities handle this ;( */
          /*if(abi == 0)
                sig_die("complex division by zero", 1);*/
        ratio = b->r / b->i ;
index 80f1a12b19df70fa46140d7ebef758a2fe24ad84..d3fbfc1771f813f11ece4051ed6979fcdad28221 100644 (file)
@@ -8,15 +8,19 @@
 #define F2C_INCLUDE
 
 #include <math.h>
+#include "numpy/npy_common.h"
+#include "npy_cblas.h"
 
-typedef int integer;
+#include "lapack_lite_names.h"
+
+typedef CBLAS_INT integer;
 typedef char *address;
 typedef short int shortint;
 typedef float real;
 typedef double doublereal;
 typedef struct { real r, i; } complex;
 typedef struct { doublereal r, i; } doublecomplex;
-typedef int logical;
+typedef CBLAS_INT logical;
 typedef short int shortlogical;
 typedef char logical1;
 typedef char integer1;
@@ -37,9 +41,9 @@ typedef short flag;
 typedef short ftnlen;
 typedef short ftnint;
 #else
-typedef int flag;
-typedef int ftnlen;
-typedef int ftnint;
+typedef CBLAS_INT flag;
+typedef CBLAS_INT ftnlen;
+typedef CBLAS_INT ftnint;
 #endif
 
 /*external read, write*/
@@ -352,7 +356,7 @@ extern void s_copy(char *, char *, ftnlen, ftnlen);
 extern int s_paus(char *, ftnlen);
 extern integer s_rdfe(cilist *);
 extern integer s_rdue(cilist *);
-extern integer s_rnge(char *, integer, char *, integer);
+extern int s_rnge(char *, int, char *, int);
 extern integer s_rsfe(cilist *);
 extern integer s_rsfi(icilist *);
 extern integer s_rsle(cilist *);
@@ -381,6 +385,9 @@ extern void z_log(doublecomplex *, doublecomplex *);
 extern void z_sin(doublecomplex *, doublecomplex *);
 extern void z_sqrt(doublecomplex *, doublecomplex *);
 
+extern double f__cabs(double, double);
+extern double f__cabsf(float, float);
+
 #ifdef __cplusplus
        }
 #endif
index 3af506b71247593d8558f4ae8ffaa82d0ae89472..65286892fb641386b9153f10be7093bead18c212 100644 (file)
@@ -1,7 +1,7 @@
 /*
-NOTE: This is generated code. Look in Misc/lapack_lite for information on
     remaking this file.
-*/
+ * NOTE: This is generated code. Look in numpy/linalg/lapack_lite for
*       information on remaking this file.
+ */
 #include "f2c.h"
 
 #ifdef HAVE_CONFIG
index f52e1e1572c9f953ddf0ad8081cd63434953d790..c36c0e3683a8a47f5ab6c0498880db40879ad3ca 100644 (file)
@@ -1,7 +1,7 @@
 /*
-NOTE: This is generated code. Look in Misc/lapack_lite for information on
     remaking this file.
-*/
+ * NOTE: This is generated code. Look in numpy/linalg/lapack_lite for
*       information on remaking this file.
+ */
 #include "f2c.h"
 
 #ifdef HAVE_CONFIG
index 2fe608227fae615fbd9f31b105fdb64ad1e326a2..3f59e026378fbb87945a6ae59d8a8b66062120d5 100644 (file)
@@ -1,7 +1,7 @@
 /*
-NOTE: This is generated code. Look in Misc/lapack_lite for information on
     remaking this file.
-*/
+ * NOTE: This is generated code. Look in numpy/linalg/lapack_lite for
*       information on remaking this file.
+ */
 #include "f2c.h"
 
 #ifdef HAVE_CONFIG
index 1a6675ef119a39f0fd8f32ee85ce68e10e10aa3f..233db74b996fc32653ed302bd9beacbcf834d5d4 100644 (file)
@@ -1,7 +1,7 @@
 /*
-NOTE: This is generated code. Look in Misc/lapack_lite for information on
     remaking this file.
-*/
+ * NOTE: This is generated code. Look in numpy/linalg/lapack_lite for
*       information on remaking this file.
+ */
 #include "f2c.h"
 
 #ifdef HAVE_CONFIG
index d956ddbbb744ba383b8eb9fa9fbfc39585cf79c1..752261044bf8382a76c3160bbf360127c7fd28b8 100644 (file)
@@ -1,7 +1,7 @@
 /*
-NOTE: This is generated code. Look in Misc/lapack_lite for information on
     remaking this file.
-*/
+ * NOTE: This is generated code. Look in numpy/linalg/lapack_lite for
*       information on remaking this file.
+ */
 #include "f2c.h"
 
 #ifdef HAVE_CONFIG
index fccb1f58b553e7efe0617d8dd325ebcaa882c2cf..2a32315c71b5657eed1c85ef2642165936cfbbe6 100644 (file)
@@ -1,7 +1,7 @@
 /*
-NOTE: This is generated code. Look in Misc/lapack_lite for information on
     remaking this file.
-*/
+ * NOTE: This is generated code. Look in numpy/linalg/lapack_lite for
*       information on remaking this file.
+ */
 #include "f2c.h"
 
 #ifdef HAVE_CONFIG
index 0f11f2e725e3c888b6b2baa77ff3a72cc4a45b22..8234eca41080fa746eb3c337c438d04b87c3abd4 100644 (file)
@@ -1,7 +1,7 @@
 /*
-NOTE: This is generated code. Look in Misc/lapack_lite for information on
     remaking this file.
-*/
+ * NOTE: This is generated code. Look in numpy/linalg/lapack_lite for
*       information on remaking this file.
+ */
 #include "f2c.h"
 
 #ifdef HAVE_CONFIG
index dc0a5ebd90ba1dc798dac96185274cbad9f0dfcb..3aaefb92f14c5446bc05ebff2d7c99f7f7e0bfd2 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import re
 import itertools
 
@@ -14,7 +12,7 @@ def isContinuation(line):
 
 COMMENT, STATEMENT, CONTINUATION = 0, 1, 2
 def lineType(line):
-    """Return the type of a line of Fortan code."""
+    """Return the type of a line of Fortran code."""
     if isBlank(line):
         return COMMENT
     elif isLabel(line):
@@ -26,7 +24,7 @@ def lineType(line):
     else:
         return STATEMENT
 
-class LineIterator(object):
+class LineIterator:
     """LineIterator(iterable)
 
     Return rstrip()'d lines from iterable, while keeping a count of the
@@ -46,10 +44,8 @@ class LineIterator(object):
         line = line.rstrip()
         return line
 
-    next = __next__
-
 
-class PushbackIterator(object):
+class PushbackIterator:
     """PushbackIterator(iterable)
 
     Return an iterator for which items can be pushed back into.
@@ -73,8 +69,6 @@ class PushbackIterator(object):
     def pushback(self, item):
         self.buffer.append(item)
 
-    next = __next__
-
 
 def fortranSourceLines(fo):
     """Return an iterator over statement lines of a Fortran source file.
diff --git a/numpy/linalg/lapack_lite/lapack_lite_names.h b/numpy/linalg/lapack_lite/lapack_lite_names.h
new file mode 100644 (file)
index 0000000..08fd725
--- /dev/null
@@ -0,0 +1,691 @@
+/*
+ * NOTE: This is generated code. Look in numpy/linalg/lapack_lite for
+ *       information on remaking this file.
+ */
+/*
+ * This file renames all BLAS/LAPACK and f2c symbols to avoid
+ * dynamic symbol name conflicts, in cases where e.g.
+ * integer sizes do not match with 'standard' ABI.
+ */
+#define caxpy_ BLAS_FUNC(caxpy)
+#define ccopy_ BLAS_FUNC(ccopy)
+#define cdotc_ BLAS_FUNC(cdotc)
+#define cdotu_ BLAS_FUNC(cdotu)
+#define cgebak_ BLAS_FUNC(cgebak)
+#define cgebal_ BLAS_FUNC(cgebal)
+#define cgebd2_ BLAS_FUNC(cgebd2)
+#define cgebrd_ BLAS_FUNC(cgebrd)
+#define cgeev_ BLAS_FUNC(cgeev)
+#define cgehd2_ BLAS_FUNC(cgehd2)
+#define cgehrd_ BLAS_FUNC(cgehrd)
+#define cgelq2_ BLAS_FUNC(cgelq2)
+#define cgelqf_ BLAS_FUNC(cgelqf)
+#define cgelsd_ BLAS_FUNC(cgelsd)
+#define cgemm_ BLAS_FUNC(cgemm)
+#define cgemv_ BLAS_FUNC(cgemv)
+#define cgeqr2_ BLAS_FUNC(cgeqr2)
+#define cgeqrf_ BLAS_FUNC(cgeqrf)
+#define cgerc_ BLAS_FUNC(cgerc)
+#define cgeru_ BLAS_FUNC(cgeru)
+#define cgesdd_ BLAS_FUNC(cgesdd)
+#define cgesv_ BLAS_FUNC(cgesv)
+#define cgetf2_ BLAS_FUNC(cgetf2)
+#define cgetrf_ BLAS_FUNC(cgetrf)
+#define cgetrs_ BLAS_FUNC(cgetrs)
+#define cheevd_ BLAS_FUNC(cheevd)
+#define chemv_ BLAS_FUNC(chemv)
+#define cher2_ BLAS_FUNC(cher2)
+#define cher2k_ BLAS_FUNC(cher2k)
+#define cherk_ BLAS_FUNC(cherk)
+#define chetd2_ BLAS_FUNC(chetd2)
+#define chetrd_ BLAS_FUNC(chetrd)
+#define chseqr_ BLAS_FUNC(chseqr)
+#define clabrd_ BLAS_FUNC(clabrd)
+#define clacgv_ BLAS_FUNC(clacgv)
+#define clacp2_ BLAS_FUNC(clacp2)
+#define clacpy_ BLAS_FUNC(clacpy)
+#define clacrm_ BLAS_FUNC(clacrm)
+#define cladiv_ BLAS_FUNC(cladiv)
+#define claed0_ BLAS_FUNC(claed0)
+#define claed7_ BLAS_FUNC(claed7)
+#define claed8_ BLAS_FUNC(claed8)
+#define clahqr_ BLAS_FUNC(clahqr)
+#define clahr2_ BLAS_FUNC(clahr2)
+#define clals0_ BLAS_FUNC(clals0)
+#define clalsa_ BLAS_FUNC(clalsa)
+#define clalsd_ BLAS_FUNC(clalsd)
+#define clange_ BLAS_FUNC(clange)
+#define clanhe_ BLAS_FUNC(clanhe)
+#define claqr0_ BLAS_FUNC(claqr0)
+#define claqr1_ BLAS_FUNC(claqr1)
+#define claqr2_ BLAS_FUNC(claqr2)
+#define claqr3_ BLAS_FUNC(claqr3)
+#define claqr4_ BLAS_FUNC(claqr4)
+#define claqr5_ BLAS_FUNC(claqr5)
+#define clarcm_ BLAS_FUNC(clarcm)
+#define clarf_ BLAS_FUNC(clarf)
+#define clarfb_ BLAS_FUNC(clarfb)
+#define clarfg_ BLAS_FUNC(clarfg)
+#define clarft_ BLAS_FUNC(clarft)
+#define clartg_ BLAS_FUNC(clartg)
+#define clascl_ BLAS_FUNC(clascl)
+#define claset_ BLAS_FUNC(claset)
+#define clasr_ BLAS_FUNC(clasr)
+#define classq_ BLAS_FUNC(classq)
+#define claswp_ BLAS_FUNC(claswp)
+#define clatrd_ BLAS_FUNC(clatrd)
+#define clatrs_ BLAS_FUNC(clatrs)
+#define clauu2_ BLAS_FUNC(clauu2)
+#define clauum_ BLAS_FUNC(clauum)
+#define cpotf2_ BLAS_FUNC(cpotf2)
+#define cpotrf_ BLAS_FUNC(cpotrf)
+#define cpotri_ BLAS_FUNC(cpotri)
+#define cpotrs_ BLAS_FUNC(cpotrs)
+#define crot_ BLAS_FUNC(crot)
+#define cscal_ BLAS_FUNC(cscal)
+#define csrot_ BLAS_FUNC(csrot)
+#define csscal_ BLAS_FUNC(csscal)
+#define cstedc_ BLAS_FUNC(cstedc)
+#define csteqr_ BLAS_FUNC(csteqr)
+#define cswap_ BLAS_FUNC(cswap)
+#define ctrevc_ BLAS_FUNC(ctrevc)
+#define ctrexc_ BLAS_FUNC(ctrexc)
+#define ctrmm_ BLAS_FUNC(ctrmm)
+#define ctrmv_ BLAS_FUNC(ctrmv)
+#define ctrsm_ BLAS_FUNC(ctrsm)
+#define ctrsv_ BLAS_FUNC(ctrsv)
+#define ctrti2_ BLAS_FUNC(ctrti2)
+#define ctrtri_ BLAS_FUNC(ctrtri)
+#define cung2r_ BLAS_FUNC(cung2r)
+#define cungbr_ BLAS_FUNC(cungbr)
+#define cunghr_ BLAS_FUNC(cunghr)
+#define cungl2_ BLAS_FUNC(cungl2)
+#define cunglq_ BLAS_FUNC(cunglq)
+#define cungqr_ BLAS_FUNC(cungqr)
+#define cunm2l_ BLAS_FUNC(cunm2l)
+#define cunm2r_ BLAS_FUNC(cunm2r)
+#define cunmbr_ BLAS_FUNC(cunmbr)
+#define cunmhr_ BLAS_FUNC(cunmhr)
+#define cunml2_ BLAS_FUNC(cunml2)
+#define cunmlq_ BLAS_FUNC(cunmlq)
+#define cunmql_ BLAS_FUNC(cunmql)
+#define cunmqr_ BLAS_FUNC(cunmqr)
+#define cunmtr_ BLAS_FUNC(cunmtr)
+#define daxpy_ BLAS_FUNC(daxpy)
+#define dbdsdc_ BLAS_FUNC(dbdsdc)
+#define dbdsqr_ BLAS_FUNC(dbdsqr)
+#define dcabs1_ BLAS_FUNC(dcabs1)
+#define dcopy_ BLAS_FUNC(dcopy)
+#define ddot_ BLAS_FUNC(ddot)
+#define dgebak_ BLAS_FUNC(dgebak)
+#define dgebal_ BLAS_FUNC(dgebal)
+#define dgebd2_ BLAS_FUNC(dgebd2)
+#define dgebrd_ BLAS_FUNC(dgebrd)
+#define dgeev_ BLAS_FUNC(dgeev)
+#define dgehd2_ BLAS_FUNC(dgehd2)
+#define dgehrd_ BLAS_FUNC(dgehrd)
+#define dgelq2_ BLAS_FUNC(dgelq2)
+#define dgelqf_ BLAS_FUNC(dgelqf)
+#define dgelsd_ BLAS_FUNC(dgelsd)
+#define dgemm_ BLAS_FUNC(dgemm)
+#define dgemv_ BLAS_FUNC(dgemv)
+#define dgeqr2_ BLAS_FUNC(dgeqr2)
+#define dgeqrf_ BLAS_FUNC(dgeqrf)
+#define dger_ BLAS_FUNC(dger)
+#define dgesdd_ BLAS_FUNC(dgesdd)
+#define dgesv_ BLAS_FUNC(dgesv)
+#define dgetf2_ BLAS_FUNC(dgetf2)
+#define dgetrf_ BLAS_FUNC(dgetrf)
+#define dgetrs_ BLAS_FUNC(dgetrs)
+#define dhseqr_ BLAS_FUNC(dhseqr)
+#define disnan_ BLAS_FUNC(disnan)
+#define dlabad_ BLAS_FUNC(dlabad)
+#define dlabrd_ BLAS_FUNC(dlabrd)
+#define dlacpy_ BLAS_FUNC(dlacpy)
+#define dladiv_ BLAS_FUNC(dladiv)
+#define dlae2_ BLAS_FUNC(dlae2)
+#define dlaed0_ BLAS_FUNC(dlaed0)
+#define dlaed1_ BLAS_FUNC(dlaed1)
+#define dlaed2_ BLAS_FUNC(dlaed2)
+#define dlaed3_ BLAS_FUNC(dlaed3)
+#define dlaed4_ BLAS_FUNC(dlaed4)
+#define dlaed5_ BLAS_FUNC(dlaed5)
+#define dlaed6_ BLAS_FUNC(dlaed6)
+#define dlaed7_ BLAS_FUNC(dlaed7)
+#define dlaed8_ BLAS_FUNC(dlaed8)
+#define dlaed9_ BLAS_FUNC(dlaed9)
+#define dlaeda_ BLAS_FUNC(dlaeda)
+#define dlaev2_ BLAS_FUNC(dlaev2)
+#define dlaexc_ BLAS_FUNC(dlaexc)
+#define dlahqr_ BLAS_FUNC(dlahqr)
+#define dlahr2_ BLAS_FUNC(dlahr2)
+#define dlaisnan_ BLAS_FUNC(dlaisnan)
+#define dlaln2_ BLAS_FUNC(dlaln2)
+#define dlals0_ BLAS_FUNC(dlals0)
+#define dlalsa_ BLAS_FUNC(dlalsa)
+#define dlalsd_ BLAS_FUNC(dlalsd)
+#define dlamc1_ BLAS_FUNC(dlamc1)
+#define dlamc2_ BLAS_FUNC(dlamc2)
+#define dlamc3_ BLAS_FUNC(dlamc3)
+#define dlamc4_ BLAS_FUNC(dlamc4)
+#define dlamc5_ BLAS_FUNC(dlamc5)
+#define dlamch_ BLAS_FUNC(dlamch)
+#define dlamrg_ BLAS_FUNC(dlamrg)
+#define dlange_ BLAS_FUNC(dlange)
+#define dlanst_ BLAS_FUNC(dlanst)
+#define dlansy_ BLAS_FUNC(dlansy)
+#define dlanv2_ BLAS_FUNC(dlanv2)
+#define dlapy2_ BLAS_FUNC(dlapy2)
+#define dlapy3_ BLAS_FUNC(dlapy3)
+#define dlaqr0_ BLAS_FUNC(dlaqr0)
+#define dlaqr1_ BLAS_FUNC(dlaqr1)
+#define dlaqr2_ BLAS_FUNC(dlaqr2)
+#define dlaqr3_ BLAS_FUNC(dlaqr3)
+#define dlaqr4_ BLAS_FUNC(dlaqr4)
+#define dlaqr5_ BLAS_FUNC(dlaqr5)
+#define dlarf_ BLAS_FUNC(dlarf)
+#define dlarfb_ BLAS_FUNC(dlarfb)
+#define dlarfg_ BLAS_FUNC(dlarfg)
+#define dlarft_ BLAS_FUNC(dlarft)
+#define dlarfx_ BLAS_FUNC(dlarfx)
+#define dlartg_ BLAS_FUNC(dlartg)
+#define dlas2_ BLAS_FUNC(dlas2)
+#define dlascl_ BLAS_FUNC(dlascl)
+#define dlasd0_ BLAS_FUNC(dlasd0)
+#define dlasd1_ BLAS_FUNC(dlasd1)
+#define dlasd2_ BLAS_FUNC(dlasd2)
+#define dlasd3_ BLAS_FUNC(dlasd3)
+#define dlasd4_ BLAS_FUNC(dlasd4)
+#define dlasd5_ BLAS_FUNC(dlasd5)
+#define dlasd6_ BLAS_FUNC(dlasd6)
+#define dlasd7_ BLAS_FUNC(dlasd7)
+#define dlasd8_ BLAS_FUNC(dlasd8)
+#define dlasda_ BLAS_FUNC(dlasda)
+#define dlasdq_ BLAS_FUNC(dlasdq)
+#define dlasdt_ BLAS_FUNC(dlasdt)
+#define dlaset_ BLAS_FUNC(dlaset)
+#define dlasq1_ BLAS_FUNC(dlasq1)
+#define dlasq2_ BLAS_FUNC(dlasq2)
+#define dlasq3_ BLAS_FUNC(dlasq3)
+#define dlasq4_ BLAS_FUNC(dlasq4)
+#define dlasq5_ BLAS_FUNC(dlasq5)
+#define dlasq6_ BLAS_FUNC(dlasq6)
+#define dlasr_ BLAS_FUNC(dlasr)
+#define dlasrt_ BLAS_FUNC(dlasrt)
+#define dlassq_ BLAS_FUNC(dlassq)
+#define dlasv2_ BLAS_FUNC(dlasv2)
+#define dlaswp_ BLAS_FUNC(dlaswp)
+#define dlasy2_ BLAS_FUNC(dlasy2)
+#define dlatrd_ BLAS_FUNC(dlatrd)
+#define dlauu2_ BLAS_FUNC(dlauu2)
+#define dlauum_ BLAS_FUNC(dlauum)
+#define dnrm2_ BLAS_FUNC(dnrm2)
+#define dorg2r_ BLAS_FUNC(dorg2r)
+#define dorgbr_ BLAS_FUNC(dorgbr)
+#define dorghr_ BLAS_FUNC(dorghr)
+#define dorgl2_ BLAS_FUNC(dorgl2)
+#define dorglq_ BLAS_FUNC(dorglq)
+#define dorgqr_ BLAS_FUNC(dorgqr)
+#define dorm2l_ BLAS_FUNC(dorm2l)
+#define dorm2r_ BLAS_FUNC(dorm2r)
+#define dormbr_ BLAS_FUNC(dormbr)
+#define dormhr_ BLAS_FUNC(dormhr)
+#define dorml2_ BLAS_FUNC(dorml2)
+#define dormlq_ BLAS_FUNC(dormlq)
+#define dormql_ BLAS_FUNC(dormql)
+#define dormqr_ BLAS_FUNC(dormqr)
+#define dormtr_ BLAS_FUNC(dormtr)
+#define dpotf2_ BLAS_FUNC(dpotf2)
+#define dpotrf_ BLAS_FUNC(dpotrf)
+#define dpotri_ BLAS_FUNC(dpotri)
+#define dpotrs_ BLAS_FUNC(dpotrs)
+#define drot_ BLAS_FUNC(drot)
+#define dscal_ BLAS_FUNC(dscal)
+#define dstedc_ BLAS_FUNC(dstedc)
+#define dsteqr_ BLAS_FUNC(dsteqr)
+#define dsterf_ BLAS_FUNC(dsterf)
+#define dswap_ BLAS_FUNC(dswap)
+#define dsyevd_ BLAS_FUNC(dsyevd)
+#define dsymv_ BLAS_FUNC(dsymv)
+#define dsyr2_ BLAS_FUNC(dsyr2)
+#define dsyr2k_ BLAS_FUNC(dsyr2k)
+#define dsyrk_ BLAS_FUNC(dsyrk)
+#define dsytd2_ BLAS_FUNC(dsytd2)
+#define dsytrd_ BLAS_FUNC(dsytrd)
+#define dtrevc_ BLAS_FUNC(dtrevc)
+#define dtrexc_ BLAS_FUNC(dtrexc)
+#define dtrmm_ BLAS_FUNC(dtrmm)
+#define dtrmv_ BLAS_FUNC(dtrmv)
+#define dtrsm_ BLAS_FUNC(dtrsm)
+#define dtrti2_ BLAS_FUNC(dtrti2)
+#define dtrtri_ BLAS_FUNC(dtrtri)
+#define dzasum_ BLAS_FUNC(dzasum)
+#define dznrm2_ BLAS_FUNC(dznrm2)
+#define icamax_ BLAS_FUNC(icamax)
+#define idamax_ BLAS_FUNC(idamax)
+#define ieeeck_ BLAS_FUNC(ieeeck)
+#define ilaclc_ BLAS_FUNC(ilaclc)
+#define ilaclr_ BLAS_FUNC(ilaclr)
+#define iladlc_ BLAS_FUNC(iladlc)
+#define iladlr_ BLAS_FUNC(iladlr)
+#define ilaenv_ BLAS_FUNC(ilaenv)
+#define ilaslc_ BLAS_FUNC(ilaslc)
+#define ilaslr_ BLAS_FUNC(ilaslr)
+#define ilazlc_ BLAS_FUNC(ilazlc)
+#define ilazlr_ BLAS_FUNC(ilazlr)
+#define iparmq_ BLAS_FUNC(iparmq)
+#define isamax_ BLAS_FUNC(isamax)
+#define izamax_ BLAS_FUNC(izamax)
+#define lsame_ BLAS_FUNC(lsame)
+#define saxpy_ BLAS_FUNC(saxpy)
+#define sbdsdc_ BLAS_FUNC(sbdsdc)
+#define sbdsqr_ BLAS_FUNC(sbdsqr)
+#define scabs1_ BLAS_FUNC(scabs1)
+#define scasum_ BLAS_FUNC(scasum)
+#define scnrm2_ BLAS_FUNC(scnrm2)
+#define scopy_ BLAS_FUNC(scopy)
+#define sdot_ BLAS_FUNC(sdot)
+#define sgebak_ BLAS_FUNC(sgebak)
+#define sgebal_ BLAS_FUNC(sgebal)
+#define sgebd2_ BLAS_FUNC(sgebd2)
+#define sgebrd_ BLAS_FUNC(sgebrd)
+#define sgeev_ BLAS_FUNC(sgeev)
+#define sgehd2_ BLAS_FUNC(sgehd2)
+#define sgehrd_ BLAS_FUNC(sgehrd)
+#define sgelq2_ BLAS_FUNC(sgelq2)
+#define sgelqf_ BLAS_FUNC(sgelqf)
+#define sgelsd_ BLAS_FUNC(sgelsd)
+#define sgemm_ BLAS_FUNC(sgemm)
+#define sgemv_ BLAS_FUNC(sgemv)
+#define sgeqr2_ BLAS_FUNC(sgeqr2)
+#define sgeqrf_ BLAS_FUNC(sgeqrf)
+#define sger_ BLAS_FUNC(sger)
+#define sgesdd_ BLAS_FUNC(sgesdd)
+#define sgesv_ BLAS_FUNC(sgesv)
+#define sgetf2_ BLAS_FUNC(sgetf2)
+#define sgetrf_ BLAS_FUNC(sgetrf)
+#define sgetrs_ BLAS_FUNC(sgetrs)
+#define shseqr_ BLAS_FUNC(shseqr)
+#define sisnan_ BLAS_FUNC(sisnan)
+#define slabad_ BLAS_FUNC(slabad)
+#define slabrd_ BLAS_FUNC(slabrd)
+#define slacpy_ BLAS_FUNC(slacpy)
+#define sladiv_ BLAS_FUNC(sladiv)
+#define slae2_ BLAS_FUNC(slae2)
+#define slaed0_ BLAS_FUNC(slaed0)
+#define slaed1_ BLAS_FUNC(slaed1)
+#define slaed2_ BLAS_FUNC(slaed2)
+#define slaed3_ BLAS_FUNC(slaed3)
+#define slaed4_ BLAS_FUNC(slaed4)
+#define slaed5_ BLAS_FUNC(slaed5)
+#define slaed6_ BLAS_FUNC(slaed6)
+#define slaed7_ BLAS_FUNC(slaed7)
+#define slaed8_ BLAS_FUNC(slaed8)
+#define slaed9_ BLAS_FUNC(slaed9)
+#define slaeda_ BLAS_FUNC(slaeda)
+#define slaev2_ BLAS_FUNC(slaev2)
+#define slaexc_ BLAS_FUNC(slaexc)
+#define slahqr_ BLAS_FUNC(slahqr)
+#define slahr2_ BLAS_FUNC(slahr2)
+#define slaisnan_ BLAS_FUNC(slaisnan)
+#define slaln2_ BLAS_FUNC(slaln2)
+#define slals0_ BLAS_FUNC(slals0)
+#define slalsa_ BLAS_FUNC(slalsa)
+#define slalsd_ BLAS_FUNC(slalsd)
+#define slamc1_ BLAS_FUNC(slamc1)
+#define slamc2_ BLAS_FUNC(slamc2)
+#define slamc3_ BLAS_FUNC(slamc3)
+#define slamc4_ BLAS_FUNC(slamc4)
+#define slamc5_ BLAS_FUNC(slamc5)
+#define slamch_ BLAS_FUNC(slamch)
+#define slamrg_ BLAS_FUNC(slamrg)
+#define slange_ BLAS_FUNC(slange)
+#define slanst_ BLAS_FUNC(slanst)
+#define slansy_ BLAS_FUNC(slansy)
+#define slanv2_ BLAS_FUNC(slanv2)
+#define slapy2_ BLAS_FUNC(slapy2)
+#define slapy3_ BLAS_FUNC(slapy3)
+#define slaqr0_ BLAS_FUNC(slaqr0)
+#define slaqr1_ BLAS_FUNC(slaqr1)
+#define slaqr2_ BLAS_FUNC(slaqr2)
+#define slaqr3_ BLAS_FUNC(slaqr3)
+#define slaqr4_ BLAS_FUNC(slaqr4)
+#define slaqr5_ BLAS_FUNC(slaqr5)
+#define slarf_ BLAS_FUNC(slarf)
+#define slarfb_ BLAS_FUNC(slarfb)
+#define slarfg_ BLAS_FUNC(slarfg)
+#define slarft_ BLAS_FUNC(slarft)
+#define slarfx_ BLAS_FUNC(slarfx)
+#define slartg_ BLAS_FUNC(slartg)
+#define slas2_ BLAS_FUNC(slas2)
+#define slascl_ BLAS_FUNC(slascl)
+#define slasd0_ BLAS_FUNC(slasd0)
+#define slasd1_ BLAS_FUNC(slasd1)
+#define slasd2_ BLAS_FUNC(slasd2)
+#define slasd3_ BLAS_FUNC(slasd3)
+#define slasd4_ BLAS_FUNC(slasd4)
+#define slasd5_ BLAS_FUNC(slasd5)
+#define slasd6_ BLAS_FUNC(slasd6)
+#define slasd7_ BLAS_FUNC(slasd7)
+#define slasd8_ BLAS_FUNC(slasd8)
+#define slasda_ BLAS_FUNC(slasda)
+#define slasdq_ BLAS_FUNC(slasdq)
+#define slasdt_ BLAS_FUNC(slasdt)
+#define slaset_ BLAS_FUNC(slaset)
+#define slasq1_ BLAS_FUNC(slasq1)
+#define slasq2_ BLAS_FUNC(slasq2)
+#define slasq3_ BLAS_FUNC(slasq3)
+#define slasq4_ BLAS_FUNC(slasq4)
+#define slasq5_ BLAS_FUNC(slasq5)
+#define slasq6_ BLAS_FUNC(slasq6)
+#define slasr_ BLAS_FUNC(slasr)
+#define slasrt_ BLAS_FUNC(slasrt)
+#define slassq_ BLAS_FUNC(slassq)
+#define slasv2_ BLAS_FUNC(slasv2)
+#define slaswp_ BLAS_FUNC(slaswp)
+#define slasy2_ BLAS_FUNC(slasy2)
+#define slatrd_ BLAS_FUNC(slatrd)
+#define slauu2_ BLAS_FUNC(slauu2)
+#define slauum_ BLAS_FUNC(slauum)
+#define snrm2_ BLAS_FUNC(snrm2)
+#define sorg2r_ BLAS_FUNC(sorg2r)
+#define sorgbr_ BLAS_FUNC(sorgbr)
+#define sorghr_ BLAS_FUNC(sorghr)
+#define sorgl2_ BLAS_FUNC(sorgl2)
+#define sorglq_ BLAS_FUNC(sorglq)
+#define sorgqr_ BLAS_FUNC(sorgqr)
+#define sorm2l_ BLAS_FUNC(sorm2l)
+#define sorm2r_ BLAS_FUNC(sorm2r)
+#define sormbr_ BLAS_FUNC(sormbr)
+#define sormhr_ BLAS_FUNC(sormhr)
+#define sorml2_ BLAS_FUNC(sorml2)
+#define sormlq_ BLAS_FUNC(sormlq)
+#define sormql_ BLAS_FUNC(sormql)
+#define sormqr_ BLAS_FUNC(sormqr)
+#define sormtr_ BLAS_FUNC(sormtr)
+#define spotf2_ BLAS_FUNC(spotf2)
+#define spotrf_ BLAS_FUNC(spotrf)
+#define spotri_ BLAS_FUNC(spotri)
+#define spotrs_ BLAS_FUNC(spotrs)
+#define srot_ BLAS_FUNC(srot)
+#define sscal_ BLAS_FUNC(sscal)
+#define sstedc_ BLAS_FUNC(sstedc)
+#define ssteqr_ BLAS_FUNC(ssteqr)
+#define ssterf_ BLAS_FUNC(ssterf)
+#define sswap_ BLAS_FUNC(sswap)
+#define ssyevd_ BLAS_FUNC(ssyevd)
+#define ssymv_ BLAS_FUNC(ssymv)
+#define ssyr2_ BLAS_FUNC(ssyr2)
+#define ssyr2k_ BLAS_FUNC(ssyr2k)
+#define ssyrk_ BLAS_FUNC(ssyrk)
+#define ssytd2_ BLAS_FUNC(ssytd2)
+#define ssytrd_ BLAS_FUNC(ssytrd)
+#define strevc_ BLAS_FUNC(strevc)
+#define strexc_ BLAS_FUNC(strexc)
+#define strmm_ BLAS_FUNC(strmm)
+#define strmv_ BLAS_FUNC(strmv)
+#define strsm_ BLAS_FUNC(strsm)
+#define strti2_ BLAS_FUNC(strti2)
+#define strtri_ BLAS_FUNC(strtri)
+#define xerbla_ BLAS_FUNC(xerbla)
+#define zaxpy_ BLAS_FUNC(zaxpy)
+#define zcopy_ BLAS_FUNC(zcopy)
+#define zdotc_ BLAS_FUNC(zdotc)
+#define zdotu_ BLAS_FUNC(zdotu)
+#define zdrot_ BLAS_FUNC(zdrot)
+#define zdscal_ BLAS_FUNC(zdscal)
+#define zgebak_ BLAS_FUNC(zgebak)
+#define zgebal_ BLAS_FUNC(zgebal)
+#define zgebd2_ BLAS_FUNC(zgebd2)
+#define zgebrd_ BLAS_FUNC(zgebrd)
+#define zgeev_ BLAS_FUNC(zgeev)
+#define zgehd2_ BLAS_FUNC(zgehd2)
+#define zgehrd_ BLAS_FUNC(zgehrd)
+#define zgelq2_ BLAS_FUNC(zgelq2)
+#define zgelqf_ BLAS_FUNC(zgelqf)
+#define zgelsd_ BLAS_FUNC(zgelsd)
+#define zgemm_ BLAS_FUNC(zgemm)
+#define zgemv_ BLAS_FUNC(zgemv)
+#define zgeqr2_ BLAS_FUNC(zgeqr2)
+#define zgeqrf_ BLAS_FUNC(zgeqrf)
+#define zgerc_ BLAS_FUNC(zgerc)
+#define zgeru_ BLAS_FUNC(zgeru)
+#define zgesdd_ BLAS_FUNC(zgesdd)
+#define zgesv_ BLAS_FUNC(zgesv)
+#define zgetf2_ BLAS_FUNC(zgetf2)
+#define zgetrf_ BLAS_FUNC(zgetrf)
+#define zgetrs_ BLAS_FUNC(zgetrs)
+#define zheevd_ BLAS_FUNC(zheevd)
+#define zhemv_ BLAS_FUNC(zhemv)
+#define zher2_ BLAS_FUNC(zher2)
+#define zher2k_ BLAS_FUNC(zher2k)
+#define zherk_ BLAS_FUNC(zherk)
+#define zhetd2_ BLAS_FUNC(zhetd2)
+#define zhetrd_ BLAS_FUNC(zhetrd)
+#define zhseqr_ BLAS_FUNC(zhseqr)
+#define zlabrd_ BLAS_FUNC(zlabrd)
+#define zlacgv_ BLAS_FUNC(zlacgv)
+#define zlacp2_ BLAS_FUNC(zlacp2)
+#define zlacpy_ BLAS_FUNC(zlacpy)
+#define zlacrm_ BLAS_FUNC(zlacrm)
+#define zladiv_ BLAS_FUNC(zladiv)
+#define zlaed0_ BLAS_FUNC(zlaed0)
+#define zlaed7_ BLAS_FUNC(zlaed7)
+#define zlaed8_ BLAS_FUNC(zlaed8)
+#define zlahqr_ BLAS_FUNC(zlahqr)
+#define zlahr2_ BLAS_FUNC(zlahr2)
+#define zlals0_ BLAS_FUNC(zlals0)
+#define zlalsa_ BLAS_FUNC(zlalsa)
+#define zlalsd_ BLAS_FUNC(zlalsd)
+#define zlange_ BLAS_FUNC(zlange)
+#define zlanhe_ BLAS_FUNC(zlanhe)
+#define zlaqr0_ BLAS_FUNC(zlaqr0)
+#define zlaqr1_ BLAS_FUNC(zlaqr1)
+#define zlaqr2_ BLAS_FUNC(zlaqr2)
+#define zlaqr3_ BLAS_FUNC(zlaqr3)
+#define zlaqr4_ BLAS_FUNC(zlaqr4)
+#define zlaqr5_ BLAS_FUNC(zlaqr5)
+#define zlarcm_ BLAS_FUNC(zlarcm)
+#define zlarf_ BLAS_FUNC(zlarf)
+#define zlarfb_ BLAS_FUNC(zlarfb)
+#define zlarfg_ BLAS_FUNC(zlarfg)
+#define zlarft_ BLAS_FUNC(zlarft)
+#define zlartg_ BLAS_FUNC(zlartg)
+#define zlascl_ BLAS_FUNC(zlascl)
+#define zlaset_ BLAS_FUNC(zlaset)
+#define zlasr_ BLAS_FUNC(zlasr)
+#define zlassq_ BLAS_FUNC(zlassq)
+#define zlaswp_ BLAS_FUNC(zlaswp)
+#define zlatrd_ BLAS_FUNC(zlatrd)
+#define zlatrs_ BLAS_FUNC(zlatrs)
+#define zlauu2_ BLAS_FUNC(zlauu2)
+#define zlauum_ BLAS_FUNC(zlauum)
+#define zpotf2_ BLAS_FUNC(zpotf2)
+#define zpotrf_ BLAS_FUNC(zpotrf)
+#define zpotri_ BLAS_FUNC(zpotri)
+#define zpotrs_ BLAS_FUNC(zpotrs)
+#define zrot_ BLAS_FUNC(zrot)
+#define zscal_ BLAS_FUNC(zscal)
+#define zstedc_ BLAS_FUNC(zstedc)
+#define zsteqr_ BLAS_FUNC(zsteqr)
+#define zswap_ BLAS_FUNC(zswap)
+#define ztrevc_ BLAS_FUNC(ztrevc)
+#define ztrexc_ BLAS_FUNC(ztrexc)
+#define ztrmm_ BLAS_FUNC(ztrmm)
+#define ztrmv_ BLAS_FUNC(ztrmv)
+#define ztrsm_ BLAS_FUNC(ztrsm)
+#define ztrsv_ BLAS_FUNC(ztrsv)
+#define ztrti2_ BLAS_FUNC(ztrti2)
+#define ztrtri_ BLAS_FUNC(ztrtri)
+#define zung2r_ BLAS_FUNC(zung2r)
+#define zungbr_ BLAS_FUNC(zungbr)
+#define zunghr_ BLAS_FUNC(zunghr)
+#define zungl2_ BLAS_FUNC(zungl2)
+#define zunglq_ BLAS_FUNC(zunglq)
+#define zungqr_ BLAS_FUNC(zungqr)
+#define zunm2l_ BLAS_FUNC(zunm2l)
+#define zunm2r_ BLAS_FUNC(zunm2r)
+#define zunmbr_ BLAS_FUNC(zunmbr)
+#define zunmhr_ BLAS_FUNC(zunmhr)
+#define zunml2_ BLAS_FUNC(zunml2)
+#define zunmlq_ BLAS_FUNC(zunmlq)
+#define zunmql_ BLAS_FUNC(zunmql)
+#define zunmqr_ BLAS_FUNC(zunmqr)
+#define zunmtr_ BLAS_FUNC(zunmtr)
+
+/* Symbols exported by f2c.c */
+#define abort_ numpy_lapack_lite_abort_
+#define c_abs numpy_lapack_lite_c_abs
+#define c_cos numpy_lapack_lite_c_cos
+#define c_div numpy_lapack_lite_c_div
+#define c_exp numpy_lapack_lite_c_exp
+#define c_log numpy_lapack_lite_c_log
+#define c_sin numpy_lapack_lite_c_sin
+#define c_sqrt numpy_lapack_lite_c_sqrt
+#define d_abs numpy_lapack_lite_d_abs
+#define d_acos numpy_lapack_lite_d_acos
+#define d_asin numpy_lapack_lite_d_asin
+#define d_atan numpy_lapack_lite_d_atan
+#define d_atn2 numpy_lapack_lite_d_atn2
+#define d_cnjg numpy_lapack_lite_d_cnjg
+#define d_cos numpy_lapack_lite_d_cos
+#define d_cosh numpy_lapack_lite_d_cosh
+#define d_dim numpy_lapack_lite_d_dim
+#define d_exp numpy_lapack_lite_d_exp
+#define d_imag numpy_lapack_lite_d_imag
+#define d_int numpy_lapack_lite_d_int
+#define d_lg10 numpy_lapack_lite_d_lg10
+#define d_log numpy_lapack_lite_d_log
+#define d_mod numpy_lapack_lite_d_mod
+#define d_nint numpy_lapack_lite_d_nint
+#define d_prod numpy_lapack_lite_d_prod
+#define d_sign numpy_lapack_lite_d_sign
+#define d_sin numpy_lapack_lite_d_sin
+#define d_sinh numpy_lapack_lite_d_sinh
+#define d_sqrt numpy_lapack_lite_d_sqrt
+#define d_tan numpy_lapack_lite_d_tan
+#define d_tanh numpy_lapack_lite_d_tanh
+#define derf_ numpy_lapack_lite_derf_
+#define derfc_ numpy_lapack_lite_derfc_
+#define do_fio numpy_lapack_lite_do_fio
+#define do_lio numpy_lapack_lite_do_lio
+#define do_uio numpy_lapack_lite_do_uio
+#define e_rdfe numpy_lapack_lite_e_rdfe
+#define e_rdue numpy_lapack_lite_e_rdue
+#define e_rsfe numpy_lapack_lite_e_rsfe
+#define e_rsfi numpy_lapack_lite_e_rsfi
+#define e_rsle numpy_lapack_lite_e_rsle
+#define e_rsli numpy_lapack_lite_e_rsli
+#define e_rsue numpy_lapack_lite_e_rsue
+#define e_wdfe numpy_lapack_lite_e_wdfe
+#define e_wdue numpy_lapack_lite_e_wdue
+#define e_wsfe numpy_lapack_lite_e_wsfe
+#define e_wsfi numpy_lapack_lite_e_wsfi
+#define e_wsle numpy_lapack_lite_e_wsle
+#define e_wsli numpy_lapack_lite_e_wsli
+#define e_wsue numpy_lapack_lite_e_wsue
+#define ef1asc_ numpy_lapack_lite_ef1asc_
+#define ef1cmc_ numpy_lapack_lite_ef1cmc_
+#define erf_ numpy_lapack_lite_erf_
+#define erfc_ numpy_lapack_lite_erfc_
+#define f__cabs numpy_lapack_lite_f__cabs
+#define f__cabsf numpy_lapack_lite_f__cabsf
+#define f_back numpy_lapack_lite_f_back
+#define f_clos numpy_lapack_lite_f_clos
+#define f_end numpy_lapack_lite_f_end
+#define f_exit numpy_lapack_lite_f_exit
+#define f_inqu numpy_lapack_lite_f_inqu
+#define f_open numpy_lapack_lite_f_open
+#define f_rew numpy_lapack_lite_f_rew
+#define flush_ numpy_lapack_lite_flush_
+#define getarg_ numpy_lapack_lite_getarg_
+#define getenv_ numpy_lapack_lite_getenv_
+#define h_abs numpy_lapack_lite_h_abs
+#define h_dim numpy_lapack_lite_h_dim
+#define h_dnnt numpy_lapack_lite_h_dnnt
+#define h_indx numpy_lapack_lite_h_indx
+#define h_len numpy_lapack_lite_h_len
+#define h_mod numpy_lapack_lite_h_mod
+#define h_nint numpy_lapack_lite_h_nint
+#define h_sign numpy_lapack_lite_h_sign
+#define hl_ge numpy_lapack_lite_hl_ge
+#define hl_gt numpy_lapack_lite_hl_gt
+#define hl_le numpy_lapack_lite_hl_le
+#define hl_lt numpy_lapack_lite_hl_lt
+#define i_abs numpy_lapack_lite_i_abs
+#define i_dim numpy_lapack_lite_i_dim
+#define i_dnnt numpy_lapack_lite_i_dnnt
+#define i_indx numpy_lapack_lite_i_indx
+#define i_len numpy_lapack_lite_i_len
+#define i_mod numpy_lapack_lite_i_mod
+#define i_nint numpy_lapack_lite_i_nint
+#define i_sign numpy_lapack_lite_i_sign
+#define iargc_ numpy_lapack_lite_iargc_
+#define l_ge numpy_lapack_lite_l_ge
+#define l_gt numpy_lapack_lite_l_gt
+#define l_le numpy_lapack_lite_l_le
+#define l_lt numpy_lapack_lite_l_lt
+#define pow_ci numpy_lapack_lite_pow_ci
+#define pow_dd numpy_lapack_lite_pow_dd
+#define pow_di numpy_lapack_lite_pow_di
+#define pow_hh numpy_lapack_lite_pow_hh
+#define pow_ii numpy_lapack_lite_pow_ii
+#define pow_ri numpy_lapack_lite_pow_ri
+#define pow_zi numpy_lapack_lite_pow_zi
+#define pow_zz numpy_lapack_lite_pow_zz
+#define r_abs numpy_lapack_lite_r_abs
+#define r_acos numpy_lapack_lite_r_acos
+#define r_asin numpy_lapack_lite_r_asin
+#define r_atan numpy_lapack_lite_r_atan
+#define r_atn2 numpy_lapack_lite_r_atn2
+#define r_cnjg numpy_lapack_lite_r_cnjg
+#define r_cos numpy_lapack_lite_r_cos
+#define r_cosh numpy_lapack_lite_r_cosh
+#define r_dim numpy_lapack_lite_r_dim
+#define r_exp numpy_lapack_lite_r_exp
+#define r_imag numpy_lapack_lite_r_imag
+#define r_int numpy_lapack_lite_r_int
+#define r_lg10 numpy_lapack_lite_r_lg10
+#define r_log numpy_lapack_lite_r_log
+#define r_mod numpy_lapack_lite_r_mod
+#define r_nint numpy_lapack_lite_r_nint
+#define r_sign numpy_lapack_lite_r_sign
+#define r_sin numpy_lapack_lite_r_sin
+#define r_sinh numpy_lapack_lite_r_sinh
+#define r_sqrt numpy_lapack_lite_r_sqrt
+#define r_tan numpy_lapack_lite_r_tan
+#define r_tanh numpy_lapack_lite_r_tanh
+#define s_cat numpy_lapack_lite_s_cat
+#define s_cmp numpy_lapack_lite_s_cmp
+#define s_copy numpy_lapack_lite_s_copy
+#define s_paus numpy_lapack_lite_s_paus
+#define s_rdfe numpy_lapack_lite_s_rdfe
+#define s_rdue numpy_lapack_lite_s_rdue
+#define s_rnge numpy_lapack_lite_s_rnge
+#define s_rsfe numpy_lapack_lite_s_rsfe
+#define s_rsfi numpy_lapack_lite_s_rsfi
+#define s_rsle numpy_lapack_lite_s_rsle
+#define s_rsli numpy_lapack_lite_s_rsli
+#define s_rsne numpy_lapack_lite_s_rsne
+#define s_rsni numpy_lapack_lite_s_rsni
+#define s_rsue numpy_lapack_lite_s_rsue
+#define s_stop numpy_lapack_lite_s_stop
+#define s_wdfe numpy_lapack_lite_s_wdfe
+#define s_wdue numpy_lapack_lite_s_wdue
+#define s_wsfe numpy_lapack_lite_s_wsfe
+#define s_wsfi numpy_lapack_lite_s_wsfi
+#define s_wsle numpy_lapack_lite_s_wsle
+#define s_wsli numpy_lapack_lite_s_wsli
+#define s_wsne numpy_lapack_lite_s_wsne
+#define s_wsni numpy_lapack_lite_s_wsni
+#define s_wsue numpy_lapack_lite_s_wsue
+#define sig_die numpy_lapack_lite_sig_die
+#define signal_ numpy_lapack_lite_signal_
+#define system_ numpy_lapack_lite_system_
+#define z_abs numpy_lapack_lite_z_abs
+#define z_cos numpy_lapack_lite_z_cos
+#define z_div numpy_lapack_lite_z_div
+#define z_exp numpy_lapack_lite_z_exp
+#define z_log numpy_lapack_lite_z_log
+#define z_sin numpy_lapack_lite_z_sin
+#define z_sqrt numpy_lapack_lite_z_sqrt
index 61102d6ab07ec82b552c4956d466eefb522f705f..23921acf4bd544832a287a9bf17b84d7ce4df8dc 100755 (executable)
@@ -1,6 +1,6 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
-Usage: make_lite.py <wrapped_routines_file> <lapack_dir> <output_dir>
+Usage: make_lite.py <wrapped_routines_file> <lapack_dir>
 
 Typical invocation:
 
@@ -11,22 +11,16 @@ Requires the following to be on the path:
  * patch
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 import os
+import re
 import subprocess
 import shutil
 
 import fortran
 import clapack_scrub
 
-PY2 = sys.version_info < (3, 0)
-
-if PY2:
-    from distutils.spawn import find_executable as which
-else:
-    from shutil import which
+from shutil import which
 
 # Arguments to pass to f2c. You'll always want -A for ANSI C prototypes
 # Others of interest: -a to not make variables static by default
@@ -35,11 +29,14 @@ F2C_ARGS = ['-A', '-Nx800']
 
 # The header to add to the top of the f2c_*.c file. Note that dlamch_() calls
 # will be replaced by the macros below by clapack_scrub.scrub_source()
-HEADER = '''\
+HEADER_BLURB = '''\
 /*
-NOTE: This is generated code. Look in Misc/lapack_lite for information on
-      remaking this file.
-*/
+ * NOTE: This is generated code. Look in numpy/linalg/lapack_lite for
+ *       information on remaking this file.
+ */
+'''
+
+HEADER = HEADER_BLURB + '''\
 #include "f2c.h"
 
 #ifdef HAVE_CONFIG
@@ -65,7 +62,7 @@ them.
 #endif
 '''
 
-class FortranRoutine(object):
+class FortranRoutine:
     """Wrapper for a Fortran routine in a file.
     """
     type = 'generic'
@@ -97,7 +94,7 @@ class UnknownFortranRoutine(FortranRoutine):
     def dependencies(self):
         return []
 
-class FortranLibrary(object):
+class FortranLibrary:
     """Container for a bunch of Fortran routines.
     """
     def __init__(self, src_dirs):
@@ -281,6 +278,52 @@ def ensure_executable(name):
     except:
         raise SystemExit(name + ' not found')
 
+def create_name_header(output_dir):
+    routine_re = re.compile(r'^      (subroutine|.* function)\s+(\w+)\(.*$',
+                            re.I)
+    extern_re = re.compile(r'^extern [a-z]+ ([a-z0-9_]+)\(.*$')
+
+    # BLAS/LAPACK symbols
+    symbols = set(['xerbla'])
+    for fn in os.listdir(output_dir):
+        fn = os.path.join(output_dir, fn)
+
+        if not fn.endswith('.f'):
+            continue
+
+        with open(fn, 'r') as f:
+            for line in f:
+                m = routine_re.match(line)
+                if m:
+                    symbols.add(m.group(2).lower())
+
+    # f2c symbols
+    f2c_symbols = set()
+    with open('f2c.h', 'r') as f:
+        for line in f:
+            m = extern_re.match(line)
+            if m:
+                f2c_symbols.add(m.group(1))
+
+    with open(os.path.join(output_dir, 'lapack_lite_names.h'), 'w') as f:
+        f.write(HEADER_BLURB)
+        f.write(
+            "/*\n"
+            " * This file renames all BLAS/LAPACK and f2c symbols to avoid\n"
+            " * dynamic symbol name conflicts, in cases where e.g.\n"
+            " * integer sizes do not match with 'standard' ABI.\n"
+            " */\n")
+
+        # Rename BLAS/LAPACK symbols
+        for name in sorted(symbols):
+            f.write("#define %s_ BLAS_FUNC(%s)\n" % (name, name))
+
+        # Rename also symbols that f2c exports itself
+        f.write("\n"
+                "/* Symbols exported by f2c.c */\n")
+        for name in sorted(f2c_symbols):
+            f.write("#define %s numpy_lapack_lite_%s\n" % (name, name))
+
 def main():
     if len(sys.argv) != 3:
         print(__doc__)
@@ -330,12 +373,14 @@ def main():
 
         print()
 
+    create_name_header(output_dir)
+
     for fname in os.listdir(output_dir):
-        if fname.endswith('.c'):
+        if fname.endswith('.c') or fname == 'lapack_lite_names.h':
             print('Copying ' + fname)
             shutil.copy(
                 os.path.join(output_dir, fname),
-                os.path.dirname(__file__),
+                os.path.abspath(os.path.dirname(__file__)),
             )
 
 
index 4dbb92e1f455d69a9a289730f3c2b90576831a25..fe2f718b2e58765030b444dc4c7346370f54d789 100644 (file)
@@ -2,9 +2,6 @@
 #include "numpy/npy_common.h"
 #include "npy_cblas.h"
 
-#undef c_abs
-#include "f2c.h"
-
 /*
   From the original manpage:
   --------------------------
index 4c80317f556b02b9c2accd4bdde98bf67084b055..362a593a61b9c3496b4a400dfc7d9658ece1bd39 100644 (file)
@@ -377,7 +377,6 @@ static struct PyMethodDef lapack_lite_module_methods[] = {
 };
 
 
-#if PY_MAJOR_VERSION >= 3
 static struct PyModuleDef moduledef = {
         PyModuleDef_HEAD_INIT,
         "lapack_lite",
@@ -389,32 +388,25 @@ static struct PyModuleDef moduledef = {
         NULL,
         NULL
 };
-#endif
 
 /* Initialization function for the module */
-#if PY_MAJOR_VERSION >= 3
-#define RETVAL(x) x
 PyMODINIT_FUNC PyInit_lapack_lite(void)
-#else
-#define RETVAL(x)
-PyMODINIT_FUNC
-initlapack_lite(void)
-#endif
 {
     PyObject *m,*d;
-#if PY_MAJOR_VERSION >= 3
     m = PyModule_Create(&moduledef);
-#else
-    m = Py_InitModule4("lapack_lite", lapack_lite_module_methods,
-                       "", (PyObject*)NULL,PYTHON_API_VERSION);
-#endif
     if (m == NULL) {
-        return RETVAL(NULL);
+        return NULL;
     }
     import_array();
     d = PyModule_GetDict(m);
     LapackError = PyErr_NewException("lapack_lite.LapackError", NULL, NULL);
     PyDict_SetItemString(d, "LapackError", LapackError);
 
-    return RETVAL(m);
+#ifdef HAVE_BLAS_ILP64
+    PyDict_SetItemString(d, "_ilp64", Py_True);
+#else
+    PyDict_SetItemString(d, "_ilp64", Py_False);
+#endif
+
+    return m;
 }
index f1b2c222868497f5514443bdb800cf195fb50fc5..5ee326f3cf9ebafa10ead8a178ab1f3f4dda38db 100644 (file)
@@ -8,8 +8,6 @@ version only accesses the following LAPACK functions: dgesv, zgesv,
 dgeev, zgeev, dgesdd, zgesdd, dgelsd, zgelsd, dsyevd, zheevd, dgetrf,
 zgetrf, dpotrf, zpotrf, dgeqrf, zgeqrf, zungqr, dorgqr.
 """
-from __future__ import division, absolute_import, print_function
-
 
 __all__ = ['matrix_power', 'solve', 'tensorsolve', 'tensorinv', 'inv',
            'cholesky', 'eigvals', 'eigvalsh', 'pinv', 'slogdet', 'det',
@@ -26,7 +24,7 @@ from numpy.core import (
     add, multiply, sqrt, fastCopyAndTranspose, sum, isfinite,
     finfo, errstate, geterrobj, moveaxis, amin, amax, product, abs,
     atleast_2d, intp, asanyarray, object_, matmul,
-    swapaxes, divide, count_nonzero, isnan, sign
+    swapaxes, divide, count_nonzero, isnan, sign, argsort, sort
 )
 from numpy.core.multiarray import normalize_axis_index
 from numpy.core.overrides import set_module
@@ -39,13 +37,6 @@ array_function_dispatch = functools.partial(
     overrides.array_function_dispatch, module='numpy.linalg')
 
 
-# For Python2/3 compatibility
-_N = b'N'
-_V = b'V'
-_A = b'A'
-_S = b'S'
-_L = b'L'
-
 fortran_int = intc
 
 
@@ -345,6 +336,10 @@ def solve(a, b):
     LinAlgError
         If `a` is singular or not square.
 
+    See Also
+    --------
+    scipy.linalg.solve : Similar function in SciPy.
+
     Notes
     -----
 
@@ -502,6 +497,10 @@ def inv(a):
     LinAlgError
         If `a` is not square or inversion fails.
 
+    See Also
+    --------
+    scipy.linalg.inv : Similar function in SciPy.
+
     Notes
     -----
 
@@ -623,8 +622,8 @@ def matrix_power(a, n):
 
     try:
         n = operator.index(n)
-    except TypeError:
-        raise TypeError("exponent must be an integer")
+    except TypeError as e:
+        raise TypeError("exponent must be an integer") from e
 
     # Fall back on dot for object arrays. Object arrays are not supported by
     # the current implementation of matmul using einsum
@@ -679,8 +678,10 @@ def cholesky(a):
     Return the Cholesky decomposition, `L * L.H`, of the square matrix `a`,
     where `L` is lower-triangular and .H is the conjugate transpose operator
     (which is the ordinary transpose if `a` is real-valued).  `a` must be
-    Hermitian (symmetric if real-valued) and positive-definite.  Only `L` is
-    actually returned.
+    Hermitian (symmetric if real-valued) and positive-definite. No
+    checking is performed to verify whether `a` is Hermitian or not.
+    In addition, only the lower-triangular and diagonal elements of `a`
+    are used. Only `L` is actually returned.
 
     Parameters
     ----------
@@ -700,6 +701,14 @@ def cholesky(a):
        If the decomposition fails, for example, if `a` is not
        positive-definite.
 
+    See Also
+    --------
+    scipy.linalg.cholesky : Similar function in SciPy.
+    scipy.linalg.cholesky_banded : Cholesky decompose a banded Hermitian
+                                   positive-definite matrix.
+    scipy.linalg.cho_factor : Cholesky decomposition of a matrix, to use in
+                              `scipy.linalg.cho_solve`.
+
     Notes
     -----
 
@@ -756,7 +765,7 @@ def cholesky(a):
     return wrap(r.astype(result_t, copy=False))
 
 
-# QR decompostion
+# QR decomposition
 
 def _qr_dispatcher(a, mode=None):
     return (a,)
@@ -812,6 +821,11 @@ def qr(a, mode='reduced'):
     LinAlgError
         If factoring fails.
 
+    See Also
+    --------
+    scipy.linalg.qr : Similar function in SciPy.
+    scipy.linalg.rq : Compute RQ decomposition of a matrix.
+
     Notes
     -----
     This is an interface to the LAPACK routines ``dgeqrf``, ``zgeqrf``,
@@ -1004,6 +1018,7 @@ def eigvals(a):
                (conjugate symmetric) arrays.
     eigh : eigenvalues and eigenvectors of real symmetric or complex
            Hermitian (conjugate symmetric) arrays.
+    scipy.linalg.eigvals : Similar function in SciPy.
 
     Notes
     -----
@@ -1105,6 +1120,7 @@ def eigvalsh(a, UPLO='L'):
     eigvals : eigenvalues of general real or complex arrays.
     eig : eigenvalues and right eigenvectors of general real or complex
           arrays.
+    scipy.linalg.eigvalsh : Similar function in SciPy.
 
     Notes
     -----
@@ -1203,12 +1219,14 @@ def eig(a):
     See Also
     --------
     eigvals : eigenvalues of a non-symmetric array.
-
     eigh : eigenvalues and eigenvectors of a real symmetric or complex
            Hermitian (conjugate symmetric) array.
-
     eigvalsh : eigenvalues of a real symmetric or complex Hermitian
                (conjugate symmetric) array.
+    scipy.linalg.eig : Similar function in SciPy that also solves the
+                       generalized eigenvalue problem.
+    scipy.linalg.schur : Best choice for unitary and other non-Hermitian
+                         normal matrices.
 
     Notes
     -----
@@ -1222,21 +1240,26 @@ def eig(a):
     the eigenvalues and eigenvectors of general square arrays.
 
     The number `w` is an eigenvalue of `a` if there exists a vector
-    `v` such that ``dot(a,v) = w * v``. Thus, the arrays `a`, `w`, and
-    `v` satisfy the equations ``dot(a[:,:], v[:,i]) = w[i] * v[:,i]``
+    `v` such that ``a @ v = w * v``. Thus, the arrays `a`, `w`, and
+    `v` satisfy the equations ``a @ v[:,i] = w[i] * v[:,i]``
     for :math:`i \\in \\{0,...,M-1\\}`.
 
     The array `v` of eigenvectors may not be of maximum rank, that is, some
     of the columns may be linearly dependent, although round-off error may
     obscure that fact. If the eigenvalues are all different, then theoretically
-    the eigenvectors are linearly independent. Likewise, the (complex-valued)
-    matrix of eigenvectors `v` is unitary if the matrix `a` is normal, i.e.,
-    if ``dot(a, a.H) = dot(a.H, a)``, where `a.H` denotes the conjugate
-    transpose of `a`.
+    the eigenvectors are linearly independent and `a` can be diagonalized by
+    a similarity transformation using `v`, i.e, ``inv(v) @ a @ v`` is diagonal.
+
+    For non-Hermitian normal matrices the SciPy function `scipy.linalg.schur`
+    is preferred because the matrix `v` is guaranteed to be unitary, which is
+    not the case when using `eig`. The Schur factorization produces an
+    upper triangular matrix rather than a diagonal matrix, but for normal
+    matrices only the diagonal of the upper triangular matrix is needed, the
+    rest is roundoff error.
 
     Finally, it is emphasized that `v` consists of the *right* (as in
     right-hand side) eigenvectors of `a`.  A vector `y` satisfying
-    ``dot(y.T, a) = z * y.T`` for some number `z` is called a *left*
+    ``y.T @ a = z * y.T`` for some number `z` is called a *left*
     eigenvector of `a`, and, in general, the left and right eigenvectors
     of a matrix are not necessarily the (perhaps conjugate) transposes
     of each other.
@@ -1355,6 +1378,8 @@ def eigh(a, UPLO='L'):
                (conjugate symmetric) arrays.
     eig : eigenvalues and right eigenvectors for non-symmetric arrays.
     eigvals : eigenvalues of non-symmetric arrays.
+    scipy.linalg.eigh : Similar function in SciPy (but also solves the
+                        generalized eigenvalue problem).
 
     Notes
     -----
@@ -1506,6 +1531,11 @@ def svd(a, full_matrices=True, compute_uv=True, hermitian=False):
     LinAlgError
         If SVD computation does not converge.
 
+    See Also
+    --------
+    scipy.linalg.svd : Similar function in SciPy.
+    scipy.linalg.svdvals : Compute singular values of a matrix.
+
     Notes
     -----
 
@@ -1585,24 +1615,29 @@ def svd(a, full_matrices=True, compute_uv=True, hermitian=False):
     True
 
     """
+    import numpy as _nx
     a, wrap = _makearray(a)
 
     if hermitian:
-        # note: lapack returns eigenvalues in reverse order to our contract.
-        # reversing is cheap by design in numpy, so we do so to be consistent
+        # note: lapack svd returns eigenvalues with s ** 2 sorted descending,
+        # but eig returns s sorted ascending, so we re-order the eigenvalues
+        # and related arrays to have the correct order
         if compute_uv:
             s, u = eigh(a)
-            s = s[..., ::-1]
-            u = u[..., ::-1]
-            # singular values are unsigned, move the sign into v
-            vt = transpose(u * sign(s)[..., None, :]).conjugate()
+            sgn = sign(s)
             s = abs(s)
+            sidx = argsort(s)[..., ::-1]
+            sgn = _nx.take_along_axis(sgn, sidx, axis=-1)
+            s = _nx.take_along_axis(s, sidx, axis=-1)
+            u = _nx.take_along_axis(u, sidx[..., None, :], axis=-1)
+            # singular values are unsigned, move the sign into v
+            vt = transpose(u * sgn[..., None, :]).conjugate()
             return wrap(u), s, wrap(vt)
         else:
             s = eigvalsh(a)
             s = s[..., ::-1]
             s = abs(s)
-            return s
+            return sort(s)[..., ::-1]
 
     _assert_stacked_2d(a)
     t, result_t = _commonType(a)
@@ -1917,6 +1952,13 @@ def pinv(a, rcond=1e-15, hermitian=False):
     LinAlgError
         If the SVD computation does not converge.
 
+    See Also
+    --------
+    scipy.linalg.pinv : Similar function in SciPy.
+    scipy.linalg.pinv2 : Similar function in SciPy (SVD-based).
+    scipy.linalg.pinvh : Compute the (Moore-Penrose) pseudo-inverse of a
+                         Hermitian matrix.
+
     Notes
     -----
     The pseudo-inverse of a matrix A, denoted :math:`A^+`, is
@@ -2079,6 +2121,7 @@ def det(a):
     --------
     slogdet : Another way to represent the determinant, more suitable
       for large matrices where underflow/overflow may occur.
+    scipy.linalg.det : Similar function in SciPy.
 
     Notes
     -----
@@ -2129,13 +2172,13 @@ def lstsq(a, b, rcond="warn"):
     r"""
     Return the least-squares solution to a linear matrix equation.
 
-    Solves the equation :math:`a x = b` by computing a vector `x` that
-    minimizes the squared Euclidean 2-norm :math:`\| b - a x \|^2_2`.
-    The equation may be under-, well-, or over-determined (i.e., the
-    number of linearly independent rows of `a` can be less than, equal
-    to, or greater than its number of linearly independent columns).
+    Computes the vector x that approximatively solves the equation
+    ``a @ x = b``. The equation may be under-, well-, or over-determined
+    (i.e., the number of linearly independent rows of `a` can be less than,
+    equal to, or greater than its number of linearly independent columns).
     If `a` is square and of full rank, then `x` (but for round-off error)
-    is the "exact" solution of the equation.
+    is the "exact" solution of the equation. Else, `x` minimizes the
+    Euclidean 2-norm :math:`|| b - a x ||`.
 
     Parameters
     ----------
@@ -2179,6 +2222,10 @@ def lstsq(a, b, rcond="warn"):
     LinAlgError
         If computation does not converge.
 
+    See Also
+    --------
+    scipy.linalg.lstsq : Similar function in SciPy.
+
     Notes
     -----
     If `b` is a matrix, then all array results are returned as matrices.
@@ -2353,9 +2400,13 @@ def norm(x, ord=None, axis=None, keepdims=False):
     n : float or ndarray
         Norm of the matrix or vector(s).
 
+    See Also
+    --------
+    scipy.linalg.norm : Similar function in SciPy.
+
     Notes
     -----
-    For values of ``ord <= 0``, the result is, strictly speaking, not a
+    For values of ``ord < 1``, the result is, strictly speaking, not a
     mathematical 'norm', but it may still be useful for various numerical
     purposes.
 
@@ -2383,6 +2434,9 @@ def norm(x, ord=None, axis=None, keepdims=False):
 
     The nuclear norm is the sum of the singular values.
 
+    Both the Frobenius and nuclear norm orders are only defined for
+    matrices and raise a ValueError when ``x.ndim != 2``.
+
     References
     ----------
     .. [1] G. H. Golub and C. F. Van Loan, *Matrix Computations*,
@@ -2486,8 +2540,8 @@ def norm(x, ord=None, axis=None, keepdims=False):
     elif not isinstance(axis, tuple):
         try:
             axis = int(axis)
-        except Exception:
-            raise TypeError("'axis' must be None, an integer or a tuple of integers")
+        except Exception as e:
+            raise TypeError("'axis' must be None, an integer or a tuple of integers") from e
         axis = (axis,)
 
     if len(axis) == 1:
@@ -2505,11 +2559,11 @@ def norm(x, ord=None, axis=None, keepdims=False):
             # special case for speedup
             s = (x.conj() * x).real
             return sqrt(add.reduce(s, axis=axis, keepdims=keepdims))
+        # None of the str-type keywords for ord ('fro', 'nuc') 
+        # are valid for vectors
+        elif isinstance(ord, str):
+            raise ValueError(f"Invalid norm order '{ord}' for vectors")
         else:
-            try:
-                ord + 1
-            except TypeError:
-                raise ValueError("Invalid norm order for vectors.")
             absx = abs(x)
             absx **= ord
             ret = add.reduce(absx, axis=axis, keepdims=keepdims)
@@ -2559,12 +2613,13 @@ def norm(x, ord=None, axis=None, keepdims=False):
 
 # multi_dot
 
-def _multidot_dispatcher(arrays):
-    return arrays
+def _multidot_dispatcher(arrays, *, out=None):
+    yield from arrays
+    yield out
 
 
 @array_function_dispatch(_multidot_dispatcher)
-def multi_dot(arrays):
+def multi_dot(arrays, *, out=None):
     """
     Compute the dot product of two or more arrays in a single function call,
     while automatically selecting the fastest evaluation order.
@@ -2588,6 +2643,15 @@ def multi_dot(arrays):
         If the first argument is 1-D it is treated as row vector.
         If the last argument is 1-D it is treated as column vector.
         The other arguments must be 2-D.
+    out : ndarray, optional
+        Output argument. This must have the exact kind that would be returned
+        if it was not used. In particular, it must have the right type, must be
+        C-contiguous, and its dtype must be the dtype that would be returned
+        for `dot(a, b)`. This is a performance feature. Therefore, if these
+        conditions are not met, an exception is raised, instead of attempting
+        to be flexible.
+
+        .. versionadded:: 1.19.0
 
     Returns
     -------
@@ -2645,7 +2709,7 @@ def multi_dot(arrays):
     if n < 2:
         raise ValueError("Expecting at least two arrays.")
     elif n == 2:
-        return dot(arrays[0], arrays[1])
+        return dot(arrays[0], arrays[1], out=out)
 
     arrays = [asanyarray(a) for a in arrays]
 
@@ -2661,10 +2725,10 @@ def multi_dot(arrays):
 
     # _multi_dot_three is much faster than _multi_dot_matrix_chain_order
     if n == 3:
-        result = _multi_dot_three(arrays[0], arrays[1], arrays[2])
+        result = _multi_dot_three(arrays[0], arrays[1], arrays[2], out=out)
     else:
         order = _multi_dot_matrix_chain_order(arrays)
-        result = _multi_dot(arrays, order, 0, n - 1)
+        result = _multi_dot(arrays, order, 0, n - 1, out=out)
 
     # return proper shape
     if ndim_first == 1 and ndim_last == 1:
@@ -2675,7 +2739,7 @@ def multi_dot(arrays):
         return result
 
 
-def _multi_dot_three(A, B, C):
+def _multi_dot_three(A, B, C, out=None):
     """
     Find the best order for three arrays and do the multiplication.
 
@@ -2691,9 +2755,9 @@ def _multi_dot_three(A, B, C):
     cost2 = a1b0 * c1 * (a0 + b1c0)
 
     if cost1 < cost2:
-        return dot(dot(A, B), C)
+        return dot(dot(A, B), C, out=out)
     else:
-        return dot(A, dot(B, C))
+        return dot(A, dot(B, C), out=out)
 
 
 def _multi_dot_matrix_chain_order(arrays, return_costs=False):
@@ -2737,10 +2801,14 @@ def _multi_dot_matrix_chain_order(arrays, return_costs=False):
     return (s, m) if return_costs else s
 
 
-def _multi_dot(arrays, order, i, j):
+def _multi_dot(arrays, order, i, j, out=None):
     """Actually do the multiplication with the given order."""
     if i == j:
+        # the initial call with non-None out should never get here
+        assert out is None
+
         return arrays[i]
     else:
         return dot(_multi_dot(arrays, order, i, order[i, j]),
-                   _multi_dot(arrays, order, order[i, j] + 1, j))
+                   _multi_dot(arrays, order, order[i, j] + 1, j),
+                   out=out)
index 6315a34b41d09f24b1c4ea2fdebf6563fa1ede70..57fdd502b485a14d1fa23cdc04e564428f8c6066 100644 (file)
@@ -1,14 +1,12 @@
-from __future__ import division, print_function
-
 import os
 import sys
 
 def configuration(parent_package='', top_path=None):
     from numpy.distutils.misc_util import Configuration
-    from numpy.distutils.system_info import get_info
+    from numpy.distutils.system_info import get_info, system_info
     config = Configuration('linalg', parent_package, top_path)
 
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
 
     # Configure lapack_lite
 
@@ -31,8 +29,28 @@ def configuration(parent_package='', top_path=None):
     else:
         lapack_info = get_info('lapack_opt', 0)  # and {}
 
+    use_lapack_lite = not lapack_info
+
+    if use_lapack_lite:
+        # This makes numpy.distutils write the fact that lapack_lite
+        # is being used to numpy.__config__
+        class numpy_linalg_lapack_lite(system_info):
+            def calc_info(self):
+                info = {'language': 'c'}
+                if sys.maxsize > 2**32:
+                    # Build lapack-lite in 64-bit integer mode.
+                    # The suffix is arbitrary (lapack_lite symbols follow it),
+                    # but use the "64_" convention here.
+                    info['define_macros'] = [
+                        ('HAVE_BLAS_ILP64', None),
+                        ('BLAS_SYMBOL_SUFFIX', '64_')
+                    ]
+                self.set_info(**info)
+
+        lapack_info = numpy_linalg_lapack_lite().get_info(2)
+
     def get_lapack_lite_sources(ext, build_dir):
-        if not lapack_info:
+        if use_lapack_lite:
             print("### Warning:  Using unoptimized lapack ###")
             return all_sources
         else:
index 921390da33143ae72d14d7f0a319492ea84e051f..cbf3089bcf5f720d1f6923f2ff555ff051fdf423 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from subprocess import PIPE, Popen
 import sys
 import re
@@ -9,7 +7,7 @@ from numpy.linalg import lapack_lite
 from numpy.testing import assert_
 
 
-class FindDependenciesLdd(object):
+class FindDependenciesLdd:
 
     def __init__(self):
         self.cmd = ['ldd']
@@ -41,7 +39,7 @@ class FindDependenciesLdd(object):
         return founds
 
 
-class TestF77Mismatch(object):
+class TestF77Mismatch:
 
     @pytest.mark.skipif(not(sys.platform[:5] == 'linux'),
                         reason="no fortran compiler on non-Linux platform")
index e12755e0d586cd00c96ec917438befaffb1508b3..cd4c10832e7e7240175571605a07541f0c188f89 100644 (file)
@@ -1,8 +1,6 @@
 """Test deprecation and future warnings.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.testing import assert_warns
 
index ef05b595ea9d001c9150117b355d9d9a02210989..3f3bf9f7091785ab30083aee62d5842fec3eb4d8 100644 (file)
@@ -1,8 +1,6 @@
 """ Test functions for linalg module
 
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 import itertools
@@ -68,7 +66,7 @@ all_tags = {
 }
 
 
-class LinalgCase(object):
+class LinalgCase:
     def __init__(self, name, a, b, tags=set()):
         """
         A bundle of arguments to be passed to a test case, with an identifying
@@ -333,7 +331,7 @@ CASES += _make_strided_cases()
 #
 # Test different routines against the above cases
 #
-class LinalgTestCase(object):
+class LinalgTestCase:
     TEST_CASES = CASES
 
     def check_cases(self, require=set(), exclude=set()):
@@ -634,7 +632,7 @@ class TestEig(EigCases):
         assert_(isinstance(a, np.ndarray))
 
 
-class SVDBaseTests(object):
+class SVDBaseTests:
     hermitian = False
 
     @pytest.mark.parametrize('dtype', [single, double, csingle, cdouble])
@@ -682,6 +680,14 @@ class SVDHermitianCases(HermitianTestCase, HermitianGeneralizedTestCase):
         assert_allclose(a, dot_generalized(np.asarray(u) * np.asarray(s)[..., None, :],
                                            np.asarray(vt)),
                         rtol=get_rtol(u.dtype))
+        def hermitian(mat):
+            axes = list(range(mat.ndim))
+            axes[-1], axes[-2] = axes[-2], axes[-1]
+            return np.conj(np.transpose(mat, axes=axes))
+        
+        assert_almost_equal(np.matmul(u, hermitian(u)), np.broadcast_to(np.eye(u.shape[-1]), u.shape))
+        assert_almost_equal(np.matmul(vt, hermitian(vt)), np.broadcast_to(np.eye(vt.shape[-1]), vt.shape))
+        assert_equal(np.sort(s)[..., ::-1], s)
         assert_(consistent_subclass(u, a))
         assert_(consistent_subclass(vt, a))
 
@@ -976,7 +982,7 @@ class TestLstsq(LstsqCases):
 
 
 @pytest.mark.parametrize('dt', [np.dtype(c) for c in '?bBhHiIqQefdgFDGO']) 
-class TestMatrixPower(object):
+class TestMatrixPower:
 
     rshft_0 = np.eye(4)
     rshft_1 = rshft_0[[3, 0, 1, 2]]
@@ -1076,7 +1082,7 @@ class TestEigvalshCases(HermitianTestCase, HermitianGeneralizedTestCase):
         assert_allclose(ev2, evalues, rtol=get_rtol(ev.dtype))
 
 
-class TestEigvalsh(object):
+class TestEigvalsh:
     @pytest.mark.parametrize('dtype', [single, double, csingle, cdouble])
     def test_types(self, dtype):
         x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
@@ -1152,7 +1158,7 @@ class TestEighCases(HermitianTestCase, HermitianGeneralizedTestCase):
                         rtol=get_rtol(ev.dtype), err_msg=repr(a))
 
 
-class TestEigh(object):
+class TestEigh:
     @pytest.mark.parametrize('dtype', [single, double, csingle, cdouble])
     def test_types(self, dtype):
         x = np.array([[1, 0.5], [0.5, 1]], dtype=dtype)
@@ -1211,7 +1217,7 @@ class TestEigh(object):
         assert_(isinstance(a, np.ndarray))
 
 
-class _TestNormBase(object):
+class _TestNormBase:
     dt = None
     dec = None
 
@@ -1474,11 +1480,12 @@ class _TestNorm2D(_TestNormBase):
 
         # Using `axis=<integer>` or passing in a 1-D array implies vector
         # norms are being computed, so also using `ord='fro'`
-        # or `ord='nuc'` raises a ValueError.
+        # or `ord='nuc'` or any other string raises a ValueError.
         assert_raises(ValueError, norm, A, 'fro', 0)
         assert_raises(ValueError, norm, A, 'nuc', 0)
         assert_raises(ValueError, norm, [3, 4], 'fro', None)
         assert_raises(ValueError, norm, [3, 4], 'nuc', None)
+        assert_raises(ValueError, norm, [3, 4], 'test', None)
 
         # Similarly, norm should raise an exception when ord is any finite
         # number other than 1, 2, -1 or -2 when computing matrix norms.
@@ -1497,7 +1504,7 @@ class _TestNorm(_TestNorm2D, _TestNormGeneral):
     pass
 
 
-class TestNorm_NonSystematic(object):
+class TestNorm_NonSystematic:
 
     def test_longdouble_norm(self):
         # Non-regression test: p-norm of longdouble would previously raise
@@ -1552,7 +1559,7 @@ class TestNormInt64(_TestNorm, _TestNormInt64Base):
     pass
 
 
-class TestMatrixRank(object):
+class TestMatrixRank:
 
     def test_matrix_rank(self):
         # Full rank matrix
@@ -1601,7 +1608,7 @@ def test_reduced_rank():
         assert_equal(matrix_rank(X), 8)
 
 
-class TestQR(object):
+class TestQR:
     # Define the array class here, so run this on matrices elsewhere.
     array = np.array
 
@@ -1701,7 +1708,7 @@ class TestQR(object):
             self.check_qr(m2.T)
 
 
-class TestCholesky(object):
+class TestCholesky:
     # TODO: are there no other tests for cholesky?
 
     def test_basic_property(self):
@@ -1829,6 +1836,7 @@ def test_xerbla_override():
             pytest.skip('Numpy xerbla not linked in.')
 
 
+@pytest.mark.slow
 def test_sdot_bug_8577():
     # Regression test that loading certain other libraries does not
     # result to wrong results in float32 linear algebra.
@@ -1863,7 +1871,7 @@ def test_sdot_bug_8577():
         subprocess.check_call([sys.executable, "-c", code])
 
 
-class TestMultiDot(object):
+class TestMultiDot:
 
     def test_basic_function_with_three_arguments(self):
         # multi_dot with three arguments uses a fast hand coded algorithm to
@@ -1922,6 +1930,41 @@ class TestMultiDot(object):
         # the result should be a scalar
         assert_equal(multi_dot([A1d, B, C, D1d]).shape, ())
 
+    def test_three_arguments_and_out(self):
+        # multi_dot with three arguments uses a fast hand coded algorithm to
+        # determine the optimal order. Therefore test it separately.
+        A = np.random.random((6, 2))
+        B = np.random.random((2, 6))
+        C = np.random.random((6, 2))
+
+        out = np.zeros((6, 2))
+        ret = multi_dot([A, B, C], out=out)
+        assert out is ret
+        assert_almost_equal(out, A.dot(B).dot(C))
+        assert_almost_equal(out, np.dot(A, np.dot(B, C)))
+
+    def test_two_arguments_and_out(self):
+        # separate code path with two arguments
+        A = np.random.random((6, 2))
+        B = np.random.random((2, 6))
+        out = np.zeros((6, 6))
+        ret = multi_dot([A, B], out=out)
+        assert out is ret
+        assert_almost_equal(out, A.dot(B))
+        assert_almost_equal(out, np.dot(A, B))
+
+    def test_dynamic_programing_optimization_and_out(self):
+        # multi_dot with four or more arguments uses the dynamic programing
+        # optimization and therefore deserve a separate test
+        A = np.random.random((6, 2))
+        B = np.random.random((2, 6))
+        C = np.random.random((6, 2))
+        D = np.random.random((2, 1))
+        out = np.zeros((6, 1))
+        ret = multi_dot([A, B, C, D], out=out)
+        assert out is ret
+        assert_almost_equal(out, A.dot(B).dot(C).dot(D))
+
     def test_dynamic_programming_logic(self):
         # Test for the dynamic programming part
         # This test is directly taken from Cormen page 376.
@@ -1957,7 +2000,7 @@ class TestMultiDot(object):
         assert_raises(ValueError, multi_dot, [np.random.random((3, 3))])
 
 
-class TestTensorinv(object):
+class TestTensorinv:
 
     @pytest.mark.parametrize("arr, ind", [
         (np.ones((4, 6, 8, 2)), 2),
index bd3a45872cb198030308f0214ef88c12ae1215f4..7ed932bc928d9911b7d5cc4eb11d3d86c141b36b 100644 (file)
@@ -1,7 +1,5 @@
 """ Test functions for linalg module
 """
-from __future__ import division, absolute_import, print_function
-
 import warnings
 
 import numpy as np
@@ -12,7 +10,7 @@ from numpy.testing import (
 )
 
 
-class TestRegression(object):
+class TestRegression:
 
     def test_eig_build(self):
         # Ticket #652
@@ -59,8 +57,8 @@ class TestRegression(object):
         assert_array_almost_equal(b, np.zeros((2, 2)))
 
     def test_norm_vector_badarg(self):
-        # Regression for #786: Froebenius norm for vectors raises
-        # TypeError.
+        # Regression for #786: Frobenius norm for vectors raises
+        # ValueError.
         assert_raises(ValueError, linalg.norm, array([1., 2., 3.]), 'fro')
 
     def test_lapack_endian(self):
index e864c541b089d4dd6f4bff4d49f0d40a20f12bf2..59647c67d2acb951022b6684ff734abb75a9fb57 100644 (file)
@@ -1084,8 +1084,8 @@ static NPY_INLINE void
 
 static void
 @TYPE@_slogdet(char **args,
-               npy_intp *dimensions,
-               npy_intp *steps,
+               npy_intp const *dimensions,
+               npy_intp const *steps,
                void *NPY_UNUSED(func))
 {
     fortran_int m;
@@ -1127,8 +1127,8 @@ static void
 
 static void
 @TYPE@_det(char **args,
-           npy_intp *dimensions,
-           npy_intp *steps,
+           npy_intp const *dimensions,
+           npy_intp const *steps,
            void *NPY_UNUSED(func))
 {
     fortran_int m;
@@ -1426,8 +1426,8 @@ static NPY_INLINE void
 @TYPE@_eigh_wrapper(char JOBZ,
                     char UPLO,
                     char**args,
-                    npy_intpdimensions,
-                    npy_intpsteps)
+                    npy_intp const *dimensions,
+                    npy_intp const *steps)
 {
     ptrdiff_t outer_steps[3];
     size_t iter;
@@ -1501,8 +1501,8 @@ static NPY_INLINE void
  */
 static void
 @TYPE@_eighlo(char **args,
-              npy_intp *dimensions,
-              npy_intp *steps,
+              npy_intp const *dimensions,
+              npy_intp const *steps,
               void *NPY_UNUSED(func))
 {
     @TYPE@_eigh_wrapper('V', 'L', args, dimensions, steps);
@@ -1510,8 +1510,8 @@ static void
 
 static void
 @TYPE@_eighup(char **args,
-              npy_intp *dimensions,
-              npy_intp *steps,
+              npy_intp const *dimensions,
+              npy_intp const *steps,
               void* NPY_UNUSED(func))
 {
     @TYPE@_eigh_wrapper('V', 'U', args, dimensions, steps);
@@ -1519,8 +1519,8 @@ static void
 
 static void
 @TYPE@_eigvalshlo(char **args,
-                  npy_intp *dimensions,
-                  npy_intp *steps,
+                  npy_intp const *dimensions,
+                  npy_intp const *steps,
                   void* NPY_UNUSED(func))
 {
     @TYPE@_eigh_wrapper('N', 'L', args, dimensions, steps);
@@ -1528,8 +1528,8 @@ static void
 
 static void
 @TYPE@_eigvalshup(char **args,
-                  npy_intp *dimensions,
-                  npy_intp *steps,
+                  npy_intp const *dimensions,
+                  npy_intp const *steps,
                   void* NPY_UNUSED(func))
 {
     @TYPE@_eigh_wrapper('N', 'U', args, dimensions, steps);
@@ -1618,7 +1618,7 @@ release_@lapack_func@(GESV_PARAMS_t *params)
 }
 
 static void
-@TYPE@_solve(char **args, npy_intp *dimensions, npy_intp *steps,
+@TYPE@_solve(char **args, npy_intp const *dimensions, npy_intp const *steps,
              void *NPY_UNUSED(func))
 {
     GESV_PARAMS_t params;
@@ -1655,7 +1655,7 @@ static void
 }
 
 static void
-@TYPE@_solve1(char **args, npy_intp *dimensions, npy_intp *steps,
+@TYPE@_solve1(char **args, npy_intp const *dimensions, npy_intp const *steps,
               void *NPY_UNUSED(func))
 {
     GESV_PARAMS_t params;
@@ -1690,7 +1690,7 @@ static void
 }
 
 static void
-@TYPE@_inv(char **args, npy_intp *dimensions, npy_intp *steps,
+@TYPE@_inv(char **args, npy_intp const *dimensions, npy_intp const *steps,
            void *NPY_UNUSED(func))
 {
     GESV_PARAMS_t params;
@@ -1792,7 +1792,7 @@ release_@lapack_func@(POTR_PARAMS_t *params)
 }
 
 static void
-@TYPE@_cholesky(char uplo, char **args, npy_intp *dimensions, npy_intp *steps)
+@TYPE@_cholesky(char uplo, char **args, npy_intp const *dimensions, npy_intp const *steps)
 {
     POTR_PARAMS_t params;
     int error_occurred = get_fp_invalid_and_clear();
@@ -1825,7 +1825,7 @@ static void
 }
 
 static void
-@TYPE@_cholesky_lo(char **args, npy_intp *dimensions, npy_intp *steps,
+@TYPE@_cholesky_lo(char **args, npy_intp const *dimensions, npy_intp const *steps,
                 void *NPY_UNUSED(func))
 {
     @TYPE@_cholesky('L', args, dimensions, steps);
@@ -1841,7 +1841,7 @@ typedef struct geev_params_struct {
     void *WR; /* RWORK in complex versions, REAL W buffer for (sd)geev*/
     void *WI;
     void *VLR; /* REAL VL buffers for _geev where _ is s, d */
-    void *VRR; /* REAL VR buffers for _geev hwere _ is s, d */
+    void *VRR; /* REAL VR buffers for _geev where _ is s, d */
     void *WORK;
     void *W;  /* final w */
     void *VL; /* final vl */
@@ -2235,8 +2235,8 @@ static NPY_INLINE void
 @TYPE@_eig_wrapper(char JOBVL,
                    char JOBVR,
                    char**args,
-                   npy_intpdimensions,
-                   npy_intpsteps)
+                   npy_intp const *dimensions,
+                   npy_intp const *steps)
 {
     ptrdiff_t outer_steps[4];
     size_t iter;
@@ -2329,8 +2329,8 @@ static NPY_INLINE void
 
 static void
 @TYPE@_eig(char **args,
-           npy_intp *dimensions,
-           npy_intp *steps,
+           npy_intp const *dimensions,
+           npy_intp const *steps,
            void *NPY_UNUSED(func))
 {
     @TYPE@_eig_wrapper('N', 'V', args, dimensions, steps);
@@ -2338,8 +2338,8 @@ static void
 
 static void
 @TYPE@_eigvals(char **args,
-               npy_intp *dimensions,
-               npy_intp *steps,
+               npy_intp const *dimensions,
+               npy_intp const *steps,
                void *NPY_UNUSED(func))
 {
     @TYPE@_eig_wrapper('N', 'N', args, dimensions, steps);
@@ -2712,8 +2712,8 @@ release_@lapack_func@(GESDD_PARAMS_t* params)
 static NPY_INLINE void
 @TYPE@_svd_wrapper(char JOBZ,
                    char **args,
-                   npy_intpdimensions,
-                   npy_intpsteps)
+                   npy_intp const *dimensions,
+                   npy_intp const *steps)
 {
     ptrdiff_t outer_steps[4];
     int error_occurred = get_fp_invalid_and_clear();
@@ -2807,8 +2807,8 @@ static NPY_INLINE void
  */
 static void
 @TYPE@_svd_N(char **args,
-             npy_intp *dimensions,
-             npy_intp *steps,
+             npy_intp const *dimensions,
+             npy_intp const *steps,
              void *NPY_UNUSED(func))
 {
     @TYPE@_svd_wrapper('N', args, dimensions, steps);
@@ -2816,8 +2816,8 @@ static void
 
 static void
 @TYPE@_svd_S(char **args,
-             npy_intp *dimensions,
-             npy_intp *steps,
+             npy_intp const *dimensions,
+             npy_intp const *steps,
              void *NPY_UNUSED(func))
 {
     @TYPE@_svd_wrapper('S', args, dimensions, steps);
@@ -2825,8 +2825,8 @@ static void
 
 static void
 @TYPE@_svd_A(char **args,
-             npy_intp *dimensions,
-             npy_intp *steps,
+             npy_intp const *dimensions,
+             npy_intp const *steps,
              void *NPY_UNUSED(func))
 {
     @TYPE@_svd_wrapper('A', args, dimensions, steps);
@@ -3163,7 +3163,7 @@ static @basetyp@
 }
 
 static void
-@TYPE@_lstsq(char **args, npy_intp *dimensions, npy_intp *steps,
+@TYPE@_lstsq(char **args, npy_intp const *dimensions, npy_intp const *steps,
              void *NPY_UNUSED(func))
 {
     GELSD_PARAMS_t params;
@@ -3590,7 +3590,7 @@ GUFUNC_DESCRIPTOR_t gufunc_descriptors [] = {
     }
 };
 
-static void
+static int
 addUfuncs(PyObject *dictionary) {
     PyObject *f;
     int i;
@@ -3609,12 +3609,19 @@ addUfuncs(PyObject *dictionary) {
                                                 d->doc,
                                                 0,
                                                 d->signature);
-        PyDict_SetItemString(dictionary, d->name, f);
+        if (f == NULL) {
+            return -1;
+        }
 #if 0
         dump_ufunc_object((PyUFuncObject*) f);
 #endif
+        int ret = PyDict_SetItemString(dictionary, d->name, f);
         Py_DECREF(f);
+        if (ret < 0) {
+            return -1;
+        }
     }
+    return 0;
 }
 
 
@@ -3626,7 +3633,6 @@ static PyMethodDef UMath_LinAlgMethods[] = {
     {NULL, NULL, 0, NULL}        /* Sentinel */
 };
 
-#if defined(NPY_PY3K)
 static struct PyModuleDef moduledef = {
         PyModuleDef_HEAD_INIT,
         UMATH_LINALG_MODULE_NAME,
@@ -3638,48 +3644,41 @@ static struct PyModuleDef moduledef = {
         NULL,
         NULL
 };
-#endif
 
-#if defined(NPY_PY3K)
-#define RETVAL(x) x
 PyObject *PyInit__umath_linalg(void)
-#else
-#define RETVAL(x)
-PyMODINIT_FUNC
-init_umath_linalg(void)
-#endif
 {
     PyObject *m;
     PyObject *d;
     PyObject *version;
 
     init_constants();
-#if defined(NPY_PY3K)
     m = PyModule_Create(&moduledef);
-#else
-    m = Py_InitModule(UMATH_LINALG_MODULE_NAME, UMath_LinAlgMethods);
-#endif
     if (m == NULL) {
-        return RETVAL(NULL);
+        return NULL;
     }
 
     import_array();
     import_ufunc();
 
     d = PyModule_GetDict(m);
+    if (d == NULL) {
+        return NULL;
+    }
 
     version = PyString_FromString(umath_linalg_version_string);
-    PyDict_SetItemString(d, "__version__", version);
+    if (version == NULL) {
+        return NULL;
+    }
+    int ret = PyDict_SetItemString(d, "__version__", version);
     Py_DECREF(version);
+    if (ret < 0) {
+        return NULL;
+    }
 
     /* Load the ufunc operators into the module's namespace */
-    addUfuncs(d);
-
-    if (PyErr_Occurred()) {
-        PyErr_SetString(PyExc_RuntimeError,
-                        "cannot load _umath_linalg module.");
-        return RETVAL(NULL);
+    if (addUfuncs(d) < 0) {
+        return NULL;
     }
 
-    return RETVAL(m);
+    return m;
 }
diff --git a/numpy/ma/README.rst b/numpy/ma/README.rst
new file mode 100644 (file)
index 0000000..47f20d6
--- /dev/null
@@ -0,0 +1,236 @@
+==================================
+A Guide to Masked Arrays in NumPy
+==================================
+
+.. Contents::
+
+See http://www.scipy.org/scipy/numpy/wiki/MaskedArray (dead link)
+for updates of this document.
+
+
+History
+-------
+
+As a regular user of MaskedArray, I (Pierre G.F. Gerard-Marchant) became
+increasingly frustrated with the subclassing of masked arrays (even if
+I can only blame my inexperience). I needed to develop a class of arrays
+that could store some additional information along with numerical values,
+while keeping the possibility for missing data (picture storing a series
+of dates along with measurements, what would later become the `TimeSeries
+Scikit <http://projects.scipy.org/scipy/scikits/wiki/TimeSeries>`__
+(dead link).
+
+I started to implement such a class, but then quickly realized that
+any additional information disappeared when processing these subarrays
+(for example, adding a constant value to a subarray would erase its
+dates). I ended up writing the equivalent of *numpy.core.ma* for my
+particular class, ufuncs included. Everything went fine until I needed to
+subclass my new class, when more problems showed up: some attributes of
+the new subclass were lost during processing. I identified the culprit as
+MaskedArray, which returns masked ndarrays when I expected masked
+arrays of my class. I was preparing myself to rewrite *numpy.core.ma*
+when I forced myself to learn how to subclass ndarrays. As I became more
+familiar with the *__new__* and *__array_finalize__* methods,
+I started to wonder why masked arrays were objects, and not ndarrays,
+and whether it wouldn't be more convenient for subclassing if they did
+behave like regular ndarrays.
+
+The new *maskedarray* is what I eventually come up with. The
+main differences with the initial *numpy.core.ma* package are
+that MaskedArray is now a subclass of *ndarray* and that the
+*_data* section can now be any subclass of *ndarray*. Apart from a
+couple of issues listed below, the behavior of the new MaskedArray
+class reproduces the old one. Initially the *maskedarray*
+implementation was marginally slower than *numpy.ma* in some areas,
+but work is underway to speed it up; the expectation is that it can be
+made substantially faster than the present *numpy.ma*.
+
+
+Note that if the subclass has some special methods and
+attributes, they are not propagated to the masked version:
+this would require a modification of the *__getattribute__*
+method (first trying *ndarray.__getattribute__*, then trying
+*self._data.__getattribute__* if an exception is raised in the first
+place), which really slows things down.
+
+Main differences
+----------------
+
+ * The *_data* part of the masked array can be any subclass of ndarray (but not recarray, cf below).
+ * *fill_value* is now a property, not a function.
+ * in the majority of cases, the mask is forced to *nomask* when no value is actually masked. A notable exception is when a masked array (with no masked values) has just been unpickled.
+ * I got rid of the *share_mask* flag, I never understood its purpose.
+ * *put*, *putmask* and *take* now mimic the ndarray methods, to avoid unpleasant surprises. Moreover, *put* and *putmask* both update the mask when needed.  * if *a* is a masked array, *bool(a)* raises a *ValueError*, as it does with ndarrays.
+ * in the same way, the comparison of two masked arrays is a masked array, not a boolean
+ * *filled(a)* returns an array of the same subclass as *a._data*, and no test is performed on whether it is contiguous or not.
+ * the mask is always printed, even if it's *nomask*, which makes things easy (for me at least) to remember that a masked array is used.
+ * *cumsum* works as if the *_data* array was filled with 0. The mask is preserved, but not updated.
+ * *cumprod* works as if the *_data* array was filled with 1. The mask is preserved, but not updated.
+
+New features
+------------
+
+This list is non-exhaustive...
+
+ * the *mr_* function mimics *r_* for masked arrays.
+ * the *anom* method returns the anomalies (deviations from the average)
+
+Using the new package with numpy.core.ma
+----------------------------------------
+
+I tried to make sure that the new package can understand old masked
+arrays. Unfortunately, there's no upward compatibility.
+
+For example:
+
+>>> import numpy.core.ma as old_ma
+>>> import maskedarray as new_ma
+>>> x = old_ma.array([1,2,3,4,5], mask=[0,0,1,0,0])
+>>> x
+array(data =
+ [     1      2 999999      4      5],
+      mask =
+ [False False True False False],
+      fill_value=999999)
+>>> y = new_ma.array([1,2,3,4,5], mask=[0,0,1,0,0])
+>>> y
+array(data = [1 2 -- 4 5],
+      mask = [False False True False False],
+      fill_value=999999)
+>>> x==y
+array(data =
+ [True True True True True],
+      mask =
+ [False False True False False],
+      fill_value=?)
+>>> old_ma.getmask(x) == new_ma.getmask(x)
+array([True, True, True, True, True])
+>>> old_ma.getmask(y) == new_ma.getmask(y)
+array([True, True, False, True, True])
+>>> old_ma.getmask(y)
+False
+
+
+Using maskedarray with matplotlib
+---------------------------------
+
+Starting with matplotlib 0.91.2, the masked array importing will work with
+the maskedarray branch) as well as with earlier versions.
+
+By default matplotlib still uses numpy.ma, but there is an rcParams setting
+that you can use to select maskedarray instead.  In the matplotlibrc file
+you will find::
+
+  #maskedarray : False       # True to use external maskedarray module
+                             # instead of numpy.ma; this is a temporary #
+                             setting for testing maskedarray.
+
+
+Uncomment and set to True to select maskedarray everywhere.
+Alternatively, you can test a script with maskedarray by using a
+command-line option, e.g.::
+
+  python simple_plot.py --maskedarray
+
+
+Masked records
+--------------
+
+Like *numpy.core.ma*, the *ndarray*-based implementation
+of MaskedArray is limited when working with records: you can
+mask any record of the array, but not a field in a record. If you
+need this feature, you may want to give the *mrecords* package
+a try (available in the *maskedarray* directory in the scipy
+sandbox). This module defines a new class, *MaskedRecord*. An
+instance of this class accepts a *recarray* as data, and uses two
+masks: the *fieldmask* has as many entries as records in the array,
+each entry with the same fields as a record, but of boolean types:
+they indicate whether the field is masked or not; a record entry
+is flagged as masked in the *mask* array if all the fields are
+masked. A few examples in the file should give you an idea of what
+can be done. Note that *mrecords* is still experimental...
+
+Optimizing maskedarray
+----------------------
+
+Should masked arrays be filled before processing or not?
+--------------------------------------------------------
+
+In the current implementation, most operations on masked arrays involve
+the following steps:
+
+ * the input arrays are filled
+ * the operation is performed on the filled arrays
+ * the mask is set for the results, from the combination of the input masks and the mask corresponding to the domain of the operation.
+
+For example, consider the division of two masked arrays::
+
+  import numpy
+  import maskedarray as ma
+  x = ma.array([1,2,3,4],mask=[1,0,0,0], dtype=numpy.float_)
+  y = ma.array([-1,0,1,2], mask=[0,0,0,1], dtype=numpy.float_)
+
+The division of x by y is then computed as::
+
+  d1 = x.filled(0) # d1 = array([0., 2., 3., 4.])
+  d2 = y.filled(1) # array([-1.,  0.,  1.,  1.])
+  m = ma.mask_or(ma.getmask(x), ma.getmask(y)) # m =
+  array([True,False,False,True])
+  dm = ma.divide.domain(d1,d2) # array([False,  True, False, False])
+  result = (d1/d2).view(MaskedArray) # masked_array([-0. inf, 3., 4.])
+  result._mask = logical_or(m, dm)
+
+Note that a division by zero takes place. To avoid it, we can consider
+to fill the input arrays, taking the domain mask into account, so that::
+
+  d1 = x._data.copy() # d1 = array([1., 2., 3., 4.])
+  d2 = y._data.copy() # array([-1.,  0.,  1.,  2.])
+  dm = ma.divide.domain(d1,d2) # array([False,  True, False, False])
+  numpy.putmask(d2, dm, 1) # d2 = array([-1.,  1.,  1.,  2.])
+  m = ma.mask_or(ma.getmask(x), ma.getmask(y)) # m =
+  array([True,False,False,True])
+  result = (d1/d2).view(MaskedArray) # masked_array([-1. 0., 3., 2.])
+  result._mask = logical_or(m, dm)
+
+Note that the *.copy()* is required to avoid updating the inputs with
+*putmask*.  The *.filled()* method also involves a *.copy()*.
+
+A third possibility consists in avoid filling the arrays::
+
+  d1 = x._data # d1 = array([1., 2., 3., 4.])
+  d2 = y._data # array([-1.,  0.,  1.,  2.])
+  dm = ma.divide.domain(d1,d2) # array([False,  True, False, False])
+  m = ma.mask_or(ma.getmask(x), ma.getmask(y)) # m =
+  array([True,False,False,True])
+  result = (d1/d2).view(MaskedArray) # masked_array([-1. inf, 3., 2.])
+  result._mask = logical_or(m, dm)
+
+Note that here again the division by zero takes place.
+
+A quick benchmark gives the following results:
+
+ * *numpy.ma.divide*  : 2.69 ms per loop
+ * classical division     : 2.21 ms per loop
+ * division w/ prefilling : 2.34 ms per loop
+ * division w/o filling   : 1.55 ms per loop
+
+So, is it worth filling the arrays beforehand ? Yes, if we are interested
+in avoiding floating-point exceptions that may fill the result with infs
+and nans. No, if we are only interested into speed...
+
+
+Thanks
+------
+
+I'd like to thank Paul Dubois, Travis Oliphant and Sasha for the
+original masked array package: without you, I would never have started
+that (it might be argued that I shouldn't have anyway, but that's
+another story...).  I also wish to extend these thanks to Reggie Dugard
+and Eric Firing for their suggestions and numerous improvements.
+
+
+Revision notes
+--------------
+
+  * 08/25/2007 : Creation of this page
+  * 01/23/2007 : The package has been moved to the SciPy sandbox, and is regularly updated: please check out your SVN version!
diff --git a/numpy/ma/README.txt b/numpy/ma/README.txt
deleted file mode 100644 (file)
index 47f20d6..0000000
+++ /dev/null
@@ -1,236 +0,0 @@
-==================================
-A Guide to Masked Arrays in NumPy
-==================================
-
-.. Contents::
-
-See http://www.scipy.org/scipy/numpy/wiki/MaskedArray (dead link)
-for updates of this document.
-
-
-History
--------
-
-As a regular user of MaskedArray, I (Pierre G.F. Gerard-Marchant) became
-increasingly frustrated with the subclassing of masked arrays (even if
-I can only blame my inexperience). I needed to develop a class of arrays
-that could store some additional information along with numerical values,
-while keeping the possibility for missing data (picture storing a series
-of dates along with measurements, what would later become the `TimeSeries
-Scikit <http://projects.scipy.org/scipy/scikits/wiki/TimeSeries>`__
-(dead link).
-
-I started to implement such a class, but then quickly realized that
-any additional information disappeared when processing these subarrays
-(for example, adding a constant value to a subarray would erase its
-dates). I ended up writing the equivalent of *numpy.core.ma* for my
-particular class, ufuncs included. Everything went fine until I needed to
-subclass my new class, when more problems showed up: some attributes of
-the new subclass were lost during processing. I identified the culprit as
-MaskedArray, which returns masked ndarrays when I expected masked
-arrays of my class. I was preparing myself to rewrite *numpy.core.ma*
-when I forced myself to learn how to subclass ndarrays. As I became more
-familiar with the *__new__* and *__array_finalize__* methods,
-I started to wonder why masked arrays were objects, and not ndarrays,
-and whether it wouldn't be more convenient for subclassing if they did
-behave like regular ndarrays.
-
-The new *maskedarray* is what I eventually come up with. The
-main differences with the initial *numpy.core.ma* package are
-that MaskedArray is now a subclass of *ndarray* and that the
-*_data* section can now be any subclass of *ndarray*. Apart from a
-couple of issues listed below, the behavior of the new MaskedArray
-class reproduces the old one. Initially the *maskedarray*
-implementation was marginally slower than *numpy.ma* in some areas,
-but work is underway to speed it up; the expectation is that it can be
-made substantially faster than the present *numpy.ma*.
-
-
-Note that if the subclass has some special methods and
-attributes, they are not propagated to the masked version:
-this would require a modification of the *__getattribute__*
-method (first trying *ndarray.__getattribute__*, then trying
-*self._data.__getattribute__* if an exception is raised in the first
-place), which really slows things down.
-
-Main differences
-----------------
-
- * The *_data* part of the masked array can be any subclass of ndarray (but not recarray, cf below).
- * *fill_value* is now a property, not a function.
- * in the majority of cases, the mask is forced to *nomask* when no value is actually masked. A notable exception is when a masked array (with no masked values) has just been unpickled.
- * I got rid of the *share_mask* flag, I never understood its purpose.
- * *put*, *putmask* and *take* now mimic the ndarray methods, to avoid unpleasant surprises. Moreover, *put* and *putmask* both update the mask when needed.  * if *a* is a masked array, *bool(a)* raises a *ValueError*, as it does with ndarrays.
- * in the same way, the comparison of two masked arrays is a masked array, not a boolean
- * *filled(a)* returns an array of the same subclass as *a._data*, and no test is performed on whether it is contiguous or not.
- * the mask is always printed, even if it's *nomask*, which makes things easy (for me at least) to remember that a masked array is used.
- * *cumsum* works as if the *_data* array was filled with 0. The mask is preserved, but not updated.
- * *cumprod* works as if the *_data* array was filled with 1. The mask is preserved, but not updated.
-
-New features
-------------
-
-This list is non-exhaustive...
-
- * the *mr_* function mimics *r_* for masked arrays.
- * the *anom* method returns the anomalies (deviations from the average)
-
-Using the new package with numpy.core.ma
-----------------------------------------
-
-I tried to make sure that the new package can understand old masked
-arrays. Unfortunately, there's no upward compatibility.
-
-For example:
-
->>> import numpy.core.ma as old_ma
->>> import maskedarray as new_ma
->>> x = old_ma.array([1,2,3,4,5], mask=[0,0,1,0,0])
->>> x
-array(data =
- [     1      2 999999      4      5],
-      mask =
- [False False True False False],
-      fill_value=999999)
->>> y = new_ma.array([1,2,3,4,5], mask=[0,0,1,0,0])
->>> y
-array(data = [1 2 -- 4 5],
-      mask = [False False True False False],
-      fill_value=999999)
->>> x==y
-array(data =
- [True True True True True],
-      mask =
- [False False True False False],
-      fill_value=?)
->>> old_ma.getmask(x) == new_ma.getmask(x)
-array([True, True, True, True, True])
->>> old_ma.getmask(y) == new_ma.getmask(y)
-array([True, True, False, True, True])
->>> old_ma.getmask(y)
-False
-
-
-Using maskedarray with matplotlib
----------------------------------
-
-Starting with matplotlib 0.91.2, the masked array importing will work with
-the maskedarray branch) as well as with earlier versions.
-
-By default matplotlib still uses numpy.ma, but there is an rcParams setting
-that you can use to select maskedarray instead.  In the matplotlibrc file
-you will find::
-
-  #maskedarray : False       # True to use external maskedarray module
-                             # instead of numpy.ma; this is a temporary #
-                             setting for testing maskedarray.
-
-
-Uncomment and set to True to select maskedarray everywhere.
-Alternatively, you can test a script with maskedarray by using a
-command-line option, e.g.::
-
-  python simple_plot.py --maskedarray
-
-
-Masked records
---------------
-
-Like *numpy.core.ma*, the *ndarray*-based implementation
-of MaskedArray is limited when working with records: you can
-mask any record of the array, but not a field in a record. If you
-need this feature, you may want to give the *mrecords* package
-a try (available in the *maskedarray* directory in the scipy
-sandbox). This module defines a new class, *MaskedRecord*. An
-instance of this class accepts a *recarray* as data, and uses two
-masks: the *fieldmask* has as many entries as records in the array,
-each entry with the same fields as a record, but of boolean types:
-they indicate whether the field is masked or not; a record entry
-is flagged as masked in the *mask* array if all the fields are
-masked. A few examples in the file should give you an idea of what
-can be done. Note that *mrecords* is still experimental...
-
-Optimizing maskedarray
-----------------------
-
-Should masked arrays be filled before processing or not?
---------------------------------------------------------
-
-In the current implementation, most operations on masked arrays involve
-the following steps:
-
- * the input arrays are filled
- * the operation is performed on the filled arrays
- * the mask is set for the results, from the combination of the input masks and the mask corresponding to the domain of the operation.
-
-For example, consider the division of two masked arrays::
-
-  import numpy
-  import maskedarray as ma
-  x = ma.array([1,2,3,4],mask=[1,0,0,0], dtype=numpy.float_)
-  y = ma.array([-1,0,1,2], mask=[0,0,0,1], dtype=numpy.float_)
-
-The division of x by y is then computed as::
-
-  d1 = x.filled(0) # d1 = array([0., 2., 3., 4.])
-  d2 = y.filled(1) # array([-1.,  0.,  1.,  1.])
-  m = ma.mask_or(ma.getmask(x), ma.getmask(y)) # m =
-  array([True,False,False,True])
-  dm = ma.divide.domain(d1,d2) # array([False,  True, False, False])
-  result = (d1/d2).view(MaskedArray) # masked_array([-0. inf, 3., 4.])
-  result._mask = logical_or(m, dm)
-
-Note that a division by zero takes place. To avoid it, we can consider
-to fill the input arrays, taking the domain mask into account, so that::
-
-  d1 = x._data.copy() # d1 = array([1., 2., 3., 4.])
-  d2 = y._data.copy() # array([-1.,  0.,  1.,  2.])
-  dm = ma.divide.domain(d1,d2) # array([False,  True, False, False])
-  numpy.putmask(d2, dm, 1) # d2 = array([-1.,  1.,  1.,  2.])
-  m = ma.mask_or(ma.getmask(x), ma.getmask(y)) # m =
-  array([True,False,False,True])
-  result = (d1/d2).view(MaskedArray) # masked_array([-1. 0., 3., 2.])
-  result._mask = logical_or(m, dm)
-
-Note that the *.copy()* is required to avoid updating the inputs with
-*putmask*.  The *.filled()* method also involves a *.copy()*.
-
-A third possibility consists in avoid filling the arrays::
-
-  d1 = x._data # d1 = array([1., 2., 3., 4.])
-  d2 = y._data # array([-1.,  0.,  1.,  2.])
-  dm = ma.divide.domain(d1,d2) # array([False,  True, False, False])
-  m = ma.mask_or(ma.getmask(x), ma.getmask(y)) # m =
-  array([True,False,False,True])
-  result = (d1/d2).view(MaskedArray) # masked_array([-1. inf, 3., 2.])
-  result._mask = logical_or(m, dm)
-
-Note that here again the division by zero takes place.
-
-A quick benchmark gives the following results:
-
- * *numpy.ma.divide*  : 2.69 ms per loop
- * classical division     : 2.21 ms per loop
- * division w/ prefilling : 2.34 ms per loop
- * division w/o filling   : 1.55 ms per loop
-
-So, is it worth filling the arrays beforehand ? Yes, if we are interested
-in avoiding floating-point exceptions that may fill the result with infs
-and nans. No, if we are only interested into speed...
-
-
-Thanks
-------
-
-I'd like to thank Paul Dubois, Travis Oliphant and Sasha for the
-original masked array package: without you, I would never have started
-that (it might be argued that I shouldn't have anyway, but that's
-another story...).  I also wish to extend these thanks to Reggie Dugard
-and Eric Firing for their suggestions and numerous improvements.
-
-
-Revision notes
---------------
-
-  * 08/25/2007 : Creation of this page
-  * 01/23/2007 : The package has been moved to the SciPy sandbox, and is regularly updated: please check out your SVN version!
index 36ceb1f6e7ae3c07e26cd400604e4bc3509aad23..870cc4ef2daabf7ac770415f73940b3edfd2477c 100644 (file)
@@ -39,8 +39,6 @@ may now proceed to calculate the mean of the other values:
 .. moduleauthor:: Jarrod Millman
 
 """
-from __future__ import division, absolute_import, print_function
-
 from . import core
 from .core import *
 
index a9ba42deae40ebe8a98b4ca04e817827a82aceee..83cc6aea7fb2c560db2f6fd608ad1df92ddf49d3 100644 (file)
@@ -1,8 +1,6 @@
-#! /usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 
-from __future__ import division, print_function
-
 import timeit
 import numpy
 
index 2baf547a423aa0f708e575459f3e7e1a579ae6f0..8d612b8ed6f9f1986464bdd65ca1b1c7b3e63dbb 100644 (file)
@@ -20,20 +20,13 @@ Released for unlimited redistribution.
 
 """
 # pylint: disable-msg=E1002
-from __future__ import division, absolute_import, print_function
-
-import sys
+import builtins
 import operator
 import warnings
 import textwrap
 import re
 from functools import reduce
 
-if sys.version_info[0] >= 3:
-    import builtins
-else:
-    import __builtin__ as builtins
-
 import numpy as np
 import numpy.core.umath as umath
 import numpy.core.numerictypes as ntypes
@@ -41,7 +34,7 @@ from numpy import ndarray, amax, amin, iscomplexobj, bool_, _NoValue
 from numpy import array as narray
 from numpy.lib.function_base import angle
 from numpy.compat import (
-    getargspec, formatargspec, long, basestring, unicode, bytes
+    getargspec, formatargspec, long, unicode, bytes
     )
 from numpy import expand_dims
 from numpy.core.numeric import normalize_axis_tuple
@@ -101,7 +94,7 @@ def _deprecate_argsort_axis(arr):
         The array which argsort was called on
 
     np.ma.argsort has a long-term bug where the default of the axis argument
-    is wrong (gh-8701), which now must be kept for backwards compatibiity.
+    is wrong (gh-8701), which now must be kept for backwards compatibility.
     Thankfully, this only makes a difference when arrays are 2- or more-
     dimensional, so we only need a warning then.
     """
@@ -198,14 +191,17 @@ for v in ["Y", "M", "W", "D", "h", "m", "s", "ms", "us", "ns", "ps",
     default_filler["M8[" + v + "]"] = np.datetime64("NaT", v)
     default_filler["m8[" + v + "]"] = np.timedelta64("NaT", v)
 
+float_types_list = [np.half, np.single, np.double, np.longdouble,
+                    np.csingle, np.cdouble, np.clongdouble]
 max_filler = ntypes._minvals
-max_filler.update([(k, -np.inf) for k in [np.float32, np.float64]])
+max_filler.update([(k, -np.inf) for k in float_types_list[:4]])
+max_filler.update([(k, complex(-np.inf, -np.inf)) for k in float_types_list[-3:]])
+
 min_filler = ntypes._maxvals
-min_filler.update([(k, +np.inf) for k in [np.float32, np.float64]])
-if 'float128' in ntypes.typeDict:
-    max_filler.update([(np.float128, -np.inf)])
-    min_filler.update([(np.float128, +np.inf)])
+min_filler.update([(k,  +np.inf) for k in float_types_list[:4]])
+min_filler.update([(k, complex(+np.inf, +np.inf)) for k in float_types_list[-3:]])
 
+del float_types_list
 
 def _recursive_fill_value(dtype, f):
     """
@@ -292,11 +288,10 @@ def _extremum_fill_value(obj, extremum, extremum_name):
     def _scalar_fill_value(dtype):
         try:
             return extremum[dtype]
-        except KeyError:
+        except KeyError as e:
             raise TypeError(
-                "Unsuitable type {} for calculating {}."
-                .format(dtype, extremum_name)
-            )
+                f"Unsuitable type {dtype} for calculating {extremum_name}."
+            ) from None
 
     dtype = _get_dtype_of(obj)
     return _recursive_fill_value(dtype, _scalar_fill_value)
@@ -462,7 +457,7 @@ def _check_fill_value(fill_value, ndtype):
             fill_value = np.array(_recursive_set_fill_value(fill_value, ndtype),
                                   dtype=ndtype)
     else:
-        if isinstance(fill_value, basestring) and (ndtype.char not in 'OSVU'):
+        if isinstance(fill_value, str) and (ndtype.char not in 'OSVU'):
             # Note this check doesn't work if fill_value is not a scalar
             err_msg = "Cannot set fill value of string with array of dtype %s"
             raise TypeError(err_msg % ndtype)
@@ -787,9 +782,9 @@ def fix_invalid(a, mask=nomask, copy=True, fill_value=None):
     return a
 
 def is_string_or_list_of_strings(val):
-    return (isinstance(val, basestring) or
+    return (isinstance(val, str) or
             (isinstance(val, list) and val and
-             builtins.all(isinstance(s, basestring) for s in val)))
+             builtins.all(isinstance(s, str) for s in val)))
 
 ###############################################################################
 #                                  Ufuncs                                     #
@@ -800,7 +795,7 @@ ufunc_domain = {}
 ufunc_fills = {}
 
 
-class _DomainCheckInterval(object):
+class _DomainCheckInterval:
     """
     Define a valid interval, so that :
 
@@ -825,7 +820,7 @@ class _DomainCheckInterval(object):
                                     umath.less(x, self.a))
 
 
-class _DomainTan(object):
+class _DomainTan:
     """
     Define a valid interval for the `tan` function, so that:
 
@@ -843,7 +838,7 @@ class _DomainTan(object):
             return umath.less(umath.absolute(umath.cos(x)), self.eps)
 
 
-class _DomainSafeDivide(object):
+class _DomainSafeDivide:
     """
     Define a domain for safe division.
 
@@ -864,7 +859,7 @@ class _DomainSafeDivide(object):
             return umath.absolute(a) * self.tolerance >= umath.absolute(b)
 
 
-class _DomainGreater(object):
+class _DomainGreater:
     """
     DomainGreater(v)(x) is True where x <= v.
 
@@ -880,7 +875,7 @@ class _DomainGreater(object):
             return umath.less_equal(x, self.critical_value)
 
 
-class _DomainGreaterEqual(object):
+class _DomainGreaterEqual:
     """
     DomainGreaterEqual(v)(x) is True where x < v.
 
@@ -896,14 +891,14 @@ class _DomainGreaterEqual(object):
             return umath.less(x, self.critical_value)
 
 
-class _MaskedUFunc(object):
+class _MaskedUFunc:
     def __init__(self, ufunc):
         self.f = ufunc
         self.__doc__ = ufunc.__doc__
         self.__name__ = ufunc.__name__
 
     def __str__(self):
-        return "Masked version of {}".format(self.f)
+        return f"Masked version of {self.f}"
 
 
 class _MaskedUnaryOperation(_MaskedUFunc):
@@ -1809,8 +1804,7 @@ def flatten_mask(mask):
         try:
             for element in sequence:
                 if hasattr(element, '__iter__'):
-                    for f in _flatsequence(element):
-                        yield f
+                    yield from _flatsequence(element)
                 else:
                     yield element
         except TypeError:
@@ -2386,7 +2380,7 @@ def masked_invalid(a, copy=True):
 ###############################################################################
 
 
-class _MaskedPrintOption(object):
+class _MaskedPrintOption:
     """
     Handle the string used to represent missing data in a masked array.
 
@@ -2537,8 +2531,7 @@ def flatten_structured_array(a):
         """
         for elm in iter(iterable):
             if hasattr(elm, '__iter__'):
-                for f in flatten_sequence(elm):
-                    yield f
+                yield from flatten_sequence(elm)
             else:
                 yield elm
 
@@ -2604,7 +2597,7 @@ def _arraymethod(funcname, onmask=True):
     return wrapped_method
 
 
-class MaskedIterator(object):
+class MaskedIterator:
     """
     Flat iterator object to iterate over masked arrays.
 
@@ -2711,8 +2704,6 @@ class MaskedIterator(object):
                 return masked
         return d
 
-    next = __next__
-
 
 class MaskedArray(ndarray):
     """
@@ -2767,6 +2758,52 @@ class MaskedArray(ndarray):
         in any order (either C-, Fortran-contiguous, or even discontiguous),
         unless a copy is required, in which case it will be C-contiguous.
 
+    Examples
+    --------
+
+    The ``mask`` can be initialized with an array of boolean values
+    with the same shape as ``data``.
+
+    >>> data = np.arange(6).reshape((2, 3))
+    >>> np.ma.MaskedArray(data, mask=[[False, True, False],
+    ...                               [False, False, True]])
+    masked_array(
+      data=[[0, --, 2],
+            [3, 4, --]],
+      mask=[[False,  True, False],
+            [False, False,  True]],
+      fill_value=999999)
+
+    Alternatively, the ``mask`` can be initialized to homogeneous boolean
+    array with the same shape as ``data`` by passing in a scalar
+    boolean value:
+
+    >>> np.ma.MaskedArray(data, mask=False)
+    masked_array(
+      data=[[0, 1, 2],
+            [3, 4, 5]],
+      mask=[[False, False, False],
+            [False, False, False]],
+      fill_value=999999)
+
+    >>> np.ma.MaskedArray(data, mask=True)
+    masked_array(
+      data=[[--, --, --],
+            [--, --, --]],
+      mask=[[ True,  True,  True],
+            [ True,  True,  True]],
+      fill_value=999999,
+      dtype=int64)
+
+    .. note::
+        The recommended practice for initializing ``mask`` with a scalar
+        boolean value is to use ``True``/``False`` rather than
+        ``np.True_``/``np.False_``. The reason is :attr:`nomask`
+        is represented internally as ``np.False_``.
+
+        >>> np.False_ is np.ma.nomask
+        True
+
     """
 
     __array_priority__ = 15
@@ -2828,8 +2865,8 @@ class MaskedArray(ndarray):
             elif isinstance(data, (tuple, list)):
                 try:
                     # If data is a sequence of masked array
-                    mask = np.array([getmaskarray(m) for m in data],
-                                    dtype=mdtype)
+                    mask = np.array([getmaskarray(np.asanyarray(m, dtype=mdtype))
+                                                    for m in data], dtype=mdtype)
                 except ValueError:
                     # If data is nested
                     mask = nomask
@@ -3265,6 +3302,10 @@ class MaskedArray(ndarray):
                 if self._fill_value is not None:
                     dout._fill_value = self._fill_value[indx]
 
+                    # Something like gh-15895 has happened if this check fails.
+                    # _fill_value should always be an ndarray.
+                    if not isinstance(dout._fill_value, np.ndarray):
+                        raise RuntimeError('Internal NumPy error.')
                     # If we're indexing a multidimensional field in a
                     # structured array (such as dtype("(2,)i2,(2,)i1")),
                     # dimensionality goes up (M[field].ndim == M.ndim +
@@ -3272,19 +3313,21 @@ class MaskedArray(ndarray):
                     # M[field] but problematic for M[field].fill_value
                     # which should have shape () to avoid breaking several
                     # methods. There is no great way out, so set to
-                    # first element.  See issue #6723.
+                    # first element. See issue #6723.
                     if dout._fill_value.ndim > 0:
                         if not (dout._fill_value ==
                                 dout._fill_value.flat[0]).all():
                             warnings.warn(
                                 "Upon accessing multidimensional field "
-                                "{indx:s}, need to keep dimensionality "
+                                f"{indx!s}, need to keep dimensionality "
                                 "of fill_value at 0. Discarding "
                                 "heterogeneous fill_value and setting "
-                                "all to {fv!s}.".format(indx=indx,
-                                    fv=dout._fill_value[0]),
+                                f"all to {dout._fill_value[0]!s}.",
                                 stacklevel=2)
-                        dout._fill_value = dout._fill_value.flat[0]
+                        # Need to use `.flat[0:1].squeeze(...)` instead of just
+                        # `.flat[0]` to ensure the result is a 0d array and not
+                        # a scalar.
+                        dout._fill_value = dout._fill_value.flat[0:1].squeeze(axis=0)
                 dout._isfield = True
             # Update the mask if needed
             if mout is not nomask:
@@ -3306,7 +3349,7 @@ class MaskedArray(ndarray):
             raise MaskError('Cannot alter the masked element.')
         _data = self._data
         _mask = self._mask
-        if isinstance(indx, basestring):
+        if isinstance(indx, str):
             _data[indx] = value
             if _mask is nomask:
                 self._mask = _mask = make_mask_none(self.shape, self.dtype)
@@ -3897,10 +3940,6 @@ class MaskedArray(ndarray):
     def __str__(self):
         return str(self._insert_masked_print())
 
-    if sys.version_info.major < 3:
-        def __unicode__(self):
-            return unicode(self._insert_masked_print())
-
     def __repr__(self):
         """
         Literal string representation.
@@ -3930,7 +3969,7 @@ class MaskedArray(ndarray):
             )
             return _legacy_print_templates[key] % parameters
 
-        prefix = 'masked_{}('.format(name)
+        prefix = f"masked_{name}("
 
         dtype_needed = (
             not np.core.arrayprint.dtype_is_implied(self.dtype) or
@@ -4344,17 +4383,6 @@ class MaskedArray(ndarray):
             raise MaskError('Cannot convert masked element to a Python int.')
         return int(self.item())
 
-    def __long__(self):
-        """
-        Convert to long.
-        """
-        if self.size > 1:
-            raise TypeError("Only length-1 arrays can be converted "
-                            "to Python scalars")
-        elif self._mask:
-            raise MaskError('Cannot convert masked element to a Python long.')
-        return long(self.item())
-
     @property
     def imag(self):
         """
@@ -4750,7 +4778,7 @@ class MaskedArray(ndarray):
 
         >>> x = np.ma.array([1, 2, 3])
         >>> x.ids()
-        (166691080, 3083169284L) # may vary
+        (166691080, 3083169284) # may vary
 
         """
         if self._mask is nomask:
@@ -5835,6 +5863,14 @@ class MaskedArray(ndarray):
         Return (maximum - minimum) along the given dimension
         (i.e. peak-to-peak value).
 
+        .. warning::
+            `ptp` preserves the data type of the array. This means the
+            return value for an input of signed integers with n bits
+            (e.g. `np.int8`, `np.int16`, etc) is also a signed integer
+            with n bits.  In that case, peak-to-peak values greater than
+            ``2**(n-1)-1`` will be returned as negative values. An example
+            with a work-around is shown below.
+
         Parameters
         ----------
         axis : {None, int}, optional
@@ -5857,6 +5893,45 @@ class MaskedArray(ndarray):
             A new array holding the result, unless ``out`` was
             specified, in which case a reference to ``out`` is returned.
 
+        Examples
+        --------
+        >>> x = np.ma.MaskedArray([[4, 9, 2, 10],
+        ...                        [6, 9, 7, 12]])
+
+        >>> x.ptp(axis=1)
+        masked_array(data=[8, 6],
+                     mask=False,
+               fill_value=999999)
+
+        >>> x.ptp(axis=0)
+        masked_array(data=[2, 0, 5, 2],
+                     mask=False,
+               fill_value=999999)
+
+        >>> x.ptp()
+        10
+
+        This example shows that a negative value can be returned when
+        the input is an array of signed integers.
+
+        >>> y = np.ma.MaskedArray([[1, 127],
+        ...                        [0, 127],
+        ...                        [-1, 127],
+        ...                        [-2, 127]], dtype=np.int8)
+        >>> y.ptp(axis=1)
+        masked_array(data=[ 126,  127, -128, -127],
+                     mask=False,
+               fill_value=999999,
+                    dtype=int8)
+
+        A work-around is to use the `view()` method to view the result as
+        unsigned integers with the same bit width:
+
+        >>> y.ptp(axis=1).view(np.uint8)
+        masked_array(data=[126, 127, 128, 129],
+                     mask=False,
+               fill_value=999999,
+                    dtype=uint8)
         """
         if out is None:
             result = self.max(axis=axis, fill_value=fill_value,
@@ -5873,13 +5948,13 @@ class MaskedArray(ndarray):
 
     def partition(self, *args, **kwargs):
         warnings.warn("Warning: 'partition' will ignore the 'mask' "
-                      "of the {}.".format(self.__class__.__name__),
+                      f"of the {self.__class__.__name__}.",
                       stacklevel=2)
         return super(MaskedArray, self).partition(*args, **kwargs)
 
     def argpartition(self, *args, **kwargs):
         warnings.warn("Warning: 'argpartition' will ignore the 'mask' "
-                      "of the {}.".format(self.__class__.__name__),
+                      f"of the {self.__class__.__name__}.",
                       stacklevel=2)
         return super(MaskedArray, self).argpartition(*args, **kwargs)
 
@@ -5971,10 +6046,17 @@ class MaskedArray(ndarray):
         return result.tolist()
 
     def tostring(self, fill_value=None, order='C'):
+        r"""
+        A compatibility alias for `tobytes`, with exactly the same behavior.
+
+        Despite its name, it returns `bytes` not `str`\ s.
+
+        .. deprecated:: 1.19.0
         """
-        This function is a compatibility alias for tobytes. Despite its name it
-        returns bytes not strings.
-        """
+        # 2020-03-30, Numpy 1.19.0
+        warnings.warn(
+            "tostring() is deprecated. Use tobytes() instead.",
+            DeprecationWarning, stacklevel=2)
 
         return self.tobytes(fill_value, order=order)
 
@@ -6225,8 +6307,7 @@ class mvoid(MaskedArray):
         "Defines an iterator for mvoid"
         (_data, _mask) = (self._data, self._mask)
         if _mask is nomask:
-            for d in _data:
-                yield d
+            yield from _data
         else:
             for (d, m) in zip(_data, _mask):
                 if m:
@@ -6396,10 +6477,6 @@ class MaskedConstant(MaskedArray):
     def __str__(self):
         return str(masked_print_option._display)
 
-    if sys.version_info.major < 3:
-        def __unicode__(self):
-            return unicode(masked_print_option._display)
-
     def __repr__(self):
         if self is MaskedConstant.__singleton:
             return 'masked'
@@ -6407,6 +6484,21 @@ class MaskedConstant(MaskedArray):
             # it's a subclass, or something is wrong, make it obvious
             return object.__repr__(self)
 
+    def __format__(self, format_spec):
+        # Replace ndarray.__format__ with the default, which supports no format characters.
+        # Supporting format characters is unwise here, because we do not know what type
+        # the user was expecting - better to not guess.
+        try:
+            return object.__format__(self, format_spec)
+        except TypeError:
+            # 2020-03-23, NumPy 1.19.0
+            warnings.warn(
+                "Format strings passed to MaskedConstant are ignored, but in future may "
+                "error or produce different behavior",
+                FutureWarning, stacklevel=2
+            )
+            return object.__format__(self, "")
+
     def __reduce__(self):
         """Override of MaskedArray's __reduce__.
         """
@@ -6443,7 +6535,7 @@ class MaskedConstant(MaskedArray):
             return super(MaskedConstant, self).__setattr__(attr, value)
         elif self is self.__singleton:
             raise AttributeError(
-                "attributes of {!r} are not writeable".format(self))
+                f"attributes of {self!r} are not writeable")
         else:
             # duplicate instance - we can end up here from __array_finalize__,
             # where we set the __class__ attribute
@@ -6548,8 +6640,8 @@ class _extrema_operation(_MaskedUFunc):
         if b is None:
             # 2016-04-13, 1.13.0
             warnings.warn(
-                "Single-argument form of np.ma.{0} is deprecated. Use "
-                "np.ma.{0}.reduce instead.".format(self.__name__),
+                f"Single-argument form of np.ma.{self.__name__} is deprecated. Use "
+                f"np.ma.{self.__name__}.reduce instead.",
                 DeprecationWarning, stacklevel=2)
             return self.reduce(a)
         return where(self.compare(a, b), a, b)
@@ -6562,11 +6654,9 @@ class _extrema_operation(_MaskedUFunc):
         if axis is np._NoValue and target.ndim > 1:
             # 2017-05-06, Numpy 1.13.0: warn on axis default
             warnings.warn(
-                "In the future the default for ma.{0}.reduce will be axis=0, "
-                "not the current None, to match np.{0}.reduce. "
-                "Explicitly pass 0 or None to silence this warning.".format(
-                    self.__name__
-                ),
+                f"In the future the default for ma.{self.__name__}.reduce will be axis=0, "
+                f"not the current None, to match np.{self.__name__}.reduce. "
+                "Explicitly pass 0 or None to silence this warning.",
                 MaskedArrayFutureWarning, stacklevel=2)
             axis = None
 
@@ -6646,7 +6736,7 @@ ptp.__doc__ = MaskedArray.ptp.__doc__
 ##############################################################################
 
 
-class _frommethod(object):
+class _frommethod:
     """
     Define functions from existing MaskedArray methods.
 
@@ -6793,7 +6883,18 @@ def argsort(a, axis=np._NoValue, kind=None, order=None, endwith=True, fill_value
 argsort.__doc__ = MaskedArray.argsort.__doc__
 
 def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None):
-    "Function version of the eponymous method."
+    """
+    Return a sorted copy of the masked array.
+
+    Equivalent to creating a copy of the array
+    and applying the  MaskedArray ``sort()`` method.
+
+    Refer to ``MaskedArray.sort`` for the full documentation
+
+    See Also
+    --------
+    MaskedArray.sort : equivalent method
+    """
     a = np.array(a, copy=True, subok=True)
     if axis is None:
         a = a.flatten()
@@ -6805,7 +6906,6 @@ def sort(a, axis=-1, kind=None, order=None, endwith=True, fill_value=None):
     else:
         a.sort(axis=axis, kind=kind, order=order)
     return a
-sort.__doc__ = MaskedArray.sort.__doc__
 
 
 def compressed(x):
@@ -7905,10 +8005,8 @@ def asanyarray(a, dtype=None):
 def _pickle_warn(method):
     # NumPy 1.15.0, 2017-12-10
     warnings.warn(
-        "np.ma.{method} is deprecated, use pickle.{method} instead"
-            .format(method=method),
-        DeprecationWarning,
-        stacklevel=3)
+        f"np.ma.{method} is deprecated, use pickle.{method} instead",
+        DeprecationWarning, stacklevel=3)
 
 
 def fromfile(file, dtype=float, count=-1, sep=''):
@@ -7980,7 +8078,7 @@ def fromflex(fxarray):
     return masked_array(fxarray['_data'], mask=fxarray['_mask'])
 
 
-class _convert2ma(object):
+class _convert2ma:
 
     """
     Convert functions from numpy to numpy.ma.
index f4a9144719702544bd71e1205ce1f35b09905f38..f86ebf5518ec542324f81f8e19648a4102ea3e0b 100644 (file)
@@ -8,8 +8,6 @@ A collection of utilities for `numpy.ma`.
 :version: $Id: extras.py 3473 2007-10-29 15:18:13Z jarrod.millman $
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = [
     'apply_along_axis', 'apply_over_axes', 'atleast_1d', 'atleast_2d',
     'atleast_3d', 'average', 'clump_masked', 'clump_unmasked',
@@ -214,7 +212,7 @@ def masked_all_like(arr):
 #####--------------------------------------------------------------------------
 #---- --- Standard functions ---
 #####--------------------------------------------------------------------------
-class _fromnxfunction(object):
+class _fromnxfunction:
     """
     Defines a wrapper to adapt NumPy functions to masked arrays.
 
@@ -813,7 +811,7 @@ def compress_nd(x, axis=None):
     ----------
     x : array_like, MaskedArray
         The array to operate on. If not a MaskedArray instance (or if no array
-        elements are masked, `x` is interpreted as a MaskedArray with `mask`
+        elements are masked), `x` is interpreted as a MaskedArray with `mask`
         set to `nomask`.
     axis : tuple of ints or int, optional
         Which dimensions to suppress slices from can be configured with this
index ae1a12c2cbd8fd64ea49ab269950127f48e8b510..cd93a9a1431364af47bcb4ff5a536d58438ab5a4 100644 (file)
@@ -8,18 +8,14 @@ and the masking of individual fields.
 .. moduleauthor:: Pierre Gerard-Marchant
 
 """
-from __future__ import division, absolute_import, print_function
-
 #  We should make sure that no field is called '_mask','mask','_fieldmask',
 #  or whatever restricted keywords.  An idea would be to no bother in the
 #  first place, and then rename the invalid fields with a trailing
 #  underscore. Maybe we could just overload the parser function ?
 
-import sys
 import warnings
 
 import numpy as np
-from numpy.compat import basestring
 from numpy import (
         bool_, dtype, ndarray, recarray, array as narray
         )
@@ -87,7 +83,7 @@ def _get_fieldmask(self):
     return fdmask
 
 
-class MaskedRecords(MaskedArray, object):
+class MaskedRecords(MaskedArray):
     """
 
     Attributes
@@ -305,7 +301,7 @@ class MaskedRecords(MaskedArray, object):
         _mask = ndarray.__getattribute__(self, '_mask')
         _data = ndarray.view(self, _localdict['_baseclass'])
         # We want a field
-        if isinstance(indx, basestring):
+        if isinstance(indx, str):
             # Make sure _sharedmask is True to propagate back to _fieldmask
             # Don't use _set_mask, there are some copies being made that
             # break propagation Don't force the mask to nomask, that wreaks
@@ -332,7 +328,7 @@ class MaskedRecords(MaskedArray, object):
 
         """
         MaskedArray.__setitem__(self, indx, value)
-        if isinstance(indx, basestring):
+        if isinstance(indx, str):
             self._mask[indx] = ma.getmaskarray(value)
 
     def __str__(self):
index d1d6c89b513952ce0630888bcc99cf9c19ffde9d..d3f34c874607732ffc718dada3370eb12a815fdd 100644 (file)
@@ -1,10 +1,8 @@
-#!/usr/bin/env python
-from __future__ import division, print_function
-
+#!/usr/bin/env python3
 def configuration(parent_package='',top_path=None):
     from numpy.distutils.misc_util import Configuration
     config = Configuration('ma', parent_package, top_path)
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
     return config
 
 if __name__ == "__main__":
index b72ce56aa2996a042e16e1139ebfd89db0b70950..6f34144bb147f4596e2cfbd6ac017fc1f9dfa1a1 100644 (file)
@@ -4,8 +4,6 @@
 :author: Pierre Gerard-Marchant
 :contact: pierregm_at_uga_dot_edu
 """
-from __future__ import division, absolute_import, print_function
-
 __author__ = "Pierre GF Gerard-Marchant"
 
 import sys
@@ -65,7 +63,7 @@ num_dts = [np.dtype(dt_) for dt_ in '?bhilqBHILQefdgFD']
 num_ids = [dt_.char for dt_ in num_dts]
 
 
-class TestMaskedArray(object):
+class TestMaskedArray:
     # Base test class for MaskedArrays.
 
     def setup(self):
@@ -449,6 +447,21 @@ class TestMaskedArray(object):
         assert_equal(copied.mask, [0, 0, 0])
         assert_equal(a.mask, [0, 1, 0])
 
+    def test_format(self):
+        a = array([0, 1, 2], mask=[False, True, False])
+        assert_equal(format(a), "[0 -- 2]")
+        assert_equal(format(masked), "--")
+        assert_equal(format(masked, ""), "--")
+
+        # Postponed from PR #15410, perhaps address in the future.
+        # assert_equal(format(masked, " >5"), "   --")
+        # assert_equal(format(masked, " <5"), "--   ")
+
+        # Expect a FutureWarning for using format_spec with MaskedElement
+        with assert_warns(FutureWarning):
+            with_format_string = format(masked, " >5")
+        assert_equal(with_format_string, "--")
+
     def test_str_repr(self):
         a = array([0, 1, 2], mask=[False, True, False])
         assert_equal(str(a), '[0 -- 2]')
@@ -936,7 +949,7 @@ class TestMaskedArray(object):
     def test_object_with_array(self):
         mx1 = masked_array([1.], mask=[True])
         mx2 = masked_array([1., 2.])
-        mx = masked_array([mx1, mx2], mask=[False, True])
+        mx = masked_array([mx1, mx2], mask=[False, True], dtype=object)
         assert_(mx[0] is mx1)
         assert_(mx[1] is not mx2)
         assert_(np.all(mx[1].data == mx2.data))
@@ -946,7 +959,7 @@ class TestMaskedArray(object):
         assert_(mx2[0] == 0.)
 
 
-class TestMaskedArrayArithmetic(object):
+class TestMaskedArrayArithmetic:
     # Base test class for MaskedArrays.
 
     def setup(self):
@@ -1232,6 +1245,48 @@ class TestMaskedArrayArithmetic(object):
         assert_(x.max() is masked)
         assert_(x.ptp() is masked)
 
+    def test_minmax_dtypes(self):
+        # Additional tests on max/min for non-standard float and complex dtypes
+        x = np.array([1., 1., 1., -2., pi/2.0, 4., 5., -10., 10., 1., 2., 3.])
+        a10 = 10.
+        an10 = -10.0
+        m1 = [1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0]
+        xm = masked_array(x, mask=m1)
+        xm.set_fill_value(1e+20)
+        float_dtypes = [np.half, np.single, np.double,
+                        np.longdouble, np.cfloat, np.cdouble, np.clongdouble]
+        for float_dtype in float_dtypes:
+            assert_equal(masked_array(x, mask=m1, dtype=float_dtype).max(),
+                         float_dtype(a10))
+            assert_equal(masked_array(x, mask=m1, dtype=float_dtype).min(),
+                         float_dtype(an10))
+
+        assert_equal(xm.min(), an10)
+        assert_equal(xm.max(), a10)
+
+        # Non-complex type only test
+        for float_dtype in float_dtypes[:4]:
+            assert_equal(masked_array(x, mask=m1, dtype=float_dtype).max(),
+                         float_dtype(a10))
+            assert_equal(masked_array(x, mask=m1, dtype=float_dtype).min(),
+                         float_dtype(an10))
+
+        # Complex types only test
+        for float_dtype in float_dtypes[-3:]:
+            ym = masked_array([1e20+1j, 1e20-2j, 1e20-1j], mask=[0, 1, 0],
+                          dtype=float_dtype)
+            assert_equal(ym.min(), float_dtype(1e20-1j))
+            assert_equal(ym.max(), float_dtype(1e20+1j))
+
+            zm = masked_array([np.inf+2j, np.inf+3j, -np.inf-1j], mask=[0, 1, 0],
+                              dtype=float_dtype)
+            assert_equal(zm.min(), float_dtype(-np.inf-1j))
+            assert_equal(zm.max(), float_dtype(np.inf+2j))
+            
+            cmax = np.inf - 1j * np.finfo(np.float64).max
+            assert masked_array([-cmax, 0], mask=[0, 1]).max() == -cmax
+            assert masked_array([cmax, 0], mask=[0, 1]).min() == cmax
+
     def test_addsumprod(self):
         # Tests add, sum, product.
         (x, y, a10, m1, m2, xm, ym, z, zm, xf) = self.d
@@ -1558,7 +1613,11 @@ class TestMaskedArrayArithmetic(object):
         assert_equal(test.mask, [True, True])
         assert_(test.fill_value == True)
 
-        # test = (a[0] == b)  # doesn't work in Python2
+        test = (a[0] == b)
+        assert_equal(test.data, [False, False])
+        assert_equal(test.mask, [True, False])
+        assert_(test.fill_value == True)
+
         test = (b == a[0])
         assert_equal(test.data, [False, False])
         assert_equal(test.mask, [True, False])
@@ -1586,7 +1645,11 @@ class TestMaskedArrayArithmetic(object):
         assert_equal(test.mask, [True, True])
         assert_(test.fill_value == True)
 
-        # test = (a[0] != b)  # doesn't work in Python2
+        test = (a[0] != b)
+        assert_equal(test.data, [True, True])
+        assert_equal(test.mask, [True, False])
+        assert_(test.fill_value == True)
+
         test = (b != a[0])
         assert_equal(test.data, [True, True])
         assert_equal(test.mask, [True, False])
@@ -1615,7 +1678,11 @@ class TestMaskedArrayArithmetic(object):
         assert_equal(test.mask, [True, True])
         assert_(test.fill_value == True)
 
-        # test = (a[0] == b)  # doesn't work in Python2
+        test = (a[0] == b)
+        assert_equal(test.data, [False, False])
+        assert_equal(test.mask, [True, False])
+        assert_(test.fill_value == True)
+
         test = (b == a[0])
         assert_equal(test.data, [False, False])
         assert_equal(test.mask, [True, False])
@@ -1644,7 +1711,11 @@ class TestMaskedArrayArithmetic(object):
         assert_equal(test.mask, [True, True])
         assert_(test.fill_value == True)
 
-        # test = (a[0] != b)  # doesn't work in Python2
+        test = (a[0] != b)
+        assert_equal(test.data, [True, True])
+        assert_equal(test.mask, [True, False])
+        assert_(test.fill_value == True)
+
         test = (b != a[0])
         assert_equal(test.data, [True, True])
         assert_equal(test.mask, [True, False])
@@ -1715,7 +1786,7 @@ class TestMaskedArrayArithmetic(object):
         assert_equal(a.mask, [0, 0, 0, 0, 1])
 
 
-class TestMaskedArrayAttributes(object):
+class TestMaskedArrayAttributes:
 
     def test_keepmask(self):
         # Tests the keep mask flag
@@ -1891,7 +1962,7 @@ class TestMaskedArrayAttributes(object):
         assert_equal(m._mask, np.ma.nomask)
 
 
-class TestFillingValues(object):
+class TestFillingValues:
 
     def test_check_on_scalar(self):
         # Test _check_fill_value set to valid and invalid values
@@ -2229,7 +2300,7 @@ class TestFillingValues(object):
         assert_equal(a["f1"].fill_value, default_fill_value("eggs"))
 
 
-class TestUfuncs(object):
+class TestUfuncs:
     # Test class for the application of ufuncs on MaskedArrays.
 
     def setup(self):
@@ -2309,7 +2380,7 @@ class TestUfuncs(object):
         assert_raises(TypeError, operator.mul, a, "abc")
         assert_raises(TypeError, operator.truediv, a, "abc")
 
-        class MyClass(object):
+        class MyClass:
             __array_priority__ = a.__array_priority__ + 1
 
             def __mul__(self, other):
@@ -2323,7 +2394,7 @@ class TestUfuncs(object):
         assert_(a * me == "My rmul")
 
         # and that __array_priority__ is respected
-        class MyClass2(object):
+        class MyClass2:
             __array_priority__ = 100
 
             def __mul__(self, other):
@@ -2373,7 +2444,7 @@ class TestUfuncs(object):
             # also check that allclose uses ma ufuncs, to avoid warning
             allclose(m, 0.5)
 
-class TestMaskedArrayInPlaceArithmetics(object):
+class TestMaskedArrayInPlaceArithmetics:
     # Test MaskedArray Arithmetics
 
     def setup(self):
@@ -2875,7 +2946,7 @@ class TestMaskedArrayInPlaceArithmetics(object):
                 assert_equal(len(w), 0, "Failed on type=%s." % t)
 
 
-class TestMaskedArrayMethods(object):
+class TestMaskedArrayMethods:
     # Test class for miscellaneous MaskedArrays methods.
     def setup(self):
         # Base data definition.
@@ -3582,7 +3653,7 @@ class TestMaskedArrayMethods(object):
         assert_equal(xd.data, x.diagonal().data)
 
 
-class TestMaskedArrayMathMethods(object):
+class TestMaskedArrayMathMethods:
 
     def setup(self):
         # Base data definition.
@@ -3860,7 +3931,7 @@ class TestMaskedArrayMathMethods(object):
         assert_equal(a.max(1), [3, 6])
 
 
-class TestMaskedArrayMathMethodsComplex(object):
+class TestMaskedArrayMathMethodsComplex:
     # Test class for miscellaneous MaskedArrays methods.
     def setup(self):
         # Base data definition.
@@ -3913,7 +3984,7 @@ class TestMaskedArrayMathMethodsComplex(object):
                                 mX[:, k].compressed().std())
 
 
-class TestMaskedArrayFunctions(object):
+class TestMaskedArrayFunctions:
     # Test class for miscellaneous functions.
 
     def setup(self):
@@ -4552,7 +4623,7 @@ class TestMaskedArrayFunctions(object):
         assert_equal(test, masked_equal([-1, -1, -1, -1, -1], -1))
 
 
-class TestMaskedFields(object):
+class TestMaskedFields:
 
     def setup(self):
         ilist = [1, 2, 3, 4, 5]
@@ -4714,7 +4785,7 @@ class TestMaskedFields(object):
             assert_equal(len(rec), len(self.data['ddtype']))
 
 
-class TestMaskedObjectArray(object):
+class TestMaskedObjectArray:
 
     def test_getitem(self):
         arr = np.ma.array([None, None])
@@ -4762,7 +4833,7 @@ class TestMaskedObjectArray(object):
         assert_(arr[0] is np.ma.masked)
 
 
-class TestMaskedView(object):
+class TestMaskedView:
 
     def setup(self):
         iterator = list(zip(np.arange(10), np.random.rand(10)))
@@ -4840,7 +4911,7 @@ class TestMaskedView(object):
         assert_(not isinstance(test, MaskedArray))
 
 
-class TestOptionalArgs(object):
+class TestOptionalArgs:
     def test_ndarrayfuncs(self):
         # test axis arg behaves the same as ndarray (including multiple axes)
 
@@ -4927,7 +4998,7 @@ class TestOptionalArgs(object):
         assert_raises(np.AxisError, count, np.ma.array(1), axis=1)
 
 
-class TestMaskedConstant(object):
+class TestMaskedConstant:
     def _do_add_test(self, add):
         # sanity check
         assert_(add(np.ma.masked, 1) is np.ma.masked)
@@ -5008,11 +5079,6 @@ class TestMaskedConstant(object):
         assert_raises(MaskError, operator.setitem, a_i, (), np.ma.masked)
         assert_raises(MaskError, int, np.ma.masked)
 
-    @pytest.mark.skipif(sys.version_info.major == 3,
-                        reason="long doesn't exist in Python 3")
-    def test_coercion_long(self):
-        assert_raises(MaskError, long, np.ma.masked)
-
     def test_coercion_float(self):
         a_f = np.zeros((), float)
         assert_warns(UserWarning, operator.setitem, a_f, (), np.ma.masked)
@@ -5044,7 +5110,7 @@ class TestMaskedConstant(object):
         assert_raises(AttributeError, setattr, np.ma.masked, 'dtype', np.int64)
 
 
-class TestMaskedWhereAliases(object):
+class TestMaskedWhereAliases:
 
     # TODO: Test masked_object, masked_equal, ...
 
index 72cc29aa046e177f07f2d68039f2c569a5399e94..14f69737583f4655357d654bf55fbc3a580b594b 100644 (file)
@@ -1,14 +1,12 @@
 """Test deprecation and future warnings.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.testing import assert_warns
 from numpy.ma.testutils import assert_equal
 from numpy.ma.core import MaskedArrayFutureWarning
 
-class TestArgsort(object):
+class TestArgsort:
     """ gh-8701 """
     def _test_base(self, argsort, cls):
         arr_0d = np.array(1).view(cls)
@@ -37,7 +35,7 @@ class TestArgsort(object):
         return self._test_base(np.ma.MaskedArray.argsort, np.ma.MaskedArray)
 
 
-class TestMinimumMaximum(object):
+class TestMinimumMaximum:
     def test_minimum(self):
         assert_warns(DeprecationWarning, np.ma.minimum, np.ma.array([1, 2]))
 
index c75c47801bf488776a863911932002cc570a3329..d237829cb71f453f7cfb61512274315bdbd6103f 100644 (file)
@@ -7,8 +7,6 @@ Adapted from the original test_ma by Pierre Gerard-Marchant
 :version: $Id: test_extras.py 3473 2007-10-29 15:18:13Z jarrod.millman $
 
 """
-from __future__ import division, absolute_import, print_function
-
 import warnings
 import itertools
 import pytest
@@ -34,7 +32,7 @@ from numpy.ma.extras import (
     )
 
 
-class TestGeneric(object):
+class TestGeneric:
     #
     def test_masked_all(self):
         # Tests masked_all
@@ -66,6 +64,28 @@ class TestGeneric(object):
         control = array([[(1, (1, 1))]], mask=[[(1, (1, 1))]], dtype=dt)
         assert_equal(test, control)
 
+    def test_masked_all_with_object_nested(self):
+        # Test masked_all works with nested array with dtype of an 'object'
+        # refers to issue #15895
+        my_dtype = np.dtype([('b', ([('c', object)], (1,)))])
+        masked_arr = np.ma.masked_all((1,), my_dtype)
+
+        assert_equal(type(masked_arr['b']), np.ma.core.MaskedArray)
+        assert_equal(type(masked_arr['b']['c']), np.ma.core.MaskedArray)
+        assert_equal(len(masked_arr['b']['c']), 1)
+        assert_equal(masked_arr['b']['c'].shape, (1, 1))
+        assert_equal(masked_arr['b']['c']._fill_value.shape, ())
+    
+    def test_masked_all_with_object(self):
+        # same as above except that the array is not nested
+        my_dtype = np.dtype([('b', (object, (1,)))])
+        masked_arr = np.ma.masked_all((1,), my_dtype)
+
+        assert_equal(type(masked_arr['b']), np.ma.core.MaskedArray)
+        assert_equal(len(masked_arr['b']), 1)
+        assert_equal(masked_arr['b'].shape, (1, 1))
+        assert_equal(masked_arr['b']._fill_value.shape, ())
+
     def test_masked_all_like(self):
         # Tests masked_all
         # Standard dtype
@@ -142,7 +162,7 @@ class TestGeneric(object):
         assert_equal(test, [])
 
 
-class TestAverage(object):
+class TestAverage:
     # Several tests of average. Why so many ? Good point...
     def test_testAverage1(self):
         # Test of average.
@@ -273,7 +293,7 @@ class TestAverage(object):
         assert_almost_equal(wav1.imag, expected1.imag)
 
 
-class TestConcatenator(object):
+class TestConcatenator:
     # Tests for mr_, the equivalent of r_ for masked arrays.
 
     def test_1d(self):
@@ -317,7 +337,7 @@ class TestConcatenator(object):
         assert_equal(actual.data[:2], [1, 2])
 
 
-class TestNotMasked(object):
+class TestNotMasked:
     # Tests notmasked_edges and notmasked_contiguous.
 
     def test_edges(self):
@@ -387,7 +407,7 @@ class TestNotMasked(object):
         ])
 
 
-class TestCompressFunctions(object):
+class TestCompressFunctions:
 
     def test_compress_nd(self):
         # Tests compress_nd
@@ -652,7 +672,7 @@ class TestCompressFunctions(object):
         assert_equal(a, res)
 
 
-class TestApplyAlongAxis(object):
+class TestApplyAlongAxis:
     # Tests 2D functions
     def test_3d(self):
         a = arange(12.).reshape(2, 2, 3)
@@ -674,7 +694,7 @@ class TestApplyAlongAxis(object):
         assert_equal(xa, [[2, 5], [8, 11]])
 
 
-class TestApplyOverAxes(object):
+class TestApplyOverAxes:
     # Tests apply_over_axes
     def test_basic(self):
         a = arange(24).reshape(2, 3, 4)
@@ -687,7 +707,7 @@ class TestApplyOverAxes(object):
         assert_equal(test, ctrl)
 
 
-class TestMedian(object):
+class TestMedian:
     def test_pytype(self):
         r = np.ma.median([[np.inf, np.inf], [np.inf, np.inf]], axis=-1)
         assert_equal(r, np.inf)
@@ -1066,7 +1086,7 @@ class TestMedian(object):
         assert_(type(np.ma.median(o.astype(object))), float)
 
 
-class TestCov(object):
+class TestCov:
 
     def setup(self):
         self.data = array(np.random.rand(12))
@@ -1133,7 +1153,7 @@ class TestCov(object):
                              x.shape[0] / frac))
 
 
-class TestCorrcoef(object):
+class TestCorrcoef:
 
     def setup(self):
         self.data = array(np.random.rand(12))
@@ -1240,7 +1260,7 @@ class TestCorrcoef(object):
                                 control[:-1, :-1])
 
 
-class TestPolynomial(object):
+class TestPolynomial:
     #
     def test_polyfit(self):
         # Tests polyfit
@@ -1298,7 +1318,7 @@ class TestPolynomial(object):
             assert_almost_equal(a, a_)
 
 
-class TestArraySetOps(object):
+class TestArraySetOps:
 
     def test_unique_onlist(self):
         # Test unique on list
@@ -1530,7 +1550,7 @@ class TestArraySetOps(object):
         assert_array_equal(setdiff1d(a, b), np.array(['c']))
 
 
-class TestShapeBase(object):
+class TestShapeBase:
 
     def test_atleast_2d(self):
         # Test atleast_2d
@@ -1586,7 +1606,7 @@ class TestShapeBase(object):
         assert_equal(b.mask.shape, b.data.shape)
 
 
-class TestStack(object):
+class TestStack:
 
     def test_stack_1d(self):
         a = masked_array([0, 1, 2], mask=[0, 1, 0])
index 94e772d5571d78621fb11504f6a4d5ce38545ed2..c2f859273c386ee368156822c70b5261579970a1 100644 (file)
@@ -5,8 +5,6 @@
 :contact: pierregm_at_uga_dot_edu
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 import numpy.ma as ma
 from numpy import recarray
@@ -26,7 +24,7 @@ from numpy.ma.testutils import (
 from numpy.compat import pickle
 
 
-class TestMRecords(object):
+class TestMRecords:
 
     ilist = [1, 2, 3, 4, 5]
     flist = [1.1, 2.2, 3.3, 4.4, 5.5]
@@ -348,7 +346,7 @@ class TestMRecords(object):
                                       dtype=mult.dtype))
 
 
-class TestView(object):
+class TestView:
 
     def setup(self):
         (a, b) = (np.arange(10), np.random.rand(10))
@@ -386,7 +384,7 @@ class TestView(object):
 
 
 ##############################################################################
-class TestMRecordsImport(object):
+class TestMRecordsImport:
 
     _a = ma.array([1, 2, 3], mask=[0, 0, 1], dtype=int)
     _b = ma.array([1.1, 2.2, 3.3], mask=[0, 0, 1], dtype=float)
index 7100eccbbe82c01b37ffaeac3d61c2aa6ee20e20..96c7e3609795263691e5c3488348762d9146da1b 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 from functools import reduce
 
 import numpy as np
@@ -33,7 +31,7 @@ def eq(v, w, msg=''):
     return result
 
 
-class TestMa(object):
+class TestMa:
 
     def setup(self):
         x = np.array([1., 1., 1., -2., pi/2.0, 4., 5., -10., 10., 1., 2., 3.])
@@ -700,7 +698,7 @@ class TestMa(object):
         assert_equal(b[1].shape, ())
 
 
-class TestUfuncs(object):
+class TestUfuncs:
     def setup(self):
         self.d = (array([1.0, 0, -1, pi / 2] * 2, mask=[0, 1] + [0] * 6),
                   array([1.0, 0, -1, pi / 2] * 2, mask=[1, 0] + [0] * 6),)
@@ -765,7 +763,7 @@ class TestUfuncs(object):
             assert_(eq(nonzero(x), [0]))
 
 
-class TestArrayMethods(object):
+class TestArrayMethods:
 
     def setup(self):
         x = np.array([8.375, 7.545, 8.828, 8.5, 1.757, 5.928,
index b83873a5a181422eec9d59c9a3f1f250041a1713..7e76eb05491b2fa41c68a6b2d96a82171e641f69 100644 (file)
@@ -1,12 +1,10 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.testing import (
     assert_, assert_array_equal, assert_allclose, suppress_warnings
     )
 
 
-class TestRegression(object):
+class TestRegression:
     def test_masked_array_create(self):
         # Ticket #17
         x = np.ma.masked_array([0, 1, 2, 3, 0, 4, 5, 6],
@@ -88,6 +86,6 @@ class TestRegression(object):
         ma = np.ma.MaskedArray([(1, 1.), (2, 2.), (3, 3.)], dtype='i4,f4')
         assert_array_equal(ma[[]], ma[:0])
 
-    def test_masked_array_tostring_fortran(self):
+    def test_masked_array_tobytes_fortran(self):
         ma = np.ma.arange(4).reshape((2,2))
-        assert_array_equal(ma.tostring(order='F'), ma.T.tostring())
+        assert_array_equal(ma.tobytes(order='F'), ma.T.tobytes())
index 440b367224a52bde992b2d790867deb477b450cf..caa746740534e3d4d0bff0eef4adafc53aa4e2f8 100644 (file)
@@ -6,8 +6,6 @@
 :version: $Id: test_subclassing.py 3473 2007-10-29 15:18:13Z jarrod.millman $
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.testing import assert_, assert_raises
 from numpy.ma.testutils import assert_equal
@@ -80,7 +78,7 @@ msubarray = MSubArray
 # and overrides __array_wrap__, updating the info dict, to check that this
 # doesn't get destroyed by MaskedArray._update_from.  But this one also needs
 # its own iterator...
-class CSAIterator(object):
+class CSAIterator:
     """
     Flat iterator object that uses its own setter/getter
     (works around ndarray.flat not propagating subclass setters/getters
@@ -107,8 +105,6 @@ class CSAIterator(object):
     def __next__(self):
         return next(self._dataiter).__array__().view(type(self._original))
 
-    next = __next__
-
 
 class ComplicatedSubArray(SubArray):
 
@@ -154,7 +150,7 @@ class ComplicatedSubArray(SubArray):
         return obj
 
 
-class TestSubclassing(object):
+class TestSubclassing:
     # Test suite for masked subclasses of ndarray.
 
     def setup(self):
index c0deaa9f48841edb5f9f13c1d3a43d3dc9695667..51ab03948ebc5399332478fcc92b8e75f8803206 100644 (file)
@@ -5,8 +5,6 @@
 :version: $Id: testutils.py 3529 2007-11-13 08:01:14Z jarrod.millman $
 
 """
-from __future__ import division, absolute_import, print_function
-
 import operator
 
 import numpy as np
index 4ad635e38edcee7d906a4fef4fe2ee4080ac13f6..83bd7852ef5f80a70adac50f1e3f35e2e042e908 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import timeit
 from functools import reduce
 
@@ -15,7 +13,7 @@ np.seterr(all='ignore')
 pi = np.pi
 
 
-class ModuleTester(object):
+class ModuleTester:
     def __init__(self, module):
         self.module = module
         self.allequal = module.allequal
index b1b15558645f2bccb4f2d2a4595387373a864727..bd6b632891fce38b03d51dd26eef08e063e9a995 100644 (file)
@@ -1,9 +1,20 @@
-from __future__ import division, absolute_import, print_function
+import warnings
+
+# 2018-05-29, PendingDeprecationWarning added to matrix.__new__
+# 2020-01-23, numpy 1.19.0 PendingDeprecatonWarning
+warnings.warn("Importing from numpy.matlib is deprecated since 1.19.0. "
+              "The matrix subclass is not the recommended way to represent "
+              "matrices or deal with linear algebra (see "
+              "https://docs.scipy.org/doc/numpy/user/numpy-for-matlab-users.html). "
+              "Please adjust your code to use regular ndarray. ",
+              PendingDeprecationWarning, stacklevel=2)
 
 import numpy as np
 from numpy.matrixlib.defmatrix import matrix, asmatrix
-# need * as we're copying the numpy namespace (FIXME: this makes little sense)
-from numpy import *
+# Matlib.py contains all functions in the numpy namespace with a few
+# replacements. See doc/source/reference/routines.matlib.rst for details.
+# Need * as we're copying the numpy namespace.
+from numpy import *  # noqa: F403
 
 __version__ = np.__version__
 
index 777e0cd33909c718f288c56c2c375b19793b083a..54154d11f750f8dbc6f0cac06d870ce310303a02 100644 (file)
@@ -1,8 +1,6 @@
 """Sub-package containing the matrix class and related functions.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from .defmatrix import *
 
 __all__ = defmatrix.__all__
index cabd41367e83a4f5e97a0912ff954535579b07b4..a13ff23f43aafb7644d6fca4d241c28ecb0b79be 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 __all__ = ['matrix', 'bmat', 'mat', 'asmatrix']
 
 import sys
@@ -804,7 +802,7 @@ class matrix(N.ndarray):
         -------
         ret : matrix object
             If `self` is non-singular, `ret` is such that ``ret * self`` ==
-            ``self * ret`` == ``np.matrix(np.eye(self[0,:].size)`` all return
+            ``self * ret`` == ``np.matrix(np.eye(self[0,:].size))`` all return
             ``True``.
 
         Raises
@@ -1026,8 +1024,8 @@ def _from_string(str, gdict, ldict):
             except KeyError:
                 try:
                     thismat = gdict[col]
-                except KeyError:
-                    raise KeyError("%s not found" % (col,))
+                except KeyError as e:
+                    raise NameError(f"name {col!r} is not defined") from None
 
             coltup.append(thismat)
         rowtup.append(concatenate(coltup, axis=-1))
index d0981d6584b72aeea1a43ec9eb5336c198c3acfd..19b3bb2de7c6e69f40b437f06ada16c0d9632832 100644 (file)
@@ -1,10 +1,8 @@
-#!/usr/bin/env python
-from __future__ import division, print_function
-
+#!/usr/bin/env python3
 def configuration(parent_package='', top_path=None):
     from numpy.distutils.misc_util import Configuration
     config = Configuration('matrixlib', parent_package, top_path)
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
     return config
 
 if __name__ == "__main__":
index aa6e08d64de29a0a2e3657751d59bd22d405c4af..4cb5f3a375e933fbc63b3aaab12527e60423de0c 100644 (file)
@@ -1,11 +1,4 @@
-from __future__ import division, absolute_import, print_function
-
-try:
-    # Accessing collections abstract classes from collections
-    # has been deprecated since Python 3.3
-    import collections.abc as collections_abc
-except ImportError:
-    import collections as collections_abc
+import collections.abc
 
 import numpy as np
 from numpy import matrix, asmatrix, bmat
@@ -16,7 +9,7 @@ from numpy.testing import (
 from numpy.linalg import matrix_power
 from numpy.matrixlib import mat
 
-class TestCtor(object):
+class TestCtor:
     def test_basic(self):
         A = np.array([[1, 2], [3, 4]])
         mA = matrix(A)
@@ -63,7 +56,7 @@ class TestCtor(object):
         assert_(np.all(b2 == mixresult))
 
 
-class TestProperties(object):
+class TestProperties:
     def test_sum(self):
         """Test whether matrix.sum(axis=1) preserves orientation.
         Fails in NumPy <= 0.9.6.2127.
@@ -196,7 +189,7 @@ class TestProperties(object):
         B = matrix([[True], [True], [False]])
         assert_array_equal(A, B)
 
-class TestCasting(object):
+class TestCasting:
     def test_basic(self):
         A = np.arange(100).reshape(10, 10)
         mA = matrix(A)
@@ -215,7 +208,7 @@ class TestCasting(object):
         assert_(np.all(mA != mB))
 
 
-class TestAlgebra(object):
+class TestAlgebra:
     def test_basic(self):
         import numpy.linalg as linalg
 
@@ -274,7 +267,7 @@ class TestAlgebra(object):
             A*object()
 
 
-class TestMatrixReturn(object):
+class TestMatrixReturn:
     def test_instance_methods(self):
         a = matrix([1.0], dtype='f8')
         methodargs = {
@@ -299,7 +292,7 @@ class TestMatrixReturn(object):
             if attrib.startswith('_') or attrib in excluded_methods:
                 continue
             f = getattr(a, attrib)
-            if isinstance(f, collections_abc.Callable):
+            if isinstance(f, collections.abc.Callable):
                 # reset contents of a
                 a.astype('f8')
                 a.fill(1.0)
@@ -316,7 +309,7 @@ class TestMatrixReturn(object):
         assert_(type(d) is np.ndarray)
 
 
-class TestIndexing(object):
+class TestIndexing:
     def test_basic(self):
         x = asmatrix(np.zeros((3, 2), float))
         y = np.zeros((3, 1), float)
@@ -325,7 +318,7 @@ class TestIndexing(object):
         assert_equal(x, [[0, 1], [0, 0], [0, 0]])
 
 
-class TestNewScalarIndexing(object):
+class TestNewScalarIndexing:
     a = matrix([[1, 2], [3, 4]])
 
     def test_dimesions(self):
@@ -392,7 +385,7 @@ class TestNewScalarIndexing(object):
         assert_array_equal(x[[2, 1, 0],:], x[::-1,:])
 
 
-class TestPower(object):
+class TestPower:
     def test_returntype(self):
         a = np.array([[0, 1], [0, 0]])
         assert_(type(matrix_power(a, 2)) is np.ndarray)
@@ -403,7 +396,7 @@ class TestPower(object):
         assert_array_equal(matrix_power([[0, 1], [0, 0]], 2), [[0, 0], [0, 0]])
 
 
-class TestShape(object):
+class TestShape:
 
     a = np.array([[1], [2]])
     m = matrix([[1], [2]])
index 088ae3c6a661763a4eabd27ea5cdf4f2d985ba3c..5154bd621c61d7c081630c4659f74d70059e1746 100644 (file)
@@ -2,8 +2,6 @@
 
 Note that tests with MaskedArray and linalg are done in separate files.
 """
-from __future__ import division, absolute_import, print_function
-
 import pytest
 
 import textwrap
@@ -290,7 +288,7 @@ def test_kron_matrix():
     assert_equal(type(np.kron(m, a)), np.matrix)
 
 
-class TestConcatenatorMatrix(object):
+class TestConcatenatorMatrix:
     # 2018-04-29: moved here from core.tests.test_index_tricks.
     def test_matrix(self):
         a = [1, 2]
@@ -326,24 +324,17 @@ class TestConcatenatorMatrix(object):
 
 def test_array_equal_error_message_matrix():
     # 2018-04-29: moved here from testing.tests.test_utils.
-    try:
+    with pytest.raises(AssertionError) as exc_info:
         assert_equal(np.array([1, 2]), np.matrix([1, 2]))
-    except AssertionError as e:
-        msg = str(e)
-        msg2 = msg.replace("shapes (2L,), (1L, 2L)", "shapes (2,), (1, 2)")
-        msg_reference = textwrap.dedent("""\
-
-        Arrays are not equal
-
-        (shapes (2,), (1, 2) mismatch)
-         x: array([1, 2])
-         y: matrix([[1, 2]])""")
-        try:
-            assert_equal(msg, msg_reference)
-        except AssertionError:
-            assert_equal(msg2, msg_reference)
-    else:
-        raise AssertionError("Did not raise")
+    msg = str(exc_info.value)
+    msg_reference = textwrap.dedent("""\
+
+    Arrays are not equal
+
+    (shapes (2,), (1, 2) mismatch)
+     x: array([1, 2])
+     y: matrix([[1, 2]])""")
+    assert_equal(msg, msg_reference)
 
 
 def test_array_almost_equal_matrix():
index d3911d2e105360cd0dfba31a3a32f9343c95bc69..45424ecf06105ae0ff5052d9976b27fbce67eefd 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.ma.testutils import (assert_, assert_equal, assert_raises,
                                 assert_array_equal)
@@ -29,7 +27,7 @@ class MMatrix(MaskedArray, np.matrix,):
         return _view
 
 
-class TestMaskedMatrix(object):
+class TestMaskedMatrix:
     def test_matrix_indexing(self):
         # Tests conversions and indexing
         x1 = np.matrix([[1, 2, 3], [4, 3, 2]])
@@ -171,7 +169,7 @@ class TestMaskedMatrix(object):
         assert_(not isinstance(test, MaskedArray))
 
 
-class TestSubclassing(object):
+class TestSubclassing:
     # Test suite for masked subclasses of ndarray.
 
     def setup(self):
@@ -212,7 +210,7 @@ class TestSubclassing(object):
         assert_(isinstance(divide(mx, x), MMatrix))
         assert_equal(divide(mx, mx), divide(xmx, xmx))
 
-class TestConcatenator(object):
+class TestConcatenator:
     # Tests for mr_, the equivalent of r_ for masked arrays.
 
     def test_matrix_builder(self):
index 6fc733c2e91c2de47a9db4752f861be5de91603e..106c2e38217a633829329a94df077c097fbcbf7a 100644 (file)
@@ -1,6 +1,4 @@
 """ Test functions for linalg module using the matrix class."""
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 
 from numpy.linalg.tests.test_linalg import (
index 6d84bd4777a5b62af54b4611f861d4cee7fdccea..638d0d1534deba060140ffda3b61950a0b4f815d 100644 (file)
@@ -1,9 +1,7 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.testing import assert_, assert_equal, assert_array_equal
 
-class TestView(object):
+class TestView:
     def test_type(self):
         x = np.array([1, 2, 3])
         assert_(isinstance(x.view(np.matrix), np.matrix))
index 95e1c800177daafd271c486dcd0446c7ef7cb51f..a772bb388847404a0497efa3a6b4fd241c5ec8a8 100644 (file)
@@ -1,9 +1,7 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.testing import assert_equal
 
-class TestDot(object):
+class TestDot:
     def test_matscalar(self):
         b1 = np.matrix(np.ones((3, 3), dtype=complex))
         assert_equal(b1*1.0, b1)
index 70e1472793fa1f342bc1002f3d6e19c8bd014e11..a54d44020a70ebf7832443458a6c3483513243ab 100644 (file)
@@ -1,10 +1,8 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 from numpy.testing import assert_, assert_equal, assert_raises
 
 
-class TestRegression(object):
+class TestRegression:
     def test_kron_matrix(self):
         # Ticket #71
         x = np.matrix('[1 0; 1 0]')
index 85cee9ce6bf4cfcf337ba76d48a436493f72b606..4ff2df57ea05b0615379d2ba4b684f6daf6c5ab1 100644 (file)
@@ -13,8 +13,6 @@ implemented as operations on the coefficients.  Additional (module-specific)
 information can be found in the docstring for the module of interest.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from .polynomial import Polynomial
 from .chebyshev import Chebyshev
 from .legendre import Legendre
index bfa030714613e4dd447b1e97d757f86748713ff5..53efbb90f2bca50b41be4582012a807779e941c5 100644 (file)
@@ -6,8 +6,6 @@ for the various polynomial classes. It operates as a mixin, but uses the
 abc module from the stdlib, hence it is only available for Python >= 2.6.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import abc
 import numbers
 
@@ -279,18 +277,16 @@ class ABCPolyBase(abc.ABC):
             self.window = window
 
     def __repr__(self):
-        format = "%s(%s, domain=%s, window=%s)"
         coef = repr(self.coef)[6:-1]
         domain = repr(self.domain)[6:-1]
         window = repr(self.window)[6:-1]
         name = self.__class__.__name__
-        return format % (name, coef, domain, window)
+        return f"{name}({coef}, domain={domain}, window={window})"
 
     def __str__(self):
-        format = "%s(%s)"
         coef = str(self.coef)
         name = self.nickname
-        return format % (name, coef)
+        return f"{name}({coef})"
 
     @classmethod
     def _repr_latex_term(cls, i, arg_str, needs_parens):
@@ -299,9 +295,7 @@ class ABCPolyBase(abc.ABC):
                 "Subclasses must define either a basis name, or override "
                 "_repr_latex_term(i, arg_str, needs_parens)")
         # since we always add parens, we don't care if the expression needs them
-        return "{{{basis}}}_{{{i}}}({arg_str})".format(
-            basis=cls.basis_name, i=i, arg_str=arg_str
-        )
+        return f"{{{cls.basis_name}}}_{{{i}}}({arg_str})"
 
     @staticmethod
     def _repr_latex_scalar(x):
@@ -316,19 +310,15 @@ class ABCPolyBase(abc.ABC):
             term = 'x'
             needs_parens = False
         elif scale == 1:
-            term = '{} + x'.format(
-                self._repr_latex_scalar(off)
-            )
+            term = f"{self._repr_latex_scalar(off)} + x"
             needs_parens = True
         elif off == 0:
-            term = '{}x'.format(
-                self._repr_latex_scalar(scale)
-            )
+            term = f"{self._repr_latex_scalar(scale)}x"
             needs_parens = True
         else:
-            term = '{} + {}x'.format(
-                self._repr_latex_scalar(off),
-                self._repr_latex_scalar(scale)
+            term = (
+                f"{self._repr_latex_scalar(off)} + "
+                f"{self._repr_latex_scalar(scale)}x"
             )
             needs_parens = True
 
@@ -338,20 +328,20 @@ class ABCPolyBase(abc.ABC):
         for i, c in enumerate(self.coef):
             # prevent duplication of + and - signs
             if i == 0:
-                coef_str = '{}'.format(self._repr_latex_scalar(c))
+                coef_str = f"{self._repr_latex_scalar(c)}"
             elif not isinstance(c, numbers.Real):
-                coef_str = ' + ({})'.format(self._repr_latex_scalar(c))
+                coef_str = f" + ({self._repr_latex_scalar(c)})"
             elif not np.signbit(c):
-                coef_str = ' + {}'.format(self._repr_latex_scalar(c))
+                coef_str = f" + {self._repr_latex_scalar(c)}"
             else:
-                coef_str = ' - {}'.format(self._repr_latex_scalar(-c))
+                coef_str = f" - {self._repr_latex_scalar(-c)}"
 
             # produce the string for the term
             term_str = self._repr_latex_term(i, term, needs_parens)
             if term_str == '1':
                 part = coef_str
             else:
-                part = r'{}\,{}'.format(coef_str, term_str)
+                part = rf"{coef_str}\,{term_str}"
 
             if c == 0:
                 part = mute(part)
@@ -364,7 +354,7 @@ class ABCPolyBase(abc.ABC):
             # in case somehow there are no coefficients at all
             body = '0'
 
-        return r'$x \mapsto {}$'.format(body)
+        return rf"$x \mapsto {body}$"
 
 
 
@@ -425,17 +415,15 @@ class ABCPolyBase(abc.ABC):
             return NotImplemented
         return self.__class__(coef, self.domain, self.window)
 
-    def __div__(self, other):
-        # this can be removed when python 2 support is dropped.
-        return self.__floordiv__(other)
-
     def __truediv__(self, other):
         # there is no true divide if the rhs is not a Number, although it
         # could return the first n elements of an infinite series.
         # It is hard to see where n would come from, though.
         if not isinstance(other, numbers.Number) or isinstance(other, bool):
-            form = "unsupported types for true division: '%s', '%s'"
-            raise TypeError(form % (type(self), type(other)))
+            raise TypeError(
+                f"unsupported types for true division: "
+                f"'{type(self)}', '{type(other)}'"
+            )
         return self.__floordiv__(other)
 
     def __floordiv__(self, other):
index 0cd9c4d23edd8578a10f6d55e8ef46289ed03e0c..4ddb0c6883c4a74ace0055ad3a6b1aeded292f95 100644 (file)
@@ -1,5 +1,7 @@
 """
-Objects for dealing with Chebyshev series.
+====================================================
+Chebyshev Series (:mod:`numpy.polynomial.chebyshev`)
+====================================================
 
 This module provides a number of objects (mostly functions) useful for
 dealing with Chebyshev series, including a `Chebyshev` class that
@@ -7,57 +9,75 @@ encapsulates the usual arithmetic operations.  (General information
 on how this module represents and works with such polynomials is in the
 docstring for its "parent" sub-package, `numpy.polynomial`).
 
+Classes
+-------
+
+.. autosummary::
+   :toctree: generated/
+
+   Chebyshev
+
+
 Constants
 ---------
-- `chebdomain` -- Chebyshev series default domain, [-1,1].
-- `chebzero` -- (Coefficients of the) Chebyshev series that evaluates
-  identically to 0.
-- `chebone` -- (Coefficients of the) Chebyshev series that evaluates
-  identically to 1.
-- `chebx` -- (Coefficients of the) Chebyshev series for the identity map,
-  ``f(x) = x``.
+
+.. autosummary::
+   :toctree: generated/
+
+   chebdomain
+   chebzero
+   chebone
+   chebx
 
 Arithmetic
 ----------
-- `chebadd` -- add two Chebyshev series.
-- `chebsub` -- subtract one Chebyshev series from another.
-- `chebmulx` -- multiply a Chebyshev series in ``P_i(x)`` by ``x``.
-- `chebmul` -- multiply two Chebyshev series.
-- `chebdiv` -- divide one Chebyshev series by another.
-- `chebpow` -- raise a Chebyshev series to a positive integer power.
-- `chebval` -- evaluate a Chebyshev series at given points.
-- `chebval2d` -- evaluate a 2D Chebyshev series at given points.
-- `chebval3d` -- evaluate a 3D Chebyshev series at given points.
-- `chebgrid2d` -- evaluate a 2D Chebyshev series on a Cartesian product.
-- `chebgrid3d` -- evaluate a 3D Chebyshev series on a Cartesian product.
+
+.. autosummary::
+   :toctree: generated/
+
+   chebadd
+   chebsub
+   chebmulx
+   chebmul
+   chebdiv
+   chebpow
+   chebval
+   chebval2d
+   chebval3d
+   chebgrid2d
+   chebgrid3d
 
 Calculus
 --------
-- `chebder` -- differentiate a Chebyshev series.
-- `chebint` -- integrate a Chebyshev series.
+
+.. autosummary::
+   :toctree: generated/
+
+   chebder
+   chebint
 
 Misc Functions
 --------------
-- `chebfromroots` -- create a Chebyshev series with specified roots.
-- `chebroots` -- find the roots of a Chebyshev series.
-- `chebvander` -- Vandermonde-like matrix for Chebyshev polynomials.
-- `chebvander2d` -- Vandermonde-like matrix for 2D power series.
-- `chebvander3d` -- Vandermonde-like matrix for 3D power series.
-- `chebgauss` -- Gauss-Chebyshev quadrature, points and weights.
-- `chebweight` -- Chebyshev weight function.
-- `chebcompanion` -- symmetrized companion matrix in Chebyshev form.
-- `chebfit` -- least-squares fit returning a Chebyshev series.
-- `chebpts1` -- Chebyshev points of the first kind.
-- `chebpts2` -- Chebyshev points of the second kind.
-- `chebtrim` -- trim leading coefficients from a Chebyshev series.
-- `chebline` -- Chebyshev series representing given straight line.
-- `cheb2poly` -- convert a Chebyshev series to a polynomial.
-- `poly2cheb` -- convert a polynomial to a Chebyshev series.
-- `chebinterpolate` -- interpolate a function at the Chebyshev points.
 
-Classes
--------
-- `Chebyshev` -- A Chebyshev series class.
+.. autosummary::
+   :toctree: generated/
+
+   chebfromroots
+   chebroots
+   chebvander
+   chebvander2d
+   chebvander3d
+   chebgauss
+   chebweight
+   chebcompanion
+   chebfit
+   chebpts1
+   chebpts2
+   chebtrim
+   chebline
+   cheb2poly
+   poly2cheb
+   chebinterpolate
 
 See also
 --------
@@ -87,9 +107,6 @@ References
   (preprint: https://www.math.hmc.edu/~benjamin/papers/CombTrig.pdf, pg. 4)
 
 """
-from __future__ import division, absolute_import, print_function
-
-import warnings
 import numpy as np
 import numpy.linalg as la
 from numpy.core.multiarray import normalize_axis_index
@@ -1060,7 +1077,6 @@ def chebint(c, m=1, k=[], lbnd=0, scl=1, axis=0):
             if n > 1:
                 tmp[2] = c[1]/4
             for j in range(2, n):
-                t = c[j]/(2*j + 1)  # FIXME: t never used
                 tmp[j + 1] = c[j]/(2*(j + 1))
                 tmp[j - 1] -= c[j]/(2*(j - 1))
             tmp[0] += k[i] - chebval(lbnd, tmp)
@@ -1455,7 +1471,7 @@ def chebvander2d(x, y, deg):
     -------
     vander2d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)`.  The dtype will be the same
+        :math:`order = (deg[0]+1)*(deg[1]+1)`.  The dtype will be the same
         as the converted `x` and `y`.
 
     See Also
@@ -1509,7 +1525,7 @@ def chebvander3d(x, y, z, deg):
     -------
     vander3d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`.  The dtype will
+        :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`.  The dtype will
         be the same as the converted `x`, `y`, and `z`.
 
     See Also
index 9b1aea239763cdc9524bfeac9a1ea30ee8838cff..487d8dfdba722b58344363bdc8935910bccdffe9 100644 (file)
@@ -1,5 +1,7 @@
 """
-Objects for dealing with Hermite series.
+==============================================================
+Hermite Series, "Physicists" (:mod:`numpy.polynomial.hermite`)
+==============================================================
 
 This module provides a number of objects (mostly functions) useful for
 dealing with Hermite series, including a `Hermite` class that
@@ -7,60 +9,72 @@ encapsulates the usual arithmetic operations.  (General information
 on how this module represents and works with such polynomials is in the
 docstring for its "parent" sub-package, `numpy.polynomial`).
 
+Classes
+-------
+.. autosummary::
+   :toctree: generated/
+
+   Hermite
+
 Constants
 ---------
-- `hermdomain` -- Hermite series default domain, [-1,1].
-- `hermzero` -- Hermite series that evaluates identically to 0.
-- `hermone` -- Hermite series that evaluates identically to 1.
-- `hermx` -- Hermite series for the identity map, ``f(x) = x``.
+.. autosummary::
+   :toctree: generated/
+
+   hermdomain
+   hermzero
+   hermone
+   hermx
 
 Arithmetic
 ----------
-- `hermadd` -- add two Hermite series.
-- `hermsub` -- subtract one Hermite series from another.
-- `hermmulx` -- multiply a Hermite series in ``P_i(x)`` by ``x``.
-- `hermmul` -- multiply two Hermite series.
-- `hermdiv` -- divide one Hermite series by another.
-- `hermpow` -- raise a Hermite series to a positive integer power.
-- `hermval` -- evaluate a Hermite series at given points.
-- `hermval2d` -- evaluate a 2D Hermite series at given points.
-- `hermval3d` -- evaluate a 3D Hermite series at given points.
-- `hermgrid2d` -- evaluate a 2D Hermite series on a Cartesian product.
-- `hermgrid3d` -- evaluate a 3D Hermite series on a Cartesian product.
+.. autosummary::
+   :toctree: generated/
+
+   hermadd
+   hermsub
+   hermmulx
+   hermmul
+   hermdiv
+   hermpow
+   hermval
+   hermval2d
+   hermval3d
+   hermgrid2d
+   hermgrid3d
 
 Calculus
 --------
-- `hermder` -- differentiate a Hermite series.
-- `hermint` -- integrate a Hermite series.
+.. autosummary::
+   :toctree: generated/
+
+   hermder
+   hermint
 
 Misc Functions
 --------------
-- `hermfromroots` -- create a Hermite series with specified roots.
-- `hermroots` -- find the roots of a Hermite series.
-- `hermvander` -- Vandermonde-like matrix for Hermite polynomials.
-- `hermvander2d` -- Vandermonde-like matrix for 2D power series.
-- `hermvander3d` -- Vandermonde-like matrix for 3D power series.
-- `hermgauss` -- Gauss-Hermite quadrature, points and weights.
-- `hermweight` -- Hermite weight function.
-- `hermcompanion` -- symmetrized companion matrix in Hermite form.
-- `hermfit` -- least-squares fit returning a Hermite series.
-- `hermtrim` -- trim leading coefficients from a Hermite series.
-- `hermline` -- Hermite series of given straight line.
-- `herm2poly` -- convert a Hermite series to a polynomial.
-- `poly2herm` -- convert a polynomial to a Hermite series.
-
-Classes
--------
-- `Hermite` -- A Hermite series class.
+.. autosummary::
+   :toctree: generated/
+
+   hermfromroots
+   hermroots
+   hermvander
+   hermvander2d
+   hermvander3d
+   hermgauss
+   hermweight
+   hermcompanion
+   hermfit
+   hermtrim
+   hermline
+   herm2poly
+   poly2herm
 
 See also
 --------
 `numpy.polynomial`
 
 """
-from __future__ import division, absolute_import, print_function
-
-import warnings
 import numpy as np
 import numpy.linalg as la
 from numpy.core.multiarray import normalize_axis_index
@@ -1180,7 +1194,7 @@ def hermvander2d(x, y, deg):
     -------
     vander2d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)`.  The dtype will be the same
+        :math:`order = (deg[0]+1)*(deg[1]+1)`.  The dtype will be the same
         as the converted `x` and `y`.
 
     See Also
@@ -1234,7 +1248,7 @@ def hermvander3d(x, y, z, deg):
     -------
     vander3d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`.  The dtype will
+        :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`.  The dtype will
         be the same as the converted `x`, `y`, and `z`.
 
     See Also
@@ -1355,8 +1369,8 @@ def hermfit(x, y, deg, rcond=None, full=False, w=None):
 
     Fits using Hermite series are probably most useful when the data can be
     approximated by ``sqrt(w(x)) * p(x)``, where `w(x)` is the Hermite
-    weight. In that case the weight ``sqrt(w(x[i])`` should be used
-    together with data values ``y[i]/sqrt(w(x[i])``. The weight function is
+    weight. In that case the weight ``sqrt(w(x[i]))`` should be used
+    together with data values ``y[i]/sqrt(w(x[i]))``. The weight function is
     available as `hermweight`.
 
     References
index c5a0a05a2c8823ca0b8aec769f43062babf8c3d3..cbec15184b3b253d1499fe0ab223d792e67caee6 100644 (file)
@@ -1,5 +1,7 @@
 """
-Objects for dealing with Hermite_e series.
+===================================================================
+HermiteE Series, "Probabilists" (:mod:`numpy.polynomial.hermite_e`)
+===================================================================
 
 This module provides a number of objects (mostly functions) useful for
 dealing with Hermite_e series, including a `HermiteE` class that
@@ -7,60 +9,72 @@ encapsulates the usual arithmetic operations.  (General information
 on how this module represents and works with such polynomials is in the
 docstring for its "parent" sub-package, `numpy.polynomial`).
 
+Classes
+-------
+.. autosummary::
+   :toctree: generated/
+
+   HermiteE
+
 Constants
 ---------
-- `hermedomain` -- Hermite_e series default domain, [-1,1].
-- `hermezero` -- Hermite_e series that evaluates identically to 0.
-- `hermeone` -- Hermite_e series that evaluates identically to 1.
-- `hermex` -- Hermite_e series for the identity map, ``f(x) = x``.
+.. autosummary::
+   :toctree: generated/
+
+   hermedomain
+   hermezero
+   hermeone
+   hermex
 
 Arithmetic
 ----------
-- `hermeadd` -- add two Hermite_e series.
-- `hermesub` -- subtract one Hermite_e series from another.
-- `hermemulx` -- multiply a Hermite_e series in ``P_i(x)`` by ``x``.
-- `hermemul` -- multiply two Hermite_e series.
-- `hermediv` -- divide one Hermite_e series by another.
-- `hermepow` -- raise a Hermite_e series to a positive integer power.
-- `hermeval` -- evaluate a Hermite_e series at given points.
-- `hermeval2d` -- evaluate a 2D Hermite_e series at given points.
-- `hermeval3d` -- evaluate a 3D Hermite_e series at given points.
-- `hermegrid2d` -- evaluate a 2D Hermite_e series on a Cartesian product.
-- `hermegrid3d` -- evaluate a 3D Hermite_e series on a Cartesian product.
+.. autosummary::
+   :toctree: generated/
+
+   hermeadd
+   hermesub
+   hermemulx
+   hermemul
+   hermediv
+   hermepow
+   hermeval
+   hermeval2d
+   hermeval3d
+   hermegrid2d
+   hermegrid3d
 
 Calculus
 --------
-- `hermeder` -- differentiate a Hermite_e series.
-- `hermeint` -- integrate a Hermite_e series.
+.. autosummary::
+   :toctree: generated/
+
+   hermeder
+   hermeint
 
 Misc Functions
 --------------
-- `hermefromroots` -- create a Hermite_e series with specified roots.
-- `hermeroots` -- find the roots of a Hermite_e series.
-- `hermevander` -- Vandermonde-like matrix for Hermite_e polynomials.
-- `hermevander2d` -- Vandermonde-like matrix for 2D power series.
-- `hermevander3d` -- Vandermonde-like matrix for 3D power series.
-- `hermegauss` -- Gauss-Hermite_e quadrature, points and weights.
-- `hermeweight` -- Hermite_e weight function.
-- `hermecompanion` -- symmetrized companion matrix in Hermite_e form.
-- `hermefit` -- least-squares fit returning a Hermite_e series.
-- `hermetrim` -- trim leading coefficients from a Hermite_e series.
-- `hermeline` -- Hermite_e series of given straight line.
-- `herme2poly` -- convert a Hermite_e series to a polynomial.
-- `poly2herme` -- convert a polynomial to a Hermite_e series.
-
-Classes
--------
-- `HermiteE` -- A Hermite_e series class.
+.. autosummary::
+   :toctree: generated/
+
+   hermefromroots
+   hermeroots
+   hermevander
+   hermevander2d
+   hermevander3d
+   hermegauss
+   hermeweight
+   hermecompanion
+   hermefit
+   hermetrim
+   hermeline
+   herme2poly
+   poly2herme
 
 See also
 --------
 `numpy.polynomial`
 
 """
-from __future__ import division, absolute_import, print_function
-
-import warnings
 import numpy as np
 import numpy.linalg as la
 from numpy.core.multiarray import normalize_axis_index
@@ -1173,7 +1187,7 @@ def hermevander2d(x, y, deg):
     -------
     vander2d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)`.  The dtype will be the same
+        :math:`order = (deg[0]+1)*(deg[1]+1)`.  The dtype will be the same
         as the converted `x` and `y`.
 
     See Also
@@ -1227,7 +1241,7 @@ def hermevander3d(x, y, z, deg):
     -------
     vander3d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`.  The dtype will
+        :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`.  The dtype will
         be the same as the converted `x`, `y`, and `z`.
 
     See Also
@@ -1348,8 +1362,8 @@ def hermefit(x, y, deg, rcond=None, full=False, w=None):
 
     Fits using HermiteE series are probably most useful when the data can
     be approximated by ``sqrt(w(x)) * p(x)``, where `w(x)` is the HermiteE
-    weight. In that case the weight ``sqrt(w(x[i])`` should be used
-    together with data values ``y[i]/sqrt(w(x[i])``. The weight function is
+    weight. In that case the weight ``sqrt(w(x[i]))`` should be used
+    together with data values ``y[i]/sqrt(w(x[i]))``. The weight function is
     available as `hermeweight`.
 
     References
index 538a1d449786f605083a4308d662be37d7738b79..5b66d943e4bdf51eece9eccd440ffdd55521753e 100644 (file)
@@ -1,5 +1,7 @@
 """
-Objects for dealing with Laguerre series.
+==================================================
+Laguerre Series (:mod:`numpy.polynomial.laguerre`)
+==================================================
 
 This module provides a number of objects (mostly functions) useful for
 dealing with Laguerre series, including a `Laguerre` class that
@@ -7,60 +9,72 @@ encapsulates the usual arithmetic operations.  (General information
 on how this module represents and works with such polynomials is in the
 docstring for its "parent" sub-package, `numpy.polynomial`).
 
+Classes
+-------
+.. autosummary::
+   :toctree: generated/
+
+   Laguerre
+
 Constants
 ---------
-- `lagdomain` -- Laguerre series default domain, [-1,1].
-- `lagzero` -- Laguerre series that evaluates identically to 0.
-- `lagone` -- Laguerre series that evaluates identically to 1.
-- `lagx` -- Laguerre series for the identity map, ``f(x) = x``.
+.. autosummary::
+   :toctree: generated/
+
+   lagdomain
+   lagzero
+   lagone
+   lagx
 
 Arithmetic
 ----------
-- `lagadd` -- add two Laguerre series.
-- `lagsub` -- subtract one Laguerre series from another.
-- `lagmulx` -- multiply a Laguerre series in ``P_i(x)`` by ``x``.
-- `lagmul` -- multiply two Laguerre series.
-- `lagdiv` -- divide one Laguerre series by another.
-- `lagpow` -- raise a Laguerre series to a positive integer power.
-- `lagval` -- evaluate a Laguerre series at given points.
-- `lagval2d` -- evaluate a 2D Laguerre series at given points.
-- `lagval3d` -- evaluate a 3D Laguerre series at given points.
-- `laggrid2d` -- evaluate a 2D Laguerre series on a Cartesian product.
-- `laggrid3d` -- evaluate a 3D Laguerre series on a Cartesian product.
+.. autosummary::
+   :toctree: generated/
+
+   lagadd
+   lagsub
+   lagmulx
+   lagmul
+   lagdiv
+   lagpow
+   lagval
+   lagval2d
+   lagval3d
+   laggrid2d
+   laggrid3d
 
 Calculus
 --------
-- `lagder` -- differentiate a Laguerre series.
-- `lagint` -- integrate a Laguerre series.
+.. autosummary::
+   :toctree: generated/
+
+   lagder
+   lagint
 
 Misc Functions
 --------------
-- `lagfromroots` -- create a Laguerre series with specified roots.
-- `lagroots` -- find the roots of a Laguerre series.
-- `lagvander` -- Vandermonde-like matrix for Laguerre polynomials.
-- `lagvander2d` -- Vandermonde-like matrix for 2D power series.
-- `lagvander3d` -- Vandermonde-like matrix for 3D power series.
-- `laggauss` -- Gauss-Laguerre quadrature, points and weights.
-- `lagweight` -- Laguerre weight function.
-- `lagcompanion` -- symmetrized companion matrix in Laguerre form.
-- `lagfit` -- least-squares fit returning a Laguerre series.
-- `lagtrim` -- trim leading coefficients from a Laguerre series.
-- `lagline` -- Laguerre series of given straight line.
-- `lag2poly` -- convert a Laguerre series to a polynomial.
-- `poly2lag` -- convert a polynomial to a Laguerre series.
-
-Classes
--------
-- `Laguerre` -- A Laguerre series class.
+.. autosummary::
+   :toctree: generated/
+
+   lagfromroots
+   lagroots
+   lagvander
+   lagvander2d
+   lagvander3d
+   laggauss
+   lagweight
+   lagcompanion
+   lagfit
+   lagtrim
+   lagline
+   lag2poly
+   poly2lag
 
 See also
 --------
 `numpy.polynomial`
 
 """
-from __future__ import division, absolute_import, print_function
-
-import warnings
 import numpy as np
 import numpy.linalg as la
 from numpy.core.multiarray import normalize_axis_index
@@ -1180,7 +1194,7 @@ def lagvander2d(x, y, deg):
     -------
     vander2d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)`.  The dtype will be the same
+        :math:`order = (deg[0]+1)*(deg[1]+1)`.  The dtype will be the same
         as the converted `x` and `y`.
 
     See Also
@@ -1234,7 +1248,7 @@ def lagvander3d(x, y, z, deg):
     -------
     vander3d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`.  The dtype will
+        :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`.  The dtype will
         be the same as the converted `x`, `y`, and `z`.
 
     See Also
@@ -1355,8 +1369,8 @@ def lagfit(x, y, deg, rcond=None, full=False, w=None):
 
     Fits using Laguerre series are probably most useful when the data can
     be approximated by ``sqrt(w(x)) * p(x)``, where `w(x)` is the Laguerre
-    weight. In that case the weight ``sqrt(w(x[i])`` should be used
-    together with data values ``y[i]/sqrt(w(x[i])``. The weight function is
+    weight. In that case the weight ``sqrt(w(x[i]))`` should be used
+    together with data values ``y[i]/sqrt(w(x[i]))``. The weight function is
     available as `lagweight`.
 
     References
index c11824761bb382c6f983e3e63fdcc2db7015c1db..47e47a7b606a70a78bc1cfd5564c0848812bc3cf 100644 (file)
@@ -1,8 +1,7 @@
 """
-Legendre Series (:mod: `numpy.polynomial.legendre`)
-===================================================
-
-.. currentmodule:: numpy.polynomial.polynomial
+==================================================
+Legendre Series (:mod:`numpy.polynomial.legendre`)
+==================================================
 
 This module provides a number of objects (mostly functions) useful for
 dealing with Legendre series, including a `Legendre` class that
@@ -10,16 +9,23 @@ encapsulates the usual arithmetic operations.  (General information
 on how this module represents and works with such polynomials is in the
 docstring for its "parent" sub-package, `numpy.polynomial`).
 
+Classes
+-------
+.. autosummary::
+   :toctree: generated/
+
+    Legendre
+
 Constants
 ---------
 
 .. autosummary::
    :toctree: generated/
 
-   legdomain            Legendre series default domain, [-1,1].
-   legzero              Legendre series that evaluates identically to 0.
-   legone               Legendre series that evaluates identically to 1.
-   legx                 Legendre series for the identity map, ``f(x) = x``.
+   legdomain
+   legzero
+   legone
+   legx
 
 Arithmetic
 ----------
@@ -27,17 +33,17 @@ Arithmetic
 .. autosummary::
    :toctree: generated/
 
-   legadd               add two Legendre series.
-   legsub               subtract one Legendre series from another.
-   legmulx              multiply a Legendre series in ``P_i(x)`` by ``x``.
-   legmul               multiply two Legendre series.
-   legdiv               divide one Legendre series by another.
-   legpow               raise a Legendre series to a positive integer power.
-   legval               evaluate a Legendre series at given points.
-   legval2d             evaluate a 2D Legendre series at given points.
-   legval3d             evaluate a 3D Legendre series at given points.
-   leggrid2d            evaluate a 2D Legendre series on a Cartesian product.
-   leggrid3d            evaluate a 3D Legendre series on a Cartesian product.
+   legadd
+   legsub
+   legmulx
+   legmul
+   legdiv
+   legpow
+   legval
+   legval2d
+   legval3d
+   leggrid2d
+   leggrid3d
 
 Calculus
 --------
@@ -45,8 +51,8 @@ Calculus
 .. autosummary::
    :toctree: generated/
 
-   legder               differentiate a Legendre series.
-   legint               integrate a Legendre series.
+   legder
+   legint
 
 Misc Functions
 --------------
@@ -54,36 +60,25 @@ Misc Functions
 .. autosummary::
    :toctree: generated/
 
-   legfromroots          create a Legendre series with specified roots.
-   legroots              find the roots of a Legendre series.
-   legvander             Vandermonde-like matrix for Legendre polynomials.
-   legvander2d           Vandermonde-like matrix for 2D power series.
-   legvander3d           Vandermonde-like matrix for 3D power series.
-   leggauss              Gauss-Legendre quadrature, points and weights.
-   legweight             Legendre weight function.
-   legcompanion          symmetrized companion matrix in Legendre form.
-   legfit                least-squares fit returning a Legendre series.
-   legtrim               trim leading coefficients from a Legendre series.
-   legline               Legendre series representing given straight line.
-   leg2poly              convert a Legendre series to a polynomial.
-   poly2leg              convert a polynomial to a Legendre series.
-
-Classes
--------
-    Legendre            A Legendre series class.
+   legfromroots
+   legroots
+   legvander
+   legvander2d
+   legvander3d
+   leggauss
+   legweight
+   legcompanion
+   legfit
+   legtrim
+   legline
+   leg2poly
+   poly2leg
 
 See also
 --------
-numpy.polynomial.polynomial
-numpy.polynomial.chebyshev
-numpy.polynomial.laguerre
-numpy.polynomial.hermite
-numpy.polynomial.hermite_e
+numpy.polynomial
 
 """
-from __future__ import division, absolute_import, print_function
-
-import warnings
 import numpy as np
 import numpy.linalg as la
 from numpy.core.multiarray import normalize_axis_index
@@ -1216,7 +1211,7 @@ def legvander2d(x, y, deg):
     -------
     vander2d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)`.  The dtype will be the same
+        :math:`order = (deg[0]+1)*(deg[1]+1)`.  The dtype will be the same
         as the converted `x` and `y`.
 
     See Also
@@ -1270,7 +1265,7 @@ def legvander3d(x, y, z, deg):
     -------
     vander3d : ndarray
         The shape of the returned matrix is ``x.shape + (order,)``, where
-        :math:`order = (deg[0]+1)*(deg([1]+1)*(deg[2]+1)`.  The dtype will
+        :math:`order = (deg[0]+1)*(deg[1]+1)*(deg[2]+1)`.  The dtype will
         be the same as the converted `x`, `y`, and `z`.
 
     See Also
index 315ea14958834128889bfc3d9918712e0a2f7025..2fb032db36c28fef8a1deafb009876182a7ecd13 100644 (file)
@@ -1,5 +1,7 @@
 """
-Objects for dealing with polynomials.
+=================================================
+Power Series (:mod:`numpy.polynomial.polynomial`)
+=================================================
 
 This module provides a number of objects (mostly functions) useful for
 dealing with polynomials, including a `Polynomial` class that
@@ -7,56 +9,69 @@ encapsulates the usual arithmetic operations.  (General information
 on how this module represents and works with polynomial objects is in
 the docstring for its "parent" sub-package, `numpy.polynomial`).
 
+Classes
+-------
+.. autosummary::
+   :toctree: generated/
+
+   Polynomial
+
 Constants
 ---------
-- `polydomain` -- Polynomial default domain, [-1,1].
-- `polyzero` -- (Coefficients of the) "zero polynomial."
-- `polyone` -- (Coefficients of the) constant polynomial 1.
-- `polyx` -- (Coefficients of the) identity map polynomial, ``f(x) = x``.
+.. autosummary::
+   :toctree: generated/
+
+   polydomain
+   polyzero
+   polyone
+   polyx
 
 Arithmetic
 ----------
-- `polyadd` -- add two polynomials.
-- `polysub` -- subtract one polynomial from another.
-- `polymulx` -- multiply a polynomial in ``P_i(x)`` by ``x``.
-- `polymul` -- multiply two polynomials.
-- `polydiv` -- divide one polynomial by another.
-- `polypow` -- raise a polynomial to a positive integer power.
-- `polyval` -- evaluate a polynomial at given points.
-- `polyval2d` -- evaluate a 2D polynomial at given points.
-- `polyval3d` -- evaluate a 3D polynomial at given points.
-- `polygrid2d` -- evaluate a 2D polynomial on a Cartesian product.
-- `polygrid3d` -- evaluate a 3D polynomial on a Cartesian product.
+.. autosummary::
+   :toctree: generated/
+
+   polyadd
+   polysub
+   polymulx
+   polymul
+   polydiv
+   polypow
+   polyval
+   polyval2d
+   polyval3d
+   polygrid2d
+   polygrid3d
 
 Calculus
 --------
-- `polyder` -- differentiate a polynomial.
-- `polyint` -- integrate a polynomial.
+.. autosummary::
+   :toctree: generated/
+
+   polyder
+   polyint
 
 Misc Functions
 --------------
-- `polyfromroots` -- create a polynomial with specified roots.
-- `polyroots` -- find the roots of a polynomial.
-- `polyvalfromroots` -- evaluate a polynomial at given points from roots.
-- `polyvander` -- Vandermonde-like matrix for powers.
-- `polyvander2d` -- Vandermonde-like matrix for 2D power series.
-- `polyvander3d` -- Vandermonde-like matrix for 3D power series.
-- `polycompanion` -- companion matrix in power series form.
-- `polyfit` -- least-squares fit returning a polynomial.
-- `polytrim` -- trim leading coefficients from a polynomial.
-- `polyline` -- polynomial representing given straight line.
-
-Classes
--------
-- `Polynomial` -- polynomial class.
+.. autosummary::
+   :toctree: generated/
+
+   polyfromroots
+   polyroots
+   polyvalfromroots
+   polyvander
+   polyvander2d
+   polyvander3d
+   polycompanion
+   polyfit
+   polytrim
+   polyline
 
 See Also
 --------
 `numpy.polynomial`
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = [
     'polyzero', 'polyone', 'polyx', 'polydomain', 'polyline', 'polyadd',
     'polysub', 'polymulx', 'polymul', 'polydiv', 'polypow', 'polyval',
@@ -64,7 +79,6 @@ __all__ = [
     'polyfit', 'polytrim', 'polyroots', 'Polynomial', 'polyval2d', 'polyval3d',
     'polygrid2d', 'polygrid3d', 'polyvander2d', 'polyvander3d']
 
-import warnings
 import numpy as np
 import numpy.linalg as la
 from numpy.core.multiarray import normalize_axis_index
@@ -1484,10 +1498,10 @@ class Polynomial(ABCPolyBase):
     @staticmethod
     def _repr_latex_term(i, arg_str, needs_parens):
         if needs_parens:
-            arg_str = r'\left({}\right)'.format(arg_str)
+            arg_str = rf"\left({arg_str}\right)"
         if i == 0:
             return '1'
         elif i == 1:
             return arg_str
         else:
-            return '{}^{{{}}}'.format(arg_str, i)
+            return f"{arg_str}^{{{i}}}"
index 5dcfa7a7a2ffed013a927abb0737d30e8c210556..b1cf07e8a27b634f83ed8cc0aefc80b2f07b7f28 100644 (file)
@@ -43,8 +43,6 @@ Functions
    mapparms     parameters of the linear map between domains.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import operator
 import functools
 import warnings
@@ -80,7 +78,7 @@ class PolyDomainError(PolyError):
 # Base class for all polynomial types
 #
 
-class PolyBase(object):
+class PolyBase:
     """
     Base class for all polynomial types.
 
@@ -195,8 +193,8 @@ def as_series(alist, trim=True):
     else:
         try:
             dtype = np.common_type(*arrays)
-        except Exception:
-            raise ValueError("Coefficient arrays have no common type")
+        except Exception as e:
+            raise ValueError("Coefficient arrays have no common type") from e
         ret = [np.array(a, copy=True, dtype=dtype) for a in arrays]
     return ret
 
@@ -470,10 +468,10 @@ def _vander_nd(vander_fs, points, degrees):
     n_dims = len(vander_fs)
     if n_dims != len(points):
         raise ValueError(
-            "Expected {} dimensions of sample points, got {}".format(n_dims, len(points)))
+            f"Expected {n_dims} dimensions of sample points, got {len(points)}")
     if n_dims != len(degrees):
         raise ValueError(
-            "Expected {} dimensions of degrees, got {}".format(n_dims, len(degrees)))
+            f"Expected {n_dims} dimensions of degrees, got {len(degrees)}")
     if n_dims == 0:
         raise ValueError("Unable to guess a dtype or shape when no points are given")
 
@@ -542,17 +540,15 @@ def _valnd(val_f, c, *args):
     c, args :
         See the ``<type>val<n>d`` functions for more detail
     """
-    try:
-        args = tuple(np.array(args, copy=False))
-    except Exception:
-        # preserve the old error message
-        if len(args) == 2:
+    args = [np.asanyarray(a) for a in args]
+    shape0 = args[0].shape
+    if not all((a.shape == shape0 for a in args[1:])):
+        if len(args) == 3:
             raise ValueError('x, y, z are incompatible')
-        elif len(args) == 3:
+        elif len(args) == 2:
             raise ValueError('x, y are incompatible')
         else:
             raise ValueError('ordinates are incompatible')
-
     it = iter(args)
     x0 = next(it)
 
@@ -781,7 +777,7 @@ def _deprecate_as_int(x, desc):
     """
     try:
         return operator.index(x)
-    except TypeError:
+    except TypeError as e:
         # Numpy 1.17.0, 2019-03-11
         try:
             ix = int(x)
@@ -790,12 +786,11 @@ def _deprecate_as_int(x, desc):
         else:
             if ix == x:
                 warnings.warn(
-                    "In future, this will raise TypeError, as {} will need to "
-                    "be an integer not just an integral float."
-                    .format(desc),
+                    f"In future, this will raise TypeError, as {desc} will "
+                    "need to be an integer not just an integral float.",
                     DeprecationWarning,
                     stacklevel=3
                 )
                 return ix
 
-        raise TypeError("{} must be an integer".format(desc))
+        raise TypeError(f"{desc} must be an integer") from e
index cb59ee1e56d9c5d58f09c598c8006bcbdffd8f2d..6414645186fac3ded9dbf089bc43cf102c5dd708 100644 (file)
@@ -1,9 +1,7 @@
-from __future__ import division, print_function
-
 def configuration(parent_package='',top_path=None):
     from numpy.distutils.misc_util import Configuration
     config = Configuration('polynomial', parent_package, top_path)
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
     return config
 
 if __name__ == '__main__':
index c8d2d6dbaae0aef8ddd330d4a5ccbd520f30c891..2f54bebfdb27d54f436378e4ab6d6c8f2426dd90 100644 (file)
@@ -1,8 +1,6 @@
 """Tests for chebyshev module.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from functools import reduce
 
 import numpy as np
@@ -30,7 +28,7 @@ T9 = [0, 9, 0, -120, 0, 432, 0, -576, 0, 256]
 Tlist = [T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]
 
 
-class TestPrivate(object):
+class TestPrivate:
 
     def test__cseries_to_zseries(self):
         for i in range(5):
@@ -47,7 +45,7 @@ class TestPrivate(object):
             assert_equal(res, tgt)
 
 
-class TestConstants(object):
+class TestConstants:
 
     def test_chebdomain(self):
         assert_equal(cheb.chebdomain, [-1, 1])
@@ -62,12 +60,12 @@ class TestConstants(object):
         assert_equal(cheb.chebx, [0, 1])
 
 
-class TestArithmetic(object):
+class TestArithmetic:
 
     def test_chebadd(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] += 1
@@ -77,7 +75,7 @@ class TestArithmetic(object):
     def test_chebsub(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] -= 1
@@ -95,7 +93,7 @@ class TestArithmetic(object):
     def test_chebmul(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(i + j + 1)
                 tgt[i + j] += .5
                 tgt[abs(i - j)] += .5
@@ -105,7 +103,7 @@ class TestArithmetic(object):
     def test_chebdiv(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 ci = [0]*i + [1]
                 cj = [0]*j + [1]
                 tgt = cheb.chebadd(ci, cj)
@@ -116,14 +114,14 @@ class TestArithmetic(object):
     def test_chebpow(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 c = np.arange(i + 1)
                 tgt = reduce(cheb.chebmul, [c]*j, np.array([1]))
                 res = cheb.chebpow(c, j)
                 assert_equal(trim(res), trim(tgt), err_msg=msg)
 
 
-class TestEvaluation(object):
+class TestEvaluation:
     # coefficients of 1 + 2*x + 3*x**2
     c1d = np.array([2.5, 2., 1.5])
     c2d = np.einsum('i,j->ij', c1d, c1d)
@@ -141,7 +139,7 @@ class TestEvaluation(object):
         x = np.linspace(-1, 1)
         y = [polyval(x, c) for c in Tlist]
         for i in range(10):
-            msg = "At i=%d" % i
+            msg = f"At i={i}"
             tgt = y[i]
             res = cheb.chebval(x, [0]*i + [1])
             assert_almost_equal(res, tgt, err_msg=msg)
@@ -217,7 +215,7 @@ class TestEvaluation(object):
         assert_(res.shape == (2, 3)*3)
 
 
-class TestIntegral(object):
+class TestIntegral:
 
     def test_chebint(self):
         # check exceptions
@@ -319,7 +317,7 @@ class TestIntegral(object):
         assert_almost_equal(res, tgt)
 
 
-class TestDerivative(object):
+class TestDerivative:
 
     def test_chebder(self):
         # check exceptions
@@ -359,7 +357,7 @@ class TestDerivative(object):
         assert_almost_equal(res, tgt)
 
 
-class TestVander(object):
+class TestVander:
     # some random values in [-1, 1)
     x = np.random.random((3, 5))*2 - 1
 
@@ -407,7 +405,7 @@ class TestVander(object):
         assert_(van.shape == (1, 5, 24))
 
 
-class TestFitting(object):
+class TestFitting:
 
     def test_chebfit(self):
         def f(x):
@@ -484,7 +482,7 @@ class TestFitting(object):
         assert_almost_equal(coef1, coef2)
 
 
-class TestInterpolate(object):
+class TestInterpolate:
 
     def f(self, x):
         return x * (x - 1) * (x - 2)
@@ -509,7 +507,7 @@ class TestInterpolate(object):
                 assert_almost_equal(cheb.chebval(x, c), powx(x, p), decimal=12)
 
 
-class TestCompanion(object):
+class TestCompanion:
 
     def test_raises(self):
         assert_raises(ValueError, cheb.chebcompanion, [])
@@ -524,7 +522,7 @@ class TestCompanion(object):
         assert_(cheb.chebcompanion([1, 2])[0, 0] == -.5)
 
 
-class TestGauss(object):
+class TestGauss:
 
     def test_100(self):
         x, w = cheb.chebgauss(100)
@@ -543,7 +541,7 @@ class TestGauss(object):
         assert_almost_equal(w.sum(), tgt)
 
 
-class TestMisc(object):
+class TestMisc:
 
     def test_chebfromroots(self):
         res = cheb.chebfromroots([])
index 2261f960b1d7fa4b53652726856196ca26e11770..8e71a19459bca2074c7e60af33aef6561aad6929 100644 (file)
@@ -3,8 +3,6 @@
 This tests the convert and cast methods of all the polynomial classes.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import operator as op
 from numbers import Number
 
@@ -15,7 +13,6 @@ from numpy.polynomial import (
 from numpy.testing import (
     assert_almost_equal, assert_raises, assert_equal, assert_,
     )
-from numpy.compat import long
 from numpy.polynomial.polyutils import RankWarning
 
 #
@@ -44,7 +41,7 @@ def assert_poly_almost_equal(p1, p2, msg=""):
         assert_(np.all(p1.window == p2.window))
         assert_almost_equal(p1.coef, p2.coef)
     except AssertionError:
-        msg = "Result: %s\nTarget: %s", (p1, p2)
+        msg = f"Result: {p1}\nTarget: {p2}"
         raise AssertionError(msg)
 
 
@@ -317,7 +314,7 @@ def test_truediv(Poly):
         s = stype(5)
         assert_poly_almost_equal(op.truediv(p2, s), p1)
         assert_raises(TypeError, op.truediv, s, p2)
-    for stype in (int, long, float):
+    for stype in (int, float):
         s = stype(5)
         assert_poly_almost_equal(op.truediv(p2, s), p1)
         assert_raises(TypeError, op.truediv, s, p2)
@@ -573,62 +570,12 @@ def test_ufunc_override(Poly):
     assert_raises(TypeError, np.add, x, p)
 
 
-
-class TestLatexRepr(object):
-    """Test the latex repr used by ipython """
-
-    def as_latex(self, obj):
-        # right now we ignore the formatting of scalars in our tests, since
-        # it makes them too verbose. Ideally, the formatting of scalars will
-        # be fixed such that tests below continue to pass
-        obj._repr_latex_scalar = lambda x: str(x)
-        try:
-            return obj._repr_latex_()
-        finally:
-            del obj._repr_latex_scalar
-
-    def test_simple_polynomial(self):
-        # default input
-        p = Polynomial([1, 2, 3])
-        assert_equal(self.as_latex(p),
-            r'$x \mapsto 1.0 + 2.0\,x + 3.0\,x^{2}$')
-
-        # translated input
-        p = Polynomial([1, 2, 3], domain=[-2, 0])
-        assert_equal(self.as_latex(p),
-            r'$x \mapsto 1.0 + 2.0\,\left(1.0 + x\right) + 3.0\,\left(1.0 + x\right)^{2}$')
-
-        # scaled input
-        p = Polynomial([1, 2, 3], domain=[-0.5, 0.5])
-        assert_equal(self.as_latex(p),
-            r'$x \mapsto 1.0 + 2.0\,\left(2.0x\right) + 3.0\,\left(2.0x\right)^{2}$')
-
-        # affine input
-        p = Polynomial([1, 2, 3], domain=[-1, 0])
-        assert_equal(self.as_latex(p),
-            r'$x \mapsto 1.0 + 2.0\,\left(1.0 + 2.0x\right) + 3.0\,\left(1.0 + 2.0x\right)^{2}$')
-
-    def test_basis_func(self):
-        p = Chebyshev([1, 2, 3])
-        assert_equal(self.as_latex(p),
-            r'$x \mapsto 1.0\,{T}_{0}(x) + 2.0\,{T}_{1}(x) + 3.0\,{T}_{2}(x)$')
-        # affine input - check no surplus parens are added
-        p = Chebyshev([1, 2, 3], domain=[-1, 0])
-        assert_equal(self.as_latex(p),
-            r'$x \mapsto 1.0\,{T}_{0}(1.0 + 2.0x) + 2.0\,{T}_{1}(1.0 + 2.0x) + 3.0\,{T}_{2}(1.0 + 2.0x)$')
-
-    def test_multichar_basis_func(self):
-        p = HermiteE([1, 2, 3])
-        assert_equal(self.as_latex(p),
-            r'$x \mapsto 1.0\,{He}_{0}(x) + 2.0\,{He}_{1}(x) + 3.0\,{He}_{2}(x)$')
-
-
 #
 # Test class method that only exists for some classes
 #
 
 
-class TestInterpolate(object):
+class TestInterpolate:
 
     def f(self, x):
         return x * (x - 1) * (x - 2)
index 271c1964b0931ddec20cde3a46eb947be39cd317..53ee0844e3c58456807bfd7828bdb9cf58f8ed76 100644 (file)
@@ -1,8 +1,6 @@
 """Tests for hermite module.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from functools import reduce
 
 import numpy as np
@@ -30,7 +28,7 @@ def trim(x):
     return herm.hermtrim(x, tol=1e-6)
 
 
-class TestConstants(object):
+class TestConstants:
 
     def test_hermdomain(self):
         assert_equal(herm.hermdomain, [-1, 1])
@@ -45,13 +43,13 @@ class TestConstants(object):
         assert_equal(herm.hermx, [0, .5])
 
 
-class TestArithmetic(object):
+class TestArithmetic:
     x = np.linspace(-3, 3, 100)
 
     def test_hermadd(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] += 1
@@ -61,7 +59,7 @@ class TestArithmetic(object):
     def test_hermsub(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] -= 1
@@ -82,7 +80,7 @@ class TestArithmetic(object):
             pol1 = [0]*i + [1]
             val1 = herm.hermval(self.x, pol1)
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 pol2 = [0]*j + [1]
                 val2 = herm.hermval(self.x, pol2)
                 pol3 = herm.hermmul(pol1, pol2)
@@ -93,7 +91,7 @@ class TestArithmetic(object):
     def test_hermdiv(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 ci = [0]*i + [1]
                 cj = [0]*j + [1]
                 tgt = herm.hermadd(ci, cj)
@@ -104,14 +102,14 @@ class TestArithmetic(object):
     def test_hermpow(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 c = np.arange(i + 1)
                 tgt = reduce(herm.hermmul, [c]*j, np.array([1]))
                 res = herm.hermpow(c, j) 
                 assert_equal(trim(res), trim(tgt), err_msg=msg)
 
 
-class TestEvaluation(object):
+class TestEvaluation:
     # coefficients of 1 + 2*x + 3*x**2
     c1d = np.array([2.5, 1., .75])
     c2d = np.einsum('i,j->ij', c1d, c1d)
@@ -129,7 +127,7 @@ class TestEvaluation(object):
         x = np.linspace(-1, 1)
         y = [polyval(x, c) for c in Hlist]
         for i in range(10):
-            msg = "At i=%d" % i
+            msg = f"At i={i}"
             tgt = y[i]
             res = herm.hermval(x, [0]*i + [1])
             assert_almost_equal(res, tgt, err_msg=msg)
@@ -205,7 +203,7 @@ class TestEvaluation(object):
         assert_(res.shape == (2, 3)*3)
 
 
-class TestIntegral(object):
+class TestIntegral:
 
     def test_hermint(self):
         # check exceptions
@@ -307,7 +305,7 @@ class TestIntegral(object):
         assert_almost_equal(res, tgt)
 
 
-class TestDerivative(object):
+class TestDerivative:
 
     def test_hermder(self):
         # check exceptions
@@ -347,7 +345,7 @@ class TestDerivative(object):
         assert_almost_equal(res, tgt)
 
 
-class TestVander(object):
+class TestVander:
     # some random values in [-1, 1)
     x = np.random.random((3, 5))*2 - 1
 
@@ -395,7 +393,7 @@ class TestVander(object):
         assert_(van.shape == (1, 5, 24))
 
 
-class TestFitting(object):
+class TestFitting:
 
     def test_hermfit(self):
         def f(x):
@@ -472,7 +470,7 @@ class TestFitting(object):
         assert_almost_equal(coef1, coef2)
 
 
-class TestCompanion(object):
+class TestCompanion:
 
     def test_raises(self):
         assert_raises(ValueError, herm.hermcompanion, [])
@@ -487,7 +485,7 @@ class TestCompanion(object):
         assert_(herm.hermcompanion([1, 2])[0, 0] == -.25)
 
 
-class TestGauss(object):
+class TestGauss:
 
     def test_100(self):
         x, w = herm.hermgauss(100)
@@ -506,7 +504,7 @@ class TestGauss(object):
         assert_almost_equal(w.sum(), tgt)
 
 
-class TestMisc(object):
+class TestMisc:
 
     def test_hermfromroots(self):
         res = herm.hermfromroots([])
index 434b30e7bb284d4c54f13dee534f2e6c16265954..2d262a3306222bd79f682b09763b0bd2b90ba8fe 100644 (file)
@@ -1,8 +1,6 @@
 """Tests for hermite_e module.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from functools import reduce
 
 import numpy as np
@@ -30,7 +28,7 @@ def trim(x):
     return herme.hermetrim(x, tol=1e-6)
 
 
-class TestConstants(object):
+class TestConstants:
 
     def test_hermedomain(self):
         assert_equal(herme.hermedomain, [-1, 1])
@@ -45,13 +43,13 @@ class TestConstants(object):
         assert_equal(herme.hermex, [0, 1])
 
 
-class TestArithmetic(object):
+class TestArithmetic:
     x = np.linspace(-3, 3, 100)
 
     def test_hermeadd(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] += 1
@@ -61,7 +59,7 @@ class TestArithmetic(object):
     def test_hermesub(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] -= 1
@@ -82,7 +80,7 @@ class TestArithmetic(object):
             pol1 = [0]*i + [1]
             val1 = herme.hermeval(self.x, pol1)
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 pol2 = [0]*j + [1]
                 val2 = herme.hermeval(self.x, pol2)
                 pol3 = herme.hermemul(pol1, pol2)
@@ -93,7 +91,7 @@ class TestArithmetic(object):
     def test_hermediv(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 ci = [0]*i + [1]
                 cj = [0]*j + [1]
                 tgt = herme.hermeadd(ci, cj)
@@ -104,14 +102,14 @@ class TestArithmetic(object):
     def test_hermepow(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 c = np.arange(i + 1)
                 tgt = reduce(herme.hermemul, [c]*j, np.array([1]))
                 res = herme.hermepow(c, j)
                 assert_equal(trim(res), trim(tgt), err_msg=msg)
 
 
-class TestEvaluation(object):
+class TestEvaluation:
     # coefficients of 1 + 2*x + 3*x**2
     c1d = np.array([4., 2., 3.])
     c2d = np.einsum('i,j->ij', c1d, c1d)
@@ -129,7 +127,7 @@ class TestEvaluation(object):
         x = np.linspace(-1, 1)
         y = [polyval(x, c) for c in Helist]
         for i in range(10):
-            msg = "At i=%d" % i
+            msg = f"At i={i}"
             tgt = y[i]
             res = herme.hermeval(x, [0]*i + [1])
             assert_almost_equal(res, tgt, err_msg=msg)
@@ -205,7 +203,7 @@ class TestEvaluation(object):
         assert_(res.shape == (2, 3)*3)
 
 
-class TestIntegral(object):
+class TestIntegral:
 
     def test_hermeint(self):
         # check exceptions
@@ -307,7 +305,7 @@ class TestIntegral(object):
         assert_almost_equal(res, tgt)
 
 
-class TestDerivative(object):
+class TestDerivative:
 
     def test_hermeder(self):
         # check exceptions
@@ -348,7 +346,7 @@ class TestDerivative(object):
         assert_almost_equal(res, tgt)
 
 
-class TestVander(object):
+class TestVander:
     # some random values in [-1, 1)
     x = np.random.random((3, 5))*2 - 1
 
@@ -396,7 +394,7 @@ class TestVander(object):
         assert_(van.shape == (1, 5, 24))
 
 
-class TestFitting(object):
+class TestFitting:
 
     def test_hermefit(self):
         def f(x):
@@ -473,7 +471,7 @@ class TestFitting(object):
         assert_almost_equal(coef1, coef2)
 
 
-class TestCompanion(object):
+class TestCompanion:
 
     def test_raises(self):
         assert_raises(ValueError, herme.hermecompanion, [])
@@ -488,7 +486,7 @@ class TestCompanion(object):
         assert_(herme.hermecompanion([1, 2])[0, 0] == -.5)
 
 
-class TestGauss(object):
+class TestGauss:
 
     def test_100(self):
         x, w = herme.hermegauss(100)
@@ -507,7 +505,7 @@ class TestGauss(object):
         assert_almost_equal(w.sum(), tgt)
 
 
-class TestMisc(object):
+class TestMisc:
 
     def test_hermefromroots(self):
         res = herme.hermefromroots([])
index 4b9b2863757bc5d0180320c821f0fa71ce8e0c45..227ef3c5576dd666e2eb76576eb260d5ba48cb0e 100644 (file)
@@ -1,8 +1,6 @@
 """Tests for laguerre module.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from functools import reduce
 
 import numpy as np
@@ -27,7 +25,7 @@ def trim(x):
     return lag.lagtrim(x, tol=1e-6)
 
 
-class TestConstants(object):
+class TestConstants:
 
     def test_lagdomain(self):
         assert_equal(lag.lagdomain, [0, 1])
@@ -42,13 +40,13 @@ class TestConstants(object):
         assert_equal(lag.lagx, [1, -1])
 
 
-class TestArithmetic(object):
+class TestArithmetic:
     x = np.linspace(-3, 3, 100)
 
     def test_lagadd(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] += 1
@@ -58,7 +56,7 @@ class TestArithmetic(object):
     def test_lagsub(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] -= 1
@@ -79,7 +77,7 @@ class TestArithmetic(object):
             pol1 = [0]*i + [1]
             val1 = lag.lagval(self.x, pol1)
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 pol2 = [0]*j + [1]
                 val2 = lag.lagval(self.x, pol2)
                 pol3 = lag.lagmul(pol1, pol2)
@@ -90,7 +88,7 @@ class TestArithmetic(object):
     def test_lagdiv(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 ci = [0]*i + [1]
                 cj = [0]*j + [1]
                 tgt = lag.lagadd(ci, cj)
@@ -101,14 +99,14 @@ class TestArithmetic(object):
     def test_lagpow(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 c = np.arange(i + 1)
                 tgt = reduce(lag.lagmul, [c]*j, np.array([1]))
                 res = lag.lagpow(c, j) 
                 assert_equal(trim(res), trim(tgt), err_msg=msg)
 
 
-class TestEvaluation(object):
+class TestEvaluation:
     # coefficients of 1 + 2*x + 3*x**2
     c1d = np.array([9., -14., 6.])
     c2d = np.einsum('i,j->ij', c1d, c1d)
@@ -126,7 +124,7 @@ class TestEvaluation(object):
         x = np.linspace(-1, 1)
         y = [polyval(x, c) for c in Llist]
         for i in range(7):
-            msg = "At i=%d" % i
+            msg = f"At i={i}"
             tgt = y[i]
             res = lag.lagval(x, [0]*i + [1])
             assert_almost_equal(res, tgt, err_msg=msg)
@@ -202,7 +200,7 @@ class TestEvaluation(object):
         assert_(res.shape == (2, 3)*3)
 
 
-class TestIntegral(object):
+class TestIntegral:
 
     def test_lagint(self):
         # check exceptions
@@ -304,7 +302,7 @@ class TestIntegral(object):
         assert_almost_equal(res, tgt)
 
 
-class TestDerivative(object):
+class TestDerivative:
 
     def test_lagder(self):
         # check exceptions
@@ -344,7 +342,7 @@ class TestDerivative(object):
         assert_almost_equal(res, tgt)
 
 
-class TestVander(object):
+class TestVander:
     # some random values in [-1, 1)
     x = np.random.random((3, 5))*2 - 1
 
@@ -392,7 +390,7 @@ class TestVander(object):
         assert_(van.shape == (1, 5, 24))
 
 
-class TestFitting(object):
+class TestFitting:
 
     def test_lagfit(self):
         def f(x):
@@ -454,7 +452,7 @@ class TestFitting(object):
         assert_almost_equal(lag.lagfit(x, x, [0, 1]), [1, -1])
 
 
-class TestCompanion(object):
+class TestCompanion:
 
     def test_raises(self):
         assert_raises(ValueError, lag.lagcompanion, [])
@@ -469,7 +467,7 @@ class TestCompanion(object):
         assert_(lag.lagcompanion([1, 2])[0, 0] == 1.5)
 
 
-class TestGauss(object):
+class TestGauss:
 
     def test_100(self):
         x, w = lag.laggauss(100)
@@ -488,7 +486,7 @@ class TestGauss(object):
         assert_almost_equal(w.sum(), tgt)
 
 
-class TestMisc(object):
+class TestMisc:
 
     def test_lagfromroots(self):
         res = lag.lagfromroots([])
index 917a7e03afdf97e0a02a3e28b2e8678dd46127e7..a2a212c242e3c4380f89f31e59ddd16fc345d195 100644 (file)
@@ -1,8 +1,6 @@
 """Tests for legendre module.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from functools import reduce
 
 import numpy as np
@@ -30,7 +28,7 @@ def trim(x):
     return leg.legtrim(x, tol=1e-6)
 
 
-class TestConstants(object):
+class TestConstants:
 
     def test_legdomain(self):
         assert_equal(leg.legdomain, [-1, 1])
@@ -45,13 +43,13 @@ class TestConstants(object):
         assert_equal(leg.legx, [0, 1])
 
 
-class TestArithmetic(object):
+class TestArithmetic:
     x = np.linspace(-1, 1, 100)
 
     def test_legadd(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] += 1
@@ -61,7 +59,7 @@ class TestArithmetic(object):
     def test_legsub(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] -= 1
@@ -83,7 +81,7 @@ class TestArithmetic(object):
             pol1 = [0]*i + [1]
             val1 = leg.legval(self.x, pol1)
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 pol2 = [0]*j + [1]
                 val2 = leg.legval(self.x, pol2)
                 pol3 = leg.legmul(pol1, pol2)
@@ -94,7 +92,7 @@ class TestArithmetic(object):
     def test_legdiv(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 ci = [0]*i + [1]
                 cj = [0]*j + [1]
                 tgt = leg.legadd(ci, cj)
@@ -105,14 +103,14 @@ class TestArithmetic(object):
     def test_legpow(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 c = np.arange(i + 1)
                 tgt = reduce(leg.legmul, [c]*j, np.array([1]))
                 res = leg.legpow(c, j) 
                 assert_equal(trim(res), trim(tgt), err_msg=msg)
 
 
-class TestEvaluation(object):
+class TestEvaluation:
     # coefficients of 1 + 2*x + 3*x**2
     c1d = np.array([2., 2., 2.])
     c2d = np.einsum('i,j->ij', c1d, c1d)
@@ -130,7 +128,7 @@ class TestEvaluation(object):
         x = np.linspace(-1, 1)
         y = [polyval(x, c) for c in Llist]
         for i in range(10):
-            msg = "At i=%d" % i
+            msg = f"At i={i}"
             tgt = y[i]
             res = leg.legval(x, [0]*i + [1])
             assert_almost_equal(res, tgt, err_msg=msg)
@@ -206,7 +204,7 @@ class TestEvaluation(object):
         assert_(res.shape == (2, 3)*3)
 
 
-class TestIntegral(object):
+class TestIntegral:
 
     def test_legint(self):
         # check exceptions
@@ -308,7 +306,7 @@ class TestIntegral(object):
         assert_almost_equal(res, tgt)
 
 
-class TestDerivative(object):
+class TestDerivative:
 
     def test_legder(self):
         # check exceptions
@@ -348,7 +346,7 @@ class TestDerivative(object):
         assert_almost_equal(res, tgt)
 
 
-class TestVander(object):
+class TestVander:
     # some random values in [-1, 1)
     x = np.random.random((3, 5))*2 - 1
 
@@ -396,7 +394,7 @@ class TestVander(object):
         assert_(van.shape == (1, 5, 24))
 
 
-class TestFitting(object):
+class TestFitting:
 
     def test_legfit(self):
         def f(x):
@@ -473,7 +471,7 @@ class TestFitting(object):
         assert_almost_equal(coef1, coef2)
 
 
-class TestCompanion(object):
+class TestCompanion:
 
     def test_raises(self):
         assert_raises(ValueError, leg.legcompanion, [])
@@ -488,7 +486,7 @@ class TestCompanion(object):
         assert_(leg.legcompanion([1, 2])[0, 0] == -.5)
 
 
-class TestGauss(object):
+class TestGauss:
 
     def test_100(self):
         x, w = leg.leggauss(100)
@@ -507,7 +505,7 @@ class TestGauss(object):
         assert_almost_equal(w.sum(), tgt)
 
 
-class TestMisc(object):
+class TestMisc:
 
     def test_legfromroots(self):
         res = leg.legfromroots([])
index 1436963c671511c23bbd9cb8238fc21d9c58e3ca..5fd1a82a2faf4e7c44391932cf23027b5da4de06 100644 (file)
@@ -1,15 +1,13 @@
 """Tests for polynomial module.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from functools import reduce
 
 import numpy as np
 import numpy.polynomial.polynomial as poly
 from numpy.testing import (
     assert_almost_equal, assert_raises, assert_equal, assert_,
-    assert_warns, assert_array_equal)
+    assert_warns, assert_array_equal, assert_raises_regex)
 
 
 def trim(x):
@@ -29,7 +27,7 @@ T9 = [0, 9, 0, -120, 0, 432, 0, -576, 0, 256]
 Tlist = [T0, T1, T2, T3, T4, T5, T6, T7, T8, T9]
 
 
-class TestConstants(object):
+class TestConstants:
 
     def test_polydomain(self):
         assert_equal(poly.polydomain, [-1, 1])
@@ -44,12 +42,12 @@ class TestConstants(object):
         assert_equal(poly.polyx, [0, 1])
 
 
-class TestArithmetic(object):
+class TestArithmetic:
 
     def test_polyadd(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] += 1
@@ -59,7 +57,7 @@ class TestArithmetic(object):
     def test_polysub(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(max(i, j) + 1)
                 tgt[i] += 1
                 tgt[j] -= 1
@@ -77,7 +75,7 @@ class TestArithmetic(object):
     def test_polymul(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 tgt = np.zeros(i + j + 1)
                 tgt[i + j] += 1
                 res = poly.polymul([0]*i + [1], [0]*j + [1])
@@ -96,7 +94,7 @@ class TestArithmetic(object):
         # check rest.
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 ci = [0]*i + [1, 2]
                 cj = [0]*j + [1, 2]
                 tgt = poly.polyadd(ci, cj)
@@ -107,14 +105,14 @@ class TestArithmetic(object):
     def test_polypow(self):
         for i in range(5):
             for j in range(5):
-                msg = "At i=%d, j=%d" % (i, j)
+                msg = f"At i={i}, j={j}"
                 c = np.arange(i + 1)
                 tgt = reduce(poly.polymul, [c]*j, np.array([1]))
                 res = poly.polypow(c, j) 
                 assert_equal(trim(res), trim(tgt), err_msg=msg)
 
 
-class TestEvaluation(object):
+class TestEvaluation:
     # coefficients of 1 + 2*x + 3*x**2
     c1d = np.array([1., 2., 3.])
     c2d = np.einsum('i,j->ij', c1d, c1d)
@@ -229,7 +227,8 @@ class TestEvaluation(object):
         y1, y2, y3 = self.y
 
         #test exceptions
-        assert_raises(ValueError, poly.polyval2d, x1, x2[:2], self.c2d)
+        assert_raises_regex(ValueError, 'incompatible',
+                            poly.polyval2d, x1, x2[:2], self.c2d)
 
         #test values
         tgt = y1*y2
@@ -246,7 +245,8 @@ class TestEvaluation(object):
         y1, y2, y3 = self.y
 
         #test exceptions
-        assert_raises(ValueError, poly.polyval3d, x1, x2, x3[:2], self.c3d)
+        assert_raises_regex(ValueError, 'incompatible',
+                      poly.polyval3d, x1, x2, x3[:2], self.c3d)
 
         #test values
         tgt = y1*y2*y3
@@ -287,7 +287,7 @@ class TestEvaluation(object):
         assert_(res.shape == (2, 3)*3)
 
 
-class TestIntegral(object):
+class TestIntegral:
 
     def test_polyint(self):
         # check exceptions
@@ -386,7 +386,7 @@ class TestIntegral(object):
         assert_almost_equal(res, tgt)
 
 
-class TestDerivative(object):
+class TestDerivative:
 
     def test_polyder(self):
         # check exceptions
@@ -426,7 +426,7 @@ class TestDerivative(object):
         assert_almost_equal(res, tgt)
 
 
-class TestVander(object):
+class TestVander:
     # some random values in [-1, 1)
     x = np.random.random((3, 5))*2 - 1
 
@@ -474,7 +474,7 @@ class TestVander(object):
         assert_(van.shape == (1, 5, 24))
 
 
-class TestCompanion(object):
+class TestCompanion:
 
     def test_raises(self):
         assert_raises(ValueError, poly.polycompanion, [])
@@ -489,7 +489,7 @@ class TestCompanion(object):
         assert_(poly.polycompanion([1, 2])[0, 0] == -.5)
 
 
-class TestMisc(object):
+class TestMisc:
 
     def test_polyfromroots(self):
         res = poly.polyfromroots([])
index 801c558ccca4c635d73b9ad77ad57bdc1261ff63..1b27f53b59882953b693362fdec754faa158f50a 100644 (file)
@@ -1,8 +1,6 @@
 """Tests for polyutils module.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 import numpy.polynomial.polyutils as pu
 from numpy.testing import (
@@ -10,7 +8,7 @@ from numpy.testing import (
     )
 
 
-class TestMisc(object):
+class TestMisc:
 
     def test_trimseq(self):
         for i in range(5):
@@ -43,7 +41,7 @@ class TestMisc(object):
         assert_equal(pu.trimcoef(coef, 2), [0])
 
 
-class TestDomain(object):
+class TestDomain:
 
     def test_getdomain(self):
         # test for real values
index 3f123640222830be8812b658d6f401047a4bcbaa..bbd5502afa6479f2fa1ea19f4c9304f31b5b7a60 100644 (file)
@@ -1,10 +1,8 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy.polynomial as poly
 from numpy.testing import assert_equal
 
 
-class TestStr(object):
+class TestStr:
     def test_polynomial_str(self):
         res = str(poly.Polynomial([0, 1]))
         tgt = 'poly([0. 1.])'
@@ -36,7 +34,7 @@ class TestStr(object):
         assert_equal(res, tgt)
 
 
-class TestRepr(object):
+class TestRepr:
     def test_polynomial_str(self):
         res = repr(poly.Polynomial([0, 1]))
         tgt = 'Polynomial([0., 1.], domain=[-1,  1], window=[-1,  1])'
@@ -66,3 +64,52 @@ class TestRepr(object):
         res = repr(poly.Laguerre([0, 1]))
         tgt = 'Laguerre([0., 1.], domain=[0, 1], window=[0, 1])'
         assert_equal(res, tgt)
+
+
+class TestLatexRepr:
+    """Test the latex repr used by Jupyter"""
+
+    def as_latex(self, obj):
+        # right now we ignore the formatting of scalars in our tests, since
+        # it makes them too verbose. Ideally, the formatting of scalars will
+        # be fixed such that tests below continue to pass
+        obj._repr_latex_scalar = lambda x: str(x)
+        try:
+            return obj._repr_latex_()
+        finally:
+            del obj._repr_latex_scalar
+
+    def test_simple_polynomial(self):
+        # default input
+        p = poly.Polynomial([1, 2, 3])
+        assert_equal(self.as_latex(p),
+            r'$x \mapsto 1.0 + 2.0\,x + 3.0\,x^{2}$')
+
+        # translated input
+        p = poly.Polynomial([1, 2, 3], domain=[-2, 0])
+        assert_equal(self.as_latex(p),
+            r'$x \mapsto 1.0 + 2.0\,\left(1.0 + x\right) + 3.0\,\left(1.0 + x\right)^{2}$')
+
+        # scaled input
+        p = poly.Polynomial([1, 2, 3], domain=[-0.5, 0.5])
+        assert_equal(self.as_latex(p),
+            r'$x \mapsto 1.0 + 2.0\,\left(2.0x\right) + 3.0\,\left(2.0x\right)^{2}$')
+
+        # affine input
+        p = poly.Polynomial([1, 2, 3], domain=[-1, 0])
+        assert_equal(self.as_latex(p),
+            r'$x \mapsto 1.0 + 2.0\,\left(1.0 + 2.0x\right) + 3.0\,\left(1.0 + 2.0x\right)^{2}$')
+
+    def test_basis_func(self):
+        p = poly.Chebyshev([1, 2, 3])
+        assert_equal(self.as_latex(p),
+            r'$x \mapsto 1.0\,{T}_{0}(x) + 2.0\,{T}_{1}(x) + 3.0\,{T}_{2}(x)$')
+        # affine input - check no surplus parens are added
+        p = poly.Chebyshev([1, 2, 3], domain=[-1, 0])
+        assert_equal(self.as_latex(p),
+            r'$x \mapsto 1.0\,{T}_{0}(1.0 + 2.0x) + 2.0\,{T}_{1}(1.0 + 2.0x) + 3.0\,{T}_{2}(1.0 + 2.0x)$')
+
+    def test_multichar_basis_func(self):
+        p = poly.HermiteE([1, 2, 3])
+        assert_equal(self.as_latex(p),
+            r'$x \mapsto 1.0\,{He}_{0}(x) + 2.0\,{He}_{1}(x) + 3.0\,{He}_{2}(x)$')
index 05e07387667384251d9e4af5f6cc7cfe27dad314..1f9057296ba9475574a191cf231dc04ace3f910c 100644 (file)
@@ -11,4 +11,4 @@ cdef extern from "numpy/random/bitgen.h":
 
     ctypedef bitgen bitgen_t
 
-from numpy.random._bit_generator cimport BitGenerator, SeedSequence
+from numpy.random.bit_generator cimport BitGenerator, SeedSequence
index 1ceb5c4dd7b7647051dae7568468eddcd12c14f1..7efa5c07fcfe8fa70ffdf41a54c32944279b32c8 100644 (file)
@@ -122,8 +122,6 @@ set_state            Set state of generator.
 
 
 """
-from __future__ import division, absolute_import, print_function
-
 __all__ = [
     'beta',
     'binomial',
@@ -183,7 +181,7 @@ from . import _common
 from . import _bounded_integers
 
 from ._generator import Generator, default_rng
-from ._bit_generator import SeedSequence, BitGenerator
+from .bit_generator import SeedSequence, BitGenerator
 from ._mt19937 import MT19937
 from ._pcg64 import PCG64
 from ._philox import Philox
diff --git a/numpy/random/_bit_generator.pxd b/numpy/random/_bit_generator.pxd
deleted file mode 100644 (file)
index bd5e47a..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-cimport numpy as np
-from libc.stdint cimport uint32_t, uint64_t
-
-cdef extern from "numpy/random/bitgen.h":
-    struct bitgen:
-        void *state
-        uint64_t (*next_uint64)(void *st) nogil
-        uint32_t (*next_uint32)(void *st) nogil
-        double (*next_double)(void *st) nogil
-        uint64_t (*next_raw)(void *st) nogil
-
-    ctypedef bitgen bitgen_t
-
-cdef class BitGenerator():
-    cdef readonly object _seed_seq
-    cdef readonly object lock
-    cdef bitgen_t _bitgen
-    cdef readonly object _ctypes
-    cdef readonly object _cffi
-    cdef readonly object capsule
-
-
-cdef class SeedSequence():
-    cdef readonly object entropy
-    cdef readonly tuple spawn_key
-    cdef readonly uint32_t pool_size
-    cdef readonly object pool
-    cdef readonly uint32_t n_children_spawned
-
-    cdef mix_entropy(self, np.ndarray[np.npy_uint32, ndim=1] mixer,
-                     np.ndarray[np.npy_uint32, ndim=1] entropy_array)
-    cdef get_assembled_entropy(self)
-
-cdef class SeedlessSequence():
-    pass
diff --git a/numpy/random/_bit_generator.pyx b/numpy/random/_bit_generator.pyx
deleted file mode 100644 (file)
index 21d21e6..0000000
+++ /dev/null
@@ -1,626 +0,0 @@
-"""
-BitGenerator base class and SeedSequence used to seed the BitGenerators.
-
-SeedSequence is derived from Melissa E. O'Neill's C++11 `std::seed_seq`
-implementation, as it has a lot of nice properties that we want.
-
-https://gist.github.com/imneme/540829265469e673d045
-http://www.pcg-random.org/posts/developing-a-seed_seq-alternative.html
-
-The MIT License (MIT)
-
-Copyright (c) 2015 Melissa E. O'Neill
-Copyright (c) 2019 NumPy Developers
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-"""
-
-import abc
-import sys
-from itertools import cycle
-import re
-
-try:
-    from secrets import randbits
-except ImportError:
-    # secrets unavailable on python 3.5 and before
-    from random import SystemRandom
-    randbits = SystemRandom().getrandbits
-
-try:
-    from threading import Lock
-except ImportError:
-    from dummy_threading import Lock
-
-from cpython.pycapsule cimport PyCapsule_New
-
-import numpy as np
-cimport numpy as np
-
-from ._common cimport (random_raw, benchmark, prepare_ctypes, prepare_cffi)
-
-__all__ = ['SeedSequence', 'BitGenerator']
-
-np.import_array()
-
-DECIMAL_RE = re.compile(r'[0-9]+')
-
-cdef uint32_t DEFAULT_POOL_SIZE = 4  # Appears also in docstring for pool_size
-cdef uint32_t INIT_A = 0x43b0d7e5
-cdef uint32_t MULT_A = 0x931e8875
-cdef uint32_t INIT_B = 0x8b51f9dd
-cdef uint32_t MULT_B = 0x58f38ded
-cdef uint32_t MIX_MULT_L = 0xca01f9dd
-cdef uint32_t MIX_MULT_R = 0x4973f715
-cdef uint32_t XSHIFT = np.dtype(np.uint32).itemsize * 8 // 2
-cdef uint32_t MASK32 = 0xFFFFFFFF
-
-def _int_to_uint32_array(n):
-    arr = []
-    if n < 0:
-        raise ValueError("expected non-negative integer")
-    if n == 0:
-        arr.append(np.uint32(n))
-    if isinstance(n, np.unsignedinteger):
-        # Cannot do n & MASK32, convert to python int
-        n = int(n)
-    while n > 0:
-        arr.append(np.uint32(n & MASK32))
-        n //= (2**32)
-    return np.array(arr, dtype=np.uint32)
-
-def _coerce_to_uint32_array(x):
-    """ Coerce an input to a uint32 array.
-
-    If a `uint32` array, pass it through directly.
-    If a non-negative integer, then break it up into `uint32` words, lowest
-    bits first.
-    If a string starting with "0x", then interpret as a hex integer, as above.
-    If a string of decimal digits, interpret as a decimal integer, as above.
-    If a sequence of ints or strings, interpret each element as above and
-    concatenate.
-
-    Note that the handling of `int64` or `uint64` arrays are not just
-    straightforward views as `uint32` arrays. If an element is small enough to
-    fit into a `uint32`, then it will only take up one `uint32` element in the
-    output. This is to make sure that the interpretation of a sequence of
-    integers is the same regardless of numpy's default integer type, which
-    differs on different platforms.
-
-    Parameters
-    ----------
-    x : int, str, sequence of int or str
-
-    Returns
-    -------
-    seed_array : uint32 array
-
-    Examples
-    --------
-    >>> import numpy as np
-    >>> from numpy.random._bit_generator import _coerce_to_uint32_array
-    >>> _coerce_to_uint32_array(12345)
-    array([12345], dtype=uint32)
-    >>> _coerce_to_uint32_array('12345')
-    array([12345], dtype=uint32)
-    >>> _coerce_to_uint32_array('0x12345')
-    array([74565], dtype=uint32)
-    >>> _coerce_to_uint32_array([12345, '67890'])
-    array([12345, 67890], dtype=uint32)
-    >>> _coerce_to_uint32_array(np.array([12345, 67890], dtype=np.uint32))
-    array([12345, 67890], dtype=uint32)
-    >>> _coerce_to_uint32_array(np.array([12345, 67890], dtype=np.int64))
-    array([12345, 67890], dtype=uint32)
-    >>> _coerce_to_uint32_array([12345, 0x10deadbeef, 67890, 0xdeadbeef])
-    array([     12345, 3735928559,         16,      67890, 3735928559],
-          dtype=uint32)
-    >>> _coerce_to_uint32_array(1234567890123456789012345678901234567890)
-    array([3460238034, 2898026390, 3235640248, 2697535605,          3],
-          dtype=uint32)
-    """
-    if isinstance(x, np.ndarray) and x.dtype == np.dtype(np.uint32):
-        return x.copy()
-    elif isinstance(x, str):
-        if x.startswith('0x'):
-            x = int(x, base=16)
-        elif DECIMAL_RE.match(x):
-            x = int(x)
-        else:
-            raise ValueError("unrecognized seed string")
-    if isinstance(x, (int, np.integer)):
-        return _int_to_uint32_array(x)
-    elif isinstance(x, (float, np.inexact)):
-        raise TypeError('seed must be integer')
-    else:
-        if len(x) == 0:
-            return np.array([], dtype=np.uint32)
-        # Should be a sequence of interpretable-as-ints. Convert each one to
-        # a uint32 array and concatenate.
-        subseqs = [_coerce_to_uint32_array(v) for v in x]
-        return np.concatenate(subseqs)
-
-
-cdef uint32_t hashmix(uint32_t value, uint32_t * hash_const):
-    # We are modifying the multiplier as we go along, so it is input-output
-    value ^= hash_const[0]
-    hash_const[0] *= MULT_A
-    value *=  hash_const[0]
-    value ^= value >> XSHIFT
-    return value
-
-cdef uint32_t mix(uint32_t x, uint32_t y):
-    cdef uint32_t result = (MIX_MULT_L * x - MIX_MULT_R * y)
-    result ^= result >> XSHIFT
-    return result
-
-
-class ISeedSequence(abc.ABC):
-    """
-    Abstract base class for seed sequences.
-
-    ``BitGenerator`` implementations should treat any object that adheres to
-    this interface as a seed sequence.
-
-    See Also
-    --------
-    SeedSequence, SeedlessSeedSequence
-    """
-
-    @abc.abstractmethod
-    def generate_state(self, n_words, dtype=np.uint32):
-        """
-        generate_state(n_words, dtype=np.uint32)
-
-        Return the requested number of words for PRNG seeding.
-
-        A BitGenerator should call this method in its constructor with
-        an appropriate `n_words` parameter to properly seed itself.
-
-        Parameters
-        ----------
-        n_words : int
-        dtype : np.uint32 or np.uint64, optional
-            The size of each word. This should only be either `uint32` or
-            `uint64`. Strings (`'uint32'`, `'uint64'`) are fine. Note that
-            requesting `uint64` will draw twice as many bits as `uint32` for
-            the same `n_words`. This is a convenience for `BitGenerator`s that
-            express their states as `uint64` arrays.
-
-        Returns
-        -------
-        state : uint32 or uint64 array, shape=(n_words,)
-        """
-
-
-class ISpawnableSeedSequence(ISeedSequence):
-    """
-    Abstract base class for seed sequences that can spawn.
-    """
-
-    @abc.abstractmethod
-    def spawn(self, n_children):
-        """
-        spawn(n_children)
-
-        Spawn a number of child `SeedSequence` s by extending the
-        `spawn_key`.
-
-        Parameters
-        ----------
-        n_children : int
-
-        Returns
-        -------
-        seqs : list of `SeedSequence` s
-        """
-
-
-cdef class SeedlessSeedSequence():
-    """
-    A seed sequence for BitGenerators with no need for seed state.
-
-    See Also
-    --------
-    SeedSequence, ISeedSequence
-    """
-
-    def generate_state(self, n_words, dtype=np.uint32):
-        raise NotImplementedError('seedless SeedSequences cannot generate state')
-
-    def spawn(self, n_children):
-        return [self] * n_children
-
-
-# We cannot directly subclass a `cdef class` type from an `ABC` in Cython, so
-# we must register it after the fact.
-ISpawnableSeedSequence.register(SeedlessSeedSequence)
-
-
-cdef class SeedSequence():
-    """
-    SeedSequence(entropy=None, *, spawn_key=(), pool_size=4)
-
-    SeedSequence mixes sources of entropy in a reproducible way to set the
-    initial state for independent and very probably non-overlapping
-    BitGenerators.
-
-    Once the SeedSequence is instantiated, you can call the `generate_state`
-    method to get an appropriately sized seed. Calling `spawn(n) <spawn>` will
-    create ``n`` SeedSequences that can be used to seed independent
-    BitGenerators, i.e. for different threads.
-
-    Parameters
-    ----------
-    entropy : {None, int, sequence[int]}, optional
-        The entropy for creating a `SeedSequence`.
-    spawn_key : {(), sequence[int]}, optional
-        A third source of entropy, used internally when calling
-        `SeedSequence.spawn`
-    pool_size : {int}, optional
-        Size of the pooled entropy to store. Default is 4 to give a 128-bit
-        entropy pool. 8 (for 256 bits) is another reasonable choice if working
-        with larger PRNGs, but there is very little to be gained by selecting
-        another value.
-    n_children_spawned : {int}, optional
-        The number of children already spawned. Only pass this if
-        reconstructing a `SeedSequence` from a serialized form.
-
-    Notes
-    -----
-
-    Best practice for achieving reproducible bit streams is to use
-    the default ``None`` for the initial entropy, and then use
-    `SeedSequence.entropy` to log/pickle the `entropy` for reproducibility:
-
-    >>> sq1 = np.random.SeedSequence()
-    >>> sq1.entropy
-    243799254704924441050048792905230269161  # random
-    >>> sq2 = np.random.SeedSequence(sq1.entropy)
-    >>> np.all(sq1.generate_state(10) == sq2.generate_state(10))
-    True
-    """
-
-    def __init__(self, entropy=None, *, spawn_key=(),
-                 pool_size=DEFAULT_POOL_SIZE, n_children_spawned=0):
-        if pool_size < DEFAULT_POOL_SIZE:
-            raise ValueError("The size of the entropy pool should be at least "
-                             f"{DEFAULT_POOL_SIZE}")
-        if entropy is None:
-            entropy = randbits(pool_size * 32)
-        elif not isinstance(entropy, (int, np.integer, list, tuple, range,
-                                      np.ndarray)):
-            raise TypeError('SeedSequence expects int or sequence of ints for '
-                            'entropy not {}'.format(entropy))
-        self.entropy = entropy
-        self.spawn_key = tuple(spawn_key)
-        self.pool_size = pool_size
-        self.n_children_spawned = n_children_spawned
-
-        self.pool = np.zeros(pool_size, dtype=np.uint32)
-        self.mix_entropy(self.pool, self.get_assembled_entropy())
-
-    def __repr__(self):
-        lines = [
-            f'{type(self).__name__}(',
-            f'    entropy={self.entropy!r},',
-        ]
-        # Omit some entries if they are left as the defaults in order to
-        # simplify things.
-        if self.spawn_key:
-            lines.append(f'    spawn_key={self.spawn_key!r},')
-        if self.pool_size != DEFAULT_POOL_SIZE:
-            lines.append(f'    pool_size={self.pool_size!r},')
-        if self.n_children_spawned != 0:
-            lines.append(f'    n_children_spawned={self.n_children_spawned!r},')
-        lines.append(')')
-        text = '\n'.join(lines)
-        return text
-
-    @property
-    def state(self):
-        return {k:getattr(self, k) for k in
-                ['entropy', 'spawn_key', 'pool_size',
-                 'n_children_spawned']
-                if getattr(self, k) is not None}
-
-    cdef mix_entropy(self, np.ndarray[np.npy_uint32, ndim=1] mixer,
-                     np.ndarray[np.npy_uint32, ndim=1] entropy_array):
-        """ Mix in the given entropy to mixer.
-
-        Parameters
-        ----------
-        mixer : 1D uint32 array, modified in-place
-        entropy_array : 1D uint32 array
-        """
-        cdef uint32_t hash_const[1]
-        hash_const[0] = INIT_A
-
-        # Add in the entropy up to the pool size.
-        for i in range(len(mixer)):
-            if i < len(entropy_array):
-                mixer[i] = hashmix(entropy_array[i], hash_const)
-            else:
-                # Our pool size is bigger than our entropy, so just keep
-                # running the hash out.
-                mixer[i] = hashmix(0, hash_const)
-
-        # Mix all bits together so late bits can affect earlier bits.
-        for i_src in range(len(mixer)):
-            for i_dst in range(len(mixer)):
-                if i_src != i_dst:
-                    mixer[i_dst] = mix(mixer[i_dst],
-                                       hashmix(mixer[i_src], hash_const))
-
-        # Add any remaining entropy, mixing each new entropy word with each
-        # pool word.
-        for i_src in range(len(mixer), len(entropy_array)):
-            for i_dst in range(len(mixer)):
-                mixer[i_dst] = mix(mixer[i_dst],
-                                   hashmix(entropy_array[i_src], hash_const))
-
-    cdef get_assembled_entropy(self):
-        """ Convert and assemble all entropy sources into a uniform uint32
-        array.
-
-        Returns
-        -------
-        entropy_array : 1D uint32 array
-        """
-        # Convert run-entropy, program-entropy, and the spawn key into uint32
-        # arrays and concatenate them.
-
-        # We MUST have at least some run-entropy. The others are optional.
-        assert self.entropy is not None
-        run_entropy = _coerce_to_uint32_array(self.entropy)
-        spawn_entropy = _coerce_to_uint32_array(self.spawn_key)
-        entropy_array = np.concatenate([run_entropy, spawn_entropy])
-        return entropy_array
-
-    @np.errstate(over='ignore')
-    def generate_state(self, n_words, dtype=np.uint32):
-        """
-        generate_state(n_words, dtype=np.uint32)
-
-        Return the requested number of words for PRNG seeding.
-
-        A BitGenerator should call this method in its constructor with
-        an appropriate `n_words` parameter to properly seed itself.
-
-        Parameters
-        ----------
-        n_words : int
-        dtype : np.uint32 or np.uint64, optional
-            The size of each word. This should only be either `uint32` or
-            `uint64`. Strings (`'uint32'`, `'uint64'`) are fine. Note that
-            requesting `uint64` will draw twice as many bits as `uint32` for
-            the same `n_words`. This is a convenience for `BitGenerator`s that
-            express their states as `uint64` arrays.
-
-        Returns
-        -------
-        state : uint32 or uint64 array, shape=(n_words,)
-        """
-        cdef uint32_t hash_const = INIT_B
-        cdef uint32_t data_val
-
-        out_dtype = np.dtype(dtype)
-        if out_dtype == np.dtype(np.uint32):
-            pass
-        elif out_dtype == np.dtype(np.uint64):
-            n_words *= 2
-        else:
-            raise ValueError("only support uint32 or uint64")
-        state = np.zeros(n_words, dtype=np.uint32)
-        src_cycle = cycle(self.pool)
-        for i_dst in range(n_words):
-            data_val = next(src_cycle)
-            data_val ^= hash_const
-            hash_const *= MULT_B
-            data_val *= hash_const
-            data_val ^= data_val >> XSHIFT
-            state[i_dst] = data_val
-        if out_dtype == np.dtype(np.uint64):
-            # For consistency across different endiannesses, view first as
-            # little-endian then convert the values to the native endianness.
-            state = state.astype('<u4').view('<u8').astype(np.uint64)
-        return state
-
-    def spawn(self, n_children):
-        """
-        spawn(n_children)
-
-        Spawn a number of child `SeedSequence` s by extending the
-        `spawn_key`.
-
-        Parameters
-        ----------
-        n_children : int
-
-        Returns
-        -------
-        seqs : list of `SeedSequence` s
-        """
-        cdef uint32_t i
-
-        seqs = []
-        for i in range(self.n_children_spawned,
-                       self.n_children_spawned + n_children):
-            seqs.append(type(self)(
-                self.entropy,
-                spawn_key=self.spawn_key + (i,),
-                pool_size=self.pool_size,
-            ))
-        self.n_children_spawned += n_children
-        return seqs
-
-
-ISpawnableSeedSequence.register(SeedSequence)
-
-
-cdef class BitGenerator():
-    """
-    BitGenerator(seed=None)
-
-    Base Class for generic BitGenerators, which provide a stream
-    of random bits based on different algorithms. Must be overridden.
-
-    Parameters
-    ----------
-    seed : {None, int, array_like[ints], SeedSequence}, optional
-        A seed to initialize the `BitGenerator`. If None, then fresh,
-        unpredictable entropy will be pulled from the OS. If an ``int`` or
-        ``array_like[ints]`` is passed, then it will be passed to
-        ~`numpy.random.SeedSequence` to derive the initial `BitGenerator` state.
-        One may also pass in a `SeedSequence` instance.
-
-    Attributes
-    ----------
-    lock : threading.Lock
-        Lock instance that is shared so that the same BitGenerator can
-        be used in multiple Generators without corrupting the state. Code that
-        generates values from a bit generator should hold the bit generator's
-        lock.
-
-    See Also
-    -------
-    SeedSequence
-    """
-
-    def __init__(self, seed=None):
-        self.lock = Lock()
-        self._bitgen.state = <void *>0
-        if type(self) is BitGenerator:
-            raise NotImplementedError('BitGenerator is a base class and cannot be instantized')
-
-        self._ctypes = None
-        self._cffi = None
-
-        cdef const char *name = "BitGenerator"
-        self.capsule = PyCapsule_New(<void *>&self._bitgen, name, NULL)
-        if not isinstance(seed, ISeedSequence):
-            seed = SeedSequence(seed)
-        self._seed_seq = seed
-
-    # Pickling support:
-    def __getstate__(self):
-        return self.state
-
-    def __setstate__(self, state):
-        self.state = state
-
-    def __reduce__(self):
-        from ._pickle import __bit_generator_ctor
-        return __bit_generator_ctor, (self.state['bit_generator'],), self.state
-
-    @property
-    def state(self):
-        """
-        Get or set the PRNG state
-
-        The base BitGenerator.state must be overridden by a subclass
-
-        Returns
-        -------
-        state : dict
-            Dictionary containing the information required to describe the
-            state of the PRNG
-        """
-        raise NotImplementedError('Not implemented in base BitGenerator')
-
-    @state.setter
-    def state(self, value):
-        raise NotImplementedError('Not implemented in base BitGenerator')
-
-    def random_raw(self, size=None, output=True):
-        """
-        random_raw(self, size=None)
-
-        Return randoms as generated by the underlying BitGenerator
-
-        Parameters
-        ----------
-        size : int or tuple of ints, optional
-            Output shape.  If the given shape is, e.g., ``(m, n, k)``, then
-            ``m * n * k`` samples are drawn.  Default is None, in which case a
-            single value is returned.
-        output : bool, optional
-            Output values.  Used for performance testing since the generated
-            values are not returned.
-
-        Returns
-        -------
-        out : uint or ndarray
-            Drawn samples.
-
-        Notes
-        -----
-        This method directly exposes the the raw underlying pseudo-random
-        number generator. All values are returned as unsigned 64-bit
-        values irrespective of the number of bits produced by the PRNG.
-
-        See the class docstring for the number of bits returned.
-        """
-        return random_raw(&self._bitgen, self.lock, size, output)
-
-    def _benchmark(self, Py_ssize_t cnt, method=u'uint64'):
-        '''Used in tests'''
-        return benchmark(&self._bitgen, self.lock, cnt, method)
-
-    @property
-    def ctypes(self):
-        """
-        ctypes interface
-
-        Returns
-        -------
-        interface : namedtuple
-            Named tuple containing ctypes wrapper
-
-            * state_address - Memory address of the state struct
-            * state - pointer to the state struct
-            * next_uint64 - function pointer to produce 64 bit integers
-            * next_uint32 - function pointer to produce 32 bit integers
-            * next_double - function pointer to produce doubles
-            * bitgen - pointer to the bit generator struct
-        """
-        if self._ctypes is None:
-            self._ctypes = prepare_ctypes(&self._bitgen)
-
-        return self._ctypes
-
-    @property
-    def cffi(self):
-        """
-        CFFI interface
-
-        Returns
-        -------
-        interface : namedtuple
-            Named tuple containing CFFI wrapper
-
-            * state_address - Memory address of the state struct
-            * state - pointer to the state struct
-            * next_uint64 - function pointer to produce 64 bit integers
-            * next_uint32 - function pointer to produce 32 bit integers
-            * next_double - function pointer to produce doubles
-            * bitgen - pointer to the bit generator struct
-        """
-        if self._cffi is None:
-            self._cffi = prepare_cffi(&self._bitgen)
-        return self._cffi
index accf571d1ed4b7d75a17056a9c1e104b1c67323c..9f46685d32588476361c859303fd0351a3bbb24f 100644 (file)
@@ -304,8 +304,7 @@ cdef object _rand_{{nptype}}(object low, object high, object size,
     high_arr = <np.ndarray>np.array(high, copy=False)
     low_ndim = np.PyArray_NDIM(low_arr)
     high_ndim = np.PyArray_NDIM(high_arr)
-    if ((low_ndim == 0 or (low_ndim == 1 and low_arr.size == 1 and size is not None)) and
-            (high_ndim == 0 or (high_ndim == 1 and high_arr.size == 1 and size is not None))):
+    if low_ndim == 0 and high_ndim == 0:
         low = int(low_arr)
         high = int(high_arr)
         # Subtract 1 since internal generator produces on closed interval [low, high]
index ef1afac7c55251a8b57f0a61bca13a6efa6f1719..dfa488ef38b76b9e36e088af798ac07788ec894d 100644 (file)
@@ -218,6 +218,20 @@ cdef np.ndarray int_to_array(object value, object name, object bits, object uint
     return out
 
 
+cdef validate_output_shape(iter_shape, np.ndarray output):
+    cdef np.npy_intp *shape
+    cdef np.npy_intp ndim, i
+    cdef bint error
+    dims = np.PyArray_DIMS(output)
+    ndim = np.PyArray_NDIM(output)
+    output_shape = tuple((dims[i] for i in range(ndim)))
+    if iter_shape != output_shape:
+        raise ValueError(
+            f"Output size {output_shape} is not compatible with broadcast "
+            f"dimensions of inputs {iter_shape}."
+        )
+
+
 cdef check_output(object out, object dtype, object size):
     if out is None:
         return
@@ -404,6 +418,7 @@ cdef object cont_broadcast_1(void *func, void *state, object size, object lock,
     randoms_data = <double *>np.PyArray_DATA(randoms)
     n = np.PyArray_SIZE(randoms)
     it = np.PyArray_MultiIterNew2(randoms, a_arr)
+    validate_output_shape(it.shape, randoms)
 
     with lock, nogil:
         for i in range(n):
@@ -441,6 +456,8 @@ cdef object cont_broadcast_2(void *func, void *state, object size, object lock,
     n = np.PyArray_SIZE(randoms)
 
     it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr)
+    validate_output_shape(it.shape, randoms)
+
     with lock, nogil:
         for i in range(n):
             a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -482,6 +499,8 @@ cdef object cont_broadcast_3(void *func, void *state, object size, object lock,
     n = np.PyArray_SIZE(randoms)
 
     it = np.PyArray_MultiIterNew4(randoms, a_arr, b_arr, c_arr)
+    validate_output_shape(it.shape, randoms)
+
     with lock, nogil:
         for i in range(n):
             a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -611,6 +630,8 @@ cdef object discrete_broadcast_d(void *func, void *state, object size, object lo
     n = np.PyArray_SIZE(randoms)
 
     it = np.PyArray_MultiIterNew2(randoms, a_arr)
+    validate_output_shape(it.shape, randoms)
+
     with lock, nogil:
         for i in range(n):
             a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -645,6 +666,8 @@ cdef object discrete_broadcast_dd(void *func, void *state, object size, object l
     n = np.PyArray_SIZE(randoms)
 
     it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr)
+    validate_output_shape(it.shape, randoms)
+
     with lock, nogil:
         for i in range(n):
             a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -680,6 +703,8 @@ cdef object discrete_broadcast_di(void *func, void *state, object size, object l
     n = np.PyArray_SIZE(randoms)
 
     it = np.PyArray_MultiIterNew3(randoms, a_arr, b_arr)
+    validate_output_shape(it.shape, randoms)
+
     with lock, nogil:
         for i in range(n):
             a_val = (<double*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -719,6 +744,8 @@ cdef object discrete_broadcast_iii(void *func, void *state, object size, object
     n = np.PyArray_SIZE(randoms)
 
     it = np.PyArray_MultiIterNew4(randoms, a_arr, b_arr, c_arr)
+    validate_output_shape(it.shape, randoms)
+
     with lock, nogil:
         for i in range(n):
             a_val = (<int64_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -750,6 +777,8 @@ cdef object discrete_broadcast_i(void *func, void *state, object size, object lo
     n = np.PyArray_SIZE(randoms)
 
     it = np.PyArray_MultiIterNew2(randoms, a_arr)
+    validate_output_shape(it.shape, randoms)
+
     with lock, nogil:
         for i in range(n):
             a_val = (<int64_t*>np.PyArray_MultiIter_DATA(it, 1))[0]
@@ -923,6 +952,7 @@ cdef object cont_broadcast_1_f(void *func, bitgen_t *state, object size, object
     randoms_data = <float *>np.PyArray_DATA(randoms)
     n = np.PyArray_SIZE(randoms)
     it = np.PyArray_MultiIterNew2(randoms, a_arr)
+    validate_output_shape(it.shape, randoms)
 
     with lock, nogil:
         for i in range(n):
index 7a0dfe078fbb8c79324c34b02a793d51ea111b4e..3a7f81aa0466cf4144d1308d3cf266c573741023 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #cython: language_level=3
 
 from libc.stdint cimport uint32_t
index 1bef506ef4fad387fdd07de265cecc9328424d21..d908e92d01b055589284666f5bb64fe4120c083c 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 #cython: language_level=3
 """
 This file shows how the to use a BitGenerator to create a distribution.
@@ -10,6 +10,8 @@ from cpython.pycapsule cimport PyCapsule_IsValid, PyCapsule_GetPointer
 from libc.stdint cimport uint16_t, uint64_t
 from numpy.random cimport bitgen_t
 from numpy.random import PCG64
+from numpy.random.c_distributions cimport (
+      random_standard_uniform_fill, random_standard_uniform_fill_f)
 
 
 @cython.boundscheck(False)
@@ -40,7 +42,7 @@ def uniforms(Py_ssize_t n):
     randoms = np.asarray(random_values)
 
     return randoms
+
 # cython example 2
 @cython.boundscheck(False)
 @cython.wraparound(False)
@@ -72,3 +74,44 @@ def uint10_uniforms(Py_ssize_t n):
     randoms = np.asarray(random_values)
     return randoms
 
+# cython example 3
+def uniforms_ex(bit_generator, Py_ssize_t n, dtype=np.float64):
+    """
+    Create an array of `n` uniformly distributed doubles via a "fill" function.
+
+    A 'real' distribution would want to process the values into
+    some non-uniform distribution
+
+    Parameters
+    ----------
+    bit_generator: BitGenerator instance
+    n: int
+        Output vector length
+    dtype: {str, dtype}, optional
+        Desired dtype, either 'd' (or 'float64') or 'f' (or 'float32'). The
+        default dtype value is 'd'
+    """
+    cdef Py_ssize_t i
+    cdef bitgen_t *rng
+    cdef const char *capsule_name = "BitGenerator"
+    cdef np.ndarray randoms
+
+    capsule = bit_generator.capsule
+    # Optional check that the capsule if from a BitGenerator
+    if not PyCapsule_IsValid(capsule, capsule_name):
+        raise ValueError("Invalid pointer to anon_func_state")
+    # Cast the pointer
+    rng = <bitgen_t *> PyCapsule_GetPointer(capsule, capsule_name)
+
+    _dtype = np.dtype(dtype)
+    randoms = np.empty(n, dtype=_dtype)
+    if _dtype == np.float32:
+        with bit_generator.lock:
+            random_standard_uniform_fill_f(rng, n, <float*>np.PyArray_DATA(randoms))
+    elif _dtype == np.float64:
+        with bit_generator.lock:
+            random_standard_uniform_fill(rng, n, <double*>np.PyArray_DATA(randoms))
+    else:
+        raise TypeError('Unsupported dtype %r for random' % _dtype)
+    return randoms
+
index 20cedc4e38f0bde772d1ec13051f6dd23a7a380f..42425c2c199fa4b81331a68d6af84e31ca4a8516 100644 (file)
@@ -12,7 +12,11 @@ from setuptools.extension import Extension
 from os.path import join, dirname
 
 path = dirname(__file__)
+src_dir = join(dirname(path), '..', 'src')
 defs = [('NPY_NO_DEPRECATED_API', 0)]
+inc_path = np.get_include()
+# not so nice. We need the random/lib library from numpy
+lib_path = join(np.get_include(), '..', '..', 'random', 'lib')
 
 extending = Extension("extending",
                       sources=[join(path, 'extending.pyx')],
@@ -24,7 +28,9 @@ extending = Extension("extending",
                       )
 distributions = Extension("extending_distributions",
                           sources=[join(path, 'extending_distributions.pyx')],
-                          include_dirs=[np.get_include()],
+                          include_dirs=[inc_path],
+                          library_dirs=[lib_path],
+                          libraries=['npyrandom'],
                           define_macros=defs,
                          )
 
index 7bfa8e1c09cb4a33b764e0514f95f76a8e22becb..e5bb02e24725b1ed336c4912370332a6848253ba 100644 (file)
@@ -11,6 +11,7 @@ import numpy as np
 cimport numpy as np
 from numpy.core.multiarray import normalize_axis_index
 
+from .c_distributions cimport *
 from libc cimport string
 from libc.stdint cimport (uint8_t, uint16_t, uint32_t, uint64_t,
                           int32_t, int64_t, INT64_MAX, SIZE_MAX)
@@ -26,117 +27,8 @@ from ._common cimport (POISSON_LAM_MAX, CONS_POSITIVE, CONS_NONE,
             check_array_constraint, check_constraint, disc, discrete_broadcast_iii,
         )
 
-
-cdef extern from "numpy/random/distributions.h":
-
-    struct s_binomial_t:
-        int has_binomial
-        double psave
-        int64_t nsave
-        double r
-        double q
-        double fm
-        int64_t m
-        double p1
-        double xm
-        double xl
-        double xr
-        double c
-        double laml
-        double lamr
-        double p2
-        double p3
-        double p4
-
-    ctypedef s_binomial_t binomial_t
-
-    double random_standard_uniform(bitgen_t *bitgen_state) nogil
-    void random_standard_uniform_fill(bitgen_t* bitgen_state, np.npy_intp cnt, double *out) nogil
-    double random_standard_exponential(bitgen_t *bitgen_state) nogil
-    double random_standard_exponential_f(bitgen_t *bitgen_state) nogil
-    void random_standard_exponential_fill(bitgen_t *bitgen_state, np.npy_intp cnt, double *out) nogil
-    void random_standard_exponential_fill_f(bitgen_t *bitgen_state, np.npy_intp cnt, double *out) nogil
-    void random_standard_exponential_inv_fill(bitgen_t *bitgen_state, np.npy_intp cnt, double *out) nogil
-    void random_standard_exponential_inv_fill_f(bitgen_t *bitgen_state, np.npy_intp cnt, double *out) nogil
-    double random_standard_normal(bitgen_t* bitgen_state) nogil
-    void random_standard_normal_fill(bitgen_t *bitgen_state, np.npy_intp count, double *out) nogil
-    void random_standard_normal_fill_f(bitgen_t *bitgen_state, np.npy_intp count, float *out) nogil
-    double random_standard_gamma(bitgen_t *bitgen_state, double shape) nogil
-
-    float random_standard_uniform_f(bitgen_t *bitgen_state) nogil
-    void random_standard_uniform_fill_f(bitgen_t* bitgen_state, np.npy_intp cnt, float *out) nogil
-    float random_standard_normal_f(bitgen_t* bitgen_state) nogil
-    float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) nogil
-
-    int64_t random_positive_int64(bitgen_t *bitgen_state) nogil
-    int32_t random_positive_int32(bitgen_t *bitgen_state) nogil
-    int64_t random_positive_int(bitgen_t *bitgen_state) nogil
-    uint64_t random_uint(bitgen_t *bitgen_state) nogil
-
-    double random_normal(bitgen_t *bitgen_state, double loc, double scale) nogil
-
-    double random_gamma(bitgen_t *bitgen_state, double shape, double scale) nogil
-    float random_gamma_f(bitgen_t *bitgen_state, float shape, float scale) nogil
-
-    double random_exponential(bitgen_t *bitgen_state, double scale) nogil
-    double random_uniform(bitgen_t *bitgen_state, double lower, double range) nogil
-    double random_beta(bitgen_t *bitgen_state, double a, double b) nogil
-    double random_chisquare(bitgen_t *bitgen_state, double df) nogil
-    double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) nogil
-    double random_standard_cauchy(bitgen_t *bitgen_state) nogil
-    double random_pareto(bitgen_t *bitgen_state, double a) nogil
-    double random_weibull(bitgen_t *bitgen_state, double a) nogil
-    double random_power(bitgen_t *bitgen_state, double a) nogil
-    double random_laplace(bitgen_t *bitgen_state, double loc, double scale) nogil
-    double random_gumbel(bitgen_t *bitgen_state, double loc, double scale) nogil
-    double random_logistic(bitgen_t *bitgen_state, double loc, double scale) nogil
-    double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma) nogil
-    double random_rayleigh(bitgen_t *bitgen_state, double mode) nogil
-    double random_standard_t(bitgen_t *bitgen_state, double df) nogil
-    double random_noncentral_chisquare(bitgen_t *bitgen_state, double df,
-                                       double nonc) nogil
-    double random_noncentral_f(bitgen_t *bitgen_state, double dfnum,
-                               double dfden, double nonc) nogil
-    double random_wald(bitgen_t *bitgen_state, double mean, double scale) nogil
-    double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa) nogil
-    double random_triangular(bitgen_t *bitgen_state, double left, double mode,
-                             double right) nogil
-
-    int64_t random_poisson(bitgen_t *bitgen_state, double lam) nogil
-    int64_t random_negative_binomial(bitgen_t *bitgen_state, double n, double p) nogil
-    int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, binomial_t *binomial) nogil
-    int64_t random_logseries(bitgen_t *bitgen_state, double p) nogil
-    int64_t random_geometric_search(bitgen_t *bitgen_state, double p) nogil
-    int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p) nogil
-    int64_t random_geometric(bitgen_t *bitgen_state, double p) nogil
-    int64_t random_zipf(bitgen_t *bitgen_state, double a) nogil
-    int64_t random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad,
-                                    int64_t sample) nogil
-
-    uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max) nogil
-
-    # Generate random uint64 numbers in closed interval [off, off + rng].
-    uint64_t random_bounded_uint64(bitgen_t *bitgen_state,
-                                   uint64_t off, uint64_t rng,
-                                   uint64_t mask, bint use_masked) nogil
-
-    void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix,
-                            double *pix, np.npy_intp d, binomial_t *binomial) nogil
-
-    int random_multivariate_hypergeometric_count(bitgen_t *bitgen_state,
-                          int64_t total,
-                          size_t num_colors, int64_t *colors,
-                          int64_t nsample,
-                          size_t num_variates, int64_t *variates) nogil
-    void random_multivariate_hypergeometric_marginals(bitgen_t *bitgen_state,
-                               int64_t total,
-                               size_t num_colors, int64_t *colors,
-                               int64_t nsample,
-                               size_t num_variates, int64_t *variates) nogil
-
 np.import_array()
 
-
 cdef int64_t _safe_sum_nonneg_int64(size_t num_colors, int64_t *colors):
     """
     Sum the values in the array `colors`.
@@ -223,7 +115,7 @@ cdef class Generator:
         capsule = bit_generator.capsule
         cdef const char *name = "BitGenerator"
         if not PyCapsule_IsValid(capsule, name):
-            raise ValueError("Invalid bit generator'. The bit generator must "
+            raise ValueError("Invalid bit generator. The bit generator must "
                              "be instantiated.")
         self._bitgen = (<bitgen_t *> PyCapsule_GetPointer(capsule, name))[0]
         self.lock = bit_generator.lock
@@ -624,32 +516,32 @@ cdef class Generator:
     @cython.wraparound(True)
     def choice(self, a, size=None, replace=True, p=None, axis=0, bint shuffle=True):
         """
-        choice(a, size=None, replace=True, p=None, axis=0):
+        choice(a, size=None, replace=True, p=None, axis=0, shuffle=True)
 
         Generates a random sample from a given 1-D array
 
         Parameters
         ----------
-        a : 1-D array-like or int
+        a : {array_like, int}
             If an ndarray, a random sample is generated from its elements.
-            If an int, the random sample is generated as if a were np.arange(a)
-        size : int or tuple of ints, optional
+            If an int, the random sample is generated from np.arange(a).
+        size : {int, tuple[int]}, optional
             Output shape.  If the given shape is, e.g., ``(m, n, k)``, then
             ``m * n * k`` samples are drawn from the 1-d `a`. If `a` has more
             than one dimension, the `size` shape will be inserted into the
             `axis` dimension, so the output ``ndim`` will be ``a.ndim - 1 +
             len(size)``. Default is None, in which case a single value is
             returned.
-        replace : boolean, optional
+        replace : bool, optional
             Whether the sample is with or without replacement
-        p : 1-D array-like, optional
+        p : 1-D array_like, optional
             The probabilities associated with each entry in a.
             If not given the sample assumes a uniform distribution over all
             entries in a.
         axis : int, optional
             The axis along which the selection is performed. The default, 0,
             selects by row.
-        shuffle : boolean, optional
+        shuffle : bool, optional
             Whether the sample is shuffled when sampling without replacement.
             Default is True, False provides a speedup.
 
@@ -720,13 +612,15 @@ cdef class Generator:
                 # __index__ must return an integer by python rules.
                 pop_size = operator.index(a.item())
             except TypeError:
-                raise ValueError("a must be 1-dimensional or an integer")
+                raise ValueError("a must an array or an integer")
             if pop_size <= 0 and np.prod(size) != 0:
-                raise ValueError("a must be greater than 0 unless no samples are taken")
+                raise ValueError("a must be a positive integer unless no"
+                                 "samples are taken")
         else:
             pop_size = a.shape[axis]
             if pop_size == 0 and np.prod(size) != 0:
-                raise ValueError("'a' cannot be empty unless no samples are taken")
+                raise ValueError("a cannot be empty unless no samples are"
+                                 "taken")
 
         if p is not None:
             d = len(p)
@@ -741,9 +635,9 @@ cdef class Generator:
             pix = <double*>np.PyArray_DATA(p)
 
             if p.ndim != 1:
-                raise ValueError("'p' must be 1-dimensional")
+                raise ValueError("p must be 1-dimensional")
             if p.size != pop_size:
-                raise ValueError("'a' and 'p' must have same size")
+                raise ValueError("a and p must have same size")
             p_sum = kahan_sum(pix, d)
             if np.isnan(p_sum):
                 raise ValueError("probabilities contain NaN")
@@ -765,13 +659,14 @@ cdef class Generator:
                 cdf /= cdf[-1]
                 uniform_samples = self.random(shape)
                 idx = cdf.searchsorted(uniform_samples, side='right')
-                idx = np.array(idx, copy=False, dtype=np.int64)  # searchsorted returns a scalar
+                # searchsorted returns a scalar
+                idx = np.array(idx, copy=False, dtype=np.int64)
             else:
                 idx = self.integers(0, pop_size, size=shape, dtype=np.int64)
         else:
             if size > pop_size:
                 raise ValueError("Cannot take a larger sample than "
-                                 "population when 'replace=False'")
+                                 "population when replace is False")
             elif size < 0:
                 raise ValueError("negative dimensions are not allowed")
 
@@ -2908,7 +2803,6 @@ cdef class Generator:
                 it = np.PyArray_MultiIterNew2(p_arr, n_arr)
                 randoms = <np.ndarray>np.empty(it.shape, np.int64)
 
-            randoms_data = <np.int64_t *>np.PyArray_DATA(randoms)
             cnt = np.PyArray_SIZE(randoms)
 
             it = np.PyArray_MultiIterNew3(randoms, p_arr, n_arr)
@@ -2950,14 +2844,14 @@ cdef class Generator:
 
         Samples are drawn from a negative binomial distribution with specified
         parameters, `n` successes and `p` probability of success where `n`
-        is > 0 and `p` is in the interval [0, 1].
+        is > 0 and `p` is in the interval (0, 1].
 
         Parameters
         ----------
         n : float or array_like of floats
             Parameter of the distribution, > 0.
         p : float or array_like of floats
-            Parameter of the distribution, >= 0 and <=1.
+            Parameter of the distribution. Must satisfy 0 < p <= 1.
         size : int or tuple of ints, optional
             Output shape.  If the given shape is, e.g., ``(m, n, k)``, then
             ``m * n * k`` samples are drawn.  If size is ``None`` (default),
@@ -3015,7 +2909,7 @@ cdef class Generator:
         """
         return disc(&random_negative_binomial, &self._bitgen, size, self.lock, 2, 0,
                     n, 'n', CONS_POSITIVE_NOT_NAN,
-                    p, 'p', CONS_BOUNDED_0_1,
+                    p, 'p', CONS_BOUNDED_GT_0_1,
                     0.0, '', CONS_NONE)
 
     def poisson(self, lam=1.0, size=None):
@@ -4005,7 +3899,7 @@ cdef class Generator:
                                         total, num_colors, colors_ptr, nsamp,
                                         num_variates, variates_ptr)
             if result == -1:
-                raise MemoryError("Insufficent memory for multivariate_"
+                raise MemoryError("Insufficient memory for multivariate_"
                                   "hypergeometric with method='count' and "
                                   "sum(colors)=%d" % total)
         else:
@@ -4113,10 +4007,12 @@ cdef class Generator:
         # return val
 
         cdef np.npy_intp k, totsize, i, j
-        cdef np.ndarray alpha_arr, val_arr
+        cdef np.ndarray alpha_arr, val_arr, alpha_csum_arr
+        cdef double csum
         cdef double *alpha_data
+        cdef double *alpha_csum_data
         cdef double *val_data
-        cdef double acc, invacc
+        cdef double acc, invacc, v
 
         k = len(alpha)
         alpha_arr = <np.ndarray>np.PyArray_FROMANY(
@@ -4140,17 +4036,74 @@ cdef class Generator:
 
         i = 0
         totsize = np.PyArray_SIZE(val_arr)
-        with self.lock, nogil:
-            while i < totsize:
-                acc = 0.0
-                for j in range(k):
-                    val_data[i+j] = random_standard_gamma(&self._bitgen,
-                                                              alpha_data[j])
-                    acc = acc + val_data[i + j]
-                invacc = 1/acc
-                for j in range(k):
-                    val_data[i + j] = val_data[i + j] * invacc
-                i = i + k
+
+        # Select one of the following two algorithms for the generation
+        #  of Dirichlet random variates (RVs)
+        #
+        # A) Small alpha case: Use the stick-breaking approach with beta
+        #    random variates (RVs).
+        # B) Standard case: Perform unit normalisation of a vector
+        #    of gamma random variates
+        #
+        # A) prevents NaNs resulting from 0/0 that may occur in B)
+        # when all values in the vector ':math:\\alpha' are smaller
+        # than 1, then there is a nonzero probability that all
+        # generated gamma RVs will be 0. When that happens, the
+        # normalization process ends up computing 0/0, giving nan. A)
+        # does not use divisions, so that a situation in which 0/0 has
+        # to be computed cannot occur. A) is slower than B) as
+        # generation of beta RVs is slower than generation of gamma
+        # RVs. A) is selected whenever `alpha.max() < t`, where `t <
+        # 1` is a threshold that controls the probability of
+        # generating a NaN value when B) is used. For a given
+        # threshold `t` this probability can be bounded by
+        # `gammainc(t, d)` where `gammainc` is the regularized
+        # incomplete gamma function and `d` is the smallest positive
+        # floating point number that can be represented with a given
+        # precision. For the chosen threshold `t=0.1` this probability
+        # is smaller than `1.8e-31` for double precision floating
+        # point numbers.
+
+        if (k > 0) and (alpha_arr.max() < 0.1):
+            # Small alpha case: Use stick-breaking approach with beta
+            # random variates (RVs).
+            # alpha_csum_data will hold the cumulative sum, right to
+            # left, of alpha_arr.
+            # Use a numpy array for memory management only.  We could just as
+            # well have malloc'd alpha_csum_data.  alpha_arr is a C-contiguous
+            # double array, therefore so is alpha_csum_arr.
+            alpha_csum_arr = np.empty_like(alpha_arr)
+            alpha_csum_data = <double*>np.PyArray_DATA(alpha_csum_arr)
+            csum = 0.0
+            for j in range(k - 1, -1, -1):
+                csum += alpha_data[j]
+                alpha_csum_data[j] = csum
+
+            with self.lock, nogil:
+                while i < totsize:
+                    acc = 1.
+                    for j in range(k - 1):
+                        v = random_beta(&self._bitgen, alpha_data[j],
+                                        alpha_csum_data[j + 1])
+                        val_data[i + j] = acc * v
+                        acc *= (1. - v)
+                    val_data[i + k - 1] = acc
+                    i = i + k
+
+        else:
+            # Standard case: Unit normalisation of a vector of gamma random
+            # variates
+            with self.lock, nogil:
+                while i < totsize:
+                    acc = 0.
+                    for j in range(k):
+                        val_data[i + j] = random_standard_gamma(&self._bitgen,
+                                                                alpha_data[j])
+                        acc = acc + val_data[i + j]
+                    invacc = 1. / acc
+                    for j in range(k):
+                        val_data[i + j] = val_data[i + j] * invacc
+                    i = i + k
 
         return diric
 
@@ -4335,7 +4288,7 @@ cdef class Generator:
         >>> rng.permutation("abc")
         Traceback (most recent call last):
             ...
-        numpy.AxisError: x must be an integer or at least 1-dimensional
+        numpy.AxisError: axis 0 is out of bounds for array of dimension 0
 
         >>> arr = np.arange(9).reshape((3, 3))
         >>> rng.permutation(arr, axis=1)
index 919a96a4c43ebce24973e96a7aeb21dc360ea5ed..16a377cc63b9105bed93a1ee1450f58c7b19b271 100644 (file)
@@ -226,6 +226,23 @@ cdef class MT19937(BitGenerator):
         -------
         bit_generator : MT19937
             New instance of generator jumped iter times
+
+        Notes
+        -----
+        The jump step is computed using a modified version of Matsumoto's
+        implementation of Horner's method. The step polynomial is precomputed
+        to perform 2**128 steps. The jumped state has been verified to match
+        the state produced using Matsumoto's original code.
+
+        References
+        ----------
+        .. [1] Matsumoto, M, Generating multiple disjoint streams of
+           pseudorandom number sequences.  Accessed on: May 6, 2020.
+           http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/JUMP/
+        .. [2] Hiroshi Haramoto, Makoto Matsumoto, Takuji Nishimura, François
+           Panneton, Pierre L\'Ecuyer, "Efficient Jump Ahead for F2-Linear
+           Random Number Generators", INFORMS JOURNAL ON COMPUTING, Vol. 20,
+           No. 3, Summer 2008, pp. 385-390.
         """
         cdef MT19937 bit_generator
 
index 05d27db5c87b86658b29ff5aaac49de795755005..605aae4bcb21907abffa4f96a20b13435814f7fb 100644 (file)
@@ -38,7 +38,7 @@ cdef double pcg64_double(void* st) nogil:
 
 cdef class PCG64(BitGenerator):
     """
-    PCG64(seed_seq=None)
+    PCG64(seed=None)
 
     BitGenerator for the PCG-64 pseudo-random number generator.
 
diff --git a/numpy/random/bit_generator.pxd b/numpy/random/bit_generator.pxd
new file mode 100644 (file)
index 0000000..bd5e47a
--- /dev/null
@@ -0,0 +1,35 @@
+cimport numpy as np
+from libc.stdint cimport uint32_t, uint64_t
+
+cdef extern from "numpy/random/bitgen.h":
+    struct bitgen:
+        void *state
+        uint64_t (*next_uint64)(void *st) nogil
+        uint32_t (*next_uint32)(void *st) nogil
+        double (*next_double)(void *st) nogil
+        uint64_t (*next_raw)(void *st) nogil
+
+    ctypedef bitgen bitgen_t
+
+cdef class BitGenerator():
+    cdef readonly object _seed_seq
+    cdef readonly object lock
+    cdef bitgen_t _bitgen
+    cdef readonly object _ctypes
+    cdef readonly object _cffi
+    cdef readonly object capsule
+
+
+cdef class SeedSequence():
+    cdef readonly object entropy
+    cdef readonly tuple spawn_key
+    cdef readonly uint32_t pool_size
+    cdef readonly object pool
+    cdef readonly uint32_t n_children_spawned
+
+    cdef mix_entropy(self, np.ndarray[np.npy_uint32, ndim=1] mixer,
+                     np.ndarray[np.npy_uint32, ndim=1] entropy_array)
+    cdef get_assembled_entropy(self)
+
+cdef class SeedlessSequence():
+    pass
diff --git a/numpy/random/bit_generator.pyx b/numpy/random/bit_generator.pyx
new file mode 100644 (file)
index 0000000..3c52a99
--- /dev/null
@@ -0,0 +1,635 @@
+"""
+BitGenerator base class and SeedSequence used to seed the BitGenerators.
+
+SeedSequence is derived from Melissa E. O'Neill's C++11 `std::seed_seq`
+implementation, as it has a lot of nice properties that we want.
+
+https://gist.github.com/imneme/540829265469e673d045
+http://www.pcg-random.org/posts/developing-a-seed_seq-alternative.html
+
+The MIT License (MIT)
+
+Copyright (c) 2015 Melissa E. O'Neill
+Copyright (c) 2019 NumPy Developers
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+"""
+
+import abc
+import sys
+from itertools import cycle
+import re
+
+try:
+    from secrets import randbits
+except ImportError:
+    # secrets unavailable on python 3.5 and before
+    from random import SystemRandom
+    randbits = SystemRandom().getrandbits
+
+try:
+    from threading import Lock
+except ImportError:
+    from dummy_threading import Lock
+
+from cpython.pycapsule cimport PyCapsule_New
+
+import numpy as np
+cimport numpy as np
+
+from ._common cimport (random_raw, benchmark, prepare_ctypes, prepare_cffi)
+
+__all__ = ['SeedSequence', 'BitGenerator']
+
+np.import_array()
+
+DECIMAL_RE = re.compile(r'[0-9]+')
+
+cdef uint32_t DEFAULT_POOL_SIZE = 4  # Appears also in docstring for pool_size
+cdef uint32_t INIT_A = 0x43b0d7e5
+cdef uint32_t MULT_A = 0x931e8875
+cdef uint32_t INIT_B = 0x8b51f9dd
+cdef uint32_t MULT_B = 0x58f38ded
+cdef uint32_t MIX_MULT_L = 0xca01f9dd
+cdef uint32_t MIX_MULT_R = 0x4973f715
+cdef uint32_t XSHIFT = np.dtype(np.uint32).itemsize * 8 // 2
+cdef uint32_t MASK32 = 0xFFFFFFFF
+
+def _int_to_uint32_array(n):
+    arr = []
+    if n < 0:
+        raise ValueError("expected non-negative integer")
+    if n == 0:
+        arr.append(np.uint32(n))
+    if isinstance(n, np.unsignedinteger):
+        # Cannot do n & MASK32, convert to python int
+        n = int(n)
+    while n > 0:
+        arr.append(np.uint32(n & MASK32))
+        n //= (2**32)
+    return np.array(arr, dtype=np.uint32)
+
+def _coerce_to_uint32_array(x):
+    """ Coerce an input to a uint32 array.
+
+    If a `uint32` array, pass it through directly.
+    If a non-negative integer, then break it up into `uint32` words, lowest
+    bits first.
+    If a string starting with "0x", then interpret as a hex integer, as above.
+    If a string of decimal digits, interpret as a decimal integer, as above.
+    If a sequence of ints or strings, interpret each element as above and
+    concatenate.
+
+    Note that the handling of `int64` or `uint64` arrays are not just
+    straightforward views as `uint32` arrays. If an element is small enough to
+    fit into a `uint32`, then it will only take up one `uint32` element in the
+    output. This is to make sure that the interpretation of a sequence of
+    integers is the same regardless of numpy's default integer type, which
+    differs on different platforms.
+
+    Parameters
+    ----------
+    x : int, str, sequence of int or str
+
+    Returns
+    -------
+    seed_array : uint32 array
+
+    Examples
+    --------
+    >>> import numpy as np
+    >>> from numpy.random.bit_generator import _coerce_to_uint32_array
+    >>> _coerce_to_uint32_array(12345)
+    array([12345], dtype=uint32)
+    >>> _coerce_to_uint32_array('12345')
+    array([12345], dtype=uint32)
+    >>> _coerce_to_uint32_array('0x12345')
+    array([74565], dtype=uint32)
+    >>> _coerce_to_uint32_array([12345, '67890'])
+    array([12345, 67890], dtype=uint32)
+    >>> _coerce_to_uint32_array(np.array([12345, 67890], dtype=np.uint32))
+    array([12345, 67890], dtype=uint32)
+    >>> _coerce_to_uint32_array(np.array([12345, 67890], dtype=np.int64))
+    array([12345, 67890], dtype=uint32)
+    >>> _coerce_to_uint32_array([12345, 0x10deadbeef, 67890, 0xdeadbeef])
+    array([     12345, 3735928559,         16,      67890, 3735928559],
+          dtype=uint32)
+    >>> _coerce_to_uint32_array(1234567890123456789012345678901234567890)
+    array([3460238034, 2898026390, 3235640248, 2697535605,          3],
+          dtype=uint32)
+    """
+    if isinstance(x, np.ndarray) and x.dtype == np.dtype(np.uint32):
+        return x.copy()
+    elif isinstance(x, str):
+        if x.startswith('0x'):
+            x = int(x, base=16)
+        elif DECIMAL_RE.match(x):
+            x = int(x)
+        else:
+            raise ValueError("unrecognized seed string")
+    if isinstance(x, (int, np.integer)):
+        return _int_to_uint32_array(x)
+    elif isinstance(x, (float, np.inexact)):
+        raise TypeError('seed must be integer')
+    else:
+        if len(x) == 0:
+            return np.array([], dtype=np.uint32)
+        # Should be a sequence of interpretable-as-ints. Convert each one to
+        # a uint32 array and concatenate.
+        subseqs = [_coerce_to_uint32_array(v) for v in x]
+        return np.concatenate(subseqs)
+
+
+cdef uint32_t hashmix(uint32_t value, uint32_t * hash_const):
+    # We are modifying the multiplier as we go along, so it is input-output
+    value ^= hash_const[0]
+    hash_const[0] *= MULT_A
+    value *=  hash_const[0]
+    value ^= value >> XSHIFT
+    return value
+
+cdef uint32_t mix(uint32_t x, uint32_t y):
+    cdef uint32_t result = (MIX_MULT_L * x - MIX_MULT_R * y)
+    result ^= result >> XSHIFT
+    return result
+
+
+class ISeedSequence(abc.ABC):
+    """
+    Abstract base class for seed sequences.
+
+    ``BitGenerator`` implementations should treat any object that adheres to
+    this interface as a seed sequence.
+
+    See Also
+    --------
+    SeedSequence, SeedlessSeedSequence
+    """
+
+    @abc.abstractmethod
+    def generate_state(self, n_words, dtype=np.uint32):
+        """
+        generate_state(n_words, dtype=np.uint32)
+
+        Return the requested number of words for PRNG seeding.
+
+        A BitGenerator should call this method in its constructor with
+        an appropriate `n_words` parameter to properly seed itself.
+
+        Parameters
+        ----------
+        n_words : int
+        dtype : np.uint32 or np.uint64, optional
+            The size of each word. This should only be either `uint32` or
+            `uint64`. Strings (`'uint32'`, `'uint64'`) are fine. Note that
+            requesting `uint64` will draw twice as many bits as `uint32` for
+            the same `n_words`. This is a convenience for `BitGenerator`s that
+            express their states as `uint64` arrays.
+
+        Returns
+        -------
+        state : uint32 or uint64 array, shape=(n_words,)
+        """
+
+
+class ISpawnableSeedSequence(ISeedSequence):
+    """
+    Abstract base class for seed sequences that can spawn.
+    """
+
+    @abc.abstractmethod
+    def spawn(self, n_children):
+        """
+        spawn(n_children)
+
+        Spawn a number of child `SeedSequence` s by extending the
+        `spawn_key`.
+
+        Parameters
+        ----------
+        n_children : int
+
+        Returns
+        -------
+        seqs : list of `SeedSequence` s
+        """
+
+
+cdef class SeedlessSeedSequence():
+    """
+    A seed sequence for BitGenerators with no need for seed state.
+
+    See Also
+    --------
+    SeedSequence, ISeedSequence
+    """
+
+    def generate_state(self, n_words, dtype=np.uint32):
+        raise NotImplementedError('seedless SeedSequences cannot generate state')
+
+    def spawn(self, n_children):
+        return [self] * n_children
+
+
+# We cannot directly subclass a `cdef class` type from an `ABC` in Cython, so
+# we must register it after the fact.
+ISpawnableSeedSequence.register(SeedlessSeedSequence)
+
+
+cdef class SeedSequence():
+    """
+    SeedSequence(entropy=None, *, spawn_key=(), pool_size=4)
+
+    SeedSequence mixes sources of entropy in a reproducible way to set the
+    initial state for independent and very probably non-overlapping
+    BitGenerators.
+
+    Once the SeedSequence is instantiated, you can call the `generate_state`
+    method to get an appropriately sized seed. Calling `spawn(n) <spawn>` will
+    create ``n`` SeedSequences that can be used to seed independent
+    BitGenerators, i.e. for different threads.
+
+    Parameters
+    ----------
+    entropy : {None, int, sequence[int]}, optional
+        The entropy for creating a `SeedSequence`.
+    spawn_key : {(), sequence[int]}, optional
+        A third source of entropy, used internally when calling
+        `SeedSequence.spawn`
+    pool_size : {int}, optional
+        Size of the pooled entropy to store. Default is 4 to give a 128-bit
+        entropy pool. 8 (for 256 bits) is another reasonable choice if working
+        with larger PRNGs, but there is very little to be gained by selecting
+        another value.
+    n_children_spawned : {int}, optional
+        The number of children already spawned. Only pass this if
+        reconstructing a `SeedSequence` from a serialized form.
+
+    Notes
+    -----
+
+    Best practice for achieving reproducible bit streams is to use
+    the default ``None`` for the initial entropy, and then use
+    `SeedSequence.entropy` to log/pickle the `entropy` for reproducibility:
+
+    >>> sq1 = np.random.SeedSequence()
+    >>> sq1.entropy
+    243799254704924441050048792905230269161  # random
+    >>> sq2 = np.random.SeedSequence(sq1.entropy)
+    >>> np.all(sq1.generate_state(10) == sq2.generate_state(10))
+    True
+    """
+
+    def __init__(self, entropy=None, *, spawn_key=(),
+                 pool_size=DEFAULT_POOL_SIZE, n_children_spawned=0):
+        if pool_size < DEFAULT_POOL_SIZE:
+            raise ValueError("The size of the entropy pool should be at least "
+                             f"{DEFAULT_POOL_SIZE}")
+        if entropy is None:
+            entropy = randbits(pool_size * 32)
+        elif not isinstance(entropy, (int, np.integer, list, tuple, range,
+                                      np.ndarray)):
+            raise TypeError('SeedSequence expects int or sequence of ints for '
+                            'entropy not {}'.format(entropy))
+        self.entropy = entropy
+        self.spawn_key = tuple(spawn_key)
+        self.pool_size = pool_size
+        self.n_children_spawned = n_children_spawned
+
+        self.pool = np.zeros(pool_size, dtype=np.uint32)
+        self.mix_entropy(self.pool, self.get_assembled_entropy())
+
+    def __repr__(self):
+        lines = [
+            f'{type(self).__name__}(',
+            f'    entropy={self.entropy!r},',
+        ]
+        # Omit some entries if they are left as the defaults in order to
+        # simplify things.
+        if self.spawn_key:
+            lines.append(f'    spawn_key={self.spawn_key!r},')
+        if self.pool_size != DEFAULT_POOL_SIZE:
+            lines.append(f'    pool_size={self.pool_size!r},')
+        if self.n_children_spawned != 0:
+            lines.append(f'    n_children_spawned={self.n_children_spawned!r},')
+        lines.append(')')
+        text = '\n'.join(lines)
+        return text
+
+    @property
+    def state(self):
+        return {k:getattr(self, k) for k in
+                ['entropy', 'spawn_key', 'pool_size',
+                 'n_children_spawned']
+                if getattr(self, k) is not None}
+
+    cdef mix_entropy(self, np.ndarray[np.npy_uint32, ndim=1] mixer,
+                     np.ndarray[np.npy_uint32, ndim=1] entropy_array):
+        """ Mix in the given entropy to mixer.
+
+        Parameters
+        ----------
+        mixer : 1D uint32 array, modified in-place
+        entropy_array : 1D uint32 array
+        """
+        cdef uint32_t hash_const[1]
+        hash_const[0] = INIT_A
+
+        # Add in the entropy up to the pool size.
+        for i in range(len(mixer)):
+            if i < len(entropy_array):
+                mixer[i] = hashmix(entropy_array[i], hash_const)
+            else:
+                # Our pool size is bigger than our entropy, so just keep
+                # running the hash out.
+                mixer[i] = hashmix(0, hash_const)
+
+        # Mix all bits together so late bits can affect earlier bits.
+        for i_src in range(len(mixer)):
+            for i_dst in range(len(mixer)):
+                if i_src != i_dst:
+                    mixer[i_dst] = mix(mixer[i_dst],
+                                       hashmix(mixer[i_src], hash_const))
+
+        # Add any remaining entropy, mixing each new entropy word with each
+        # pool word.
+        for i_src in range(len(mixer), len(entropy_array)):
+            for i_dst in range(len(mixer)):
+                mixer[i_dst] = mix(mixer[i_dst],
+                                   hashmix(entropy_array[i_src], hash_const))
+
+    cdef get_assembled_entropy(self):
+        """ Convert and assemble all entropy sources into a uniform uint32
+        array.
+
+        Returns
+        -------
+        entropy_array : 1D uint32 array
+        """
+        # Convert run-entropy and the spawn key into uint32
+        # arrays and concatenate them.
+
+        # We MUST have at least some run-entropy. The others are optional.
+        assert self.entropy is not None
+        run_entropy = _coerce_to_uint32_array(self.entropy)
+        spawn_entropy = _coerce_to_uint32_array(self.spawn_key)
+        if len(spawn_entropy) > 0 and len(run_entropy) < self.pool_size:
+            # Explicitly fill out the entropy with 0s to the pool size to avoid
+            # conflict with spawn keys. We changed this in 1.19.0 to fix
+            # gh-16539. In order to preserve stream-compatibility with
+            # unspawned SeedSequences with small entropy inputs, we only do
+            # this when a spawn_key is specified.
+            diff = self.pool_size - len(run_entropy)
+            run_entropy = np.concatenate(
+                [run_entropy, np.zeros(diff, dtype=np.uint32)])
+        entropy_array = np.concatenate([run_entropy, spawn_entropy])
+        return entropy_array
+
+    @np.errstate(over='ignore')
+    def generate_state(self, n_words, dtype=np.uint32):
+        """
+        generate_state(n_words, dtype=np.uint32)
+
+        Return the requested number of words for PRNG seeding.
+
+        A BitGenerator should call this method in its constructor with
+        an appropriate `n_words` parameter to properly seed itself.
+
+        Parameters
+        ----------
+        n_words : int
+        dtype : np.uint32 or np.uint64, optional
+            The size of each word. This should only be either `uint32` or
+            `uint64`. Strings (`'uint32'`, `'uint64'`) are fine. Note that
+            requesting `uint64` will draw twice as many bits as `uint32` for
+            the same `n_words`. This is a convenience for `BitGenerator`s that
+            express their states as `uint64` arrays.
+
+        Returns
+        -------
+        state : uint32 or uint64 array, shape=(n_words,)
+        """
+        cdef uint32_t hash_const = INIT_B
+        cdef uint32_t data_val
+
+        out_dtype = np.dtype(dtype)
+        if out_dtype == np.dtype(np.uint32):
+            pass
+        elif out_dtype == np.dtype(np.uint64):
+            n_words *= 2
+        else:
+            raise ValueError("only support uint32 or uint64")
+        state = np.zeros(n_words, dtype=np.uint32)
+        src_cycle = cycle(self.pool)
+        for i_dst in range(n_words):
+            data_val = next(src_cycle)
+            data_val ^= hash_const
+            hash_const *= MULT_B
+            data_val *= hash_const
+            data_val ^= data_val >> XSHIFT
+            state[i_dst] = data_val
+        if out_dtype == np.dtype(np.uint64):
+            # For consistency across different endiannesses, view first as
+            # little-endian then convert the values to the native endianness.
+            state = state.astype('<u4').view('<u8').astype(np.uint64)
+        return state
+
+    def spawn(self, n_children):
+        """
+        spawn(n_children)
+
+        Spawn a number of child `SeedSequence` s by extending the
+        `spawn_key`.
+
+        Parameters
+        ----------
+        n_children : int
+
+        Returns
+        -------
+        seqs : list of `SeedSequence` s
+        """
+        cdef uint32_t i
+
+        seqs = []
+        for i in range(self.n_children_spawned,
+                       self.n_children_spawned + n_children):
+            seqs.append(type(self)(
+                self.entropy,
+                spawn_key=self.spawn_key + (i,),
+                pool_size=self.pool_size,
+            ))
+        self.n_children_spawned += n_children
+        return seqs
+
+
+ISpawnableSeedSequence.register(SeedSequence)
+
+
+cdef class BitGenerator():
+    """
+    BitGenerator(seed=None)
+
+    Base Class for generic BitGenerators, which provide a stream
+    of random bits based on different algorithms. Must be overridden.
+
+    Parameters
+    ----------
+    seed : {None, int, array_like[ints], SeedSequence}, optional
+        A seed to initialize the `BitGenerator`. If None, then fresh,
+        unpredictable entropy will be pulled from the OS. If an ``int`` or
+        ``array_like[ints]`` is passed, then it will be passed to
+        ~`numpy.random.SeedSequence` to derive the initial `BitGenerator` state.
+        One may also pass in a `SeedSequence` instance.
+
+    Attributes
+    ----------
+    lock : threading.Lock
+        Lock instance that is shared so that the same BitGenerator can
+        be used in multiple Generators without corrupting the state. Code that
+        generates values from a bit generator should hold the bit generator's
+        lock.
+
+    See Also
+    -------
+    SeedSequence
+    """
+
+    def __init__(self, seed=None):
+        self.lock = Lock()
+        self._bitgen.state = <void *>0
+        if type(self) is BitGenerator:
+            raise NotImplementedError('BitGenerator is a base class and cannot be instantized')
+
+        self._ctypes = None
+        self._cffi = None
+
+        cdef const char *name = "BitGenerator"
+        self.capsule = PyCapsule_New(<void *>&self._bitgen, name, NULL)
+        if not isinstance(seed, ISeedSequence):
+            seed = SeedSequence(seed)
+        self._seed_seq = seed
+
+    # Pickling support:
+    def __getstate__(self):
+        return self.state
+
+    def __setstate__(self, state):
+        self.state = state
+
+    def __reduce__(self):
+        from ._pickle import __bit_generator_ctor
+        return __bit_generator_ctor, (self.state['bit_generator'],), self.state
+
+    @property
+    def state(self):
+        """
+        Get or set the PRNG state
+
+        The base BitGenerator.state must be overridden by a subclass
+
+        Returns
+        -------
+        state : dict
+            Dictionary containing the information required to describe the
+            state of the PRNG
+        """
+        raise NotImplementedError('Not implemented in base BitGenerator')
+
+    @state.setter
+    def state(self, value):
+        raise NotImplementedError('Not implemented in base BitGenerator')
+
+    def random_raw(self, size=None, output=True):
+        """
+        random_raw(self, size=None)
+
+        Return randoms as generated by the underlying BitGenerator
+
+        Parameters
+        ----------
+        size : int or tuple of ints, optional
+            Output shape.  If the given shape is, e.g., ``(m, n, k)``, then
+            ``m * n * k`` samples are drawn.  Default is None, in which case a
+            single value is returned.
+        output : bool, optional
+            Output values.  Used for performance testing since the generated
+            values are not returned.
+
+        Returns
+        -------
+        out : uint or ndarray
+            Drawn samples.
+
+        Notes
+        -----
+        This method directly exposes the the raw underlying pseudo-random
+        number generator. All values are returned as unsigned 64-bit
+        values irrespective of the number of bits produced by the PRNG.
+
+        See the class docstring for the number of bits returned.
+        """
+        return random_raw(&self._bitgen, self.lock, size, output)
+
+    def _benchmark(self, Py_ssize_t cnt, method=u'uint64'):
+        '''Used in tests'''
+        return benchmark(&self._bitgen, self.lock, cnt, method)
+
+    @property
+    def ctypes(self):
+        """
+        ctypes interface
+
+        Returns
+        -------
+        interface : namedtuple
+            Named tuple containing ctypes wrapper
+
+            * state_address - Memory address of the state struct
+            * state - pointer to the state struct
+            * next_uint64 - function pointer to produce 64 bit integers
+            * next_uint32 - function pointer to produce 32 bit integers
+            * next_double - function pointer to produce doubles
+            * bitgen - pointer to the bit generator struct
+        """
+        if self._ctypes is None:
+            self._ctypes = prepare_ctypes(&self._bitgen)
+
+        return self._ctypes
+
+    @property
+    def cffi(self):
+        """
+        CFFI interface
+
+        Returns
+        -------
+        interface : namedtuple
+            Named tuple containing CFFI wrapper
+
+            * state_address - Memory address of the state struct
+            * state - pointer to the state struct
+            * next_uint64 - function pointer to produce 64 bit integers
+            * next_uint32 - function pointer to produce 32 bit integers
+            * next_double - function pointer to produce doubles
+            * bitgen - pointer to the bit generator struct
+        """
+        if self._cffi is None:
+            self._cffi = prepare_cffi(&self._bitgen)
+        return self._cffi
diff --git a/numpy/random/c_distributions.pxd b/numpy/random/c_distributions.pxd
new file mode 100644 (file)
index 0000000..6f905ed
--- /dev/null
@@ -0,0 +1,114 @@
+#!python
+#cython: wraparound=False, nonecheck=False, boundscheck=False, cdivision=True, language_level=3
+from numpy cimport npy_intp
+
+from libc.stdint cimport (uint64_t, int32_t, int64_t)
+from numpy.random cimport bitgen_t
+
+cdef extern from "numpy/random/distributions.h":
+
+    struct s_binomial_t:
+        int has_binomial
+        double psave
+        int64_t nsave
+        double r
+        double q
+        double fm
+        int64_t m
+        double p1
+        double xm
+        double xl
+        double xr
+        double c
+        double laml
+        double lamr
+        double p2
+        double p3
+        double p4
+
+    ctypedef s_binomial_t binomial_t
+
+    double random_standard_uniform(bitgen_t *bitgen_state) nogil
+    void random_standard_uniform_fill(bitgen_t* bitgen_state, npy_intp cnt, double *out) nogil
+    double random_standard_exponential(bitgen_t *bitgen_state) nogil
+    double random_standard_exponential_f(bitgen_t *bitgen_state) nogil
+    void random_standard_exponential_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) nogil
+    void random_standard_exponential_fill_f(bitgen_t *bitgen_state, npy_intp cnt, double *out) nogil
+    void random_standard_exponential_inv_fill(bitgen_t *bitgen_state, npy_intp cnt, double *out) nogil
+    void random_standard_exponential_inv_fill_f(bitgen_t *bitgen_state, npy_intp cnt, double *out) nogil
+    double random_standard_normal(bitgen_t* bitgen_state) nogil
+    void random_standard_normal_fill(bitgen_t *bitgen_state, npy_intp count, double *out) nogil
+    void random_standard_normal_fill_f(bitgen_t *bitgen_state, npy_intp count, float *out) nogil
+    double random_standard_gamma(bitgen_t *bitgen_state, double shape) nogil
+
+    float random_standard_uniform_f(bitgen_t *bitgen_state) nogil
+    void random_standard_uniform_fill_f(bitgen_t* bitgen_state, npy_intp cnt, float *out) nogil
+    float random_standard_normal_f(bitgen_t* bitgen_state) nogil
+    float random_standard_gamma_f(bitgen_t *bitgen_state, float shape) nogil
+
+    int64_t random_positive_int64(bitgen_t *bitgen_state) nogil
+    int32_t random_positive_int32(bitgen_t *bitgen_state) nogil
+    int64_t random_positive_int(bitgen_t *bitgen_state) nogil
+    uint64_t random_uint(bitgen_t *bitgen_state) nogil
+
+    double random_normal(bitgen_t *bitgen_state, double loc, double scale) nogil
+
+    double random_gamma(bitgen_t *bitgen_state, double shape, double scale) nogil
+    float random_gamma_f(bitgen_t *bitgen_state, float shape, float scale) nogil
+
+    double random_exponential(bitgen_t *bitgen_state, double scale) nogil
+    double random_uniform(bitgen_t *bitgen_state, double lower, double range) nogil
+    double random_beta(bitgen_t *bitgen_state, double a, double b) nogil
+    double random_chisquare(bitgen_t *bitgen_state, double df) nogil
+    double random_f(bitgen_t *bitgen_state, double dfnum, double dfden) nogil
+    double random_standard_cauchy(bitgen_t *bitgen_state) nogil
+    double random_pareto(bitgen_t *bitgen_state, double a) nogil
+    double random_weibull(bitgen_t *bitgen_state, double a) nogil
+    double random_power(bitgen_t *bitgen_state, double a) nogil
+    double random_laplace(bitgen_t *bitgen_state, double loc, double scale) nogil
+    double random_gumbel(bitgen_t *bitgen_state, double loc, double scale) nogil
+    double random_logistic(bitgen_t *bitgen_state, double loc, double scale) nogil
+    double random_lognormal(bitgen_t *bitgen_state, double mean, double sigma) nogil
+    double random_rayleigh(bitgen_t *bitgen_state, double mode) nogil
+    double random_standard_t(bitgen_t *bitgen_state, double df) nogil
+    double random_noncentral_chisquare(bitgen_t *bitgen_state, double df,
+                                       double nonc) nogil
+    double random_noncentral_f(bitgen_t *bitgen_state, double dfnum,
+                               double dfden, double nonc) nogil
+    double random_wald(bitgen_t *bitgen_state, double mean, double scale) nogil
+    double random_vonmises(bitgen_t *bitgen_state, double mu, double kappa) nogil
+    double random_triangular(bitgen_t *bitgen_state, double left, double mode,
+                             double right) nogil
+
+    int64_t random_poisson(bitgen_t *bitgen_state, double lam) nogil
+    int64_t random_negative_binomial(bitgen_t *bitgen_state, double n, double p) nogil
+    int64_t random_binomial(bitgen_t *bitgen_state, double p, int64_t n, binomial_t *binomial) nogil
+    int64_t random_logseries(bitgen_t *bitgen_state, double p) nogil
+    int64_t random_geometric_search(bitgen_t *bitgen_state, double p) nogil
+    int64_t random_geometric_inversion(bitgen_t *bitgen_state, double p) nogil
+    int64_t random_geometric(bitgen_t *bitgen_state, double p) nogil
+    int64_t random_zipf(bitgen_t *bitgen_state, double a) nogil
+    int64_t random_hypergeometric(bitgen_t *bitgen_state, int64_t good, int64_t bad,
+                                    int64_t sample) nogil
+
+    uint64_t random_interval(bitgen_t *bitgen_state, uint64_t max) nogil
+
+    # Generate random uint64 numbers in closed interval [off, off + rng].
+    uint64_t random_bounded_uint64(bitgen_t *bitgen_state,
+                                   uint64_t off, uint64_t rng,
+                                   uint64_t mask, bint use_masked) nogil
+
+    void random_multinomial(bitgen_t *bitgen_state, int64_t n, int64_t *mnix,
+                            double *pix, npy_intp d, binomial_t *binomial) nogil
+
+    int random_multivariate_hypergeometric_count(bitgen_t *bitgen_state,
+                          int64_t total,
+                          size_t num_colors, int64_t *colors,
+                          int64_t nsample,
+                          size_t num_variates, int64_t *variates) nogil
+    void random_multivariate_hypergeometric_marginals(bitgen_t *bitgen_state,
+                               int64_t total,
+                               size_t num_colors, int64_t *colors,
+                               int64_t nsample,
+                               size_t num_variates, int64_t *variates) nogil
+
index 0d86d1a3c5d0c4ccb1bbee86ae5fefcc6f22f99b..54d656e3bdb6c3b1bc8cbeaac16eaf1f94b64ab0 100644 (file)
@@ -251,6 +251,12 @@ cdef class RandomState:
 
         For more details, see `set_state`.
 
+        Parameters
+        ----------
+        legacy : bool, optional
+            Flag indicating to return a legacy tuple state when the BitGenerator
+            is MT19937, instead of a dict.
+
         Returns
         -------
         out : {tuple(str, ndarray of 624 uints, int, int, float), dict}
@@ -262,13 +268,9 @@ cdef class RandomState:
             4. an integer ``has_gauss``.
             5. a float ``cached_gaussian``.
 
-            If `legacy` is False, or the BitGenerator is not NT19937, then
+            If `legacy` is False, or the BitGenerator is not MT19937, then
             state is returned as a dictionary.
 
-        legacy : bool
-            Flag indicating the return a legacy tuple state when the BitGenerator
-            is MT19937.
-
         See Also
         --------
         set_state
@@ -805,7 +807,7 @@ cdef class RandomState:
 
         Generates a random sample from a given 1-D array
 
-                .. versionadded:: 1.7.0
+        .. versionadded:: 1.7.0
 
         .. note::
             New code should use the ``choice`` method of a ``default_rng()``
@@ -846,6 +848,11 @@ cdef class RandomState:
         randint, shuffle, permutation
         Generator.choice: which should be used in new code
 
+        Notes
+        -----
+        Sampling random rows from a 2-D array is not possible with this function,
+        but is possible with `Generator.choice` through its ``axis`` keyword.
+
         Examples
         --------
         Generate a uniform random sample from np.arange(5) of size 3:
@@ -946,7 +953,7 @@ cdef class RandomState:
                 raise ValueError("Cannot take a larger sample than "
                                  "population when 'replace=False'")
             elif size < 0:
-                raise ValueError("negative dimensions are not allowed")
+                raise ValueError("Negative dimensions are not allowed")
 
             if p is not None:
                 if np.count_nonzero(p > 0) < size:
@@ -1015,7 +1022,7 @@ cdef class RandomState:
             greater than or equal to low.  The default value is 0.
         high : float or array_like of floats
             Upper boundary of the output interval.  All values generated will be
-            less than high.  The default value is 1.0.
+            less than or equal to high.  The default value is 1.0.
         size : int or tuple of ints, optional
             Output shape.  If the given shape is, e.g., ``(m, n, k)``, then
             ``m * n * k`` samples are drawn.  If size is ``None`` (default),
@@ -1051,7 +1058,14 @@ cdef class RandomState:
         If ``high`` < ``low``, the results are officially undefined
         and may eventually raise an error, i.e. do not rely on this
         function to behave when passed arguments satisfying that
-        inequality condition.
+        inequality condition. The ``high`` limit may be included in the
+        returned array of floats due to floating-point rounding in the
+        equation ``low + (high-low) * random_sample()``. For example:
+
+        >>> x = np.float32(5*0.99999999)
+        >>> x
+        5.0
+
 
         Examples
         --------
@@ -3354,7 +3368,6 @@ cdef class RandomState:
                 it = np.PyArray_MultiIterNew2(p_arr, n_arr)
                 randoms = <np.ndarray>np.empty(it.shape, int)
 
-            randoms_data = <long *>np.PyArray_DATA(randoms)
             cnt = np.PyArray_SIZE(randoms)
 
             it = np.PyArray_MultiIterNew3(randoms, p_arr, n_arr)
index 1b093d6d381df21ff31c150760898119ac3f01e3..88ddb12687ea8ec8ee94135c5d921f54a96aee0b 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, print_function
-
 import os
 import platform
 import sys
@@ -33,12 +31,15 @@ def configuration(parent_package='', top_path=None):
                 ('_LARGEFILE64_SOURCE', '1')]
 
     defs.append(('NPY_NO_DEPRECATED_API', 0))
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
+    config.add_data_dir('tests/data')
     config.add_data_dir('_examples')
 
     EXTRA_LINK_ARGS = []
-    # Math lib
-    EXTRA_LIBRARIES = ['m'] if os.name != 'nt' else []
+    EXTRA_LIBRARIES = ['npyrandom']
+    if os.name != 'nt':
+        # Math lib
+        EXTRA_LIBRARIES.append('m')
     # Some bit generators exclude GCC inlining
     EXTRA_COMPILE_ARGS = ['-U__GNUC_GNU_INLINE__']
 
@@ -54,78 +55,88 @@ def configuration(parent_package='', top_path=None):
     PCG64_DEFS = []
     # One can force emulated 128-bit arithmetic if one wants.
     #PCG64_DEFS += [('PCG_FORCE_EMULATED_128BIT_MATH', '1')]
+    depends = ['__init__.pxd', 'c_distributions.pxd', 'bit_generator.pxd']
+
+    # npyrandom - a library like npymath
+    npyrandom_sources = [
+        'src/distributions/logfactorial.c',
+        'src/distributions/distributions.c',
+        'src/distributions/random_mvhg_count.c',
+        'src/distributions/random_mvhg_marginals.c',
+        'src/distributions/random_hypergeometric.c',
+    ]
+    config.add_installed_library('npyrandom',
+        sources=npyrandom_sources,
+        install_dir='lib',
+        build_info={
+            'include_dirs' : [],  # empty list required for creating npyrandom.h
+            'extra_compiler_args' : (['/GL-'] if is_msvc else []),
+        })
 
     for gen in ['mt19937']:
         # gen.pyx, src/gen/gen.c, src/gen/gen-jump.c
-        config.add_extension('_{0}'.format(gen),
-                             sources=['_{0}.c'.format(gen),
-                                      'src/{0}/{0}.c'.format(gen),
-                                      'src/{0}/{0}-jump.c'.format(gen)],
+        config.add_extension(f'_{gen}',
+                             sources=[f'_{gen}.c',
+                                      f'src/{gen}/{gen}.c',
+                                      f'src/{gen}/{gen}-jump.c'],
                              include_dirs=['.', 'src', join('src', gen)],
                              libraries=EXTRA_LIBRARIES,
                              extra_compile_args=EXTRA_COMPILE_ARGS,
                              extra_link_args=EXTRA_LINK_ARGS,
-                             depends=['_%s.pyx' % gen],
+                             depends=depends + [f'_{gen}.pyx'],
                              define_macros=defs,
                              )
     for gen in ['philox', 'pcg64', 'sfc64']:
         # gen.pyx, src/gen/gen.c
         _defs = defs + PCG64_DEFS if gen == 'pcg64' else defs
-        config.add_extension('_{0}'.format(gen),
-                             sources=['_{0}.c'.format(gen),
-                                      'src/{0}/{0}.c'.format(gen)],
+        config.add_extension(f'_{gen}',
+                             sources=[f'_{gen}.c',
+                                      f'src/{gen}/{gen}.c'],
                              include_dirs=['.', 'src', join('src', gen)],
                              libraries=EXTRA_LIBRARIES,
                              extra_compile_args=EXTRA_COMPILE_ARGS,
                              extra_link_args=EXTRA_LINK_ARGS,
-                             depends=['_%s.pyx' % gen, '_bit_generator.pyx',
-                                      '_bit_generator.pxd'],
+                             depends=depends + [f'_{gen}.pyx',
+                                   'bit_generator.pyx', 'bit_generator.pxd'],
                              define_macros=_defs,
                              )
-    for gen in ['_common', '_bit_generator']:
+    for gen in ['_common', 'bit_generator']:
         # gen.pyx
         config.add_extension(gen,
-                             sources=['{0}.c'.format(gen)],
+                             sources=[f'{gen}.c'],
                              libraries=EXTRA_LIBRARIES,
                              extra_compile_args=EXTRA_COMPILE_ARGS,
                              extra_link_args=EXTRA_LINK_ARGS,
                              include_dirs=['.', 'src'],
-                             depends=['%s.pyx' % gen, '%s.pxd' % gen,],
+                             depends=depends + [f'{gen}.pyx', f'{gen}.pxd',],
                              define_macros=defs,
                              )
-        config.add_data_files('{0}.pxd'.format(gen))
-    other_srcs = [
-        'src/distributions/logfactorial.c',
-        'src/distributions/distributions.c',
-        'src/distributions/random_mvhg_count.c',
-        'src/distributions/random_mvhg_marginals.c',
-        'src/distributions/random_hypergeometric.c',
-    ]
+        config.add_data_files(f'{gen}.pxd')
     for gen in ['_generator', '_bounded_integers']:
         # gen.pyx, src/distributions/distributions.c
         config.add_extension(gen,
-                             sources=['{0}.c'.format(gen)] + other_srcs,
+                             sources=[f'{gen}.c'],
                              libraries=EXTRA_LIBRARIES,
                              extra_compile_args=EXTRA_COMPILE_ARGS,
                              include_dirs=['.', 'src'],
                              extra_link_args=EXTRA_LINK_ARGS,
-                             depends=['%s.pyx' % gen],
+                             depends=depends + [f'{gen}.pyx'],
                              define_macros=defs,
                              )
     config.add_data_files('_bounded_integers.pxd')
     config.add_extension('mtrand',
                          sources=['mtrand.c',
                                   'src/legacy/legacy-distributions.c',
-                                  'src/distributions/logfactorial.c',
-                                  'src/distributions/distributions.c'],
+                                  'src/distributions/distributions.c',
+                                 ],
                          include_dirs=['.', 'src', 'src/legacy'],
-                         libraries=EXTRA_LIBRARIES,
+                         libraries=['m'] if os.name != 'nt' else [],
                          extra_compile_args=EXTRA_COMPILE_ARGS,
                          extra_link_args=EXTRA_LINK_ARGS,
-                         depends=['mtrand.pyx'],
+                         depends=depends + ['mtrand.pyx'],
                          define_macros=defs + LEGACY_DEFS,
                          )
-    config.add_data_files('__init__.pxd')
+    config.add_data_files(*depends)
     return config
 
 
index 7cbed1f9e0fc29df601eafdf0cae0c35fa217c0c..1d4ed978ed35c35a7a1a7c10db0e6ff163d1cda5 100644 (file)
@@ -1,8 +1,8 @@
+#include "numpy/random/distributions.h"
 #include <stdint.h>
 #include <stdlib.h>
 #include <stdbool.h>
 
-#include "numpy/random/distributions.h"
 
 /*
  *  random_multivariate_hypergeometric_count
index 809d129deb4effd9e2b75bd59b5842f79e7585f4..689a856711b653b09115845d2069490edf84aa5a 100644 (file)
@@ -1,9 +1,9 @@
+#include "numpy/random/distributions.h"
 #include <stdint.h>
 #include <stddef.h>
 #include <stdbool.h>
 #include <math.h>
 
-#include "numpy/random/distributions.h"
 #include "logfactorial.h"
 
 
index 46b28cf96bcb33960d9cd51aed1c9dd2995db9e6..1a83a4c2e23b7291bf2eea9e1c8eca337913b1dd 100644 (file)
@@ -10,28 +10,6 @@ unsigned long get_coef(unsigned long *pf, unsigned int deg) {
     return (0);
 }
 
-/* 32-bit function */
-/* set the coefficient of the polynomial pf with v */
-void set_coef(unsigned long *pf, unsigned int deg, unsigned long v) {
-  if (v != 0)
-    pf[deg >> 5] ^= (LSB << (deg & 0x1ful));
-  else
-    ;
-}
-
-void gray_code(unsigned long *h) {
-  unsigned int i, j = 1, l = 1, term = LL;
-
-  h[0] = 0;
-
-  for (i = 1; i <= QQ; i++) {
-    l = (l << 1);
-    term = (term >> 1);
-    for (; j < l; j++)
-      h[j] = h[l - j - 1] ^ term;
-  }
-}
-
 void copy_state(mt19937_state *target_state, mt19937_state *state) {
   int i;
 
@@ -83,69 +61,6 @@ void add_state(mt19937_state *state1, mt19937_state *state2) {
   }
 }
 
-/*
-void gen_vec_h(mt19937_state *state, mt19937_state *vec_h,
-               unsigned long *h) {
-  int i;
-  unsigned long k, g;
-  mt19937_state v;
-
-  gray_code(h);
-
-  copy_state(&vec_h[0], state);
-
-  for (i = 0; i < QQ; i++)
-    gen_next(&vec_h[0]);
-
-  for (i = 1; i < LL; i++) {
-    copy_state(&v, state);
-    g = h[i] ^ h[i - 1];
-    for (k = 1; k < g; k = (k << 1))
-      gen_next(&v);
-    copy_state(&vec_h[h[i]], &vec_h[h[i - 1]]);
-    add_state(&vec_h[h[i]], &v);
-  }
-}
-*/
-
-/* compute pf(ss) using Sliding window algorithm */
-/*
-void calc_state(unsigned long *pf, mt19937_state *state,
-                mt19937_state *vec_h) {
-  mt19937_state *temp1;
-  int i = MEXP - 1, j, digit, skip = 0;
-
-  temp1 = (mt19937_state *)calloc(1, sizeof(mt19937_state));
-
-  while (get_coef(pf, i) == 0)
-    i--;
-
-  for (; i >= QQ; i--) {
-    if (get_coef(pf, i) != 0) {
-      for (j = 0; j < QQ + 1; j++)
-        gen_next(temp1);
-      digit = 0;
-      for (j = 0; j < QQ; j++)
-        digit = (digit << 1) ^ get_coef(pf, i - j - 1);
-      add_state(temp1, &vec_h[digit]);
-      i -= QQ;
-    } else
-      gen_next(temp1);
-  }
-
-  for (; i > -1; i--) {
-    gen_next(temp1);
-    if (get_coef(pf, i) == 1)
-      add_state(temp1, state);
-    else
-      ;
-  }
-
-  copy_state(state, temp1);
-  free(temp1);
-}
-*/
-
 /* compute pf(ss) using standard Horner method */
 void horner1(unsigned long *pf, mt19937_state *state) {
   int i = MEXP - 1;
@@ -180,18 +95,15 @@ void horner1(unsigned long *pf, mt19937_state *state) {
   free(temp);
 }
 
-void mt19937_jump_state(mt19937_state *state, const char *jump_str) {
+void mt19937_jump_state(mt19937_state *state) {
   unsigned long *pf;
   int i;
 
   pf = (unsigned long *)calloc(P_SIZE, sizeof(unsigned long));
-
-  for (i = MEXP - 1; i > -1; i--) {
-    if (jump_str[i] == '1')
-      set_coef(pf, i, 1);
+  for (i = 0; i<P_SIZE; i++) {
+    pf[i] = poly_coef[i];
   }
-  /* TODO: Should generate the next set and start from 0, but doesn't matter ??
-   */
+
   if (state->pos >= N) {
     state->pos = 0;
   }
@@ -200,25 +112,3 @@ void mt19937_jump_state(mt19937_state *state, const char *jump_str) {
 
   free(pf);
 }
-/*
-void mt19937_jump(mt19937_state *state, const char *jump_str)
-{
-    unsigned long h[LL];
-    mt19937_state vec_h[LL];
-    unsigned long *pf;
-    int i;
-
-    pf = (unsigned long *)calloc(P_SIZE, sizeof(unsigned long));
-
-    for (i = MEXP - 1; i > -1; i--)
-    {
-        if (jump_str[i] == '1')
-            set_coef(pf, i, 1);
-    }
-
-    gen_vec_h(state, &vec_h, &h);
-    calc_state(pf, state, &vec_h);
-
-    free(pf);
-}
-*/
\ No newline at end of file
index 394c150a0336d5bcbcb0c7532f129c5a4f9fc267..8371cbd5fc5b55c171c24fbe15328cb99cf0ba2e 100644 (file)
 #define QQ 7
 #define LL 128 /* LL = 2^(QQ) */
 
-void mt19937_jump_state(mt19937_state *state, const char *jump_str);
+void mt19937_jump_state(mt19937_state *state);
 
-void set_coef(unsigned long *pf, unsigned int deg, unsigned long v);
\ No newline at end of file
+void set_coef(unsigned long *pf, unsigned int deg, unsigned long v);
+
+/*
+ * 2**128 step polynomial produced using the file mt19937-generate-jump-poly.c
+ * (randomgen) which is a modified version of minipoly_mt19937.c as distributed
+ * in
+ * http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/JUMP/jump_ahead_1.02.tar.gz
+ *
+ * These files are not part of NumPy.
+ */
+
+static const unsigned long poly_coef[624] = {
+    1927166307UL, 3044056772UL, 2284297142UL, 2820929765UL, 651705945UL,
+    69149273UL,   3892165397UL, 2337412983UL, 1219880790UL, 3207074517UL,
+    3836784057UL, 189286826UL,  1049791363UL, 3916249550UL, 2942382547UL,
+    166392552UL,  861176918UL,  3246476411UL, 2302311555UL, 4273801148UL,
+    29196903UL,   1363664063UL, 3802562022UL, 2600400244UL, 3090369801UL,
+    4040416970UL, 1432485208UL, 3632558139UL, 4015816763UL, 3013316418UL,
+    551532385UL,  3592224467UL, 3479125595UL, 1195467127UL, 2391032553UL,
+    2393493419UL, 1482493632UL, 1625159565UL, 748389672UL,  4042774030UL,
+    2998615036UL, 3393119101UL, 2177492569UL, 2265897321UL, 2507383006UL,
+    3461498961UL, 2003319700UL, 1942857197UL, 1455226044UL, 4097545580UL,
+    529653268UL,  3204756480UL, 2486748289UL, 495294513UL,  3396001954UL,
+    2643963605UL, 2655404568UL, 3881604377UL, 624710790UL,  3443737948UL,
+    1941294296UL, 2139259604UL, 3368734020UL, 422436761UL,  3602810182UL,
+    1384691081UL, 3035786407UL, 2551797119UL, 537227499UL,  65486120UL,
+    642436100UL,  2023822537UL, 2515598203UL, 1122953367UL, 2882306242UL,
+    1743213032UL, 321965189UL,  336496623UL,  2436602518UL, 3556266590UL,
+    1055117829UL, 463541647UL,  743234441UL,  527083645UL,  2606668346UL,
+    2274046499UL, 2761475053UL, 2760669048UL, 2538258534UL, 487125077UL,
+    3365962306UL, 3604906217UL, 2714700608UL, 680709708UL,  2217161159UL,
+    1614899374UL, 3710119533UL, 3201300658UL, 3752620679UL, 2755041105UL,
+    3129723037UL, 1247297753UL, 2812642690UL, 4114340845UL, 3485092247UL,
+    2752814364UL, 3586551747UL, 4073138437UL, 3462966585UL, 2924318358UL,
+    4061374901UL, 3314086806UL, 2640385723UL, 744590670UL,  3007586513UL,
+    3959120371UL, 997207767UL,  3420235506UL, 2092400998UL, 3190305685UL,
+    60965738UL,   549507222UL,  3784354415UL, 3209279509UL, 1238863299UL,
+    2605037827UL, 178570440UL,  1743491299UL, 4079686640UL, 2136795825UL,
+    3435430548UL, 1679732443UL, 1835708342UL, 2159367000UL, 1924487218UL,
+    4059723674UL, 996192116UL,  2308091645UL, 1336281586UL, 674600050UL,
+    1642572529UL, 1383973289UL, 2202960007UL, 3165481279UL, 3385474038UL,
+    2501318550UL, 2671842890UL, 3084085109UL, 3475033915UL, 1551329147UL,
+    4101397249UL, 1205851807UL, 3641536021UL, 3607635071UL, 1609126163UL,
+    2910426664UL, 3324508658UL, 4244311266UL, 254034382UL,  1258304384UL,
+    1914048768UL, 1358592011UL, 527610138UL,  3072108727UL, 4289413885UL,
+    1417001678UL, 2445445945UL, 896462712UL,  339855811UL,  3699378285UL,
+    2529457297UL, 3049459401UL, 2723472429UL, 2838633181UL, 2520397330UL,
+    3272339035UL, 1667003847UL, 3742634787UL, 942706520UL,  2301027215UL,
+    1907791250UL, 2306299096UL, 1021173342UL, 1539334516UL, 2907834628UL,
+    3199959207UL, 1556251860UL, 3642580275UL, 2355865416UL, 285806145UL,
+    867932457UL,  1177354172UL, 3291107470UL, 4022765061UL, 1613380116UL,
+    588147929UL,  650574324UL,  1236855601UL, 1371354511UL, 2085218212UL,
+    1203081931UL, 420526905UL,  1022192219UL, 2903287064UL, 2470845899UL,
+    3649873273UL, 2502333582UL, 3972385637UL, 4246356763UL, 199084157UL,
+    1567178788UL, 2107121836UL, 4293612856UL, 1902910177UL, 332397359UL,
+    83422598UL,   3614961721UL, 456321943UL,  2277615967UL, 2302518510UL,
+    3258315116UL, 2521897172UL, 3900282042UL, 4186973154UL, 3146532165UL,
+    2299685029UL, 3889120948UL, 1293301857UL, 187455105UL,  3395849230UL,
+    913321567UL,  3093513909UL, 1440944571UL, 1923481911UL, 338680924UL,
+    1204882963UL, 2739724491UL, 2886241328UL, 2408907774UL, 1299817192UL,
+    2474012871UL, 45400213UL,   553186784UL,  134558656UL,  2180943666UL,
+    2870807589UL, 76511085UL,   3053566760UL, 2516601415UL, 4172865902UL,
+    1751297915UL, 1251975234UL, 2964780642UL, 1412975316UL, 2739978478UL,
+    2171013719UL, 637935041UL,  975972384UL,  3044407449UL, 3111425639UL,
+    1938684970UL, 2860857400UL, 13419586UL,   2772079268UL, 3484375614UL,
+    3184054178UL, 159924837UL,  1386213021UL, 2765617231UL, 2523689118UL,
+    1283505218UL, 3510789588UL, 4125878259UL, 2990287597UL, 2152014833UL,
+    3084155970UL, 2815101609UL, 1932985704UL, 114887365UL,  1712687646UL,
+    2550515629UL, 3299051916UL, 2022747614UL, 2143630992UL, 2244188960UL,
+    3309469192UL, 3234358520UL, 800720365UL,  3278176634UL, 554357439UL,
+    2415629802UL, 1620877315UL, 2389462898UL, 2229691332UL, 1007748450UL,
+    1966873768UL, 2264971043UL, 1214524156UL, 346854700UL,  3471905342UL,
+    3984889660UL, 4034246840UL, 216712649UL,  4027196762UL, 3754772604UL,
+    2121785562UL, 2347070732UL, 7457687UL,    1443375102UL, 683948143UL,
+    2940226032UL, 3211475670UL, 2836507357UL, 774899409UL,  1588968308UL,
+    780438009UL,  3278878781UL, 2217181540UL, 2184194887UL, 1642129086UL,
+    69346830UL,   297114710UL,  3841068188UL, 2631265450UL, 4167492314UL,
+    2613519651UL, 1388582503UL, 2171556668UL, 1201873758UL, 2698772382UL,
+    207791958UL,  3936134563UL, 3725025702UL, 3306317801UL, 1055730422UL,
+    4069230694UL, 1767821343UL, 4252407395UL, 2422583118UL, 3158834399UL,
+    3754582617UL, 1112422556UL, 376187931UL,  3137549150UL, 712221089UL,
+    3300799453UL, 3868250200UL, 1165257666UL, 2494837767UL, 131304831UL,
+    1619349427UL, 1958236644UL, 3678218946UL, 3651007751UL, 2261987899UL,
+    1567368524UL, 2193599522UL, 3034394674UL, 2994602555UL, 3072727647UL,
+    889094521UL,  1089692095UL, 1822324824UL, 3876999182UL, 1703361286UL,
+    902229515UL,  4213728487UL, 3838170364UL, 672727494UL,  2240733828UL,
+    3858539469UL, 1149254245UL, 4166055926UL, 4193525313UL, 1709921593UL,
+    2278290377UL, 3190784116UL, 2919588882UL, 1012709717UL, 3640562031UL,
+    2931984863UL, 3515665246UL, 250577343UL,  1147230194UL, 1183856202UL,
+    3734511989UL, 3243867808UL, 3499383067UL, 2985115159UL, 2036821626UL,
+    3298159553UL, 2726542838UL, 1686910320UL, 1778823772UL, 965412224UL,
+    233509772UL,  3843098861UL, 1312622954UL, 500855830UL,  2950562091UL,
+    1915683607UL, 3405781138UL, 596073719UL,  2195150546UL, 3381728478UL,
+    546426436UL,  3527890868UL, 2324975353UL, 2241074266UL, 3992514859UL,
+    2576108287UL, 4077653225UL, 2632319392UL, 3127212632UL, 917000669UL,
+    2498161805UL, 3980835128UL, 2259526768UL, 1083920509UL, 1187452089UL,
+    97018536UL,   3056075838UL, 2059706760UL, 2373335692UL, 182196406UL,
+    2136713111UL, 1762080153UL, 1572125803UL, 1145919955UL, 1023966754UL,
+    3921694345UL, 1632005969UL, 1418372326UL, 354407429UL,  2438288265UL,
+    1620072033UL, 1586320921UL, 1044153697UL, 969324572UL,  613487980UL,
+    4230993062UL, 397726764UL,  2194259193UL, 735511759UL,  2066049260UL,
+    88093248UL,   1562536153UL, 2114157419UL, 3630951546UL, 589238503UL,
+    3120654384UL, 2521793793UL, 2746692127UL, 2557723425UL, 889897693UL,
+    2778878177UL, 643269509UL,  3342389831UL, 19218890UL,   3442706236UL,
+    3314581273UL, 3503147052UL, 1546343434UL, 1448529060UL, 529038801UL,
+    2748942264UL, 2213019208UL, 111314040UL,  2488697563UL, 1180642808UL,
+    2605272289UL, 4207476668UL, 1502558669UL, 2972370981UL, 4204339995UL,
+    1046225278UL, 992840610UL,  3847290298UL, 2387673094UL, 2221565747UL,
+    1045901716UL, 3997739302UL, 1556952765UL, 1103336648UL, 279418400UL,
+    2711316466UL, 2336215718UL, 2317900806UL, 974624729UL,  909575434UL,
+    1675610631UL, 1922393214UL, 2054896570UL, 3197007361UL, 3932554569UL,
+    1008619802UL, 3349254938UL, 113511461UL,  932630384UL,  2098759268UL,
+    3436837432UL, 3119972401UL, 1612590197UL, 2281609013UL, 4174211248UL,
+    4016332246UL, 2097525539UL, 1398632760UL, 1543697535UL, 2419227174UL,
+    1676465074UL, 2882923045UL, 23216933UL,   808195649UL,  3690720147UL,
+    484419260UL,  2254772642UL, 2975434733UL, 288528113UL,  204598404UL,
+    589968818UL,  3021152400UL, 2463155141UL, 1397846755UL, 157285579UL,
+    4230258857UL, 2469135246UL, 625357422UL,  3435224647UL, 465239124UL,
+    1022535736UL, 2823317040UL, 274194469UL,  2214966446UL, 3661001613UL,
+    518802547UL,  2293436304UL, 1335881988UL, 2247010176UL, 1856732584UL,
+    1088028094UL, 1877563709UL, 1015352636UL, 1700817932UL, 2960695857UL,
+    1882229300UL, 1666906557UL, 1838841022UL, 3983797810UL, 1667630361UL,
+    385998221UL,  241341791UL,  403550441UL,  2629200403UL, 3552759102UL,
+    2029750442UL, 2247999048UL, 2726665298UL, 2507798776UL, 2419064129UL,
+    1266444923UL, 526255242UL,  2384866697UL, 1886200981UL, 3954956408UL,
+    2171436866UL, 2295200753UL, 1047315850UL, 1967809707UL, 2860382973UL,
+    3918334466UL, 3057439479UL, 952682588UL,  1925559679UL, 3112119050UL,
+    3833190964UL, 1430139895UL, 2089165610UL, 3009202424UL, 3989186157UL,
+    3395807230UL, 347600520UL,  120428923UL,  3017004655UL, 1384933954UL,
+    303039929UL,  234010146UL,  2278760249UL, 315514836UL,  3987659575UL,
+    1239335668UL, 2387869477UL, 3885908826UL, 1983922602UL, 698609264UL,
+    3009002846UL, 1520611399UL, 809159940UL,  3089771783UL, 374838722UL,
+    2789914419UL, 2500831937UL, 3751970335UL, 4279852547UL, 2362894437UL,
+    1588814060UL, 1671213155UL, 434218829UL,  2126587176UL, 2002526422UL,
+    2756464095UL, 141700479UL,  2965974322UL, 2211530172UL, 992085992UL,
+    1943691492UL, 2705131817UL, 2519208889UL, 1938768395UL, 3949294294UL,
+    354046666UL,  2158272751UL, 602858583UL,  0UL};
diff --git a/numpy/random/src/mt19937/mt19937-poly.h b/numpy/random/src/mt19937/mt19937-poly.h
deleted file mode 100644 (file)
index b037478..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-static const char * poly =
-"0001000111110111011100100010101111000000010100100101000001110111100010101000110100101001011001010"
-"1110101101100101011100101101011001110011100011110100001000001011100101100010100000010011101110011"
-"0100001001111010000100100101001011100111101101001100000111001000011101100100010000001111110100010"
-"0000111101000101000101101111001011000011001001001011010011001000001000011100100010110101111111101"
-"0010001001100010011011101111101110111010111000010000011010110011111101100000100100101001010000001"
-"1001111000011010011101001101011000111001110010110000011000110101111010110011011000001110110010001"
-"1001101011011101000011001011111111100011001010111100000001111011111101000101000011000011111100101"
-"0100001111101010101100000110100110010010101011011100110011000101100101011110010101110000101011100"
-"0001010100010110100000111001100000011101011001101000001000101101010100010101100000100011110110011"
-"0101100110111101010111100010100110100011111011100111000001110110010000000100000110101010111001111"
-"0011110010000110101101010001110010100111111111100100101010010011101111011000010111101001110110110"
-"1011101101101100110111000100101100111001011111110101001000011111010011000111110011100100001101111"
-"1001010110110001000100001001000010000000001011011100101010010100011000110101001000010101100111101"
-"0011110101100110111100000111001011011001100101111011000101001011011111110110100010001100101001100"
-"1111110011111111110111011011100011000100110011011011011001101011100110010001111100001111100100001"
-"1000100011001010100101010100111110001100111111011111100100011110011101101000110100101110010111111"
-"1001010110000101001110010110001011011010101111111001110001100100011001000010111001011011000111100"
-"1101001011110111111010011000110100001010000000101010101001111101111110101111110101110101010010100"
-"1100100101010110011111001101100110001011000101010001000110011011111101111110001100000010110110101"
-"1111110100001011101011101110111101100001111000011100000110110100100100100101011000111000100110001"
-"0110110001001000111110101111000000100100010100100101101111100011010100111101110010000001011111111"
-"1101010000011001010101111001111110001111100010100010100001011001110001010010100001011111110110111"
-"1100100100001111000111110111000100010101010110100111100001011001101001111101001110010110110011010"
-"1000010011000110000000110110110000111010010000111001100010100101010101111100010111000000011101110"
-"1100011010110001101100110000001010001100111101101011100111110111000110010011011011001101001111100"
-"1011111001100011010110101111100110111101011100000011000010001010001101001011000001111000101000100"
-"0110001011001010110000001101100000011000011110010000101000011010011110001101111111010010101100100"
-"1111010100000011011001111111011011111001101110101010110111110110101000100001011110111010100111100"
-"0000001001111100111111111000100000100100010001011001100001111100100000001111011101100010011000111"
-"0011110110100011011001110011100011011000010000000101101101001010111000010000010101111110000000100"
-"1011010100001001000011001100011000000111100111100101010100000111000000110111011101011111100010101"
-"0011001100110000010101111001000111001001010100011000110010011011101001001100101100000000111000111"
-"0111111000010010010100000101010010000100101011111111111001100101101010011010100010111001011100011"
-"1001001011010000110000111100010110110100000100110010000010010000001000110010101000110101101100100"
-"0001100001100011110110010000100000100010011001010010110111100011011000101011001100001111110110110"
-"0001100110010100011001101000100001110011011111101001101011110011011011111110111110101110010011001"
-"1000000101100000101100100000100000001011000100100001100100101101010111101010111101010001001010110"
-"0011111011001101001110110010100100000011001001111010001001100101110000000010111101000111111101010"
-"0110101110101110001001110000111110100000101101100110010001111101111011001000101110111010110111110"
-"0011001101011010001011000010000111111111101001011100110101011000000001111000101100011101011011100"
-"1111101110000000000110001110011001101100111111010001110000111110100011000100001100110010000110111"
-"1001011011001111011100000000011011000100000011000010010111000111101000011001001100011010001111000"
-"0011110010100010001101011101010011001100000010101001001101111101000111001110110000000010111101001"
-"1110110011101110111010011100101001010101100100011111100110001111011111110010100000011100110110001"
-"1011100000101000010100011101000010111100101111101100110001010001010000101110000000110100010110011"
-"1111110100101010011010100001100110110110011111110010000100001010011110010110001000000100000111000"
-"0111001010011001000010111001100110100110110101111011110111001001000101010010010011000111110010101"
-"1100110001100101001000010001101010011001110011001110001110010100010000000000000110111001010101000"
-"0111111011011101000111011001011011000101110100010001111100101110000100001011111101111101010011001"
-"0010001100011011101100010010101011001000001001010101100110001111001110011100110111111010110010001"
-"1111111101111001001101101001001010011001110000101000110010111110010110111111000100101000101011010"
-"0000101101101100000110101000101000010001111000100000111110011111111110010010001010001111011001100"
-"0011110111000000111111000100001111101110100010101011001010110110011001010010001011100001010110101"
-"0100000010101101000011001101110010000010110011000101100100000111111100011001110011010011001110000"
-"1110011110000000001001001010100000111001010110001110011100011010010010001110010011001010111100000"
-"1110000101101001011010001001010000111000010011010100001010110000101101110110011000011100111100001"
-"1001000011010001110110111001100100001111110010110010011111000010100000001101110100000000101101000"
-"0011000000100011000111110001000011100111110110000110101111101100011110100111111000000011011110110"
-"1101011010111010010001001101000110110010000010101000000001100100100000001111011001001010110100011"
-"1011000010101111010111000001001100111110000010110010011011110011111001000101111011010011010100001"
-"0110011111100001011111101010010100110001001001001000100010101011011000011100111000110101110000001"
-"1100001111100011110010000101011000010101111010001101010101100001100101100000100100000101011001100"
-"0011001000101010101010100111000100100010101000111111101010000000101010101001000101010100100111001"
-"1001100001010001100110111101010001111010011100000001001110100010010011110100001000011111100010001"
-"0010001000100110101011001110100110101110110110100101111000110101101101001000001110011010110011001"
-"0111111101011011101001111001011100001010110111000001100010110110100011010111011000111010100011000"
-"1111010110001001010000110001000101101100010100000000100001111100000010111001000011000101010100001"
-"0001101100011100010100101110010100000010011011010100000111110110000110101011011010010001110000111"
-"0110101000110101110010011100010010100111001101110110010001101001101101010100001010001110111011011"
-"1010011001010111101001011000100111001110011000000001101000001111001100001100000011001110100110011"
-"0011000110001001010111111111110110111111000111100010010101110000101100101000001010001011010100010"
-"1010010100010011101111100111010010010001110101011110110100001000001001000111001110010001001100100"
-"1100100010001010011011110100000101101011101010110110100100010001110000111010111001111011111001011"
-"0000000000011000100100100111001000101111000000110001011110101111110111100000000100101011000111011"
-"1011010011101000001011001001110001111010000100101101010111001010001000100001000111011010000110111"
-"1010110001001110001100001110011000101100000101100000000110101000000110101100100101110001100100100"
-"0110000110101011100001010001010000011101111011111011011000100100101011110101111000001011110010110"
-"0111011011100111101010110001111011010011111000010111110100001001010001011001000110111100000101011"
-"0010111111010100000110111101001100000100001011101010100011010010000001101100100101001000100011000"
-"0101010111111100100000111011101111100000011011111111010001100011001100101101011110101011101100001"
-"0100010011101111111011000111111101001000101101111001111000101110010111001010101011010111000000101"
-"0110010000010010101111100010111110000000011101001000011111001011111100111100100101100101111010110"
-"1010101001110011111100111110100000111100100000111111000010100001111011111110110010001001000000000"
-"1110100110010111100101111111001010001111001101100001011000111011100010100001000010100000011001000"
-"0000111000110111001001100010111010100111111001111101100101000011001001110011100110101110001101110"
-"1110000010110110010110000111001110110000011011100111000101100101000000001110011011001001111001111"
-"0000101100001000000111100110110000110111111001101001111111010000001011110011011011100100110000110"
-"1001011111101100100111111000000010001110111011010011011101001100000011001010000010101111111010110"
-"0001000100101110101101100001001010100110010000110110100110011001000111011110110011001110111110101"
-"0000011111011011001111010010101011000010011101001011100001010001111001000110000010000101010011111"
-"0110011000001111101001110001101011111111001010010110100001101000000011101000101011101000110101111"
-"0000101110011010010000110100000101100011000100101111100011001111011101001010100111001110100001101"
-"0000110111011000000110011001101011110000101100110110000101100000110110100001001001110001110001001"
-"1100110111111100101001100010010110011011110001000111111111001101111110010000011001011010111101001"
-"1101111110101110110100101100110001101101001010111101101000000011111111100101000101110001000011001"
-"1000111110111011010010101011110110110001010001001001100111111010011101111000000111011000011010011"
-"0111010101001110010100101101000110000110001100010101001110101011010100000110110111111111110011110"
-"0100011110100011001000110101111010000001011011110101001100111100010100101100010000010110011001111"
-"0011011110001110010010100100011111110000110011011100010110110101001110011010101111011001010101011"
-"1001001111001000001100100111000001000110110101100111000101011000000100001000100010011000001110011"
-"0000111100000111001101011111010000010001100000010101101000111100001000010011110000001011001001100"
-"0011011011111011100000111101001011101000010010001001111110010101111010110101101110110111010000101"
-"1100011000000000110110100011010100100010001101010101101110110111111011010110011101011010110101011"
-"1101000000010010011111000000101000110001000011100001101111010101100000100000100111111111100000000"
-"0011100011100101110010111100010111110010101110101000011000111111001110111111000001101101011011111"
-"1100110101001000011111001111000000001010001001010101101000001100111010101100010111001001111100000"
-"1110101101110001011100011101101100001001001011100111100110011101111000100010010001111100001010010"
-"1011001001010100101100010010000110010000101010111111001000011100000000101101110010001101110101001"
-"1110000011100101010000011110000010001000001010110001010000100111001100110001111000100100011100110"
-"1100010011110111001001100000100111001010000000000011100011111111101110010101111010100010000100001"
-"0101101001010111111110000110110010100000001011110100010111110111010000001011110110111000000110010"
-"0001100100111110001100010101000010011111100000100010000101110000111001101100100000011111111100010"
-"1001101101001000001111000100100001010110111011110110001001010001110001001100011001001100000000101"
-"1100011110101101011001100001010110001010000111100000011011011001000010101100010101110011001101110"
-"0000101011010001010011111001011000010101010100110110111110101000111110001000010100000000100010100"
-"1000111111000110110010001111000010101011101101111101011110101111100111111100111101000101000010011"
-"0010111010100010011001000000010111100010000101001011001101100011100001001111010100100110101111111"
-"1000010011110101001010011111111011101001110100001001100010000100001001100101101111011100100011001"
-"1111010001011001111101011110101101000111110101001010011101010010010101001000000000011001100110001"
-"0001000010101010101000010100111000001110000111001110001101111111000010101010111001011101001001011"
-"0011001111011010101110101111110001001100100111010001011000010100000100000001001100000011000011101"
-"1100000110000001011001110000101001010111101000110101000011000000111011100101010000111000010010101"
-"1010100101100001011011011110110011000100100101010011111101000000100001001101000011000101010111101"
-"1110111111100010111000111000010110111010010110000000000100101001000111101101100000000110111011001"
-"0100000000100100011110111011101101101101010110001110100001100001001011000000111111110100011110011"
-"0010000010000000010100110011110000000010000011111000111101011110000000000010101101001100000010010"
-"1011001001101110110011100001100011101001101011110011010001011101000100011111001010100000011111111"
-"1010101100000010001000110000110000101000110100110011100000110010110100011111010001000011100001001"
-"1000101000010111111011100010111000111001010100110000000010011011101010101111000110001000110111011"
-"1011100001100011010001101011010100110110011100000010111001011111110010100110100010001100000011100"
-"0001011001011000101011010000001010011010001011000111000011000011110011111001111010001101011010010"
-"0010010001001001101000101001011011101110001100010001010100010111111001100100000010001111100010111"
-"0100001111001100101001011101010010110010100010001100011010100110000100011010111110001011011001000"
-"1001001111011010010011101110100001111100000110101001010111110001101100110010111010111001011111010"
-"1110111011111110000001110010000010011111000111011011000011000010011110011111111101100101111011100"
-"0101101100000110101110000111111111111010110101010100111000011111011001100000100000101011000101110"
-"1011010010100000000100100000010111101110111001000011111011111110100011010010000110001101111101100"
-"1100010111001011011001011001010100100110100101001000111011011001100011001010010101111001100100110"
-"1000110000111011100101110101101000011001010010100011000001111001110110101101010010110110001100100"
-"0100001011101100111001010001111011010110010010110010110111110001001001111001111010010001010001101"
-"1110100110101100011110100100110111000111010110011000100100110110001101111100111110100001000110000"
-"1110011011001101100101100000001010100011101000010100111011111100011010000110000001011100010000101"
-"0100101000010001110010001100010110011111111101111000011001110111011100110010010100100010001000010"
-"0100001110010000011000110001101011101001110100100011011001000111010101110100110011010111001100001"
-"0100001001101010010111110101110111000000010100111101011010101001000001001000001000101101111000000"
-"0110000101110100001111001101110111011110010111101000100101110111010101001101100001110001101101101"
-"0010101100100101000100100100110111000111000111100111000001100001000111101011000110111110001010000"
-"0100110010001101100011010111000111010111000111110000110000101111101110010110111001011000111010001"
-"1011000010010101010010011001000011010110111011010001001010100111001000010110110110101110000110000"
-"1110110010011001011011000100011101001001000111011100100000000000100001101101000101000100000111001"
-"0011100001100110101011011101110111101111000100100011100001010001011001110010101010001110101101110"
-"1011001110111111111010101101000010111111011011011100011100101010001011011100011111011100101011000"
-"1000110100101000011111010011110000000101101110010000101100001000100000000010010110000000000110011"
-"1000000000001111001001000100000111001110111111001111101100001100111000101100011000100111111110011"
-"1110010101011010111100110010110001010000101111111101001010100010001001111010111000010000010010001"
-"1111111101100100001101011011100001010101000111110111111101011010011111111101000111011001011011000"
-"0000101011100011101110110011101111011110011110010000011001111001110111011011111010011011001110111"
-"0101100111110100000100010110010010101001010100010111000101111001011011001001110010100011101111110"
-"1101011110010101101011010010011111110000011010011101000000010000111010100100111110111000001101010"
-"0101100001111001111010101011110001001010000011010110010100011100100100111110100110000010011111001"
-"0100010011001001010101110111111010011101101100000101011110111010011110001111110100111011110011010"
-"0111001010110101010110000011001010000000101101010101001101011000011011010110101010101111101101100"
-"1100100000111101010111011011011110011001100010010000010100101000111111101011100111010101011000111"
-"1100110010101100010011111100000110011111101011100100001110001100001010101001001100010011001000100"
-"1101101000101101110010000001101001001110101111000110111000011101111110100100110111000000101011110"
-"0001100100001010101001101111001000001100000011010000100101100000001110100010010000110110101010111"
-"1100010100000110011100101010111110010110111100000010110011011001011110111001010011011110010001110"
-"1101110000001011101101011111101011111110110110000111110011101100110100010000100000110100010010110"
-"0011000011000110101001110100111010110000100010110101110111100010110001000111100111001011011110010"
-"0001001110101001101101011010111001001101100011101001011011001110011010001010110100111001111100101"
-"1000111001010010000010111010101110001100110111111000011101001000001010010011101000111001100111110"
-"1110100100100110010111111101010011101111011011111011011010011110100101100001011000001001001010010"
-"1100001000000110110011011101010001011110010001001110110100100001101101001011101010001110111111010"
-"1100011100101000011110111110110011111111100010110010110111010010001111101110011011010110000001000"
-"0010110100010101110100001000010011100110001110001110010100010010010110011100100110010100001110011"
-"1100001011010000001101011011011110100000001110100111001000101000001000001001000010000111010000100"
-"0111100000101010110010111010010101100000001100110101001001000110001110111011110001010010010011000"
-"1100001111101101100001111000101100110010001000111001101101011110100110100011101000011111011010101"
-"0101000011111010010110001001100110110111000100100011011101000010001010110001111001111101110001111"
-"0100100000010111010011111110000101001001011110100100010011101110011010100101100001010000001110100"
-"0011111101111000100110011000011001100100001010110011111100111010100011110100010101011110011001000"
-"0000110000100100001011101110111010001001011110010101111100001111101101111011011110001010000100010"
-"1001100100100100110010010101100110000000100000000111110011100111101001010000010000000000101011100"
-"0011101011100110000001100101010101011111111011010011110010011011001010011101010010100010001011010"
-"1100010011101011010111110100001010100011000011001001011011101111110011001110010001100101011001101"
-"0100010001111111100000101000001011010100011100111011010111001100110110001100110101000011010001010"
-"1011100001001010011110001010100100001101110011101011100100101010001100110011110010001100100001000"
-"0110001001110110010111101011101101010111001010011010101110000010100010000111011000010110011000001"
-"1000110010100001110001100010010000001101111110000010010110100000000000001111110010001110111100001"
-"0100111101000011101110010101011011000101011010111100111111001011110001110011110011011010010111101"
-"1010111011101101000001110111001010011001110010100100100100001010001100101010111001110100000110111"
-"1010000111000011101101100101101001100000011100100111100110010110011100101000111110111000110111110"
-"1101100101011101100111011111111001111000011110111110101100000111000101100100110111000010100101000"
-"0110000011011101111101111000110101011000010111010000111011000000100011101010100111001111101010111"
-"0001110100001000100001011101001010001110100000101100001011101111100111101011111001111100101101111"
-"0101100001110011111110110100110010000011011111101101110110000110110011100110111000111101000010111"
-"0111101011100100000000011101111011000100001000111000000111011010101010110000111111101010110001111"
-"0000110100111101111011001010101110000011001101001101000010011001101011111110111101010111010011100"
-"0101010011001111101111001100101000101000111110111001011111100000001101111011000001001100111111111"
-"1010111101000001111011110010001001001110100111110010000011110000011000000101001100011110110011001"
-"1010101001000010001010110000010011110101011110010111010001010111101100001001100011101001111101001"
-"0110110100111001110011100011111010010010100010111000001100001011010010000100100110101010111001001"
-"0110000101011011011100110111111001010000001001011010101010010001011010111100111010101101000101101"
-"0100100001011101110111111001111111110110111011000101010000010000011111001000100101100100100110110"
-"1100000111110010110011010100000100011111110001110010110001000001001111001101110110110101101010111"
-"0000100111101100010001110010110111100011100101100011";
index e5ca9e0cff675ebfa4b9c54b2d78326d04f8c718..bec518af80596a43c710185f17126d48b9d7a555 100644 (file)
@@ -1,6 +1,5 @@
 #include "mt19937.h"
 #include "mt19937-jump.h"
-#include "mt19937-poly.h"
 
 void mt19937_seed(mt19937_state *state, uint32_t seed) {
   int pos;
@@ -104,4 +103,4 @@ extern inline uint32_t mt19937_next32(mt19937_state *state);
 
 extern inline double mt19937_next_double(mt19937_state *state);
 
-void mt19937_jump(mt19937_state *state) { mt19937_jump_state(state, poly); }
+void mt19937_jump(mt19937_state *state) { mt19937_jump_state(state); }
index df5814d5f518556adab73d281b126e4f43382120..9856a9b8e2a4ad39fbce318e40b6667c7ff61b69 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Simple benchamrk command
+ * Simple benchmark command
  *
  *  cl philox-benchmark.c /Ox
  *
index 9f77f0ad28e0b286dcf69457c4d6ff65da880af4..dad12c8a80ec7e94501c027c7e9a2d3ac315d076 100644 (file)
@@ -127,7 +127,7 @@ def gauss_from_uint(x, n, bits):
     return gauss[:n]
 
 def test_seedsequence():
-    from numpy.random._bit_generator import (ISeedSequence,
+    from numpy.random.bit_generator import (ISeedSequence,
                                             ISpawnableSeedSequence,
                                             SeedlessSeedSequence)
 
@@ -145,7 +145,7 @@ def test_seedsequence():
     assert len(dummy.spawn(10)) == 10
 
 
-class Base(object):
+class Base:
     dtype = np.uint64
     data2 = data1 = {}
 
@@ -410,7 +410,7 @@ class TestSFC64(Base):
         cls.invalid_init_values = [(-1,)]
 
 
-class TestDefaultRNG(object):
+class TestDefaultRNG:
     def test_seed(self):
         for args in [(), (None,), (1234,), ([1234, 5678],)]:
             rg = default_rng(*args)
index ce34c1b878d1c24520c74dccc8428d52179ba59e..77353463e9b4328f63917e7ff90bfc1d998c957f 100644 (file)
@@ -1,8 +1,10 @@
-import os, sys
+import os
 import pytest
-import warnings
 import shutil
 import subprocess
+import sys
+import warnings
+import numpy as np
 
 try:
     import cffi
@@ -41,17 +43,53 @@ else:
 @pytest.mark.skipif(cython is None, reason="requires cython")
 @pytest.mark.slow
 def test_cython(tmp_path):
-    examples = os.path.join(os.path.dirname(__file__), '..', '_examples')
-    # CPython 3.5 and below does not handle __fspath__ well: see bpo-26027
-    shutil.copytree(examples, str(tmp_path / '_examples'))
-    subprocess.check_call([sys.executable, 'setup.py', 'build'],
-                          cwd=str(tmp_path / '_examples' / 'cython'))
+    srcdir = os.path.join(os.path.dirname(__file__), '..')
+    shutil.copytree(srcdir, tmp_path / 'random')
+    # build the examples and "install" them into a temporary directory
+    build_dir = tmp_path / 'random' / '_examples' / 'cython'
+    subprocess.check_call([sys.executable, 'setup.py', 'build', 'install',
+                           '--prefix', str(tmp_path / 'installdir'),
+                           '--single-version-externally-managed',
+                           '--record', str(tmp_path/ 'tmp_install_log.txt'),
+                          ],
+                          cwd=str(build_dir),
+                      )
+    # gh-16162: make sure numpy's __init__.pxd was used for cython
+    # not really part of this test, but it is a convenient place to check
+    with open(build_dir / 'extending.c') as fid:
+        txt_to_find = 'NumPy API declarations from "numpy/__init__.pxd"'
+        for i, line in enumerate(fid):
+            if txt_to_find in line:
+                break
+        else:
+            assert False, ("Could not find '{}' in C file, "
+                           "wrong pxd used".format(txt_to_find))
+    # get the path to the so's
+    so1 = so2 = None
+    with open(tmp_path /'tmp_install_log.txt') as fid:
+        for line in fid:
+            if 'extending.' in line:
+                so1 = line.strip()
+            if 'extending_distributions' in line:
+                so2 = line.strip()
+    assert so1 is not None
+    assert so2 is not None
+    # import the so's without adding the directory to sys.path
+    from importlib.machinery import ExtensionFileLoader 
+    extending = ExtensionFileLoader('extending', so1).load_module()
+    extending_distributions = ExtensionFileLoader('extending_distributions', so2).load_module()
+
+    # actually test the cython c-extension
+    from numpy.random import PCG64
+    values = extending_distributions.uniforms_ex(PCG64(0), 10, 'd')
+    assert values.shape == (10,)
+    assert values.dtype == np.float64
 
 @pytest.mark.skipif(numba is None or cffi is None,
                     reason="requires numba and cffi")
 def test_numba():
-    from numpy.random._examples.numba import extending
+    from numpy.random._examples.numba import extending  # noqa: F401
 
 @pytest.mark.skipif(cffi is None, reason="requires cffi")
 def test_cffi():
-    from numpy.random._examples.cffi import extending
+    from numpy.random._examples.cffi import extending  # noqa: F401
index 2f542e4d96a30092785698a80a160adcbd86bfa3..332b631985d5a5458d56026645c9d96e58cbff26 100644 (file)
@@ -1,9 +1,9 @@
 import sys
+import hashlib
 
 import pytest
 
 import numpy as np
-from numpy.dual import cholesky, eigh, svd
 from numpy.linalg import LinAlgError
 from numpy.testing import (
     assert_, assert_raises, assert_equal, assert_allclose,
@@ -14,13 +14,33 @@ from numpy.random import Generator, MT19937, SeedSequence
 
 random = Generator(MT19937())
 
+JUMP_TEST_DATA = [
+    {
+        "seed": 0,
+        "steps": 10,
+        "initial": {"key_md5": "64eaf265d2203179fb5ffb73380cd589", "pos": 9},
+        "jumped": {"key_md5": "8cb7b061136efceef5217a9ce2cc9a5a", "pos": 598},
+    },
+    {
+        "seed":384908324,
+        "steps":312,
+        "initial": {"key_md5": "e99708a47b82ff51a2c7b0625b81afb5", "pos": 311},
+        "jumped": {"key_md5": "2ecdbfc47a895b253e6e19ccb2e74b90", "pos": 276},
+    },
+    {
+        "seed": [839438204, 980239840, 859048019, 821],
+        "steps": 511,
+        "initial": {"key_md5": "9fcd6280df9199785e17e93162ce283c", "pos": 510},
+        "jumped": {"key_md5": "433b85229f2ed853cde06cd872818305", "pos": 475},
+    },
+]
 
 @pytest.fixture(scope='module', params=[True, False])
 def endpoint(request):
     return request.param
 
 
-class TestSeed(object):
+class TestSeed:
     def test_scalar(self):
         s = Generator(MT19937(0))
         assert_equal(s.integers(1000), 479)
@@ -56,7 +76,7 @@ class TestSeed(object):
         assert_raises(ValueError, Generator, MT19937)
 
 
-class TestBinomial(object):
+class TestBinomial:
     def test_n_zero(self):
         # Tests the corner case of n == 0 for the binomial distribution.
         # binomial(0, p) should be zero for any p in [0, 1].
@@ -71,7 +91,7 @@ class TestBinomial(object):
         assert_raises(ValueError, random.binomial, 1, np.nan)
 
 
-class TestMultinomial(object):
+class TestMultinomial:
     def test_basic(self):
         random.multinomial(100, [0.2, 0.8])
 
@@ -123,7 +143,7 @@ class TestMultinomial(object):
         assert_raises(ValueError, random.multinomial, 10, np.array([[0, 1], [1, 0]]))
 
 
-class TestMultivariateHypergeometric(object):
+class TestMultivariateHypergeometric:
 
     def setup(self):
         self.seed = 8675309
@@ -257,7 +277,7 @@ class TestMultivariateHypergeometric(object):
         assert_array_equal(sample, expected)
 
 
-class TestSetState(object):
+class TestSetState:
     def setup(self):
         self.seed = 1234567890
         self.rg = Generator(MT19937(self.seed))
@@ -291,7 +311,7 @@ class TestSetState(object):
         self.rg.negative_binomial(0.5, 0.5)
 
 
-class TestIntegers(object):
+class TestIntegers:
     rfunc = random.integers
 
     # valid integer/boolean types
@@ -463,7 +483,6 @@ class TestIntegers(object):
             assert_array_equal(scalar, array)
 
     def test_repeatability(self, endpoint):
-        import hashlib
         # We use a md5 hash of generated sequences of 1000 samples
         # in the range [0, 6) for all but bool, where the range
         # is [0, 2). Hashes are for little endian numbers.
@@ -488,7 +507,7 @@ class TestIntegers(object):
                 val = random.integers(0, 6 - endpoint, size=1000, endpoint=endpoint,
                                  dtype=dt).byteswap()
 
-            res = hashlib.md5(val.view(np.int8)).hexdigest()
+            res = hashlib.md5(val).hexdigest()
             assert_(tgt[np.dtype(dt).name] == res)
 
         # bools do not depend on endianness
@@ -682,7 +701,7 @@ class TestIntegers(object):
         assert chi2 < chi2max
 
 
-class TestRandomDist(object):
+class TestRandomDist:
     # Make sure the random distribution returns the correct value for a
     # given seed
 
@@ -886,8 +905,6 @@ class TestRandomDist(object):
         assert actual.dtype == np.int64
 
     def test_choice_large_sample(self):
-        import hashlib
-
         choice_hash = 'd44962a0b1e92f4a3373c23222244e21'
         random = Generator(MT19937(self.seed))
         actual = random.choice(10000, 5000, replace=False)
@@ -1104,6 +1121,31 @@ class TestRandomDist(object):
                                   size=(3, 2))
         assert_array_almost_equal(non_contig, contig)
 
+    def test_dirichlet_small_alpha(self):
+        eps = 1.0e-9  # 1.0e-10 -> runtime x 10; 1e-11 -> runtime x 200, etc.
+        alpha = eps * np.array([1., 1.0e-3])
+        random = Generator(MT19937(self.seed))
+        actual = random.dirichlet(alpha, size=(3, 2))
+        expected = np.array([
+            [[1., 0.],
+             [1., 0.]],
+            [[1., 0.],
+             [1., 0.]],
+            [[1., 0.],
+             [1., 0.]]
+        ])
+        assert_array_almost_equal(actual, expected, decimal=15)
+
+    @pytest.mark.slow
+    def test_dirichlet_moderately_small_alpha(self):
+        # Use alpha.max() < 0.1 to trigger stick breaking code path
+        alpha = np.array([0.02, 0.04, 0.03])
+        exact_mean = alpha / alpha.sum()
+        random = Generator(MT19937(self.seed))
+        sample = random.dirichlet(alpha, size=20000000)
+        sample_mean = sample.mean(axis=0)
+        assert_allclose(sample_mean, exact_mean, rtol=1e-3)
+
     def test_exponential(self):
         random = Generator(MT19937(self.seed))
         actual = random.exponential(1.1234, size=(3, 2))
@@ -1348,6 +1390,11 @@ class TestRandomDist(object):
             assert_raises(ValueError, random.negative_binomial, 100,
                           [np.nan] * 10)
 
+    def test_negative_binomial_p0_exception(self):
+        # Verify that p=0 raises an exception.
+        with assert_raises(ValueError):
+            x = random.negative_binomial(1, 0)
+
     def test_noncentral_chisquare(self):
         random = Generator(MT19937(self.seed))
         actual = random.noncentral_chisquare(df=5, nonc=5, size=(3, 2))
@@ -1640,7 +1687,7 @@ class TestRandomDist(object):
         assert_array_equal(actual, desired)
 
 
-class TestBroadcast(object):
+class TestBroadcast:
     # tests that functions that broadcast behave
     # correctly when presented with non-scalar arguments
     def setup(self):
@@ -2192,7 +2239,7 @@ class TestBroadcast(object):
         assert_array_equal(actual, desired)
 
 
-class TestThread(object):
+class TestThread:
     # make sure each state produces the same sequence even in threads
     def setup(self):
         self.seeds = range(4)
@@ -2239,7 +2286,7 @@ class TestThread(object):
 
 
 # See Issue #4263
-class TestSingleEltArrayInput(object):
+class TestSingleEltArrayInput:
     def setup(self):
         self.argOne = np.array([2])
         self.argTwo = np.array([3])
@@ -2322,3 +2369,72 @@ class TestSingleEltArrayInput(object):
 
             out = func(self.argOne, self.argTwo[0], self.argThree)
             assert_equal(out.shape, self.tgtShape)
+
+
+@pytest.mark.parametrize("config", JUMP_TEST_DATA)
+def test_jumped(config):
+    # Each config contains the initial seed, a number of raw steps
+    # the md5 hashes of the initial and the final states' keys and
+    # the position of of the initial and the final state.
+    # These were produced using the original C implementation.
+    seed = config["seed"]
+    steps = config["steps"]
+
+    mt19937 = MT19937(seed)
+    # Burn step
+    mt19937.random_raw(steps)
+    key = mt19937.state["state"]["key"]
+    if sys.byteorder == 'big':
+        key = key.byteswap()
+    md5 = hashlib.md5(key)
+    assert mt19937.state["state"]["pos"] == config["initial"]["pos"]
+    assert md5.hexdigest() == config["initial"]["key_md5"]
+
+    jumped = mt19937.jumped()
+    key = jumped.state["state"]["key"]
+    if sys.byteorder == 'big':
+        key = key.byteswap()
+    md5 = hashlib.md5(key)
+    assert jumped.state["state"]["pos"] == config["jumped"]["pos"]
+    assert md5.hexdigest() == config["jumped"]["key_md5"]
+
+
+def test_broadcast_size_error():
+    mu = np.ones(3)
+    sigma = np.ones((4, 3))
+    size = (10, 4, 2)
+    assert random.normal(mu, sigma, size=(5, 4, 3)).shape == (5, 4, 3)
+    with pytest.raises(ValueError):
+        random.normal(mu, sigma, size=size)
+    with pytest.raises(ValueError):
+        random.normal(mu, sigma, size=(1, 3))
+    with pytest.raises(ValueError):
+        random.normal(mu, sigma, size=(4, 1, 1))
+    # 1 arg
+    shape = np.ones((4, 3))
+    with pytest.raises(ValueError):
+        random.standard_gamma(shape, size=size)
+    with pytest.raises(ValueError):
+        random.standard_gamma(shape, size=(3,))
+    with pytest.raises(ValueError):
+        random.standard_gamma(shape, size=3)
+    # Check out
+    out = np.empty(size)
+    with pytest.raises(ValueError):
+        random.standard_gamma(shape, out=out)
+
+    # 3 arg
+    a = random.chisquare(5, size=3)
+    b = random.chisquare(5, size=(4, 3))
+    c = random.chisquare(5, size=(5, 4, 3))
+    assert random.noncentral_f(a, b, c).shape == (5, 4, 3)
+    with pytest.raises(ValueError, match=r"Output size \(6, 5, 1, 1\) is"):
+        random.noncentral_f(a, b, c, size=(6, 5, 1, 1))
+
+
+def test_broadcast_size_scalar():
+    mu = np.ones(3)
+    sigma = np.ones(3)
+    random.normal(mu, sigma, size=3)
+    with pytest.raises(ValueError):
+        random.normal(mu, sigma, size=2)
index 3a937f997a43b28b55d1a1104c318e6d7a6f24f4..456c932d4cb2b7d471b595b7df1003289abbdf67 100644 (file)
@@ -1,6 +1,4 @@
-import sys
 from numpy.testing import (assert_, assert_array_equal)
-from numpy.compat import long
 import numpy as np
 import pytest
 from numpy.random import Generator, MT19937
@@ -8,7 +6,7 @@ from numpy.random import Generator, MT19937
 mt19937 = Generator(MT19937())
 
 
-class TestRegression(object):
+class TestRegression:
 
     def test_VonMises_range(self):
         # Make sure generated random variables are in [-pi, pi].
@@ -42,13 +40,6 @@ class TestRegression(object):
         msg = "Frequency was %f, should be < 0.23" % freq
         assert_(freq < 0.23, msg)
 
-    def test_permutation_longs(self):
-        mt19937 = Generator(MT19937(1234))
-        a = mt19937.permutation(12)
-        mt19937 = Generator(MT19937(1234))
-        b = mt19937.permutation(long(12))
-        assert_array_equal(a, b)
-
     def test_shuffle_mixed_dimension(self):
         # Test for trac ticket #2074
         for t in [[1, 2, 3, None],
@@ -56,9 +47,10 @@ class TestRegression(object):
                   [1, (2, 2), (3, 3), None],
                   [(1, 1), 2, 3, None]]:
             mt19937 = Generator(MT19937(12345))
-            shuffled = list(t)
+            shuffled = np.array(t, dtype=object)
             mt19937.shuffle(shuffled)
-            assert_array_equal(shuffled, [t[2], t[0], t[3], t[1]])
+            expected = np.array([t[2], t[0], t[3], t[1]], dtype=object)
+            assert_array_equal(np.array(shuffled, dtype=object), expected)
 
     def test_call_within_randomstate(self):
         # Check that custom BitGenerator does not call into global state
@@ -118,7 +110,7 @@ class TestRegression(object):
         # a segfault on garbage collection.
         # See gh-7719
         mt19937 = Generator(MT19937(1234))
-        a = np.array([np.arange(1), np.arange(4)])
+        a = np.array([np.arange(1), np.arange(4)], dtype=object)
 
         for _ in range(1000):
             mt19937.shuffle(a)
@@ -137,7 +129,7 @@ class TestRegression(object):
         assert_array_equal(perm, np.array([2, 0, 1]))
         assert_array_equal(orig, np.arange(3).view(N))
 
-        class M(object):
+        class M:
             a = np.arange(5)
 
             def __array__(self):
index 3785405eb324c8e73124461211a35c3bbb664edd..276b5bc81c5e74a1310fbfd4a7fa78f01ed3145f 100644 (file)
@@ -1,4 +1,3 @@
-from __future__ import division, absolute_import, print_function
 import warnings
 
 import numpy as np
@@ -11,7 +10,7 @@ from numpy import random
 import sys
 
 
-class TestSeed(object):
+class TestSeed:
     def test_scalar(self):
         s = np.random.RandomState(0)
         assert_equal(s.randint(1000), 684)
@@ -50,7 +49,7 @@ class TestSeed(object):
                                                           [4, 5, 6]])
 
 
-class TestBinomial(object):
+class TestBinomial:
     def test_n_zero(self):
         # Tests the corner case of n == 0 for the binomial distribution.
         # binomial(0, p) should be zero for any p in [0, 1].
@@ -65,7 +64,7 @@ class TestBinomial(object):
         assert_raises(ValueError, random.binomial, 1, np.nan)
 
 
-class TestMultinomial(object):
+class TestMultinomial:
     def test_basic(self):
         random.multinomial(100, [0.2, 0.8])
 
@@ -99,7 +98,7 @@ class TestMultinomial(object):
         assert_raises(ValueError, np.random.multinomial, 10, np.array([[0, 1], [1, 0]]))
 
 
-class TestSetState(object):
+class TestSetState:
     def setup(self):
         self.seed = 1234567890
         self.prng = random.RandomState(self.seed)
@@ -147,7 +146,7 @@ class TestSetState(object):
         self.prng.negative_binomial(0.5, 0.5)
 
 
-class TestRandint(object):
+class TestRandint:
 
     rfunc = np.random.randint
 
@@ -285,7 +284,7 @@ class TestRandint(object):
             assert_equal(type(sample), dt)
 
 
-class TestRandomDist(object):
+class TestRandomDist:
     # Make sure the random distribution returns the correct value for a
     # given seed
 
@@ -986,7 +985,7 @@ class TestRandomDist(object):
         assert_array_equal(actual, desired)
 
 
-class TestBroadcast(object):
+class TestBroadcast:
     # tests that functions that broadcast behave
     # correctly when presented with non-scalar arguments
     def setup(self):
@@ -1556,7 +1555,7 @@ class TestBroadcast(object):
         assert_raises(ValueError, logseries, bad_p_two * 3)
 
 
-class TestThread(object):
+class TestThread:
     # make sure each state produces the same sequence even in threads
     def setup(self):
         self.seeds = range(4)
@@ -1600,7 +1599,7 @@ class TestThread(object):
 
 
 # See Issue #4263
-class TestSingleEltArrayInput(object):
+class TestSingleEltArrayInput:
     def setup(self):
         self.argOne = np.array([2])
         self.argTwo = np.array([3])
index 3626f2c3335d0806c03c95bd552248fed112c46f..edd7811bf5c707e58a6b0facfc1dbaaaeacbb746 100644 (file)
@@ -61,7 +61,7 @@ def assert_mt19937_state_equal(a, b):
     assert_equal(a['gauss'], b['gauss'])
 
 
-class TestSeed(object):
+class TestSeed:
     def test_scalar(self):
         s = random.RandomState(0)
         assert_equal(s.randint(1000), 684)
@@ -108,7 +108,7 @@ class TestSeed(object):
         assert_raises(ValueError, random.RandomState, MT19937)
 
 
-class TestBinomial(object):
+class TestBinomial:
     def test_n_zero(self):
         # Tests the corner case of n == 0 for the binomial distribution.
         # binomial(0, p) should be zero for any p in [0, 1].
@@ -123,7 +123,7 @@ class TestBinomial(object):
         assert_raises(ValueError, random.binomial, 1, np.nan)
 
 
-class TestMultinomial(object):
+class TestMultinomial:
     def test_basic(self):
         random.multinomial(100, [0.2, 0.8])
 
@@ -168,7 +168,7 @@ class TestMultinomial(object):
         assert_array_equal(non_contig, contig)
 
 
-class TestSetState(object):
+class TestSetState:
     def setup(self):
         self.seed = 1234567890
         self.random_state = random.RandomState(self.seed)
@@ -255,7 +255,7 @@ class TestSetState(object):
         assert repr(self.random_state).startswith('RandomState(MT19937)')
 
 
-class TestRandint(object):
+class TestRandint:
 
     rfunc = random.randint
 
@@ -416,7 +416,7 @@ class TestRandint(object):
             assert_equal(type(sample), dt)
 
 
-class TestRandomDist(object):
+class TestRandomDist:
     # Make sure the random distribution returns the correct value for a
     # given seed
 
@@ -1269,7 +1269,7 @@ class TestRandomDist(object):
         assert_array_equal(actual, desired)
 
 
-class TestBroadcast(object):
+class TestBroadcast:
     # tests that functions that broadcast behave
     # correctly when presented with non-scalar arguments
     def setup(self):
@@ -1856,7 +1856,7 @@ class TestBroadcast(object):
         assert_raises(ValueError, logseries, bad_p_two * 3)
 
 
-class TestThread(object):
+class TestThread:
     # make sure each state produces the same sequence even in threads
     def setup(self):
         self.seeds = range(4)
@@ -1903,7 +1903,7 @@ class TestThread(object):
 
 
 # See Issue #4263
-class TestSingleEltArrayInput(object):
+class TestSingleEltArrayInput:
     def setup(self):
         self.argOne = np.array([2])
         self.argTwo = np.array([3])
index bdc2214b6ee5e2987ea937a9fd73be70addaa3ce..4eb82fc4ca9333f60483157144ef4786bbfca708 100644 (file)
@@ -5,13 +5,12 @@ import pytest
 from numpy.testing import (
     assert_, assert_array_equal, assert_raises,
     )
-from numpy.compat import long
 import numpy as np
 
 from numpy import random
 
 
-class TestRegression(object):
+class TestRegression:
 
     def test_VonMises_range(self):
         # Make sure generated random variables are in [-pi, pi].
@@ -52,13 +51,6 @@ class TestRegression(object):
         msg = "Frequency was %f, should be < 0.23" % freq
         assert_(freq < 0.23, msg)
 
-    def test_permutation_longs(self):
-        random.seed(1234)
-        a = random.permutation(12)
-        random.seed(1234)
-        b = random.permutation(long(12))
-        assert_array_equal(a, b)
-
     def test_shuffle_mixed_dimension(self):
         # Test for trac ticket #2074
         for t in [[1, 2, 3, None],
@@ -68,7 +60,8 @@ class TestRegression(object):
             random.seed(12345)
             shuffled = list(t)
             random.shuffle(shuffled)
-            assert_array_equal(shuffled, [t[0], t[3], t[1], t[2]])
+            expected = np.array([t[0], t[3], t[1], t[2]], dtype=object)
+            assert_array_equal(np.array(shuffled, dtype=object), expected)
 
     def test_call_within_randomstate(self):
         # Check that custom RandomState does not call into global state
@@ -128,7 +121,7 @@ class TestRegression(object):
         # a segfault on garbage collection.
         # See gh-7719
         random.seed(1234)
-        a = np.array([np.arange(1), np.arange(4)])
+        a = np.array([np.arange(1), np.arange(4)], dtype=object)
 
         for _ in range(1000):
             random.shuffle(a)
@@ -147,7 +140,7 @@ class TestRegression(object):
         assert_array_equal(perm, np.array([0, 2, 1]))
         assert_array_equal(orig, np.arange(3).view(N))
 
-        class M(object):
+        class M:
             a = np.arange(5)
 
             def __array__(self):
index 509e2d57ff284d2c7724acc67ea5e9c031a7a2e5..2786222871735d18a3b1e551a78118d8e4383b31 100644 (file)
@@ -1,15 +1,12 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 from numpy.testing import (
     assert_, assert_array_equal, assert_raises,
     )
 from numpy import random
-from numpy.compat import long
 import numpy as np
 
 
-class TestRegression(object):
+class TestRegression:
 
     def test_VonMises_range(self):
         # Make sure generated random variables are in [-pi, pi].
@@ -50,13 +47,6 @@ class TestRegression(object):
         msg = "Frequency was %f, should be < 0.23" % freq
         assert_(freq < 0.23, msg)
 
-    def test_permutation_longs(self):
-        np.random.seed(1234)
-        a = np.random.permutation(12)
-        np.random.seed(1234)
-        b = np.random.permutation(long(12))
-        assert_array_equal(a, b)
-
     def test_shuffle_mixed_dimension(self):
         # Test for trac ticket #2074
         for t in [[1, 2, 3, None],
@@ -66,7 +56,8 @@ class TestRegression(object):
             np.random.seed(12345)
             shuffled = list(t)
             random.shuffle(shuffled)
-            assert_array_equal(shuffled, [t[0], t[3], t[1], t[2]])
+            expected = np.array([t[0], t[3], t[1], t[2]], dtype=object)
+            assert_array_equal(np.array(shuffled, dtype=object), expected)
 
     def test_call_within_randomstate(self):
         # Check that custom RandomState does not call into global state
@@ -126,7 +117,7 @@ class TestRegression(object):
         # a segfault on garbage collection.
         # See gh-7719
         np.random.seed(1234)
-        a = np.array([np.arange(1), np.arange(4)])
+        a = np.array([np.arange(1), np.arange(4)], dtype=object)
 
         for _ in range(1000):
             np.random.shuffle(a)
@@ -145,7 +136,7 @@ class TestRegression(object):
         assert_array_equal(perm, np.array([0, 2, 1]))
         assert_array_equal(orig, np.arange(3).view(N))
 
-        class M(object):
+        class M:
             a = np.arange(5)
 
             def __array__(self):
index fe23680edcfd8f0465ce16fe625d9656b33cfd16..f08cf80faafa2fc1a369eaf7dd4d6fcccd5e9158 100644 (file)
@@ -1,5 +1,5 @@
 import numpy as np
-from numpy.testing import assert_array_equal
+from numpy.testing import assert_array_equal, assert_array_compare
 
 from numpy.random import SeedSequence
 
@@ -52,3 +52,29 @@ def test_reference_data():
         assert_array_equal(state, expected)
         state64 = ss.generate_state(len(expected64), dtype=np.uint64)
         assert_array_equal(state64, expected64)
+
+
+def test_zero_padding():
+    """ Ensure that the implicit zero-padding does not cause problems.
+    """
+    # Ensure that large integers are inserted in little-endian fashion to avoid
+    # trailing 0s.
+    ss0 = SeedSequence(42)
+    ss1 = SeedSequence(42 << 32)
+    assert_array_compare(
+        np.not_equal,
+        ss0.generate_state(4),
+        ss1.generate_state(4))
+
+    # Ensure backwards compatibility with the original 0.17 release for small
+    # integers and no spawn key.
+    expected42 = np.array([3444837047, 2669555309, 2046530742, 3581440988],
+                          dtype=np.uint32)
+    assert_array_equal(SeedSequence(42).generate_state(4), expected42)
+
+    # Regression test for gh-16539 to ensure that the implicit 0s don't
+    # conflict with spawn keys.
+    assert_array_compare(
+        np.not_equal,
+        SeedSequence(42, spawn_key=(0,)).generate_state(4),
+        expected42)
index 58ef6a09af0dd355b106a2d1a2d7d023d1ca3f56..ebfc6825ebb9642049ea8de6f61c27c2c5e9c0fe 100644 (file)
@@ -1,5 +1,4 @@
 import pickle
-import time
 from functools import partial
 
 import numpy as np
@@ -92,7 +91,7 @@ def warmup(rg, n=None):
     rg.random(n, dtype=np.float32)
 
 
-class RNG(object):
+class RNG:
     @classmethod
     def setup_class(cls):
         # Overridden in test classes. Place holder to silence IDE noise
index 4ccdaeea5e94830655424f4a5c642f8aea9e2f95..52db6a68bbd9f32d0808228d97877ce5c35d149b 100644 (file)
@@ -1,6 +1,4 @@
-#!/usr/bin/env python
-from __future__ import division, print_function
-
+#!/usr/bin/env python3
 
 def configuration(parent_package='',top_path=None):
     from numpy.distutils.misc_util import Configuration
@@ -20,7 +18,7 @@ def configuration(parent_package='',top_path=None):
     config.add_subpackage('random')
     config.add_subpackage('testing')
     config.add_data_dir('doc')
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
     config.make_config_py() # installs __config__.py
     return config
 
index a8bd4fc1560ca49966cf9811e5af21ec2102a205..e1f87621f9e7f16a6636a272f575b34e950bdf73 100644 (file)
@@ -5,8 +5,6 @@ in a single location, so that test scripts can just import it and work right
 away.
 
 """
-from __future__ import division, absolute_import, print_function
-
 from unittest import TestCase
 
 from ._private.utils import *
index 24c4e385d1d1709e025fb2f2e49641633a2f47ff..b4b6259a0497dea5634b0acf17794653a01e70e9 100644 (file)
@@ -13,14 +13,7 @@ function name, setup and teardown functions and so on - see
 ``nose.tools`` for more information.
 
 """
-from __future__ import division, absolute_import, print_function
-
-try:
-    # Accessing collections abstract classes from collections
-    # has been deprecated since Python 3.3
-    import collections.abc as collections_abc
-except ImportError:
-    import collections as collections_abc
+import collections.abc
 
 from .utils import SkipTest, assert_warns, HAS_REFCOUNT
 
@@ -131,7 +124,7 @@ def skipif(skip_condition, msg=None):
         import nose
 
         # Allow for both boolean or callable skip conditions.
-        if isinstance(skip_condition, collections_abc.Callable):
+        if isinstance(skip_condition, collections.abc.Callable):
             skip_val = lambda: skip_condition()
         else:
             skip_val = lambda: skip_condition
@@ -159,8 +152,7 @@ def skipif(skip_condition, msg=None):
             if skip_val():
                 raise SkipTest(get_msg(f, msg))
             else:
-                for x in f(*args, **kwargs):
-                    yield x
+                yield from f(*args, **kwargs)
 
         # Choose the right skipper to use when building the actual decorator.
         if nose.util.isgenerator(f):
@@ -207,7 +199,7 @@ def knownfailureif(fail_condition, msg=None):
         msg = 'Test skipped due to known failure'
 
     # Allow for both boolean or callable known failure conditions.
-    if isinstance(fail_condition, collections_abc.Callable):
+    if isinstance(fail_condition, collections.abc.Callable):
         fail_val = lambda: fail_condition()
     else:
         fail_val = lambda: fail_condition
@@ -262,7 +254,7 @@ def deprecated(conditional=True):
             with assert_warns(DeprecationWarning):
                 f(*args, **kwargs)
 
-        if isinstance(conditional, collections_abc.Callable):
+        if isinstance(conditional, collections.abc.Callable):
             cond = conditional()
         else:
             cond = conditional
index e99bbc97de2db45a4257ff50d6f2ec6d9c2dd7b3..69e19e9594d4f7a3c65d334e368193911ef71c68 100644 (file)
@@ -4,8 +4,6 @@
 # Because this module imports nose directly, it should not
 # be used except by nosetester.py to avoid a general NumPy
 # dependency on nose.
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 import doctest
@@ -212,7 +210,7 @@ class NumpyDoctest(npd.Doctest):
         # starting Python and executing "import numpy as np", and,
         # for SciPy packages, an additional import of the local
         # package (so that scipy.linalg.basic.py's doctests have an
-        # implicit "from scipy import linalg" as well.
+        # implicit "from scipy import linalg" as well).
         #
         # Note: __file__ allows the doctest in NoseTester to run
         # without producing an error
@@ -268,7 +266,7 @@ class NumpyDoctest(npd.Doctest):
         return npd.Doctest.wantFile(self, file)
 
 
-class Unplugger(object):
+class Unplugger:
     """ Nose plugin to remove named plugin late in loading
 
     By default it removes the "doctest" plugin.
index 19569a5098a1b745c2859c9137248c7d652b3e86..bd6d002aa535c42ccd36d0a5dc6d47a41db7db3d 100644 (file)
@@ -4,12 +4,9 @@ Nose test running.
 This module implements ``test()`` and ``bench()`` functions for NumPy modules.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 import warnings
-from numpy.compat import basestring
 import numpy as np
 
 from .utils import import_nose, suppress_warnings
@@ -112,7 +109,7 @@ def run_module_suite(file_to_run=None, argv=None):
     nose.run(argv=argv, addplugins=[KnownFailurePlugin()])
 
 
-class NoseTester(object):
+class NoseTester:
     """
     Nose test runner.
 
@@ -214,7 +211,7 @@ class NoseTester(object):
         '''
         argv = [__file__, self.package_path, '-s']
         if label and label != 'full':
-            if not isinstance(label, basestring):
+            if not isinstance(label, str):
                 raise TypeError('Selection label should be a string')
             if label == 'fast':
                 label = 'not slow'
@@ -421,7 +418,7 @@ class NoseTester(object):
 
         _warn_opts = dict(develop=(Warning,),
                           release=())
-        if isinstance(raise_warnings, basestring):
+        if isinstance(raise_warnings, str):
             raise_warnings = _warn_opts[raise_warnings]
 
         with suppress_warnings("location") as sup:
@@ -450,20 +447,6 @@ class NoseTester(object):
                 warnings.simplefilter("always")
                 from ...distutils import cpuinfo
             sup.filter(category=UserWarning, module=cpuinfo)
-            # See #7949: Filter out deprecation warnings due to the -3 flag to
-            # python 2
-            if sys.version_info.major == 2 and sys.py3kwarning:
-                # This is very specific, so using the fragile module filter
-                # is fine
-                import threading
-                sup.filter(DeprecationWarning,
-                           r"sys\.exc_clear\(\) not supported in 3\.x",
-                           module=threading)
-                sup.filter(DeprecationWarning, message=r"in 3\.x, __setslice__")
-                sup.filter(DeprecationWarning, message=r"in 3\.x, __getslice__")
-                sup.filter(DeprecationWarning, message=r"buffer\(\) not supported in 3\.x")
-                sup.filter(DeprecationWarning, message=r"CObject type is not supported in 3\.x")
-                sup.filter(DeprecationWarning, message=r"comparing unequal types not supported in 3\.x")
             # Filter out some deprecation warnings inside nose 1.3.7 when run
             # on python 3.5b2. See
             #     https://github.com/nose-devs/nose/issues/929
index 489d8e09a0ad01fae680adaf2a85c16cd6014f51..3bd8ede91fad8a253dbe5dc775eb8848a0e6ba6d 100644 (file)
@@ -31,11 +31,10 @@ either expressed or implied, of David Wolever.
 
 """
 import re
-import sys
 import inspect
 import warnings
 from functools import wraps
-from types import MethodType as MethodType
+from types import MethodType
 from collections import namedtuple
 
 try:
@@ -45,30 +44,6 @@ except ImportError:
 
 from unittest import TestCase
 
-PY2 = sys.version_info[0] == 2
-
-
-if PY2:
-    from types import InstanceType
-    lzip = zip
-    text_type = unicode
-    bytes_type = str
-    string_types = basestring,
-    def make_method(func, instance, type):
-        return MethodType(func, instance, type)
-else:
-    # Python 3 doesn't have an InstanceType, so just use a dummy type.
-    class InstanceType():
-        pass
-    lzip = lambda *a: list(zip(*a))
-    text_type = str
-    string_types = str,
-    bytes_type = bytes
-    def make_method(func, instance, type):
-        if instance is None:
-            return func
-        return MethodType(func, instance)
-
 _param = namedtuple("param", "args kwargs")
 
 class param(_param):
@@ -122,7 +97,7 @@ class param(_param):
             """
         if isinstance(args, param):
             return args
-        elif isinstance(args, string_types):
+        elif isinstance(args, (str,)):
             args = (args, )
         try:
             return cls(*args)
@@ -179,7 +154,7 @@ def parameterized_argument_value_pairs(func, p):
 
     named_args = argspec.args[arg_offset:]
 
-    result = lzip(named_args, p.args)
+    result = list(zip(named_args, p.args))
     named_args = argspec.args[len(result) + arg_offset:]
     varargs = p.args[len(result):]
 
@@ -214,11 +189,11 @@ def short_repr(x, n=64):
     """
 
     x_repr = repr(x)
-    if isinstance(x_repr, bytes_type):
+    if isinstance(x_repr, bytes):
         try:
-            x_repr = text_type(x_repr, "utf-8")
+            x_repr = str(x_repr, "utf-8")
         except UnicodeDecodeError:
-            x_repr = text_type(x_repr, "latin1")
+            x_repr = str(x_repr, "latin1")
     if len(x_repr) > n:
         x_repr = x_repr[:n//2] + "..." + x_repr[len(x_repr) - n//2:]
     return x_repr
@@ -246,7 +221,7 @@ def default_doc_func(func, num, p):
 def default_name_func(func, num, p):
     base_name = func.__name__
     name_suffix = "_%s" %(num, )
-    if len(p.args) > 0 and isinstance(p.args[0], string_types):
+    if len(p.args) > 0 and isinstance(p.args[0], (str,)):
         name_suffix += "_" + parameterized.to_safe_name(p.args[0])
     return base_name + name_suffix
 
@@ -271,7 +246,7 @@ def set_test_runner(name):
 def detect_runner():
     """ Guess which test runner we're using by traversing the stack and looking
         for the first matching module. This *should* be reasonably safe, as
-        it's done during test disocvery where the test runner should be the
+        it's done during test discovery where the test runner should be the
         stack frame immediately outside. """
     if _test_runner_override is not None:
         return _test_runner_override
@@ -286,17 +261,14 @@ def detect_runner():
             if module in _test_runners:
                 _test_runner_guess = module
                 break
-            if record[1].endswith("python2.6/unittest.py"):
-                _test_runner_guess = "unittest"
-                break
         else:
             _test_runner_guess = None
     return _test_runner_guess
 
-class parameterized(object):
+class parameterized:
     """ Parameterize a test case::
 
-            class TestInt(object):
+            class TestInt:
                 @parameterized([
                     ("A", 10),
                     ("F", 15),
@@ -324,15 +296,6 @@ class parameterized(object):
         @wraps(test_func)
         def wrapper(test_self=None):
             test_cls = test_self and type(test_self)
-            if test_self is not None:
-                if issubclass(test_cls, InstanceType):
-                    raise TypeError((
-                        "@parameterized can't be used with old-style classes, but "
-                        "%r has an old-style class. Consider using a new-style "
-                        "class, or '@parameterized.expand' "
-                        "(see http://stackoverflow.com/q/54867/71522 for more "
-                        "information on old-style classes)."
-                    ) %(test_self, ))
 
             original_doc = wrapper.__doc__
             for num, args in enumerate(wrapper.parameterized_input):
@@ -365,15 +328,7 @@ class parameterized(object):
         # Python 3 doesn't let us pull the function out of a bound method.
         unbound_func = nose_func
         if test_self is not None:
-            # Under nose on Py2 we need to return an unbound method to make
-            # sure that the `self` in the method is properly shared with the
-            # `self` used in `setUp` and `tearDown`. But only there. Everyone
-            # else needs a bound method.
-            func_self = (
-                None if PY2 and detect_runner() == "nose" else
-                test_self
-            )
-            nose_func = make_method(nose_func, func_self, type(test_self))
+            nose_func = MethodType(nose_func, test_self)
         return unbound_func, (nose_func, ) + p.args + (p.kwargs or {}, )
 
     def assert_not_in_testcase_subclass(self):
index d00538c19c3a37dfaf2dd6454d1d1d21bf82cfe5..4097a67387224860b7a3476678ace5c76936081f 100644 (file)
@@ -2,8 +2,6 @@
 Utility function to facilitate testing.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import os
 import sys
 import platform
@@ -21,12 +19,9 @@ import pprint
 
 from numpy.core import(
      intp, float32, empty, arange, array_repr, ndarray, isnat, array)
-import numpy.__config__
+import numpy.linalg.lapack_lite
 
-if sys.version_info[0] >= 3:
-    from io import StringIO
-else:
-    from StringIO import StringIO
+from io import StringIO
 
 __all__ = [
         'assert_equal', 'assert_almost_equal', 'assert_approx_equal',
@@ -54,7 +49,7 @@ verbose = 0
 
 IS_PYPY = platform.python_implementation() == 'PyPy'
 HAS_REFCOUNT = getattr(sys, 'getrefcount', None) is not None
-HAS_LAPACK64 = hasattr(numpy.__config__, 'lapack_ilp64_opt_info')
+HAS_LAPACK64 = numpy.linalg.lapack_lite._ilp64
 
 
 def import_nose():
@@ -197,9 +192,8 @@ elif sys.platform[:5] == 'linux':
 
         """
         try:
-            f = open(_proc_pid_stat, 'r')
-            l = f.readline().split(' ')
-            f.close()
+            with open(_proc_pid_stat, 'r') as f:
+                l = f.readline().split(' ')
             return int(l[22])
         except Exception:
             return
@@ -226,9 +220,8 @@ if sys.platform[:5] == 'linux':
         if not _load_time:
             _load_time.append(time.time())
         try:
-            f = open(_proc_pid_stat, 'r')
-            l = f.readline().split(' ')
-            f.close()
+            with open(_proc_pid_stat, 'r') as f:
+                l = f.readline().split(' ')
             return int(l[13])
         except Exception:
             return int(100*(time.time()-_load_time[0]))
@@ -291,7 +284,7 @@ def assert_equal(actual, desired, err_msg='', verbose=True):
     the scalar.
 
     This function handles NaN comparisons as if NaN was a "normal" number.
-    That is, no assertion is raised if both objects have NaNs in the same
+    That is, AssertionError is not raised if both objects have NaNs in the same
     positions.  This is in contrast to the IEEE standard on NaNs, which says
     that NaN compared to anything must return False.
 
@@ -537,7 +530,8 @@ def assert_almost_equal(actual,desired,decimal=7,err_msg='',verbose=True):
         ...
     AssertionError:
     Arrays are not almost equal to 9 decimals
-    Mismatch: 50%
+    <BLANKLINE>
+    Mismatched elements: 1 / 2 (50%)
     Max absolute difference: 6.66669964e-09
     Max relative difference: 2.85715698e-09
      x: array([1.         , 2.333333333])
@@ -911,7 +905,8 @@ def assert_array_equal(x, y, err_msg='', verbose=True):
         ...
     AssertionError:
     Arrays are not equal
-    Mismatch: 33.3%
+    <BLANKLINE>
+    Mismatched elements: 1 / 3 (33.3%)
     Max absolute difference: 4.4408921e-16
     Max relative difference: 1.41357986e-16
      x: array([1.      , 3.141593,      nan])
@@ -994,7 +989,8 @@ def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True):
         ...
     AssertionError:
     Arrays are not almost equal to 5 decimals
-    Mismatch: 33.3%
+    <BLANKLINE>
+    Mismatched elements: 1 / 3 (33.3%)
     Max absolute difference: 6.e-05
     Max relative difference: 2.57136612e-05
      x: array([1.     , 2.33333,     nan])
@@ -1006,6 +1002,7 @@ def assert_array_almost_equal(x, y, decimal=6, err_msg='', verbose=True):
         ...
     AssertionError:
     Arrays are not almost equal to 5 decimals
+    <BLANKLINE>
     x and y nan location mismatch:
      x: array([1.     , 2.33333,     nan])
      y: array([1.     , 2.33333, 5.     ])
@@ -1093,7 +1090,8 @@ def assert_array_less(x, y, err_msg='', verbose=True):
         ...
     AssertionError:
     Arrays are not less-ordered
-    Mismatch: 33.3%
+    <BLANKLINE>
+    Mismatched elements: 1 / 3 (33.3%)
     Max absolute difference: 1.
     Max relative difference: 0.5
      x: array([ 1.,  1., nan])
@@ -1104,7 +1102,8 @@ def assert_array_less(x, y, err_msg='', verbose=True):
         ...
     AssertionError:
     Arrays are not less-ordered
-    Mismatch: 50%
+    <BLANKLINE>
+    Mismatched elements: 1 / 2 (50%)
     Max absolute difference: 2.
     Max relative difference: 0.66666667
      x: array([1., 4.])
@@ -1115,6 +1114,7 @@ def assert_array_less(x, y, err_msg='', verbose=True):
         ...
     AssertionError:
     Arrays are not less-ordered
+    <BLANKLINE>
     (shapes (3,), (1,) mismatch)
      x: array([1., 2., 3.])
      y: array([4])
@@ -1346,14 +1346,7 @@ def assert_raises_regex(exception_class, expected_regexp, *args, **kwargs):
 
     """
     __tracebackhide__ = True  # Hide traceback for py.test
-
-    if sys.version_info.major >= 3:
-        funcname = _d.assertRaisesRegex
-    else:
-        # Only present in Python 2.7, missing from unittest in 2.6
-        funcname = _d.assertRaisesRegexp
-
-    return funcname(exception_class, expected_regexp, *args, **kwargs)
+    return _d.assertRaisesRegex(exception_class, expected_regexp, *args, **kwargs)
 
 
 def decorate_methods(cls, decorator, testmatch=None):
@@ -1458,7 +1451,9 @@ def _assert_valid_refcount(op):
     """
     if not HAS_REFCOUNT:
         return True
-    import numpy as np, gc
+
+    import gc
+    import numpy as np
 
     b = np.arange(100*100).reshape(100, 100)
     c = b
@@ -1621,6 +1616,12 @@ def assert_array_max_ulp(a, b, maxulp=1, dtype=None):
     AssertionError
         If one or more elements differ by more than `maxulp`.
 
+    Notes
+    -----
+    For computing the ULP difference, this API does not differentiate between
+    various representations of NAN (ULP difference between 0x7fc00000 and 0xffc00000
+    is zero).
+
     See Also
     --------
     assert_array_almost_equal_nulp : Compare two arrays relatively to their
@@ -1636,8 +1637,9 @@ def assert_array_max_ulp(a, b, maxulp=1, dtype=None):
     import numpy as np
     ret = nulp_diff(a, b, dtype)
     if not np.all(ret <= maxulp):
-        raise AssertionError("Arrays are not almost equal up to %g ULP" %
-                             maxulp)
+        raise AssertionError("Arrays are not almost equal up to %g "
+                             "ULP (max difference is %g ULP)" %
+                             (maxulp, np.max(ret)))
     return ret
 
 
@@ -1660,6 +1662,12 @@ def nulp_diff(x, y, dtype=None):
         number of representable floating point numbers between each item in x
         and y.
 
+    Notes
+    -----
+    For computing the ULP difference, this API does not differentiate between
+    various representations of NAN (ULP difference between 0x7fc00000 and 0xffc00000
+    is zero).
+
     Examples
     --------
     # By definition, epsilon is the smallest number such as 1 + eps != 1, so
@@ -1679,8 +1687,11 @@ def nulp_diff(x, y, dtype=None):
     if np.iscomplexobj(x) or np.iscomplexobj(y):
         raise NotImplementedError("_nulp not implemented for complex array")
 
-    x = np.array(x, dtype=t)
-    y = np.array(y, dtype=t)
+    x = np.array([x], dtype=t)
+    y = np.array([y], dtype=t)
+
+    x[np.isnan(x)] = np.nan
+    y[np.isnan(y)] = np.nan
 
     if not x.shape == y.shape:
         raise ValueError("x and y do not have the same shape: %s - %s" %
@@ -2002,7 +2013,7 @@ class clear_and_catch_warnings(warnings.catch_warnings):
                 mod.__warningregistry__.update(self._warnreg_copies[mod])
 
 
-class suppress_warnings(object):
+class suppress_warnings:
     """
     Context manager and decorator doing much the same as
     ``warnings.catch_warnings``.
@@ -2217,8 +2228,7 @@ class suppress_warnings(object):
         del self._filters
 
     def _showwarning(self, message, category, filename, lineno,
-                     *args, **kwargs):
-        use_warnmsg = kwargs.pop("use_warnmsg", None)
+                     *args, use_warnmsg=None, **kwargs):
         for cat, _, pattern, mod, rec in (
                 self._suppressions + self._tmp_suppressions)[::-1]:
             if (issubclass(category, cat) and
index 72b22cee1ccd6cd72f8c2078b6ebbf16940ceea7..8024df12856f564a86be2d5a94e3788323796b73 100755 (executable)
@@ -1,13 +1,11 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """Prints type-coercion tables for the built-in NumPy types
 
 """
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 
 # Generic object that can be added, but doesn't do anything else
-class GenericObject(object):
+class GenericObject:
     def __init__(self, v):
         self.v = v
 
index 7c3f2fbdfd66477ec92fd47545c1c07d13142da5..13191f13fe0c9af128b7223c4a25037ab75eac9a 100755 (executable)
@@ -1,13 +1,11 @@
-#!/usr/bin/env python
-from __future__ import division, print_function
-
+#!/usr/bin/env python3
 
 def configuration(parent_package='',top_path=None):
     from numpy.distutils.misc_util import Configuration
     config = Configuration('testing', parent_package, top_path)
 
     config.add_subpackage('_private')
-    config.add_data_dir('tests')
+    config.add_subpackage('tests')
     return config
 
 if __name__ == '__main__':
index c029bf90c11996f2b4aa988d05294fba63f8c6a7..b60d6dfbce90b673c35f3d23f6f4da3dbbb08152 100644 (file)
@@ -2,8 +2,6 @@
 Test the decorators from ``testing.decorators``.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import warnings
 import pytest
 
@@ -23,7 +21,7 @@ else:
 
 
 @pytest.mark.skipif(not HAVE_NOSE, reason="Needs nose")
-class TestNoseDecorators(object):
+class TestNoseDecorators:
     # These tests are run in a class for simplicity while still
     # getting a report on each, skipped or success.
 
@@ -108,8 +106,7 @@ class TestNoseDecorators(object):
     def test_skip_generators_hardcoded(self):
         @dec.knownfailureif(True, "This test is known to fail")
         def g1(x):
-            for i in range(x):
-                yield i
+            yield from range(x)
 
         try:
             for j in g1(10):
@@ -121,8 +118,7 @@ class TestNoseDecorators(object):
 
         @dec.knownfailureif(False, "This test is NOT known to fail")
         def g2(x):
-            for i in range(x):
-                yield i
+            yield from range(x)
             raise self.DidntSkipException('FAIL')
 
         try:
@@ -139,8 +135,7 @@ class TestNoseDecorators(object):
 
         @dec.knownfailureif(skip_tester, "This test is known to fail")
         def g1(x):
-            for i in range(x):
-                yield i
+            yield from range(x)
 
         try:
             skip_flag = 'skip me!'
@@ -153,8 +148,7 @@ class TestNoseDecorators(object):
 
         @dec.knownfailureif(skip_tester, "This test is NOT known to fail")
         def g2(x):
-            for i in range(x):
-                yield i
+            yield from range(x)
             raise self.DidntSkipException('FAIL')
 
         try:
index b77cd93e0b5ccbb319a65550bf87f8500648f954..92c2156d814a96e3b8167dedb2e0590cdbe5fac6 100644 (file)
@@ -1,8 +1,6 @@
 """ Doctests for NumPy-specific nose/doctest modifications
 
 """
-from __future__ import division, absolute_import, print_function
-
 #FIXME: None of these tests is run, because 'check' is not a recognized
 # testing prefix.
 
index 1e3f527154ec77824d27f81ceecd140ad1199681..6a6cc664a3cc1fcd10b8efcff7753342aa89579f 100644 (file)
@@ -1,10 +1,7 @@
-from __future__ import division, absolute_import, print_function
-
 import warnings
 import sys
 import os
 import itertools
-import textwrap
 import pytest
 import weakref
 
@@ -20,7 +17,7 @@ from numpy.testing import (
 from numpy.core.overrides import ARRAY_FUNCTION_ENABLED
 
 
-class _GenericTest(object):
+class _GenericTest:
 
     def _test_equal(self, a, b):
         self._assert_func(a, b)
@@ -211,7 +208,7 @@ class TestArrayEqual(_GenericTest):
         self._test_not_equal(b, a)
 
 
-class TestBuildErrorMessage(object):
+class TestBuildErrorMessage:
 
     def test_build_err_msg_defaults(self):
         x = np.array([1.00001, 2.00002, 3.00003])
@@ -343,24 +340,6 @@ class TestEqual(TestArrayEqual):
         self._assert_func(x, x)
         self._test_not_equal(x, y)
 
-    def test_error_message(self):
-        with pytest.raises(AssertionError) as exc_info:
-            self._assert_func(np.array([1, 2]), np.array([[1, 2]]))
-        msg = str(exc_info.value)
-        msg2 = msg.replace("shapes (2L,), (1L, 2L)", "shapes (2,), (1, 2)")
-        msg_reference = textwrap.dedent("""\
-
-        Arrays are not equal
-
-        (shapes (2,), (1, 2) mismatch)
-         x: array([1, 2])
-         y: array([[1, 2]])""")
-
-        try:
-            assert_equal(msg, msg_reference)
-        except AssertionError:
-            assert_equal(msg2, msg_reference)
-
     def test_object(self):
         #gh-12942
         import datetime
@@ -618,14 +597,14 @@ class TestAlmostEqual(_GenericTest):
         self._assert_func(a, a)
 
 
-class TestApproxEqual(object):
+class TestApproxEqual:
 
     def setup(self):
         self._assert_func = assert_approx_equal
 
-    def test_simple_arrays(self):
-        x = np.array([1234.22])
-        y = np.array([1234.23])
+    def test_simple_0d_arrays(self):
+        x = np.array(1234.22)
+        y = np.array(1234.23)
 
         self._assert_func(x, y, significant=5)
         self._assert_func(x, y, significant=6)
@@ -661,7 +640,7 @@ class TestApproxEqual(object):
         assert_raises(AssertionError, lambda: self._assert_func(ainf, anan))
 
 
-class TestArrayAssertLess(object):
+class TestArrayAssertLess:
 
     def setup(self):
         self._assert_func = assert_array_less
@@ -771,7 +750,7 @@ class TestArrayAssertLess(object):
 
 
 @pytest.mark.skip(reason="The raises decorator depends on Nose")
-class TestRaises(object):
+class TestRaises:
 
     def setup(self):
         class MyException(Exception):
@@ -805,7 +784,7 @@ class TestRaises(object):
             raise AssertionError("should have raised an AssertionError")
 
 
-class TestWarns(object):
+class TestWarns:
 
     def test_warn(self):
         def f():
@@ -856,7 +835,7 @@ class TestWarns(object):
             raise AssertionError("wrong warning caught by assert_warn")
 
 
-class TestAssertAllclose(object):
+class TestAssertAllclose:
 
     def test_simple(self):
         x = 1e-3
@@ -926,7 +905,7 @@ class TestAssertAllclose(object):
         assert_('Max relative difference: 0.5' in msg)
 
 
-class TestArrayAlmostEqualNulp(object):
+class TestArrayAlmostEqualNulp:
 
     def test_float64_pass(self):
         # The number of units of least precision
@@ -962,6 +941,17 @@ class TestArrayAlmostEqualNulp(object):
         assert_raises(AssertionError, assert_array_almost_equal_nulp,
                       x, y, nulp)
 
+    def test_float64_ignore_nan(self):
+        # Ignore ULP differences between various NAN's
+        # Note that MIPS may reverse quiet and signaling nans
+        # so we use the builtin version as a base.
+        offset = np.uint64(0xffffffff)
+        nan1_i64 = np.array(np.nan, dtype=np.float64).view(np.uint64)
+        nan2_i64 = nan1_i64 ^ offset  # nan payload on MIPS is all ones.
+        nan1_f64 = nan1_i64.view(np.float64)
+        nan2_f64 = nan2_i64.view(np.float64)
+        assert_array_max_ulp(nan1_f64, nan2_f64, 0)
+
     def test_float32_pass(self):
         nulp = 5
         x = np.linspace(-20, 20, 50, dtype=np.float32)
@@ -992,6 +982,17 @@ class TestArrayAlmostEqualNulp(object):
         assert_raises(AssertionError, assert_array_almost_equal_nulp,
                       x, y, nulp)
 
+    def test_float32_ignore_nan(self):
+        # Ignore ULP differences between various NAN's
+        # Note that MIPS may reverse quiet and signaling nans
+        # so we use the builtin version as a base.
+        offset = np.uint32(0xffff)
+        nan1_i32 = np.array(np.nan, dtype=np.float32).view(np.uint32)
+        nan2_i32 = nan1_i32 ^ offset  # nan payload on MIPS is all ones.
+        nan1_f32 = nan1_i32.view(np.float32)
+        nan2_f32 = nan2_i32.view(np.float32)
+        assert_array_max_ulp(nan1_f32, nan2_f32, 0)
+
     def test_float16_pass(self):
         nulp = 5
         x = np.linspace(-4, 4, 10, dtype=np.float16)
@@ -1022,6 +1023,17 @@ class TestArrayAlmostEqualNulp(object):
         assert_raises(AssertionError, assert_array_almost_equal_nulp,
                       x, y, nulp)
 
+    def test_float16_ignore_nan(self):
+        # Ignore ULP differences between various NAN's
+        # Note that MIPS may reverse quiet and signaling nans
+        # so we use the builtin version as a base.
+        offset = np.uint16(0xff)
+        nan1_i16 = np.array(np.nan, dtype=np.float16).view(np.uint16)
+        nan2_i16 = nan1_i16 ^ offset  # nan payload on MIPS is all ones.
+        nan1_f16 = nan1_i16.view(np.float16)
+        nan2_f16 = nan2_i16.view(np.float16)
+        assert_array_max_ulp(nan1_f16, nan2_f16, 0)
+
     def test_complex128_pass(self):
         nulp = 5
         x = np.linspace(-20, 20, 50, dtype=np.float64)
@@ -1123,7 +1135,7 @@ class TestArrayAlmostEqualNulp(object):
                       xi, y + y*1j, nulp)
 
 
-class TestULP(object):
+class TestULP:
 
     def test_equal(self):
         x = np.random.randn(10)
@@ -1179,7 +1191,7 @@ class TestULP(object):
                           maxulp=maxulp))
 
 
-class TestStringEqual(object):
+class TestStringEqual:
     def test_simple(self):
         assert_string_equal("hello", "hello")
         assert_string_equal("hello\nmultiline", "hello\nmultiline")
@@ -1241,7 +1253,7 @@ def test_warn_len_equal_call_scenarios():
     # check that no assertion is uncaught
 
     # parallel scenario -- no warning issued yet
-    class mod(object):
+    class mod:
         pass
 
     mod_inst = mod()
@@ -1251,7 +1263,7 @@ def test_warn_len_equal_call_scenarios():
 
     # serial test scenario -- the __warningregistry__
     # attribute should be present
-    class mod(object):
+    class mod:
         def __init__(self):
             self.__warningregistry__ = {'warning1':1,
                                         'warning2':2}
@@ -1526,7 +1538,7 @@ def test_clear_and_catch_warnings_inherit():
 
 
 @pytest.mark.skipif(not HAS_REFCOUNT, reason="Python lacks refcounts")
-class TestAssertNoGcCycles(object):
+class TestAssertNoGcCycles:
     """ Test assert_no_gc_cycles """
     def test_passes(self):
         def no_cycle():
@@ -1560,7 +1572,7 @@ class TestAssertNoGcCycles(object):
         error, instead of hanging forever trying to clear it.
         """
 
-        class ReferenceCycleInDel(object):
+        class ReferenceCycleInDel:
             """
             An object that not only contains a reference cycle, but creates new
             cycles whenever it's garbage-collected and its __del__ runs
index 975f6ad5d1eb42ddac15db391c19046677821663..753258c1368385cfdc4bc908006a62f954561701 100644 (file)
@@ -3,8 +3,6 @@ Back compatibility utils module. It will import the appropriate
 set of tools
 
 """
-from __future__ import division, absolute_import, print_function
-
 import warnings
 
 # 2018-04-04, numpy 1.15.0 ImportWarning
index 521208c36d3d20f62fd41cbff0e55c41eb6b9820..af3730df1cc9aeb067f20081cae5866eb6f1c992 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import pytest
 import weakref
@@ -37,7 +35,7 @@ else:
                     reason="ctypes not available in this python")
 @pytest.mark.skipif(sys.platform == 'cygwin',
                     reason="Known to fail on cygwin")
-class TestLoadLibrary(object):
+class TestLoadLibrary:
     def test_basic(self):
         try:
             # Should succeed
@@ -63,7 +61,7 @@ class TestLoadLibrary(object):
             print(msg)
 
 
-class TestNdpointer(object):
+class TestNdpointer:
     def test_dtype(self):
         dt = np.intc
         p = ndpointer(dtype=dt)
@@ -130,7 +128,7 @@ class TestNdpointer(object):
 
 @pytest.mark.skipif(ctypes is None,
                     reason="ctypes not available on this python installation")
-class TestNdpointerCFunc(object):
+class TestNdpointerCFunc:
     def test_arguments(self):
         """ Test that arguments are coerced from arrays """
         c_forward_pointer.restype = ctypes.c_void_p
@@ -186,7 +184,7 @@ class TestNdpointerCFunc(object):
 
 @pytest.mark.skipif(ctypes is None,
                     reason="ctypes not available on this python installation")
-class TestAsArray(object):
+class TestAsArray:
     def test_array(self):
         from ctypes import c_int
 
@@ -277,7 +275,7 @@ class TestAsArray(object):
 
 @pytest.mark.skipif(ctypes is None,
                     reason="ctypes not available on this python installation")
-class TestAsCtypesType(object):
+class TestAsCtypesType:
     """ Test conversion from dtypes to ctypes types """
     def test_scalar(self):
         dt = np.dtype('<u2')
index 38a7e39dfb698cb7ae81ca5f56cd8bdb5c31d994..0e93c4848d75432c97189273f4f2e0cbc6c04e20 100644 (file)
@@ -1,13 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
-# As we are testing matrices, we ignore its PendingDeprecationWarnings
-try:
-    import pytest
-    pytestmark = pytest.mark.filterwarnings(
-        'ignore:the matrix subclass is not:PendingDeprecationWarning')
-except ImportError:
-    pass
-
 import numpy as np
 import numpy.matlib
 from numpy.testing import assert_array_equal, assert_
index 7fac8fd22ead4afd5130a7990a483f19280b7ddf..916ab93830df8b3ce6a879aa2cdb93b1b86dfc85 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import re
 
 import numpy as np
index 0484bb8cdb45fb0d7121951a32068ae9580315cc..fb7ec5d83eb42f842395e8e2d329c72b12100dde 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 import sys
 import subprocess
 import pkgutil
@@ -30,9 +28,6 @@ def check_dir(module, module_name=None):
     return results
 
 
-@pytest.mark.skipif(
-    sys.version_info[0] < 3,
-    reason="NumPy exposes slightly different functions on Python 2")
 def test_numpy_namespace():
     # None of these objects are publicly documented to be part of the main
     # NumPy namespace (some are useful though, others need to be cleaned up)
@@ -50,7 +45,6 @@ def test_numpy_namespace():
         'fastCopyAndTranspose': 'numpy.core._multiarray_umath._fastCopyAndTranspose',
         'get_array_wrap': 'numpy.lib.shape_base.get_array_wrap',
         'get_include': 'numpy.lib.utils.get_include',
-        'int_asbuffer': 'numpy.core._multiarray_umath.int_asbuffer',
         'mafromtxt': 'numpy.lib.npyio.mafromtxt',
         'ndfromtxt': 'numpy.lib.npyio.ndfromtxt',
         'recfromcsv': 'numpy.lib.npyio.recfromcsv',
@@ -100,6 +94,12 @@ def test_import_lazy_import(name):
     assert name in dir(np)
 
 
+def test_dir_testing():
+    """Assert that output of dir has only one "testing/tester"
+    attribute without duplicate"""
+    assert len(dir(np)) == len(set(dir(np)))
+    
+
 def test_numpy_linalg():
     bad_results = check_dir(np.linalg)
     assert bad_results == {}
@@ -228,7 +228,6 @@ PRIVATE_BUT_PRESENT_MODULES = ['numpy.' + s for s in [
     "distutils.command.install_data",
     "distutils.command.install_headers",
     "distutils.command.sdist",
-    "distutils.compat",
     "distutils.conv_template",
     "distutils.core",
     "distutils.extension",
@@ -299,6 +298,7 @@ PRIVATE_BUT_PRESENT_MODULES = ['numpy.' + s for s in [
     "matrixlib",
     "matrixlib.defmatrix",
     "random.mtrand",
+    "random.bit_generator",
     "testing.print_coercion_tables",
     "testing.utils",
 ]]
index e378d1463f4bbb6db09ddb49ec8a80ab750c34f4..61ae91b00d5556e4c69fc8381eaf360716938b33 100644 (file)
@@ -1,14 +1,11 @@
-from __future__ import division, absolute_import, print_function
-
-import sys
-
 from numpy.testing import assert_raises, assert_, assert_equal
 from numpy.compat import pickle
 
-if sys.version_info[:2] >= (3, 4):
-    from importlib import reload
-else:
-    from imp import reload
+import sys
+import subprocess
+import textwrap
+from importlib import reload
+
 
 def test_numpy_reloading():
     # gh-7844. Also check that relevant globals retain their identity.
@@ -36,3 +33,25 @@ def test_novalue():
         assert_equal(repr(np._NoValue), '<no value>')
         assert_(pickle.loads(pickle.dumps(np._NoValue,
                                           protocol=proto)) is np._NoValue)
+
+
+def test_full_reimport():
+    """At the time of writing this, it is *not* truly supported, but
+    apparently enough users rely on it, for it to be an annoying change
+    when it started failing previously.
+    """
+    # Test within a new process, to ensure that we do not mess with the
+    # global state during the test run (could lead to cryptic test failures).
+    # This is generally unsafe, especially, since we also reload the C-modules.
+    code = textwrap.dedent(r"""
+        import sys
+        import numpy as np
+
+        for k in list(sys.modules.keys()):
+            if "numpy" in k:
+                del sys.modules[k]
+
+        import numpy as np
+        """)
+    p = subprocess.run([sys.executable, '-c', code])
+    assert p.returncode == 0
index e42dc25f98e93eb1a28bc53e7d1c23de71a39992..a0f2ba70a4a16ba4e8b9cf78f0f6d183372a07bc 100644 (file)
@@ -2,8 +2,6 @@
 
 Test that we can run executable scripts that have been installed with numpy.
 """
-from __future__ import division, print_function, absolute_import
-
 import sys
 import os
 import pytest
@@ -11,8 +9,7 @@ from os.path import join as pathjoin, isfile, dirname
 import subprocess
 
 import numpy as np
-from numpy.compat.py3k import basestring
-from numpy.testing import assert_, assert_equal
+from numpy.testing import assert_equal
 
 is_inplace = isfile(pathjoin(dirname(np.__file__),  '..', 'setup.py'))
 
index f5560a099a16383e2eab0dbe35f946b0c40754a5..d7a6d880cbdb7e5967bfc6cfccbb2e5a880a57f7 100644 (file)
@@ -2,77 +2,73 @@
 Tests which scan for certain occurrences in the code, they may not find
 all of these occurrences but should catch almost all.
 """
-from __future__ import division, absolute_import, print_function
-
-import sys
 import pytest
 
-if sys.version_info >= (3, 4):
-    from pathlib import Path
-    import ast
-    import tokenize
-    import numpy
-
-    class ParseCall(ast.NodeVisitor):
-        def __init__(self):
-            self.ls = []
-
-        def visit_Attribute(self, node):
-            ast.NodeVisitor.generic_visit(self, node)
-            self.ls.append(node.attr)
-
-        def visit_Name(self, node):
-            self.ls.append(node.id)
+from pathlib import Path
+import ast
+import tokenize
+import numpy
 
+class ParseCall(ast.NodeVisitor):
+    def __init__(self):
+        self.ls = []
 
-    class FindFuncs(ast.NodeVisitor):
-        def __init__(self, filename):
-            super().__init__()
-            self.__filename = filename
+    def visit_Attribute(self, node):
+        ast.NodeVisitor.generic_visit(self, node)
+        self.ls.append(node.attr)
 
-        def visit_Call(self, node):
-            p = ParseCall()
-            p.visit(node.func)
-            ast.NodeVisitor.generic_visit(self, node)
+    def visit_Name(self, node):
+        self.ls.append(node.id)
 
-            if p.ls[-1] == 'simplefilter' or p.ls[-1] == 'filterwarnings':
-                if node.args[0].s == "ignore":
-                    raise AssertionError(
-                        "ignore filter should not be used; found in "
-                        "{} on line {}".format(self.__filename, node.lineno))
 
-            if p.ls[-1] == 'warn' and (
-                    len(p.ls) == 1 or p.ls[-2] == 'warnings'):
+class FindFuncs(ast.NodeVisitor):
+    def __init__(self, filename):
+        super().__init__()
+        self.__filename = filename
 
-                if "testing/tests/test_warnings.py" == self.__filename:
-                    # This file
-                    return
+    def visit_Call(self, node):
+        p = ParseCall()
+        p.visit(node.func)
+        ast.NodeVisitor.generic_visit(self, node)
 
-                # See if stacklevel exists:
-                if len(node.args) == 3:
-                    return
-                args = {kw.arg for kw in node.keywords}
-                if "stacklevel" in args:
-                    return
+        if p.ls[-1] == 'simplefilter' or p.ls[-1] == 'filterwarnings':
+            if node.args[0].s == "ignore":
                 raise AssertionError(
                     "warnings should have an appropriate stacklevel; found in "
                     "{} on line {}".format(self.__filename, node.lineno))
 
+        if p.ls[-1] == 'warn' and (
+                len(p.ls) == 1 or p.ls[-2] == 'warnings'):
+
+            if "testing/tests/test_warnings.py" == self.__filename:
+                # This file
+                return
+
+            # See if stacklevel exists:
+            if len(node.args) == 3:
+                return
+            args = {kw.arg for kw in node.keywords}
+            if "stacklevel" in args:
+                return
+            raise AssertionError(
+                "warnings should have an appropriate stacklevel; found in "
+                "{} on line {}".format(self.__filename, node.lineno))
+
 
-    @pytest.mark.slow
-    def test_warning_calls():
-        # combined "ignore" and stacklevel error
-        base = Path(numpy.__file__).parent
+@pytest.mark.slow
+def test_warning_calls():
+    # combined "ignore" and stacklevel error
+    base = Path(numpy.__file__).parent
 
-        for path in base.rglob("*.py"):
-            if base / "testing" in path.parents:
-                continue
-            if path == base / "__init__.py":
-                continue
-            if path == base / "random" / "__init__.py":
-                continue
-            # use tokenize to auto-detect encoding on systems where no
-            # default encoding is defined (e.g. LANG='C')
-            with tokenize.open(str(path)) as file:
-                tree = ast.parse(file.read())
-                FindFuncs(path).visit(tree)
+    for path in base.rglob("*.py"):
+        if base / "testing" in path.parents:
+            continue
+        if path == base / "__init__.py":
+            continue
+        if path == base / "random" / "__init__.py":
+            continue
+        # use tokenize to auto-detect encoding on systems where no
+        # default encoding is defined (e.g. LANG='C')
+        with tokenize.open(str(path)) as file:
+            tree = ast.parse(file.read())
+            FindFuncs(path).visit(tree)
index 1f6c278cb3f04ee78ebf0569c208c887aed76db6..46239dbf5d91d268c5e26c6013175d1904d8f9ed 100644 (file)
@@ -22,13 +22,9 @@ TODO
     - fix bdist_mpkg: we build the same source twice -> how to make sure we use
       the same underlying python for egg install in venv and for bdist_mpkg
 """
-from __future__ import division, print_function
-
 import os
 import sys
 import shutil
-import subprocess
-import re
 import hashlib
 
 # The paver package needs to be installed to run tasks
@@ -41,7 +37,7 @@ from paver.easy import Bunch, options, task, sh
 #-----------------------------------
 
 # Path to the release notes
-RELEASE_NOTES = 'doc/source/release/1.18.5-notes.rst'
+RELEASE_NOTES = 'doc/source/release/1.19.0-notes.rst'
 
 
 #-------------------------------------------------------
@@ -88,12 +84,13 @@ def tarball_name(ftype='gztar'):
         Type of archive, default is 'gztar'.
 
     """
-    root = 'numpy-%s' % FULLVERSION
+    root = f'numpy-{FULLVERSION}'
     if ftype == 'gztar':
         return root + '.tar.gz'
     elif ftype == 'zip':
         return root + '.zip'
-    raise ValueError("Unknown type %s" % type)
+    raise ValueError(f"Unknown type {type}")
+
 
 @task
 def sdist(options):
index 74faefd6e7ee145cd9b5159b6eafe92ef9c85ee3..0db7f80ddec67f1e73c5cd68468003c40f678d86 100644 (file)
@@ -13,15 +13,7 @@ filterwarnings =
     ignore::UserWarning:cpuinfo,
 # Matrix PendingDeprecationWarning.
     ignore:the matrix subclass is not
-# Ignore python2.7 -3 warnings
-    ignore:sys\.exc_clear\(\) not supported in 3\.x:DeprecationWarning
-    ignore:in 3\.x, __setslice__:DeprecationWarning
-    ignore:in 3\.x, __getslice__:DeprecationWarning
-    ignore:buffer\(\) not supported in 3\.x:DeprecationWarning
-    ignore:CObject type is not supported in 3\.x:DeprecationWarning
-    ignore:comparing unequal types not supported in 3\.x:DeprecationWarning
-    ignore:the commands module has been removed in Python 3\.0:DeprecationWarning
-    ignore:The 'new' module has been removed in Python 3\.0:DeprecationWarning
+    ignore:Importing from numpy.matlib is
 
 env =
     PYTHONHASHSEED=0
index a38054f868728073576099557675166a5d28db8f..7f1d55b85cf61a2d9ea4c34d3d2abc8bfd616ceb 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 runtests.py [OPTIONS] [-- ARGS]
 
@@ -29,8 +29,6 @@ Generate C code coverage listing under build/lcov/:
     $ python runtests.py --lcov-html
 
 """
-from __future__ import division, print_function
-
 #
 # This is a generic test runner script for projects using NumPy's test
 # framework. Change the following values to adapt to your project:
@@ -127,7 +125,7 @@ def main(argv):
                               "COMMIT. Note that you need to commit your "
                               "changes first!"))
     parser.add_argument("args", metavar="ARGS", default=[], nargs=REMAINDER,
-                        help="Arguments to pass to Nose, Python or shell")
+                        help="Arguments to pass to Nose, asv, Python or shell")
     args = parser.parse_args(argv)
 
     if args.durations < 0:
@@ -164,8 +162,10 @@ def main(argv):
         site_dir = os.path.sep.join(_temp.__file__.split(os.path.sep)[:-2])
 
     extra_argv = args.args[:]
-    if extra_argv and extra_argv[0] == '--':
-        extra_argv = extra_argv[1:]
+    if not args.bench:
+        # extra_argv may also lists selected benchmarks
+        if extra_argv and extra_argv[0] == '--':
+            extra_argv = extra_argv[1:]
 
     if args.python:
         # Debugging issues with warnings is much easier if you can see them
@@ -183,7 +183,7 @@ def main(argv):
             sys.modules['__main__'] = types.ModuleType('__main__')
             ns = dict(__name__='__main__',
                       __file__=extra_argv[0])
-            exec_(script, ns)
+            exec(script, ns)
             sys.exit(0)
         else:
             import code
@@ -222,13 +222,21 @@ def main(argv):
 
     if args.bench:
         # Run ASV
-        items = extra_argv
+        for i, v in enumerate(extra_argv):
+            if v.startswith("--"):
+                items = extra_argv[:i]
+                if v == "--":
+                    i += 1  # skip '--' indicating further are passed on.
+                bench_args = extra_argv[i:]
+                break
+        else:
+            items = extra_argv
+            bench_args = []
+
         if args.tests:
             items += args.tests
         if args.submodule:
             items += [args.submodule]
-
-        bench_args = []
         for a in items:
             bench_args.extend(['--bench', a])
 
@@ -481,25 +489,5 @@ def lcov_generate():
         print("HTML output generated under build/lcov/")
 
 
-#
-# Python 3 support
-#
-
-if sys.version_info[0] >= 3:
-    import builtins
-    exec_ = getattr(builtins, "exec")
-else:
-    def exec_(code, globs=None, locs=None):
-        """Execute code in a namespace."""
-        if globs is None:
-            frame = sys._getframe(1)
-            globs = frame.f_globals
-            if locs is None:
-                locs = frame.f_locals
-            del frame
-        elif locs is None:
-            locs = globs
-        exec("""exec code in globs, locs""")
-
 if __name__ == "__main__":
     main(argv=sys.argv[1:])
index 95fc9dd57428d94db419f85692fd7f3c5ff87d34..e8320581f2260aa01dad0dfced46fa541050bb79 100755 (executable)
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """ NumPy is the fundamental package for array computing with Python.
 
 It provides:
@@ -17,8 +17,6 @@ variety of databases.
 All NumPy wheels distributed on PyPI are BSD licensed.
 
 """
-from __future__ import division, print_function
-
 DOCLINES = (__doc__ or '').split("\n")
 
 import os
@@ -28,8 +26,8 @@ import textwrap
 import sysconfig
 
 
-if sys.version_info[:2] < (3, 5):
-    raise RuntimeError("Python version >= 3.5 required.")
+if sys.version_info[:2] < (3, 6):
+    raise RuntimeError("Python version >= 3.6 required.")
 
 import builtins
 
@@ -42,7 +40,6 @@ License :: OSI Approved
 Programming Language :: C
 Programming Language :: Python
 Programming Language :: Python :: 3
-Programming Language :: Python :: 3.5
 Programming Language :: Python :: 3.6
 Programming Language :: Python :: 3.7
 Programming Language :: Python :: 3.8
@@ -57,8 +54,8 @@ Operating System :: MacOS
 """
 
 MAJOR               = 1
-MINOR               = 18
-MICRO               = 5
+MINOR               = 19
+MICRO               = 0
 ISRELEASED          = True
 VERSION             = '%d.%d.%d' % (MAJOR, MINOR, MICRO)
 
@@ -164,6 +161,7 @@ def configuration(parent_package='',top_path=None):
 
     config.add_subpackage('numpy')
     config.add_data_files(('numpy', 'LICENSE.txt'))
+    config.add_data_files(('numpy', 'numpy/__init__.pxd'))
 
     config.get_version('numpy/version.py') # sets config.version
 
@@ -181,7 +179,7 @@ def check_submodules():
             if 'path' in l:
                 p = l.split('=')[-1].strip()
                 if not os.path.exists(p):
-                    raise ValueError('Submodule %s missing' % p)
+                    raise ValueError('Submodule {} missing'.format(p))
 
 
     proc = subprocess.Popen(['git', 'submodule', 'status'],
@@ -190,7 +188,8 @@ def check_submodules():
     status = status.decode("ascii", "replace")
     for line in status.splitlines():
         if line.startswith('-') or line.startswith('+'):
-            raise ValueError('Submodule not clean: %s' % line)
+            raise ValueError('Submodule not clean: {}'.format(line))
+            
 
 
 class concat_license_files():
@@ -410,7 +409,7 @@ def setup_package():
     os.chdir(src_path)
     sys.path.insert(0, src_path)
 
-    # Rewrite the version file everytime
+    # Rewrite the version file every time
     write_version_py()
 
     # The f2py scripts that will be installed
@@ -444,9 +443,9 @@ def setup_package():
         license = 'BSD',
         classifiers=[_f for _f in CLASSIFIERS.split('\n') if _f],
         platforms = ["Windows", "Linux", "Solaris", "Mac OS-X", "Unix"],
-        test_suite='nose.collector',
+        test_suite='pytest',
         cmdclass=cmdclass,
-        python_requires='>=3.5',
+        python_requires='>=3.6',
         zip_safe=False,
         entry_points={
             'console_scripts': f2py_cmds
@@ -460,8 +459,9 @@ def setup_package():
         # Raise errors for unsupported commands, improve help output, etc.
         run_build = parse_setuppy_commands()
 
-    from setuptools import setup
     if run_build:
+        # patches distutils, even though we don't use it
+        import setuptools  # noqa: F401
         from numpy.distutils.core import setup
         cwd = os.path.abspath(os.path.dirname(__file__))
         if not 'sdist' in sys.argv:
@@ -472,6 +472,7 @@ def setup_package():
         # Customize extension building
         cmdclass['build_clib'], cmdclass['build_ext'] = get_build_overrides()
     else:
+        from setuptools import setup
         # Version number is added to metadata inside configuration() if build
         # is run.
         metadata['version'] = get_version_info()[0]
index 4313a6de2cf22e3dde22e9d2b72c7db66a3ebcb7..dc3617e120d278a4c1932bbb6d49dad9038bd7aa 100644 (file)
@@ -21,9 +21,10 @@ runtime:
 
 build:
     ci:
-    # install dependencies
+    # install dependencies and newer toolchain for gfortran5
+    - sudo add-apt-repository ppa:ubuntu-toolchain-r/test
     - sudo apt-get update
-    - sudo apt-get install gcc gfortran
+    - sudo apt-get install gcc gfortran libgfortran5
     - target=$(python tools/openblas_support.py)
     - ls -lR "${target}"
     - sudo cp -r "${target}"/lib/* /usr/lib
@@ -48,7 +49,7 @@ build:
     - extra_path=$(printf "%s:" "${extra_directories[@]}")
     - export PATH="${extra_path}${PATH}"
     # check OpenBLAS version
-    - python tools/openblas_support.py --check_version 0.3.7
+    - python tools/openblas_support.py --check_version
     # run the test suite
     - python runtests.py -n --debug-info --show-build-log -- -rsx --junit-xml=$SHIPPABLE_REPO_DIR/shippable/testresults/tests.xml -n 2 --durations=10
 
index cff0763813d9838e66ebcf3ced2c95ef0e5f9812..3eba3bbd734179285d0722e2fbada38993319a73 100644 (file)
@@ -40,7 +40,7 @@
 #       List of directories to add to the header file search path.
 #           include_dirs = /usr/include:/usr/local/include
 #
-#   src_dirs 
+#   src_dirs
 #       List of directories that contain extracted source code for the
 #       dependency. For some dependencies, numpy.distutils will be able to build
 #       them from source if binaries cannot be found. The FORTRAN BLAS and
@@ -56,7 +56,7 @@
 #           search_static_first = false
 #
 #   runtime_library_dirs/rpath
-#       List of directories that contains the libraries that should be 
+#       List of directories that contains the libraries that should be
 #       used at runtime, thereby disregarding the LD_LIBRARY_PATH variable.
 #       See 'library_dirs' for formatting on different platforms.
 #           runtime_library_dirs = /opt/blas/lib:/opt/lapack/lib
 
 # Defaults
 # ========
-# The settings given here will apply to all other sections if not overridden.
+# The settings here will apply to all sections as general defaults
 # This is a good place to add general library and include directories like
 # /usr/local/{lib,include}
-#
-#[ALL]
-#library_dirs = /usr/local/lib
-#include_dirs = /usr/local/include
-#
+# These settings apply when they are not overridden in the sections below.
+# Note that the standard paths (e.g. `/usr/lib`) are not searched if you
+# override these settings, unless they are explicitly included.
+# The ``:`` is os.pathsep, which is ``;`` on windows
+#[DEFAULT]
+#library_dirs = /usr/local/lib64:/usr/local/lib:/usr/lib64:/usr/lib
+#include_dirs = /usr/local/include:/usr/include
+
 
 # ATLAS
 # -----
 # for your configuration (in the following example we installed OpenBLAS with
 # ``make install PREFIX=/opt/OpenBLAS``.
 # OpenBLAS is generically installed as a shared library, to force the OpenBLAS
-# library linked to also be used at runtime you can utilize the 
+# library linked to also be used at runtime you can utilize the
 # runtime_library_dirs variable.
 #
 # **Warning**: OpenBLAS, by default, is built in multithreaded mode. Due to the
 # runtime_library_dirs = /home/username/flame/lib
 
 # MKL
-#---- 
-# Intel MKL is Intel's very optimized yet proprietary implementation of BLAS and 
+#----
+# Intel MKL is Intel's very optimized yet proprietary implementation of BLAS and
 # LAPACK. Find the latest info on building NumPy with Intel MKL in this article:
 # https://software.intel.com/en-us/articles/numpyscipy-with-intel-mkl
-# Assuming you installed the mkl in /opt/intel/compilers_and_libraries_2018/linux/mkl, 
-# for 64 bits code at Linux: 
-# [mkl] 
+# Assuming you installed the mkl in /opt/intel/compilers_and_libraries_2018/linux/mkl,
+# for 64 bits code at Linux:
+# [mkl]
 # library_dirs = /opt/intel/compilers_and_libraries_2018/linux/mkl/lib/intel64
-# include_dirs = /opt/intel/compilers_and_libraries_2018/linux/mkl/include 
+# include_dirs = /opt/intel/compilers_and_libraries_2018/linux/mkl/include
 # libraries = mkl_rt
-# 
-# For 32 bit code at Linux: 
+#
+# For 32 bit code at Linux:
 # [mkl]
 # library_dirs = /opt/intel/compilers_and_libraries_2018/linux/mkl/lib/ia32
-# include_dirs = /opt/intel/compilers_and_libraries_2018/linux/mkl/include 
+# include_dirs = /opt/intel/compilers_and_libraries_2018/linux/mkl/include
 # libraries = mkl_rt
-# 
-# On win-64, the following options compiles NumPy with the MKL library 
-# dynamically linked. 
-# [mkl] 
+#
+# On win-64, the following options compiles NumPy with the MKL library
+# dynamically linked.
+# [mkl]
 # include_dirs = C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2018\windows\mkl\include
 # library_dirs = C:\Program Files (x86)\IntelSWTools\compilers_and_libraries_2018\windows\mkl\lib\intel64
 # libraries = mkl_rt
 
 # UMFPACK
 # -------
-# The UMFPACK library is used in scikits.umfpack to factor large sparse matrices. 
+# The UMFPACK library is used in scikits.umfpack to factor large sparse matrices.
 # It, in turn, depends on the AMD library for reordering the matrices for
 # better performance.  Note that the AMD library has nothing to do with AMD
 # (Advanced Micro Devices), the CPU company.
 #[fftw]
 #libraries = fftw3
 #
-# For djbfft, numpy.distutils will look for either djbfft.a or libdjbfft.a . 
+# For djbfft, numpy.distutils will look for either djbfft.a or libdjbfft.a .
 #[djbfft]
 #include_dirs = /usr/local/djbfft/include
 #library_dirs = /usr/local/djbfft/lib
index 299089674549bb0f7ecb5d89a386f370228d69d5..5db322b9bed138716056c06613ea24845cbcbb55 100644 (file)
@@ -1,9 +1,9 @@
-cython==0.29.15
-pytest==5.3.5
-pytz==2019.3
+cython==0.29.17
+hypothesis==5.12.0
+pytest==5.4.2
+pytz==2020.1
 pytest-cov==2.8.1
 pickle5; python_version == '3.7'
 pickle5; python_version == '3.6' and platform_python_implementation != 'PyPy'
-pickle5>=0.0.10; python_version == '3.5' and platform_python_implementation != 'PyPy'
 # for numpy.random.test.test_extending
 cffi
index d1e656f90254da8ef46bfefe76c779a962fc675d..eeefe1704a6ca76f1c3ae80c1621b4a3b15acc58 100644 (file)
@@ -22,7 +22,7 @@ cdef void pyhook(void *old, void *new, size_t size, void *user_data):
            PyLong_FromVoidPtr(new),
            size)
 
-class NumpyAllocHook(object):
+class NumpyAllocHook:
     def __init__(self, callback):
         self.callback = callback
 
index a75c95e911e21004367db06536643c68e87bc8d8..4462f9f4ec8c954ca98de0d7fbee312db73d8248 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, print_function
-
 from distutils.core import setup
 from distutils.extension import Extension
 from Cython.Distutils import build_ext
index d259938002f9b5d682ebe49309993eab1a3db01b..2a80d8f877ea5238a08ea1206f3cc1d95f354e70 100644 (file)
@@ -1,11 +1,9 @@
-from __future__ import division, absolute_import, print_function
-
 import numpy as np
 import gc
 import inspect
 from alloc_hook import NumpyAllocHook
 
-class AllocationTracker(object):
+class AllocationTracker:
     def __init__(self, threshold=0):
         '''track numpy allocations of size threshold bytes or more.'''
 
@@ -108,30 +106,29 @@ class AllocationTracker(object):
         self.current_line = line
 
     def write_html(self, filename):
-        f = open(filename, "w")
-        f.write('<HTML><HEAD><script src="sorttable.js"></script></HEAD><BODY>\n')
-        f.write('<TABLE class="sortable" width=100%>\n')
-        f.write("<TR>\n")
-        cols = "event#,lineinfo,bytes allocated,bytes freed,#allocations,#frees,max memory usage,long lived bytes".split(',')
-        for header in cols:
-            f.write("  <TH>{0}</TH>".format(header))
-        f.write("\n</TR>\n")
-        for idx, event in enumerate(self.allocation_trace):
+        with open(filename, "w") as f:
+            f.write('<HTML><HEAD><script src="sorttable.js"></script></HEAD><BODY>\n')
+            f.write('<TABLE class="sortable" width=100%>\n')
             f.write("<TR>\n")
-            event = [idx] + list(event)
-            for col, val in zip(cols, event):
-                if col == 'lineinfo':
-                    # special handling
-                    try:
-                        filename, line, module, code, index = val
-                        val = "{0}({1}): {2}".format(filename, line, code[index])
-                    except Exception:
-                        # sometimes this info is not available (from eval()?)
-                        val = str(val)
-                f.write("  <TD>{0}</TD>".format(val))
+            cols = "event#,lineinfo,bytes allocated,bytes freed,#allocations,#frees,max memory usage,long lived bytes".split(',')
+            for header in cols:
+                f.write("  <TH>{0}</TH>".format(header))
             f.write("\n</TR>\n")
-        f.write("</TABLE></BODY></HTML>\n")
-        f.close()
+            for idx, event in enumerate(self.allocation_trace):
+                f.write("<TR>\n")
+                event = [idx] + list(event)
+                for col, val in zip(cols, event):
+                    if col == 'lineinfo':
+                        # special handling
+                        try:
+                            filename, line, module, code, index = val
+                            val = "{0}({1}): {2}".format(filename, line, code[index])
+                        except Exception:
+                            # sometimes this info is not available (from eval()?)
+                            val = str(val)
+                    f.write("  <TD>{0}</TD>".format(val))
+                f.write("\n</TR>\n")
+            f.write("</TABLE></BODY></HTML>\n")
 
 
 if __name__ == '__main__':
index 327f6dc05b0e9c52308428290ecb2f13dd8c0f42..bd3eeaee9776a94ed858dc32f9b12f1efe68f436 100755 (executable)
@@ -1,12 +1,9 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 A script to create C code-coverage reports based on the output of
 valgrind's callgrind tool.
 
 """
-from __future__ import division, absolute_import, print_function
-
-import optparse
 import os
 import re
 import sys
@@ -145,39 +142,43 @@ def collect_stats(files, fd, pattern):
 
 
 if __name__ == '__main__':
-    parser = optparse.OptionParser(
-        usage="[options] callgrind_file(s)")
-    parser.add_option(
-        '-d', '--directory', dest='directory',
-        default='coverage',
-        help='Destination directory for output [default: coverage]')
-    parser.add_option(
-        '-p', '--pattern', dest='pattern',
-        default='numpy',
-        help='Regex pattern to match against source file paths [default: numpy]')
-    parser.add_option(
-        '-f', '--format', dest='format', default=[],
-        action='append', type='choice', choices=('text', 'html'),
-        help="Output format(s) to generate, may be 'text' or 'html' [default: both]")
-    (options, args) = parser.parse_args()
+    import argparse
+
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument(
+        'callgrind_file', nargs='+',
+        help='One or more callgrind files')
+    parser.add_argument(
+        '-d', '--directory', default='coverage',
+        help='Destination directory for output (default: %(default)s)')
+    parser.add_argument(
+        '-p', '--pattern', default='numpy',
+        help='Regex pattern to match against source file paths '
+             '(default: %(default)s)')
+    parser.add_argument(
+        '-f', '--format', action='append', default=[],
+        choices=['text', 'html'],
+        help="Output format(s) to generate. "
+             "If option not provided, both will be generated.")
+    args = parser.parse_args()
 
     files = SourceFiles()
-    for log_file in args:
+    for log_file in args.callgrind_file:
         log_fd = open(log_file, 'r')
-        collect_stats(files, log_fd, options.pattern)
+        collect_stats(files, log_fd, args.pattern)
         log_fd.close()
 
-    if not os.path.exists(options.directory):
-        os.makedirs(options.directory)
+    if not os.path.exists(args.directory):
+        os.makedirs(args.directory)
 
-    if options.format == []:
+    if args.format == []:
         formats = ['text', 'html']
     else:
-        formats = options.format
+        formats = args.format
     if 'text' in formats:
-        files.write_text(options.directory)
+        files.write_text(args.directory)
     if 'html' in formats:
         if not has_pygments:
             print("Pygments 0.11 or later is required to generate HTML")
             sys.exit(1)
-        files.write_html(options.directory)
+        files.write_html(args.directory)
index b135b14e51cdc27e6d08c0c4260fc6ac09fe346c..92f33af244531c107dc1d409eb87396f1a8d2b39 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- encoding:utf-8 -*-
 """
 Script to generate contributor and pull request lists
@@ -33,18 +33,14 @@ From the bash command line with $GITHUB token::
     $ ./tools/announce $GITHUB v1.13.0..v1.14.0 > 1.14.0-changelog.rst
 
 """
-from __future__ import print_function, division
-
 import os
 import sys
 import re
-import codecs
 from git import Repo
 from github import Github
 
-if sys.version_info.major < 3:
-    UTF8Writer = codecs.getwriter('utf8')
-    sys.stdout = UTF8Writer(sys.stdout)
+if sys.version_info[:2] < (3, 6):
+    raise RuntimeError("Python version must be >= 3.6")
 
 this_repo = Repo(os.path.join(os.path.dirname(__file__), ".."))
 
index a98966880d0fd2c7f3b7f6335084d3e41049ea8a..ae530548459b0f84e53a3dbccf8151ba2d8c9732 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import argparse
 import subprocess
index 6c4591fd866d077b2d15cd83f4b9a5e9b2ef10e6..c2e03154945d01770f3c765e0515be198c73aea5 100755 (executable)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 
 import sys
 import toml
index a35d7b724df63883262da894079ffc5a64900abd..14c37d4d2b97a4d33471d666d7bbc3b32af15d09 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import division, absolute_import, print_function
-
 # Run svn log -l <some number>
 
 import re
index e5352a9542b1d38122bdcc286c188e3541a19095..65b79f7161b66c4e3c5c9ee98c231a4b8af648f0 100755 (executable)
@@ -30,8 +30,6 @@ Note: this script does not check any of the dependent C libraries; it only
 operates on the Cython .pyx files.
 """
 
-from __future__ import division, print_function, absolute_import
-
 import os
 import re
 import sys
@@ -75,8 +73,7 @@ def process_pyx(fromfile, tofile):
         required_version = LooseVersion('0.29.14')
 
         if LooseVersion(cython_version) < required_version:
-            raise RuntimeError('Building {} requires Cython >= {}'.format(
-                VENDOR, required_version))
+            raise RuntimeError(f'Building {VENDOR} requires Cython >= {required_version}')
         subprocess.check_call(
             [sys.executable, '-m', 'cython'] + flags + ["-o", tofile, fromfile])
 
@@ -181,13 +178,13 @@ def process(path, fromfile, tofile, processor_function, hash_db):
     fulltopath = os.path.join(path, tofile)
     current_hash = get_hash(fullfrompath, fulltopath)
     if current_hash == hash_db.get(normpath(fullfrompath), None):
-        print('%s has not changed' % fullfrompath)
+        print(f'{fullfrompath} has not changed')
         return
 
     orig_cwd = os.getcwd()
     try:
         os.chdir(path)
-        print('Processing %s' % fullfrompath)
+        print(f'Processing {fullfrompath}')
         processor_function(fromfile, tofile)
     finally:
         os.chdir(orig_cwd)
diff --git a/tools/download-wheels.py b/tools/download-wheels.py
new file mode 100644 (file)
index 0000000..276fcc6
--- /dev/null
@@ -0,0 +1,80 @@
+#!/usr/bin/env python
+"""
+Download NumPy wheels from Anaconda staging area.
+
+"""
+import sys
+import os
+import re
+import shutil
+import argparse
+
+import urllib3
+from bs4 import BeautifulSoup
+
+__version__ = '0.1'
+
+# Edit these for other projects.
+STAGING_URL = 'https://anaconda.org/multibuild-wheels-staging/numpy'
+PREFIX = '^.*numpy-'
+
+def get_wheel_names(version):
+    """ Get wheel names from Anaconda HTML directory.
+
+    This looks in the Anaconda multibuild-wheels-staging page and
+    parses the HTML to get all the wheel names for a release version.
+
+    Parameters
+    ----------
+    version : str
+        The release version. For instance, "1.18.3".
+
+    """
+    http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED')
+    tmpl = re.compile(PREFIX + version + '.*\.whl$')
+    index_url =  f"{STAGING_URL}/files"
+    index_html = http.request('GET', index_url)
+    soup = BeautifulSoup(index_html.data, 'html.parser')
+    return soup.findAll(text=tmpl)
+
+
+def download_wheels(version, wheelhouse):
+    """Download release wheels.
+
+    The release wheels for the given NumPy version are downloaded
+    into the given directory.
+
+    Parameters
+    ----------
+    version : str
+        The release version. For instance, "1.18.3".
+    wheelhouse : str
+        Directory in which to download the wheels.
+
+    """
+    http = urllib3.PoolManager(cert_reqs='CERT_REQUIRED')
+    wheel_names = get_wheel_names(version)
+    for wheel_name in wheel_names:
+        wheel_url = f"{STAGING_URL}/{version}/download/{wheel_name}"
+        wheel_path = os.path.join(wheelhouse, wheel_name)
+        with open(wheel_path, 'wb') as f:
+            with http.request('GET', wheel_url, preload_content=False,) as r:
+                print(f"Downloading {wheel_name}")
+                shutil.copyfileobj(r, f)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+    parser.add_argument(
+        "version",
+         help="NumPy version to download.")
+    parser.add_argument(
+        "-w", "--wheelhouse",
+        default=os.path.join(os.getcwd(), "release", "installers"),
+        help="Directory in which to store downloaded wheels\n"
+             "[defaults to <cwd>/release/installers]")
+
+    args = parser.parse_args()
+
+    wheelhouse = os.path.expanduser(args.wheelhouse)
+    download_wheels(args.version, wheelhouse)
index 6f90001ca6b12e0565c3e45364f57c44b03ffec6..22efaae65b69c09e8915fd1d56dbe93ffd2976f6 100644 (file)
@@ -1,4 +1,4 @@
-#! /usr/bin/env python
+#!/usr/bin/env python3
 r"""
 Look for escape sequences deprecated in Python 3.6.
 
@@ -7,8 +7,6 @@ were accepted before. For instance, '\(' was previously accepted but must now
 be written as '\\(' or r'\('.
 
 """
-from __future__ import division, absolute_import, print_function
-
 import sys
 
 def main(root):
index f75f23a212d3666db4df3f117a9f96726ac309d2..50a99510450d15a062952ce3d858f591859bc971 100644 (file)
@@ -32,8 +32,6 @@ This copy of tempita was taken from https://github.com/gjhiggins/tempita
 with a few changes to remove the six dependency.
 
 """
-from __future__ import absolute_import, division, print_function
-
 import re
 import sys
 try:
@@ -48,7 +46,7 @@ import os
 import tokenize
 from ._looper import looper
 from .compat3 import (
-    PY3, bytes, basestring_, next, is_unicode, coerce_text, iteritems)
+    bytes, basestring_, next, is_unicode, coerce_text, iteritems)
 
 
 __all__ = ['TemplateError', 'Template', 'sub', 'HTMLTemplate',
@@ -92,7 +90,7 @@ def get_file_template(name, from_template):
         get_template=from_template.get_template)
 
 
-class Template(object):
+class Template:
 
     default_namespace = {
         'start_braces': '{{',
@@ -157,7 +155,7 @@ class Template(object):
             c = f.read()
         if encoding:
             c = c.decode(encoding)
-        elif PY3:
+        else:
             c = c.decode('latin-1')
         return cls(content=c, name=filename, namespace=namespace,
                    default_inherit=default_inherit, get_template=get_template)
@@ -319,11 +317,8 @@ class Template(object):
                 arg0 = e_value.args[0]
             else:
                 arg0 = coerce_text(e_value)
-            e_value.args = (self._add_line_info(arg0, pos),)            
-            if PY3:
-                raise e_value
-            else:
-                exec('raise e_type, e_value, e_traceback')
+            e_value.args = (self._add_line_info(arg0, pos),)
+            raise e_value
 
     def _exec(self, code, ns, pos):
         # __traceback_hide__ = True
@@ -335,10 +330,7 @@ class Template(object):
                 e_value.args = (self._add_line_info(e_value.args[0], pos),)
             else:
                 e_value.args = (self._add_line_info(None, pos),)
-            if PY3:
-                raise e_value
-            else:
-                exec('raise e_type, e_value, e_traceback')
+            raise e_value
 
     def _repr(self, value, pos):
         # __traceback_hide__ = True
@@ -357,10 +349,7 @@ class Template(object):
         except:
             e_type, e_value, e_traceback = sys.exc_info()
             e_value.args = (self._add_line_info(e_value.args[0], pos),)
-            if PY3:
-                raise e_value
-            else:
-                exec('raise e_type, e_value, e_traceback')
+            raise e_value
         else:
             if self._unicode and isinstance(value, bytes):
                 if not self.default_encoding:
@@ -440,7 +429,7 @@ class bunch(dict):
 ############################################################
 
 
-class html(object):
+class html:
 
     def __init__(self, value):
         self.value = value
@@ -463,14 +452,11 @@ def html_quote(value, force=True):
         return ''
     if not isinstance(value, basestring_):
         value = coerce_text(value)
-    if sys.version >= "3" and isinstance(value, bytes):
+    if isinstance(value, bytes):
         value = html_escape(value.decode('latin1'), 1)
         value = value.encode('latin1')
     else:
         value = html_escape(value, 1)
-    if sys.version < "3":
-        if is_unicode(value):
-            value = value.encode('ascii', 'xmlcharrefreplace')
     return value
 
 
@@ -522,7 +508,7 @@ def sub_html(content, **kw):
     return tmpl.substitute(kw)
 
 
-class TemplateDef(object):
+class TemplateDef:
     def __init__(self, template, func_name, func_signature,
                  body, ns, pos, bound_self=None):
         self._template = template
@@ -599,7 +585,7 @@ class TemplateDef(object):
         return values
 
 
-class TemplateObject(object):
+class TemplateObject:
 
     def __init__(self, name):
         self.__name = name
@@ -609,7 +595,7 @@ class TemplateObject(object):
         return '<%s %s>' % (self.__class__.__name__, self.__name)
 
 
-class TemplateObjectGetter(object):
+class TemplateObjectGetter:
 
     def __init__(self, template_obj):
         self.__template_obj = template_obj
@@ -622,7 +608,7 @@ class TemplateObjectGetter(object):
             self.__class__.__name__, self.__template_obj)
 
 
-class _Empty(object):
+class _Empty:
     def __call__(self, *args, **kw):
         return self
 
@@ -633,7 +619,7 @@ class _Empty(object):
         return 'Empty'
 
     def __unicode__(self):
-        return '' if PY3 else u''
+        return ''
 
     def __iter__(self):
         return iter(())
@@ -641,9 +627,6 @@ class _Empty(object):
     def __bool__(self):
         return False
 
-    if sys.version < "3":
-        __nonzero__ = __bool__
-
 Empty = _Empty()
 del _Empty
 
@@ -653,6 +636,27 @@ del _Empty
 
 
 def lex(s, name=None, trim_whitespace=True, line_offset=0, delimiters=None):
+    """
+    Lex a string into chunks:
+
+        >>> lex('hey')
+        ['hey']
+        >>> lex('hey {{you}}')
+        ['hey ', ('you', (1, 7))]
+        >>> lex('hey {{')
+        Traceback (most recent call last):
+            ...
+        tempita.TemplateError: No }} to finish last expression at line 1 column 7
+        >>> lex('hey }}')
+        Traceback (most recent call last):
+            ...
+        tempita.TemplateError: }} outside expression at line 1 column 7
+        >>> lex('hey {{ {{')
+        Traceback (most recent call last):
+            ...
+        tempita.TemplateError: {{ inside expression at line 1 column 10
+    """
+
     if delimiters is None:
         delimiters = (Template.default_namespace['start_braces'],
                       Template.default_namespace['end_braces'])
@@ -693,48 +697,6 @@ def lex(s, name=None, trim_whitespace=True, line_offset=0, delimiters=None):
         chunks = trim_lex(chunks)
     return chunks
 
-lex.__doc__ = """
-Lex a string into chunks:
-
-    >>> lex('hey')
-    ['hey']
-    >>> lex('hey {{you}}')
-    ['hey ', ('you', (1, 7))]
-    >>> lex('hey {{')
-    Traceback (most recent call last):
-        ...
-    tempita.TemplateError: No }} to finish last expression at line 1 column 7
-    >>> lex('hey }}')
-    Traceback (most recent call last):
-        ...
-    tempita.TemplateError: }} outside expression at line 1 column 7
-    >>> lex('hey {{ {{')
-    Traceback (most recent call last):
-        ...
-    tempita.TemplateError: {{ inside expression at line 1 column 10
-
-""" if PY3 else """
-Lex a string into chunks:
-
-    >>> lex('hey')
-    ['hey']
-    >>> lex('hey {{you}}')
-    ['hey ', ('you', (1, 7))]
-    >>> lex('hey {{')
-    Traceback (most recent call last):
-        ...
-    TemplateError: No }} to finish last expression at line 1 column 7
-    >>> lex('hey }}')
-    Traceback (most recent call last):
-        ...
-    TemplateError: }} outside expression at line 1 column 7
-    >>> lex('hey {{ {{')
-    Traceback (most recent call last):
-        ...
-    TemplateError: {{ inside expression at line 1 column 10
-
-"""
-
 statement_re = re.compile(r'^(?:if |elif |for |def |inherit |default |py:)')
 single_statements = ['else', 'endif', 'endfor', 'enddef', 'continue', 'break']
 trail_whitespace_re = re.compile(r'\n\r?[\t ]*$')
@@ -742,6 +704,16 @@ lead_whitespace_re = re.compile(r'^[\t ]*\n')
 
 
 def trim_lex(tokens):
+    r"""
+    Takes a lexed set of tokens, and removes whitespace when there is
+    a directive on a line by itself:
+
+       >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False)
+       >>> tokens
+       [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny']
+       >>> trim_lex(tokens)
+       [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y']
+    """
     last_trim = None
     for i in range(len(tokens)):
         current = tokens[i]
@@ -789,26 +761,6 @@ def trim_lex(tokens):
                     tokens[i + 1] = next_chunk
     return tokens
 
-trim_lex.__doc__ = r"""
-    Takes a lexed set of tokens, and removes whitespace when there is
-    a directive on a line by itself:
-
-       >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False)
-       >>> tokens
-       [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny']
-       >>> trim_lex(tokens)
-       [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y']
-    """ if PY3 else r"""
-    Takes a lexed set of tokens, and removes whitespace when there is
-    a directive on a line by itself:
-
-       >>> tokens = lex('{{if x}}\nx\n{{endif}}\ny', trim_whitespace=False)
-       >>> tokens
-       [('if x', (1, 3)), '\nx\n', ('endif', (3, 3)), '\ny']
-       >>> trim_lex(tokens)
-       [('if x', (1, 3)), 'x\n', ('endif', (3, 3)), 'y']
-    """
-
 
 def find_position(string, index, last_index, last_pos):
     """
@@ -823,18 +775,7 @@ def find_position(string, index, last_index, last_pos):
 
 
 def parse(s, name=None, line_offset=0, delimiters=None):
-
-    if delimiters is None:
-        delimiters = (Template.default_namespace['start_braces'],
-                      Template.default_namespace['end_braces'])
-    tokens = lex(s, name=name, line_offset=line_offset, delimiters=delimiters)
-    result = []
-    while tokens:
-        next_chunk, tokens = parse_expr(tokens, name)
-        result.append(next_chunk)
-    return result
-
-parse.__doc__ = r"""
+    r"""
     Parses a string into a kind of AST
 
         >>> parse('{{x}}')
@@ -889,63 +830,18 @@ parse.__doc__ = r"""
             ...
         tempita.TemplateError: Multi-line py blocks must start
             with a newline at line 1 column 3
-    """ if PY3 else r"""
-    Parses a string into a kind of AST
-
-        >>> parse('{{x}}')
-        [('expr', (1, 3), 'x')]
-        >>> parse('foo')
-        ['foo']
-        >>> parse('{{if x}}test{{endif}}')
-        [('cond', (1, 3), ('if', (1, 3), 'x', ['test']))]
-        >>> parse(
-        ...    'series->{{for x in y}}x={{x}}{{endfor}}'
-        ... )  #doctest: +NORMALIZE_WHITESPACE
-        ['series->',
-            ('for', (1, 11), ('x',), 'y', ['x=', ('expr', (1, 27), 'x')])]
-        >>> parse('{{for x, y in z:}}{{continue}}{{endfor}}')
-        [('for', (1, 3), ('x', 'y'), 'z', [('continue', (1, 21))])]
-        >>> parse('{{py:x=1}}')
-        [('py', (1, 3), 'x=1')]
-        >>> parse(
-        ...    '{{if x}}a{{elif y}}b{{else}}c{{endif}}'
-        ... )  #doctest: +NORMALIZE_WHITESPACE
-        [('cond', (1, 3), ('if', (1, 3), 'x', ['a']),
-            ('elif', (1, 12), 'y', ['b']), ('else', (1, 23), None, ['c']))]
-
-    Some exceptions::
-
-        >>> parse('{{continue}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: continue outside of for loop at line 1 column 3
-        >>> parse('{{if x}}foo')
-        Traceback (most recent call last):
-            ...
-        TemplateError: No {{endif}} at line 1 column 3
-        >>> parse('{{else}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: else outside of an if block at line 1 column 3
-        >>> parse('{{if x}}{{for x in y}}{{endif}}{{endfor}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: Unexpected endif at line 1 column 25
-        >>> parse('{{if}}{{endif}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: if with no expression at line 1 column 3
-        >>> parse('{{for x y}}{{endfor}}')
-        Traceback (most recent call last):
-            ...
-        TemplateError: Bad for (no "in") in 'x y' at line 1 column 3
-        >>> parse('{{py:x=1\ny=2}}')  #doctest: +NORMALIZE_WHITESPACE
-        Traceback (most recent call last):
-            ...
-        TemplateError: Multi-line py blocks must start
-            with a newline at line 1 column 3
     """
 
+    if delimiters is None:
+        delimiters = (Template.default_namespace['start_braces'],
+                      Template.default_namespace['end_braces'])
+    tokens = lex(s, name=name, line_offset=line_offset, delimiters=delimiters)
+    result = []
+    while tokens:
+        next_chunk, tokens = parse_expr(tokens, name)
+        result.append(next_chunk)
+    return result
+
 
 def parse_expr(tokens, name, context=()):
     if isinstance(tokens[0], basestring_):
@@ -1291,7 +1187,7 @@ def fill_command(args=None):
         template_content = sys.stdin.read()
         template_name = '<stdin>'
     else:
-        with open(template_name, 'rb', encoding="latin-1") as f: 
+        with open(template_name, 'rb', encoding="latin-1") as f:
             template_content = f.read()
     if options.use_html:
         TemplateClass = HTMLTemplate
@@ -1300,7 +1196,7 @@ def fill_command(args=None):
     template = TemplateClass(template_content, name=template_name)
     result = template.substitute(vars)
     if options.output:
-        with open(options.output, 'wb') as f: 
+        with open(options.output, 'wb') as f:
             f.write(result)
     else:
         sys.stdout.write(result)
index 047bf52926aaa53a3014c8aed08fd4de8f999345..8a1156678d0f91bbf169e9d2967d65bf86d0233c 100644 (file)
@@ -17,15 +17,13 @@ looper you can get a better sense of the context.  Use like::
     3 c
 
 """
-from __future__ import absolute_import, division, print_function
-
 import sys
 from .compat3 import basestring_
 
 __all__ = ['looper']
 
 
-class looper(object):
+class looper:
     """
     Helper for looping (particularly in templates)
 
@@ -47,7 +45,7 @@ class looper(object):
             self.__class__.__name__, self.seq)
 
 
-class looper_iter(object):
+class looper_iter:
 
     def __init__(self, seq):
         self.seq = list(seq)
@@ -63,11 +61,8 @@ class looper_iter(object):
         self.pos += 1
         return result
 
-    if sys.version < "3":
-        next = __next__
-
 
-class loop_pos(object):
+class loop_pos:
 
     def __init__(self, seq, pos):
         self.seq = seq
@@ -96,9 +91,6 @@ class loop_pos(object):
         except IndexError:
             return None
 
-    if sys.version < "3":
-        next = __next__
-
     @property
     def previous(self):
         if self.pos == 0:
index 01d7713455e081aff2cab401d4b259e15803c0de..d9d682ff55f588fd3c0edb7ade3f07d7b5a38b68 100644 (file)
@@ -1,5 +1,3 @@
-from __future__ import absolute_import, division, print_function
-
 import sys
 
 __all__ = ['PY3', 'b', 'basestring_', 'bytes', 'next', 'is_unicode',
index a8d5fb7fd06ac6db640ab4be9cf5e20c8368a45a..cbb6a5e437794c78ced4b8397a5da6b6b92ab0fa 100644 (file)
@@ -1,45 +1,60 @@
-from __future__ import division, absolute_import, print_function
+import glob
+import hashlib
 import os
+import platform
 import sys
-import glob
 import shutil
+import tarfile
 import textwrap
-import platform
-try:
-    from urllib.request import urlopen
-    from urllib.error import HTTPError
-except:
-    #Python2
-    from urllib2 import urlopen, HTTPError
+import zipfile
 
 from tempfile import mkstemp, gettempdir
-import zipfile
-import tarfile
+from urllib.request import urlopen, Request
+
+OPENBLAS_V = '0.3.9'
+# Temporary build of OpenBLAS to test a fix for dynamic detection of CPU
+OPENBLAS_LONG = 'v0.3.7-527-g79fd006c'  # the 0.3.7 is misleading
+BASE_LOC = 'https://anaconda.org/multibuild-wheels-staging/openblas-libs'
+BASEURL = f'{BASE_LOC}/{OPENBLAS_LONG}/download'
+ARCHITECTURES = ['', 'windows', 'darwin', 'aarch64', 'x86_64', 'i686', 'ppc64le', 's390x']
+sha256_vals = {
+"openblas-v0.3.7-527-g79fd006c-win_amd64-gcc_7_1_0.zip": "7249d68c02e6b6339e06edfeab1fecddf29ee1e67a3afaa77917c320c43de840",
+"openblas64_-v0.3.7-527-g79fd006c-win_amd64-gcc_7_1_0.zip": "6488e0961a5926e47242f63b63b41cfdd661e6f1d267e8e313e397cde4775c17",
+"openblas-v0.3.7-527-g79fd006c-win32-gcc_7_1_0.zip": "5fb0867ca70b1d0fdbf68dd387c0211f26903d74631420e4aabb49e94aa3930d",
+"openblas-v0.3.7-527-g79fd006c-macosx_10_9_x86_64-gf_1becaaa.tar.gz": "69434bd626bbc495da9ce8c36b005d140c75e3c47f94e88c764a199e820f9259",
+"openblas64_-v0.3.7-527-g79fd006c-macosx_10_9_x86_64-gf_1becaaa.tar.gz": "093f6d953e3fa76a86809be67bd1f0b27656671b5a55b233169cfaa43fd63e22",
+"openblas-v0.3.7-527-g79fd006c-manylinux2014_aarch64.tar.gz": "42676c69dc48cd6e412251b39da6b955a5a0e00323ddd77f9137f7c259d35319",
+"openblas64_-v0.3.7-527-g79fd006c-manylinux2014_aarch64.tar.gz": "5aec167af4052cf5e9e3e416c522d9794efabf03a2aea78b9bb3adc94f0b73d8",
+"openblas-v0.3.7-527-g79fd006c-manylinux2010_x86_64.tar.gz": "fa67c6cc29d4cc5c70a147c80526243239a6f95fc3feadcf83a78176cd9c526b",
+"openblas64_-v0.3.7-527-g79fd006c-manylinux2010_x86_64.tar.gz": "9ad34e89a5307dcf5823bf5c020580d0559a0c155fe85b44fc219752e61852b0",
+"openblas-v0.3.7-527-g79fd006c-manylinux2010_i686.tar.gz": "0b8595d316c8b7be84ab1f1d5a0c89c1b35f7c987cdaf61d441bcba7ab4c7439",
+"openblas-v0.3.7-527-g79fd006c-manylinux2014_ppc64le.tar.gz": "3e1c7d6472c34e7210e3605be4bac9ddd32f613d44297dc50cf2d067e720c4a9",
+"openblas64_-v0.3.7-527-g79fd006c-manylinux2014_ppc64le.tar.gz": "a0885873298e21297a04be6cb7355a585df4fa4873e436b4c16c0a18fc9073ea",
+"openblas-v0.3.7-527-g79fd006c-manylinux2014_s390x.tar.gz": "79b454320817574e20499d58f05259ed35213bea0158953992b910607b17f240",
+"openblas64_-v0.3.7-527-g79fd006c-manylinux2014_s390x.tar.gz": "9fddbebf5301518fc4a5d2022a61886544a0566868c8c014359a1ee6b17f2814",
+"openblas-v0.3.7-527-g79fd006c-manylinux1_i686.tar.gz": "24fb92684ec4676185fff5c9340f50c3db6075948bcef760e9c715a8974e4680",
+"openblas-v0.3.7-527-g79fd006c-manylinux1_x86_64.tar.gz": "ebb8236b57a1b4075fd5cdc3e9246d2900c133a42482e5e714d1e67af5d00e62",
+"openblas-v0.3.7-527-g79fd006c-manylinux1_i686.tar.gz": "24fb92684ec4676185fff5c9340f50c3db6075948bcef760e9c715a8974e4680",
+"openblas-v0.3.7-527-g79fd006c-manylinux1_x86_64.tar.gz": "ebb8236b57a1b4075fd5cdc3e9246d2900c133a42482e5e714d1e67af5d00e62",
+"openblas-v0.3.7-527-g79fd006c-manylinux1_i686.tar.gz": "24fb92684ec4676185fff5c9340f50c3db6075948bcef760e9c715a8974e4680",
+"openblas-v0.3.7-527-g79fd006c-manylinux1_x86_64.tar.gz": "ebb8236b57a1b4075fd5cdc3e9246d2900c133a42482e5e714d1e67af5d00e62",
+}
 
-OPENBLAS_V = 'v0.3.7'
-OPENBLAS_LONG = 'v0.3.7'
-BASE_LOC = ''
-RACKSPACE = 'https://3f23b170c54c2533c070-1c8a9b3114517dc5fe17b7c3f8c63a43.ssl.cf2.rackcdn.com'
-ARCHITECTURES = ['', 'windows', 'darwin', 'arm', 'x86', 'ppc64']
 
 IS_32BIT = sys.maxsize < 2**32
+
 def get_arch():
     if platform.system() == 'Windows':
         ret = 'windows'
     elif platform.system() == 'Darwin':
         ret = 'darwin'
-    # Python3 returns a named tuple, but Python2 does not, so we are stuck
-    elif 'arm' in os.uname()[-1]:
-        ret = 'arm';
-    elif 'aarch64' in os.uname()[-1]:
-        ret = 'arm';
-    elif 'x86' in os.uname()[-1] or os.uname()[-1] == 'i686':
-        ret = 'x86'
-    elif 'ppc64' in os.uname()[-1]:
-        ret = 'ppc64'
     else:
-        ret = ''
-    assert ret in ARCHITECTURES
+        ret = platform.uname().machine
+        # What do 32 bit machines report?
+        # If they are a docker, they can report x86_64
+        if 'x86' in ret and IS_32BIT:
+            arch = 'i686'
+    assert ret in ARCHITECTURES, f'invalid architecture {ret}'
     return ret
 
 def get_ilp64():
@@ -49,52 +64,61 @@ def get_ilp64():
         raise RuntimeError("NPY_USE_BLAS_ILP64 set on 32-bit arch")
     return "64_"
 
+def get_manylinux(arch):
+    if arch in ('x86_64', 'i686'):
+        default = '2010'
+    else:
+        default = '2014'
+    ret = os.environ.get("MB_ML_VER", default)
+    # XXX For PEP 600 this can be a glibc version
+    assert ret in ('1', '2010', '2014'), f'invalid MB_ML_VER {ret}'
+    return ret
+
+
 def download_openblas(target, arch, ilp64):
+    ml_ver = get_manylinux(arch)
     fnsuffix = {None: "", "64_": "64_"}[ilp64]
     filename = ''
-    if arch == 'arm':
-        # ARMv8 OpenBLAS built using script available here:
-        # https://github.com/tylerjereddy/openblas-static-gcc/tree/master/ARMv8
-        # build done on GCC compile farm machine named gcc115
-        # tarball uploaded manually to an unshared Dropbox location
-        filename = ('https://www.dropbox.com/s/vdeckao4omss187/'
-                    'openblas{}-{}-armv8.tar.gz?dl=1'.format(fnsuffix, OPENBLAS_V))
-        typ = 'tar.gz'
-    elif arch == 'ppc64':
-        # build script for POWER8 OpenBLAS available here:
-        # https://github.com/tylerjereddy/openblas-static-gcc/blob/master/power8
-        # built on GCC compile farm machine named gcc112
-        # manually uploaded tarball to an unshared Dropbox location
-        filename = ('https://www.dropbox.com/s/yt0d2j86x1j8nh1/'
-                    'openblas{}-{}-ppc64le-power8.tar.gz?dl=1'.format(fnsuffix, OPENBLAS_V))
+    headers = {'User-Agent': ('Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 ; '
+                              '(KHTML, like Gecko) Chrome/41.0.2228.0 '
+                              'Safari/537.3')}
+    if arch in ('aarch64', 'ppc64le', 's390x', 'x86_64', 'i686'):
+        suffix = f'manylinux{ml_ver}_{arch}.tar.gz'
+        filename = f'{BASEURL}/openblas{fnsuffix}-{OPENBLAS_LONG}-{suffix}'
         typ = 'tar.gz'
     elif arch == 'darwin':
-        filename = '{0}/openblas{1}-{2}-macosx_10_9_x86_64-gf_1becaaa.tar.gz'.format(
-                        RACKSPACE, fnsuffix, OPENBLAS_LONG)
+        suffix = 'macosx_10_9_x86_64-gf_1becaaa.tar.gz'
+        filename = f'{BASEURL}/openblas{fnsuffix}-{OPENBLAS_LONG}-{suffix}'
         typ = 'tar.gz'
     elif arch == 'windows':
         if IS_32BIT:
             suffix = 'win32-gcc_7_1_0.zip'
         else:
             suffix = 'win_amd64-gcc_7_1_0.zip'
-        filename = '{0}/openblas{1}-{2}-{3}'.format(RACKSPACE, fnsuffix, OPENBLAS_LONG, suffix)
+        filename = f'{BASEURL}/openblas{fnsuffix}-{OPENBLAS_LONG}-{suffix}'
         typ = 'zip'
-    elif arch == 'x86':
-        if IS_32BIT:
-            suffix = 'manylinux1_i686.tar.gz'
-        else:
-            suffix = 'manylinux1_x86_64.tar.gz'
-        filename = '{0}/openblas{1}-{2}-{3}'.format(RACKSPACE, fnsuffix, OPENBLAS_LONG, suffix)
-        typ = 'tar.gz'
     if not filename:
         return None
-    print("Downloading:", filename, file=sys.stderr)
-    try:
-        with open(target, 'wb') as fid:
-            fid.write(urlopen(filename).read())
-    except HTTPError:
-        print('Could not download "%s"' % filename)
+    req = Request(url=filename, headers=headers)
+    response = urlopen(req)
+    length = response.getheader('content-length')
+    if response.status != 200:
+        print(f'Could not download "{filename}"', file=sys.stderr)
         return None
+    print(f"Downloading {length} from {filename}", file=sys.stderr)
+    data = response.read()
+    # Verify hash
+    key = os.path.basename(filename)
+    sha256_returned = hashlib.sha256(data).hexdigest()
+    if key not in sha256_vals:
+        raise ValueError(
+            f'key "{key}" with hash "{sha256_returned}" not in sha256_vals')
+    sha256_expected = sha256_vals[key]
+    if sha256_returned != sha256_expected:
+        raise ValueError(f'sha256 hash mismatch for filename {filename}')
+    print("Saving to file", file=sys.stderr)
+    with open(target, 'wb') as fid:
+        fid.write(data)
     return typ
 
 def setup_openblas(arch=get_arch(), ilp64=get_ilp64()):
@@ -124,7 +148,6 @@ def setup_openblas(arch=get_arch(), ilp64=get_ilp64()):
         return unpack_targz(tmp)
 
 def unpack_windows_zip(fname):
-    import sysconfig
     with zipfile.ZipFile(fname, 'r') as zf:
         # Get the openblas.a file, but not openblas.dll.a nor openblas.dev.a
         lib = [x for x in zf.namelist() if OPENBLAS_LONG in x and
@@ -184,12 +207,12 @@ def make_init(dirname):
             and is created as part of the scripts that build the wheel.
             '''
             import os
-            from ctypes import WinDLL
             import glob
             if os.name == 'nt':
                 # convention for storing / loading the DLL from
                 # numpy/.libs/, if present
                 try:
+                    from ctypes import WinDLL
                     basedir = os.path.dirname(__file__)
                 except:
                     pass
@@ -198,16 +221,16 @@ def make_init(dirname):
                     DLL_filenames = []
                     if os.path.isdir(libs_dir):
                         for filename in glob.glob(os.path.join(libs_dir,
-                                                             '*openblas*dll')):
+                                                               '*openblas*dll')):
                             # NOTE: would it change behavior to load ALL
                             # DLLs at this path vs. the name restriction?
                             WinDLL(os.path.abspath(filename))
                             DLL_filenames.append(filename)
-                if len(DLL_filenames) > 1:
-                    import warnings
-                    warnings.warn("loaded more than 1 DLL from .libs:\\n%s" %
-                              "\\n".join(DLL_filenames),
-                              stacklevel=1)
+                    if len(DLL_filenames) > 1:
+                        import warnings
+                        warnings.warn("loaded more than 1 DLL from .libs:\\n%s" %
+                                      "\\n".join(DLL_filenames),
+                                      stacklevel=1)
     """))
 
 def test_setup(arches):
@@ -217,9 +240,10 @@ def test_setup(arches):
     def items():
         for arch in arches:
             yield arch, None
-            if arch in ('x86', 'darwin', 'windows'):
+            if arch not in ('i686'):
                 yield arch, '64_'
 
+    errs = []
     for arch, ilp64 in items():
         if arch == '':
             continue
@@ -228,11 +252,13 @@ def test_setup(arches):
         try:
             try:
                 target = setup_openblas(arch, ilp64)
-            except:
-                print('Could not setup %s' % arch)
-                raise
+            except Exception as e:
+                print(f'Could not setup {arch}:')
+                print(str(e))
+                errs.append(e)
+                continue
             if not target:
-                raise RuntimeError('Could not setup %s' % arch)
+                raise RuntimeError(f'Could not setup {arch}')
             print(target)
             if arch == 'windows':
                 if not target.endswith('.a'):
@@ -247,6 +273,9 @@ def test_setup(arches):
                     os.unlink(target)
                 else:
                     shutil.rmtree(target)
+    if errs:
+        raise errs[0]
+
 
 def test_version(expected_version, ilp64=get_ilp64()):
     """
@@ -264,8 +293,11 @@ def test_version(expected_version, ilp64=get_ilp64()):
     get_config.restype=ctypes.c_char_p
     res = get_config()
     print('OpenBLAS get_config returned', str(res))
-    check_str = b'OpenBLAS %s' % expected_version[0].encode()
-    assert check_str in res
+    if not expected_version:
+        expected_version = OPENBLAS_V
+    check_str = b'OpenBLAS %s' % expected_version.encode()
+    print(check_str)
+    assert check_str in res, '%s not found in %s' %(expected_version, res)
     if ilp64:
         assert b"USE64BITINT" in res
     else:
@@ -278,10 +310,10 @@ if __name__ == '__main__':
                     'architecture')
     parser.add_argument('--test', nargs='*', default=None,
         help='Test different architectures. "all", or any of %s' % ARCHITECTURES)
-    parser.add_argument('--check_version', nargs=1, default=None,
+    parser.add_argument('--check_version', nargs='?', default='',
         help='Check provided OpenBLAS version string against available OpenBLAS')
     args = parser.parse_args()
-    if args.check_version is not None:
+    if args.check_version != '':
         test_version(args.check_version)
     elif args.test is None:
         print(setup_openblas())
index 867c26d76faca8b492a11062c5d4ae8c76b728e2..e24d7a99d86936b8c559fb491979f6c726cf4d6f 100755 (executable)
@@ -7,8 +7,9 @@ set -o pipefail
 set -x
 
 sudo apt-get -yq update
-sudo apt-get -yq install libatlas-base-dev liblapack-dev gfortran-5
-F77=gfortran-5 F90=gfortran-5 \
+sudo apt-get -yq install gfortran-5
+export F77=gfortran-5
+export F90=gfortran-5
 
 # Download the proper OpenBLAS x64 precompiled library
 target=$(python3 tools/openblas_support.py)
@@ -27,16 +28,16 @@ include_dirs = $target/lib:$LIB
 runtime_library_dirs = $target/lib
 EOF
 
-echo getting PyPy 3.6 nightly
-wget -q http://buildbot.pypy.org/nightly/py3.6/pypy-c-jit-latest-linux64.tar.bz2 -O pypy.tar.bz2
+echo getting PyPy 3.6-v7.3.1
+wget -q https://downloads.python.org/pypy/pypy3.6-v7.3.1-linux64.tar.bz2 -O pypy.tar.bz2
 mkdir -p pypy3
 (cd pypy3; tar --strip-components=1 -xf ../pypy.tar.bz2)
 pypy3/bin/pypy3 -mensurepip
-pypy3/bin/pypy3 -m pip install --upgrade pip setuptools
+pypy3/bin/pypy3 -m pip install --upgrade pip setuptools wheel
 pypy3/bin/pypy3 -m pip install --user -r test_requirements.txt --no-warn-script-location
 
 echo
-echo pypy3 version 
+echo pypy3 version
 pypy3/bin/pypy3 -c "import sys; print(sys.version)"
 echo
 
@@ -44,6 +45,5 @@ pypy3/bin/pypy3 runtests.py --debug-info --show-build-log -v -- -rsx \
       --junitxml=junit/test-results.xml --durations 10
 
 echo Make sure the correct openblas has been linked in
-
-pypy3/bin/pypy3 -m pip install .
-pypy3/bin/pypy3 tools/openblas_support.py --check_version "$OpenBLAS_version"
+pypy3/bin/pypy3 -mpip install --no-build-isolation .
+pypy3/bin/pypy3 tools/openblas_support.py --check_version
index 2c628091f33b887b147359b6e28e8245559dcde6..b3891c5cbc97a45c0f95dae678f236176981505c 100644 (file)
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 """
 refguide_check.py [OPTIONS] [-- ARGS]
 
@@ -25,23 +25,22 @@ or in RST-based documentations::
 
     $ python refguide_check.py --rst docs
 """
-from __future__ import print_function
-
-import sys
-import os
-import re
 import copy
-import inspect
-import warnings
 import doctest
-import tempfile
+import inspect
 import io
-import docutils.core
-from docutils.parsers.rst import directives
+import os
+import re
 import shutil
-import glob
-from doctest import NORMALIZE_WHITESPACE, ELLIPSIS, IGNORE_EXCEPTION_DETAIL
+import sys
+import tempfile
+import warnings
+import docutils.core
 from argparse import ArgumentParser
+from contextlib import contextmanager, redirect_stderr
+from doctest import NORMALIZE_WHITESPACE, ELLIPSIS, IGNORE_EXCEPTION_DETAIL
+
+from docutils.parsers.rst import directives
 from pkg_resources import parse_version
 
 import sphinx
@@ -120,6 +119,9 @@ RST_SKIPLIST = [
     'doc/release',
     'doc/source/release',
     'c-info.ufunc-tutorial.rst',
+    'c-info.python-as-glue.rst',
+    'f2py.getting-started.rst',
+    'arrays.nditer.cython.rst',
 ]
 
 # these names are not required to be present in ALL despite being in
@@ -152,6 +154,17 @@ HAVE_MATPLOTLIB = False
 def short_path(path, cwd=None):
     """
     Return relative or absolute path name, whichever is shortest.
+
+    Parameters
+    ----------
+    path: str or None
+
+    cwd: str or None
+
+    Returns
+    -------
+    str
+        Relative path or absolute path based on current working directory
     """
     if not isinstance(path, str):
         return path
@@ -165,17 +178,32 @@ def short_path(path, cwd=None):
 
 
 def find_names(module, names_dict):
-    # Refguide entries:
-    #
-    # - 3 spaces followed by function name, and maybe some spaces, some
-    #   dashes, and an explanation; only function names listed in
-    #   refguide are formatted like this (mostly, there may be some false
-    #   positives)
-    #
-    # - special directives, such as data and function
-    #
-    # - (scipy.constants only): quoted list
-    #
+    """
+    Finds the occurrences of function names, special directives like data
+    and functions and scipy constants in the docstrings of `module`. The
+    following patterns are searched for:
+
+    * 3 spaces followed by function name, and maybe some spaces, some
+      dashes, and an explanation; only function names listed in
+      refguide are formatted like this (mostly, there may be some false
+      positives
+    * special directives, such as data and function
+    * (scipy.constants only): quoted list
+
+    The `names_dict` is updated by reference and accessible in calling method
+
+    Parameters
+    ----------
+    module : ModuleType
+        The module, whose docstrings is to be searched
+    names_dict : dict
+        Dictionary which contains module name as key and a set of found
+        function names and directives as value
+
+    Returns
+    -------
+    None
+    """
     patterns = [
         r"^\s\s\s([a-z_0-9A-Z]+)(\s+-+.*)?$",
         r"^\.\. (?:data|function)::\s*([a-z_0-9A-Z]+)\s*$"
@@ -203,7 +231,23 @@ def find_names(module, names_dict):
 
 
 def get_all_dict(module):
-    """Return a copy of the __all__ dict with irrelevant items removed."""
+    """
+    Return a copy of the __all__ dict with irrelevant items removed.
+
+    Parameters
+    ----------
+    module : ModuleType
+        The module whose __all__ dict has to be processed
+
+    Returns
+    -------
+    deprecated : list
+        List of callable and deprecated sub modules
+    not_deprecated : list
+        List of non callable or non deprecated sub modules
+    others : list
+        List of remaining types of sub modules
+    """
     if hasattr(module, "__all__"):
         all_dict = copy.deepcopy(module.__all__)
     else:
@@ -239,7 +283,30 @@ def get_all_dict(module):
 
 
 def compare(all_dict, others, names, module_name):
-    """Return sets of objects only in __all__, refguide, or completely missing."""
+    """
+    Return sets of objects from all_dict.
+    Will return three sets:
+     {in module_name.__all__},
+     {in REFGUIDE*},
+     and {missing from others}
+
+    Parameters
+    ----------
+    all_dict : list
+        List of non deprecated sub modules for module_name
+    others : list
+        List of sub modules for module_name
+    names :  set
+        Set of function names or special directives present in
+        docstring of module_name
+    module_name : ModuleType
+
+    Returns
+    -------
+    only_all : set
+    only_ref : set
+    missing : set
+    """
     only_all = set()
     for name in all_dict:
         if name not in names:
@@ -265,6 +332,17 @@ def compare(all_dict, others, names, module_name):
 
 
 def is_deprecated(f):
+    """
+    Check if module `f` is deprecated
+
+    Parameter
+    ---------
+    f : ModuleType
+
+    Returns
+    -------
+    bool
+    """
     with warnings.catch_warnings(record=True) as w:
         warnings.simplefilter("error")
         try:
@@ -280,6 +358,26 @@ def check_items(all_dict, names, deprecated, others, module_name, dots=True):
     """
     Check that `all_dict` is consistent with the `names` in `module_name`
     For instance, that there are no deprecated or extra objects.
+
+    Parameters
+    ----------
+    all_dict : list
+
+    names : set
+
+    deprecated : list
+
+    others : list
+
+    module_name : ModuleType
+
+    dots : bool
+        Whether to print a dot for each check
+
+    Returns
+    -------
+    list
+        List of [(name, success_flag, output)...]
     """
     num_all = len(all_dict)
     num_ref = len(names)
@@ -331,13 +429,28 @@ def check_items(all_dict, names, deprecated, others, module_name, dots=True):
 
 
 def validate_rst_syntax(text, name, dots=True):
+    """
+    Validates the doc string in a snippet of documentation
+    `text` from file `name`
+    Parameters
+    ----------
+    text : str
+        Docstring text
+    name : str
+        File name for which the doc string is to be validated
+    dots : bool
+        Whether to print a dot symbol for each check
+    Returns
+    -------
+    (bool, str)
+    """
     if text is None:
         if dots:
             output_dot('E')
         return False, "ERROR: %s: no documentation" % (name,)
 
     ok_unknown_items = set([
-        'mod', 'currentmodule', 'autosummary', 'data', 'attr',
+        'mod', 'doc', 'currentmodule', 'autosummary', 'data', 'attr',
         'obj', 'versionadded', 'versionchanged', 'module', 'class',
         'ref', 'func', 'toctree', 'moduleauthor', 'term', 'c:member',
         'sectionauthor', 'codeauthor', 'eq', 'doi', 'DOI', 'arXiv', 'arxiv'
@@ -407,7 +520,16 @@ def check_rest(module, names, dots=True):
     """
     Check reStructuredText formatting of docstrings
 
-    Returns: [(name, success_flag, output), ...]
+    Parameters
+    ----------
+    module : ModuleType
+
+    names : set
+
+    Returns
+    -------
+    result : list
+        List of [(module_name, success_flag, output),...]
     """
 
     try:
@@ -498,6 +620,9 @@ CHECK_NAMESPACE = {
 
 
 class DTRunner(doctest.DocTestRunner):
+    """
+    The doctest runner
+    """
     DIVIDER = "\n"
 
     def __init__(self, item_name, checker=None, verbose=None, optionflags=0):
@@ -531,8 +656,10 @@ class DTRunner(doctest.DocTestRunner):
                                                     example, got)
 
 class Checker(doctest.OutputChecker):
+    """
+    Check the docstrings
+    """
     obj_pattern = re.compile('at 0x[0-9a-fA-F]+>')
-    int_pattern = re.compile('^[0-9]+L?$')
     vanilla = doctest.OutputChecker()
     rndm_markers = {'# random', '# Random', '#random', '#Random', "# may vary",
                     "# uninitialized", "#uninitialized"}
@@ -571,11 +698,6 @@ class Checker(doctest.OutputChecker):
         if want.lstrip().startswith("#"):
             return True
 
-        # python 2 long integers are equal to python 3 integers
-        if self.int_pattern.match(want) and self.int_pattern.match(got):
-            if want.rstrip("L\r\n") == got.rstrip("L\r\n"):
-                return True
-
         # try the standard doctest
         try:
             if self.vanilla.check_output(want, got, optionflags):
@@ -644,43 +766,49 @@ class Checker(doctest.OutputChecker):
 
 
 def _run_doctests(tests, full_name, verbose, doctest_warnings):
-    """Run modified doctests for the set of `tests`.
+    """
+    Run modified doctests for the set of `tests`.
 
-    Returns: list of [(success_flag, output), ...]
+    Parameters
+    ----------
+    tests: list
+
+    full_name : str
+
+    verbose : bool
+
+    doctest_warning : bool
+
+    Returns
+    -------
+    tuple(bool, list)
+        Tuple of (success, output)
     """
-    flags = NORMALIZE_WHITESPACE | ELLIPSIS | IGNORE_EXCEPTION_DETAIL
+    flags = NORMALIZE_WHITESPACE | ELLIPSIS
     runner = DTRunner(full_name, checker=Checker(), optionflags=flags,
                       verbose=verbose)
 
-    output = []
+    output = io.StringIO(newline='')
     success = True
-    def out(msg):
-        output.append(msg)
-
-    class MyStderr(object):
-        """Redirect stderr to the current stdout"""
-        def write(self, msg):
-            if doctest_warnings:
-                sys.stdout.write(msg)
-            else:
-                out(msg)
 
-        # a flush method is required when a doctest uses multiprocessing
-        # multiprocessing/popen_fork.py flushes sys.stderr
-        def flush(self):
-            if doctest_warnings:
-                sys.stdout.flush()
+    # Redirect stderr to the stdout or output
+    tmp_stderr = sys.stdout if doctest_warnings else output
+
+    @contextmanager
+    def temp_cwd():
+        cwd = os.getcwd()
+        tmpdir = tempfile.mkdtemp()
+        try:
+            os.chdir(tmpdir)
+            yield tmpdir
+        finally:
+            os.chdir(cwd)
+            shutil.rmtree(tmpdir)
 
     # Run tests, trying to restore global state afterward
-    old_printoptions = np.get_printoptions()
-    old_errstate = np.seterr()
-    old_stderr = sys.stderr
     cwd = os.getcwd()
-    tmpdir = tempfile.mkdtemp()
-    sys.stderr = MyStderr()
-    try:
-        os.chdir(tmpdir)
-
+    with np.errstate(), np.printoptions(), temp_cwd() as tmpdir, \
+            redirect_stderr(tmp_stderr):
         # try to ensure random seed is NOT reproducible
         np.random.seed(None)
 
@@ -695,25 +823,36 @@ def _run_doctests(tests, full_name, verbose, doctest_warnings):
             # Process our options
             if any([SKIPBLOCK in ex.options for ex in t.examples]):
                 continue
-            fails, successes = runner.run(t, out=out, clear_globs=False)
+            fails, successes = runner.run(t, out=output.write, clear_globs=False)
             if fails > 0:
                 success = False
             ns = t.globs
-    finally:
-        sys.stderr = old_stderr
-        os.chdir(cwd)
-        shutil.rmtree(tmpdir)
-        np.set_printoptions(**old_printoptions)
-        np.seterr(**old_errstate)
 
-    return success, output
+    output.seek(0)
+    return success, output.read()
 
 
 def check_doctests(module, verbose, ns=None,
                    dots=True, doctest_warnings=False):
-    """Check code in docstrings of the module's public symbols.
-
-    Returns: list of [(item_name, success_flag, output), ...]
+    """
+    Check code in docstrings of the module's public symbols.
+
+    Parameters
+    ----------
+    module : ModuleType
+        Name of module
+    verbose : bool
+        Should the result be verbose
+    ns : dict
+        Name space of module
+    dots : bool
+
+    doctest_warnings : bool
+
+    Returns
+    -------
+    results : list
+        List of [(item_name, success_flag, output), ...]
     """
     if ns is None:
         ns = dict(DEFAULT_NAMESPACE)
@@ -752,7 +891,7 @@ def check_doctests(module, verbose, ns=None,
         if dots:
             output_dot('.' if success else 'F')
 
-        results.append((full_name, success, "".join(output)))
+        results.append((full_name, success, output))
 
         if HAVE_MATPLOTLIB:
             import matplotlib.pyplot as plt
@@ -763,17 +902,42 @@ def check_doctests(module, verbose, ns=None,
 
 def check_doctests_testfile(fname, verbose, ns=None,
                    dots=True, doctest_warnings=False):
-    """Check code in a text file.
+    """
+    Check code in a text file.
 
     Mimic `check_doctests` above, differing mostly in test discovery.
     (which is borrowed from stdlib's doctest.testfile here,
      https://github.com/python-git/python/blob/master/Lib/doctest.py)
 
-    Returns: list of [(item_name, success_flag, output), ...]
+    Parameters
+    ----------
+    fname : str
+        File name
+    verbose : bool
+
+    ns : dict
+        Name space
+
+    dots : bool
+
+    doctest_warnings : bool
+
+    Returns
+    -------
+    list
+        List of [(item_name, success_flag, output), ...]
 
     Notes
     -----
 
+    refguide can be signalled to skip testing code by adding
+    ``#doctest: +SKIP`` to the end of the line. If the output varies or is
+    random, add ``# may vary`` or ``# random`` to the comment. for example
+
+    >>> plt.plot(...)  # doctest: +SKIP
+    >>> random.randint(0,10)
+    5 # random
+
     We also try to weed out pseudocode:
     * We maintain a list of exceptions which signal pseudocode,
     * We split the text file into "blocks" of code separated by empty lines
@@ -805,12 +969,8 @@ def check_doctests_testfile(fname, verbose, ns=None,
         return results
 
     full_name = fname
-    if sys.version_info.major <= 2:
-        with open(fname) as f:
-            text = f.read()
-    else:
-        with open(fname, encoding='utf-8') as f:
-            text = f.read()
+    with open(fname, encoding='utf-8') as f:
+        text = f.read()
 
     PSEUDOCODE = set(['some_function', 'some_module', 'import example',
                       'ctypes.CDLL',     # likely need compiling, skip it
@@ -851,7 +1011,7 @@ def check_doctests_testfile(fname, verbose, ns=None,
     if dots:
         output_dot('.' if success else 'F')
 
-    results.append((full_name, success, "".join(output)))
+    results.append((full_name, success, output))
 
     if HAVE_MATPLOTLIB:
         import matplotlib.pyplot as plt
@@ -865,6 +1025,19 @@ def iter_included_files(base_path, verbose=0, suffixes=('.rst',)):
     Generator function to walk `base_path` and its subdirectories, skipping
     files or directories in RST_SKIPLIST, and yield each file with a suffix in
     `suffixes`
+
+    Parameters
+    ----------
+    base_path : str
+        Base path of the directory to be processed
+    verbose : int
+
+    suffixes : tuple
+
+    Yields
+    ------
+    path
+        Path of the directory and its sub directories
     """
     if os.path.exists(base_path) and os.path.isfile(base_path):
         yield base_path
@@ -914,6 +1087,9 @@ def check_documentation(base_path, results, args, dots):
 
 
 def init_matplotlib():
+    """
+    Check feasibility of matplotlib initialization.
+    """
     global HAVE_MATPLOTLIB
 
     try:
@@ -925,6 +1101,10 @@ def init_matplotlib():
 
 
 def main(argv):
+    """
+    Validates the docstrings of all the pre decided set of
+    modules for errors and docstring standards.
+    """
     parser = ArgumentParser(usage=__doc__.lstrip())
     parser.add_argument("module_names", metavar="SUBMODULES", default=[],
                         nargs='*', help="Submodules to check (default: all public)")
@@ -948,7 +1128,7 @@ def main(argv):
     os.environ['SCIPY_PIL_IMAGE_VIEWER'] = 'true'
 
     module_names = list(args.module_names)
-    for name in list(module_names):
+    for name in module_names:
         if name in OTHER_MODULE_DOCS:
             name = OTHER_MODULE_DOCS[name]
             if name not in module_names:
@@ -1003,8 +1183,6 @@ def main(argv):
                 sys.stderr.write('\n')
                 sys.stderr.flush()
 
-            all_dict, deprecated, others = get_all_dict(module)
-
     if args.rst:
         base_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..')
         rst_path = os.path.relpath(os.path.join(base_dir, args.rst))
index 36bb55c98cff1e306fe7e0e6efd6077fa24cc46d..8416e82f3a9017123a931eb53339617a2f4bdcbd 100644 (file)
     if (PyDict_Check(    py_obj)) return "dict"        ;
     if (PyList_Check(    py_obj)) return "list"        ;
     if (PyTuple_Check(   py_obj)) return "tuple"       ;
-%#if PY_MAJOR_VERSION < 3
-    if (PyFile_Check(    py_obj)) return "file"        ;
-    if (PyModule_Check(  py_obj)) return "module"      ;
-    if (PyInstance_Check(py_obj)) return "instance"    ;
-%#endif
 
     return "unknown type";
   }
     const npy_intp *dims = array_dimensions(ary);
     for (i=0; i < nd; ++i)
       n_non_one += (dims[i] != 1) ? 1 : 0;
-    if (n_non_one > 1)    
+    if (n_non_one > 1)
       array_clearflags(ary,NPY_ARRAY_CARRAY);
     array_enableflags(ary,NPY_ARRAY_FARRAY);
     /* Recompute the strides */
index 97ca8cf97c316076ac372ef8a4b0587394644f97..ce2452f8020d1fe4335aebff5df2c002e37ae7ed 100644 (file)
   SWIGINTERN int
   SWIG_AsVal_dec(unsigned long)(PyObject *obj, unsigned long *val)
   {
-    %#if PY_VERSION_HEX < 0x03000000
-    if (PyInt_Check(obj)) 
-    {
-      long v = PyInt_AsLong(obj);
-      if (v >= 0) 
-      {
-        if (val) *val = v;
-           return SWIG_OK;
-      } 
-      else 
-      {
-           return SWIG_OverflowError;
-      }
-    } else 
-    %#endif
     if (PyLong_Check(obj)) {
       unsigned long v = PyLong_AsUnsignedLong(obj);
       if (!PyErr_Occurred()) {
index e3558f786157aef2e291109fa5feaf715335d5fa..2da61f7285699409a6edc684a2e9225408725fbf 100644 (file)
@@ -90,6 +90,11 @@ void Array2::resize(int nrows, int ncols, long* data)
   }
 }
 
+void Array2::resize(int nrows, int ncols)
+{
+  resize(nrows, ncols, nullptr);
+}
+
 // Set item accessor
 Array1 & Array2::operator[](int i)
 {
index 7f8d4ca65874a79befdb3378355692c772184860..7ab68827b93b51e15d8250e6bea9aa38a1c0e132 100644 (file)
@@ -31,9 +31,10 @@ public:
   int nrows() const;
   int ncols() const;
 
-  // Resize array
-  void resize(int nrows, int ncols, long* data=0);
-
+  // Resize array  
+  void resize(int nrows, int ncols, long* data);
+  void resize(int nrows, int ncols);
+  
   // Set item accessor
   Array1 & operator[](int i);
 
index 4ff870e1938576491f785b625fac752c1e9694eb..71830fd2cc535699edce203ca6d0dc54878994fa 100755 (executable)
@@ -1,9 +1,6 @@
-#! /usr/bin/env python
-from __future__ import division, print_function
-
+#!/usr/bin/env python3
 # System imports
-from distutils.core import *
-from distutils      import sysconfig
+from distutils.core import Extension, setup
 
 # Third-party modules - we depend on numpy for everything
 import numpy
index 8d9c7977223b81b717a5d8b11fc3c29b8424f787..49011bb133046266cbe5ae299c9bfaeda5930a1c 100755 (executable)
@@ -1,9 +1,5 @@
-#! /usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
+#!/usr/bin/env python3
 # System imports
-from   distutils.util import get_platform
-import os
 import sys
 import unittest
 
@@ -28,24 +24,24 @@ class Array1TestCase(unittest.TestCase):
     def testConstructor0(self):
         "Test Array1 default constructor"
         a = Array.Array1()
-        self.failUnless(isinstance(a, Array.Array1))
-        self.failUnless(len(a) == 0)
+        self.assertTrue(isinstance(a, Array.Array1))
+        self.assertTrue(len(a) == 0)
 
     def testConstructor1(self):
         "Test Array1 length constructor"
-        self.failUnless(isinstance(self.array1, Array.Array1))
+        self.assertTrue(isinstance(self.array1, Array.Array1))
 
     def testConstructor2(self):
         "Test Array1 array constructor"
         na = np.arange(self.length)
         aa = Array.Array1(na)
-        self.failUnless(isinstance(aa, Array.Array1))
+        self.assertTrue(isinstance(aa, Array.Array1))
 
     def testConstructor3(self):
         "Test Array1 copy constructor"
         for i in range(self.array1.length()): self.array1[i] = i
         arrayCopy = Array.Array1(self.array1)
-        self.failUnless(arrayCopy == self.array1)
+        self.assertTrue(arrayCopy == self.array1)
 
     def testConstructorBad(self):
         "Test Array1 length constructor, negative"
@@ -53,23 +49,23 @@ class Array1TestCase(unittest.TestCase):
 
     def testLength(self):
         "Test Array1 length method"
-        self.failUnless(self.array1.length() == self.length)
+        self.assertTrue(self.array1.length() == self.length)
 
     def testLen(self):
         "Test Array1 __len__ method"
-        self.failUnless(len(self.array1) == self.length)
+        self.assertTrue(len(self.array1) == self.length)
 
     def testResize0(self):
         "Test Array1 resize method, length"
         newLen = 2 * self.length
         self.array1.resize(newLen)
-        self.failUnless(len(self.array1) == newLen)
+        self.assertTrue(len(self.array1) == newLen)
 
     def testResize1(self):
         "Test Array1 resize method, array"
         a = np.zeros((2*self.length,), dtype='l')
         self.array1.resize(a)
-        self.failUnless(len(self.array1) == a.size)
+        self.assertTrue(len(self.array1) == a.size)
 
     def testResizeBad(self):
         "Test Array1 resize method, negative length"
@@ -81,7 +77,7 @@ class Array1TestCase(unittest.TestCase):
         for i in range(n):
             self.array1[i] = i*i
         for i in range(n):
-            self.failUnless(self.array1[i] == i*i)
+            self.assertTrue(self.array1[i] == i*i)
 
     def testSetBad1(self):
         "Test Array1 __setitem__ method, negative index"
@@ -102,20 +98,20 @@ class Array1TestCase(unittest.TestCase):
     def testAsString(self):
         "Test Array1 asString method"
         for i in range(self.array1.length()): self.array1[i] = i+1
-        self.failUnless(self.array1.asString() == "[ 1, 2, 3, 4, 5 ]")
+        self.assertTrue(self.array1.asString() == "[ 1, 2, 3, 4, 5 ]")
 
     def testStr(self):
         "Test Array1 __str__ method"
         for i in range(self.array1.length()): self.array1[i] = i-2
-        self.failUnless(str(self.array1) == "[ -2, -1, 0, 1, 2 ]")
+        self.assertTrue(str(self.array1) == "[ -2, -1, 0, 1, 2 ]")
 
     def testView(self):
         "Test Array1 view method"
         for i in range(self.array1.length()): self.array1[i] = i+1
         a = self.array1.view()
-        self.failUnless(isinstance(a, np.ndarray))
-        self.failUnless(len(a) == self.length)
-        self.failUnless((a == [1, 2, 3, 4, 5]).all())
+        self.assertTrue(isinstance(a, np.ndarray))
+        self.assertTrue(len(a) == self.length)
+        self.assertTrue((a == [1, 2, 3, 4, 5]).all())
 
 ######################################################################
 
@@ -129,18 +125,18 @@ class Array2TestCase(unittest.TestCase):
     def testConstructor0(self):
         "Test Array2 default constructor"
         a = Array.Array2()
-        self.failUnless(isinstance(a, Array.Array2))
-        self.failUnless(len(a) == 0)
+        self.assertTrue(isinstance(a, Array.Array2))
+        self.assertTrue(len(a) == 0)
 
     def testConstructor1(self):
         "Test Array2 nrows, ncols constructor"
-        self.failUnless(isinstance(self.array2, Array.Array2))
+        self.assertTrue(isinstance(self.array2, Array.Array2))
 
     def testConstructor2(self):
         "Test Array2 array constructor"
         na = np.zeros((3, 4), dtype="l")
         aa = Array.Array2(na)
-        self.failUnless(isinstance(aa, Array.Array2))
+        self.assertTrue(isinstance(aa, Array.Array2))
 
     def testConstructor3(self):
         "Test Array2 copy constructor"
@@ -148,7 +144,7 @@ class Array2TestCase(unittest.TestCase):
             for j in range(self.ncols):
                 self.array2[i][j] = i * j
         arrayCopy = Array.Array2(self.array2)
-        self.failUnless(arrayCopy == self.array2)
+        self.assertTrue(arrayCopy == self.array2)
 
     def testConstructorBad1(self):
         "Test Array2 nrows, ncols constructor, negative nrows"
@@ -160,28 +156,28 @@ class Array2TestCase(unittest.TestCase):
 
     def testNrows(self):
         "Test Array2 nrows method"
-        self.failUnless(self.array2.nrows() == self.nrows)
+        self.assertTrue(self.array2.nrows() == self.nrows)
 
     def testNcols(self):
         "Test Array2 ncols method"
-        self.failUnless(self.array2.ncols() == self.ncols)
+        self.assertTrue(self.array2.ncols() == self.ncols)
 
     def testLen(self):
         "Test Array2 __len__ method"
-        self.failUnless(len(self.array2) == self.nrows*self.ncols)
+        self.assertTrue(len(self.array2) == self.nrows*self.ncols)
 
     def testResize0(self):
         "Test Array2 resize method, size"
         newRows = 2 * self.nrows
         newCols = 2 * self.ncols
         self.array2.resize(newRows, newCols)
-        self.failUnless(len(self.array2) == newRows * newCols)
+        self.assertTrue(len(self.array2) == newRows * newCols)
 
     def testResize1(self):
         "Test Array2 resize method, array"
         a = np.zeros((2*self.nrows, 2*self.ncols), dtype='l')
         self.array2.resize(a)
-        self.failUnless(len(self.array2) == a.size)
+        self.assertTrue(len(self.array2) == a.size)
 
     def testResizeBad1(self):
         "Test Array2 resize method, negative nrows"
@@ -202,7 +198,7 @@ class Array2TestCase(unittest.TestCase):
         for i in range(m):
             self.array2[i] = array1[i]
         for i in range(m):
-            self.failUnless(self.array2[i] == array1[i])
+            self.assertTrue(self.array2[i] == array1[i])
 
     def testSetGet2(self):
         "Test Array2 chained __setitem__, __getitem__ methods"
@@ -213,7 +209,7 @@ class Array2TestCase(unittest.TestCase):
                 self.array2[i][j] = i*j
         for i in range(m):
             for j in range(n):
-                self.failUnless(self.array2[i][j] == i*j)
+                self.assertTrue(self.array2[i][j] == i*j)
 
     def testSetBad1(self):
         "Test Array2 __setitem__ method, negative index"
@@ -245,7 +241,7 @@ class Array2TestCase(unittest.TestCase):
         for i in range(self.nrows):
             for j in range(self.ncols):
                 self.array2[i][j] = i+j
-        self.failUnless(self.array2.asString() == result)
+        self.assertTrue(self.array2.asString() == result)
 
     def testStr(self):
         "Test Array2 __str__ method"
@@ -259,13 +255,13 @@ class Array2TestCase(unittest.TestCase):
         for i in range(self.nrows):
             for j in range(self.ncols):
                 self.array2[i][j] = i-j
-        self.failUnless(str(self.array2) == result)
+        self.assertTrue(str(self.array2) == result)
 
     def testView(self):
         "Test Array2 view method"
         a = self.array2.view()
-        self.failUnless(isinstance(a, np.ndarray))
-        self.failUnless(len(a) == self.nrows)
+        self.assertTrue(isinstance(a, np.ndarray))
+        self.assertTrue(len(a) == self.nrows)
 
 ######################################################################
 
@@ -278,24 +274,24 @@ class ArrayZTestCase(unittest.TestCase):
     def testConstructor0(self):
         "Test ArrayZ default constructor"
         a = Array.ArrayZ()
-        self.failUnless(isinstance(a, Array.ArrayZ))
-        self.failUnless(len(a) == 0)
+        self.assertTrue(isinstance(a, Array.ArrayZ))
+        self.assertTrue(len(a) == 0)
 
     def testConstructor1(self):
         "Test ArrayZ length constructor"
-        self.failUnless(isinstance(self.array3, Array.ArrayZ))
+        self.assertTrue(isinstance(self.array3, Array.ArrayZ))
 
     def testConstructor2(self):
         "Test ArrayZ array constructor"
         na = np.arange(self.length, dtype=np.complex128)
         aa = Array.ArrayZ(na)
-        self.failUnless(isinstance(aa, Array.ArrayZ))
+        self.assertTrue(isinstance(aa, Array.ArrayZ))
 
     def testConstructor3(self):
         "Test ArrayZ copy constructor"
         for i in range(self.array3.length()): self.array3[i] = complex(i,-i)
         arrayCopy = Array.ArrayZ(self.array3)
-        self.failUnless(arrayCopy == self.array3)
+        self.assertTrue(arrayCopy == self.array3)
 
     def testConstructorBad(self):
         "Test ArrayZ length constructor, negative"
@@ -303,23 +299,23 @@ class ArrayZTestCase(unittest.TestCase):
 
     def testLength(self):
         "Test ArrayZ length method"
-        self.failUnless(self.array3.length() == self.length)
+        self.assertTrue(self.array3.length() == self.length)
 
     def testLen(self):
         "Test ArrayZ __len__ method"
-        self.failUnless(len(self.array3) == self.length)
+        self.assertTrue(len(self.array3) == self.length)
 
     def testResize0(self):
         "Test ArrayZ resize method, length"
         newLen = 2 * self.length
         self.array3.resize(newLen)
-        self.failUnless(len(self.array3) == newLen)
+        self.assertTrue(len(self.array3) == newLen)
 
     def testResize1(self):
         "Test ArrayZ resize method, array"
         a = np.zeros((2*self.length,), dtype=np.complex128)
         self.array3.resize(a)
-        self.failUnless(len(self.array3) == a.size)
+        self.assertTrue(len(self.array3) == a.size)
 
     def testResizeBad(self):
         "Test ArrayZ resize method, negative length"
@@ -331,7 +327,7 @@ class ArrayZTestCase(unittest.TestCase):
         for i in range(n):
             self.array3[i] = i*i
         for i in range(n):
-            self.failUnless(self.array3[i] == i*i)
+            self.assertTrue(self.array3[i] == i*i)
 
     def testSetBad1(self):
         "Test ArrayZ __setitem__ method, negative index"
@@ -352,20 +348,20 @@ class ArrayZTestCase(unittest.TestCase):
     def testAsString(self):
         "Test ArrayZ asString method"
         for i in range(self.array3.length()): self.array3[i] = complex(i+1,-i-1)
-        self.failUnless(self.array3.asString() == "[ (1,-1), (2,-2), (3,-3), (4,-4), (5,-5) ]")
+        self.assertTrue(self.array3.asString() == "[ (1,-1), (2,-2), (3,-3), (4,-4), (5,-5) ]")
 
     def testStr(self):
         "Test ArrayZ __str__ method"
         for i in range(self.array3.length()): self.array3[i] = complex(i-2,(i-2)*2)
-        self.failUnless(str(self.array3) == "[ (-2,-4), (-1,-2), (0,0), (1,2), (2,4) ]")
+        self.assertTrue(str(self.array3) == "[ (-2,-4), (-1,-2), (0,0), (1,2), (2,4) ]")
 
     def testView(self):
         "Test ArrayZ view method"
         for i in range(self.array3.length()): self.array3[i] = complex(i+1,i+2)
         a = self.array3.view()
-        self.failUnless(isinstance(a, np.ndarray))
-        self.failUnless(len(a) == self.length)
-        self.failUnless((a == [1+2j, 2+3j, 3+4j, 4+5j, 5+6j]).all())
+        self.assertTrue(isinstance(a, np.ndarray))
+        self.assertTrue(len(a) == self.length)
+        self.assertTrue((a == [1+2j, 2+3j, 3+4j, 4+5j, 5+6j]).all())
 
 ######################################################################
 
index e8bf711c580de0d1b1c33757c68f3d8e699f2a71..43a6003f411f1e57656ad93237ecc98e411f3d0d 100755 (executable)
@@ -1,6 +1,4 @@
-#! /usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
+#!/usr/bin/env python3
 # System imports
 from   distutils.util import get_platform
 import os
index 71be277b175b02a6cdb5b535fd1fc27440017457..e3e456a564155aebbe722985f33e388277e3d513 100755 (executable)
@@ -1,9 +1,5 @@
-#! /usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
+#!/usr/bin/env python3
 # System imports
-from   distutils.util import get_platform
-import os
 import sys
 import unittest
 
@@ -31,7 +27,7 @@ class FlatTestCase(unittest.TestCase):
         "Test Process function 1D array"
         print(self.typeStr, "... ", end=' ', file=sys.stderr)
         process = Flat.__dict__[self.typeStr + "Process"]
-        pack_output = ''
+        pack_output = b''
         for i in range(10):
             pack_output += struct.pack(self.typeCode,i)
         x = np.frombuffer(pack_output, dtype=self.typeCode)
@@ -43,7 +39,7 @@ class FlatTestCase(unittest.TestCase):
         "Test Process function 3D array"
         print(self.typeStr, "... ", end=' ', file=sys.stderr)
         process = Flat.__dict__[self.typeStr + "Process"]
-        pack_output = ''
+        pack_output = b''
         for i in range(24):
             pack_output += struct.pack(self.typeCode,i)
         x = np.frombuffer(pack_output, dtype=self.typeCode)
@@ -56,7 +52,7 @@ class FlatTestCase(unittest.TestCase):
         "Test Process function 3D array, FORTRAN order"
         print(self.typeStr, "... ", end=' ', file=sys.stderr)
         process = Flat.__dict__[self.typeStr + "Process"]
-        pack_output = ''
+        pack_output = b''
         for i in range(24):
             pack_output += struct.pack(self.typeCode,i)
         x = np.frombuffer(pack_output, dtype=self.typeCode)
@@ -69,7 +65,7 @@ class FlatTestCase(unittest.TestCase):
         "Test Process function with non-contiguous array, which should raise an error"
         print(self.typeStr, "... ", end=' ', file=sys.stderr)
         process = Flat.__dict__[self.typeStr + "Process"]
-        pack_output = ''
+        pack_output = b''
         for i in range(24):
             pack_output += struct.pack(self.typeCode,i)
         x = np.frombuffer(pack_output, dtype=self.typeCode)
index 426e8943dec647f33a4b88c8332f36933f6d1d10..348355afcba8af50748893659e8b5c6ad77671ad 100644 (file)
@@ -1,9 +1,5 @@
-#! /usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
+#!/usr/bin/env python3
 # System imports
-from   distutils.util import get_platform
-import os
 import sys
 import unittest
 
index 065be0d443b257e93b0898cb19a726380c5b7345..814c0d5780396703ae7eba6bb91bd649e506cddd 100755 (executable)
@@ -1,9 +1,5 @@
-#! /usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
+#!/usr/bin/env python3
 # System imports
-from   distutils.util import get_platform
-import os
 import sys
 import unittest
 
index 97fe80c332a521bbba8c37130967819c2c472ce5..121c4a405805b4ed679021a24a1580a83e19c38d 100644 (file)
@@ -1,10 +1,5 @@
-#! /usr/bin/env python
-from __future__ import division, print_function
-
+#!/usr/bin/env python3
 # System imports
-from   distutils.util import get_platform
-from   math           import sqrt
-import os
 import sys
 import unittest
 
index ac1b7491a046c05725656a1818a3eaf00130f8cd..164ceb2d5626d378f5087b6a2f21f8790d016517 100755 (executable)
@@ -1,10 +1,6 @@
-#! /usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
+#!/usr/bin/env python3
 # System imports
-from   distutils.util import get_platform
 from   math           import sqrt
-import os
 import sys
 import unittest
 
index 45e763b360c1d10ccd6a1ed823c8745a4cd0bae3..1a663d1db83b56c331970ba3a035d2b7030c532f 100755 (executable)
@@ -1,9 +1,5 @@
-#! /usr/bin/env python
-from __future__ import division, absolute_import, print_function
-
+#!/usr/bin/env python3
 # System imports
-from   distutils.util import get_platform
-import os
 import sys
 import unittest
 
index dbe2f6ea2f0bb49625168e3235d674f355e3a8a5..e468dd9323130f9e95f046c5ef5246838c9055d4 100755 (executable)
@@ -41,8 +41,7 @@ pip install --upgrade pip
 # A specific version of cython is required, so we read the cython package
 # requirement using `grep cython test_requirements.txt` instead of simply
 # writing 'pip install setuptools wheel cython'.
-# urllib3 is needed for openblas_support
-pip install setuptools wheel urllib3 `grep cython test_requirements.txt`
+pip install setuptools wheel `grep cython test_requirements.txt`
 
 if [ -n "$DOWNLOAD_OPENBLAS" ]; then
   pwd
index cd3ffe29ab57a446cda62de20e0d86c95ead417f..225cbfa0c0f95c4234310c3e6d877930a59e768e 100755 (executable)
@@ -97,7 +97,7 @@ run_test()
   export PYTHONWARNINGS=default
 
   if [ -n "$CHECK_BLAS" ]; then
-    $PYTHON ../tools/openblas_support.py --check_version $OpenBLAS_version
+    $PYTHON ../tools/openblas_support.py --check_version
   fi
 
   if [ -n "$RUN_FULL_TESTS" ]; then
diff --git a/tox.ini b/tox.ini
index 5a6d074aab958dedf8c07f72754784ec1ab08e01..e58dd6efed573d318cf78cc5944df5a8411f65a1 100644 (file)
--- a/tox.ini
+++ b/tox.ini
 #   tox -- -v
 
 # Tox assumes that you have appropriate Python interpreters already
-# installed and that they can be run as 'python2.7', 'python3.3', etc.
+# installed and that they can be run as (e.g.) 'python3.8'
 
 [tox]
 envlist =
-  py35,py36,py37,
+  py36,py37,py38,
   py37-not-relaxed-strides
 
 [testenv]